channel_credentials.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <node.h>
  19. #include "call.h"
  20. #include "call_credentials.h"
  21. #include "channel_credentials.h"
  22. #include "grpc/grpc.h"
  23. #include "grpc/grpc_security.h"
  24. #include "grpc/support/log.h"
  25. namespace grpc {
  26. namespace node {
  27. using Nan::Callback;
  28. using Nan::EscapableHandleScope;
  29. using Nan::HandleScope;
  30. using Nan::Maybe;
  31. using Nan::MaybeLocal;
  32. using Nan::ObjectWrap;
  33. using Nan::Persistent;
  34. using Nan::Utf8String;
  35. using v8::Exception;
  36. using v8::External;
  37. using v8::Function;
  38. using v8::FunctionTemplate;
  39. using v8::Integer;
  40. using v8::Local;
  41. using v8::Object;
  42. using v8::ObjectTemplate;
  43. using v8::Value;
  44. Nan::Callback *ChannelCredentials::constructor;
  45. Persistent<FunctionTemplate> ChannelCredentials::fun_tpl;
  46. ChannelCredentials::ChannelCredentials(grpc_channel_credentials *credentials)
  47. : wrapped_credentials(credentials) {}
  48. ChannelCredentials::~ChannelCredentials() {
  49. grpc_channel_credentials_release(wrapped_credentials);
  50. }
  51. void ChannelCredentials::Init(Local<Object> exports) {
  52. HandleScope scope;
  53. Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(New);
  54. tpl->SetClassName(Nan::New("ChannelCredentials").ToLocalChecked());
  55. tpl->InstanceTemplate()->SetInternalFieldCount(1);
  56. Nan::SetPrototypeMethod(tpl, "compose", Compose);
  57. fun_tpl.Reset(tpl);
  58. Local<Function> ctr = Nan::GetFunction(tpl).ToLocalChecked();
  59. Nan::Set(
  60. ctr, Nan::New("createSsl").ToLocalChecked(),
  61. Nan::GetFunction(Nan::New<FunctionTemplate>(CreateSsl)).ToLocalChecked());
  62. Nan::Set(ctr, Nan::New("createInsecure").ToLocalChecked(),
  63. Nan::GetFunction(Nan::New<FunctionTemplate>(CreateInsecure))
  64. .ToLocalChecked());
  65. Nan::Set(exports, Nan::New("ChannelCredentials").ToLocalChecked(), ctr);
  66. constructor = new Nan::Callback(ctr);
  67. }
  68. bool ChannelCredentials::HasInstance(Local<Value> val) {
  69. HandleScope scope;
  70. return Nan::New(fun_tpl)->HasInstance(val);
  71. }
  72. Local<Value> ChannelCredentials::WrapStruct(
  73. grpc_channel_credentials *credentials) {
  74. EscapableHandleScope scope;
  75. const int argc = 1;
  76. Local<Value> argv[argc] = {
  77. Nan::New<External>(reinterpret_cast<void *>(credentials))};
  78. MaybeLocal<Object> maybe_instance =
  79. Nan::NewInstance(constructor->GetFunction(), argc, argv);
  80. if (maybe_instance.IsEmpty()) {
  81. return scope.Escape(Nan::Null());
  82. } else {
  83. return scope.Escape(maybe_instance.ToLocalChecked());
  84. }
  85. }
  86. grpc_channel_credentials *ChannelCredentials::GetWrappedCredentials() {
  87. return wrapped_credentials;
  88. }
  89. NAN_METHOD(ChannelCredentials::New) {
  90. if (info.IsConstructCall()) {
  91. if (!info[0]->IsExternal()) {
  92. return Nan::ThrowTypeError(
  93. "ChannelCredentials can only be created with the provided functions");
  94. }
  95. Local<External> ext = info[0].As<External>();
  96. grpc_channel_credentials *creds_value =
  97. reinterpret_cast<grpc_channel_credentials *>(ext->Value());
  98. ChannelCredentials *credentials = new ChannelCredentials(creds_value);
  99. credentials->Wrap(info.This());
  100. info.GetReturnValue().Set(info.This());
  101. return;
  102. } else {
  103. // This should never be called directly
  104. return Nan::ThrowTypeError(
  105. "ChannelCredentials can only be created with the provided functions");
  106. }
  107. }
  108. NAN_METHOD(ChannelCredentials::CreateSsl) {
  109. char *root_certs = NULL;
  110. grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
  111. if (::node::Buffer::HasInstance(info[0])) {
  112. root_certs = ::node::Buffer::Data(info[0]);
  113. } else if (!(info[0]->IsNull() || info[0]->IsUndefined())) {
  114. return Nan::ThrowTypeError("createSsl's first argument must be a Buffer");
  115. }
  116. if (::node::Buffer::HasInstance(info[1])) {
  117. key_cert_pair.private_key = ::node::Buffer::Data(info[1]);
  118. } else if (!(info[1]->IsNull() || info[1]->IsUndefined())) {
  119. return Nan::ThrowTypeError(
  120. "createSSl's second argument must be a Buffer if provided");
  121. }
  122. if (::node::Buffer::HasInstance(info[2])) {
  123. key_cert_pair.cert_chain = ::node::Buffer::Data(info[2]);
  124. } else if (!(info[2]->IsNull() || info[2]->IsUndefined())) {
  125. return Nan::ThrowTypeError(
  126. "createSSl's third argument must be a Buffer if provided");
  127. }
  128. if ((key_cert_pair.private_key == NULL) !=
  129. (key_cert_pair.cert_chain == NULL)) {
  130. return Nan::ThrowError(
  131. "createSsl's second and third arguments must be"
  132. " provided or omitted together");
  133. }
  134. grpc_channel_credentials *creds = grpc_ssl_credentials_create(
  135. root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair,
  136. NULL);
  137. if (creds == NULL) {
  138. info.GetReturnValue().SetNull();
  139. } else {
  140. info.GetReturnValue().Set(WrapStruct(creds));
  141. }
  142. }
  143. NAN_METHOD(ChannelCredentials::Compose) {
  144. if (!ChannelCredentials::HasInstance(info.This())) {
  145. return Nan::ThrowTypeError(
  146. "compose can only be called on ChannelCredentials objects");
  147. }
  148. if (!CallCredentials::HasInstance(info[0])) {
  149. return Nan::ThrowTypeError(
  150. "compose's first argument must be a CallCredentials object");
  151. }
  152. ChannelCredentials *self =
  153. ObjectWrap::Unwrap<ChannelCredentials>(info.This());
  154. if (self->wrapped_credentials == NULL) {
  155. return Nan::ThrowTypeError("Cannot compose insecure credential");
  156. }
  157. CallCredentials *other = ObjectWrap::Unwrap<CallCredentials>(
  158. Nan::To<Object>(info[0]).ToLocalChecked());
  159. grpc_channel_credentials *creds = grpc_composite_channel_credentials_create(
  160. self->wrapped_credentials, other->GetWrappedCredentials(), NULL);
  161. if (creds == NULL) {
  162. info.GetReturnValue().SetNull();
  163. } else {
  164. info.GetReturnValue().Set(WrapStruct(creds));
  165. }
  166. }
  167. NAN_METHOD(ChannelCredentials::CreateInsecure) {
  168. info.GetReturnValue().Set(WrapStruct(NULL));
  169. }
  170. } // namespace node
  171. } // namespace grpc