Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: third_party/grpc/src/node/ext/call.cc

Issue 1932353002: Initial checkin of gRPC to third_party/ Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/grpc/src/node/ext/call.h ('k') | third_party/grpc/src/node/ext/call_credentials.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright 2015-2016, Google Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34 #include <memory>
35 #include <vector>
36 #include <map>
37
38 #include <node.h>
39
40 #include "grpc/support/log.h"
41 #include "grpc/grpc.h"
42 #include "grpc/grpc_security.h"
43 #include "grpc/support/alloc.h"
44 #include "grpc/support/time.h"
45 #include "byte_buffer.h"
46 #include "call.h"
47 #include "channel.h"
48 #include "completion_queue_async_worker.h"
49 #include "call_credentials.h"
50 #include "timeval.h"
51
52 using std::unique_ptr;
53 using std::shared_ptr;
54 using std::vector;
55
56 namespace grpc {
57 namespace node {
58
59 using Nan::Callback;
60 using Nan::EscapableHandleScope;
61 using Nan::HandleScope;
62 using Nan::Maybe;
63 using Nan::MaybeLocal;
64 using Nan::ObjectWrap;
65 using Nan::Persistent;
66 using Nan::Utf8String;
67
68 using v8::Array;
69 using v8::Boolean;
70 using v8::Exception;
71 using v8::External;
72 using v8::Function;
73 using v8::FunctionTemplate;
74 using v8::Integer;
75 using v8::Local;
76 using v8::Number;
77 using v8::Object;
78 using v8::ObjectTemplate;
79 using v8::Uint32;
80 using v8::String;
81 using v8::Value;
82
83 Callback *Call::constructor;
84 Persistent<FunctionTemplate> Call::fun_tpl;
85
86 /**
87 * Helper function for throwing errors with a grpc_call_error value.
88 * Modified from the answer by Gus Goose to
89 * http://stackoverflow.com/questions/31794200.
90 */
91 Local<Value> nanErrorWithCode(const char *msg, grpc_call_error code) {
92 EscapableHandleScope scope;
93 Local<Object> err = Nan::Error(msg).As<Object>();
94 Nan::Set(err, Nan::New("code").ToLocalChecked(), Nan::New<Uint32>(code));
95 return scope.Escape(err);
96 }
97
98 bool CreateMetadataArray(Local<Object> metadata, grpc_metadata_array *array,
99 shared_ptr<Resources> resources) {
100 HandleScope scope;
101 grpc_metadata_array_init(array);
102 Local<Array> keys = Nan::GetOwnPropertyNames(metadata).ToLocalChecked();
103 for (unsigned int i = 0; i < keys->Length(); i++) {
104 Local<String> current_key = Nan::To<String>(
105 Nan::Get(keys, i).ToLocalChecked()).ToLocalChecked();
106 Local<Value> value_array = Nan::Get(metadata, current_key).ToLocalChecked();
107 if (!value_array->IsArray()) {
108 return false;
109 }
110 array->capacity += Local<Array>::Cast(value_array)->Length();
111 }
112 array->metadata = reinterpret_cast<grpc_metadata*>(
113 gpr_malloc(array->capacity * sizeof(grpc_metadata)));
114 for (unsigned int i = 0; i < keys->Length(); i++) {
115 Local<String> current_key(keys->Get(i)->ToString());
116 Utf8String *utf8_key = new Utf8String(current_key);
117 resources->strings.push_back(unique_ptr<Utf8String>(utf8_key));
118 Local<Array> values = Local<Array>::Cast(
119 Nan::Get(metadata, current_key).ToLocalChecked());
120 for (unsigned int j = 0; j < values->Length(); j++) {
121 Local<Value> value = Nan::Get(values, j).ToLocalChecked();
122 grpc_metadata *current = &array->metadata[array->count];
123 current->key = **utf8_key;
124 // Only allow binary headers for "-bin" keys
125 if (grpc_is_binary_header(current->key, strlen(current->key))) {
126 if (::node::Buffer::HasInstance(value)) {
127 current->value = ::node::Buffer::Data(value);
128 current->value_length = ::node::Buffer::Length(value);
129 PersistentValue *handle = new PersistentValue(value);
130 resources->handles.push_back(unique_ptr<PersistentValue>(handle));
131 } else {
132 return false;
133 }
134 } else {
135 if (value->IsString()) {
136 Local<String> string_value = Nan::To<String>(value).ToLocalChecked();
137 Utf8String *utf8_value = new Utf8String(string_value);
138 resources->strings.push_back(unique_ptr<Utf8String>(utf8_value));
139 current->value = **utf8_value;
140 current->value_length = string_value->Length();
141 } else {
142 return false;
143 }
144 }
145 array->count += 1;
146 }
147 }
148 return true;
149 }
150
151 Local<Value> ParseMetadata(const grpc_metadata_array *metadata_array) {
152 EscapableHandleScope scope;
153 grpc_metadata *metadata_elements = metadata_array->metadata;
154 size_t length = metadata_array->count;
155 std::map<const char*, size_t> size_map;
156 std::map<const char*, size_t> index_map;
157
158 for (unsigned int i = 0; i < length; i++) {
159 const char *key = metadata_elements[i].key;
160 if (size_map.count(key)) {
161 size_map[key] += 1;
162 } else {
163 size_map[key] = 1;
164 }
165 index_map[key] = 0;
166 }
167 Local<Object> metadata_object = Nan::New<Object>();
168 for (unsigned int i = 0; i < length; i++) {
169 grpc_metadata* elem = &metadata_elements[i];
170 Local<String> key_string = Nan::New(elem->key).ToLocalChecked();
171 Local<Array> array;
172 MaybeLocal<Value> maybe_array = Nan::Get(metadata_object, key_string);
173 if (maybe_array.IsEmpty() || !maybe_array.ToLocalChecked()->IsArray()) {
174 array = Nan::New<Array>(size_map[elem->key]);
175 Nan::Set(metadata_object, key_string, array);
176 } else {
177 array = Local<Array>::Cast(maybe_array.ToLocalChecked());
178 }
179 if (grpc_is_binary_header(elem->key, strlen(elem->key))) {
180 Nan::Set(array, index_map[elem->key],
181 MakeFastBuffer(
182 Nan::CopyBuffer(elem->value,
183 elem->value_length).ToLocalChecked()));
184 } else {
185 Nan::Set(array, index_map[elem->key],
186 Nan::New(elem->value).ToLocalChecked());
187 }
188 index_map[elem->key] += 1;
189 }
190 return scope.Escape(metadata_object);
191 }
192
193 Local<Value> Op::GetOpType() const {
194 EscapableHandleScope scope;
195 return scope.Escape(Nan::New(GetTypeString()).ToLocalChecked());
196 }
197
198 Op::~Op() {
199 }
200
201 class SendMetadataOp : public Op {
202 public:
203 Local<Value> GetNodeValue() const {
204 EscapableHandleScope scope;
205 return scope.Escape(Nan::True());
206 }
207 bool ParseOp(Local<Value> value, grpc_op *out,
208 shared_ptr<Resources> resources) {
209 if (!value->IsObject()) {
210 return false;
211 }
212 grpc_metadata_array array;
213 MaybeLocal<Object> maybe_metadata = Nan::To<Object>(value);
214 if (maybe_metadata.IsEmpty()) {
215 return false;
216 }
217 if (!CreateMetadataArray(maybe_metadata.ToLocalChecked(),
218 &array, resources)) {
219 return false;
220 }
221 out->data.send_initial_metadata.count = array.count;
222 out->data.send_initial_metadata.metadata = array.metadata;
223 return true;
224 }
225 protected:
226 std::string GetTypeString() const {
227 return "send_metadata";
228 }
229 };
230
231 class SendMessageOp : public Op {
232 public:
233 SendMessageOp() {
234 send_message = NULL;
235 }
236 ~SendMessageOp() {
237 if (send_message != NULL) {
238 grpc_byte_buffer_destroy(send_message);
239 }
240 }
241 Local<Value> GetNodeValue() const {
242 EscapableHandleScope scope;
243 return scope.Escape(Nan::True());
244 }
245 bool ParseOp(Local<Value> value, grpc_op *out,
246 shared_ptr<Resources> resources) {
247 if (!::node::Buffer::HasInstance(value)) {
248 return false;
249 }
250 Local<Object> object_value = Nan::To<Object>(value).ToLocalChecked();
251 MaybeLocal<Value> maybe_flag_value = Nan::Get(
252 object_value, Nan::New("grpcWriteFlags").ToLocalChecked());
253 if (!maybe_flag_value.IsEmpty()) {
254 Local<Value> flag_value = maybe_flag_value.ToLocalChecked();
255 if (flag_value->IsUint32()) {
256 Maybe<uint32_t> maybe_flag = Nan::To<uint32_t>(flag_value);
257 out->flags = maybe_flag.FromMaybe(0) & GRPC_WRITE_USED_MASK;
258 }
259 }
260 send_message = BufferToByteBuffer(value);
261 out->data.send_message = send_message;
262 PersistentValue *handle = new PersistentValue(value);
263 resources->handles.push_back(unique_ptr<PersistentValue>(handle));
264 return true;
265 }
266 protected:
267 std::string GetTypeString() const {
268 return "send_message";
269 }
270 private:
271 grpc_byte_buffer *send_message;
272 };
273
274 class SendClientCloseOp : public Op {
275 public:
276 Local<Value> GetNodeValue() const {
277 EscapableHandleScope scope;
278 return scope.Escape(Nan::True());
279 }
280 bool ParseOp(Local<Value> value, grpc_op *out,
281 shared_ptr<Resources> resources) {
282 return true;
283 }
284 protected:
285 std::string GetTypeString() const {
286 return "client_close";
287 }
288 };
289
290 class SendServerStatusOp : public Op {
291 public:
292 Local<Value> GetNodeValue() const {
293 EscapableHandleScope scope;
294 return scope.Escape(Nan::True());
295 }
296 bool ParseOp(Local<Value> value, grpc_op *out,
297 shared_ptr<Resources> resources) {
298 if (!value->IsObject()) {
299 return false;
300 }
301 Local<Object> server_status = Nan::To<Object>(value).ToLocalChecked();
302 MaybeLocal<Value> maybe_metadata = Nan::Get(
303 server_status, Nan::New("metadata").ToLocalChecked());
304 if (maybe_metadata.IsEmpty()) {
305 return false;
306 }
307 if (!maybe_metadata.ToLocalChecked()->IsObject()) {
308 return false;
309 }
310 Local<Object> metadata = Nan::To<Object>(
311 maybe_metadata.ToLocalChecked()).ToLocalChecked();
312 MaybeLocal<Value> maybe_code = Nan::Get(server_status,
313 Nan::New("code").ToLocalChecked());
314 if (maybe_code.IsEmpty()) {
315 return false;
316 }
317 if (!maybe_code.ToLocalChecked()->IsUint32()) {
318 return false;
319 }
320 uint32_t code = Nan::To<uint32_t>(maybe_code.ToLocalChecked()).FromJust();
321 MaybeLocal<Value> maybe_details = Nan::Get(
322 server_status, Nan::New("details").ToLocalChecked());
323 if (maybe_details.IsEmpty()) {
324 return false;
325 }
326 if (!maybe_details.ToLocalChecked()->IsString()) {
327 return false;
328 }
329 Local<String> details = Nan::To<String>(
330 maybe_details.ToLocalChecked()).ToLocalChecked();
331 grpc_metadata_array array;
332 if (!CreateMetadataArray(metadata, &array, resources)) {
333 return false;
334 }
335 out->data.send_status_from_server.trailing_metadata_count = array.count;
336 out->data.send_status_from_server.trailing_metadata = array.metadata;
337 out->data.send_status_from_server.status =
338 static_cast<grpc_status_code>(code);
339 Utf8String *str = new Utf8String(details);
340 resources->strings.push_back(unique_ptr<Utf8String>(str));
341 out->data.send_status_from_server.status_details = **str;
342 return true;
343 }
344 protected:
345 std::string GetTypeString() const {
346 return "send_status";
347 }
348 };
349
350 class GetMetadataOp : public Op {
351 public:
352 GetMetadataOp() {
353 grpc_metadata_array_init(&recv_metadata);
354 }
355
356 ~GetMetadataOp() {
357 grpc_metadata_array_destroy(&recv_metadata);
358 }
359
360 Local<Value> GetNodeValue() const {
361 EscapableHandleScope scope;
362 return scope.Escape(ParseMetadata(&recv_metadata));
363 }
364
365 bool ParseOp(Local<Value> value, grpc_op *out,
366 shared_ptr<Resources> resources) {
367 out->data.recv_initial_metadata = &recv_metadata;
368 return true;
369 }
370
371 protected:
372 std::string GetTypeString() const {
373 return "metadata";
374 }
375
376 private:
377 grpc_metadata_array recv_metadata;
378 };
379
380 class ReadMessageOp : public Op {
381 public:
382 ReadMessageOp() {
383 recv_message = NULL;
384 }
385 ~ReadMessageOp() {
386 if (recv_message != NULL) {
387 grpc_byte_buffer_destroy(recv_message);
388 }
389 }
390 Local<Value> GetNodeValue() const {
391 EscapableHandleScope scope;
392 return scope.Escape(ByteBufferToBuffer(recv_message));
393 }
394
395 bool ParseOp(Local<Value> value, grpc_op *out,
396 shared_ptr<Resources> resources) {
397 out->data.recv_message = &recv_message;
398 return true;
399 }
400
401 protected:
402 std::string GetTypeString() const {
403 return "read";
404 }
405
406 private:
407 grpc_byte_buffer *recv_message;
408 };
409
410 class ClientStatusOp : public Op {
411 public:
412 ClientStatusOp() {
413 grpc_metadata_array_init(&metadata_array);
414 status_details = NULL;
415 details_capacity = 0;
416 }
417
418 ~ClientStatusOp() {
419 grpc_metadata_array_destroy(&metadata_array);
420 gpr_free(status_details);
421 }
422
423 bool ParseOp(Local<Value> value, grpc_op *out,
424 shared_ptr<Resources> resources) {
425 out->data.recv_status_on_client.trailing_metadata = &metadata_array;
426 out->data.recv_status_on_client.status = &status;
427 out->data.recv_status_on_client.status_details = &status_details;
428 out->data.recv_status_on_client.status_details_capacity = &details_capacity;
429 return true;
430 }
431
432 Local<Value> GetNodeValue() const {
433 EscapableHandleScope scope;
434 Local<Object> status_obj = Nan::New<Object>();
435 Nan::Set(status_obj, Nan::New("code").ToLocalChecked(),
436 Nan::New<Number>(status));
437 if (status_details != NULL) {
438 Nan::Set(status_obj, Nan::New("details").ToLocalChecked(),
439 Nan::New(status_details).ToLocalChecked());
440 }
441 Nan::Set(status_obj, Nan::New("metadata").ToLocalChecked(),
442 ParseMetadata(&metadata_array));
443 return scope.Escape(status_obj);
444 }
445 protected:
446 std::string GetTypeString() const {
447 return "status";
448 }
449 private:
450 grpc_metadata_array metadata_array;
451 grpc_status_code status;
452 char *status_details;
453 size_t details_capacity;
454 };
455
456 class ServerCloseResponseOp : public Op {
457 public:
458 Local<Value> GetNodeValue() const {
459 EscapableHandleScope scope;
460 return scope.Escape(Nan::New<Boolean>(cancelled));
461 }
462
463 bool ParseOp(Local<Value> value, grpc_op *out,
464 shared_ptr<Resources> resources) {
465 out->data.recv_close_on_server.cancelled = &cancelled;
466 return true;
467 }
468
469 protected:
470 std::string GetTypeString() const {
471 return "cancelled";
472 }
473
474 private:
475 int cancelled;
476 };
477
478 tag::tag(Callback *callback, OpVec *ops,
479 shared_ptr<Resources> resources) :
480 callback(callback), ops(ops), resources(resources){
481 }
482
483 tag::~tag() {
484 delete callback;
485 delete ops;
486 }
487
488 Local<Value> GetTagNodeValue(void *tag) {
489 EscapableHandleScope scope;
490 struct tag *tag_struct = reinterpret_cast<struct tag *>(tag);
491 Local<Object> tag_obj = Nan::New<Object>();
492 for (vector<unique_ptr<Op> >::iterator it = tag_struct->ops->begin();
493 it != tag_struct->ops->end(); ++it) {
494 Op *op_ptr = it->get();
495 Nan::Set(tag_obj, op_ptr->GetOpType(), op_ptr->GetNodeValue());
496 }
497 return scope.Escape(tag_obj);
498 }
499
500 Callback *GetTagCallback(void *tag) {
501 struct tag *tag_struct = reinterpret_cast<struct tag *>(tag);
502 return tag_struct->callback;
503 }
504
505 void DestroyTag(void *tag) {
506 struct tag *tag_struct = reinterpret_cast<struct tag *>(tag);
507 delete tag_struct;
508 }
509
510 Call::Call(grpc_call *call) : wrapped_call(call) {
511 }
512
513 Call::~Call() {
514 grpc_call_destroy(wrapped_call);
515 }
516
517 void Call::Init(Local<Object> exports) {
518 HandleScope scope;
519 Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
520 tpl->SetClassName(Nan::New("Call").ToLocalChecked());
521 tpl->InstanceTemplate()->SetInternalFieldCount(1);
522 Nan::SetPrototypeMethod(tpl, "startBatch", StartBatch);
523 Nan::SetPrototypeMethod(tpl, "cancel", Cancel);
524 Nan::SetPrototypeMethod(tpl, "cancelWithStatus", CancelWithStatus);
525 Nan::SetPrototypeMethod(tpl, "getPeer", GetPeer);
526 Nan::SetPrototypeMethod(tpl, "setCredentials", SetCredentials);
527 fun_tpl.Reset(tpl);
528 Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
529 Nan::Set(exports, Nan::New("Call").ToLocalChecked(), ctr);
530 constructor = new Callback(ctr);
531 }
532
533 bool Call::HasInstance(Local<Value> val) {
534 HandleScope scope;
535 return Nan::New(fun_tpl)->HasInstance(val);
536 }
537
538 Local<Value> Call::WrapStruct(grpc_call *call) {
539 EscapableHandleScope scope;
540 if (call == NULL) {
541 return scope.Escape(Nan::Null());
542 }
543 const int argc = 1;
544 Local<Value> argv[argc] = {Nan::New<External>(
545 reinterpret_cast<void *>(call))};
546 MaybeLocal<Object> maybe_instance = Nan::NewInstance(
547 constructor->GetFunction(), argc, argv);
548 if (maybe_instance.IsEmpty()) {
549 return scope.Escape(Nan::Null());
550 } else {
551 return scope.Escape(maybe_instance.ToLocalChecked());
552 }
553 }
554
555 NAN_METHOD(Call::New) {
556 if (info.IsConstructCall()) {
557 Call *call;
558 if (info[0]->IsExternal()) {
559 Local<External> ext = info[0].As<External>();
560 // This option is used for wrapping an existing call
561 grpc_call *call_value =
562 reinterpret_cast<grpc_call *>(ext->Value());
563 call = new Call(call_value);
564 } else {
565 if (!Channel::HasInstance(info[0])) {
566 return Nan::ThrowTypeError("Call's first argument must be a Channel");
567 }
568 if (!info[1]->IsString()) {
569 return Nan::ThrowTypeError("Call's second argument must be a string");
570 }
571 if (!(info[2]->IsNumber() || info[2]->IsDate())) {
572 return Nan::ThrowTypeError(
573 "Call's third argument must be a date or a number");
574 }
575 // These arguments are at the end because they are optional
576 grpc_call *parent_call = NULL;
577 if (Call::HasInstance(info[4])) {
578 Call *parent_obj = ObjectWrap::Unwrap<Call>(
579 Nan::To<Object>(info[4]).ToLocalChecked());
580 parent_call = parent_obj->wrapped_call;
581 } else if (!(info[4]->IsUndefined() || info[4]->IsNull())) {
582 return Nan::ThrowTypeError(
583 "Call's fifth argument must be another call, if provided");
584 }
585 uint32_t propagate_flags = GRPC_PROPAGATE_DEFAULTS;
586 if (info[5]->IsUint32()) {
587 propagate_flags = Nan::To<uint32_t>(info[5]).FromJust();
588 } else if (!(info[5]->IsUndefined() || info[5]->IsNull())) {
589 return Nan::ThrowTypeError(
590 "Call's sixth argument must be propagate flags, if provided");
591 }
592 Local<Object> channel_object = Nan::To<Object>(info[0]).ToLocalChecked();
593 Channel *channel = ObjectWrap::Unwrap<Channel>(channel_object);
594 if (channel->GetWrappedChannel() == NULL) {
595 return Nan::ThrowError("Call cannot be created from a closed channel");
596 }
597 Utf8String method(info[1]);
598 double deadline = Nan::To<double>(info[2]).FromJust();
599 grpc_channel *wrapped_channel = channel->GetWrappedChannel();
600 grpc_call *wrapped_call;
601 if (info[3]->IsString()) {
602 Utf8String host_override(info[3]);
603 wrapped_call = grpc_channel_create_call(
604 wrapped_channel, parent_call, propagate_flags,
605 CompletionQueueAsyncWorker::GetQueue(), *method,
606 *host_override, MillisecondsToTimespec(deadline), NULL);
607 } else if (info[3]->IsUndefined() || info[3]->IsNull()) {
608 wrapped_call = grpc_channel_create_call(
609 wrapped_channel, parent_call, propagate_flags,
610 CompletionQueueAsyncWorker::GetQueue(), *method,
611 NULL, MillisecondsToTimespec(deadline), NULL);
612 } else {
613 return Nan::ThrowTypeError("Call's fourth argument must be a string");
614 }
615 call = new Call(wrapped_call);
616 info.This()->SetHiddenValue(Nan::New("channel_").ToLocalChecked(),
617 channel_object);
618 }
619 call->Wrap(info.This());
620 info.GetReturnValue().Set(info.This());
621 } else {
622 const int argc = 4;
623 Local<Value> argv[argc] = {info[0], info[1], info[2], info[3]};
624 MaybeLocal<Object> maybe_instance = constructor->GetFunction()->NewInstance(
625 argc, argv);
626 if (maybe_instance.IsEmpty()) {
627 // There's probably a pending exception
628 return;
629 } else {
630 info.GetReturnValue().Set(maybe_instance.ToLocalChecked());
631 }
632 }
633 }
634
635 NAN_METHOD(Call::StartBatch) {
636 if (!Call::HasInstance(info.This())) {
637 return Nan::ThrowTypeError("startBatch can only be called on Call objects");
638 }
639 if (!info[0]->IsObject()) {
640 return Nan::ThrowError("startBatch's first argument must be an object");
641 }
642 if (!info[1]->IsFunction()) {
643 return Nan::ThrowError("startBatch's second argument must be a callback");
644 }
645 Local<Function> callback_func = info[1].As<Function>();
646 Call *call = ObjectWrap::Unwrap<Call>(info.This());
647 shared_ptr<Resources> resources(new Resources);
648 Local<Object> obj = Nan::To<Object>(info[0]).ToLocalChecked();
649 Local<Array> keys = Nan::GetOwnPropertyNames(obj).ToLocalChecked();
650 size_t nops = keys->Length();
651 vector<grpc_op> ops(nops);
652 unique_ptr<OpVec> op_vector(new OpVec());
653 for (unsigned int i = 0; i < nops; i++) {
654 unique_ptr<Op> op;
655 MaybeLocal<Value> maybe_key = Nan::Get(keys, i);
656 if (maybe_key.IsEmpty() || (!maybe_key.ToLocalChecked()->IsUint32())) {
657 return Nan::ThrowError(
658 "startBatch's first argument's keys must be integers");
659 }
660 uint32_t type = Nan::To<uint32_t>(maybe_key.ToLocalChecked()).FromJust();
661 ops[i].op = static_cast<grpc_op_type>(type);
662 ops[i].flags = 0;
663 ops[i].reserved = NULL;
664 switch (type) {
665 case GRPC_OP_SEND_INITIAL_METADATA:
666 op.reset(new SendMetadataOp());
667 break;
668 case GRPC_OP_SEND_MESSAGE:
669 op.reset(new SendMessageOp());
670 break;
671 case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
672 op.reset(new SendClientCloseOp());
673 break;
674 case GRPC_OP_SEND_STATUS_FROM_SERVER:
675 op.reset(new SendServerStatusOp());
676 break;
677 case GRPC_OP_RECV_INITIAL_METADATA:
678 op.reset(new GetMetadataOp());
679 break;
680 case GRPC_OP_RECV_MESSAGE:
681 op.reset(new ReadMessageOp());
682 break;
683 case GRPC_OP_RECV_STATUS_ON_CLIENT:
684 op.reset(new ClientStatusOp());
685 break;
686 case GRPC_OP_RECV_CLOSE_ON_SERVER:
687 op.reset(new ServerCloseResponseOp());
688 break;
689 default:
690 return Nan::ThrowError("Argument object had an unrecognized key");
691 }
692 if (!op->ParseOp(obj->Get(type), &ops[i], resources)) {
693 return Nan::ThrowTypeError("Incorrectly typed arguments to startBatch");
694 }
695 op_vector->push_back(std::move(op));
696 }
697 Callback *callback = new Callback(callback_func);
698 grpc_call_error error = grpc_call_start_batch(
699 call->wrapped_call, &ops[0], nops, new struct tag(
700 callback, op_vector.release(), resources), NULL);
701 if (error != GRPC_CALL_OK) {
702 return Nan::ThrowError(nanErrorWithCode("startBatch failed", error));
703 }
704 CompletionQueueAsyncWorker::Next();
705 }
706
707 NAN_METHOD(Call::Cancel) {
708 if (!Call::HasInstance(info.This())) {
709 return Nan::ThrowTypeError("cancel can only be called on Call objects");
710 }
711 Call *call = ObjectWrap::Unwrap<Call>(info.This());
712 grpc_call_error error = grpc_call_cancel(call->wrapped_call, NULL);
713 if (error != GRPC_CALL_OK) {
714 return Nan::ThrowError(nanErrorWithCode("cancel failed", error));
715 }
716 }
717
718 NAN_METHOD(Call::CancelWithStatus) {
719 Nan::HandleScope scope;
720 if (!HasInstance(info.This())) {
721 return Nan::ThrowTypeError("cancel can only be called on Call objects");
722 }
723 if (!info[0]->IsUint32()) {
724 return Nan::ThrowTypeError(
725 "cancelWithStatus's first argument must be a status code");
726 }
727 if (!info[1]->IsString()) {
728 return Nan::ThrowTypeError(
729 "cancelWithStatus's second argument must be a string");
730 }
731 Call *call = ObjectWrap::Unwrap<Call>(info.This());
732 grpc_status_code code = static_cast<grpc_status_code>(
733 Nan::To<uint32_t>(info[0]).FromJust());
734 if (code == GRPC_STATUS_OK) {
735 return Nan::ThrowRangeError(
736 "cancelWithStatus cannot be called with OK status");
737 }
738 Utf8String details(info[1]);
739 grpc_call_cancel_with_status(call->wrapped_call, code, *details, NULL);
740 }
741
742 NAN_METHOD(Call::GetPeer) {
743 Nan::HandleScope scope;
744 if (!HasInstance(info.This())) {
745 return Nan::ThrowTypeError("getPeer can only be called on Call objects");
746 }
747 Call *call = ObjectWrap::Unwrap<Call>(info.This());
748 char *peer = grpc_call_get_peer(call->wrapped_call);
749 Local<Value> peer_value = Nan::New(peer).ToLocalChecked();
750 gpr_free(peer);
751 info.GetReturnValue().Set(peer_value);
752 }
753
754 NAN_METHOD(Call::SetCredentials) {
755 Nan::HandleScope scope;
756 if (!HasInstance(info.This())) {
757 return Nan::ThrowTypeError(
758 "setCredentials can only be called on Call objects");
759 }
760 if (!CallCredentials::HasInstance(info[0])) {
761 return Nan::ThrowTypeError(
762 "setCredentials' first argument must be a CallCredentials");
763 }
764 Call *call = ObjectWrap::Unwrap<Call>(info.This());
765 CallCredentials *creds_object = ObjectWrap::Unwrap<CallCredentials>(
766 Nan::To<Object>(info[0]).ToLocalChecked());
767 grpc_call_credentials *creds = creds_object->GetWrappedCredentials();
768 grpc_call_error error = GRPC_CALL_ERROR;
769 if (creds) {
770 error = grpc_call_set_credentials(call->wrapped_call, creds);
771 }
772 info.GetReturnValue().Set(Nan::New<Uint32>(error));
773 }
774
775 } // namespace node
776 } // namespace grpc
OLDNEW
« no previous file with comments | « third_party/grpc/src/node/ext/call.h ('k') | third_party/grpc/src/node/ext/call_credentials.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698