1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 | #include <queue>
|
20 |
|
21 | #include <nan.h>
|
22 | #include <node.h>
|
23 | #include <v8.h>
|
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"
|
29 |
|
30 |
|
31 | #include "src/core/lib/iomgr/pollset_uv.h"
|
32 |
|
33 | #include "call.h"
|
34 | #include "call_credentials.h"
|
35 | #include "channel.h"
|
36 | #include "channel_credentials.h"
|
37 | #include "completion_queue.h"
|
38 | #include "server.h"
|
39 | #include "server_credentials.h"
|
40 | #include "slice.h"
|
41 | #include "timeval.h"
|
42 |
|
43 | using grpc::node::CreateSliceFromString;
|
44 |
|
45 | using v8::FunctionTemplate;
|
46 | using v8::Local;
|
47 | using v8::Value;
|
48 | using v8::Number;
|
49 | using v8::Object;
|
50 | using v8::Uint32;
|
51 | using v8::String;
|
52 |
|
53 | typedef struct log_args {
|
54 | gpr_log_func_args core_args;
|
55 | gpr_timespec timestamp;
|
56 | } log_args;
|
57 |
|
58 | typedef struct logger_state {
|
59 | Nan::Callback *callback;
|
60 | Nan::AsyncResource *async_resource;
|
61 | std::queue<log_args *> *pending_args;
|
62 | uv_mutex_t mutex;
|
63 | uv_async_t async;
|
64 |
|
65 | bool logger_set;
|
66 | } logger_state;
|
67 |
|
68 | logger_state grpc_logger_state;
|
69 |
|
70 | static char *pem_root_certs = NULL;
|
71 |
|
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);
|
104 | }
|
105 |
|
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(),
|
110 | channel_state);
|
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(),
|
120 | TRANSIENT_FAILURE);
|
121 | Local<Value> FATAL_FAILURE(Nan::New<Uint32, uint32_t>(GRPC_CHANNEL_SHUTDOWN));
|
122 | Nan::Set(channel_state, Nan::New("FATAL_FAILURE").ToLocalChecked(),
|
123 | FATAL_FAILURE);
|
124 | }
|
125 |
|
126 | NAN_METHOD(MetadataKeyIsLegal) {
|
127 | if (!info[0]->IsString()) {
|
128 | return Nan::ThrowTypeError("headerKeyIsLegal's argument must be a string");
|
129 | }
|
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);
|
134 | }
|
135 |
|
136 | NAN_METHOD(MetadataNonbinValueIsLegal) {
|
137 | if (!info[0]->IsString()) {
|
138 | return Nan::ThrowTypeError(
|
139 | "metadataNonbinValueIsLegal's argument must be a string");
|
140 | }
|
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);
|
146 | }
|
147 |
|
148 | NAN_METHOD(MetadataKeyIsBinary) {
|
149 | if (!info[0]->IsString()) {
|
150 | return Nan::ThrowTypeError(
|
151 | "metadataKeyIsLegal's argument must be a string");
|
152 | }
|
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);
|
157 | }
|
158 |
|
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;
|
164 | } else {
|
165 | return GRPC_SSL_ROOTS_OVERRIDE_OK;
|
166 | }
|
167 | }
|
168 |
|
169 |
|
170 |
|
171 | NAN_METHOD(SetDefaultRootsPem) {
|
172 | if (!info[0]->IsString()) {
|
173 | return Nan::ThrowTypeError(
|
174 | "setDefaultRootsPem's argument must be a string");
|
175 | }
|
176 | Nan::Utf8String utf8_roots(info[0]);
|
177 | size_t length = static_cast<size_t>(utf8_roots.length());
|
178 | if (length > 0) {
|
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);
|
182 | }
|
183 | }
|
184 |
|
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 |
|
192 | while (!args.empty()) {
|
193 | log_args *arg = args.front();
|
194 | args.pop();
|
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))
|
199 | .ToLocalChecked();
|
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))
|
203 | .ToLocalChecked();
|
204 | const int argc = 5;
|
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;
|
208 | delete arg;
|
209 | }
|
210 | }
|
211 |
|
212 | void node_log_func(gpr_log_func_args *args) {
|
213 |
|
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);
|
221 |
|
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);
|
225 |
|
226 | uv_async_send(&grpc_logger_state.async);
|
227 | }
|
228 |
|
229 | void init_logger() {
|
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;
|
237 |
|
238 | gpr_log_verbosity_init();
|
239 | }
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 | NAN_METHOD(SetDefaultLoggerCallback) {
|
247 | if (!info[0]->IsFunction()) {
|
248 | return Nan::ThrowTypeError(
|
249 | "setDefaultLoggerCallback's argument must be a function");
|
250 | }
|
251 | if (!grpc_logger_state.logger_set) {
|
252 | gpr_set_log_function(node_log_func);
|
253 | grpc_logger_state.logger_set = true;
|
254 | }
|
255 | grpc_logger_state.callback = new Nan::Callback(info[0].As<v8::Function>());
|
256 | grpc_logger_state.async_resource = new Nan::AsyncResource("grpc:logger");
|
257 | }
|
258 |
|
259 | NAN_METHOD(SetLogVerbosity) {
|
260 | if (!info[0]->IsUint32()) {
|
261 | return Nan::ThrowTypeError("setLogVerbosity's argument must be a number");
|
262 | }
|
263 | gpr_log_severity severity =
|
264 | static_cast<gpr_log_severity>(Nan::To<uint32_t>(info[0]).FromJust());
|
265 | gpr_set_log_verbosity(severity);
|
266 | }
|
267 |
|
268 | NAN_METHOD(ForcePoll) {
|
269 | grpc::node::CompletionQueueForcePoll();
|
270 | }
|
271 |
|
272 | void init(Local<Object> exports) {
|
273 | Nan::HandleScope scope;
|
274 | grpc_init();
|
275 | grpc_set_ssl_roots_override_callback(get_ssl_roots_override);
|
276 | init_logger();
|
277 |
|
278 | InitOpTypeConstants(exports);
|
279 | InitConnectivityStateConstants(exports);
|
280 |
|
281 | grpc_pollset_work_run_loop = 0;
|
282 |
|
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);
|
289 |
|
290 | grpc::node::CompletionQueueInit(exports);
|
291 |
|
292 |
|
293 | Nan::Set(exports, Nan::New("metadataKeyIsLegal").ToLocalChecked(),
|
294 | Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsLegal))
|
295 | .ToLocalChecked());
|
296 | Nan::Set(
|
297 | exports, Nan::New("metadataNonbinValueIsLegal").ToLocalChecked(),
|
298 | Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataNonbinValueIsLegal))
|
299 | .ToLocalChecked());
|
300 | Nan::Set(exports, Nan::New("metadataKeyIsBinary").ToLocalChecked(),
|
301 | Nan::GetFunction(Nan::New<FunctionTemplate>(MetadataKeyIsBinary))
|
302 | .ToLocalChecked());
|
303 | Nan::Set(exports, Nan::New("setDefaultRootsPem").ToLocalChecked(),
|
304 | Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultRootsPem))
|
305 | .ToLocalChecked());
|
306 | Nan::Set(
|
307 | exports, Nan::New("setDefaultLoggerCallback").ToLocalChecked(),
|
308 | Nan::GetFunction(Nan::New<FunctionTemplate>(SetDefaultLoggerCallback))
|
309 | .ToLocalChecked());
|
310 | Nan::Set(exports, Nan::New("setLogVerbosity").ToLocalChecked(),
|
311 | Nan::GetFunction(Nan::New<FunctionTemplate>(SetLogVerbosity))
|
312 | .ToLocalChecked());
|
313 | Nan::Set(exports, Nan::New("forcePoll").ToLocalChecked(),
|
314 | Nan::GetFunction(Nan::New<FunctionTemplate>(ForcePoll))
|
315 | .ToLocalChecked());
|
316 | }
|
317 |
|
318 | NODE_MODULE(grpc_node, init)
|