/* * * 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 #include #include #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 ParseMetadata(grpc_metadata *metadata_elements, size_t length) { NanEscapableScope(); std::map size_map; std::map 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 metadata_object = NanNew(); for (unsigned int i = 0; i < length; i++) { grpc_metadata* elem = &metadata_elements[i]; Handle key_string = String::New(elem->key); Handle array; if (metadata_object->Has(key_string)) { array = Handle::Cast(metadata_object->Get(key_string)); } else { array = NanNew(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 GetEventData(grpc_event *event) { NanEscapableScope(); size_t count; grpc_metadata *items; Handle metadata; Handle status; Handle rpc_new; switch (event->type) { case GRPC_READ: return NanEscapeScope(ByteBufferToBuffer(event->data.read)); case GRPC_WRITE_ACCEPTED: return NanEscapeScope(NanNew(event->data.write_accepted)); case GRPC_FINISH_ACCEPTED: return NanEscapeScope(NanNew(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(); status->Set(NanNew("code"), NanNew(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(); 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(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(static_cast(count)); for (unsigned int i = 0; i < count; i++) { Handle item_obj = Object::New(); item_obj->Set(NanNew("key"), NanNew(items[i].key)); item_obj->Set( NanNew("value"), NanNew(items[i].value, static_cast(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 CreateEventObject(grpc_event *event) { NanEscapableScope(); if (event == NULL) { return NanEscapeScope(NanNull()); } Handle event_obj = NanNew(); Handle call; if (TagHasCall(event->tag)) { call = TagGetCall(event->tag); } else { call = Call::WrapStruct(event->call); } event_obj->Set(NanNew("call"), call); event_obj->Set(NanNew("type"), NanNew(event->type)); event_obj->Set(NanNew("data"), GetEventData(event)); return NanEscapeScope(event_obj); } } // namespace node } // namespace grpc