diff options
author | murgatroid99 <michael.lumish@gmail.com> | 2015-01-26 17:16:57 -0800 |
---|---|---|
committer | murgatroid99 <michael.lumish@gmail.com> | 2015-01-26 17:16:57 -0800 |
commit | 9fbf7e54c29722275d5e8bc0987066004cdd9570 (patch) | |
tree | 37d0ddb59e0ac2ff89cb465023e5f899bd35b452 /src/node/ext | |
parent | f5844ee7de515c3af50c4eec01f107efe54b3f9e (diff) |
Moved extension and JS files to separate directories
Diffstat (limited to 'src/node/ext')
-rw-r--r-- | src/node/ext/byte_buffer.cc | 79 | ||||
-rw-r--r-- | src/node/ext/byte_buffer.h | 56 | ||||
-rw-r--r-- | src/node/ext/call.cc | 385 | ||||
-rw-r--r-- | src/node/ext/call.h | 82 | ||||
-rw-r--r-- | src/node/ext/channel.cc | 182 | ||||
-rw-r--r-- | src/node/ext/channel.h | 79 | ||||
-rw-r--r-- | src/node/ext/completion_queue_async_worker.cc | 89 | ||||
-rw-r--r-- | src/node/ext/completion_queue_async_worker.h | 79 | ||||
-rw-r--r-- | src/node/ext/credentials.cc | 205 | ||||
-rw-r--r-- | src/node/ext/credentials.h | 81 | ||||
-rw-r--r-- | src/node/ext/event.cc | 164 | ||||
-rw-r--r-- | src/node/ext/event.h | 48 | ||||
-rw-r--r-- | src/node/ext/node_grpc.cc | 180 | ||||
-rw-r--r-- | src/node/ext/server.cc | 236 | ||||
-rw-r--r-- | src/node/ext/server.h | 79 | ||||
-rw-r--r-- | src/node/ext/server_credentials.cc | 155 | ||||
-rw-r--r-- | src/node/ext/server_credentials.h | 77 | ||||
-rw-r--r-- | src/node/ext/tag.cc | 101 | ||||
-rw-r--r-- | src/node/ext/tag.h | 59 | ||||
-rw-r--r-- | src/node/ext/timeval.cc | 66 | ||||
-rw-r--r-- | src/node/ext/timeval.h | 48 |
21 files changed, 2530 insertions, 0 deletions
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc new file mode 100644 index 0000000000..142951475a --- /dev/null +++ b/src/node/ext/byte_buffer.cc @@ -0,0 +1,79 @@ +/* + * + * Copyright 2014, 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 <string.h> +#include <malloc.h> + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" +#include "grpc/support/slice.h" + +namespace grpc { +namespace node { + +#include "byte_buffer.h" + +using ::node::Buffer; +using v8::Handle; +using v8::Value; + +grpc_byte_buffer *BufferToByteBuffer(Handle<Value> buffer) { + NanScope(); + int length = Buffer::Length(buffer); + char *data = Buffer::Data(buffer); + gpr_slice slice = gpr_slice_malloc(length); + memcpy(GPR_SLICE_START_PTR(slice), data, length); + grpc_byte_buffer *byte_buffer(grpc_byte_buffer_create(&slice, 1)); + gpr_slice_unref(slice); + return byte_buffer; +} + +Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) { + NanEscapableScope(); + if (buffer == NULL) { + NanReturnNull(); + } + size_t length = grpc_byte_buffer_length(buffer); + char *result = reinterpret_cast<char *>(calloc(length, sizeof(char))); + size_t offset = 0; + grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer); + gpr_slice next; + while (grpc_byte_buffer_reader_next(reader, &next) != 0) { + memcpy(result + offset, GPR_SLICE_START_PTR(next), GPR_SLICE_LENGTH(next)); + offset += GPR_SLICE_LENGTH(next); + } + return NanEscapeScope(NanNewBufferHandle(result, length)); +} +} // namespace node +} // namespace grpc diff --git a/src/node/ext/byte_buffer.h b/src/node/ext/byte_buffer.h new file mode 100644 index 0000000000..ee2b4c0d15 --- /dev/null +++ b/src/node/ext/byte_buffer.h @@ -0,0 +1,56 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_BYTE_BUFFER_H_ +#define NET_GRPC_NODE_BYTE_BUFFER_H_ + +#include <string.h> + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" + +namespace grpc { +namespace node { + +/* Convert a Node.js Buffer to grpc_byte_buffer. Requires that + ::node::Buffer::HasInstance(buffer) */ +grpc_byte_buffer *BufferToByteBuffer(v8::Handle<v8::Value> buffer); + +/* Convert a grpc_byte_buffer to a Node.js Buffer */ +v8::Handle<v8::Value> ByteBufferToBuffer(grpc_byte_buffer *buffer); + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_BYTE_BUFFER_H_ diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc new file mode 100644 index 0000000000..6434c2f0d5 --- /dev/null +++ b/src/node/ext/call.cc @@ -0,0 +1,385 @@ +/* + * + * Copyright 2014, 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 <node.h> + +#include "grpc/grpc.h" +#include "grpc/support/time.h" +#include "byte_buffer.h" +#include "call.h" +#include "channel.h" +#include "completion_queue_async_worker.h" +#include "timeval.h" +#include "tag.h" + +namespace grpc { +namespace node { + +using ::node::Buffer; +using v8::Arguments; +using v8::Array; +using v8::Exception; +using v8::External; +using v8::Function; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Number; +using v8::Object; +using v8::ObjectTemplate; +using v8::Persistent; +using v8::Uint32; +using v8::String; +using v8::Value; + +Persistent<Function> Call::constructor; +Persistent<FunctionTemplate> Call::fun_tpl; + +Call::Call(grpc_call *call) : wrapped_call(call) {} + +Call::~Call() { grpc_call_destroy(wrapped_call); } + +void Call::Init(Handle<Object> exports) { + NanScope(); + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(NanNew("Call")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NanSetPrototypeTemplate(tpl, "addMetadata", + FunctionTemplate::New(AddMetadata)->GetFunction()); + NanSetPrototypeTemplate(tpl, "invoke", + FunctionTemplate::New(Invoke)->GetFunction()); + NanSetPrototypeTemplate(tpl, "serverAccept", + FunctionTemplate::New(ServerAccept)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "serverEndInitialMetadata", + FunctionTemplate::New(ServerEndInitialMetadata)->GetFunction()); + NanSetPrototypeTemplate(tpl, "cancel", + FunctionTemplate::New(Cancel)->GetFunction()); + NanSetPrototypeTemplate(tpl, "startWrite", + FunctionTemplate::New(StartWrite)->GetFunction()); + NanSetPrototypeTemplate( + tpl, "startWriteStatus", + FunctionTemplate::New(StartWriteStatus)->GetFunction()); + NanSetPrototypeTemplate(tpl, "writesDone", + FunctionTemplate::New(WritesDone)->GetFunction()); + NanSetPrototypeTemplate(tpl, "startReadMetadata", + FunctionTemplate::New(WritesDone)->GetFunction()); + NanSetPrototypeTemplate(tpl, "startRead", + FunctionTemplate::New(StartRead)->GetFunction()); + NanAssignPersistent(fun_tpl, tpl); + NanAssignPersistent(constructor, tpl->GetFunction()); + constructor->Set(NanNew("WRITE_BUFFER_HINT"), + NanNew<Uint32, uint32_t>(GRPC_WRITE_BUFFER_HINT)); + constructor->Set(NanNew("WRITE_NO_COMPRESS"), + NanNew<Uint32, uint32_t>(GRPC_WRITE_NO_COMPRESS)); + exports->Set(String::NewSymbol("Call"), constructor); +} + +bool Call::HasInstance(Handle<Value> val) { + NanScope(); + return NanHasInstance(fun_tpl, val); +} + +Handle<Value> Call::WrapStruct(grpc_call *call) { + NanEscapableScope(); + if (call == NULL) { + return NanEscapeScope(NanNull()); + } + const int argc = 1; + Handle<Value> argv[argc] = {External::New(reinterpret_cast<void *>(call))}; + return NanEscapeScope(constructor->NewInstance(argc, argv)); +} + +NAN_METHOD(Call::New) { + NanScope(); + + if (args.IsConstructCall()) { + Call *call; + if (args[0]->IsExternal()) { + // This option is used for wrapping an existing call + grpc_call *call_value = + reinterpret_cast<grpc_call *>(External::Unwrap(args[0])); + call = new Call(call_value); + } else { + if (!Channel::HasInstance(args[0])) { + return NanThrowTypeError("Call's first argument must be a Channel"); + } + if (!args[1]->IsString()) { + return NanThrowTypeError("Call's second argument must be a string"); + } + if (!(args[2]->IsNumber() || args[2]->IsDate())) { + return NanThrowTypeError( + "Call's third argument must be a date or a number"); + } + Handle<Object> channel_object = args[0]->ToObject(); + Channel *channel = ObjectWrap::Unwrap<Channel>(channel_object); + if (channel->GetWrappedChannel() == NULL) { + return NanThrowError("Call cannot be created from a closed channel"); + } + NanUtf8String method(args[1]); + double deadline = args[2]->NumberValue(); + grpc_channel *wrapped_channel = channel->GetWrappedChannel(); + grpc_call *wrapped_call = + grpc_channel_create_call(wrapped_channel, *method, channel->GetHost(), + MillisecondsToTimespec(deadline)); + call = new Call(wrapped_call); + args.This()->SetHiddenValue(String::NewSymbol("channel_"), + channel_object); + } + call->Wrap(args.This()); + NanReturnValue(args.This()); + } else { + const int argc = 4; + Local<Value> argv[argc] = {args[0], args[1], args[2], args[3]}; + NanReturnValue(constructor->NewInstance(argc, argv)); + } +} + +NAN_METHOD(Call::AddMetadata) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("addMetadata can only be called on Call objects"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + for (int i = 0; !args[i]->IsUndefined(); i++) { + if (!args[i]->IsObject()) { + return NanThrowTypeError( + "addMetadata arguments must be objects with key and value"); + } + Handle<Object> item = args[i]->ToObject(); + Handle<Value> key = item->Get(NanNew("key")); + if (!key->IsString()) { + return NanThrowTypeError( + "objects passed to addMetadata must have key->string"); + } + Handle<Value> value = item->Get(NanNew("value")); + if (!Buffer::HasInstance(value)) { + return NanThrowTypeError( + "objects passed to addMetadata must have value->Buffer"); + } + grpc_metadata metadata; + NanUtf8String utf8_key(key); + metadata.key = *utf8_key; + metadata.value = Buffer::Data(value); + metadata.value_length = Buffer::Length(value); + grpc_call_error error = + grpc_call_add_metadata(call->wrapped_call, &metadata, 0); + if (error != GRPC_CALL_OK) { + return NanThrowError("addMetadata failed", error); + } + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::Invoke) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("invoke can only be called on Call objects"); + } + if (!args[0]->IsFunction()) { + return NanThrowTypeError("invoke's first argument must be a function"); + } + if (!args[1]->IsFunction()) { + return NanThrowTypeError("invoke's second argument must be a function"); + } + if (!args[2]->IsUint32()) { + return NanThrowTypeError("invoke's third argument must be integer flags"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + unsigned int flags = args[3]->Uint32Value(); + grpc_call_error error = grpc_call_invoke( + call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), + CreateTag(args[0], args.This()), CreateTag(args[1], args.This()), flags); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("invoke failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::ServerAccept) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("accept can only be called on Call objects"); + } + if (!args[0]->IsFunction()) { + return NanThrowTypeError("accept's first argument must be a function"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_call_error error = grpc_call_server_accept( + call->wrapped_call, CompletionQueueAsyncWorker::GetQueue(), + CreateTag(args[0], args.This())); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("serverAccept failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::ServerEndInitialMetadata) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError( + "serverEndInitialMetadata can only be called on Call objects"); + } + if (!args[0]->IsUint32()) { + return NanThrowTypeError( + "serverEndInitialMetadata's second argument must be integer flags"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + unsigned int flags = args[1]->Uint32Value(); + grpc_call_error error = + grpc_call_server_end_initial_metadata(call->wrapped_call, flags); + if (error != GRPC_CALL_OK) { + return NanThrowError("serverEndInitialMetadata failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::Cancel) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("cancel can only be called on Call objects"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_call_error error = grpc_call_cancel(call->wrapped_call); + if (error != GRPC_CALL_OK) { + return NanThrowError("cancel failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::StartWrite) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("startWrite can only be called on Call objects"); + } + if (!Buffer::HasInstance(args[0])) { + return NanThrowTypeError("startWrite's first argument must be a Buffer"); + } + if (!args[1]->IsFunction()) { + return NanThrowTypeError("startWrite's second argument must be a function"); + } + if (!args[2]->IsUint32()) { + return NanThrowTypeError( + "startWrite's third argument must be integer flags"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_byte_buffer *buffer = BufferToByteBuffer(args[0]); + unsigned int flags = args[2]->Uint32Value(); + grpc_call_error error = grpc_call_start_write( + call->wrapped_call, buffer, CreateTag(args[1], args.This()), flags); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("startWrite failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::StartWriteStatus) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError( + "startWriteStatus can only be called on Call objects"); + } + if (!args[0]->IsUint32()) { + return NanThrowTypeError( + "startWriteStatus's first argument must be a status code"); + } + if (!args[1]->IsString()) { + return NanThrowTypeError( + "startWriteStatus's second argument must be a string"); + } + if (!args[2]->IsFunction()) { + return NanThrowTypeError( + "startWriteStatus's third argument must be a function"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + NanUtf8String details(args[1]); + grpc_call_error error = grpc_call_start_write_status( + call->wrapped_call, (grpc_status_code)args[0]->Uint32Value(), *details, + CreateTag(args[2], args.This())); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("startWriteStatus failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::WritesDone) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("writesDone can only be called on Call objects"); + } + if (!args[0]->IsFunction()) { + return NanThrowTypeError("writesDone's first argument must be a function"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_call_error error = grpc_call_writes_done( + call->wrapped_call, CreateTag(args[0], args.This())); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("writesDone failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Call::StartRead) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("startRead can only be called on Call objects"); + } + if (!args[0]->IsFunction()) { + return NanThrowTypeError("startRead's first argument must be a function"); + } + Call *call = ObjectWrap::Unwrap<Call>(args.This()); + grpc_call_error error = + grpc_call_start_read(call->wrapped_call, CreateTag(args[0], args.This())); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("startRead failed", error); + } + NanReturnUndefined(); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/call.h b/src/node/ext/call.h new file mode 100644 index 0000000000..1924a1bf42 --- /dev/null +++ b/src/node/ext/call.h @@ -0,0 +1,82 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_CALL_H_ +#define NET_GRPC_NODE_CALL_H_ + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" + +#include "channel.h" + +namespace grpc { +namespace node { + +/* Wrapper class for grpc_call structs. */ +class Call : public ::node::ObjectWrap { + public: + static void Init(v8::Handle<v8::Object> exports); + static bool HasInstance(v8::Handle<v8::Value> val); + /* Wrap a grpc_call struct in a javascript object */ + static v8::Handle<v8::Value> WrapStruct(grpc_call *call); + + private: + explicit Call(grpc_call *call); + ~Call(); + + // Prevent copying + Call(const Call &); + Call &operator=(const Call &); + + static NAN_METHOD(New); + static NAN_METHOD(AddMetadata); + static NAN_METHOD(Invoke); + static NAN_METHOD(ServerAccept); + static NAN_METHOD(ServerEndInitialMetadata); + static NAN_METHOD(Cancel); + static NAN_METHOD(StartWrite); + static NAN_METHOD(StartWriteStatus); + static NAN_METHOD(WritesDone); + static NAN_METHOD(StartRead); + static v8::Persistent<v8::Function> constructor; + // Used for typechecking instances of this javascript class + static v8::Persistent<v8::FunctionTemplate> fun_tpl; + + grpc_call *wrapped_call; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_CALL_H_ diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc new file mode 100644 index 0000000000..9087d6f919 --- /dev/null +++ b/src/node/ext/channel.cc @@ -0,0 +1,182 @@ +/* + * + * Copyright 2014, 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 <malloc.h> + +#include <vector> + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" +#include "channel.h" +#include "credentials.h" + +namespace grpc { +namespace node { + +using v8::Arguments; +using v8::Array; +using v8::Exception; +using v8::Function; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Object; +using v8::Persistent; +using v8::String; +using v8::Value; + +Persistent<Function> Channel::constructor; +Persistent<FunctionTemplate> Channel::fun_tpl; + +Channel::Channel(grpc_channel *channel, NanUtf8String *host) + : wrapped_channel(channel), host(host) {} + +Channel::~Channel() { + if (wrapped_channel != NULL) { + grpc_channel_destroy(wrapped_channel); + } + delete host; +} + +void Channel::Init(Handle<Object> exports) { + NanScope(); + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(NanNew("Channel")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NanSetPrototypeTemplate(tpl, "close", + FunctionTemplate::New(Close)->GetFunction()); + NanAssignPersistent(fun_tpl, tpl); + NanAssignPersistent(constructor, tpl->GetFunction()); + exports->Set(NanNew("Channel"), constructor); +} + +bool Channel::HasInstance(Handle<Value> val) { + NanScope(); + return NanHasInstance(fun_tpl, val); +} + +grpc_channel *Channel::GetWrappedChannel() { return this->wrapped_channel; } + +char *Channel::GetHost() { return **this->host; } + +NAN_METHOD(Channel::New) { + NanScope(); + + if (args.IsConstructCall()) { + if (!args[0]->IsString()) { + return NanThrowTypeError("Channel expects a string and an object"); + } + grpc_channel *wrapped_channel; + // Owned by the Channel object + NanUtf8String *host = new NanUtf8String(args[0]); + if (args[1]->IsUndefined()) { + wrapped_channel = grpc_channel_create(**host, NULL); + } else if (args[1]->IsObject()) { + grpc_credentials *creds = NULL; + Handle<Object> args_hash(args[1]->ToObject()->Clone()); + if (args_hash->HasOwnProperty(NanNew("credentials"))) { + Handle<Value> creds_value = args_hash->Get(NanNew("credentials")); + if (!Credentials::HasInstance(creds_value)) { + return NanThrowTypeError( + "credentials arg must be a Credentials object"); + } + Credentials *creds_object = + ObjectWrap::Unwrap<Credentials>(creds_value->ToObject()); + creds = creds_object->GetWrappedCredentials(); + args_hash->Delete(NanNew("credentials")); + } + Handle<Array> keys(args_hash->GetOwnPropertyNames()); + grpc_channel_args channel_args; + channel_args.num_args = keys->Length(); + channel_args.args = reinterpret_cast<grpc_arg *>( + calloc(channel_args.num_args, sizeof(grpc_arg))); + /* These are used to keep all strings until then end of the block, then + destroy them */ + std::vector<NanUtf8String *> key_strings(keys->Length()); + std::vector<NanUtf8String *> value_strings(keys->Length()); + for (unsigned int i = 0; i < channel_args.num_args; i++) { + Handle<String> current_key(keys->Get(i)->ToString()); + Handle<Value> current_value(args_hash->Get(current_key)); + key_strings[i] = new NanUtf8String(current_key); + channel_args.args[i].key = **key_strings[i]; + if (current_value->IsInt32()) { + channel_args.args[i].type = GRPC_ARG_INTEGER; + channel_args.args[i].value.integer = current_value->Int32Value(); + } else if (current_value->IsString()) { + channel_args.args[i].type = GRPC_ARG_STRING; + value_strings[i] = new NanUtf8String(current_value); + channel_args.args[i].value.string = **value_strings[i]; + } else { + free(channel_args.args); + return NanThrowTypeError("Arg values must be strings"); + } + } + if (creds == NULL) { + wrapped_channel = grpc_channel_create(**host, &channel_args); + } else { + wrapped_channel = + grpc_secure_channel_create(creds, **host, &channel_args); + } + free(channel_args.args); + } else { + return NanThrowTypeError("Channel expects a string and an object"); + } + Channel *channel = new Channel(wrapped_channel, host); + channel->Wrap(args.This()); + NanReturnValue(args.This()); + } else { + const int argc = 2; + Local<Value> argv[argc] = {args[0], args[1]}; + NanReturnValue(constructor->NewInstance(argc, argv)); + } +} + +NAN_METHOD(Channel::Close) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("close can only be called on Channel objects"); + } + Channel *channel = ObjectWrap::Unwrap<Channel>(args.This()); + if (channel->wrapped_channel != NULL) { + grpc_channel_destroy(channel->wrapped_channel); + channel->wrapped_channel = NULL; + } + NanReturnUndefined(); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/channel.h b/src/node/ext/channel.h new file mode 100644 index 0000000000..140cbf201a --- /dev/null +++ b/src/node/ext/channel.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_CHANNEL_H_ +#define NET_GRPC_NODE_CHANNEL_H_ + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" + +namespace grpc { +namespace node { + +/* Wrapper class for grpc_channel structs */ +class Channel : public ::node::ObjectWrap { + public: + static void Init(v8::Handle<v8::Object> exports); + static bool HasInstance(v8::Handle<v8::Value> val); + /* This is used to typecheck javascript objects before converting them to + this type */ + static v8::Persistent<v8::Value> prototype; + + /* Returns the grpc_channel struct that this object wraps */ + grpc_channel *GetWrappedChannel(); + + /* Return the hostname that this channel connects to */ + char *GetHost(); + + private: + explicit Channel(grpc_channel *channel, NanUtf8String *host); + ~Channel(); + + // Prevent copying + Channel(const Channel &); + Channel &operator=(const Channel &); + + static NAN_METHOD(New); + static NAN_METHOD(Close); + static v8::Persistent<v8::Function> constructor; + static v8::Persistent<v8::FunctionTemplate> fun_tpl; + + grpc_channel *wrapped_channel; + NanUtf8String *host; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_CHANNEL_H_ diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc new file mode 100644 index 0000000000..8de7db66d5 --- /dev/null +++ b/src/node/ext/completion_queue_async_worker.cc @@ -0,0 +1,89 @@ +/* + * + * Copyright 2014, 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 <node.h> +#include <nan.h> + +#include "grpc/grpc.h" +#include "grpc/support/time.h" +#include "completion_queue_async_worker.h" +#include "event.h" +#include "tag.h" + +namespace grpc { +namespace node { + +using v8::Function; +using v8::Handle; +using v8::Object; +using v8::Persistent; +using v8::Value; + +grpc_completion_queue *CompletionQueueAsyncWorker::queue; + +CompletionQueueAsyncWorker::CompletionQueueAsyncWorker() + : NanAsyncWorker(NULL) {} + +CompletionQueueAsyncWorker::~CompletionQueueAsyncWorker() {} + +void CompletionQueueAsyncWorker::Execute() { + result = grpc_completion_queue_next(queue, gpr_inf_future); +} + +grpc_completion_queue *CompletionQueueAsyncWorker::GetQueue() { return queue; } + +void CompletionQueueAsyncWorker::Next() { + NanScope(); + CompletionQueueAsyncWorker *worker = new CompletionQueueAsyncWorker(); + NanAsyncQueueWorker(worker); +} + +void CompletionQueueAsyncWorker::Init(Handle<Object> exports) { + NanScope(); + queue = grpc_completion_queue_create(); +} + +void CompletionQueueAsyncWorker::HandleOKCallback() { + NanScope(); + NanCallback event_callback(GetTagHandle(result->tag).As<Function>()); + Handle<Value> argv[] = {CreateEventObject(result)}; + + DestroyTag(result->tag); + grpc_event_finish(result); + result = NULL; + + event_callback.Call(1, argv); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/completion_queue_async_worker.h b/src/node/ext/completion_queue_async_worker.h new file mode 100644 index 0000000000..2c928b7024 --- /dev/null +++ b/src/node/ext/completion_queue_async_worker.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ +#define NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ +#include <nan.h> + +#include "grpc/grpc.h" + +namespace grpc { +namespace node { + +/* A worker that asynchronously calls completion_queue_next, and queues onto the + node event loop a call to the function stored in the event's tag. */ +class CompletionQueueAsyncWorker : public NanAsyncWorker { + public: + CompletionQueueAsyncWorker(); + + ~CompletionQueueAsyncWorker(); + /* Calls completion_queue_next with the provided deadline, and stores the + event if there was one or sets an error message if there was not */ + void Execute(); + + /* Returns the completion queue attached to this class */ + static grpc_completion_queue *GetQueue(); + + /* Convenience function to create a worker with the given arguments and queue + it to run asynchronously */ + static void Next(); + + /* Initialize the CompletionQueueAsyncWorker class */ + static void Init(v8::Handle<v8::Object> exports); + + protected: + /* Called when Execute has succeeded (completed without setting an error + message). Calls the saved callback with the event that came from + completion_queue_next */ + void HandleOKCallback(); + + private: + grpc_event *result; + + static grpc_completion_queue *queue; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_COMPLETION_QUEUE_ASYNC_WORKER_H_ diff --git a/src/node/ext/credentials.cc b/src/node/ext/credentials.cc new file mode 100644 index 0000000000..f9cd2fcfe0 --- /dev/null +++ b/src/node/ext/credentials.cc @@ -0,0 +1,205 @@ +/* + * + * Copyright 2014, 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 <node.h> + +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" +#include "grpc/support/log.h" +#include "credentials.h" + +namespace grpc { +namespace node { + +using ::node::Buffer; +using v8::Arguments; +using v8::Exception; +using v8::External; +using v8::Function; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Object; +using v8::ObjectTemplate; +using v8::Persistent; +using v8::Value; + +Persistent<Function> Credentials::constructor; +Persistent<FunctionTemplate> Credentials::fun_tpl; + +Credentials::Credentials(grpc_credentials *credentials) + : wrapped_credentials(credentials) {} + +Credentials::~Credentials() { + gpr_log(GPR_DEBUG, "Destroying credentials object"); + grpc_credentials_release(wrapped_credentials); +} + +void Credentials::Init(Handle<Object> exports) { + NanScope(); + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(NanNew("Credentials")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NanAssignPersistent(fun_tpl, tpl); + NanAssignPersistent(constructor, tpl->GetFunction()); + constructor->Set(NanNew("createDefault"), + FunctionTemplate::New(CreateDefault)->GetFunction()); + constructor->Set(NanNew("createSsl"), + FunctionTemplate::New(CreateSsl)->GetFunction()); + constructor->Set(NanNew("createComposite"), + FunctionTemplate::New(CreateComposite)->GetFunction()); + constructor->Set(NanNew("createGce"), + FunctionTemplate::New(CreateGce)->GetFunction()); + constructor->Set(NanNew("createFake"), + FunctionTemplate::New(CreateFake)->GetFunction()); + constructor->Set(NanNew("createIam"), + FunctionTemplate::New(CreateIam)->GetFunction()); + exports->Set(NanNew("Credentials"), constructor); +} + +bool Credentials::HasInstance(Handle<Value> val) { + NanScope(); + return NanHasInstance(fun_tpl, val); +} + +Handle<Value> Credentials::WrapStruct(grpc_credentials *credentials) { + NanEscapableScope(); + if (credentials == NULL) { + return NanEscapeScope(NanNull()); + } + const int argc = 1; + Handle<Value> argv[argc] = { + External::New(reinterpret_cast<void *>(credentials))}; + return NanEscapeScope(constructor->NewInstance(argc, argv)); +} + +grpc_credentials *Credentials::GetWrappedCredentials() { + return wrapped_credentials; +} + +NAN_METHOD(Credentials::New) { + NanScope(); + + if (args.IsConstructCall()) { + if (!args[0]->IsExternal()) { + return NanThrowTypeError( + "Credentials can only be created with the provided functions"); + } + grpc_credentials *creds_value = + reinterpret_cast<grpc_credentials *>(External::Unwrap(args[0])); + Credentials *credentials = new Credentials(creds_value); + credentials->Wrap(args.This()); + NanReturnValue(args.This()); + } else { + const int argc = 1; + Local<Value> argv[argc] = {args[0]}; + NanReturnValue(constructor->NewInstance(argc, argv)); + } +} + +NAN_METHOD(Credentials::CreateDefault) { + NanScope(); + NanReturnValue(WrapStruct(grpc_default_credentials_create())); +} + +NAN_METHOD(Credentials::CreateSsl) { + NanScope(); + char *root_certs = NULL; + grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; + if (Buffer::HasInstance(args[0])) { + root_certs = Buffer::Data(args[0]); + } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) { + return NanThrowTypeError("createSsl's first argument must be a Buffer"); + } + if (Buffer::HasInstance(args[1])) { + key_cert_pair.private_key = Buffer::Data(args[1]); + } else if (!(args[1]->IsNull() || args[1]->IsUndefined())) { + return NanThrowTypeError( + "createSSl's second argument must be a Buffer if provided"); + } + if (Buffer::HasInstance(args[2])) { + key_cert_pair.cert_chain = Buffer::Data(args[2]); + } else if (!(args[2]->IsNull() || args[2]->IsUndefined())) { + return NanThrowTypeError( + "createSSl's third argument must be a Buffer if provided"); + } + + NanReturnValue(WrapStruct(grpc_ssl_credentials_create( + root_certs, + key_cert_pair.private_key == NULL ? NULL : &key_cert_pair))); +} + +NAN_METHOD(Credentials::CreateComposite) { + NanScope(); + if (!HasInstance(args[0])) { + return NanThrowTypeError( + "createComposite's first argument must be a Credentials object"); + } + if (!HasInstance(args[1])) { + return NanThrowTypeError( + "createComposite's second argument must be a Credentials object"); + } + Credentials *creds1 = ObjectWrap::Unwrap<Credentials>(args[0]->ToObject()); + Credentials *creds2 = ObjectWrap::Unwrap<Credentials>(args[1]->ToObject()); + NanReturnValue(WrapStruct(grpc_composite_credentials_create( + creds1->wrapped_credentials, creds2->wrapped_credentials))); +} + +NAN_METHOD(Credentials::CreateGce) { + NanScope(); + NanReturnValue(WrapStruct(grpc_compute_engine_credentials_create())); +} + +NAN_METHOD(Credentials::CreateFake) { + NanScope(); + NanReturnValue(WrapStruct(grpc_fake_transport_security_credentials_create())); +} + +NAN_METHOD(Credentials::CreateIam) { + NanScope(); + if (!args[0]->IsString()) { + return NanThrowTypeError("createIam's first argument must be a string"); + } + if (!args[1]->IsString()) { + return NanThrowTypeError("createIam's second argument must be a string"); + } + NanUtf8String auth_token(args[0]); + NanUtf8String auth_selector(args[1]); + NanReturnValue( + WrapStruct(grpc_iam_credentials_create(*auth_token, *auth_selector))); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/credentials.h b/src/node/ext/credentials.h new file mode 100644 index 0000000000..981e5a99bc --- /dev/null +++ b/src/node/ext/credentials.h @@ -0,0 +1,81 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_CREDENTIALS_H_ +#define NET_GRPC_NODE_CREDENTIALS_H_ + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" + +namespace grpc { +namespace node { + +/* Wrapper class for grpc_credentials structs */ +class Credentials : public ::node::ObjectWrap { + public: + static void Init(v8::Handle<v8::Object> exports); + static bool HasInstance(v8::Handle<v8::Value> val); + /* Wrap a grpc_credentials struct in a javascript object */ + static v8::Handle<v8::Value> WrapStruct(grpc_credentials *credentials); + + /* Returns the grpc_credentials struct that this object wraps */ + grpc_credentials *GetWrappedCredentials(); + + private: + explicit Credentials(grpc_credentials *credentials); + ~Credentials(); + + // Prevent copying + Credentials(const Credentials &); + Credentials &operator=(const Credentials &); + + static NAN_METHOD(New); + static NAN_METHOD(CreateDefault); + static NAN_METHOD(CreateSsl); + static NAN_METHOD(CreateComposite); + static NAN_METHOD(CreateGce); + static NAN_METHOD(CreateFake); + static NAN_METHOD(CreateIam); + static v8::Persistent<v8::Function> constructor; + // Used for typechecking instances of this javascript class + static v8::Persistent<v8::FunctionTemplate> fun_tpl; + + grpc_credentials *wrapped_credentials; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_CREDENTIALS_H_ diff --git a/src/node/ext/event.cc b/src/node/ext/event.cc new file mode 100644 index 0000000000..2ca38b7448 --- /dev/null +++ b/src/node/ext/event.cc @@ -0,0 +1,164 @@ +/* + * + * Copyright 2014, 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 <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 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> 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_INVOKE_ACCEPTED: + return NanEscapeScope(NanNew<Number>(event->data.invoke_accepted)); + 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; + metadata = NanNew<Array>(static_cast<int>(count)); + for (unsigned int i = 0; i < count; i++) { + Handle<Object> item_obj = NanNew<Object>(); + item_obj->Set(NanNew<String, const char *>("key"), + NanNew<String, char *>(items[i].key)); + item_obj->Set( + NanNew<String, const char *>("value"), + NanNew<String, char *>(items[i].value, + static_cast<int>(items[i].value_length))); + metadata->Set(i, item_obj); + } + return NanEscapeScope(metadata); + 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; + metadata = NanNew<Array>(static_cast<int>(count)); + for (unsigned int i = 0; i < count; i++) { + Handle<Object> item_obj = NanNew<Object>(); + item_obj->Set(NanNew<String, const char *>("key"), + NanNew<String, char *>(items[i].key)); + item_obj->Set( + NanNew<String, const char *>("value"), + NanNew<String, char *>(items[i].value, + static_cast<int>(items[i].value_length))); + metadata->Set(i, item_obj); + } + status->Set(NanNew("metadata"), metadata); + 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<String, const char *>("method"), + NanNew<String, const char *>(event->data.server_rpc_new.method)); + rpc_new->Set( + NanNew<String, const char *>("host"), + NanNew<String, const char *>(event->data.server_rpc_new.host)); + rpc_new->Set(NanNew<String, const char *>("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<String, const char *>("key"), + NanNew<String, char *>(items[i].key)); + item_obj->Set( + NanNew<String, const char *>("value"), + NanNew<String, char *>(items[i].value, + static_cast<int>(items[i].value_length))); + metadata->Set(i, item_obj); + } + rpc_new->Set(NanNew<String, const char *>("metadata"), metadata); + 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 diff --git a/src/node/ext/event.h b/src/node/ext/event.h new file mode 100644 index 0000000000..e06d8f0168 --- /dev/null +++ b/src/node/ext/event.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_EVENT_H_ +#define NET_GRPC_NODE_EVENT_H_ + +#include <node.h> +#include "grpc/grpc.h" + +namespace grpc { +namespace node { + +v8::Handle<v8::Value> CreateEventObject(grpc_event *event); + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_EVENT_H_ diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc new file mode 100644 index 0000000000..bc1dfaf899 --- /dev/null +++ b/src/node/ext/node_grpc.cc @@ -0,0 +1,180 @@ +/* + * + * Copyright 2014, 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 <node.h> +#include <nan.h> +#include <v8.h> +#include "grpc/grpc.h" + +#include "call.h" +#include "channel.h" +#include "event.h" +#include "server.h" +#include "completion_queue_async_worker.h" +#include "credentials.h" +#include "server_credentials.h" + +using v8::Handle; +using v8::Value; +using v8::Object; +using v8::Uint32; +using v8::String; + +void InitStatusConstants(Handle<Object> exports) { + NanScope(); + Handle<Object> status = Object::New(); + exports->Set(NanNew("status"), status); + Handle<Value> OK(NanNew<Uint32, uint32_t>(GRPC_STATUS_OK)); + status->Set(NanNew("OK"), OK); + Handle<Value> CANCELLED(NanNew<Uint32, uint32_t>(GRPC_STATUS_CANCELLED)); + status->Set(NanNew("CANCELLED"), CANCELLED); + Handle<Value> UNKNOWN(NanNew<Uint32, uint32_t>(GRPC_STATUS_UNKNOWN)); + status->Set(NanNew("UNKNOWN"), UNKNOWN); + Handle<Value> INVALID_ARGUMENT( + NanNew<Uint32, uint32_t>(GRPC_STATUS_INVALID_ARGUMENT)); + status->Set(NanNew("INVALID_ARGUMENT"), INVALID_ARGUMENT); + Handle<Value> DEADLINE_EXCEEDED( + NanNew<Uint32, uint32_t>(GRPC_STATUS_DEADLINE_EXCEEDED)); + status->Set(NanNew("DEADLINE_EXCEEDED"), DEADLINE_EXCEEDED); + Handle<Value> NOT_FOUND(NanNew<Uint32, uint32_t>(GRPC_STATUS_NOT_FOUND)); + status->Set(NanNew("NOT_FOUND"), NOT_FOUND); + Handle<Value> ALREADY_EXISTS( + NanNew<Uint32, uint32_t>(GRPC_STATUS_ALREADY_EXISTS)); + status->Set(NanNew("ALREADY_EXISTS"), ALREADY_EXISTS); + Handle<Value> PERMISSION_DENIED( + NanNew<Uint32, uint32_t>(GRPC_STATUS_PERMISSION_DENIED)); + status->Set(NanNew("PERMISSION_DENIED"), PERMISSION_DENIED); + Handle<Value> UNAUTHENTICATED( + NanNew<Uint32, uint32_t>(GRPC_STATUS_UNAUTHENTICATED)); + status->Set(NanNew("UNAUTHENTICATED"), UNAUTHENTICATED); + Handle<Value> RESOURCE_EXHAUSTED( + NanNew<Uint32, uint32_t>(GRPC_STATUS_RESOURCE_EXHAUSTED)); + status->Set(NanNew("RESOURCE_EXHAUSTED"), RESOURCE_EXHAUSTED); + Handle<Value> FAILED_PRECONDITION( + NanNew<Uint32, uint32_t>(GRPC_STATUS_FAILED_PRECONDITION)); + status->Set(NanNew("FAILED_PRECONDITION"), FAILED_PRECONDITION); + Handle<Value> ABORTED(NanNew<Uint32, uint32_t>(GRPC_STATUS_ABORTED)); + status->Set(NanNew("ABORTED"), ABORTED); + Handle<Value> OUT_OF_RANGE( + NanNew<Uint32, uint32_t>(GRPC_STATUS_OUT_OF_RANGE)); + status->Set(NanNew("OUT_OF_RANGE"), OUT_OF_RANGE); + Handle<Value> UNIMPLEMENTED( + NanNew<Uint32, uint32_t>(GRPC_STATUS_UNIMPLEMENTED)); + status->Set(NanNew("UNIMPLEMENTED"), UNIMPLEMENTED); + Handle<Value> INTERNAL(NanNew<Uint32, uint32_t>(GRPC_STATUS_INTERNAL)); + status->Set(NanNew("INTERNAL"), INTERNAL); + Handle<Value> UNAVAILABLE(NanNew<Uint32, uint32_t>(GRPC_STATUS_UNAVAILABLE)); + status->Set(NanNew("UNAVAILABLE"), UNAVAILABLE); + Handle<Value> DATA_LOSS(NanNew<Uint32, uint32_t>(GRPC_STATUS_DATA_LOSS)); + status->Set(NanNew("DATA_LOSS"), DATA_LOSS); +} + +void InitCallErrorConstants(Handle<Object> exports) { + NanScope(); + Handle<Object> call_error = Object::New(); + exports->Set(NanNew("callError"), call_error); + Handle<Value> OK(NanNew<Uint32, uint32_t>(GRPC_CALL_OK)); + call_error->Set(NanNew("OK"), OK); + Handle<Value> ERROR(NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR)); + call_error->Set(NanNew("ERROR"), ERROR); + Handle<Value> NOT_ON_SERVER( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_SERVER)); + call_error->Set(NanNew("NOT_ON_SERVER"), NOT_ON_SERVER); + Handle<Value> NOT_ON_CLIENT( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_ON_CLIENT)); + call_error->Set(NanNew("NOT_ON_CLIENT"), NOT_ON_CLIENT); + Handle<Value> ALREADY_INVOKED( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_INVOKED)); + call_error->Set(NanNew("ALREADY_INVOKED"), ALREADY_INVOKED); + Handle<Value> NOT_INVOKED( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_NOT_INVOKED)); + call_error->Set(NanNew("NOT_INVOKED"), NOT_INVOKED); + Handle<Value> ALREADY_FINISHED( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_ALREADY_FINISHED)); + call_error->Set(NanNew("ALREADY_FINISHED"), ALREADY_FINISHED); + Handle<Value> TOO_MANY_OPERATIONS( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_TOO_MANY_OPERATIONS)); + call_error->Set(NanNew("TOO_MANY_OPERATIONS"), TOO_MANY_OPERATIONS); + Handle<Value> INVALID_FLAGS( + NanNew<Uint32, uint32_t>(GRPC_CALL_ERROR_INVALID_FLAGS)); + call_error->Set(NanNew("INVALID_FLAGS"), INVALID_FLAGS); +} + +void InitOpErrorConstants(Handle<Object> exports) { + NanScope(); + Handle<Object> op_error = Object::New(); + exports->Set(NanNew("opError"), op_error); + Handle<Value> OK(NanNew<Uint32, uint32_t>(GRPC_OP_OK)); + op_error->Set(NanNew("OK"), OK); + Handle<Value> ERROR(NanNew<Uint32, uint32_t>(GRPC_OP_ERROR)); + op_error->Set(NanNew("ERROR"), ERROR); +} + +void InitCompletionTypeConstants(Handle<Object> exports) { + NanScope(); + Handle<Object> completion_type = Object::New(); + exports->Set(NanNew("completionType"), completion_type); + Handle<Value> QUEUE_SHUTDOWN(NanNew<Uint32, uint32_t>(GRPC_QUEUE_SHUTDOWN)); + completion_type->Set(NanNew("QUEUE_SHUTDOWN"), QUEUE_SHUTDOWN); + Handle<Value> READ(NanNew<Uint32, uint32_t>(GRPC_READ)); + completion_type->Set(NanNew("READ"), READ); + Handle<Value> WRITE_ACCEPTED(NanNew<Uint32, uint32_t>(GRPC_WRITE_ACCEPTED)); + completion_type->Set(NanNew("WRITE_ACCEPTED"), WRITE_ACCEPTED); + Handle<Value> FINISH_ACCEPTED(NanNew<Uint32, uint32_t>(GRPC_FINISH_ACCEPTED)); + completion_type->Set(NanNew("FINISH_ACCEPTED"), FINISH_ACCEPTED); + Handle<Value> CLIENT_METADATA_READ( + NanNew<Uint32, uint32_t>(GRPC_CLIENT_METADATA_READ)); + completion_type->Set(NanNew("CLIENT_METADATA_READ"), CLIENT_METADATA_READ); + Handle<Value> FINISHED(NanNew<Uint32, uint32_t>(GRPC_FINISHED)); + completion_type->Set(NanNew("FINISHED"), FINISHED); + Handle<Value> SERVER_RPC_NEW(NanNew<Uint32, uint32_t>(GRPC_SERVER_RPC_NEW)); + completion_type->Set(NanNew("SERVER_RPC_NEW"), SERVER_RPC_NEW); +} + +void init(Handle<Object> exports) { + NanScope(); + grpc_init(); + InitStatusConstants(exports); + InitCallErrorConstants(exports); + InitOpErrorConstants(exports); + InitCompletionTypeConstants(exports); + + grpc::node::Call::Init(exports); + grpc::node::Channel::Init(exports); + grpc::node::Server::Init(exports); + grpc::node::CompletionQueueAsyncWorker::Init(exports); + grpc::node::Credentials::Init(exports); + grpc::node::ServerCredentials::Init(exports); +} + +NODE_MODULE(grpc, init) diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc new file mode 100644 index 0000000000..b102775d33 --- /dev/null +++ b/src/node/ext/server.cc @@ -0,0 +1,236 @@ +/* + * + * Copyright 2014, 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 "server.h" + +#include <node.h> +#include <nan.h> + +#include <malloc.h> + +#include <vector> +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" +#include "call.h" +#include "completion_queue_async_worker.h" +#include "tag.h" +#include "server_credentials.h" + +namespace grpc { +namespace node { + +using v8::Arguments; +using v8::Array; +using v8::Boolean; +using v8::Exception; +using v8::Function; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Local; +using v8::Number; +using v8::Object; +using v8::Persistent; +using v8::String; +using v8::Value; + +Persistent<Function> Server::constructor; +Persistent<FunctionTemplate> Server::fun_tpl; + +Server::Server(grpc_server *server) : wrapped_server(server) {} + +Server::~Server() { grpc_server_destroy(wrapped_server); } + +void Server::Init(Handle<Object> exports) { + NanScope(); + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(String::NewSymbol("Server")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NanSetPrototypeTemplate(tpl, "requestCall", + FunctionTemplate::New(RequestCall)->GetFunction()); + + NanSetPrototypeTemplate(tpl, "addHttp2Port", + FunctionTemplate::New(AddHttp2Port)->GetFunction()); + + NanSetPrototypeTemplate( + tpl, "addSecureHttp2Port", + FunctionTemplate::New(AddSecureHttp2Port)->GetFunction()); + + NanSetPrototypeTemplate(tpl, "start", + FunctionTemplate::New(Start)->GetFunction()); + + NanSetPrototypeTemplate(tpl, "shutdown", + FunctionTemplate::New(Shutdown)->GetFunction()); + + NanAssignPersistent(fun_tpl, tpl); + NanAssignPersistent(constructor, tpl->GetFunction()); + exports->Set(String::NewSymbol("Server"), constructor); +} + +bool Server::HasInstance(Handle<Value> val) { + return NanHasInstance(fun_tpl, val); +} + +NAN_METHOD(Server::New) { + NanScope(); + + /* If this is not a constructor call, make a constructor call and return + the result */ + if (!args.IsConstructCall()) { + const int argc = 1; + Local<Value> argv[argc] = {args[0]}; + NanReturnValue(constructor->NewInstance(argc, argv)); + } + grpc_server *wrapped_server; + grpc_completion_queue *queue = CompletionQueueAsyncWorker::GetQueue(); + if (args[0]->IsUndefined()) { + wrapped_server = grpc_server_create(queue, NULL); + } else if (args[0]->IsObject()) { + grpc_server_credentials *creds = NULL; + Handle<Object> args_hash(args[0]->ToObject()->Clone()); + if (args_hash->HasOwnProperty(NanNew("credentials"))) { + Handle<Value> creds_value = args_hash->Get(NanNew("credentials")); + if (!ServerCredentials::HasInstance(creds_value)) { + return NanThrowTypeError( + "credentials arg must be a ServerCredentials object"); + } + ServerCredentials *creds_object = + ObjectWrap::Unwrap<ServerCredentials>(creds_value->ToObject()); + creds = creds_object->GetWrappedServerCredentials(); + args_hash->Delete(NanNew("credentials")); + } + Handle<Array> keys(args_hash->GetOwnPropertyNames()); + grpc_channel_args channel_args; + channel_args.num_args = keys->Length(); + channel_args.args = reinterpret_cast<grpc_arg *>( + calloc(channel_args.num_args, sizeof(grpc_arg))); + /* These are used to keep all strings until then end of the block, then + destroy them */ + std::vector<NanUtf8String *> key_strings(keys->Length()); + std::vector<NanUtf8String *> value_strings(keys->Length()); + for (unsigned int i = 0; i < channel_args.num_args; i++) { + Handle<String> current_key(keys->Get(i)->ToString()); + Handle<Value> current_value(args_hash->Get(current_key)); + key_strings[i] = new NanUtf8String(current_key); + channel_args.args[i].key = **key_strings[i]; + if (current_value->IsInt32()) { + channel_args.args[i].type = GRPC_ARG_INTEGER; + channel_args.args[i].value.integer = current_value->Int32Value(); + } else if (current_value->IsString()) { + channel_args.args[i].type = GRPC_ARG_STRING; + value_strings[i] = new NanUtf8String(current_value); + channel_args.args[i].value.string = **value_strings[i]; + } else { + free(channel_args.args); + return NanThrowTypeError("Arg values must be strings"); + } + } + if (creds == NULL) { + wrapped_server = grpc_server_create(queue, &channel_args); + } else { + wrapped_server = grpc_secure_server_create(creds, queue, &channel_args); + } + free(channel_args.args); + } else { + return NanThrowTypeError("Server expects an object"); + } + Server *server = new Server(wrapped_server); + server->Wrap(args.This()); + NanReturnValue(args.This()); +} + +NAN_METHOD(Server::RequestCall) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("requestCall can only be called on a Server"); + } + Server *server = ObjectWrap::Unwrap<Server>(args.This()); + grpc_call_error error = grpc_server_request_call( + server->wrapped_server, CreateTag(args[0], NanNull())); + if (error == GRPC_CALL_OK) { + CompletionQueueAsyncWorker::Next(); + } else { + return NanThrowError("requestCall failed", error); + } + NanReturnUndefined(); +} + +NAN_METHOD(Server::AddHttp2Port) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("addHttp2Port can only be called on a Server"); + } + if (!args[0]->IsString()) { + return NanThrowTypeError("addHttp2Port's argument must be a String"); + } + Server *server = ObjectWrap::Unwrap<Server>(args.This()); + NanReturnValue(NanNew<Number>(grpc_server_add_http2_port( + server->wrapped_server, *NanUtf8String(args[0])))); +} + +NAN_METHOD(Server::AddSecureHttp2Port) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError( + "addSecureHttp2Port can only be called on a Server"); + } + if (!args[0]->IsString()) { + return NanThrowTypeError("addSecureHttp2Port's argument must be a String"); + } + Server *server = ObjectWrap::Unwrap<Server>(args.This()); + NanReturnValue(NanNew<Number>(grpc_server_add_secure_http2_port( + server->wrapped_server, *NanUtf8String(args[0])))); +} + +NAN_METHOD(Server::Start) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("start can only be called on a Server"); + } + Server *server = ObjectWrap::Unwrap<Server>(args.This()); + grpc_server_start(server->wrapped_server); + NanReturnUndefined(); +} + +NAN_METHOD(Server::Shutdown) { + NanScope(); + if (!HasInstance(args.This())) { + return NanThrowTypeError("shutdown can only be called on a Server"); + } + Server *server = ObjectWrap::Unwrap<Server>(args.This()); + grpc_server_shutdown(server->wrapped_server); + NanReturnUndefined(); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/server.h b/src/node/ext/server.h new file mode 100644 index 0000000000..d50f1fb6c5 --- /dev/null +++ b/src/node/ext/server.h @@ -0,0 +1,79 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_SERVER_H_ +#define NET_GRPC_NODE_SERVER_H_ + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" + +namespace grpc { +namespace node { + +/* Wraps grpc_server as a JavaScript object. Provides a constructor + and wrapper methods for grpc_server_create, grpc_server_request_call, + grpc_server_add_http2_port, and grpc_server_start. */ +class Server : public ::node::ObjectWrap { + public: + /* Initializes the Server class and exposes the constructor and + wrapper methods to JavaScript */ + static void Init(v8::Handle<v8::Object> exports); + /* Tests whether the given value was constructed by this class's + JavaScript constructor */ + static bool HasInstance(v8::Handle<v8::Value> val); + + private: + explicit Server(grpc_server *server); + ~Server(); + + // Prevent copying + Server(const Server &); + Server &operator=(const Server &); + + static NAN_METHOD(New); + static NAN_METHOD(RequestCall); + static NAN_METHOD(AddHttp2Port); + static NAN_METHOD(AddSecureHttp2Port); + static NAN_METHOD(Start); + static NAN_METHOD(Shutdown); + static v8::Persistent<v8::Function> constructor; + static v8::Persistent<v8::FunctionTemplate> fun_tpl; + + grpc_server *wrapped_server; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_SERVER_H_ diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc new file mode 100644 index 0000000000..393f3a6305 --- /dev/null +++ b/src/node/ext/server_credentials.cc @@ -0,0 +1,155 @@ +/* + * + * Copyright 2014, 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 <node.h> + +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" +#include "grpc/support/log.h" +#include "server_credentials.h" + +namespace grpc { +namespace node { + +using ::node::Buffer; +using v8::Arguments; +using v8::Exception; +using v8::External; +using v8::Function; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Object; +using v8::ObjectTemplate; +using v8::Persistent; +using v8::Value; + +Persistent<Function> ServerCredentials::constructor; +Persistent<FunctionTemplate> ServerCredentials::fun_tpl; + +ServerCredentials::ServerCredentials(grpc_server_credentials *credentials) + : wrapped_credentials(credentials) {} + +ServerCredentials::~ServerCredentials() { + gpr_log(GPR_DEBUG, "Destroying server credentials object"); + grpc_server_credentials_release(wrapped_credentials); +} + +void ServerCredentials::Init(Handle<Object> exports) { + NanScope(); + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(NanNew("ServerCredentials")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + NanAssignPersistent(fun_tpl, tpl); + NanAssignPersistent(constructor, tpl->GetFunction()); + constructor->Set(NanNew("createSsl"), + FunctionTemplate::New(CreateSsl)->GetFunction()); + constructor->Set(NanNew("createFake"), + FunctionTemplate::New(CreateFake)->GetFunction()); + exports->Set(NanNew("ServerCredentials"), constructor); +} + +bool ServerCredentials::HasInstance(Handle<Value> val) { + NanScope(); + return NanHasInstance(fun_tpl, val); +} + +Handle<Value> ServerCredentials::WrapStruct( + grpc_server_credentials *credentials) { + NanEscapableScope(); + if (credentials == NULL) { + return NanEscapeScope(NanNull()); + } + const int argc = 1; + Handle<Value> argv[argc] = { + External::New(reinterpret_cast<void *>(credentials))}; + return NanEscapeScope(constructor->NewInstance(argc, argv)); +} + +grpc_server_credentials *ServerCredentials::GetWrappedServerCredentials() { + return wrapped_credentials; +} + +NAN_METHOD(ServerCredentials::New) { + NanScope(); + + if (args.IsConstructCall()) { + if (!args[0]->IsExternal()) { + return NanThrowTypeError( + "ServerCredentials can only be created with the provide functions"); + } + grpc_server_credentials *creds_value = + reinterpret_cast<grpc_server_credentials *>(External::Unwrap(args[0])); + ServerCredentials *credentials = new ServerCredentials(creds_value); + credentials->Wrap(args.This()); + NanReturnValue(args.This()); + } else { + const int argc = 1; + Local<Value> argv[argc] = {args[0]}; + NanReturnValue(constructor->NewInstance(argc, argv)); + } +} + +NAN_METHOD(ServerCredentials::CreateSsl) { + // TODO: have the node API support multiple key/cert pairs. + NanScope(); + char *root_certs = NULL; + grpc_ssl_pem_key_cert_pair key_cert_pair; + if (Buffer::HasInstance(args[0])) { + root_certs = Buffer::Data(args[0]); + } else if (!(args[0]->IsNull() || args[0]->IsUndefined())) { + return NanThrowTypeError( + "createSSl's first argument must be a Buffer if provided"); + } + if (!Buffer::HasInstance(args[1])) { + return NanThrowTypeError("createSsl's second argument must be a Buffer"); + } + key_cert_pair.private_key = Buffer::Data(args[1]); + if (!Buffer::HasInstance(args[2])) { + return NanThrowTypeError("createSsl's third argument must be a Buffer"); + } + key_cert_pair.cert_chain = Buffer::Data(args[2]); + NanReturnValue(WrapStruct( + grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1))); +} + +NAN_METHOD(ServerCredentials::CreateFake) { + NanScope(); + NanReturnValue( + WrapStruct(grpc_fake_transport_security_server_credentials_create())); +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/server_credentials.h b/src/node/ext/server_credentials.h new file mode 100644 index 0000000000..8baae3f185 --- /dev/null +++ b/src/node/ext/server_credentials.h @@ -0,0 +1,77 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_SERVER_CREDENTIALS_H_ +#define NET_GRPC_NODE_SERVER_CREDENTIALS_H_ + +#include <node.h> +#include <nan.h> +#include "grpc/grpc.h" +#include "grpc/grpc_security.h" + +namespace grpc { +namespace node { + +/* Wrapper class for grpc_server_credentials structs */ +class ServerCredentials : public ::node::ObjectWrap { + public: + static void Init(v8::Handle<v8::Object> exports); + static bool HasInstance(v8::Handle<v8::Value> val); + /* Wrap a grpc_server_credentials struct in a javascript object */ + static v8::Handle<v8::Value> WrapStruct(grpc_server_credentials *credentials); + + /* Returns the grpc_server_credentials struct that this object wraps */ + grpc_server_credentials *GetWrappedServerCredentials(); + + private: + explicit ServerCredentials(grpc_server_credentials *credentials); + ~ServerCredentials(); + + // Prevent copying + ServerCredentials(const ServerCredentials &); + ServerCredentials &operator=(const ServerCredentials &); + + static NAN_METHOD(New); + static NAN_METHOD(CreateSsl); + static NAN_METHOD(CreateFake); + static v8::Persistent<v8::Function> constructor; + // Used for typechecking instances of this javascript class + static v8::Persistent<v8::FunctionTemplate> fun_tpl; + + grpc_server_credentials *wrapped_credentials; +}; + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_SERVER_CREDENTIALS_H_ diff --git a/src/node/ext/tag.cc b/src/node/ext/tag.cc new file mode 100644 index 0000000000..dc8e523e12 --- /dev/null +++ b/src/node/ext/tag.cc @@ -0,0 +1,101 @@ +/* + * + * Copyright 2014, 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 <stdlib.h> +#include <node.h> +#include <nan.h> +#include "tag.h" + +namespace grpc { +namespace node { + +using v8::Handle; +using v8::HandleScope; +using v8::Persistent; +using v8::Value; + +struct tag { + tag(Persistent<Value> *tag, Persistent<Value> *call) + : persist_tag(tag), persist_call(call) {} + + ~tag() { + persist_tag->Dispose(); + if (persist_call != NULL) { + persist_call->Dispose(); + } + } + Persistent<Value> *persist_tag; + Persistent<Value> *persist_call; +}; + +void *CreateTag(Handle<Value> tag, Handle<Value> call) { + NanScope(); + Persistent<Value> *persist_tag = new Persistent<Value>(); + NanAssignPersistent(*persist_tag, tag); + Persistent<Value> *persist_call; + if (call->IsNull() || call->IsUndefined()) { + persist_call = NULL; + } else { + persist_call = new Persistent<Value>(); + NanAssignPersistent(*persist_call, call); + } + struct tag *tag_struct = new struct tag(persist_tag, persist_call); + return reinterpret_cast<void *>(tag_struct); +} + +Handle<Value> GetTagHandle(void *tag) { + NanEscapableScope(); + struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); + Handle<Value> tag_value = NanNew<Value>(*tag_struct->persist_tag); + return NanEscapeScope(tag_value); +} + +bool TagHasCall(void *tag) { + struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); + return tag_struct->persist_call != NULL; +} + +Handle<Value> TagGetCall(void *tag) { + NanEscapableScope(); + struct tag *tag_struct = reinterpret_cast<struct tag *>(tag); + if (tag_struct->persist_call == NULL) { + return NanEscapeScope(NanNull()); + } + Handle<Value> call_value = NanNew<Value>(*tag_struct->persist_call); + return NanEscapeScope(call_value); +} + +void DestroyTag(void *tag) { delete reinterpret_cast<struct tag *>(tag); } + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/tag.h b/src/node/ext/tag.h new file mode 100644 index 0000000000..bdb09252d9 --- /dev/null +++ b/src/node/ext/tag.h @@ -0,0 +1,59 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_TAG_H_ +#define NET_GRPC_NODE_TAG_H_ + +#include <node.h> + +namespace grpc { +namespace node { + +/* Create a void* tag that can be passed to various grpc_call functions from + a javascript value and the javascript wrapper for the call. The call can be + null. */ +void *CreateTag(v8::Handle<v8::Value> tag, v8::Handle<v8::Value> call); +/* Return the javascript value stored in the tag */ +v8::Handle<v8::Value> GetTagHandle(void *tag); +/* Returns true if the call was set (non-null) when the tag was created */ +bool TagHasCall(void *tag); +/* Returns the javascript wrapper for the call associated with this tag */ +v8::Handle<v8::Value> TagGetCall(void *call); +/* Destroy the tag and all resources it is holding. It is illegal to call any + of these other functions on a tag after it has been destroyed. */ +void DestroyTag(void *tag); + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_TAG_H_ diff --git a/src/node/ext/timeval.cc b/src/node/ext/timeval.cc new file mode 100644 index 0000000000..687e33576b --- /dev/null +++ b/src/node/ext/timeval.cc @@ -0,0 +1,66 @@ +/* + * + * Copyright 2014, 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 <limits> + +#include "grpc/grpc.h" +#include "grpc/support/time.h" +#include "timeval.h" + +namespace grpc { +namespace node { + +gpr_timespec MillisecondsToTimespec(double millis) { + if (millis == std::numeric_limits<double>::infinity()) { + return gpr_inf_future; + } else if (millis == -std::numeric_limits<double>::infinity()) { + return gpr_inf_past; + } else { + return gpr_time_from_micros(static_cast<int64_t>(millis * 1000)); + } +} + +double TimespecToMilliseconds(gpr_timespec timespec) { + if (gpr_time_cmp(timespec, gpr_inf_future) == 0) { + return std::numeric_limits<double>::infinity(); + } else if (gpr_time_cmp(timespec, gpr_inf_past) == 0) { + return -std::numeric_limits<double>::infinity(); + } else { + struct timeval time = gpr_timeval_from_timespec(timespec); + return (static_cast<double>(time.tv_sec) * 1000 + + static_cast<double>(time.tv_usec) / 1000); + } +} + +} // namespace node +} // namespace grpc diff --git a/src/node/ext/timeval.h b/src/node/ext/timeval.h new file mode 100644 index 0000000000..1fb0f2c690 --- /dev/null +++ b/src/node/ext/timeval.h @@ -0,0 +1,48 @@ +/* + * + * Copyright 2014, 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. + * + */ + +#ifndef NET_GRPC_NODE_TIMEVAL_H_ +#define NET_GRPC_NODE_TIMEVAL_H_ + +#include "grpc/support/time.h" + +namespace grpc { +namespace node { + +double TimespecToMilliseconds(gpr_timespec time); +gpr_timespec MillisecondsToTimespec(double millis); + +} // namespace node +} // namespace grpc + +#endif // NET_GRPC_NODE_TIMEVAL_H_ |