Skip to content

Commit d88eb31

Browse files
authored
fix: Enrollment bug (#83)
1 parent 128f4f1 commit d88eb31

File tree

9 files changed

+151
-77
lines changed

9 files changed

+151
-77
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,12 @@ jobs:
8888
run: echo "date=$(date)" >> $GITHUB_OUTPUT
8989

9090
- name: Install CMake/Ninja
91-
uses: lukka/get-cmake@latest
91+
uses: lukka/get-cmake@v3.27.6
9292

9393
- name: Run VCPKG
94-
uses: lukka/run-vcpkg@v11
94+
uses: lukka/run-vcpkg@v10
9595
with:
96-
# tag: 2023.10.19
97-
vcpkgGitCommitId: '8eb57355a4ffb410a2e94c07b4dca2dffbee8e50'
96+
vcpkgGitCommitId: 'c8696863d371ab7f46e213d8f5ca923c4aef2a00'
9897

9998
- name: gcc version
10099
run: |

lib/enroll.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
Copyright 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+
18+
19+
/**
20+
* on_enroll()
21+
*
22+
*/
23+
const on_enroll = ( status ) => {
24+
25+
};
26+
27+
28+
/**
29+
* enroll()
30+
*
31+
* @param {*} jwt_path
32+
* @param {*} on_enroll_cb callback
33+
*/
34+
const enroll = ( jwt_path, on_enroll_cb ) => {
35+
36+
let enroll_cb;
37+
38+
if (typeof on_enroll_cb === 'undefined') {
39+
enroll_cb = on_enroll;
40+
} else {
41+
enroll_cb = on_enroll_cb;
42+
}
43+
44+
ziti.ziti_enroll(jwt_path, enroll_cb);
45+
46+
};
47+
48+
49+
exports.enroll = enroll;

lib/ziti.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ exports.close = require('./close').close;
8282
*/
8383
exports.dial = require('./dial').dial;
8484

85+
/**
86+
* Enroll a Ziti Identity.
87+
* @async
88+
* @function enroll
89+
* @param {string} jwt_path - The path to the JWT
90+
* @param {onEnrollCallback} onEnroll - The callback that receives the enrollment status.
91+
* @returns {void} No return value.
92+
*/
93+
/**
94+
* This callback is part of the `enroll` API.
95+
* @callback onEnrollCallback - The callback that receives the enrollment status.
96+
* @param {object} obj - enrollment status.
97+
*/
98+
exports.enroll = require('./enroll').enroll;
99+
85100
/**
86101
* Wrap ExpressJS to facilitate hosting (listening) on a Ziti Service instead of a TCP port.
87102
* @function express

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@openziti/ziti-sdk-nodejs",
33
"description": "A NodeJS-based SDK for delivering secure applications over a Ziti Network",
4-
"version": "0.16.0",
4+
"version": "0.17.0",
55
"main": "./lib/ziti",
66
"scripts": {
77
"build": "npm run build:init && npm run build:configure && npm run build:make",

src/ziti-add-on.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ limitations under the License.
1818

1919
extern void set_signal_handler();
2020

21+
uv_loop_t *thread_loop;
2122

2223
napi_value Init(napi_env env, napi_value exports) {
2324

src/ziti-nodejs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ UV_EXTERN int uv_gettimeofday(uv_timeval64_t* tv);
8181
# endif
8282

8383

84+
/**
85+
*
86+
*/
87+
typedef struct {
88+
napi_async_work work;
89+
napi_threadsafe_function tsfn_on_enroll;
90+
} EnrollAddonData;
91+
8492

8593
/**
8694
*

src/ziti_enroll.c

Lines changed: 57 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,6 @@ limitations under the License.
1616

1717
#include "ziti-nodejs.h"
1818

19-
ziti_context nf;
20-
uv_loop_t *enroll_loop = NULL;
21-
22-
uv_loop_t *thread_loop;
23-
uv_thread_t thread;
24-
uv_async_t async;
25-
26-
27-
typedef struct {
28-
napi_async_work work;
29-
napi_threadsafe_function tsfn;
30-
} AddonData;
3119

3220
// An item that will be generated here and passed into the JavaScript enroll callback
3321
typedef struct EnrollItem {
@@ -45,6 +33,8 @@ typedef struct EnrollItem {
4533
*/
4634
static void CallJs_on_enroll(napi_env env, napi_value js_cb, void* context, void* data) {
4735

36+
napi_status status;
37+
4838
ZITI_NODEJS_LOG(DEBUG, "entered");
4939

5040
// This parameter is not used.
@@ -70,38 +60,44 @@ static void CallJs_on_enroll(napi_env env, napi_value js_cb, void* context, void
7060

7161
// const obj = {}
7262
napi_value js_enroll_item, js_json_salvo, js_status, js_err;
73-
assert(napi_create_object(env, &js_enroll_item) == napi_ok);
63+
status = napi_create_object(env, &js_enroll_item);
64+
if (status != napi_ok) {
65+
napi_throw_error(env, NULL, "Unable to napi_create_object");
66+
}
7467

7568
// obj.identity = identity
7669
if (NULL != item->json_salvo) {
77-
assert(napi_create_string_utf8(env, (const char*)item->json_salvo, NAPI_AUTO_LENGTH, &js_json_salvo) == napi_ok);
78-
assert(napi_set_named_property(env, js_enroll_item, "identity", js_json_salvo) == napi_ok);
79-
} else {
80-
assert(napi_set_named_property(env, js_enroll_item, "identity", undefined) == napi_ok);
70+
napi_create_string_utf8(env, (const char*)item->json_salvo, NAPI_AUTO_LENGTH, &js_json_salvo);
71+
napi_set_named_property(env, js_enroll_item, "identity", js_json_salvo);
8172
}
8273

8374
// obj.status = status
84-
assert(napi_create_int64(env, (int64_t)item->status, &js_status) == napi_ok);
85-
assert(napi_set_named_property(env, js_enroll_item, "status", js_status) == napi_ok);
75+
napi_create_int64(env, (int64_t)item->status, &js_status);
76+
napi_set_named_property(env, js_enroll_item, "status", js_status);
8677

8778
// obj.err = err
8879
if (NULL != item->err) {
89-
assert(napi_create_string_utf8(env, (const char*)item->err, NAPI_AUTO_LENGTH, &js_err) == napi_ok);
90-
assert(napi_set_named_property(env, js_enroll_item, "err", js_err) == napi_ok);
91-
} else {
92-
assert(napi_set_named_property(env, js_enroll_item, "err", undefined) == napi_ok);
80+
napi_create_string_utf8(env, (const char*)item->err, NAPI_AUTO_LENGTH, &js_err);
81+
napi_set_named_property(env, js_enroll_item, "err", js_err);
9382
}
9483

9584

96-
// Call the JavaScript function and pass it the WriteItem
97-
assert(
98-
napi_call_function(
99-
env,
100-
undefined,
101-
js_cb,
102-
1,
103-
&js_enroll_item,
104-
NULL) == napi_ok);
85+
// Call the JavaScript function and pass it the EnrollItem
86+
napi_value global;
87+
status = napi_get_global(env, &global);
88+
89+
status = napi_call_function(
90+
env,
91+
global,
92+
js_cb,
93+
1,
94+
&js_enroll_item,
95+
NULL
96+
);
97+
98+
if (status != napi_ok) {
99+
napi_throw_error(env, "EINVAL", "failure to invoke JS callback");
100+
}
105101

106102
}
107103
}
@@ -110,11 +106,12 @@ static void CallJs_on_enroll(napi_env env, napi_value js_cb, void* context, void
110106
/**
111107
*
112108
*/
113-
void on_ziti_enroll(const ziti_config *cfg, int status, const char *err, void *ctx) {
109+
void on_ziti_enroll(ziti_config *cfg, int status, char *err, void *ctx) {
110+
napi_status nstatus;
114111

115112
ZITI_NODEJS_LOG(DEBUG, "\nstatus: %d, \nerr: %s,\nctx: %p", status, err, ctx);
116113

117-
AddonData* addon_data = (AddonData*)ctx;
114+
EnrollAddonData* addon_data = (EnrollAddonData*)ctx;
118115

119116
EnrollItem* item = memset(malloc(sizeof(*item)), 0, sizeof(*item));
120117

@@ -137,30 +134,28 @@ void on_ziti_enroll(const ziti_config *cfg, int status, const char *err, void *c
137134
// Initiate the call into the JavaScript callback.
138135
// The call into JavaScript will not have happened
139136
// when this function returns, but it will be queued.
140-
assert(
141-
napi_call_threadsafe_function(
142-
addon_data->tsfn,
137+
nstatus = napi_call_threadsafe_function(
138+
addon_data->tsfn_on_enroll,
143139
item,
144-
napi_tsfn_blocking) == napi_ok);
145-
}
146-
140+
napi_tsfn_blocking);
141+
if (nstatus != napi_ok) {
142+
ZITI_NODEJS_LOG(ERROR, "Unable to napi_call_threadsafe_function");
143+
}
147144

145+
}
148146

149-
void child_thread(void *data){
150-
uv_loop_t *thread_loop = (uv_loop_t *) data;
151147

152-
//Start this loop
153-
uv_run(thread_loop, UV_RUN_DEFAULT);
154-
}
155148

156-
static void consumer_notify(uv_async_t *handle, int status) { }
157149

158150
/**
159151
*
160152
*/
161153
napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
162154
napi_status status;
163155
napi_value jsRetval;
156+
napi_valuetype js_cb_type;
157+
158+
ziti_log_init(thread_loop, ZITI_LOG_DEFAULT_LEVEL, NULL);
164159

165160
ZITI_NODEJS_LOG(DEBUG, "entered");
166161

@@ -172,6 +167,7 @@ napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
172167
}
173168

174169
if (argc < 2) {
170+
ZITI_NODEJS_LOG(DEBUG, "Too few arguments");
175171
napi_throw_error(env, "EINVAL", "Too few arguments");
176172
return NULL;
177173
}
@@ -182,9 +178,16 @@ napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
182178
status = napi_get_value_string_utf8(env, args[0], JWTFileName, 256, &result);
183179

184180
// Obtain ptr to JS callback function
185-
napi_value js_cb = args[1];
181+
// napi_value js_cb = args[1];
182+
napi_typeof(env, args[1], &js_cb_type);
183+
if (js_cb_type != napi_function) {
184+
ZITI_NODEJS_LOG(DEBUG, "args[1] is NOT a napi_function");
185+
} else {
186+
ZITI_NODEJS_LOG(DEBUG, "args[1] IS a napi_function");
187+
}
186188
napi_value work_name;
187-
AddonData* addon_data = malloc(sizeof(AddonData));
189+
190+
EnrollAddonData* addon_data = memset(malloc(sizeof(*addon_data)), 0, sizeof(*addon_data));
188191

189192
// Create a string to describe this asynchronous operation.
190193
assert(napi_create_string_utf8(
@@ -195,10 +198,9 @@ napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
195198

196199
// Convert the callback retrieved from JavaScript into a thread-safe function (tsfn)
197200
// which we can call from a worker thread.
198-
assert(
199-
napi_create_threadsafe_function(
201+
status = napi_create_threadsafe_function(
200202
env,
201-
js_cb,
203+
args[1],
202204
NULL,
203205
work_name,
204206
0,
@@ -207,12 +209,11 @@ napi_value _ziti_enroll(napi_env env, const napi_callback_info info) {
207209
NULL,
208210
NULL,
209211
CallJs_on_enroll,
210-
&(addon_data->tsfn)) == napi_ok);
212+
&(addon_data->tsfn_on_enroll));
213+
if (status != napi_ok) {
214+
napi_throw_error(env, NULL, "Unable to napi_create_threadsafe_function");
215+
}
211216

212-
// Create and set up the consumer thread
213-
thread_loop = uv_loop_new();
214-
uv_async_init(thread_loop, &async, (uv_async_cb)consumer_notify);
215-
uv_thread_create(&thread, (uv_thread_cb)child_thread, thread_loop);
216217

217218
// Initiate the enrollment
218219
ziti_enroll_opts opts = {0};

tests/enroll-test.js

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1+
const bindings = require('bindings')('ziti_sdk_nodejs')
12

2-
var binary = require('@mapbox/node-pre-gyp');
3-
var path = require('path')
4-
var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')), {debug: true});
5-
// var binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
6-
var ziti = require(binding_path);
3+
const result = bindings.ziti_sdk_version();
4+
const binary = require('@mapbox/node-pre-gyp');
5+
const path = require('path')
6+
const binding_path = binary.find(path.resolve(path.join(__dirname,'../package.json')));
7+
const ziti = require(binding_path);
8+
require('assert').notEqual(result,"");
79

810
console.log("using ziti version: " + ziti.ziti_sdk_version())
9-
// require('assert').equal(ziti.ziti_sdk_version(),"ziti");
1011

1112

1213

13-
const ziti_enroll = async (jwt_path) => {
14+
const ziti_Enroll = async (jwt_path) => {
15+
console.log("JS ziti_Enroll() entered ")
1416
return new Promise((resolve, reject) => {
15-
let rc = ziti.ziti_enroll(jwt_path, (data) => {
16-
if (data.identity) {
17-
resolve(data);
18-
} else {
19-
reject(data);
17+
let rc = ziti.ziti_enroll(
18+
jwt_path,
19+
(data) => {
20+
return resolve(data);
2021
}
21-
});
22+
);
2223
});
2324
};
2425

@@ -27,8 +28,8 @@ const ziti_enroll = async (jwt_path) => {
2728

2829
let jwt_path = process.argv[2];
2930

30-
let data = await ziti_enroll(jwt_path).catch((data) => {
31-
console.log('ziti_enroll failed with error code (%o/%s)', data.status, data.err);
31+
let data = await ziti_Enroll(jwt_path).catch((data) => {
32+
console.log('JS ziti_enroll failed with error code (%o/%s)', data.status, data.err);
3233
});
3334

3435
if (data && data.identity) {

vcpkg.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
],
1717
"features": {
1818
},
19-
"builtin-baseline": "f14984af3738e69f197bf0e647a8dca12de92996"
19+
"builtin-baseline": "c8696863d371ab7f46e213d8f5ca923c4aef2a00"
2020
}

0 commit comments

Comments
 (0)