@openziti/ziti-sdk-nodejs 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/build.yml +220 -0
- package/.github/workflows/codeql-analysis.yml +71 -0
- package/.github/workflows/mattermost-ziti-webhook.yml +26 -0
- package/.gitmodules +4 -0
- package/.travis.yml-obsolete +99 -0
- package/CODE_OF_CONDUCT.md +17 -0
- package/CONTRIBUTING.md +6 -0
- package/LICENSE +201 -0
- package/README.md +155 -0
- package/appveyor.yml-obsolete +32 -0
- package/binding.gyp +227 -0
- package/lib/index.js +17 -0
- package/lib/ziti.js +40 -0
- package/package.json +56 -0
- package/scripts/build-appveyor.bat +198 -0
- package/scripts/install_node.sh +99 -0
- package/scripts/validate_tag.sh +24 -0
- package/src/Ziti_https_request.c +960 -0
- package/src/Ziti_https_request_data.c +250 -0
- package/src/Ziti_https_request_end.c +79 -0
- package/src/stack_traces.c +334 -0
- package/src/utils.c +108 -0
- package/src/utils.h +85 -0
- package/src/ziti-add-on.c +88 -0
- package/src/ziti-nodejs.h +209 -0
- package/src/ziti_close.c +79 -0
- package/src/ziti_dial.c +375 -0
- package/src/ziti_enroll.c +245 -0
- package/src/ziti_hello.c +52 -0
- package/src/ziti_init.c +315 -0
- package/src/ziti_service_available.c +222 -0
- package/src/ziti_shutdown.c +47 -0
- package/src/ziti_websocket_connect.c +458 -0
- package/src/ziti_websocket_write.c +235 -0
- package/src/ziti_write.c +223 -0
- package/tests/enroll-test.js +38 -0
- package/tests/hello.js +12 -0
- package/tests/https-test.js +206 -0
- package/tests/mattermost-test.js +124 -0
- package/tests/websocket-test.js +119 -0
- package/ziti.js +1 -0
- package/ziti.png +0 -0
package/src/ziti_init.c
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2019-2020 Netfoundry, Inc.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include "ziti-nodejs.h"
|
|
18
|
+
|
|
19
|
+
ziti_context ztx = NULL;
|
|
20
|
+
uv_loop_t *loop = NULL;
|
|
21
|
+
|
|
22
|
+
uv_thread_t thread;
|
|
23
|
+
uv_async_t async;
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
typedef struct {
|
|
27
|
+
napi_async_work work;
|
|
28
|
+
napi_threadsafe_function tsfn;
|
|
29
|
+
} AddonData;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
static const char *ALL_CONFIG_TYPES[] = {
|
|
33
|
+
"all",
|
|
34
|
+
NULL
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* This function is responsible for calling the JavaScript callback function
|
|
40
|
+
* that was specified when the ziti_init(...) was called from JavaScript.
|
|
41
|
+
*/
|
|
42
|
+
static void CallJs(napi_env env, napi_value js_cb, void* context, void* data) {
|
|
43
|
+
napi_status status;
|
|
44
|
+
|
|
45
|
+
// This parameter is not used.
|
|
46
|
+
(void) context;
|
|
47
|
+
|
|
48
|
+
// env and js_cb may both be NULL if Node.js is in its cleanup phase, and
|
|
49
|
+
// items are left over from earlier thread-safe calls from the worker thread.
|
|
50
|
+
// When env is NULL, we simply skip over the call into Javascript
|
|
51
|
+
if (env != NULL) {
|
|
52
|
+
napi_value undefined, js_rc;
|
|
53
|
+
|
|
54
|
+
// Retrieve the JavaScript `undefined` value so we can use it as the `this`
|
|
55
|
+
// value of the JavaScript function call.
|
|
56
|
+
status = napi_get_undefined(env, &undefined);
|
|
57
|
+
|
|
58
|
+
// Retrieve the rc created by the worker thread.
|
|
59
|
+
int rc = (int)data;
|
|
60
|
+
status = napi_create_int64(env, (int64_t)rc, &js_rc);
|
|
61
|
+
if (status != napi_ok) {
|
|
62
|
+
napi_throw_error(env, NULL, "Failed to napi_create_int64");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Call the JavaScript function and pass it the rc
|
|
66
|
+
status = napi_call_function(
|
|
67
|
+
env,
|
|
68
|
+
undefined,
|
|
69
|
+
js_cb,
|
|
70
|
+
1,
|
|
71
|
+
&js_rc,
|
|
72
|
+
NULL
|
|
73
|
+
);
|
|
74
|
+
if (status != napi_ok) {
|
|
75
|
+
napi_throw_error(env, NULL, "Failed to napi_call_function");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
*
|
|
83
|
+
*/
|
|
84
|
+
void on_ziti_init(ziti_context _ztx, int status, void* ctx) {
|
|
85
|
+
napi_status nstatus;
|
|
86
|
+
|
|
87
|
+
ZITI_NODEJS_LOG(DEBUG, "_ztx: %p", _ztx);
|
|
88
|
+
|
|
89
|
+
// Set the global ztx context variable
|
|
90
|
+
ztx = _ztx;
|
|
91
|
+
|
|
92
|
+
if (status == ZITI_OK) {
|
|
93
|
+
|
|
94
|
+
ziti_set_timeout(ztx, 5*1000);
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
AddonData* addon_data = (AddonData*)ctx;
|
|
99
|
+
|
|
100
|
+
// Initiate the call into the JavaScript callback.
|
|
101
|
+
// The call into JavaScript will not have happened
|
|
102
|
+
// when this function returns, but it will be queued.
|
|
103
|
+
nstatus = napi_call_threadsafe_function(
|
|
104
|
+
addon_data->tsfn,
|
|
105
|
+
(void*) (long) status,
|
|
106
|
+
napi_tsfn_blocking);
|
|
107
|
+
if (nstatus != napi_ok) {
|
|
108
|
+
ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
*
|
|
115
|
+
*/
|
|
116
|
+
static void on_ziti_event(ziti_context _ztx, const ziti_event_t *event) {
|
|
117
|
+
napi_status nstatus;
|
|
118
|
+
|
|
119
|
+
AddonData* addon_data = (AddonData*)ziti_app_ctx(_ztx);
|
|
120
|
+
|
|
121
|
+
switch (event->type) {
|
|
122
|
+
|
|
123
|
+
case ZitiContextEvent:
|
|
124
|
+
// Set the global ztx context variable
|
|
125
|
+
ztx = _ztx;
|
|
126
|
+
|
|
127
|
+
if (event->event.ctx.ctrl_status == ZITI_OK) {
|
|
128
|
+
const ziti_version *ctrl_ver = ziti_get_controller_version(_ztx);
|
|
129
|
+
const ziti_identity *proxy_id = ziti_get_identity(_ztx);
|
|
130
|
+
ZITI_NODEJS_LOG(INFO, "controller version = %s(%s)[%s]", ctrl_ver->version, ctrl_ver->revision, ctrl_ver->build_date);
|
|
131
|
+
ZITI_NODEJS_LOG(INFO, "identity = <%s>[%s]@%s", proxy_id->name, proxy_id->id, ziti_get_controller(_ztx));
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
ZITI_NODEJS_LOG(ERROR, "Failed to connect to controller: %s", event->event.ctx.err);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Initiate the call into the JavaScript callback.
|
|
138
|
+
// The call into JavaScript will not have happened
|
|
139
|
+
// when this function returns, but it will be queued.
|
|
140
|
+
nstatus = napi_call_threadsafe_function(
|
|
141
|
+
addon_data->tsfn,
|
|
142
|
+
(void*) (long) event->event.ctx.ctrl_status,
|
|
143
|
+
napi_tsfn_blocking);
|
|
144
|
+
if (nstatus != napi_ok) {
|
|
145
|
+
ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
|
|
146
|
+
}
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case ZitiServiceEvent:
|
|
150
|
+
if (event->event.service.removed != NULL) {
|
|
151
|
+
for (ziti_service **sp = event->event.service.removed; *sp != NULL; sp++) {
|
|
152
|
+
// service_check_cb(ztx, *sp, ZITI_SERVICE_UNAVAILABLE, app_ctx);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (event->event.service.added != NULL) {
|
|
157
|
+
for (ziti_service **sp = event->event.service.added; *sp != NULL; sp++) {
|
|
158
|
+
// service_check_cb(ztx, *sp, ZITI_OK, app_ctx);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
break;
|
|
162
|
+
|
|
163
|
+
case ZitiRouterEvent:
|
|
164
|
+
switch (event->event.router.status){
|
|
165
|
+
case EdgeRouterConnected:
|
|
166
|
+
ZITI_NODEJS_LOG(INFO, "ziti connected to edge router %s\nversion = %s", event->event.router.name, event->event.router.version);
|
|
167
|
+
break;
|
|
168
|
+
case EdgeRouterDisconnected:
|
|
169
|
+
ZITI_NODEJS_LOG(INFO, "ziti disconnected from edge router %s", event->event.router.name);
|
|
170
|
+
break;
|
|
171
|
+
case EdgeRouterRemoved:
|
|
172
|
+
ZITI_NODEJS_LOG(INFO, "ziti removed edge router %s", event->event.router.name);
|
|
173
|
+
break;
|
|
174
|
+
case EdgeRouterUnavailable:
|
|
175
|
+
ZITI_NODEJS_LOG(INFO, "edge router %s is not available", event->event.router.name);
|
|
176
|
+
break;
|
|
177
|
+
case EdgeRouterAdded:
|
|
178
|
+
ZITI_NODEJS_LOG(INFO, "edge router %s was added", event->event.router.name);
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
default:
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
static void child_thread(void *data){
|
|
190
|
+
uv_loop_t *thread_loop = (uv_loop_t *) data;
|
|
191
|
+
|
|
192
|
+
//Start this loop
|
|
193
|
+
uv_run(thread_loop, UV_RUN_DEFAULT);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
static void consumer_notify(uv_async_t *handle, int status) { }
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
*
|
|
200
|
+
*/
|
|
201
|
+
napi_value _ziti_init(napi_env env, const napi_callback_info info) {
|
|
202
|
+
napi_status status;
|
|
203
|
+
napi_value jsRetval;
|
|
204
|
+
|
|
205
|
+
ZITI_NODEJS_LOG(DEBUG, "initializing");
|
|
206
|
+
|
|
207
|
+
// uv_mbed_set_debug(TRACE, stdout);
|
|
208
|
+
|
|
209
|
+
size_t argc = 2;
|
|
210
|
+
napi_value args[2];
|
|
211
|
+
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
|
212
|
+
if (status != napi_ok) {
|
|
213
|
+
napi_throw_error(env, NULL, "Failed to parse arguments");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (argc < 2) {
|
|
217
|
+
napi_throw_error(env, "EINVAL", "Too few arguments");
|
|
218
|
+
return NULL;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Obtain length of location of identity file
|
|
222
|
+
size_t result;
|
|
223
|
+
size_t config_path_len;
|
|
224
|
+
status = napi_get_value_string_utf8(env, args[0], NULL, 0, &config_path_len);
|
|
225
|
+
if (status != napi_ok) {
|
|
226
|
+
napi_throw_error(env, "EINVAL", "location of identity file is not a string");
|
|
227
|
+
}
|
|
228
|
+
// Obtain length of location of identity file
|
|
229
|
+
char* config_file_name = calloc(1, config_path_len+2);
|
|
230
|
+
status = napi_get_value_string_utf8(env, args[0], config_file_name, config_path_len+1, &result);
|
|
231
|
+
if (status != napi_ok) {
|
|
232
|
+
napi_throw_error(env, "EINVAL", "Failed to obtain location of identity file");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
ZITI_NODEJS_LOG(DEBUG, "config_file_name: %s", config_file_name);
|
|
236
|
+
|
|
237
|
+
// Obtain ptr to JS callback function
|
|
238
|
+
napi_value js_cb = args[1];
|
|
239
|
+
napi_value work_name;
|
|
240
|
+
AddonData* addon_data = malloc(sizeof(AddonData));
|
|
241
|
+
|
|
242
|
+
// Create a string to describe this asynchronous operation.
|
|
243
|
+
status = napi_create_string_utf8(
|
|
244
|
+
env,
|
|
245
|
+
"N-API on_ziti_init",
|
|
246
|
+
NAPI_AUTO_LENGTH,
|
|
247
|
+
&work_name);
|
|
248
|
+
if (status != napi_ok) {
|
|
249
|
+
napi_throw_error(env, NULL, "Failed to napi_create_string_utf8");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
|
|
253
|
+
// which we can call from a worker thread.
|
|
254
|
+
status = napi_create_threadsafe_function(
|
|
255
|
+
env,
|
|
256
|
+
js_cb,
|
|
257
|
+
NULL,
|
|
258
|
+
work_name,
|
|
259
|
+
0,
|
|
260
|
+
1,
|
|
261
|
+
NULL,
|
|
262
|
+
NULL,
|
|
263
|
+
NULL,
|
|
264
|
+
CallJs,
|
|
265
|
+
&(addon_data->tsfn));
|
|
266
|
+
if (status != napi_ok) {
|
|
267
|
+
napi_throw_error(env, NULL, "Failed to napi_create_threadsafe_function");
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Create and set up the consumer thread
|
|
271
|
+
if (NULL == thread_loop) { // Spawn the loop only once
|
|
272
|
+
ZITI_NODEJS_LOG(DEBUG, "calling uv_loop_new()");
|
|
273
|
+
thread_loop = uv_loop_new();
|
|
274
|
+
uv_async_init(thread_loop, &async, (uv_async_cb)consumer_notify);
|
|
275
|
+
uv_thread_create(&thread, (uv_thread_cb)child_thread, thread_loop);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Light this candle!
|
|
279
|
+
ziti_options *opts = calloc(1, sizeof(ziti_options));
|
|
280
|
+
|
|
281
|
+
opts->config = config_file_name;
|
|
282
|
+
opts->events = ZitiContextEvent|ZitiServiceEvent|ZitiRouterEvent;
|
|
283
|
+
opts->event_cb = on_ziti_event;
|
|
284
|
+
opts->refresh_interval = 60;
|
|
285
|
+
opts->router_keepalive = 10;
|
|
286
|
+
opts->app_ctx = addon_data;
|
|
287
|
+
opts->config_types = ALL_CONFIG_TYPES;
|
|
288
|
+
opts->metrics_type = INSTANT;
|
|
289
|
+
|
|
290
|
+
int rc = ziti_init_opts(opts, thread_loop);
|
|
291
|
+
|
|
292
|
+
status = napi_create_int32(env, rc, &jsRetval);
|
|
293
|
+
if (status != napi_ok) {
|
|
294
|
+
napi_throw_error(env, NULL, "Unable to create return value");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return jsRetval;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
void expose_ziti_init(napi_env env, napi_value exports) {
|
|
302
|
+
napi_status status;
|
|
303
|
+
napi_value fn;
|
|
304
|
+
|
|
305
|
+
status = napi_create_function(env, NULL, 0, _ziti_init, NULL, &fn);
|
|
306
|
+
if (status != napi_ok) {
|
|
307
|
+
napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_init");
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
status = napi_set_named_property(env, exports, "ziti_init", fn);
|
|
311
|
+
if (status != napi_ok) {
|
|
312
|
+
napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_init");
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2019-2020 Netfoundry, Inc.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include "ziti-nodejs.h"
|
|
18
|
+
#include <time.h>
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
typedef struct {
|
|
22
|
+
napi_async_work work;
|
|
23
|
+
napi_threadsafe_function tsfn;
|
|
24
|
+
} AddonData;
|
|
25
|
+
|
|
26
|
+
// An item that will be generated here and passed into the JavaScript service_available callback
|
|
27
|
+
typedef struct ServiceAvailableItem {
|
|
28
|
+
ssize_t status;
|
|
29
|
+
int permissions;
|
|
30
|
+
} ServiceAvailableItem;
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* This function is responsible for calling the JavaScript 'service_available' callback function
|
|
35
|
+
* that was specified when the ziti_service_available(...) was called from JavaScript.
|
|
36
|
+
*/
|
|
37
|
+
static void CallJs_on_service_available(napi_env env, napi_value js_cb, void* context, void* data) {
|
|
38
|
+
napi_status status;
|
|
39
|
+
|
|
40
|
+
// This parameter is not used.
|
|
41
|
+
(void) context;
|
|
42
|
+
|
|
43
|
+
// Retrieve the ServiceAvailableItem created by the worker thread.
|
|
44
|
+
ServiceAvailableItem* item = (ServiceAvailableItem*)data;
|
|
45
|
+
|
|
46
|
+
// env and js_cb may both be NULL if Node.js is in its cleanup phase, and
|
|
47
|
+
// items are left over from earlier thread-safe calls from the worker thread.
|
|
48
|
+
// When env is NULL, we simply skip over the call into Javascript and free the
|
|
49
|
+
// items.
|
|
50
|
+
if (env != NULL) {
|
|
51
|
+
|
|
52
|
+
napi_value undefined;
|
|
53
|
+
|
|
54
|
+
// const obj = {}
|
|
55
|
+
napi_value js_service_available_item, js_status, js_permissions;
|
|
56
|
+
status = napi_create_object(env, &js_service_available_item);
|
|
57
|
+
if (status != napi_ok) {
|
|
58
|
+
napi_throw_error(env, NULL, "Unable to napi_create_object");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// obj.status = status
|
|
62
|
+
status = napi_create_int64(env, (int64_t)item->status, &js_status);
|
|
63
|
+
if (status != napi_ok) {
|
|
64
|
+
napi_throw_error(env, NULL, "Unable to napi_create_int64");
|
|
65
|
+
}
|
|
66
|
+
status = napi_set_named_property(env, js_service_available_item, "status", js_status);
|
|
67
|
+
if (status != napi_ok) {
|
|
68
|
+
napi_throw_error(env, NULL, "Unable to napi_set_named_property");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// obj.permissions = permissions
|
|
72
|
+
status = napi_create_int64(env, (int64_t)item->permissions, &js_permissions);
|
|
73
|
+
if (status != napi_ok) {
|
|
74
|
+
napi_throw_error(env, NULL, "Unable to napi_create_int64");
|
|
75
|
+
}
|
|
76
|
+
status = napi_set_named_property(env, js_service_available_item, "permissions", js_permissions);
|
|
77
|
+
if (status != napi_ok) {
|
|
78
|
+
napi_throw_error(env, NULL, "Unable to napi_set_named_property");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Retrieve the JavaScript `undefined` value so we can use it as the `this`
|
|
82
|
+
// value of the JavaScript function call.
|
|
83
|
+
status = napi_get_undefined(env, &undefined);
|
|
84
|
+
if (status != napi_ok) {
|
|
85
|
+
napi_throw_error(env, NULL, "Unable to napi_get_undefined (4)");
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Call the JavaScript function and pass it the ServiceAvailableItem
|
|
89
|
+
status = napi_call_function(
|
|
90
|
+
env,
|
|
91
|
+
undefined,
|
|
92
|
+
js_cb,
|
|
93
|
+
1,
|
|
94
|
+
&js_service_available_item,
|
|
95
|
+
NULL);
|
|
96
|
+
if (status != napi_ok) {
|
|
97
|
+
napi_throw_error(env, NULL, "Unable to napi_call_function");
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
*/
|
|
106
|
+
static void on_service_available(ziti_context nf_ctx, ziti_service* service, int status, void *ctx) {
|
|
107
|
+
napi_status nstatus;
|
|
108
|
+
|
|
109
|
+
AddonData* addon_data = (AddonData*)ctx;
|
|
110
|
+
|
|
111
|
+
ServiceAvailableItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
|
|
112
|
+
item->status = status;
|
|
113
|
+
|
|
114
|
+
if (ZITI_OK == status) {
|
|
115
|
+
item->permissions = service->perm_flags;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Initiate the call into the JavaScript callback.
|
|
119
|
+
// The call into JavaScript will not have happened
|
|
120
|
+
// when this function returns, but it will be queued.
|
|
121
|
+
nstatus = napi_call_threadsafe_function(
|
|
122
|
+
addon_data->tsfn,
|
|
123
|
+
item,
|
|
124
|
+
napi_tsfn_blocking);
|
|
125
|
+
if (nstatus != napi_ok) {
|
|
126
|
+
ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
*
|
|
132
|
+
*/
|
|
133
|
+
napi_value _ziti_service_available(napi_env env, const napi_callback_info info) {
|
|
134
|
+
napi_status status;
|
|
135
|
+
size_t argc = 2;
|
|
136
|
+
napi_value args[2];
|
|
137
|
+
napi_value jsRetval;
|
|
138
|
+
|
|
139
|
+
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
|
|
140
|
+
if (status != napi_ok) {
|
|
141
|
+
napi_throw_error(env, NULL, "Failed to parse arguments");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (argc < 2) {
|
|
145
|
+
napi_throw_error(env, "EINVAL", "Too few arguments");
|
|
146
|
+
return NULL;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Obtain service name
|
|
150
|
+
size_t result;
|
|
151
|
+
char* ServiceName = malloc(256); // TODO: make this smarter
|
|
152
|
+
status = napi_get_value_string_utf8(env, args[0], ServiceName, 100, &result);
|
|
153
|
+
if (status != napi_ok) {
|
|
154
|
+
napi_throw_error(env, NULL, "Service Name not provided");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Obtain ptr to JS 'service_available' callback function
|
|
158
|
+
napi_value js_write_cb = args[1];
|
|
159
|
+
napi_value work_name;
|
|
160
|
+
AddonData* addon_data = malloc(sizeof(AddonData));
|
|
161
|
+
|
|
162
|
+
// Create a string to describe this asynchronous operation.
|
|
163
|
+
status = napi_create_string_utf8(
|
|
164
|
+
env,
|
|
165
|
+
"N-API on_service_available",
|
|
166
|
+
NAPI_AUTO_LENGTH,
|
|
167
|
+
&work_name);
|
|
168
|
+
if (status != napi_ok) {
|
|
169
|
+
napi_throw_error(env, NULL, "Unable to napi_create_string_utf8");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
|
|
173
|
+
// which we can call from a worker thread.
|
|
174
|
+
status = napi_create_threadsafe_function(
|
|
175
|
+
env,
|
|
176
|
+
js_write_cb,
|
|
177
|
+
NULL,
|
|
178
|
+
work_name,
|
|
179
|
+
0,
|
|
180
|
+
1,
|
|
181
|
+
NULL,
|
|
182
|
+
NULL,
|
|
183
|
+
NULL,
|
|
184
|
+
CallJs_on_service_available,
|
|
185
|
+
&(addon_data->tsfn));
|
|
186
|
+
if (status != napi_ok) {
|
|
187
|
+
napi_throw_error(env, NULL, "Unable to napi_call_threadsafe_function");
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Now, call the C-SDK to see if the service name is present
|
|
191
|
+
ziti_service_available(ztx, ServiceName, on_service_available, addon_data);
|
|
192
|
+
|
|
193
|
+
status = napi_create_int32(env, 0 /* always succeed here, it is the cb that tells the real tale */, &jsRetval);
|
|
194
|
+
if (status != napi_ok) {
|
|
195
|
+
napi_throw_error(env, NULL, "Unable to create return value");
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
free(ServiceName);
|
|
199
|
+
|
|
200
|
+
return jsRetval;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
*
|
|
206
|
+
*/
|
|
207
|
+
void expose_ziti_service_available(napi_env env, napi_value exports) {
|
|
208
|
+
napi_status status;
|
|
209
|
+
napi_value fn;
|
|
210
|
+
|
|
211
|
+
status = napi_create_function(env, NULL, 0, _ziti_service_available, NULL, &fn);
|
|
212
|
+
if (status != napi_ok) {
|
|
213
|
+
napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_service_available");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
status = napi_set_named_property(env, exports, "ziti_service_available", fn);
|
|
217
|
+
if (status != napi_ok) {
|
|
218
|
+
napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_service_available");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2019-2020 Netfoundry, Inc.
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
https://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#include "ziti-nodejs.h"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
napi_value _ziti_shutdown(napi_env env, const napi_callback_info info) {
|
|
24
|
+
|
|
25
|
+
ZITI_NODEJS_LOG(DEBUG, "ztx: %p", ztx);
|
|
26
|
+
|
|
27
|
+
ziti_shutdown(ztx);
|
|
28
|
+
|
|
29
|
+
return NULL;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
void expose_ziti_shutdown(napi_env env, napi_value exports) {
|
|
34
|
+
napi_status status;
|
|
35
|
+
napi_value fn;
|
|
36
|
+
|
|
37
|
+
status = napi_create_function(env, NULL, 0, _ziti_shutdown, NULL, &fn);
|
|
38
|
+
if (status != napi_ok) {
|
|
39
|
+
napi_throw_error(env, NULL, "Unable to wrap native function '_ziti_shutdown");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
status = napi_set_named_property(env, exports, "ziti_shutdown", fn);
|
|
43
|
+
if (status != napi_ok) {
|
|
44
|
+
napi_throw_error(env, NULL, "Unable to populate exports for 'ziti_shutdown");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|