3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
24 #include "grpc/grpc.h"
25 #include "grpc/grpc_security.h"
26 #include "grpc/support/alloc.h"
27 #include "grpc/support/log.h"
28 #include "grpc/support/time.h"
30 // TODO(murgatroid99): Remove this when the endpoint API becomes public
31 #include "src/core/lib/iomgr/pollset_uv.h"
34 #include "call_credentials.h"
36 #include "channel_credentials.h"
37 #include "completion_queue.h"
39 #include "server_credentials.h"
43 using grpc::node::CreateSliceFromString;
45 using v8::FunctionTemplate;
53 typedef struct log_args {
54 gpr_log_func_args core_args;
55 gpr_timespec timestamp;
58 typedef struct logger_state {
59 Nan::Callback *callback;
60 Nan::AsyncResource *async_resource;
61 std::queue<log_args *> *pending_args;
64 // Indicates that a logger has been set
68 logger_state grpc_logger_state;
70 static char *pem_root_certs = NULL;
72 void InitOpTypeConstants(Local<Object> exports) {
73 Nan::HandleScope scope;
74 Local<Object> op_type = Nan::New<Object>();
75 Nan::Set(exports, Nan::New("opType").ToLocalChecked(), op_type);
76 Local<Value> SEND_INITIAL_METADATA(
77 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_INITIAL_METADATA));
78 Nan::Set(op_type, Nan::New("SEND_INITIAL_METADATA").ToLocalChecked(),
79 SEND_INITIAL_METADATA);
80 Local<Value> SEND_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_MESSAGE));
81 Nan::Set(op_type, Nan::New("SEND_MESSAGE").ToLocalChecked(), SEND_MESSAGE);
82 Local<Value> SEND_CLOSE_FROM_CLIENT(
83 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_CLOSE_FROM_CLIENT));
84 Nan::Set(op_type, Nan::New("SEND_CLOSE_FROM_CLIENT").ToLocalChecked(),
85 SEND_CLOSE_FROM_CLIENT);
86 Local<Value> SEND_STATUS_FROM_SERVER(
87 Nan::New<Uint32, uint32_t>(GRPC_OP_SEND_STATUS_FROM_SERVER));
88 Nan::Set(op_type, Nan::New("SEND_STATUS_FROM_SERVER").ToLocalChecked(),
89 SEND_STATUS_FROM_SERVER);
90 Local<Value> RECV_INITIAL_METADATA(
91 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_INITIAL_METADATA));
92 Nan::Set(op_type, Nan::New("RECV_INITIAL_METADATA").ToLocalChecked(),
93 RECV_INITIAL_METADATA);
94 Local<Value> RECV_MESSAGE(Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_MESSAGE));
95 Nan::Set(op_type, Nan::New("RECV_MESSAGE").ToLocalChecked(), RECV_MESSAGE);
96 Local<Value> RECV_STATUS_ON_CLIENT(
97 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_STATUS_ON_CLIENT));
98 Nan::Set(op_type, Nan::New("RECV_STATUS_ON_CLIENT").ToLocalChecked(),
99 RECV_STATUS_ON_CLIENT);
100 Local<Value> RECV_CLOSE_ON_SERVER(
101 Nan::New<Uint32, uint32_t>(GRPC_OP_RECV_CLOSE_ON_SERVER));
102 Nan::Set(op_type, Nan::New("RECV_CLOSE_ON_SERVER").ToLocalChecked(),
103 RECV_CLOSE_ON_SERVER);
106 void InitConnectivityStateConstants(Local<Object> exports) {
107 Nan::HandleScope scope;
108 Local<Object> channel_state = Nan::New<Object>();
109 Nan::Set(exports, Nan::New("connectivityState").ToLocalChecked(),
111 Local<Value> IDLE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_IDLE));
112 Nan::Set(channel_state, Nan::New("IDLE").ToLocalChecked(), IDLE);
113 Local<Value> CONNECTING(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_CONNECTING));
114 Nan::Set(channel_state, Nan::New("CONNECTING").ToLocalChecked(), CONNECTING);
115 Local<Value> READY(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_READY));
116 Nan::Set(channel_state, Nan::New("READY").ToLocalChecked(), READY);
117 Local<Value> TRANSIENT_FAILURE(
118 Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_TRANSIENT_FAILURE));
119 Nan::Set(channel_state, Nan::New("TRANSIENT_FAILURE").ToLocalChecked(),
121 Local<Value> FATAL_FAILURE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_SHUTDOWN));
122 Nan::Set(channel_state, Nan::New("FATAL_FAILURE").ToLocalChecked(),
126 NAN_METHOD(MetadataKeyIsLegal) {
127 if (!info[0]->IsString()) {
128 return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string");
130 Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
131 grpc_slice slice = CreateSliceFromString(key);
132 info.GetReturnValue().Set(static_cast<bool>(grpc_header_key_is_legal(slice)));
133 grpc_slice_unref(slice);
136 NAN_METHOD(MetadataNonbinValueIsLegal) {
137 if (!info[0]->IsString()) {
138 return Nan::ThrowTypeError(
139 "metadataNonbinValueIsLegal's argument must be a string");
141 Local<String> value = Nan::To<String>(info[0]).ToLocalChecked();
142 grpc_slice slice = CreateSliceFromString(value);
143 info.GetReturnValue().Set(
144 static_cast<bool>(grpc_header_nonbin_value_is_legal(slice)));
145 grpc_slice_unref(slice);
148 NAN_METHOD(MetadataKeyIsBinary) {
149 if (!info[0]->IsString()) {
150 return Nan::ThrowTypeError(
151 "metadataKeyIsLegal's argument must be a string");
153 Local<String> key = Nan::To<String>(info[0]).ToLocalChecked();
154 grpc_slice slice = CreateSliceFromString(key);
155 info.GetReturnValue().Set(static_cast<bool>(grpc_is_binary_header(slice)));
156 grpc_slice_unref(slice);
159 static grpc_ssl_roots_override_result get_ssl_roots_override(
160 char **pem_root_certs_ptr) {
161 *pem_root_certs_ptr = pem_root_certs;
162 if (pem_root_certs == NULL) {
163 return GRPC_SSL_ROOTS_OVERRIDE_FAIL;
165 return GRPC_SSL_ROOTS_OVERRIDE_OK;
169 /* This should only be called once, and only before creating any
170 *ServerCredentials */
171 NAN_METHOD(SetDefaultRootsPem) {
172 if (!info[0]->IsString()) {
173 return Nan::ThrowTypeError(
174 "setDefaultRootsPem's argument must be a string");
176 Nan::Utf8String utf8_roots(info[0]);
177 size_t length = static_cast<size_t>(utf8_roots.length());
179 const char *data = *utf8_roots;
180 pem_root_certs = (char *)gpr_malloc((length + 1) * sizeof(char));
181 memcpy(pem_root_certs, data, length + 1);
185 NAUV_WORK_CB(LogMessagesCallback) {
186 Nan::HandleScope scope;
187 std::queue<log_args *> args;
188 uv_mutex_lock(&grpc_logger_state.mutex);
189 grpc_logger_state.pending_args->swap(args);
190 uv_mutex_unlock(&grpc_logger_state.mutex);
191 /* Call the callback with each log message */
192 while (!args.empty()) {
193 log_args *arg = args.front();
195 Local<Value> file = Nan::New(arg->core_args.file).ToLocalChecked();
196 Local<Value> line = Nan::New<Uint32, uint32_t>(arg->core_args.line);
197 Local<Value> severity =
198 Nan::New(gpr_log_severity_string(arg->core_args.severity))
200 Local<Value> message = Nan::New(arg->core_args.message).ToLocalChecked();
201 Local<Value> timestamp =
202 Nan::New<v8::Date>(grpc::node::TimespecToMilliseconds(arg->timestamp))
205 Local<Value> argv[argc] = {file, line, severity, message, timestamp};
206 grpc_logger_state.callback->Call(argc, argv, grpc_logger_state.async_resource);
207 delete[] arg->core_args.message;
212 void node_log_func(gpr_log_func_args *args) {
213 // TODO(mlumish): Use the core's log formatter when it becomes available
214 log_args *args_copy = new log_args;
215 size_t message_len = strlen(args->message) + 1;
216 char *message = new char[message_len];
217 memcpy(message, args->message, message_len);
218 memcpy(&args_copy->core_args, args, sizeof(gpr_log_func_args));
219 args_copy->core_args.message = message;
220 args_copy->timestamp = gpr_now(GPR_CLOCK_REALTIME);
222 uv_mutex_lock(&grpc_logger_state.mutex);
223 grpc_logger_state.pending_args->push(args_copy);
224 uv_mutex_unlock(&grpc_logger_state.mutex);
226 uv_async_send(&grpc_logger_state.async);
230 memset(&grpc_logger_state, 0, sizeof(logger_state));
231 grpc_logger_state.pending_args = new std::queue<log_args *>();
232 uv_mutex_init(&grpc_logger_state.mutex);
233 uv_async_init(uv_default_loop(), &grpc_logger_state.async,
234 LogMessagesCallback);
235 uv_unref((uv_handle_t *)&grpc_logger_state.async);
236 grpc_logger_state.logger_set = false;
238 gpr_log_verbosity_init();
241 /* This registers a JavaScript logger for messages from the gRPC core. Because
242 that handler has to be run in the context of the JavaScript event loop, it
243 will be run asynchronously. To minimize the problems that could cause for
244 debugging, we leave core to do its default synchronous logging until a
245 JavaScript logger is set */
246 NAN_METHOD(SetDefaultLoggerCallback) {
247 if (!info[0]->IsFunction()) {
248 return Nan::ThrowTypeError(
249 "setDefaultLoggerCallback's argument must be a function");
251 if (!grpc_logger_state.logger_set) {
252 gpr_set_log_function(node_log_func);
253 grpc_logger_state.logger_set = true;
255 grpc_logger_state.callback = new Nan::Callback(info[0].As<v8::Function>());
256 grpc_logger_state.async_resource = new Nan::AsyncResource("grpc:logger");
259 NAN_METHOD(SetLogVerbosity) {
260 if (!info[0]->IsUint32()) {
261 return Nan::ThrowTypeError("setLogVerbosity's argument must be a number");
263 gpr_log_severity severity =
264 static_cast<gpr_log_severity>(Nan::To<uint32_t>(info[0]).FromJust());
265 gpr_set_log_verbosity(severity);
268 NAN_METHOD(ForcePoll) {
269 grpc::node::CompletionQueueForcePoll();
272 void init(Local<Object> exports) {
273 Nan::HandleScope scope;
275 grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
278 InitOpTypeConstants(exports);
279 InitConnectivityStateConstants(exports);
281 grpc_pollset_work_run_loop = 0;
283 grpc::node::Call::Init(exports);
284 grpc::node::CallCredentials::Init(exports);
285 grpc::node::Channel::Init(exports);
286 grpc::node::ChannelCredentials::Init(exports);
287 grpc::node::Server::Init(exports);
288 grpc::node::ServerCredentials::Init(exports);
290 grpc::node::CompletionQueueInit(exports);
292 // Attach a few utility functions directly to the module
293 Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(),
294 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsLegal))
297 exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(),
298 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataNonbinValueIsLegal))
300 Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(),
301 Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsBinary))
303 Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(),
304 Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultRootsPem))
307 exports, Nan::New("setDefaultLoggerCallback").ToLocalChecked(),
308 Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultLoggerCallback))
310 Nan::Set(exports, Nan::New("setLogVerbosity").ToLocalChecked(),
311 Nan::GetFunction(Nan::New<FunctionTemplate>(SetLogVerbosity))
313 Nan::Set(exports, Nan::New("forcePoll").ToLocalChecked(),
314 Nan::GetFunction(Nan::New<FunctionTemplate>(ForcePoll))
318 NODE_MODULE(grpc_node, init)