Merge github.com:grpc/grpc into cpparena

This commit is contained in:
Craig Tiller 2017-04-12 15:16:35 -07:00
commit 857a8fd02b
7 changed files with 156 additions and 156 deletions

View File

@ -31,23 +31,23 @@
* *
*/ */
#include <map>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <map>
#include <node.h> #include <node.h>
#include "grpc/support/log.h"
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"
#include "grpc/support/alloc.h"
#include "grpc/support/time.h"
#include "byte_buffer.h" #include "byte_buffer.h"
#include "call.h" #include "call.h"
#include "call_credentials.h"
#include "channel.h" #include "channel.h"
#include "completion_queue.h" #include "completion_queue.h"
#include "completion_queue_async_worker.h" #include "completion_queue_async_worker.h"
#include "call_credentials.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 "slice.h"
#include "timeval.h" #include "timeval.h"
@ -99,11 +99,10 @@ Local<Value> nanErrorWithCode(const char *msg, grpc_call_error code) {
bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) { bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
HandleScope scope; HandleScope scope;
grpc_metadata_array_init(array);
Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked(); Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked();
for (unsigned int i = 0; i < keys->Length(); i++) { for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key = Nan::To<String>( Local<String> current_key =
Nan::Get(keys, i).ToLocalChecked()).ToLocalChecked(); Nan::To<String>(Nan::Get(keys, i).ToLocalChecked()).ToLocalChecked();
Local<Value> value_array = Nan::Get(metadata, current_key).ToLocalChecked(); Local<Value> value_array = Nan::Get(metadata, current_key).ToLocalChecked();
if (!value_array->IsArray()) { if (!value_array->IsArray()) {
return false; return false;
@ -111,18 +110,20 @@ bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
array->capacity += Local<Array>::Cast(value_array)->Length(); array->capacity += Local<Array>::Cast(value_array)->Length();
} }
array->metadata = reinterpret_cast<grpc_metadata *>( array->metadata = reinterpret_cast<grpc_metadata *>(
gpr_malloc(array->capacity * sizeof(grpc_metadata))); gpr_zalloc(array->capacity * sizeof(grpc_metadata)));
for (unsigned int i = 0; i < keys->Length(); i++) { for (unsigned int i = 0; i < keys->Length(); i++) {
Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked()); Local<String> current_key(Nan::To<String>(keys->Get(i)).ToLocalChecked());
Local<Array> values = Local<Array>::Cast( Local<Array> values =
Nan::Get(metadata, current_key).ToLocalChecked()); Local<Array>::Cast(Nan::Get(metadata, current_key).ToLocalChecked());
grpc_slice key_slice = grpc_slice_intern(CreateSliceFromString(current_key)); 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++) { for (unsigned int j = 0; j < values->Length(); j++) {
Local<Value> value = Nan::Get(values, j).ToLocalChecked(); Local<Value> value = Nan::Get(values, j).ToLocalChecked();
grpc_metadata *current = &array->metadata[array->count]; grpc_metadata *current = &array->metadata[array->count];
current->key = key_slice; current->key = key_intern_slice;
// Only allow binary headers for "-bin" keys // Only allow binary headers for "-bin" keys
if (grpc_is_binary_header(key_slice)) { if (grpc_is_binary_header(key_intern_slice)) {
if (::node::Buffer::HasInstance(value)) { if (::node::Buffer::HasInstance(value)) {
current->value = CreateSliceFromBuffer(value); current->value = CreateSliceFromBuffer(value);
} else { } else {
@ -142,6 +143,14 @@ bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array) {
return true; 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) { Local<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
EscapableHandleScope scope; EscapableHandleScope scope;
grpc_metadata *metadata_elements = metadata_array->metadata; grpc_metadata *metadata_elements = metadata_array->metadata;
@ -174,11 +183,12 @@ Local<Value> Op::GetOpType() const {
return scope.Escape(Nan::New(GetTypeString()).ToLocalChecked()); return scope.Escape(Nan::New(GetTypeString()).ToLocalChecked());
} }
Op::~Op() { Op::~Op() {}
}
class SendMetadataOp : public Op { class SendMetadataOp : public Op {
public: public:
SendMetadataOp() { grpc_metadata_array_init(&send_metadata); }
~SendMetadataOp() { DestroyMetadataArray(&send_metadata); }
Local<Value> GetNodeValue() const { Local<Value> GetNodeValue() const {
EscapableHandleScope scope; EscapableHandleScope scope;
return scope.Escape(Nan::True()); return scope.Escape(Nan::True());
@ -187,33 +197,29 @@ class SendMetadataOp : public Op {
if (!value->IsObject()) { if (!value->IsObject()) {
return false; return false;
} }
grpc_metadata_array array;
MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value); MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value);
if (maybe_metadata.IsEmpty()) { if (maybe_metadata.IsEmpty()) {
return false; return false;
} }
if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(), if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(), &send_metadata)) {
&array)) {
return false; return false;
} }
out->data.send_initial_metadata.count = array.count; out->data.send_initial_metadata.count = send_metadata.count;
out->data.send_initial_metadata.metadata = array.metadata; out->data.send_initial_metadata.metadata = send_metadata.metadata;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return false; }
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "send_metadata"; }
return "send_metadata";
} private:
grpc_metadata_array send_metadata;
}; };
class SendMessageOp : public Op { class SendMessageOp : public Op {
public: public:
SendMessageOp() { SendMessageOp() { send_message = NULL; }
send_message = NULL;
}
~SendMessageOp() { ~SendMessageOp() {
if (send_message != NULL) { if (send_message != NULL) {
grpc_byte_buffer_destroy(send_message); grpc_byte_buffer_destroy(send_message);
@ -228,8 +234,8 @@ class SendMessageOp : public Op {
return false; return false;
} }
Local<Object> object_value = Nan::To<Object>(value).ToLocalChecked(); Local<Object> object_value = Nan::To<Object>(value).ToLocalChecked();
MaybeLocal<Value> maybe_flag_value = Nan::Get( MaybeLocal<Value> maybe_flag_value =
object_value, Nan::New("grpcWriteFlags").ToLocalChecked()); Nan::Get(object_value, Nan::New("grpcWriteFlags").ToLocalChecked());
if (!maybe_flag_value.IsEmpty()) { if (!maybe_flag_value.IsEmpty()) {
Local<Value> flag_value = maybe_flag_value.ToLocalChecked(); Local<Value> flag_value = maybe_flag_value.ToLocalChecked();
if (flag_value->IsUint32()) { if (flag_value->IsUint32()) {
@ -241,13 +247,11 @@ class SendMessageOp : public Op {
out->data.send_message.send_message = send_message; out->data.send_message.send_message = send_message;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return false; }
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "send_message"; }
return "send_message";
}
private: private:
grpc_byte_buffer *send_message; grpc_byte_buffer *send_message;
}; };
@ -258,22 +262,19 @@ class SendClientCloseOp : public Op {
EscapableHandleScope scope; EscapableHandleScope scope;
return scope.Escape(Nan::True()); return scope.Escape(Nan::True());
} }
bool ParseOp(Local<Value> value, grpc_op *out) { bool ParseOp(Local<Value> value, grpc_op *out) { return true; }
return true; bool IsFinalOp() { return false; }
}
bool IsFinalOp() {
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "client_close"; }
return "client_close";
}
}; };
class SendServerStatusOp : public Op { class SendServerStatusOp : public Op {
public: public:
SendServerStatusOp() { grpc_metadata_array_init(&status_metadata); }
~SendServerStatusOp() { ~SendServerStatusOp() {
grpc_slice_unref(details); grpc_slice_unref(details);
DestroyMetadataArray(&status_metadata);
} }
Local<Value> GetNodeValue() const { Local<Value> GetNodeValue() const {
EscapableHandleScope scope; EscapableHandleScope scope;
@ -284,18 +285,18 @@ class SendServerStatusOp : public Op {
return false; return false;
} }
Local<Object> server_status = Nan::To<Object>(value).ToLocalChecked(); Local<Object> server_status = Nan::To<Object>(value).ToLocalChecked();
MaybeLocal<Value> maybe_metadata = Nan::Get( MaybeLocal<Value> maybe_metadata =
server_status, Nan::New("metadata").ToLocalChecked()); Nan::Get(server_status, Nan::New("metadata").ToLocalChecked());
if (maybe_metadata.IsEmpty()) { if (maybe_metadata.IsEmpty()) {
return false; return false;
} }
if (!maybe_metadata.ToLocalChecked()->IsObject()) { if (!maybe_metadata.ToLocalChecked()->IsObject()) {
return false; return false;
} }
Local<Object> metadata = Nan::To<Object>( Local<Object> metadata =
maybe_metadata.ToLocalChecked()).ToLocalChecked(); Nan::To<Object>(maybe_metadata.ToLocalChecked()).ToLocalChecked();
MaybeLocal<Value> maybe_code = Nan::Get(server_status, MaybeLocal<Value> maybe_code =
Nan::New("code").ToLocalChecked()); Nan::Get(server_status, Nan::New("code").ToLocalChecked());
if (maybe_code.IsEmpty()) { if (maybe_code.IsEmpty()) {
return false; return false;
} }
@ -303,49 +304,44 @@ class SendServerStatusOp : public Op {
return false; return false;
} }
uint32_t code = Nan::To<uint32_t>(maybe_code.ToLocalChecked()).FromJust(); uint32_t code = Nan::To<uint32_t>(maybe_code.ToLocalChecked()).FromJust();
MaybeLocal<Value> maybe_details = Nan::Get( MaybeLocal<Value> maybe_details =
server_status, Nan::New("details").ToLocalChecked()); Nan::Get(server_status, Nan::New("details").ToLocalChecked());
if (maybe_details.IsEmpty()) { if (maybe_details.IsEmpty()) {
return false; return false;
} }
if (!maybe_details.ToLocalChecked()->IsString()) { if (!maybe_details.ToLocalChecked()->IsString()) {
return false; return false;
} }
Local<String> details = Nan::To<String>( Local<String> details =
maybe_details.ToLocalChecked()).ToLocalChecked(); Nan::To<String>(maybe_details.ToLocalChecked()).ToLocalChecked();
grpc_metadata_array array; if (!CreateMetadataArray(metadata, &status_metadata)) {
if (!CreateMetadataArray(metadata, &array)) {
return false; return false;
} }
out->data.send_status_from_server.trailing_metadata_count = array.count; out->data.send_status_from_server.trailing_metadata_count =
out->data.send_status_from_server.trailing_metadata = array.metadata; status_metadata.count;
out->data.send_status_from_server.trailing_metadata =
status_metadata.metadata;
out->data.send_status_from_server.status = out->data.send_status_from_server.status =
static_cast<grpc_status_code>(code); static_cast<grpc_status_code>(code);
this->details = CreateSliceFromString(details); this->details = CreateSliceFromString(details);
out->data.send_status_from_server.status_details = &this->details; out->data.send_status_from_server.status_details = &this->details;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return true; }
return true;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "send_status"; }
return "send_status";
}
private: private:
grpc_slice details; grpc_slice details;
grpc_metadata_array status_metadata;
}; };
class GetMetadataOp : public Op { class GetMetadataOp : public Op {
public: public:
GetMetadataOp() { GetMetadataOp() { grpc_metadata_array_init(&recv_metadata); }
grpc_metadata_array_init(&recv_metadata);
}
~GetMetadataOp() { ~GetMetadataOp() { grpc_metadata_array_destroy(&recv_metadata); }
grpc_metadata_array_destroy(&recv_metadata);
}
Local<Value> GetNodeValue() const { Local<Value> GetNodeValue() const {
EscapableHandleScope scope; EscapableHandleScope scope;
@ -356,14 +352,10 @@ class GetMetadataOp : public Op {
out->data.recv_initial_metadata.recv_initial_metadata = &recv_metadata; out->data.recv_initial_metadata.recv_initial_metadata = &recv_metadata;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return false; }
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "metadata"; }
return "metadata";
}
private: private:
grpc_metadata_array recv_metadata; grpc_metadata_array recv_metadata;
@ -371,9 +363,7 @@ class GetMetadataOp : public Op {
class ReadMessageOp : public Op { class ReadMessageOp : public Op {
public: public:
ReadMessageOp() { ReadMessageOp() { recv_message = NULL; }
recv_message = NULL;
}
~ReadMessageOp() { ~ReadMessageOp() {
if (recv_message != NULL) { if (recv_message != NULL) {
grpc_byte_buffer_destroy(recv_message); grpc_byte_buffer_destroy(recv_message);
@ -388,14 +378,10 @@ class ReadMessageOp : public Op {
out->data.recv_message.recv_message = &recv_message; out->data.recv_message.recv_message = &recv_message;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return false; }
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "read"; }
return "read";
}
private: private:
grpc_byte_buffer *recv_message; grpc_byte_buffer *recv_message;
@ -403,13 +389,9 @@ class ReadMessageOp : public Op {
class ClientStatusOp : public Op { class ClientStatusOp : public Op {
public: public:
ClientStatusOp() { ClientStatusOp() { grpc_metadata_array_init(&metadata_array); }
grpc_metadata_array_init(&metadata_array);
}
~ClientStatusOp() { ~ClientStatusOp() { grpc_metadata_array_destroy(&metadata_array); }
grpc_metadata_array_destroy(&metadata_array);
}
bool ParseOp(Local<Value> value, grpc_op *out) { bool ParseOp(Local<Value> value, grpc_op *out) {
out->data.recv_status_on_client.trailing_metadata = &metadata_array; out->data.recv_status_on_client.trailing_metadata = &metadata_array;
@ -429,13 +411,11 @@ class ClientStatusOp : public Op {
ParseMetadata(&metadata_array)); ParseMetadata(&metadata_array));
return scope.Escape(status_obj); return scope.Escape(status_obj);
} }
bool IsFinalOp() { bool IsFinalOp() { return true; }
return true;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "status"; }
return "status";
}
private: private:
grpc_metadata_array metadata_array; grpc_metadata_array metadata_array;
grpc_status_code status; grpc_status_code status;
@ -453,21 +433,19 @@ class ServerCloseResponseOp : public Op {
out->data.recv_close_on_server.cancelled = &cancelled; out->data.recv_close_on_server.cancelled = &cancelled;
return true; return true;
} }
bool IsFinalOp() { bool IsFinalOp() { return false; }
return false;
}
protected: protected:
std::string GetTypeString() const { std::string GetTypeString() const { return "cancelled"; }
return "cancelled";
}
private: private:
int cancelled; int cancelled;
}; };
tag::tag(Callback *callback, OpVec *ops, Call *call) : tag::tag(Callback *callback, OpVec *ops, Call *call, Local<Value> call_value)
callback(callback), ops(ops), call(call){ : callback(callback), ops(ops), call(call) {
HandleScope scope;
call_persist.Reset(call_value);
} }
tag::~tag() { tag::~tag() {
@ -513,16 +491,17 @@ void DestroyTag(void *tag) {
delete tag_struct; delete tag_struct;
} }
Call::Call(grpc_call *call) : wrapped_call(call), void Call::DestroyCall() {
pending_batches(0), if (this->wrapped_call != NULL) {
has_final_op_completed(false) { grpc_call_unref(this->wrapped_call);
this->wrapped_call = NULL;
}
} }
Call::~Call() { Call::Call(grpc_call *call)
if (wrapped_call != NULL) { : wrapped_call(call), pending_batches(0), has_final_op_completed(false) {}
grpc_call_unref(wrapped_call);
} Call::~Call() { DestroyCall(); }
}
void Call::Init(Local<Object> exports) { void Call::Init(Local<Object> exports) {
HandleScope scope; HandleScope scope;
@ -551,10 +530,10 @@ Local<Value> Call::WrapStruct(grpc_call *call) {
return scope.Escape(Nan::Null()); return scope.Escape(Nan::Null());
} }
const int argc = 1; const int argc = 1;
Local<Value> argv[argc] = {Nan::New<External>( Local<Value> argv[argc] = {
reinterpret_cast<void *>(call))}; Nan::New<External>(reinterpret_cast<void *>(call))};
MaybeLocal<Object> maybe_instance = Nan::NewInstance( MaybeLocal<Object> maybe_instance =
constructor->GetFunction(), argc, argv); Nan::NewInstance(constructor->GetFunction(), argc, argv);
if (maybe_instance.IsEmpty()) { if (maybe_instance.IsEmpty()) {
return scope.Escape(Nan::Null()); return scope.Escape(Nan::Null());
} else { } else {
@ -568,19 +547,25 @@ void Call::CompleteBatch(bool is_final_op) {
} }
this->pending_batches--; this->pending_batches--;
if (this->has_final_op_completed && this->pending_batches == 0) { if (this->has_final_op_completed && this->pending_batches == 0) {
grpc_call_unref(this->wrapped_call); this->DestroyCall();
this->wrapped_call = NULL;
} }
} }
NAN_METHOD(Call::New) { 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()) { if (info.IsConstructCall()) {
Call *call; Call *call;
if (info[0]->IsExternal()) { if (info[0]->IsExternal()) {
Local<External> ext = info[0].As<External>(); Local<External> ext = info[0].As<External>();
// This option is used for wrapping an existing call // This option is used for wrapping an existing call
grpc_call *call_value = grpc_call *call_value = reinterpret_cast<grpc_call *>(ext->Value());
reinterpret_cast<grpc_call *>(ext->Value());
call = new Call(call_value); call = new Call(call_value);
} else { } else {
if (!Channel::HasInstance(info[0])) { if (!Channel::HasInstance(info[0])) {
@ -596,8 +581,8 @@ NAN_METHOD(Call::New) {
// These arguments are at the end because they are optional // These arguments are at the end because they are optional
grpc_call *parent_call = NULL; grpc_call *parent_call = NULL;
if (Call::HasInstance(info[4])) { if (Call::HasInstance(info[4])) {
Call *parent_obj = ObjectWrap::Unwrap<Call>( Call *parent_obj =
Nan::To<Object>(info[4]).ToLocalChecked()); ObjectWrap::Unwrap<Call>(Nan::To<Object>(info[4]).ToLocalChecked());
parent_call = parent_obj->wrapped_call; parent_call = parent_obj->wrapped_call;
} else if (!(info[4]->IsUndefined() || info[4]->IsNull())) { } else if (!(info[4]->IsUndefined() || info[4]->IsNull())) {
return Nan::ThrowTypeError( return Nan::ThrowTypeError(
@ -618,25 +603,24 @@ NAN_METHOD(Call::New) {
double deadline = Nan::To<double>(info[2]).FromJust(); double deadline = Nan::To<double>(info[2]).FromJust();
grpc_channel *wrapped_channel = channel->GetWrappedChannel(); grpc_channel *wrapped_channel = channel->GetWrappedChannel();
grpc_call *wrapped_call; grpc_call *wrapped_call;
grpc_slice method =
CreateSliceFromString(Nan::To<String>(info[1]).ToLocalChecked());
if (info[3]->IsString()) { if (info[3]->IsString()) {
grpc_slice *host = new grpc_slice; grpc_slice *host = new grpc_slice;
*host = CreateSliceFromString( *host =
Nan::To<String>(info[3]).ToLocalChecked()); CreateSliceFromString(Nan::To<String>(info[3]).ToLocalChecked());
wrapped_call = grpc_channel_create_call( wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags, wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(),
GetCompletionQueue(), CreateSliceFromString( method, host, MillisecondsToTimespec(deadline), NULL);
Nan::To<String>(info[1]).ToLocalChecked()),
host, MillisecondsToTimespec(deadline), NULL);
delete host; delete host;
} else if (info[3]->IsUndefined() || info[3]->IsNull()) { } else if (info[3]->IsUndefined() || info[3]->IsNull()) {
wrapped_call = grpc_channel_create_call( wrapped_call = grpc_channel_create_call(
wrapped_channel, parent_call, propagate_flags, wrapped_channel, parent_call, propagate_flags, GetCompletionQueue(),
GetCompletionQueue(), CreateSliceFromString( method, NULL, MillisecondsToTimespec(deadline), NULL);
Nan::To<String>(info[1]).ToLocalChecked()),
NULL, MillisecondsToTimespec(deadline), NULL);
} else { } else {
return Nan::ThrowTypeError("Call's fourth argument must be a string"); return Nan::ThrowTypeError("Call's fourth argument must be a string");
} }
grpc_slice_unref(method);
call = new Call(wrapped_call); call = new Call(wrapped_call);
Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(), Nan::Set(info.This(), Nan::New("channel_").ToLocalChecked(),
channel_object); channel_object);
@ -646,8 +630,8 @@ NAN_METHOD(Call::New) {
} else { } else {
const int argc = 4; const int argc = 4;
Local<Value> argv[argc] = {info[0], info[1], info[2], info[3]}; Local<Value> argv[argc] = {info[0], info[1], info[2], info[3]};
MaybeLocal<Object> maybe_instance = Nan::NewInstance( MaybeLocal<Object> maybe_instance =
constructor->GetFunction(), argc, argv); Nan::NewInstance(constructor->GetFunction(), argc, argv);
if (maybe_instance.IsEmpty()) { if (maybe_instance.IsEmpty()) {
// There's probably a pending exception // There's probably a pending exception
return; return;
@ -720,8 +704,8 @@ NAN_METHOD(Call::StartBatch) {
} }
Callback *callback = new Callback(callback_func); Callback *callback = new Callback(callback_func);
grpc_call_error error = grpc_call_start_batch( grpc_call_error error = grpc_call_start_batch(
call->wrapped_call, &ops[0], nops, new struct tag( call->wrapped_call, &ops[0], nops,
callback, op_vector.release(), call), NULL); new struct tag(callback, op_vector.release(), call, info.This()), NULL);
if (error != GRPC_CALL_OK) { if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("startBatch failed", error)); return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
} }
@ -754,8 +738,8 @@ NAN_METHOD(Call::CancelWithStatus) {
"cancelWithStatus's second argument must be a string"); "cancelWithStatus's second argument must be a string");
} }
Call *call = ObjectWrap::Unwrap<Call>(info.This()); Call *call = ObjectWrap::Unwrap<Call>(info.This());
grpc_status_code code = static_cast<grpc_status_code>( grpc_status_code code =
Nan::To<uint32_t>(info[0]).FromJust()); static_cast<grpc_status_code>(Nan::To<uint32_t>(info[0]).FromJust());
if (code == GRPC_STATUS_OK) { if (code == GRPC_STATUS_OK) {
return Nan::ThrowRangeError( return Nan::ThrowRangeError(
"cancelWithStatus cannot be called with OK status"); "cancelWithStatus cannot be called with OK status");

View File

@ -58,6 +58,8 @@ v8::Local<v8::Value> ParseMetadata(const grpc_metadata_array *metadata_array);
bool CreateMetadataArray(v8::Local<v8::Object> metadata, bool CreateMetadataArray(v8::Local<v8::Object> metadata,
grpc_metadata_array *array); grpc_metadata_array *array);
void DestroyMetadataArray(grpc_metadata_array *array);
/* Wrapper class for grpc_call structs. */ /* Wrapper class for grpc_call structs. */
class Call : public Nan::ObjectWrap { class Call : public Nan::ObjectWrap {
public: public:
@ -76,6 +78,8 @@ class Call : public Nan::ObjectWrap {
Call(const Call &); Call(const Call &);
Call &operator=(const Call &); Call &operator=(const Call &);
void DestroyCall();
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(StartBatch); static NAN_METHOD(StartBatch);
static NAN_METHOD(Cancel); static NAN_METHOD(Cancel);
@ -109,11 +113,14 @@ class Op {
typedef std::vector<unique_ptr<Op>> OpVec; typedef std::vector<unique_ptr<Op>> OpVec;
struct tag { struct tag {
tag(Nan::Callback *callback, OpVec *ops, Call *call); tag(Nan::Callback *callback, OpVec *ops, Call *call,
v8::Local<v8::Value> call_value);
~tag(); ~tag();
Nan::Callback *callback; Nan::Callback *callback;
OpVec *ops; OpVec *ops;
Call *call; Call *call;
Nan::Persistent<v8::Value, Nan::CopyablePersistentTraits<v8::Value>>
call_persist;
}; };
v8::Local<v8::Value> GetTagNodeValue(void *tag); v8::Local<v8::Value> GetTagNodeValue(void *tag);

View File

@ -211,6 +211,7 @@ NAN_METHOD(PluginCallback) {
Utf8String details_utf8_str(info[1]); Utf8String details_utf8_str(info[1]);
char *details = *details_utf8_str; char *details = *details_utf8_str;
grpc_metadata_array array; grpc_metadata_array array;
grpc_metadata_array_init(&array);
Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked(); Local<Object> callback_data = Nan::To<Object>(info[3]).ToLocalChecked();
if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(), if (!CreateMetadataArray(Nan::To<Object>(info[2]).ToLocalChecked(),
&array)){ &array)){
@ -226,6 +227,7 @@ NAN_METHOD(PluginCallback) {
Nan::New("user_data").ToLocalChecked() Nan::New("user_data").ToLocalChecked()
).ToLocalChecked().As<External>()->Value(); ).ToLocalChecked().As<External>()->Value();
cb(user_data, array.metadata, array.count, code, details); cb(user_data, array.metadata, array.count, code, details);
DestroyMetadataArray(&array);
} }
NAUV_WORK_CB(SendPluginCallback) { NAUV_WORK_CB(SendPluginCallback) {

View File

@ -280,7 +280,7 @@ NAN_METHOD(Channel::WatchConnectivityState) {
channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline), channel->wrapped_channel, last_state, MillisecondsToTimespec(deadline),
GetCompletionQueue(), GetCompletionQueue(),
new struct tag(callback, new struct tag(callback,
ops.release(), NULL)); ops.release(), NULL, Nan::Null()));
CompletionQueueNext(); CompletionQueueNext();
} }

View File

@ -286,8 +286,10 @@ NAN_METHOD(MetadataKeyIsLegal) {
"headerKeyIsLegal's argument must be a string"); "headerKeyIsLegal's argument must be a string");
} }
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked(); Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>( info.GetReturnValue().Set(static_cast<bool>(
grpc_header_key_is_legal(CreateSliceFromString(key)))); grpc_header_key_is_legal(slice)));
grpc_slice_unref(slice);
} }
NAN_METHOD(MetadataNonbinValueIsLegal) { NAN_METHOD(MetadataNonbinValueIsLegal) {
@ -296,8 +298,10 @@ NAN_METHOD(MetadataNonbinValueIsLegal) {
"metadataNonbinValueIsLegal's argument must be a string"); "metadataNonbinValueIsLegal's argument must be a string");
} }
Local<String> value = Nan::To<String>(info[0]).ToLocalChecked(); Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
grpc_slice slice = CreateSliceFromString(value);
info.GetReturnValue().Set(static_cast<bool>( info.GetReturnValue().Set(static_cast<bool>(
grpc_header_nonbin_value_is_legal(CreateSliceFromString(value)))); grpc_header_nonbin_value_is_legal(slice)));
grpc_slice_unref(slice);
} }
NAN_METHOD(MetadataKeyIsBinary) { NAN_METHOD(MetadataKeyIsBinary) {
@ -306,8 +310,10 @@ NAN_METHOD(MetadataKeyIsBinary) {
"metadataKeyIsLegal's argument must be a string"); "metadataKeyIsLegal's argument must be a string");
} }
Local<String> key = Nan::To<String>(info[0]).ToLocalChecked(); Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
grpc_slice slice = CreateSliceFromString(key);
info.GetReturnValue().Set(static_cast<bool>( info.GetReturnValue().Set(static_cast<bool>(
grpc_is_binary_header(CreateSliceFromString(key)))); grpc_is_binary_header(slice)));
grpc_slice_unref(slice);
} }
static grpc_ssl_roots_override_result get_ssl_roots_override( static grpc_ssl_roots_override_result get_ssl_roots_override(

View File

@ -193,7 +193,7 @@ NAN_METHOD(Server::RequestCall) {
GetCompletionQueue(), GetCompletionQueue(),
GetCompletionQueue(), GetCompletionQueue(),
new struct tag(new Callback(info[0].As<Function>()), ops.release(), new struct tag(new Callback(info[0].As<Function>()), ops.release(),
NULL)); NULL, Nan::Null()));
if (error != GRPC_CALL_OK) { if (error != GRPC_CALL_OK) {
return Nan::ThrowError(nanErrorWithCode("requestCall failed", error)); return Nan::ThrowError(nanErrorWithCode("requestCall failed", error));
} }
@ -246,7 +246,7 @@ NAN_METHOD(Server::TryShutdown) {
grpc_server_shutdown_and_notify( grpc_server_shutdown_and_notify(
server->wrapped_server, GetCompletionQueue(), server->wrapped_server, GetCompletionQueue(),
new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(), new struct tag(new Nan::Callback(info[0].As<Function>()), ops.release(),
NULL)); NULL, Nan::Null()));
CompletionQueueNext(); CompletionQueueNext();
} }

View File

@ -118,7 +118,8 @@ void Server::ShutdownServer() {
grpc_server_shutdown_and_notify( grpc_server_shutdown_and_notify(
this->wrapped_server, GetCompletionQueue(), this->wrapped_server, GetCompletionQueue(),
new struct tag(new Callback(**shutdown_callback), ops.release(), NULL)); new struct tag(new Callback(**shutdown_callback), ops.release(), NULL,
Nan::Null()));
grpc_server_cancel_all_calls(this->wrapped_server); grpc_server_cancel_all_calls(this->wrapped_server);
CompletionQueueNext(); CompletionQueueNext();
this->wrapped_server = NULL; this->wrapped_server = NULL;