| /* |
| * |
| * Copyright 2015, Google Inc. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| #include <map> |
| |
| #include <node.h> |
| #include <nan.h> |
| #include "grpc/grpc.h" |
| #include "byte_buffer.h" |
| #include "call.h" |
| #include "event.h" |
| #include "tag.h" |
| #include "timeval.h" |
| |
| namespace grpc { |
| namespace node { |
| |
| using ::node::Buffer; |
| using v8::Array; |
| using v8::Date; |
| using v8::Handle; |
| using v8::HandleScope; |
| using v8::Number; |
| using v8::Object; |
| using v8::Persistent; |
| using v8::String; |
| using v8::Value; |
| |
| Handle<Value> ParseMetadata(grpc_metadata *metadata_elements, size_t length) { |
| NanEscapableScope(); |
| std::map<const char*, size_t> size_map; |
| std::map<const char*, size_t> index_map; |
| |
| for (unsigned int i = 0; i < length; i++) { |
| const char *key = metadata_elements[i].key; |
| if (size_map.count(key)) { |
| size_map[key] += 1; |
| } |
| index_map[key] = 0; |
| } |
| Handle<Object> metadata_object = NanNew<Object>(); |
| for (unsigned int i = 0; i < length; i++) { |
| grpc_metadata* elem = &metadata_elements[i]; |
| Handle<String> key_string = String::New(elem->key); |
| Handle<Array> array; |
| if (metadata_object->Has(key_string)) { |
| array = Handle<Array>::Cast(metadata_object->Get(key_string)); |
| } else { |
| array = NanNew<Array>(size_map[elem->key]); |
| metadata_object->Set(key_string, array); |
| } |
| array->Set(index_map[elem->key], |
| MakeFastBuffer( |
| NanNewBufferHandle(elem->value, elem->value_length))); |
| index_map[elem->key] += 1; |
| } |
| return NanEscapeScope(metadata_object); |
| } |
| |
| Handle<Value> GetEventData(grpc_event *event) { |
| NanEscapableScope(); |
| size_t count; |
| grpc_metadata *items; |
| Handle<Array> metadata; |
| Handle<Object> status; |
| Handle<Object> rpc_new; |
| switch (event->type) { |
| case GRPC_READ: |
| return NanEscapeScope(ByteBufferToBuffer(event->data.read)); |
| case GRPC_WRITE_ACCEPTED: |
| return NanEscapeScope(NanNew<Number>(event->data.write_accepted)); |
| case GRPC_FINISH_ACCEPTED: |
| return NanEscapeScope(NanNew<Number>(event->data.finish_accepted)); |
| case GRPC_CLIENT_METADATA_READ: |
| count = event->data.client_metadata_read.count; |
| items = event->data.client_metadata_read.elements; |
| return NanEscapeScope(ParseMetadata(items, count)); |
| case GRPC_FINISHED: |
| status = NanNew<Object>(); |
| status->Set(NanNew("code"), NanNew<Number>(event->data.finished.status)); |
| if (event->data.finished.details != NULL) { |
| status->Set(NanNew("details"), |
| String::New(event->data.finished.details)); |
| } |
| count = event->data.finished.metadata_count; |
| items = event->data.finished.metadata_elements; |
| status->Set(NanNew("metadata"), ParseMetadata(items, count)); |
| return NanEscapeScope(status); |
| case GRPC_SERVER_RPC_NEW: |
| rpc_new = NanNew<Object>(); |
| if (event->data.server_rpc_new.method == NULL) { |
| return NanEscapeScope(NanNull()); |
| } |
| rpc_new->Set( |
| NanNew("method"), |
| NanNew(event->data.server_rpc_new.method)); |
| rpc_new->Set( |
| NanNew("host"), |
| NanNew(event->data.server_rpc_new.host)); |
| rpc_new->Set(NanNew("absolute_deadline"), |
| NanNew<Date>(TimespecToMilliseconds( |
| event->data.server_rpc_new.deadline))); |
| count = event->data.server_rpc_new.metadata_count; |
| items = event->data.server_rpc_new.metadata_elements; |
| metadata = NanNew<Array>(static_cast<int>(count)); |
| for (unsigned int i = 0; i < count; i++) { |
| Handle<Object> item_obj = Object::New(); |
| item_obj->Set(NanNew("key"), |
| NanNew(items[i].key)); |
| item_obj->Set( |
| NanNew("value"), |
| NanNew(items[i].value, static_cast<int>(items[i].value_length))); |
| metadata->Set(i, item_obj); |
| } |
| rpc_new->Set(NanNew("metadata"), ParseMetadata(items, count)); |
| return NanEscapeScope(rpc_new); |
| default: |
| return NanEscapeScope(NanNull()); |
| } |
| } |
| |
| Handle<Value> CreateEventObject(grpc_event *event) { |
| NanEscapableScope(); |
| if (event == NULL) { |
| return NanEscapeScope(NanNull()); |
| } |
| Handle<Object> event_obj = NanNew<Object>(); |
| Handle<Value> call; |
| if (TagHasCall(event->tag)) { |
| call = TagGetCall(event->tag); |
| } else { |
| call = Call::WrapStruct(event->call); |
| } |
| event_obj->Set(NanNew<String, const char *>("call"), call); |
| event_obj->Set(NanNew<String, const char *>("type"), |
| NanNew<Number>(event->type)); |
| event_obj->Set(NanNew<String, const char *>("data"), GetEventData(event)); |
| |
| return NanEscapeScope(event_obj); |
| } |
| |
| } // namespace node |
| } // namespace grpc |