diff options
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 | 41 | ||||
-rw-r--r-- | src/node/ext/call.cc | 814 | ||||
-rw-r--r-- | src/node/ext/call.h | 119 | ||||
-rw-r--r-- | src/node/ext/call_credentials.cc | 276 | ||||
-rw-r--r-- | src/node/ext/call_credentials.h | 93 | ||||
-rw-r--r-- | src/node/ext/channel.cc | 272 | ||||
-rw-r--r-- | src/node/ext/channel.h | 68 | ||||
-rw-r--r-- | src/node/ext/channel_credentials.cc | 188 | ||||
-rw-r--r-- | src/node/ext/channel_credentials.h | 64 | ||||
-rw-r--r-- | src/node/ext/completion_queue.cc | 80 | ||||
-rw-r--r-- | src/node/ext/completion_queue.h | 32 | ||||
-rw-r--r-- | src/node/ext/node_grpc.cc | 311 | ||||
-rw-r--r-- | src/node/ext/server.cc | 342 | ||||
-rw-r--r-- | src/node/ext/server.h | 69 | ||||
-rw-r--r-- | src/node/ext/server_credentials.cc | 190 | ||||
-rw-r--r-- | src/node/ext/server_credentials.h | 62 | ||||
-rw-r--r-- | src/node/ext/slice.cc | 90 | ||||
-rw-r--r-- | src/node/ext/slice.h | 38 | ||||
-rw-r--r-- | src/node/ext/timeval.cc | 53 | ||||
-rw-r--r-- | src/node/ext/timeval.h | 33 |
21 files changed, 0 insertions, 3314 deletions
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc deleted file mode 100644 index 598b70946c..0000000000 --- a/src/node/ext/byte_buffer.cc +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <string.h> - -#include <nan.h> -#include <node.h> -#include "grpc/byte_buffer_reader.h" -#include "grpc/grpc.h" -#include "grpc/slice.h" - -#include "byte_buffer.h" -#include "slice.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::MaybeLocal; - -using v8::Function; -using v8::Local; -using v8::Number; -using v8::Object; -using v8::Value; - -grpc_byte_buffer* BufferToByteBuffer(Local<Value> buffer) { - Nan::HandleScope scope; - grpc_slice slice = CreateSliceFromBuffer(buffer); - grpc_byte_buffer* byte_buffer(grpc_raw_byte_buffer_create(&slice, 1)); - grpc_slice_unref(slice); - return byte_buffer; -} - -namespace { -void delete_buffer(char* data, void* hint) { - grpc_slice* slice = static_cast<grpc_slice*>(hint); - grpc_slice_unref(*slice); - delete slice; -} -} // namespace - -Local<Value> ByteBufferToBuffer(grpc_byte_buffer* buffer) { - Nan::EscapableHandleScope scope; - if (buffer == NULL) { - return scope.Escape(Nan::Null()); - } - grpc_byte_buffer_reader reader; - if (!grpc_byte_buffer_reader_init(&reader, buffer)) { - Nan::ThrowError("Error initializing byte buffer reader."); - return scope.Escape(Nan::Undefined()); - } - grpc_slice* slice = new grpc_slice; - *slice = grpc_byte_buffer_reader_readall(&reader); - grpc_byte_buffer_reader_destroy(&reader); - char* result = reinterpret_cast<char*>(GRPC_SLICE_START_PTR(*slice)); - size_t length = GRPC_SLICE_LENGTH(*slice); - Local<Value> buf = - Nan::NewBuffer(result, length, delete_buffer, slice).ToLocalChecked(); - return scope.Escape(buf); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/byte_buffer.h b/src/node/ext/byte_buffer.h deleted file mode 100644 index 854e374a45..0000000000 --- a/src/node/ext/byte_buffer.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_BYTE_BUFFER_H_ -#define NET_GRPC_NODE_BYTE_BUFFER_H_ - -#include <string.h> - -#include <nan.h> -#include <node.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::Local<v8::Value> buffer); - -/* Convert a grpc_byte_buffer to a Node.js Buffer */ -v8::Local<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 deleted file mode 100644 index 1547f00519..0000000000 --- a/src/node/ext/call.cc +++ /dev/null @@ -1,814 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <map> -#include <memory> -#include <vector> - -#include <node.h> - -#include "byte_buffer.h" -#include "call.h" -#include "call_credentials.h" -#include "channel.h" -#include "completion_queue.h" -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "grpc/support/alloc.h" -#include "grpc/support/log.h" -#include "grpc/support/time.h" -#include "slice.h" -#include "timeval.h" - -using std::shared_ptr; -using std::unique_ptr; -using std::vector; - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using v8::Array; -using v8::Boolean; -using v8::Exception; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Integer; -using v8::Local; -using v8::Number; -using v8::Object; -using v8::ObjectTemplate; -using v8::String; -using v8::Uint32; -using v8::Value; - -Callback* Call::constructor; -Persistent<FunctionTemplate> Call::fun_tpl; - -/** - * Helper function for throwing errors with a grpc_call_error value. - * Modified from the answer by Gus Goose to - * http://stackoverflow.com/questions/31794200. - */ -Local<Value> nanErrorWithCode(const char* msg, grpc_call_error code) { - EscapableHandleScope scope; - Local<Object> err = Nan::Error(msg).As<Object>(); - Nan::Set(err, Nan::New("code").ToLocalChecked(), Nan::New<Uint32>(code)); - return scope.Escape(err); -} - -bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array* array) { - HandleScope scope; - Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked(); - for (unsigned int i = 0; i < keys->Length(); i++) { - Local<String> current_key = - Nan::To<String>(Nan::Get(keys, i).ToLocalChecked()).ToLocalChecked(); - Local<Value> value_array = Nan::Get(metadata, current_key).ToLocalChecked(); - if (!value_array->IsArray()) { - return false; - } - array->capacity += Local<Array>::Cast(value_array)->Length(); - } - array->metadata = reinterpret_cast<grpc_metadata*>( - gpr_zalloc(array->capacity * sizeof(grpc_metadata))); - for (unsigned int i = 0; i < keys->Length(); i++) { - Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked()); - Local<Array> values = - Local<Array>::Cast(Nan::Get(metadata, current_key).ToLocalChecked()); - grpc_slice key_slice = CreateSliceFromString(current_key); - grpc_slice key_intern_slice = grpc_slice_intern(key_slice); - grpc_slice_unref(key_slice); - for (unsigned int j = 0; j < values->Length(); j++) { - Local<Value> value = Nan::Get(values, j).ToLocalChecked(); - grpc_metadata* current = &array->metadata[array->count]; - current->key = key_intern_slice; - // Only allow binary headers for "-bin" keys - if (grpc_is_binary_header(key_intern_slice)) { - if (::node::Buffer::HasInstance(value)) { - current->value = CreateSliceFromBuffer(value); - } else { - return false; - } - } else { - if (value->IsString()) { - Local<String> string_value = Nan::To<String>(value).ToLocalChecked(); - current->value = CreateSliceFromString(string_value); - } else { - return false; - } - } - array->count += 1; - } - } - return true; -} - -void DestroyMetadataArray(grpc_metadata_array* array) { - for (size_t i = 0; i < array->count; i++) { - // Don't unref keys because they are interned - grpc_slice_unref(array->metadata[i].value); - } - grpc_metadata_array_destroy(array); -} - -Local<Value> ParseMetadata(const grpc_metadata_array* metadata_array) { - EscapableHandleScope scope; - grpc_metadata* metadata_elements = metadata_array->metadata; - size_t length = metadata_array->count; - Local<Object> metadata_object = Nan::New<Object>(); - for (unsigned int i = 0; i < length; i++) { - grpc_metadata* elem = &metadata_elements[i]; - // TODO(murgatroid99): Use zero-copy string construction instead - Local<String> key_string = CopyStringFromSlice(elem->key); - Local<Array> array; - MaybeLocal<Value> maybe_array = Nan::Get(metadata_object, key_string); - if (maybe_array.IsEmpty() || !maybe_array.ToLocalChecked()->IsArray()) { - array = Nan::New<Array>(0); - Nan::Set(metadata_object, key_string, array); - } else { - array = Local<Array>::Cast(maybe_array.ToLocalChecked()); - } - if (grpc_is_binary_header(elem->key)) { - Nan::Set(array, array->Length(), CreateBufferFromSlice(elem->value)); - } else { - // TODO(murgatroid99): Use zero-copy string construction instead - Nan::Set(array, array->Length(), CopyStringFromSlice(elem->value)); - } - } - return scope.Escape(metadata_object); -} - -Local<Value> Op::GetOpType() const { - EscapableHandleScope scope; - return scope.Escape(Nan::New(GetTypeString()).ToLocalChecked()); -} - -Op::~Op() {} - -class SendMetadataOp : public Op { - public: - SendMetadataOp() { grpc_metadata_array_init(&send_metadata); } - ~SendMetadataOp() { DestroyMetadataArray(&send_metadata); } - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::True()); - } - bool ParseOp(Local<Value> value, grpc_op* out) { - if (!value->IsObject()) { - return false; - } - MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value); - if (maybe_metadata.IsEmpty()) { - return false; - } - if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(), &send_metadata)) { - return false; - } - out->data.send_initial_metadata.count = send_metadata.count; - out->data.send_initial_metadata.metadata = send_metadata.metadata; - return true; - } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "send_metadata"; } - - private: - grpc_metadata_array send_metadata; -}; - -class SendMessageOp : public Op { - public: - SendMessageOp() { send_message = NULL; } - ~SendMessageOp() { - if (send_message != NULL) { - grpc_byte_buffer_destroy(send_message); - } - } - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::True()); - } - bool ParseOp(Local<Value> value, grpc_op* out) { - if (!::node::Buffer::HasInstance(value)) { - return false; - } - Local<Object> object_value = Nan::To<Object>(value).ToLocalChecked(); - MaybeLocal<Value> maybe_flag_value = - Nan::Get(object_value, Nan::New("grpcWriteFlags").ToLocalChecked()); - if (!maybe_flag_value.IsEmpty()) { - Local<Value> flag_value = maybe_flag_value.ToLocalChecked(); - if (flag_value->IsUint32()) { - Maybe<uint32_t> maybe_flag = Nan::To<uint32_t>(flag_value); - out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK; - } - } - send_message = BufferToByteBuffer(value); - out->data.send_message.send_message = send_message; - return true; - } - - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "send_message"; } - - private: - grpc_byte_buffer* send_message; -}; - -class SendClientCloseOp : public Op { - public: - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::True()); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { return true; } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "client_close"; } -}; - -class SendServerStatusOp : public Op { - public: - SendServerStatusOp() { - details = grpc_empty_slice(); - grpc_metadata_array_init(&status_metadata); - } - ~SendServerStatusOp() { - grpc_slice_unref(details); - DestroyMetadataArray(&status_metadata); - } - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::True()); - } - bool ParseOp(Local<Value> value, grpc_op* out) { - if (!value->IsObject()) { - return false; - } - Local<Object> server_status = Nan::To<Object>(value).ToLocalChecked(); - MaybeLocal<Value> maybe_metadata = - Nan::Get(server_status, Nan::New("metadata").ToLocalChecked()); - if (maybe_metadata.IsEmpty()) { - return false; - } - if (!maybe_metadata.ToLocalChecked()->IsObject()) { - return false; - } - Local<Object> metadata = - Nan::To<Object>(maybe_metadata.ToLocalChecked()).ToLocalChecked(); - MaybeLocal<Value> maybe_code = - Nan::Get(server_status, Nan::New("code").ToLocalChecked()); - if (maybe_code.IsEmpty()) { - return false; - } - if (!maybe_code.ToLocalChecked()->IsUint32()) { - return false; - } - uint32_t code = Nan::To<uint32_t>(maybe_code.ToLocalChecked()).FromJust(); - MaybeLocal<Value> maybe_details = - Nan::Get(server_status, Nan::New("details").ToLocalChecked()); - if (maybe_details.IsEmpty()) { - return false; - } - if (!maybe_details.ToLocalChecked()->IsString()) { - return false; - } - Local<String> details = - Nan::To<String>(maybe_details.ToLocalChecked()).ToLocalChecked(); - if (!CreateMetadataArray(metadata, &status_metadata)) { - return false; - } - out->data.send_status_from_server.trailing_metadata_count = - status_metadata.count; - out->data.send_status_from_server.trailing_metadata = - status_metadata.metadata; - out->data.send_status_from_server.status = - static_cast<grpc_status_code>(code); - this->details = CreateSliceFromString(details); - out->data.send_status_from_server.status_details = &this->details; - return true; - } - bool IsFinalOp() { return true; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "send_status"; } - - private: - grpc_slice details; - grpc_metadata_array status_metadata; -}; - -class GetMetadataOp : public Op { - public: - GetMetadataOp() { grpc_metadata_array_init(&recv_metadata); } - - ~GetMetadataOp() { grpc_metadata_array_destroy(&recv_metadata); } - - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(ParseMetadata(&recv_metadata)); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { - out->data.recv_initial_metadata.recv_initial_metadata = &recv_metadata; - return true; - } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "metadata"; } - - private: - grpc_metadata_array recv_metadata; -}; - -class ReadMessageOp : public Op { - public: - ReadMessageOp() { recv_message = NULL; } - ~ReadMessageOp() { - if (recv_message != NULL) { - grpc_byte_buffer_destroy(recv_message); - } - } - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(ByteBufferToBuffer(recv_message)); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { - out->data.recv_message.recv_message = &recv_message; - return true; - } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "read"; } - - private: - grpc_byte_buffer* recv_message; -}; - -class ClientStatusOp : public Op { - public: - ClientStatusOp() { - grpc_metadata_array_init(&metadata_array); - status_details = grpc_empty_slice(); - } - - ~ClientStatusOp() { - grpc_metadata_array_destroy(&metadata_array); - grpc_slice_unref(status_details); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { - out->data.recv_status_on_client.trailing_metadata = &metadata_array; - out->data.recv_status_on_client.status = &status; - out->data.recv_status_on_client.status_details = &status_details; - return true; - } - - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - Local<Object> status_obj = Nan::New<Object>(); - Nan::Set(status_obj, Nan::New("code").ToLocalChecked(), - Nan::New<Number>(status)); - Nan::Set(status_obj, Nan::New("details").ToLocalChecked(), - CopyStringFromSlice(status_details)); - Nan::Set(status_obj, Nan::New("metadata").ToLocalChecked(), - ParseMetadata(&metadata_array)); - return scope.Escape(status_obj); - } - bool IsFinalOp() { return true; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "status"; } - - private: - grpc_metadata_array metadata_array; - grpc_status_code status; - grpc_slice status_details; -}; - -class ServerCloseResponseOp : public Op { - public: - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::New<Boolean>(cancelled)); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { - out->data.recv_close_on_server.cancelled = &cancelled; - return true; - } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - protected: - std::string GetTypeString() const { return "cancelled"; } - - private: - int cancelled; -}; - -tag::tag(Callback* callback, OpVec* ops, Call* call, Local<Value> call_value) - : callback(callback), ops(ops), call(call) { - HandleScope scope; - call_persist.Reset(call_value); -} - -tag::~tag() { - delete callback; - delete ops; -} - -void CompleteTag(void* tag, const char* error_message) { - HandleScope scope; - struct tag* tag_struct = reinterpret_cast<struct tag*>(tag); - Callback* callback = tag_struct->callback; - if (error_message == NULL) { - Local<Object> tag_obj = Nan::New<Object>(); - for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin(); - it != tag_struct->ops->end(); ++it) { - Op* op_ptr = it->get(); - Nan::Set(tag_obj, op_ptr->GetOpType(), op_ptr->GetNodeValue()); - } - Local<Value> argv[] = {Nan::Null(), tag_obj}; - callback->Call(2, argv); - } else { - Local<Value> argv[] = {Nan::Error(error_message)}; - callback->Call(1, argv); - } - bool success = (error_message == NULL); - bool is_final_op = false; - for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin(); - it != tag_struct->ops->end(); ++it) { - Op* op_ptr = it->get(); - op_ptr->OnComplete(success); - if (op_ptr->IsFinalOp()) { - is_final_op = true; - } - } - if (tag_struct->call == NULL) { - return; - } - tag_struct->call->CompleteBatch(is_final_op); -} - -void DestroyTag(void* tag) { - struct tag* tag_struct = reinterpret_cast<struct tag*>(tag); - delete tag_struct; -} - -void Call::DestroyCall() { - if (this->wrapped_call != NULL) { - grpc_call_unref(this->wrapped_call); - this->wrapped_call = NULL; - } -} - -Call::Call(grpc_call* call) - : wrapped_call(call), pending_batches(0), has_final_op_completed(false) { - peer = grpc_call_get_peer(call); -} - -Call::~Call() { - DestroyCall(); - gpr_free(peer); -} - -void Call::Init(Local<Object> exports) { - HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("Call").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetPrototypeMethod(tpl, "startBatch", StartBatch); - Nan::SetPrototypeMethod(tpl, "cancel", Cancel); - Nan::SetPrototypeMethod(tpl, "cancelWithStatus", CancelWithStatus); - Nan::SetPrototypeMethod(tpl, "getPeer", GetPeer); - Nan::SetPrototypeMethod(tpl, "setCredentials", SetCredentials); - fun_tpl.Reset(tpl); - Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked(); - Nan::Set(exports, Nan::New("Call").ToLocalChecked(), ctr); - constructor = new Callback(ctr); -} - -bool Call::HasInstance(Local<Value> val) { - HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -Local<Value> Call::WrapStruct(grpc_call* call) { - EscapableHandleScope scope; - if (call == NULL) { - return scope.Escape(Nan::Null()); - } - const int argc = 1; - Local<Value> argv[argc] = {Nan::New<External>(reinterpret_cast<void*>(call))}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - return scope.Escape(Nan::Null()); - } else { - return scope.Escape(maybe_instance.ToLocalChecked()); - } -} - -void Call::CompleteBatch(bool is_final_op) { - if (is_final_op) { - this->has_final_op_completed = true; - } - this->pending_batches--; - if (this->has_final_op_completed && this->pending_batches == 0) { - this->DestroyCall(); - } -} - -NAN_METHOD(Call::New) { - /* Arguments: - * 0: Channel to make the call on - * 1: Method - * 2: Deadline - * 3: host - * 4: parent Call - * 5: propagation flags - */ - if (info.IsConstructCall()) { - Call* call; - if (info[0]->IsExternal()) { - Local<External> ext = info[0].As<External>(); - // This option is used for wrapping an existing call - grpc_call* call_value = reinterpret_cast<grpc_call*>(ext->Value()); - call = new Call(call_value); - } else { - if (!Channel::HasInstance(info[0])) { - return Nan::ThrowTypeError("Call's first argument must be a Channel"); - } - if (!info[1]->IsString()) { - return Nan::ThrowTypeError("Call's second argument must be a string"); - } - if (!(info[2]->IsNumber() || info[2]->IsDate())) { - return Nan::ThrowTypeError( - "Call's third argument must be a date or a number"); - } - // These arguments are at the end because they are optional - grpc_call* parent_call = NULL; - if (Call::HasInstance(info[4])) { - Call* parent_obj = - ObjectWrap::Unwrap<Call>(Nan::To<Object>(info[4]).ToLocalChecked()); - parent_call = parent_obj->wrapped_call; - } else if (!(info[4]->IsUndefined() || info[4]->IsNull())) { - return Nan::ThrowTypeError( - "Call's fifth argument must be another call, if provided"); - } - uint32_t propagate_flags = GRPC_PROPAGATE_DEFAULTS; - if (info[5]->IsUint32()) { - propagate_flags = Nan::To<uint32_t>(info[5]).FromJust(); - } else if (!(info[5]->IsUndefined() || info[5]->IsNull())) { - return Nan::ThrowTypeError( - "Call's sixth argument must be propagate flags, if provided"); - } - Local<Object> channel_object = Nan::To<Object>(info[0]).ToLocalChecked(); - Channel* channel = ObjectWrap::Unwrap<Channel>(channel_object); - if (channel->GetWrappedChannel() == NULL) { - return Nan::ThrowError("Call cannot be created from a closed channel"); - } - double deadline = Nan::To<double>(info[2]).FromJust(); - grpc_channel* wrapped_channel = channel->GetWrappedChannel(); - grpc_call* wrapped_call; - grpc_slice method = - CreateSliceFromString(Nan::To<String>(info[1]).ToLocalChecked()); - if (info[3]->IsString()) { - grpc_slice* host = new grpc_slice; - *host = - CreateSliceFromString(Nan::To<String>(info[3]).ToLocalChecked()); - wrapped_call = grpc_channel_create_call( - wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(), - method, host, MillisecondsToTimespec(deadline), NULL); - delete host; - } else if (info[3]->IsUndefined() || info[3]->IsNull()) { - wrapped_call = grpc_channel_create_call( - wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(), - method, NULL, MillisecondsToTimespec(deadline), NULL); - } else { - return Nan::ThrowTypeError("Call's fourth argument must be a string"); - } - grpc_slice_unref(method); - call = new Call(wrapped_call); - Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(), - channel_object); - } - call->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } else { - const int argc = 4; - Local<Value> argv[argc] = {info[0], info[1], info[2], info[3]}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - // There's probably a pending exception - return; - } else { - info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); - } - } -} - -NAN_METHOD(Call::StartBatch) { - if (!Call::HasInstance(info.This())) { - return Nan::ThrowTypeError("startBatch can only be called on Call objects"); - } - if (!info[0]->IsObject()) { - return Nan::ThrowError("startBatch's first argument must be an object"); - } - if (!info[1]->IsFunction()) { - return Nan::ThrowError("startBatch's second argument must be a callback"); - } - Local<Function> callback_func = info[1].As<Function>(); - Call* call = ObjectWrap::Unwrap<Call>(info.This()); - if (call->wrapped_call == NULL) { - /* This implies that the call has completed and has been destroyed. To - * emulate - * previous behavior, we should call the callback immediately with an error, - * as though the batch had failed in core */ - Local<Value> argv[] = { - Nan::Error("The async function failed because the call has completed")}; - Nan::Call(callback_func, Nan::New<Object>(), 1, argv); - return; - } - Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked(); - Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked(); - size_t nops = keys->Length(); - vector<grpc_op> ops(nops); - unique_ptr<OpVec> op_vector(new OpVec()); - for (unsigned int i = 0; i < nops; i++) { - unique_ptr<Op> op; - MaybeLocal<Value> maybe_key = Nan::Get(keys, i); - if (maybe_key.IsEmpty() || (!maybe_key.ToLocalChecked()->IsUint32())) { - return Nan::ThrowError( - "startBatch's first argument's keys must be integers"); - } - uint32_t type = Nan::To<uint32_t>(maybe_key.ToLocalChecked()).FromJust(); - ops[i].op = static_cast<grpc_op_type>(type); - ops[i].flags = 0; - ops[i].reserved = NULL; - switch (type) { - case GRPC_OP_SEND_INITIAL_METADATA: - op.reset(new SendMetadataOp()); - break; - case GRPC_OP_SEND_MESSAGE: - op.reset(new SendMessageOp()); - break; - case GRPC_OP_SEND_CLOSE_FROM_CLIENT: - op.reset(new SendClientCloseOp()); - break; - case GRPC_OP_SEND_STATUS_FROM_SERVER: - op.reset(new SendServerStatusOp()); - break; - case GRPC_OP_RECV_INITIAL_METADATA: - op.reset(new GetMetadataOp()); - break; - case GRPC_OP_RECV_MESSAGE: - op.reset(new ReadMessageOp()); - break; - case GRPC_OP_RECV_STATUS_ON_CLIENT: - op.reset(new ClientStatusOp()); - break; - case GRPC_OP_RECV_CLOSE_ON_SERVER: - op.reset(new ServerCloseResponseOp()); - break; - default: - return Nan::ThrowError("Argument object had an unrecognized key"); - } - if (!op->ParseOp(obj->Get(type), &ops[i])) { - return Nan::ThrowTypeError("Incorrectly typed arguments to startBatch"); - } - op_vector->push_back(std::move(op)); - } - Callback* callback = new Callback(callback_func); - grpc_call_error error = grpc_call_start_batch( - call->wrapped_call, &ops[0], nops, - new struct tag(callback, op_vector.release(), call, info.This()), NULL); - if (error != GRPC_CALL_OK) { - return Nan::ThrowError(nanErrorWithCode("startBatch failed", error)); - } - call->pending_batches++; - CompletionQueueNext(); -} - -NAN_METHOD(Call::Cancel) { - if (!Call::HasInstance(info.This())) { - return Nan::ThrowTypeError("cancel can only be called on Call objects"); - } - Call* call = ObjectWrap::Unwrap<Call>(info.This()); - if (call->wrapped_call == NULL) { - /* Cancel is supposed to be idempotent. If the call has already finished, - * cancel should just complete silently */ - return; - } - grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL); - if (error != GRPC_CALL_OK) { - return Nan::ThrowError(nanErrorWithCode("cancel failed", error)); - } -} - -NAN_METHOD(Call::CancelWithStatus) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("cancel can only be called on Call objects"); - } - if (!info[0]->IsUint32()) { - return Nan::ThrowTypeError( - "cancelWithStatus's first argument must be a status code"); - } - if (!info[1]->IsString()) { - return Nan::ThrowTypeError( - "cancelWithStatus's second argument must be a string"); - } - Call* call = ObjectWrap::Unwrap<Call>(info.This()); - if (call->wrapped_call == NULL) { - /* Cancel is supposed to be idempotent. If the call has already finished, - * cancel should just complete silently */ - return; - } - grpc_status_code code = - static_cast<grpc_status_code>(Nan::To<uint32_t>(info[0]).FromJust()); - if (code == GRPC_STATUS_OK) { - return Nan::ThrowRangeError( - "cancelWithStatus cannot be called with OK status"); - } - Utf8String details(info[1]); - grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL); -} - -NAN_METHOD(Call::GetPeer) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("getPeer can only be called on Call objects"); - } - Call* call = ObjectWrap::Unwrap<Call>(info.This()); - Local<Value> peer_value = Nan::New(call->peer).ToLocalChecked(); - info.GetReturnValue().Set(peer_value); -} - -NAN_METHOD(Call::SetCredentials) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError( - "setCredentials can only be called on Call objects"); - } - if (!CallCredentials::HasInstance(info[0])) { - return Nan::ThrowTypeError( - "setCredentials' first argument must be a CallCredentials"); - } - Call* call = ObjectWrap::Unwrap<Call>(info.This()); - if (call->wrapped_call == NULL) { - return Nan::ThrowError( - "Cannot set credentials on a call that has already started"); - } - CallCredentials* creds_object = ObjectWrap::Unwrap<CallCredentials>( - Nan::To<Object>(info[0]).ToLocalChecked()); - grpc_call_credentials* creds = creds_object->GetWrappedCredentials(); - grpc_call_error error = GRPC_CALL_ERROR; - if (creds) { - error = grpc_call_set_credentials(call->wrapped_call, creds); - } - info.GetReturnValue().Set(Nan::New<Uint32>(error)); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/call.h b/src/node/ext/call.h deleted file mode 100644 index a809a8b585..0000000000 --- a/src/node/ext/call.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_CALL_H_ -#define NET_GRPC_NODE_CALL_H_ - -#include <memory> -#include <vector> - -#include <nan.h> -#include <node.h> -#include "grpc/grpc.h" -#include "grpc/support/log.h" - -#include "channel.h" - -namespace grpc { -namespace node { - -using std::shared_ptr; -using std::unique_ptr; - -v8::Local<v8::Value> nanErrorWithCode(const char* msg, grpc_call_error code); - -v8::Local<v8::Value> ParseMetadata(const grpc_metadata_array* metadata_array); - -bool CreateMetadataArray(v8::Local<v8::Object> metadata, - grpc_metadata_array* array); - -void DestroyMetadataArray(grpc_metadata_array* array); - -/* Wrapper class for grpc_call structs. */ -class Call : public Nan::ObjectWrap { - public: - static void Init(v8::Local<v8::Object> exports); - static bool HasInstance(v8::Local<v8::Value> val); - /* Wrap a grpc_call struct in a javascript object */ - static v8::Local<v8::Value> WrapStruct(grpc_call* call); - - void CompleteBatch(bool is_final_op); - - private: - explicit Call(grpc_call* call); - ~Call(); - - // Prevent copying - Call(const Call&); - Call& operator=(const Call&); - - void DestroyCall(); - - static NAN_METHOD(New); - static NAN_METHOD(StartBatch); - static NAN_METHOD(Cancel); - static NAN_METHOD(CancelWithStatus); - static NAN_METHOD(GetPeer); - static NAN_METHOD(SetCredentials); - static Nan::Callback* constructor; - // Used for typechecking instances of this javascript class - static Nan::Persistent<v8::FunctionTemplate> fun_tpl; - - grpc_call* wrapped_call; - // The number of ops that were started but not completed on this call - int pending_batches; - /* Indicates whether the "final" op on a call has completed. For a client - call, this is GRPC_OP_RECV_STATUS_ON_CLIENT and for a server call, this - is GRPC_OP_SEND_STATUS_FROM_SERVER */ - bool has_final_op_completed; - char* peer; -}; - -class Op { - public: - virtual v8::Local<v8::Value> GetNodeValue() const = 0; - virtual bool ParseOp(v8::Local<v8::Value> value, grpc_op* out) = 0; - virtual ~Op(); - v8::Local<v8::Value> GetOpType() const; - virtual bool IsFinalOp() = 0; - virtual void OnComplete(bool success) = 0; - - protected: - virtual std::string GetTypeString() const = 0; -}; - -typedef std::vector<unique_ptr<Op>> OpVec; -struct tag { - tag(Nan::Callback* callback, OpVec* ops, Call* call, - v8::Local<v8::Value> call_value); - ~tag(); - Nan::Callback* callback; - OpVec* ops; - Call* call; - Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> - call_persist; -}; - -void DestroyTag(void* tag); - -void CompleteTag(void* tag, const char* error_message); - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_CALL_H_ diff --git a/src/node/ext/call_credentials.cc b/src/node/ext/call_credentials.cc deleted file mode 100644 index c5818a735b..0000000000 --- a/src/node/ext/call_credentials.cc +++ /dev/null @@ -1,276 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <nan.h> -#include <node.h> -#include <uv.h> - -#include <queue> - -#include "call.h" -#include "call_credentials.h" -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "grpc/support/log.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using v8::Exception; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Integer; -using v8::Local; -using v8::Object; -using v8::ObjectTemplate; -using v8::Value; - -Nan::Callback* CallCredentials::constructor; -Persistent<FunctionTemplate> CallCredentials::fun_tpl; - -static Callback* plugin_callback; - -CallCredentials::CallCredentials(grpc_call_credentials* credentials) - : wrapped_credentials(credentials) {} - -CallCredentials::~CallCredentials() { - grpc_call_credentials_release(wrapped_credentials); -} - -void CallCredentials::Init(Local<Object> exports) { - HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("CallCredentials").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetPrototypeMethod(tpl, "compose", Compose); - fun_tpl.Reset(tpl); - Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked(); - Nan::Set(ctr, Nan::New("createFromPlugin").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(CreateFromPlugin)) - .ToLocalChecked()); - Nan::Set(exports, Nan::New("CallCredentials").ToLocalChecked(), ctr); - constructor = new Nan::Callback(ctr); - - Local<FunctionTemplate> callback_tpl = - Nan::New<FunctionTemplate>(PluginCallback); - plugin_callback = - new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked()); -} - -bool CallCredentials::HasInstance(Local<Value> val) { - HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -Local<Value> CallCredentials::WrapStruct(grpc_call_credentials* credentials) { - EscapableHandleScope scope; - const int argc = 1; - if (credentials == NULL) { - return scope.Escape(Nan::Null()); - } - Local<Value> argv[argc] = { - Nan::New<External>(reinterpret_cast<void*>(credentials))}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - return scope.Escape(Nan::Null()); - } else { - return scope.Escape(maybe_instance.ToLocalChecked()); - } -} - -grpc_call_credentials* CallCredentials::GetWrappedCredentials() { - return wrapped_credentials; -} - -NAN_METHOD(CallCredentials::New) { - if (info.IsConstructCall()) { - if (!info[0]->IsExternal()) { - return Nan::ThrowTypeError( - "CallCredentials can only be created with the provided functions"); - } - Local<External> ext = info[0].As<External>(); - grpc_call_credentials* creds_value = - reinterpret_cast<grpc_call_credentials*>(ext->Value()); - CallCredentials* credentials = new CallCredentials(creds_value); - credentials->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - return; - } else { - // This should never be called directly - return Nan::ThrowTypeError( - "CallCredentials can only be created with the provided functions"); - } -} - -NAN_METHOD(CallCredentials::Compose) { - if (!CallCredentials::HasInstance(info.This())) { - return Nan::ThrowTypeError( - "compose can only be called on CallCredentials objects"); - } - if (!CallCredentials::HasInstance(info[0])) { - return Nan::ThrowTypeError( - "compose's first argument must be a CallCredentials object"); - } - CallCredentials* self = ObjectWrap::Unwrap<CallCredentials>(info.This()); - CallCredentials* other = ObjectWrap::Unwrap<CallCredentials>( - Nan::To<Object>(info[0]).ToLocalChecked()); - grpc_call_credentials* creds = grpc_composite_call_credentials_create( - self->wrapped_credentials, other->wrapped_credentials, NULL); - info.GetReturnValue().Set(WrapStruct(creds)); -} - -NAN_METHOD(CallCredentials::CreateFromPlugin) { - if (!info[0]->IsFunction()) { - return Nan::ThrowTypeError( - "createFromPlugin's argument must be a function"); - } - grpc_metadata_credentials_plugin plugin; - plugin_state* state = new plugin_state; - state->callback = new Nan::Callback(info[0].As<Function>()); - state->pending_callbacks = new std::queue<plugin_callback_data*>(); - uv_mutex_init(&state->plugin_mutex); - uv_async_init(uv_default_loop(), &state->plugin_async, SendPluginCallback); - uv_unref((uv_handle_t*)&state->plugin_async); - - state->plugin_async.data = state; - - plugin.get_metadata = plugin_get_metadata; - plugin.destroy = plugin_destroy_state; - plugin.state = reinterpret_cast<void*>(state); - plugin.type = ""; - grpc_call_credentials* creds = - grpc_metadata_credentials_create_from_plugin(plugin, NULL); - info.GetReturnValue().Set(WrapStruct(creds)); -} - -NAN_METHOD(PluginCallback) { - // Arguments: status code, error details, metadata - if (!info[0]->IsUint32()) { - return Nan::ThrowTypeError( - "The callback's first argument must be a status code"); - } - if (!info[1]->IsString()) { - return Nan::ThrowTypeError( - "The callback's second argument must be a string"); - } - if (!info[2]->IsObject()) { - return Nan::ThrowTypeError( - "The callback's third argument must be an object"); - } - if (!info[3]->IsObject()) { - return Nan::ThrowTypeError( - "The callback's fourth argument must be an object"); - } - grpc_status_code code = - static_cast<grpc_status_code>(Nan::To<uint32_t>(info[0]).FromJust()); - Utf8String details_utf8_str(info[1]); - char* details = *details_utf8_str; - grpc_metadata_array array; - grpc_metadata_array_init(&array); - Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked(); - if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(), &array)) { - return Nan::ThrowError("Failed to parse metadata"); - } - grpc_credentials_plugin_metadata_cb cb = - reinterpret_cast<grpc_credentials_plugin_metadata_cb>( - Nan::Get(callback_data, Nan::New("cb").ToLocalChecked()) - .ToLocalChecked() - .As<External>() - ->Value()); - void* user_data = - Nan::Get(callback_data, Nan::New("user_data").ToLocalChecked()) - .ToLocalChecked() - .As<External>() - ->Value(); - cb(user_data, array.metadata, array.count, code, details); - DestroyMetadataArray(&array); -} - -NAUV_WORK_CB(SendPluginCallback) { - Nan::HandleScope scope; - plugin_state* state = reinterpret_cast<plugin_state*>(async->data); - std::queue<plugin_callback_data*> callbacks; - uv_mutex_lock(&state->plugin_mutex); - state->pending_callbacks->swap(callbacks); - uv_mutex_unlock(&state->plugin_mutex); - while (!callbacks.empty()) { - plugin_callback_data* data = callbacks.front(); - callbacks.pop(); - Local<Object> callback_data = Nan::New<Object>(); - Nan::Set(callback_data, Nan::New("cb").ToLocalChecked(), - Nan::New<v8::External>(reinterpret_cast<void*>(data->cb))); - Nan::Set(callback_data, Nan::New("user_data").ToLocalChecked(), - Nan::New<v8::External>(data->user_data)); - const int argc = 3; - v8::Local<v8::Value> argv[argc] = { - Nan::New(data->service_url).ToLocalChecked(), callback_data, - // Get Local<Function> from Nan::Callback* - **plugin_callback}; - Nan::Callback* callback = state->callback; - callback->Call(argc, argv); - delete data; - } -} - -int plugin_get_metadata( - void* state, grpc_auth_metadata_context context, - grpc_credentials_plugin_metadata_cb cb, void* user_data, - grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], - size_t* num_creds_md, grpc_status_code* status, - const char** error_details) { - plugin_state* p_state = reinterpret_cast<plugin_state*>(state); - plugin_callback_data* data = new plugin_callback_data; - data->service_url = context.service_url; - data->cb = cb; - data->user_data = user_data; - - uv_mutex_lock(&p_state->plugin_mutex); - p_state->pending_callbacks->push(data); - uv_mutex_unlock(&p_state->plugin_mutex); - - uv_async_send(&p_state->plugin_async); - return 0; // Async processing. -} - -void plugin_uv_close_cb(uv_handle_t* handle) { - uv_async_t* async = reinterpret_cast<uv_async_t*>(handle); - plugin_state* state = reinterpret_cast<plugin_state*>(async->data); - uv_mutex_destroy(&state->plugin_mutex); - delete state->pending_callbacks; - delete state->callback; - delete state; -} - -void plugin_destroy_state(void* ptr) { - plugin_state* state = reinterpret_cast<plugin_state*>(ptr); - uv_close((uv_handle_t*)&state->plugin_async, plugin_uv_close_cb); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/call_credentials.h b/src/node/ext/call_credentials.h deleted file mode 100644 index 6474ba5f12..0000000000 --- a/src/node/ext/call_credentials.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_NODE_CALL_CREDENTIALS_H_ -#define GRPC_NODE_CALL_CREDENTIALS_H_ - -#include <queue> - -#include <nan.h> -#include <node.h> -#include <uv.h> -#include "grpc/grpc_security.h" - -namespace grpc { -namespace node { - -class CallCredentials : public Nan::ObjectWrap { - public: - static void Init(v8::Local<v8::Object> exports); - static bool HasInstance(v8::Local<v8::Value> val); - /* Wrap a grpc_call_credentials struct in a javascript object */ - static v8::Local<v8::Value> WrapStruct(grpc_call_credentials* credentials); - - /* Returns the grpc_call_credentials struct that this object wraps */ - grpc_call_credentials* GetWrappedCredentials(); - - private: - explicit CallCredentials(grpc_call_credentials* credentials); - ~CallCredentials(); - - // Prevent copying - CallCredentials(const CallCredentials&); - CallCredentials& operator=(const CallCredentials&); - - static NAN_METHOD(New); - static NAN_METHOD(CreateSsl); - static NAN_METHOD(CreateFromPlugin); - - static NAN_METHOD(Compose); - static Nan::Callback* constructor; - // Used for typechecking instances of this javascript class - static Nan::Persistent<v8::FunctionTemplate> fun_tpl; - - grpc_call_credentials* wrapped_credentials; -}; - -/* Auth metadata plugin functionality */ - -typedef struct plugin_callback_data { - const char* service_url; - grpc_credentials_plugin_metadata_cb cb; - void* user_data; -} plugin_callback_data; - -typedef struct plugin_state { - Nan::Callback* callback; - std::queue<plugin_callback_data*>* pending_callbacks; - uv_mutex_t plugin_mutex; - // async.data == this - uv_async_t plugin_async; -} plugin_state; - -int plugin_get_metadata( - void* state, grpc_auth_metadata_context context, - grpc_credentials_plugin_metadata_cb cb, void* user_data, - grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX], - size_t* num_creds_md, grpc_status_code* status, const char** error_details); - -void plugin_destroy_state(void* state); - -NAN_METHOD(PluginCallback); - -NAUV_WORK_CB(SendPluginCallback); - -} // namespace node -} // namespace grpc - -#endif // GRPC_NODE_CALL_CREDENTIALS_H_ diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc deleted file mode 100644 index 2c072d5113..0000000000 --- a/src/node/ext/channel.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <vector> - -#include "grpc/support/log.h" - -#include <nan.h> -#include <node.h> -#include "call.h" -#include "channel.h" -#include "channel_credentials.h" -#include "completion_queue.h" -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "timeval.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using v8::Array; -using v8::Exception; -using v8::Function; -using v8::FunctionTemplate; -using v8::Integer; -using v8::Local; -using v8::Number; -using v8::Object; -using v8::String; -using v8::Value; - -Callback* Channel::constructor; -Persistent<FunctionTemplate> Channel::fun_tpl; - -bool ParseChannelArgs(Local<Value> args_val, - grpc_channel_args** channel_args_ptr) { - if (args_val->IsUndefined() || args_val->IsNull()) { - *channel_args_ptr = NULL; - return true; - } - if (!args_val->IsObject()) { - *channel_args_ptr = NULL; - return false; - } - grpc_channel_args* channel_args = - reinterpret_cast<grpc_channel_args*>(malloc(sizeof(grpc_channel_args))); - *channel_args_ptr = channel_args; - Local<Object> args_hash = Nan::To<Object>(args_val).ToLocalChecked(); - Local<Array> keys = Nan::GetOwnPropertyNames(args_hash).ToLocalChecked(); - channel_args->num_args = keys->Length(); - channel_args->args = reinterpret_cast<grpc_arg*>( - calloc(channel_args->num_args, sizeof(grpc_arg))); - for (unsigned int i = 0; i < channel_args->num_args; i++) { - Local<Value> key = Nan::Get(keys, i).ToLocalChecked(); - Utf8String key_str(key); - if (*key_str == NULL) { - // Key string onversion failed - return false; - } - Local<Value> value = Nan::Get(args_hash, key).ToLocalChecked(); - if (value->IsInt32()) { - channel_args->args[i].type = GRPC_ARG_INTEGER; - channel_args->args[i].value.integer = Nan::To<int32_t>(value).FromJust(); - } else if (value->IsString()) { - Utf8String val_str(value); - channel_args->args[i].type = GRPC_ARG_STRING; - channel_args->args[i].value.string = - reinterpret_cast<char*>(calloc(val_str.length() + 1, sizeof(char))); - memcpy(channel_args->args[i].value.string, *val_str, - val_str.length() + 1); - } else { - // The value does not match either of the accepted types - return false; - } - channel_args->args[i].key = - reinterpret_cast<char*>(calloc(key_str.length() + 1, sizeof(char))); - memcpy(channel_args->args[i].key, *key_str, key_str.length() + 1); - } - return true; -} - -void DeallocateChannelArgs(grpc_channel_args* channel_args) { - if (channel_args == NULL) { - return; - } - for (size_t i = 0; i < channel_args->num_args; i++) { - if (channel_args->args[i].key == NULL) { - /* NULL key implies that this argument and all subsequent arguments failed - * to parse */ - break; - } - free(channel_args->args[i].key); - if (channel_args->args[i].type == GRPC_ARG_STRING) { - free(channel_args->args[i].value.string); - } - } - free(channel_args->args); - free(channel_args); -} - -Channel::Channel(grpc_channel* channel) : wrapped_channel(channel) {} - -Channel::~Channel() { - gpr_log(GPR_DEBUG, "Destroying channel"); - if (wrapped_channel != NULL) { - grpc_channel_destroy(wrapped_channel); - } -} - -void Channel::Init(Local<Object> exports) { - Nan::HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("Channel").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetPrototypeMethod(tpl, "close", Close); - Nan::SetPrototypeMethod(tpl, "getTarget", GetTarget); - Nan::SetPrototypeMethod(tpl, "getConnectivityState", GetConnectivityState); - Nan::SetPrototypeMethod(tpl, "watchConnectivityState", - WatchConnectivityState); - fun_tpl.Reset(tpl); - Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked(); - Nan::Set(exports, Nan::New("Channel").ToLocalChecked(), ctr); - constructor = new Callback(ctr); -} - -bool Channel::HasInstance(Local<Value> val) { - HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -grpc_channel* Channel::GetWrappedChannel() { return this->wrapped_channel; } - -NAN_METHOD(Channel::New) { - if (info.IsConstructCall()) { - if (!info[0]->IsString()) { - return Nan::ThrowTypeError( - "Channel expects a string, a credential and an object"); - } - grpc_channel* wrapped_channel; - // Owned by the Channel object - Utf8String host(info[0]); - grpc_channel_credentials* creds; - if (!ChannelCredentials::HasInstance(info[1])) { - return Nan::ThrowTypeError( - "Channel's second argument must be a ChannelCredentials"); - } - ChannelCredentials* creds_object = ObjectWrap::Unwrap<ChannelCredentials>( - Nan::To<Object>(info[1]).ToLocalChecked()); - creds = creds_object->GetWrappedCredentials(); - grpc_channel_args* channel_args_ptr = NULL; - if (!ParseChannelArgs(info[2], &channel_args_ptr)) { - DeallocateChannelArgs(channel_args_ptr); - return Nan::ThrowTypeError( - "Channel options must be an object with " - "string keys and integer or string values"); - } - if (creds == NULL) { - wrapped_channel = - grpc_insecure_channel_create(*host, channel_args_ptr, NULL); - } else { - wrapped_channel = - grpc_secure_channel_create(creds, *host, channel_args_ptr, NULL); - } - DeallocateChannelArgs(channel_args_ptr); - Channel* channel = new Channel(wrapped_channel); - channel->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - return; - } else { - const int argc = 3; - Local<Value> argv[argc] = {info[0], info[1], info[2]}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - // There's probably a pending exception - return; - } else { - info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); - } - } -} - -NAN_METHOD(Channel::Close) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("close can only be called on Channel objects"); - } - Channel* channel = ObjectWrap::Unwrap<Channel>(info.This()); - if (channel->wrapped_channel != NULL) { - grpc_channel_destroy(channel->wrapped_channel); - channel->wrapped_channel = NULL; - } -} - -NAN_METHOD(Channel::GetTarget) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError( - "getTarget can only be called on Channel objects"); - } - Channel* channel = ObjectWrap::Unwrap<Channel>(info.This()); - info.GetReturnValue().Set( - Nan::New(grpc_channel_get_target(channel->wrapped_channel)) - .ToLocalChecked()); -} - -NAN_METHOD(Channel::GetConnectivityState) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError( - "getConnectivityState can only be called on Channel objects"); - } - Channel* channel = ObjectWrap::Unwrap<Channel>(info.This()); - int try_to_connect = (int)info[0]->Equals(Nan::True()); - info.GetReturnValue().Set(grpc_channel_check_connectivity_state( - channel->wrapped_channel, try_to_connect)); -} - -NAN_METHOD(Channel::WatchConnectivityState) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError( - "watchConnectivityState can only be called on Channel objects"); - } - if (!info[0]->IsUint32()) { - return Nan::ThrowTypeError( - "watchConnectivityState's first argument must be a channel state"); - } - if (!(info[1]->IsNumber() || info[1]->IsDate())) { - return Nan::ThrowTypeError( - "watchConnectivityState's second argument must be a date or a number"); - } - if (!info[2]->IsFunction()) { - return Nan::ThrowTypeError( - "watchConnectivityState's third argument must be a callback"); - } - grpc_connectivity_state last_state = static_cast<grpc_connectivity_state>( - Nan::To<uint32_t>(info[0]).FromJust()); - double deadline = Nan::To<double>(info[1]).FromJust(); - Local<Function> callback_func = info[2].As<Function>(); - Nan::Callback* callback = new Callback(callback_func); - Channel* channel = ObjectWrap::Unwrap<Channel>(info.This()); - unique_ptr<OpVec> ops(new OpVec()); - grpc_channel_watch_connectivity_state( - channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline), - GetCompletionQueue(), - new struct tag(callback, ops.release(), NULL, Nan::Null())); - CompletionQueueNext(); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/channel.h b/src/node/ext/channel.h deleted file mode 100644 index bfdcbe617c..0000000000 --- a/src/node/ext/channel.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_CHANNEL_H_ -#define NET_GRPC_NODE_CHANNEL_H_ - -#include <nan.h> -#include <node.h> -#include "grpc/grpc.h" - -namespace grpc { -namespace node { - -bool ParseChannelArgs(v8::Local<v8::Value> args_val, - grpc_channel_args** channel_args_ptr); - -void DeallocateChannelArgs(grpc_channel_args* channel_args); - -/* Wrapper class for grpc_channel structs */ -class Channel : public Nan::ObjectWrap { - public: - static void Init(v8::Local<v8::Object> exports); - static bool HasInstance(v8::Local<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(); - - private: - explicit Channel(grpc_channel* channel); - ~Channel(); - - // Prevent copying - Channel(const Channel&); - Channel& operator=(const Channel&); - - static NAN_METHOD(New); - static NAN_METHOD(Close); - static NAN_METHOD(GetTarget); - static NAN_METHOD(GetConnectivityState); - static NAN_METHOD(WatchConnectivityState); - static Nan::Callback* constructor; - static Nan::Persistent<v8::FunctionTemplate> fun_tpl; - - grpc_channel* wrapped_channel; -}; - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_CHANNEL_H_ diff --git a/src/node/ext/channel_credentials.cc b/src/node/ext/channel_credentials.cc deleted file mode 100644 index a145c0c53a..0000000000 --- a/src/node/ext/channel_credentials.cc +++ /dev/null @@ -1,188 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <node.h> - -#include "call.h" -#include "call_credentials.h" -#include "channel_credentials.h" -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "grpc/support/log.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using v8::Exception; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Integer; -using v8::Local; -using v8::Object; -using v8::ObjectTemplate; -using v8::Value; - -Nan::Callback* ChannelCredentials::constructor; -Persistent<FunctionTemplate> ChannelCredentials::fun_tpl; - -ChannelCredentials::ChannelCredentials(grpc_channel_credentials* credentials) - : wrapped_credentials(credentials) {} - -ChannelCredentials::~ChannelCredentials() { - grpc_channel_credentials_release(wrapped_credentials); -} - -void ChannelCredentials::Init(Local<Object> exports) { - HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("ChannelCredentials").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetPrototypeMethod(tpl, "compose", Compose); - fun_tpl.Reset(tpl); - Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked(); - Nan::Set( - ctr, Nan::New("createSsl").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked()); - Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(CreateInsecure)) - .ToLocalChecked()); - Nan::Set(exports, Nan::New("ChannelCredentials").ToLocalChecked(), ctr); - constructor = new Nan::Callback(ctr); -} - -bool ChannelCredentials::HasInstance(Local<Value> val) { - HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -Local<Value> ChannelCredentials::WrapStruct( - grpc_channel_credentials* credentials) { - EscapableHandleScope scope; - const int argc = 1; - Local<Value> argv[argc] = { - Nan::New<External>(reinterpret_cast<void*>(credentials))}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - return scope.Escape(Nan::Null()); - } else { - return scope.Escape(maybe_instance.ToLocalChecked()); - } -} - -grpc_channel_credentials* ChannelCredentials::GetWrappedCredentials() { - return wrapped_credentials; -} - -NAN_METHOD(ChannelCredentials::New) { - if (info.IsConstructCall()) { - if (!info[0]->IsExternal()) { - return Nan::ThrowTypeError( - "ChannelCredentials can only be created with the provided functions"); - } - Local<External> ext = info[0].As<External>(); - grpc_channel_credentials* creds_value = - reinterpret_cast<grpc_channel_credentials*>(ext->Value()); - ChannelCredentials* credentials = new ChannelCredentials(creds_value); - credentials->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - return; - } else { - // This should never be called directly - return Nan::ThrowTypeError( - "ChannelCredentials can only be created with the provided functions"); - } -} - -NAN_METHOD(ChannelCredentials::CreateSsl) { - char* root_certs = NULL; - grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL}; - if (::node::Buffer::HasInstance(info[0])) { - root_certs = ::node::Buffer::Data(info[0]); - } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) { - return Nan::ThrowTypeError("createSsl's first argument must be a Buffer"); - } - if (::node::Buffer::HasInstance(info[1])) { - key_cert_pair.private_key = ::node::Buffer::Data(info[1]); - } else if (!(info[1]->IsNull() || info[1]->IsUndefined())) { - return Nan::ThrowTypeError( - "createSSl's second argument must be a Buffer if provided"); - } - if (::node::Buffer::HasInstance(info[2])) { - key_cert_pair.cert_chain = ::node::Buffer::Data(info[2]); - } else if (!(info[2]->IsNull() || info[2]->IsUndefined())) { - return Nan::ThrowTypeError( - "createSSl's third argument must be a Buffer if provided"); - } - if ((key_cert_pair.private_key == NULL) != - (key_cert_pair.cert_chain == NULL)) { - return Nan::ThrowError( - "createSsl's second and third arguments must be" - " provided or omitted together"); - } - grpc_channel_credentials* creds = grpc_ssl_credentials_create( - root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair, - NULL); - if (creds == NULL) { - info.GetReturnValue().SetNull(); - } else { - info.GetReturnValue().Set(WrapStruct(creds)); - } -} - -NAN_METHOD(ChannelCredentials::Compose) { - if (!ChannelCredentials::HasInstance(info.This())) { - return Nan::ThrowTypeError( - "compose can only be called on ChannelCredentials objects"); - } - if (!CallCredentials::HasInstance(info[0])) { - return Nan::ThrowTypeError( - "compose's first argument must be a CallCredentials object"); - } - ChannelCredentials* self = - ObjectWrap::Unwrap<ChannelCredentials>(info.This()); - if (self->wrapped_credentials == NULL) { - return Nan::ThrowTypeError("Cannot compose insecure credential"); - } - CallCredentials* other = ObjectWrap::Unwrap<CallCredentials>( - Nan::To<Object>(info[0]).ToLocalChecked()); - grpc_channel_credentials* creds = grpc_composite_channel_credentials_create( - self->wrapped_credentials, other->GetWrappedCredentials(), NULL); - if (creds == NULL) { - info.GetReturnValue().SetNull(); - } else { - info.GetReturnValue().Set(WrapStruct(creds)); - } -} - -NAN_METHOD(ChannelCredentials::CreateInsecure) { - info.GetReturnValue().Set(WrapStruct(NULL)); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/channel_credentials.h b/src/node/ext/channel_credentials.h deleted file mode 100644 index 3be5a22719..0000000000 --- a/src/node/ext/channel_credentials.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ -#define NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ - -#include <nan.h> -#include <node.h> -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" - -namespace grpc { -namespace node { - -/* Wrapper class for grpc_channel_credentials structs */ -class ChannelCredentials : public Nan::ObjectWrap { - public: - static void Init(v8::Local<v8::Object> exports); - static bool HasInstance(v8::Local<v8::Value> val); - /* Wrap a grpc_channel_credentials struct in a javascript object */ - static v8::Local<v8::Value> WrapStruct(grpc_channel_credentials* credentials); - - /* Returns the grpc_channel_credentials struct that this object wraps */ - grpc_channel_credentials* GetWrappedCredentials(); - - private: - explicit ChannelCredentials(grpc_channel_credentials* credentials); - ~ChannelCredentials(); - - // Prevent copying - ChannelCredentials(const ChannelCredentials&); - ChannelCredentials& operator=(const ChannelCredentials&); - - static NAN_METHOD(New); - static NAN_METHOD(CreateSsl); - static NAN_METHOD(CreateInsecure); - - static NAN_METHOD(Compose); - static Nan::Callback* constructor; - // Used for typechecking instances of this javascript class - static Nan::Persistent<v8::FunctionTemplate> fun_tpl; - - grpc_channel_credentials* wrapped_credentials; -}; - -} // namespace node -} // namespace grpc - -#endif // NET_GRPC_NODE_CHANNEL_CREDENTIALS_H_ diff --git a/src/node/ext/completion_queue.cc b/src/node/ext/completion_queue.cc deleted file mode 100644 index 2b99481d38..0000000000 --- a/src/node/ext/completion_queue.cc +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <grpc/grpc.h> -#include <node.h> -#include <uv.h> -#include <v8.h> - -#include "call.h" -#include "completion_queue.h" - -namespace grpc { -namespace node { - -using v8::Local; -using v8::Object; -using v8::Value; - -grpc_completion_queue* queue; -uv_prepare_t prepare; -int pending_batches; - -void drain_completion_queue(uv_prepare_t* handle) { - Nan::HandleScope scope; - grpc_event event; - (void)handle; - do { - event = grpc_completion_queue_next(queue, gpr_inf_past(GPR_CLOCK_MONOTONIC), - NULL); - - if (event.type == GRPC_OP_COMPLETE) { - const char* error_message; - if (event.success) { - error_message = NULL; - } else { - error_message = "The async function encountered an error"; - } - CompleteTag(event.tag, error_message); - grpc::node::DestroyTag(event.tag); - pending_batches--; - if (pending_batches == 0) { - uv_prepare_stop(&prepare); - } - } - } while (event.type != GRPC_QUEUE_TIMEOUT); -} - -grpc_completion_queue* GetCompletionQueue() { return queue; } - -void CompletionQueueNext() { - if (pending_batches == 0) { - GPR_ASSERT(!uv_is_active((uv_handle_t*)&prepare)); - uv_prepare_start(&prepare, drain_completion_queue); - } - pending_batches++; -} - -void CompletionQueueInit(Local<Object> exports) { - queue = grpc_completion_queue_create_for_next(NULL); - uv_prepare_init(uv_default_loop(), &prepare); - pending_batches = 0; -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/completion_queue.h b/src/node/ext/completion_queue.h deleted file mode 100644 index 2422b2f76c..0000000000 --- a/src/node/ext/completion_queue.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <grpc/grpc.h> -#include <v8.h> - -namespace grpc { -namespace node { - -grpc_completion_queue* GetCompletionQueue(); - -void CompletionQueueNext(); - -void CompletionQueueInit(v8::Local<v8::Object> exports); - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/node_grpc.cc b/src/node/ext/node_grpc.cc deleted file mode 100644 index 1c2d60d5a7..0000000000 --- a/src/node/ext/node_grpc.cc +++ /dev/null @@ -1,311 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <queue> - -#include <nan.h> -#include <node.h> -#include <v8.h> -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "grpc/support/alloc.h" -#include "grpc/support/log.h" -#include "grpc/support/time.h" - -// TODO(murgatroid99): Remove this when the endpoint API becomes public -extern "C" { -#include "src/core/lib/iomgr/pollset_uv.h" -} - -#include "call.h" -#include "call_credentials.h" -#include "channel.h" -#include "channel_credentials.h" -#include "completion_queue.h" -#include "server.h" -#include "server_credentials.h" -#include "slice.h" -#include "timeval.h" - -using grpc::node::CreateSliceFromString; - -using v8::FunctionTemplate; -using v8::Local; -using v8::Number; -using v8::Object; -using v8::String; -using v8::Uint32; -using v8::Value; - -typedef struct log_args { - gpr_log_func_args core_args; - gpr_timespec timestamp; -} log_args; - -typedef struct logger_state { - Nan::Callback* callback; - std::queue<log_args*>* pending_args; - uv_mutex_t mutex; - uv_async_t async; - // Indicates that a logger has been set - bool logger_set; -} logger_state; - -logger_state grpc_logger_state; - -static char* pem_root_certs = NULL; - -void InitOpTypeConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> op_type = Nan::New<Object>(); - Nan::Set(exports, Nan::New("opType").ToLocalChecked(), op_type); - Local<Value> SEND_INITIAL_METADATA( - Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_INITIAL_METADATA)); - Nan::Set(op_type, Nan::New("SEND_INITIAL_METADATA").ToLocalChecked(), - SEND_INITIAL_METADATA); - Local<Value> SEND_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_MESSAGE)); - Nan::Set(op_type, Nan::New("SEND_MESSAGE").ToLocalChecked(), SEND_MESSAGE); - Local<Value> SEND_CLOSE_FROM_CLIENT( - Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_CLOSE_FROM_CLIENT)); - Nan::Set(op_type, Nan::New("SEND_CLOSE_FROM_CLIENT").ToLocalChecked(), - SEND_CLOSE_FROM_CLIENT); - Local<Value> SEND_STATUS_FROM_SERVER( - Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_STATUS_FROM_SERVER)); - Nan::Set(op_type, Nan::New("SEND_STATUS_FROM_SERVER").ToLocalChecked(), - SEND_STATUS_FROM_SERVER); - Local<Value> RECV_INITIAL_METADATA( - Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_INITIAL_METADATA)); - Nan::Set(op_type, Nan::New("RECV_INITIAL_METADATA").ToLocalChecked(), - RECV_INITIAL_METADATA); - Local<Value> RECV_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_MESSAGE)); - Nan::Set(op_type, Nan::New("RECV_MESSAGE").ToLocalChecked(), RECV_MESSAGE); - Local<Value> RECV_STATUS_ON_CLIENT( - Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_STATUS_ON_CLIENT)); - Nan::Set(op_type, Nan::New("RECV_STATUS_ON_CLIENT").ToLocalChecked(), - RECV_STATUS_ON_CLIENT); - Local<Value> RECV_CLOSE_ON_SERVER( - Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_CLOSE_ON_SERVER)); - Nan::Set(op_type, Nan::New("RECV_CLOSE_ON_SERVER").ToLocalChecked(), - RECV_CLOSE_ON_SERVER); -} - -void InitConnectivityStateConstants(Local<Object> exports) { - Nan::HandleScope scope; - Local<Object> channel_state = Nan::New<Object>(); - Nan::Set(exports, Nan::New("connectivityState").ToLocalChecked(), - channel_state); - Local<Value> IDLE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_IDLE)); - Nan::Set(channel_state, Nan::New("IDLE").ToLocalChecked(), IDLE); - Local<Value> CONNECTING(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_CONNECTING)); - Nan::Set(channel_state, Nan::New("CONNECTING").ToLocalChecked(), CONNECTING); - Local<Value> READY(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_READY)); - Nan::Set(channel_state, Nan::New("READY").ToLocalChecked(), READY); - Local<Value> TRANSIENT_FAILURE( - Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_TRANSIENT_FAILURE)); - Nan::Set(channel_state, Nan::New("TRANSIENT_FAILURE").ToLocalChecked(), - TRANSIENT_FAILURE); - Local<Value> FATAL_FAILURE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_SHUTDOWN)); - Nan::Set(channel_state, Nan::New("FATAL_FAILURE").ToLocalChecked(), - FATAL_FAILURE); -} - -NAN_METHOD(MetadataKeyIsLegal) { - if (!info[0]->IsString()) { - return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string"); - } - Local<String> key = Nan::To<String>(info[0]).ToLocalChecked(); - grpc_slice slice = CreateSliceFromString(key); - info.GetReturnValue().Set(static_cast<bool>(grpc_header_key_is_legal(slice))); - grpc_slice_unref(slice); -} - -NAN_METHOD(MetadataNonbinValueIsLegal) { - if (!info[0]->IsString()) { - return Nan::ThrowTypeError( - "metadataNonbinValueIsLegal's argument must be a string"); - } - Local<String> value = Nan::To<String>(info[0]).ToLocalChecked(); - grpc_slice slice = CreateSliceFromString(value); - info.GetReturnValue().Set( - static_cast<bool>(grpc_header_nonbin_value_is_legal(slice))); - grpc_slice_unref(slice); -} - -NAN_METHOD(MetadataKeyIsBinary) { - if (!info[0]->IsString()) { - return Nan::ThrowTypeError( - "metadataKeyIsLegal's argument must be a string"); - } - Local<String> key = Nan::To<String>(info[0]).ToLocalChecked(); - grpc_slice slice = CreateSliceFromString(key); - info.GetReturnValue().Set(static_cast<bool>(grpc_is_binary_header(slice))); - grpc_slice_unref(slice); -} - -static grpc_ssl_roots_override_result get_ssl_roots_override( - char** pem_root_certs_ptr) { - *pem_root_certs_ptr = pem_root_certs; - if (pem_root_certs == NULL) { - return GRPC_SSL_ROOTS_OVERRIDE_FAIL; - } else { - return GRPC_SSL_ROOTS_OVERRIDE_OK; - } -} - -/* This should only be called once, and only before creating any - *ServerCredentials */ -NAN_METHOD(SetDefaultRootsPem) { - if (!info[0]->IsString()) { - return Nan::ThrowTypeError( - "setDefaultRootsPem's argument must be a string"); - } - Nan::Utf8String utf8_roots(info[0]); - size_t length = static_cast<size_t>(utf8_roots.length()); - if (length > 0) { - const char* data = *utf8_roots; - pem_root_certs = (char*)gpr_malloc((length + 1) * sizeof(char)); - memcpy(pem_root_certs, data, length + 1); - } -} - -NAUV_WORK_CB(LogMessagesCallback) { - Nan::HandleScope scope; - std::queue<log_args*> args; - uv_mutex_lock(&grpc_logger_state.mutex); - grpc_logger_state.pending_args->swap(args); - uv_mutex_unlock(&grpc_logger_state.mutex); - /* Call the callback with each log message */ - while (!args.empty()) { - log_args* arg = args.front(); - args.pop(); - Local<Value> file = Nan::New(arg->core_args.file).ToLocalChecked(); - Local<Value> line = Nan::New<Uint32, uint32_t>(arg->core_args.line); - Local<Value> severity = - Nan::New(gpr_log_severity_string(arg->core_args.severity)) - .ToLocalChecked(); - Local<Value> message = Nan::New(arg->core_args.message).ToLocalChecked(); - Local<Value> timestamp = - Nan::New<v8::Date>(grpc::node::TimespecToMilliseconds(arg->timestamp)) - .ToLocalChecked(); - const int argc = 5; - Local<Value> argv[argc] = {file, line, severity, message, timestamp}; - grpc_logger_state.callback->Call(argc, argv); - delete[] arg->core_args.message; - delete arg; - } -} - -void node_log_func(gpr_log_func_args* args) { - // TODO(mlumish): Use the core's log formatter when it becomes available - log_args* args_copy = new log_args; - size_t message_len = strlen(args->message) + 1; - char* message = new char[message_len]; - memcpy(message, args->message, message_len); - memcpy(&args_copy->core_args, args, sizeof(gpr_log_func_args)); - args_copy->core_args.message = message; - args_copy->timestamp = gpr_now(GPR_CLOCK_REALTIME); - - uv_mutex_lock(&grpc_logger_state.mutex); - grpc_logger_state.pending_args->push(args_copy); - uv_mutex_unlock(&grpc_logger_state.mutex); - - uv_async_send(&grpc_logger_state.async); -} - -void init_logger() { - memset(&grpc_logger_state, 0, sizeof(logger_state)); - grpc_logger_state.pending_args = new std::queue<log_args*>(); - uv_mutex_init(&grpc_logger_state.mutex); - uv_async_init(uv_default_loop(), &grpc_logger_state.async, - LogMessagesCallback); - uv_unref((uv_handle_t*)&grpc_logger_state.async); - grpc_logger_state.logger_set = false; - - gpr_log_verbosity_init(); -} - -/* This registers a JavaScript logger for messages from the gRPC core. Because - that handler has to be run in the context of the JavaScript event loop, it - will be run asynchronously. To minimize the problems that could cause for - debugging, we leave core to do its default synchronous logging until a - JavaScript logger is set */ -NAN_METHOD(SetDefaultLoggerCallback) { - if (!info[0]->IsFunction()) { - return Nan::ThrowTypeError( - "setDefaultLoggerCallback's argument must be a function"); - } - if (!grpc_logger_state.logger_set) { - gpr_set_log_function(node_log_func); - grpc_logger_state.logger_set = true; - } - grpc_logger_state.callback = new Nan::Callback(info[0].As<v8::Function>()); -} - -NAN_METHOD(SetLogVerbosity) { - if (!info[0]->IsUint32()) { - return Nan::ThrowTypeError("setLogVerbosity's argument must be a number"); - } - gpr_log_severity severity = - static_cast<gpr_log_severity>(Nan::To<uint32_t>(info[0]).FromJust()); - gpr_set_log_verbosity(severity); -} - -void init(Local<Object> exports) { - Nan::HandleScope scope; - grpc_init(); - grpc_set_ssl_roots_override_callback(get_ssl_roots_override); - init_logger(); - - InitOpTypeConstants(exports); - InitConnectivityStateConstants(exports); - - grpc_pollset_work_run_loop = 0; - - grpc::node::Call::Init(exports); - grpc::node::CallCredentials::Init(exports); - grpc::node::Channel::Init(exports); - grpc::node::ChannelCredentials::Init(exports); - grpc::node::Server::Init(exports); - grpc::node::ServerCredentials::Init(exports); - - grpc::node::CompletionQueueInit(exports); - - // Attach a few utility functions directly to the module - Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsLegal)) - .ToLocalChecked()); - Nan::Set( - exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataNonbinValueIsLegal)) - .ToLocalChecked()); - Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsBinary)) - .ToLocalChecked()); - Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultRootsPem)) - .ToLocalChecked()); - Nan::Set( - exports, Nan::New("setDefaultLoggerCallback").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultLoggerCallback)) - .ToLocalChecked()); - Nan::Set(exports, Nan::New("setLogVerbosity").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(SetLogVerbosity)) - .ToLocalChecked()); -} - -NODE_MODULE(grpc_node, init) diff --git a/src/node/ext/server.cc b/src/node/ext/server.cc deleted file mode 100644 index 6bd6f09811..0000000000 --- a/src/node/ext/server.cc +++ /dev/null @@ -1,342 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <memory> - -#include "server.h" - -#include <nan.h> -#include <node.h> - -#include <vector> -#include "call.h" -#include "completion_queue.h" -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" -#include "grpc/support/log.h" -#include "server_credentials.h" -#include "slice.h" -#include "timeval.h" - -namespace grpc { -namespace node { - -using Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using std::unique_ptr; -using v8::Array; -using v8::Boolean; -using v8::Date; -using v8::Exception; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Local; -using v8::Number; -using v8::Object; -using v8::String; -using v8::Value; - -Nan::Callback* Server::constructor; -Persistent<FunctionTemplate> Server::fun_tpl; - -static Callback* shutdown_callback = NULL; - -class ServerShutdownOp : public Op { - public: - ServerShutdownOp(grpc_server* server) : server(server) {} - - ~ServerShutdownOp() {} - - Local<Value> GetNodeValue() const { return Nan::Null(); } - - bool ParseOp(Local<Value> value, grpc_op* out) { return true; } - bool IsFinalOp() { return false; } - void OnComplete(bool success) { - /* Because cancel_all_calls was called, we assume that shutdown_and_notify - completes successfully */ - grpc_server_destroy(server); - } - - grpc_server* server; - - protected: - std::string GetTypeString() const { return "shutdown"; } -}; - -class NewCallOp : public Op { - public: - NewCallOp() { - call = NULL; - grpc_call_details_init(&details); - grpc_metadata_array_init(&request_metadata); - } - - ~NewCallOp() { - grpc_call_details_destroy(&details); - grpc_metadata_array_destroy(&request_metadata); - } - - Local<Value> GetNodeValue() const { - Nan::EscapableHandleScope scope; - if (call == NULL) { - return scope.Escape(Nan::Null()); - } - Local<Object> obj = Nan::New<Object>(); - Nan::Set(obj, Nan::New("call").ToLocalChecked(), Call::WrapStruct(call)); - // TODO(murgatroid99): Use zero-copy string construction instead - Nan::Set(obj, Nan::New("method").ToLocalChecked(), - CopyStringFromSlice(details.method)); - Nan::Set(obj, Nan::New("host").ToLocalChecked(), - CopyStringFromSlice(details.host)); - Nan::Set(obj, Nan::New("deadline").ToLocalChecked(), - Nan::New<Date>(TimespecToMilliseconds(details.deadline)) - .ToLocalChecked()); - Nan::Set(obj, Nan::New("metadata").ToLocalChecked(), - ParseMetadata(&request_metadata)); - return scope.Escape(obj); - } - - bool ParseOp(Local<Value> value, grpc_op* out) { return true; } - bool IsFinalOp() { return false; } - void OnComplete(bool success) {} - - grpc_call* call; - grpc_call_details details; - grpc_metadata_array request_metadata; - - protected: - std::string GetTypeString() const { return "new_call"; } -}; - -class TryShutdownOp : public Op { - public: - TryShutdownOp(Server* server, Local<Value> server_value) : server(server) { - server_persist.Reset(server_value); - } - Local<Value> GetNodeValue() const { - EscapableHandleScope scope; - return scope.Escape(Nan::New(server_persist)); - } - bool ParseOp(Local<Value> value, grpc_op* out) { return true; } - bool IsFinalOp() { return false; } - void OnComplete(bool success) { - if (success) { - server->DestroyWrappedServer(); - } - } - - protected: - std::string GetTypeString() const { return "try_shutdown"; } - - private: - Server* server; - Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> - server_persist; -}; - -Server::Server(grpc_server* server) : wrapped_server(server) {} - -Server::~Server() { this->ShutdownServer(); } - -void Server::Init(Local<Object> exports) { - HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("Server").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Nan::SetPrototypeMethod(tpl, "requestCall", RequestCall); - Nan::SetPrototypeMethod(tpl, "addHttp2Port", AddHttp2Port); - Nan::SetPrototypeMethod(tpl, "start", Start); - Nan::SetPrototypeMethod(tpl, "tryShutdown", TryShutdown); - Nan::SetPrototypeMethod(tpl, "forceShutdown", ForceShutdown); - fun_tpl.Reset(tpl); - Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked(); - Nan::Set(exports, Nan::New("Server").ToLocalChecked(), ctr); - constructor = new Callback(ctr); -} - -bool Server::HasInstance(Local<Value> val) { - HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -void Server::DestroyWrappedServer() { - if (this->wrapped_server != NULL) { - grpc_server_destroy(this->wrapped_server); - this->wrapped_server = NULL; - } -} - -NAN_METHOD(ServerShutdownCallback) { - if (!info[0]->IsNull()) { - return Nan::ThrowError("forceShutdown failed somehow"); - } -} - -void Server::ShutdownServer() { - Nan::HandleScope scope; - if (this->wrapped_server != NULL) { - if (shutdown_callback == NULL) { - Local<FunctionTemplate> callback_tpl = - Nan::New<FunctionTemplate>(ServerShutdownCallback); - shutdown_callback = - new Callback(Nan::GetFunction(callback_tpl).ToLocalChecked()); - } - - ServerShutdownOp* op = new ServerShutdownOp(this->wrapped_server); - unique_ptr<OpVec> ops(new OpVec()); - ops->push_back(unique_ptr<Op>(op)); - - grpc_server_shutdown_and_notify( - this->wrapped_server, GetCompletionQueue(), - new struct tag(new Callback(**shutdown_callback), ops.release(), NULL, - Nan::Null())); - grpc_server_cancel_all_calls(this->wrapped_server); - CompletionQueueNext(); - this->wrapped_server = NULL; - } -} - -NAN_METHOD(Server::New) { - /* If this is not a constructor call, make a constructor call and return - the result */ - if (!info.IsConstructCall()) { - const int argc = 1; - Local<Value> argv[argc] = {info[0]}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - // There's probably a pending exception - return; - } else { - info.GetReturnValue().Set(maybe_instance.ToLocalChecked()); - return; - } - } - grpc_server* wrapped_server; - grpc_completion_queue* queue = GetCompletionQueue(); - grpc_channel_args* channel_args; - if (!ParseChannelArgs(info[0], &channel_args)) { - DeallocateChannelArgs(channel_args); - return Nan::ThrowTypeError( - "Server options must be an object with " - "string keys and integer or string values"); - } - wrapped_server = grpc_server_create(channel_args, NULL); - DeallocateChannelArgs(channel_args); - grpc_server_register_completion_queue(wrapped_server, queue, NULL); - Server* server = new Server(wrapped_server); - server->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); -} - -NAN_METHOD(Server::RequestCall) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("requestCall can only be called on a Server"); - } - Server* server = ObjectWrap::Unwrap<Server>(info.This()); - NewCallOp* op = new NewCallOp(); - unique_ptr<OpVec> ops(new OpVec()); - ops->push_back(unique_ptr<Op>(op)); - grpc_call_error error = grpc_server_request_call( - server->wrapped_server, &op->call, &op->details, &op->request_metadata, - GetCompletionQueue(), GetCompletionQueue(), - new struct tag(new Callback(info[0].As<Function>()), ops.release(), NULL, - Nan::Null())); - if (error != GRPC_CALL_OK) { - return Nan::ThrowError(nanErrorWithCode("requestCall failed", error)); - } - CompletionQueueNext(); -} - -NAN_METHOD(Server::AddHttp2Port) { - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("addHttp2Port can only be called on a Server"); - } - if (!info[0]->IsString()) { - return Nan::ThrowTypeError( - "addHttp2Port's first argument must be a String"); - } - if (!ServerCredentials::HasInstance(info[1])) { - return Nan::ThrowTypeError( - "addHttp2Port's second argument must be ServerCredentials"); - } - Server* server = ObjectWrap::Unwrap<Server>(info.This()); - ServerCredentials* creds_object = ObjectWrap::Unwrap<ServerCredentials>( - Nan::To<Object>(info[1]).ToLocalChecked()); - grpc_server_credentials* creds = creds_object->GetWrappedServerCredentials(); - int port; - if (creds == NULL) { - port = grpc_server_add_insecure_http2_port(server->wrapped_server, - *Utf8String(info[0])); - } else { - port = grpc_server_add_secure_http2_port(server->wrapped_server, - *Utf8String(info[0]), creds); - } - info.GetReturnValue().Set(Nan::New<Number>(port)); -} - -NAN_METHOD(Server::Start) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("start can only be called on a Server"); - } - Server* server = ObjectWrap::Unwrap<Server>(info.This()); - grpc_server_start(server->wrapped_server); -} - -NAN_METHOD(Server::TryShutdown) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("tryShutdown can only be called on a Server"); - } - Server* server = ObjectWrap::Unwrap<Server>(info.This()); - if (server->wrapped_server == NULL) { - // Server is already shut down. Call callback immediately. - Nan::Callback callback(info[0].As<Function>()); - callback.Call(0, {}); - return; - } - TryShutdownOp* op = new TryShutdownOp(server, info.This()); - unique_ptr<OpVec> ops(new OpVec()); - ops->push_back(unique_ptr<Op>(op)); - grpc_server_shutdown_and_notify( - server->wrapped_server, GetCompletionQueue(), - new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(), - NULL, Nan::Null())); - CompletionQueueNext(); -} - -NAN_METHOD(Server::ForceShutdown) { - Nan::HandleScope scope; - if (!HasInstance(info.This())) { - return Nan::ThrowTypeError("forceShutdown can only be called on a Server"); - } - Server* server = ObjectWrap::Unwrap<Server>(info.This()); - server->ShutdownServer(); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/server.h b/src/node/ext/server.h deleted file mode 100644 index 2a0bf19ba8..0000000000 --- a/src/node/ext/server.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_SERVER_H_ -#define NET_GRPC_NODE_SERVER_H_ - -#include <nan.h> -#include <node.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 Nan::ObjectWrap { - public: - /* Initializes the Server class and exposes the constructor and - wrapper methods to JavaScript */ - static void Init(v8::Local<v8::Object> exports); - /* Tests whether the given value was constructed by this class's - JavaScript constructor */ - static bool HasInstance(v8::Local<v8::Value> val); - - void DestroyWrappedServer(); - - private: - explicit Server(grpc_server* server); - ~Server(); - - // Prevent copying - Server(const Server&); - Server& operator=(const Server&); - - void ShutdownServer(); - - static NAN_METHOD(New); - static NAN_METHOD(RequestCall); - static NAN_METHOD(AddHttp2Port); - static NAN_METHOD(Start); - static NAN_METHOD(TryShutdown); - static NAN_METHOD(ForceShutdown); - static Nan::Callback* constructor; - static Nan::Persistent<v8::FunctionTemplate> fun_tpl; - - grpc_server* wrapped_server; - grpc_completion_queue* shutdown_queue; -}; - -} // 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 deleted file mode 100644 index 0c5e7749c5..0000000000 --- a/src/node/ext/server_credentials.cc +++ /dev/null @@ -1,190 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#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 Nan::Callback; -using Nan::EscapableHandleScope; -using Nan::HandleScope; -using Nan::Maybe; -using Nan::MaybeLocal; -using Nan::ObjectWrap; -using Nan::Persistent; -using Nan::Utf8String; - -using v8::Array; -using v8::Exception; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Integer; -using v8::Local; -using v8::Object; -using v8::ObjectTemplate; -using v8::String; -using v8::Value; - -Nan::Callback* ServerCredentials::constructor; -Persistent<FunctionTemplate> ServerCredentials::fun_tpl; - -ServerCredentials::ServerCredentials(grpc_server_credentials* credentials) - : wrapped_credentials(credentials) {} - -ServerCredentials::~ServerCredentials() { - grpc_server_credentials_release(wrapped_credentials); -} - -void ServerCredentials::Init(Local<Object> exports) { - Nan::HandleScope scope; - Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New); - tpl->SetClassName(Nan::New("ServerCredentials").ToLocalChecked()); - tpl->InstanceTemplate()->SetInternalFieldCount(1); - Local<Function> ctr = tpl->GetFunction(); - Nan::Set( - ctr, Nan::New("createSsl").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked()); - Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(), - Nan::GetFunction(Nan::New<FunctionTemplate>(CreateInsecure)) - .ToLocalChecked()); - fun_tpl.Reset(tpl); - constructor = new Nan::Callback(ctr); - Nan::Set(exports, Nan::New("ServerCredentials").ToLocalChecked(), ctr); -} - -bool ServerCredentials::HasInstance(Local<Value> val) { - Nan::HandleScope scope; - return Nan::New(fun_tpl)->HasInstance(val); -} - -Local<Value> ServerCredentials::WrapStruct( - grpc_server_credentials* credentials) { - Nan::EscapableHandleScope scope; - const int argc = 1; - Local<Value> argv[argc] = { - Nan::New<External>(reinterpret_cast<void*>(credentials))}; - MaybeLocal<Object> maybe_instance = - Nan::NewInstance(constructor->GetFunction(), argc, argv); - if (maybe_instance.IsEmpty()) { - return scope.Escape(Nan::Null()); - } else { - return scope.Escape(maybe_instance.ToLocalChecked()); - } -} - -grpc_server_credentials* ServerCredentials::GetWrappedServerCredentials() { - return wrapped_credentials; -} - -NAN_METHOD(ServerCredentials::New) { - if (info.IsConstructCall()) { - if (!info[0]->IsExternal()) { - return Nan::ThrowTypeError( - "ServerCredentials can only be created with the provided functions"); - } - Local<External> ext = info[0].As<External>(); - grpc_server_credentials* creds_value = - reinterpret_cast<grpc_server_credentials*>(ext->Value()); - ServerCredentials* credentials = new ServerCredentials(creds_value); - credentials->Wrap(info.This()); - info.GetReturnValue().Set(info.This()); - } else { - // This should never be called directly - return Nan::ThrowTypeError( - "ServerCredentials can only be created with the provided functions"); - } -} - -NAN_METHOD(ServerCredentials::CreateSsl) { - Nan::HandleScope scope; - char* root_certs = NULL; - if (::node::Buffer::HasInstance(info[0])) { - root_certs = ::node::Buffer::Data(info[0]); - } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) { - return Nan::ThrowTypeError( - "createSSl's first argument must be a Buffer if provided"); - } - if (!info[1]->IsArray()) { - return Nan::ThrowTypeError( - "createSsl's second argument must be a list of objects"); - } - - // Default to not requesting the client certificate - grpc_ssl_client_certificate_request_type client_certificate_request = - GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; - if (info[2]->IsBoolean()) { - client_certificate_request = - Nan::To<bool>(info[2]).FromJust() - ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY - : GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; - } else if (!(info[2]->IsUndefined() || info[2]->IsNull())) { - return Nan::ThrowTypeError( - "createSsl's third argument must be a boolean if provided"); - } - Local<Array> pair_list = Local<Array>::Cast(info[1]); - uint32_t key_cert_pair_count = pair_list->Length(); - grpc_ssl_pem_key_cert_pair* key_cert_pairs = - new grpc_ssl_pem_key_cert_pair[key_cert_pair_count]; - - Local<String> key_key = Nan::New("private_key").ToLocalChecked(); - Local<String> cert_key = Nan::New("cert_chain").ToLocalChecked(); - - for (uint32_t i = 0; i < key_cert_pair_count; i++) { - Local<Value> pair_val = Nan::Get(pair_list, i).ToLocalChecked(); - if (!pair_val->IsObject()) { - delete[] key_cert_pairs; - return Nan::ThrowTypeError("Key/cert pairs must be objects"); - } - Local<Object> pair_obj = Nan::To<Object>(pair_val).ToLocalChecked(); - Local<Value> maybe_key = Nan::Get(pair_obj, key_key).ToLocalChecked(); - Local<Value> maybe_cert = Nan::Get(pair_obj, cert_key).ToLocalChecked(); - if (!::node::Buffer::HasInstance(maybe_key)) { - delete[] key_cert_pairs; - return Nan::ThrowTypeError("private_key must be a Buffer"); - } - if (!::node::Buffer::HasInstance(maybe_cert)) { - delete[] key_cert_pairs; - return Nan::ThrowTypeError("cert_chain must be a Buffer"); - } - key_cert_pairs[i].private_key = ::node::Buffer::Data(maybe_key); - key_cert_pairs[i].cert_chain = ::node::Buffer::Data(maybe_cert); - } - grpc_server_credentials* creds = grpc_ssl_server_credentials_create_ex( - root_certs, key_cert_pairs, key_cert_pair_count, - client_certificate_request, NULL); - delete[] key_cert_pairs; - if (creds == NULL) { - info.GetReturnValue().SetNull(); - } else { - info.GetReturnValue().Set(WrapStruct(creds)); - } -} - -NAN_METHOD(ServerCredentials::CreateInsecure) { - info.GetReturnValue().Set(WrapStruct(NULL)); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/server_credentials.h b/src/node/ext/server_credentials.h deleted file mode 100644 index d514e4dea9..0000000000 --- a/src/node/ext/server_credentials.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef NET_GRPC_NODE_SERVER_CREDENTIALS_H_ -#define NET_GRPC_NODE_SERVER_CREDENTIALS_H_ - -#include <nan.h> -#include <node.h> -#include "grpc/grpc.h" -#include "grpc/grpc_security.h" - -namespace grpc { -namespace node { - -/* Wrapper class for grpc_server_credentials structs */ -class ServerCredentials : public Nan::ObjectWrap { - public: - static void Init(v8::Local<v8::Object> exports); - static bool HasInstance(v8::Local<v8::Value> val); - /* Wrap a grpc_server_credentials struct in a javascript object */ - static v8::Local<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(CreateInsecure); - static Nan::Callback* constructor; - // Used for typechecking instances of this javascript class - static Nan::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/slice.cc b/src/node/ext/slice.cc deleted file mode 100644 index 0ba6a54a59..0000000000 --- a/src/node/ext/slice.cc +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <grpc/slice.h> -#include <grpc/support/alloc.h> -#include <nan.h> -#include <node.h> - -#include "slice.h" - -namespace grpc { -namespace node { - -using Nan::Persistent; - -using v8::Local; -using v8::String; -using v8::Value; - -namespace { -void SliceFreeCallback(char* data, void* hint) { - grpc_slice* slice = reinterpret_cast<grpc_slice*>(hint); - grpc_slice_unref(*slice); - delete slice; -} - -void string_destroy_func(void* user_data) { - delete reinterpret_cast<Nan::Utf8String*>(user_data); -} - -void buffer_destroy_func(void* user_data) { - delete reinterpret_cast<PersistentValue*>(user_data); -} -} // namespace - -grpc_slice CreateSliceFromString(const Local<String> source) { - Nan::HandleScope scope; - Nan::Utf8String* utf8_value = new Nan::Utf8String(source); - return grpc_slice_new_with_user_data(**utf8_value, source->Length(), - string_destroy_func, utf8_value); -} - -grpc_slice CreateSliceFromBuffer(const Local<Value> source) { - // Prerequisite: ::node::Buffer::HasInstance(source) - Nan::HandleScope scope; - return grpc_slice_new_with_user_data( - ::node::Buffer::Data(source), ::node::Buffer::Length(source), - buffer_destroy_func, new PersistentValue(source)); -} -Local<String> CopyStringFromSlice(const grpc_slice slice) { - Nan::EscapableHandleScope scope; - if (GRPC_SLICE_LENGTH(slice) == 0) { - return scope.Escape(Nan::EmptyString()); - } - return scope.Escape( - Nan::New<String>(const_cast<char*>(reinterpret_cast<const char*>( - GRPC_SLICE_START_PTR(slice))), - GRPC_SLICE_LENGTH(slice)) - .ToLocalChecked()); -} - -Local<Value> CreateBufferFromSlice(const grpc_slice slice) { - Nan::EscapableHandleScope scope; - grpc_slice* slice_ptr = new grpc_slice; - *slice_ptr = grpc_slice_ref(slice); - return scope.Escape( - Nan::NewBuffer( - const_cast<char*>( - reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice_ptr))), - GRPC_SLICE_LENGTH(*slice_ptr), SliceFreeCallback, slice_ptr) - .ToLocalChecked()); -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/slice.h b/src/node/ext/slice.h deleted file mode 100644 index 0a652c5755..0000000000 --- a/src/node/ext/slice.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright 2016 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <grpc/slice.h> -#include <nan.h> -#include <node.h> - -namespace grpc { -namespace node { - -typedef Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>> - PersistentValue; - -grpc_slice CreateSliceFromString(const v8::Local<v8::String> source); - -grpc_slice CreateSliceFromBuffer(const v8::Local<v8::Value> source); - -v8::Local<v8::String> CopyStringFromSlice(const grpc_slice slice); - -v8::Local<v8::Value> CreateBufferFromSlice(const grpc_slice slice); - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/timeval.cc b/src/node/ext/timeval.cc deleted file mode 100644 index 6142584759..0000000000 --- a/src/node/ext/timeval.cc +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include <cstdint> -#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(GPR_CLOCK_REALTIME); - } else if (millis == -std::numeric_limits<double>::infinity()) { - return gpr_inf_past(GPR_CLOCK_REALTIME); - } else { - return gpr_time_from_micros(static_cast<int64_t>(millis * 1000), - GPR_CLOCK_REALTIME); - } -} - -double TimespecToMilliseconds(gpr_timespec timespec) { - timespec = gpr_convert_clock_type(timespec, GPR_CLOCK_REALTIME); - if (gpr_time_cmp(timespec, gpr_inf_future(GPR_CLOCK_REALTIME)) == 0) { - return std::numeric_limits<double>::infinity(); - } else if (gpr_time_cmp(timespec, gpr_inf_past(GPR_CLOCK_REALTIME)) == 0) { - return -std::numeric_limits<double>::infinity(); - } else { - return (static_cast<double>(timespec.tv_sec) * 1000 + - static_cast<double>(timespec.tv_nsec) / 1000000); - } -} - -} // namespace node -} // namespace grpc diff --git a/src/node/ext/timeval.h b/src/node/ext/timeval.h deleted file mode 100644 index 17d7f1642b..0000000000 --- a/src/node/ext/timeval.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * - * Copyright 2015 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#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_ |