blob: 11ed0838bc785a8070193772540090bb935e3670 [file] [log] [blame]
murgatroid99749666e2015-01-12 18:25:58 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
murgatroid99749666e2015-01-12 18:25:58 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
murgatroid99749666e2015-01-12 18:25:58 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
murgatroid99749666e2015-01-12 18:25:58 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
murgatroid99749666e2015-01-12 18:25:58 -080016 *
17 */
18
murgatroid99c6bbc472016-12-06 11:00:39 -080019#include <queue>
murgatroid999b9708a2016-06-01 11:42:20 -070020
murgatroid99e5061512015-01-12 18:14:35 -080021#include <nan.h>
Craig Tiller5b1c5f22017-04-19 09:52:18 -070022#include <node.h>
murgatroid99e5061512015-01-12 18:14:35 -080023#include <v8.h>
24#include "grpc/grpc.h"
murgatroid996f607662016-04-27 16:38:33 -070025#include "grpc/grpc_security.h"
26#include "grpc/support/alloc.h"
murgatroid999b9708a2016-06-01 11:42:20 -070027#include "grpc/support/log.h"
murgatroid991d2f2892016-06-02 14:33:22 -070028#include "grpc/support/time.h"
murgatroid99e5061512015-01-12 18:14:35 -080029
Michael Lumish197d87e2016-10-07 14:49:05 -070030// TODO(murgatroid99): Remove this when the endpoint API becomes public
Michael Lumish197d87e2016-10-07 14:49:05 -070031extern "C" {
murgatroid992c287ca2016-10-07 09:55:35 -070032#include "src/core/lib/iomgr/pollset_uv.h"
Michael Lumish197d87e2016-10-07 14:49:05 -070033}
murgatroid992c287ca2016-10-07 09:55:35 -070034
murgatroid99e5061512015-01-12 18:14:35 -080035#include "call.h"
murgatroid995f709ca2015-09-30 14:22:54 -070036#include "call_credentials.h"
murgatroid99e5061512015-01-12 18:14:35 -080037#include "channel.h"
murgatroid995f709ca2015-09-30 14:22:54 -070038#include "channel_credentials.h"
Craig Tiller5b1c5f22017-04-19 09:52:18 -070039#include "completion_queue.h"
murgatroid99e5061512015-01-12 18:14:35 -080040#include "server.h"
murgatroid99e5061512015-01-12 18:14:35 -080041#include "server_credentials.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080042#include "slice.h"
murgatroid991d2f2892016-06-02 14:33:22 -070043#include "timeval.h"
murgatroid99e5061512015-01-12 18:14:35 -080044
Craig Tiller7c70b6c2017-01-23 07:48:42 -080045using grpc::node::CreateSliceFromString;
46
murgatroid99f776f902016-01-07 10:03:18 -080047using v8::FunctionTemplate;
murgatroid992b097832015-09-17 13:56:25 -070048using v8::Local;
murgatroid99e5061512015-01-12 18:14:35 -080049using v8::Value;
murgatroid999b9708a2016-06-01 11:42:20 -070050using v8::Number;
murgatroid99e5061512015-01-12 18:14:35 -080051using v8::Object;
52using v8::Uint32;
53using v8::String;
54
murgatroid991d2f2892016-06-02 14:33:22 -070055typedef struct log_args {
56 gpr_log_func_args core_args;
57 gpr_timespec timestamp;
58} log_args;
59
murgatroid999b9708a2016-06-01 11:42:20 -070060typedef struct logger_state {
61 Nan::Callback *callback;
murgatroid99c6bbc472016-12-06 11:00:39 -080062 std::queue<log_args *> *pending_args;
murgatroid999b9708a2016-06-01 11:42:20 -070063 uv_mutex_t mutex;
64 uv_async_t async;
65 // Indicates that a logger has been set
66 bool logger_set;
67} logger_state;
68
69logger_state grpc_logger_state;
70
murgatroid996f607662016-04-27 16:38:33 -070071static char *pem_root_certs = NULL;
72
murgatroid992b097832015-09-17 13:56:25 -070073void InitOpTypeConstants(Local<Object> exports) {
74 Nan::HandleScope scope;
75 Local<Object> op_type = Nan::New<Object>();
76 Nan::Set(exports, Nan::New("opType").ToLocalChecked(), op_type);
77 Local<Value> SEND_INITIAL_METADATA(
78 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_INITIAL_METADATA));
79 Nan::Set(op_type, Nan::New("SEND_INITIAL_METADATA").ToLocalChecked(),
80 SEND_INITIAL_METADATA);
Craig Tiller5b1c5f22017-04-19 09:52:18 -070081 Local<Value> SEND_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_MESSAGE));
murgatroid992b097832015-09-17 13:56:25 -070082 Nan::Set(op_type, Nan::New("SEND_MESSAGE").ToLocalChecked(), SEND_MESSAGE);
83 Local<Value> SEND_CLOSE_FROM_CLIENT(
84 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_CLOSE_FROM_CLIENT));
85 Nan::Set(op_type, Nan::New("SEND_CLOSE_FROM_CLIENT").ToLocalChecked(),
86 SEND_CLOSE_FROM_CLIENT);
87 Local<Value> SEND_STATUS_FROM_SERVER(
88 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_STATUS_FROM_SERVER));
89 Nan::Set(op_type, Nan::New("SEND_STATUS_FROM_SERVER").ToLocalChecked(),
90 SEND_STATUS_FROM_SERVER);
91 Local<Value> RECV_INITIAL_METADATA(
92 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_INITIAL_METADATA));
93 Nan::Set(op_type, Nan::New("RECV_INITIAL_METADATA").ToLocalChecked(),
94 RECV_INITIAL_METADATA);
Craig Tiller5b1c5f22017-04-19 09:52:18 -070095 Local<Value> RECV_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_MESSAGE));
murgatroid992b097832015-09-17 13:56:25 -070096 Nan::Set(op_type, Nan::New("RECV_MESSAGE").ToLocalChecked(), RECV_MESSAGE);
97 Local<Value> RECV_STATUS_ON_CLIENT(
98 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_STATUS_ON_CLIENT));
99 Nan::Set(op_type, Nan::New("RECV_STATUS_ON_CLIENT").ToLocalChecked(),
100 RECV_STATUS_ON_CLIENT);
101 Local<Value> RECV_CLOSE_ON_SERVER(
102 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_CLOSE_ON_SERVER));
103 Nan::Set(op_type, Nan::New("RECV_CLOSE_ON_SERVER").ToLocalChecked(),
104 RECV_CLOSE_ON_SERVER);
murgatroid99a9b99c92015-02-05 17:42:01 -0800105}
106
murgatroid992b097832015-09-17 13:56:25 -0700107void InitConnectivityStateConstants(Local<Object> exports) {
108 Nan::HandleScope scope;
109 Local<Object> channel_state = Nan::New<Object>();
110 Nan::Set(exports, Nan::New("connectivityState").ToLocalChecked(),
111 channel_state);
112 Local<Value> IDLE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_IDLE));
113 Nan::Set(channel_state, Nan::New("IDLE").ToLocalChecked(), IDLE);
114 Local<Value> CONNECTING(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_CONNECTING));
115 Nan::Set(channel_state, Nan::New("CONNECTING").ToLocalChecked(), CONNECTING);
116 Local<Value> READY(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_READY));
117 Nan::Set(channel_state, Nan::New("READY").ToLocalChecked(), READY);
118 Local<Value> TRANSIENT_FAILURE(
119 Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_TRANSIENT_FAILURE));
120 Nan::Set(channel_state, Nan::New("TRANSIENT_FAILURE").ToLocalChecked(),
121 TRANSIENT_FAILURE);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700122 Local<Value> FATAL_FAILURE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_SHUTDOWN));
murgatroid992b097832015-09-17 13:56:25 -0700123 Nan::Set(channel_state, Nan::New("FATAL_FAILURE").ToLocalChecked(),
124 FATAL_FAILURE);
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700125}
126
murgatroid99f776f902016-01-07 10:03:18 -0800127NAN_METHOD(MetadataKeyIsLegal) {
128 if (!info[0]->IsString()) {
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700129 return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string");
murgatroid99f776f902016-01-07 10:03:18 -0800130 }
131 Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
murgatroid99753b0542017-04-03 15:31:53 -0700132 grpc_slice slice = CreateSliceFromString(key);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700133 info.GetReturnValue().Set(static_cast<bool>(grpc_header_key_is_legal(slice)));
murgatroid99753b0542017-04-03 15:31:53 -0700134 grpc_slice_unref(slice);
murgatroid99f776f902016-01-07 10:03:18 -0800135}
136
137NAN_METHOD(MetadataNonbinValueIsLegal) {
138 if (!info[0]->IsString()) {
139 return Nan::ThrowTypeError(
140 "metadataNonbinValueIsLegal's argument must be a string");
141 }
142 Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
murgatroid99753b0542017-04-03 15:31:53 -0700143 grpc_slice slice = CreateSliceFromString(value);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700144 info.GetReturnValue().Set(
145 static_cast<bool>(grpc_header_nonbin_value_is_legal(slice)));
murgatroid99753b0542017-04-03 15:31:53 -0700146 grpc_slice_unref(slice);
murgatroid99f776f902016-01-07 10:03:18 -0800147}
148
149NAN_METHOD(MetadataKeyIsBinary) {
150 if (!info[0]->IsString()) {
151 return Nan::ThrowTypeError(
152 "metadataKeyIsLegal's argument must be a string");
153 }
154 Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
murgatroid99753b0542017-04-03 15:31:53 -0700155 grpc_slice slice = CreateSliceFromString(key);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700156 info.GetReturnValue().Set(static_cast<bool>(grpc_is_binary_header(slice)));
murgatroid99753b0542017-04-03 15:31:53 -0700157 grpc_slice_unref(slice);
murgatroid99f776f902016-01-07 10:03:18 -0800158}
159
murgatroid996f607662016-04-27 16:38:33 -0700160static grpc_ssl_roots_override_result get_ssl_roots_override(
161 char **pem_root_certs_ptr) {
162 *pem_root_certs_ptr = pem_root_certs;
163 if (pem_root_certs == NULL) {
164 return GRPC_SSL_ROOTS_OVERRIDE_FAIL;
165 } else {
166 return GRPC_SSL_ROOTS_OVERRIDE_OK;
167 }
168}
169
170/* This should only be called once, and only before creating any
171 *ServerCredentials */
172NAN_METHOD(SetDefaultRootsPem) {
173 if (!info[0]->IsString()) {
174 return Nan::ThrowTypeError(
175 "setDefaultRootsPem's argument must be a string");
176 }
177 Nan::Utf8String utf8_roots(info[0]);
178 size_t length = static_cast<size_t>(utf8_roots.length());
179 if (length > 0) {
180 const char *data = *utf8_roots;
181 pem_root_certs = (char *)gpr_malloc((length + 1) * sizeof(char));
182 memcpy(pem_root_certs, data, length + 1);
183 }
184}
185
murgatroid999b9708a2016-06-01 11:42:20 -0700186NAUV_WORK_CB(LogMessagesCallback) {
187 Nan::HandleScope scope;
murgatroid99c6bbc472016-12-06 11:00:39 -0800188 std::queue<log_args *> args;
murgatroid999b9708a2016-06-01 11:42:20 -0700189 uv_mutex_lock(&grpc_logger_state.mutex);
murgatroid99c6bbc472016-12-06 11:00:39 -0800190 grpc_logger_state.pending_args->swap(args);
murgatroid999b9708a2016-06-01 11:42:20 -0700191 uv_mutex_unlock(&grpc_logger_state.mutex);
192 /* Call the callback with each log message */
193 while (!args.empty()) {
murgatroid991d2f2892016-06-02 14:33:22 -0700194 log_args *arg = args.front();
murgatroid99c6bbc472016-12-06 11:00:39 -0800195 args.pop();
murgatroid991d2f2892016-06-02 14:33:22 -0700196 Local<Value> file = Nan::New(arg->core_args.file).ToLocalChecked();
197 Local<Value> line = Nan::New<Uint32, uint32_t>(arg->core_args.line);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700198 Local<Value> severity =
199 Nan::New(gpr_log_severity_string(arg->core_args.severity))
200 .ToLocalChecked();
murgatroid991d2f2892016-06-02 14:33:22 -0700201 Local<Value> message = Nan::New(arg->core_args.message).ToLocalChecked();
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700202 Local<Value> timestamp =
203 Nan::New<v8::Date>(grpc::node::TimespecToMilliseconds(arg->timestamp))
204 .ToLocalChecked();
murgatroid991d2f2892016-06-02 14:33:22 -0700205 const int argc = 5;
206 Local<Value> argv[argc] = {file, line, severity, message, timestamp};
murgatroid999b9708a2016-06-01 11:42:20 -0700207 grpc_logger_state.callback->Call(argc, argv);
murgatroid991d2f2892016-06-02 14:33:22 -0700208 delete[] arg->core_args.message;
murgatroid999b9708a2016-06-01 11:42:20 -0700209 delete arg;
210 }
211}
212
213void node_log_func(gpr_log_func_args *args) {
214 // TODO(mlumish): Use the core's log formatter when it becomes available
murgatroid991d2f2892016-06-02 14:33:22 -0700215 log_args *args_copy = new log_args;
murgatroid999b9708a2016-06-01 11:42:20 -0700216 size_t message_len = strlen(args->message) + 1;
217 char *message = new char[message_len];
218 memcpy(message, args->message, message_len);
murgatroid991d2f2892016-06-02 14:33:22 -0700219 memcpy(&args_copy->core_args, args, sizeof(gpr_log_func_args));
220 args_copy->core_args.message = message;
221 args_copy->timestamp = gpr_now(GPR_CLOCK_REALTIME);
murgatroid999b9708a2016-06-01 11:42:20 -0700222
223 uv_mutex_lock(&grpc_logger_state.mutex);
murgatroid99c6bbc472016-12-06 11:00:39 -0800224 grpc_logger_state.pending_args->push(args_copy);
murgatroid999b9708a2016-06-01 11:42:20 -0700225 uv_mutex_unlock(&grpc_logger_state.mutex);
226
227 uv_async_send(&grpc_logger_state.async);
228}
229
230void init_logger() {
231 memset(&grpc_logger_state, 0, sizeof(logger_state));
murgatroid99c6bbc472016-12-06 11:00:39 -0800232 grpc_logger_state.pending_args = new std::queue<log_args *>();
murgatroid999b9708a2016-06-01 11:42:20 -0700233 uv_mutex_init(&grpc_logger_state.mutex);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700234 uv_async_init(uv_default_loop(), &grpc_logger_state.async,
murgatroid999b9708a2016-06-01 11:42:20 -0700235 LogMessagesCallback);
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700236 uv_unref((uv_handle_t *)&grpc_logger_state.async);
murgatroid999b9708a2016-06-01 11:42:20 -0700237 grpc_logger_state.logger_set = false;
238
239 gpr_log_verbosity_init();
240}
241
242/* This registers a JavaScript logger for messages from the gRPC core. Because
243 that handler has to be run in the context of the JavaScript event loop, it
244 will be run asynchronously. To minimize the problems that could cause for
245 debugging, we leave core to do its default synchronous logging until a
246 JavaScript logger is set */
247NAN_METHOD(SetDefaultLoggerCallback) {
248 if (!info[0]->IsFunction()) {
249 return Nan::ThrowTypeError(
250 "setDefaultLoggerCallback's argument must be a function");
251 }
252 if (!grpc_logger_state.logger_set) {
253 gpr_set_log_function(node_log_func);
254 grpc_logger_state.logger_set = true;
255 }
256 grpc_logger_state.callback = new Nan::Callback(info[0].As<v8::Function>());
257}
258
259NAN_METHOD(SetLogVerbosity) {
260 if (!info[0]->IsUint32()) {
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700261 return Nan::ThrowTypeError("setLogVerbosity's argument must be a number");
murgatroid999b9708a2016-06-01 11:42:20 -0700262 }
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700263 gpr_log_severity severity =
264 static_cast<gpr_log_severity>(Nan::To<uint32_t>(info[0]).FromJust());
murgatroid999b9708a2016-06-01 11:42:20 -0700265 gpr_set_log_verbosity(severity);
266}
267
murgatroid992b097832015-09-17 13:56:25 -0700268void init(Local<Object> exports) {
269 Nan::HandleScope scope;
murgatroid99e5061512015-01-12 18:14:35 -0800270 grpc_init();
murgatroid996f607662016-04-27 16:38:33 -0700271 grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
murgatroid999b9708a2016-06-01 11:42:20 -0700272 init_logger();
273
murgatroid99a9b99c92015-02-05 17:42:01 -0800274 InitOpTypeConstants(exports);
murgatroid99c7f4d4f2015-07-28 15:18:57 -0700275 InitConnectivityStateConstants(exports);
murgatroid99e5061512015-01-12 18:14:35 -0800276
murgatroid992c287ca2016-10-07 09:55:35 -0700277 grpc_pollset_work_run_loop = 0;
murgatroid999030c812016-09-16 13:25:08 -0700278
murgatroid99e5061512015-01-12 18:14:35 -0800279 grpc::node::Call::Init(exports);
murgatroid995f709ca2015-09-30 14:22:54 -0700280 grpc::node::CallCredentials::Init(exports);
murgatroid99e5061512015-01-12 18:14:35 -0800281 grpc::node::Channel::Init(exports);
murgatroid995f709ca2015-09-30 14:22:54 -0700282 grpc::node::ChannelCredentials::Init(exports);
murgatroid99e5061512015-01-12 18:14:35 -0800283 grpc::node::Server::Init(exports);
murgatroid99e5061512015-01-12 18:14:35 -0800284 grpc::node::ServerCredentials::Init(exports);
murgatroid99f776f902016-01-07 10:03:18 -0800285
murgatroid999030c812016-09-16 13:25:08 -0700286 grpc::node::CompletionQueueInit(exports);
287
murgatroid99f776f902016-01-07 10:03:18 -0800288 // Attach a few utility functions directly to the module
289 Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(),
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700290 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsLegal))
291 .ToLocalChecked());
292 Nan::Set(
293 exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(),
294 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataNonbinValueIsLegal))
295 .ToLocalChecked());
murgatroid99f776f902016-01-07 10:03:18 -0800296 Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(),
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700297 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsBinary))
298 .ToLocalChecked());
murgatroid996f607662016-04-27 16:38:33 -0700299 Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(),
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700300 Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultRootsPem))
301 .ToLocalChecked());
302 Nan::Set(
303 exports, Nan::New("setDefaultLoggerCallback").ToLocalChecked(),
304 Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultLoggerCallback))
305 .ToLocalChecked());
murgatroid999b9708a2016-06-01 11:42:20 -0700306 Nan::Set(exports, Nan::New("setLogVerbosity").ToLocalChecked(),
Craig Tiller5b1c5f22017-04-19 09:52:18 -0700307 Nan::GetFunction(Nan::New<FunctionTemplate>(SetLogVerbosity))
308 .ToLocalChecked());
murgatroid99e5061512015-01-12 18:14:35 -0800309}
310
murgatroid99196188f2015-10-02 12:49:03 -0700311NODE_MODULE(grpc_node, init)