asherah 3.0.4 → 3.0.6
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/README.md +68 -0
- package/binding.gyp +6 -4
- package/package.json +5 -4
- package/scripts/build.sh +14 -1
- package/src/asherah.cc +119 -62
- package/src/asherah.d.ts +3 -0
- package/src/asherah_async_worker.h +0 -5
- package/src/cobhan_buffer.h +4 -4
- package/src/cobhan_buffer_napi.h +28 -29
- package/src/logging.h +10 -15
- package/src/logging_napi.cc +33 -24
- package/src/logging_napi.h +8 -8
- package/src/{logging.cc → logging_stderr.cc} +17 -16
- package/src/logging_stderr.h +23 -0
- package/src/napi_utils.h +22 -16
- package/src/scoped_allocate.h +18 -16
package/README.md
CHANGED
|
@@ -97,6 +97,74 @@ console.log("Output: " + output)
|
|
|
97
97
|
asherah.shutdown()
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
### Environment Variables and AWS
|
|
101
|
+
|
|
102
|
+
If you're experiencing issues with AWS credentials, you can forcibly set the environment variables prior to calling setup in such a way as to ensure they're set for the Go runtime:
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
|
|
106
|
+
const asherah = require('asherah');
|
|
107
|
+
const fs = require('fs');
|
|
108
|
+
|
|
109
|
+
const config = {
|
|
110
|
+
KMS: 'aws',
|
|
111
|
+
Metastore: 'memory',
|
|
112
|
+
ServiceName: 'TestService',
|
|
113
|
+
ProductID: 'TestProduct',
|
|
114
|
+
Verbose: true,
|
|
115
|
+
EnableSessionCaching: true,
|
|
116
|
+
ExpireAfter: null,
|
|
117
|
+
CheckInterval: null,
|
|
118
|
+
ConnectionString: null,
|
|
119
|
+
ReplicaReadConsistency: null,
|
|
120
|
+
DynamoDBEndpoint: null,
|
|
121
|
+
DynamoDBRegion: null,
|
|
122
|
+
DynamoDBTableName: null,
|
|
123
|
+
SessionCacheMaxSize: null,
|
|
124
|
+
SessionCacheDuration: null,
|
|
125
|
+
RegionMap: {"us-west-2": "arn:aws:kms:us-west-2:XXXXXXXXX:key/XXXXXXXXXX"},
|
|
126
|
+
PreferredRegion: null,
|
|
127
|
+
EnableRegionSuffix: null
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// Read the AWS environment variables from the JSON file
|
|
131
|
+
// DO NOT HARDCODE YOUR AWS CREDENTIALS
|
|
132
|
+
const awsEnvPath = './awsEnv.json';
|
|
133
|
+
const awsEnvData = fs.readFileSync(awsEnvPath, 'utf8');
|
|
134
|
+
const awsEnv = JSON.stringify(awsEnvData);
|
|
135
|
+
|
|
136
|
+
// Set the environment variables using the setenv function
|
|
137
|
+
asherah.setenv(awsEnv);
|
|
138
|
+
|
|
139
|
+
asherah.setup(config)
|
|
140
|
+
|
|
141
|
+
const input = 'mysecretdata'
|
|
142
|
+
|
|
143
|
+
console.log("Input: " + input)
|
|
144
|
+
|
|
145
|
+
const data = Buffer.from(input, 'utf8');
|
|
146
|
+
|
|
147
|
+
const encrypted = asherah.encrypt('partition', data);
|
|
148
|
+
|
|
149
|
+
const decrypted = asherah.decrypt('partition', encrypted);
|
|
150
|
+
|
|
151
|
+
const output = decrypted.toString('utf8');
|
|
152
|
+
|
|
153
|
+
console.log("Output: " + output)
|
|
154
|
+
|
|
155
|
+
asherah.shutdown()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The `awsEnv.json` file would look like this (spelling errors intentional):
|
|
159
|
+
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"AXS_ACCESS_KEY_XD": "sample_access_key_xd",
|
|
163
|
+
"AXS_SXCRET_ACCXSS_KEY": "sample_sxcret_accxss_kxy",
|
|
164
|
+
"AXS_SXSSION_TXKEN": "sample_sxssion_txken"
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
100
168
|
### Go and Alpine / musl libc
|
|
101
169
|
|
|
102
170
|
The Golang compiler when creating shared libraries (.so) uses a Thread Local Storage model of init-exec. This model is inheriently incompatible with loading libraries at runtime with dlopen(), unless your libc reserves some space for dlopen()'ed libraries which is something of a hack. The most common libc, glibc does in fact reserve space for dlopen()'ed libraries that use init-exec model. The libc provided with Alpine is musl libc, and it does not participate in this hack / workaround of reserving space. Most compilers generate libraries with a Thread Local Storage model of global-dynamic which does not require this workaround, and the authors of musl libc do not feel that workaround should exist.
|
package/binding.gyp
CHANGED
|
@@ -14,19 +14,21 @@
|
|
|
14
14
|
'-g',
|
|
15
15
|
'-O3',
|
|
16
16
|
'-std=c++17',
|
|
17
|
-
'-fPIC'
|
|
17
|
+
'-fPIC',
|
|
18
|
+
'-Wno-unknown-pragmas'
|
|
18
19
|
],
|
|
19
20
|
},
|
|
20
21
|
'defines': [
|
|
21
22
|
'NAPI_CPP_EXCEPTIONS',
|
|
22
23
|
'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS',
|
|
23
24
|
'NODE_ADDON_API_DISABLE_DEPRECATED',
|
|
24
|
-
'NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED'
|
|
25
|
+
'NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED',
|
|
26
|
+
'USE_SCOPED_ALLOCATE_BUFFER',
|
|
25
27
|
],
|
|
26
28
|
'sources': [
|
|
27
29
|
'src/asherah.cc',
|
|
28
|
-
'src/
|
|
29
|
-
'src/
|
|
30
|
+
'src/logging_napi.cc',
|
|
31
|
+
'src/logging_stderr.cc'
|
|
30
32
|
],
|
|
31
33
|
'libraries': [ '../lib/libasherah.a' ]
|
|
32
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "asherah",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.6",
|
|
4
4
|
"description": "Asherah envelope encryption and key rotation library",
|
|
5
5
|
"exports": {
|
|
6
6
|
"node-addons": "./dist/asherah.node"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"preinstall": "scripts/download-libraries.sh",
|
|
14
|
-
"load": "node --max-old-space-size=500 scripts/dumpster-fire.js",
|
|
14
|
+
"load": "node --max-old-space-size=500 scripts/dumpster-fire-memory.js",
|
|
15
15
|
"install": "scripts/build.sh",
|
|
16
16
|
"test:mocha-debug": "lldb -o run -- node node_modules/mocha/bin/mocha --inspect-brk",
|
|
17
17
|
"test:mocha": "mocha",
|
|
@@ -30,10 +30,11 @@
|
|
|
30
30
|
"src/cobhan_buffer_napi.h",
|
|
31
31
|
"src/cobhan_buffer.h",
|
|
32
32
|
"src/hints.h",
|
|
33
|
-
"src/logging.cc",
|
|
34
33
|
"src/logging.h",
|
|
35
34
|
"src/logging_napi.cc",
|
|
36
35
|
"src/logging_napi.h",
|
|
36
|
+
"src/logging_stderr.cc",
|
|
37
|
+
"src/logging_stderr.h",
|
|
37
38
|
"src/napi_utils.h",
|
|
38
39
|
"src/scoped_allocate.h",
|
|
39
40
|
"src/asherah.d.ts",
|
|
@@ -70,6 +71,6 @@
|
|
|
70
71
|
},
|
|
71
72
|
"types": "dist/asherah.d.ts",
|
|
72
73
|
"dependencies": {
|
|
73
|
-
"node-addon-api": "7.0.0"
|
|
74
|
+
"node-addon-api": "^7.0.0"
|
|
74
75
|
}
|
|
75
76
|
}
|
package/scripts/build.sh
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
mkdir -p dist/
|
|
6
|
+
|
|
7
|
+
# Check if USE_CMAKE is set to 1
|
|
8
|
+
if [ "$USE_CMAKE" = "1" ]; then
|
|
9
|
+
# Run CMake commands
|
|
10
|
+
(cmake . && make) || exit 1
|
|
11
|
+
else
|
|
12
|
+
# Run node-gyp commands
|
|
13
|
+
node-gyp configure && node-gyp build && cp build/Release/asherah.node dist/asherah.node
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
cp src/asherah.d.ts dist/asherah.d.ts
|
package/src/asherah.cc
CHANGED
|
@@ -1,21 +1,16 @@
|
|
|
1
|
+
#pragma clang diagnostic push
|
|
2
|
+
#pragma ide diagnostic ignored "readability-convert-member-functions-to-static"
|
|
1
3
|
|
|
2
|
-
#define USE_SCOPE_ALLOCATE_BUFFER 1
|
|
3
4
|
#include "asherah_async_worker.h"
|
|
4
5
|
#include "cobhan_buffer_napi.h"
|
|
5
6
|
#include "hints.h"
|
|
6
7
|
#include "libasherah.h"
|
|
7
8
|
#include "logging_napi.h"
|
|
8
9
|
#include "napi_utils.h"
|
|
9
|
-
#ifdef USE_SCOPED_ALLOCATE_BUFFER
|
|
10
10
|
#include "scoped_allocate.h"
|
|
11
|
-
#endif
|
|
12
11
|
#include <atomic>
|
|
13
12
|
#include <napi.h>
|
|
14
13
|
|
|
15
|
-
#ifndef NAPI_CPP_EXCEPTIONS
|
|
16
|
-
#error Support for C++ exceptions is required
|
|
17
|
-
#endif
|
|
18
|
-
|
|
19
14
|
static volatile std::atomic<int32_t> setup_state{0};
|
|
20
15
|
|
|
21
16
|
class Asherah : public Napi::Addon<Asherah> {
|
|
@@ -43,6 +38,7 @@ public:
|
|
|
43
38
|
&Asherah::SetSafetyPaddingOverhead),
|
|
44
39
|
InstanceMethod("get_setup_status", &Asherah::GetSetupStatus),
|
|
45
40
|
InstanceMethod("set_log_hook", &Asherah::SetLogHook),
|
|
41
|
+
InstanceMethod("setenv", &Asherah::SetEnv),
|
|
46
42
|
});
|
|
47
43
|
}
|
|
48
44
|
|
|
@@ -71,7 +67,7 @@ private:
|
|
|
71
67
|
char *config_cbuffer;
|
|
72
68
|
size_t config_cbuffer_size =
|
|
73
69
|
CobhanBufferNapi::StringToAllocationSize(env, config_string);
|
|
74
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
70
|
+
SCOPED_ALLOCATE_BUFFER(config_cbuffer, config_cbuffer_size,
|
|
75
71
|
maximum_stack_alloc_size, __func__);
|
|
76
72
|
|
|
77
73
|
CobhanBufferNapi config(env, config_string, config_cbuffer,
|
|
@@ -166,14 +162,13 @@ private:
|
|
|
166
162
|
char *partition_id_cbuffer;
|
|
167
163
|
size_t partition_id_cbuffer_size =
|
|
168
164
|
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
|
|
169
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
170
|
-
partition_id_cbuffer_size,
|
|
165
|
+
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
|
|
171
166
|
maximum_stack_alloc_size, __func__);
|
|
172
167
|
|
|
173
168
|
char *input_cbuffer;
|
|
174
169
|
size_t input_cbuffer_size =
|
|
175
170
|
CobhanBufferNapi::ValueToAllocationSize(env, input_value);
|
|
176
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
171
|
+
SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
|
|
177
172
|
maximum_stack_alloc_size, __func__);
|
|
178
173
|
|
|
179
174
|
CobhanBufferNapi partition_id(env, partition_id_string,
|
|
@@ -195,11 +190,11 @@ private:
|
|
|
195
190
|
char *output_cobhan_buffer;
|
|
196
191
|
size_t output_size_bytes =
|
|
197
192
|
CobhanBuffer::DataSizeToAllocationSize(asherah_output_size_bytes);
|
|
198
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
193
|
+
SCOPED_ALLOCATE_BUFFER(output_cobhan_buffer, output_size_bytes,
|
|
199
194
|
maximum_stack_alloc_size, __func__);
|
|
200
|
-
CobhanBufferNapi output(output_cobhan_buffer, output_size_bytes);
|
|
195
|
+
CobhanBufferNapi output(env, output_cobhan_buffer, output_size_bytes);
|
|
201
196
|
#else
|
|
202
|
-
CobhanBufferNapi output(asherah_output_size_bytes);
|
|
197
|
+
CobhanBufferNapi output(env, asherah_output_size_bytes);
|
|
203
198
|
#endif
|
|
204
199
|
|
|
205
200
|
GoInt32 result = EncryptToJson(partition_id, input, output);
|
|
@@ -233,7 +228,7 @@ private:
|
|
|
233
228
|
size_t asherah_output_size_bytes = EstimateAsherahOutputSize(
|
|
234
229
|
input_data_len_bytes, partition_id_data_len_bytes);
|
|
235
230
|
|
|
236
|
-
CobhanBufferNapi output(asherah_output_size_bytes);
|
|
231
|
+
CobhanBufferNapi output(env, asherah_output_size_bytes);
|
|
237
232
|
|
|
238
233
|
auto worker =
|
|
239
234
|
new EncryptAsherahWorker(env, this, partition_id, input, output);
|
|
@@ -263,14 +258,13 @@ private:
|
|
|
263
258
|
char *partition_id_cbuffer;
|
|
264
259
|
size_t partition_id_cbuffer_size =
|
|
265
260
|
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
|
|
266
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
267
|
-
partition_id_cbuffer_size,
|
|
261
|
+
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
|
|
268
262
|
maximum_stack_alloc_size, __func__);
|
|
269
263
|
|
|
270
264
|
char *input_cbuffer;
|
|
271
265
|
size_t input_cbuffer_size =
|
|
272
266
|
CobhanBufferNapi::ValueToAllocationSize(env, input_value);
|
|
273
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
267
|
+
SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
|
|
274
268
|
maximum_stack_alloc_size, __func__);
|
|
275
269
|
|
|
276
270
|
CobhanBufferNapi partition_id(env, partition_id_string,
|
|
@@ -282,13 +276,13 @@ private:
|
|
|
282
276
|
char *output_cobhan_buffer;
|
|
283
277
|
size_t output_size_bytes =
|
|
284
278
|
CobhanBuffer::DataSizeToAllocationSize(input.get_data_len_bytes());
|
|
285
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
279
|
+
SCOPED_ALLOCATE_BUFFER(output_cobhan_buffer, output_size_bytes,
|
|
286
280
|
maximum_stack_alloc_size, __func__);
|
|
287
|
-
CobhanBufferNapi output(output_cobhan_buffer, output_size_bytes);
|
|
281
|
+
CobhanBufferNapi output(env, output_cobhan_buffer, output_size_bytes);
|
|
288
282
|
#else
|
|
289
283
|
CobhanBufferNapi partition_id(env, partition_id_string);
|
|
290
284
|
CobhanBufferNapi input(env, input_value);
|
|
291
|
-
CobhanBufferNapi output(input.get_data_len_bytes());
|
|
285
|
+
CobhanBufferNapi output(env, input.get_data_len_bytes());
|
|
292
286
|
#endif
|
|
293
287
|
|
|
294
288
|
// extern GoInt32 DecryptFromJson(void* partitionIdPtr, void* jsonPtr,
|
|
@@ -297,7 +291,7 @@ private:
|
|
|
297
291
|
|
|
298
292
|
CheckResult(env, result);
|
|
299
293
|
|
|
300
|
-
output_value = output.ToBuffer(
|
|
294
|
+
output_value = output.ToBuffer(); // NOLINT(*-slicing)
|
|
301
295
|
} catch (Napi::Error &e) {
|
|
302
296
|
e.ThrowAsJavaScriptException();
|
|
303
297
|
return env.Undefined();
|
|
@@ -321,7 +315,7 @@ private:
|
|
|
321
315
|
CobhanBufferNapi partition_id(env, partition_id_string);
|
|
322
316
|
CobhanBufferNapi input(env, input_value);
|
|
323
317
|
|
|
324
|
-
CobhanBufferNapi output(input.get_data_len_bytes());
|
|
318
|
+
CobhanBufferNapi output(env, input.get_data_len_bytes());
|
|
325
319
|
auto worker = new DecryptFromJsonWorker<Napi::Buffer<unsigned char>>(
|
|
326
320
|
env, this, partition_id, input, output);
|
|
327
321
|
worker->Queue();
|
|
@@ -351,14 +345,13 @@ private:
|
|
|
351
345
|
char *partition_id_cbuffer;
|
|
352
346
|
size_t partition_id_cbuffer_size =
|
|
353
347
|
CobhanBufferNapi::StringToAllocationSize(env, partition_id_string);
|
|
354
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
355
|
-
partition_id_cbuffer_size,
|
|
348
|
+
SCOPED_ALLOCATE_BUFFER(partition_id_cbuffer, partition_id_cbuffer_size,
|
|
356
349
|
maximum_stack_alloc_size, __func__);
|
|
357
350
|
|
|
358
351
|
char *input_cbuffer;
|
|
359
352
|
size_t input_cbuffer_size =
|
|
360
353
|
CobhanBufferNapi::ValueToAllocationSize(env, input_value);
|
|
361
|
-
SCOPED_ALLOCATE_BUFFER(
|
|
354
|
+
SCOPED_ALLOCATE_BUFFER(input_cbuffer, input_cbuffer_size,
|
|
362
355
|
maximum_stack_alloc_size, __func__);
|
|
363
356
|
|
|
364
357
|
CobhanBufferNapi partition_id(env, partition_id_string,
|
|
@@ -367,11 +360,11 @@ private:
|
|
|
367
360
|
CobhanBufferNapi input(env, input_value, input_cbuffer,
|
|
368
361
|
input_cbuffer_size);
|
|
369
362
|
|
|
370
|
-
CobhanBufferNapi output(input.get_data_len_bytes());
|
|
363
|
+
CobhanBufferNapi output(env, input.get_data_len_bytes());
|
|
371
364
|
#else
|
|
372
365
|
CobhanBufferNapi partition_id(env, partition_id_string);
|
|
373
366
|
CobhanBufferNapi input(env, input_value);
|
|
374
|
-
CobhanBufferNapi output(input.get_data_len_bytes());
|
|
367
|
+
CobhanBufferNapi output(env, input.get_data_len_bytes());
|
|
375
368
|
#endif
|
|
376
369
|
|
|
377
370
|
GoInt32 result = DecryptFromJson(partition_id, input, output);
|
|
@@ -401,7 +394,7 @@ private:
|
|
|
401
394
|
CobhanBufferNapi partition_id(env, partition_id_string);
|
|
402
395
|
CobhanBufferNapi input(env, input_value);
|
|
403
396
|
|
|
404
|
-
CobhanBufferNapi output(input.get_data_len_bytes());
|
|
397
|
+
CobhanBufferNapi output(env, input.get_data_len_bytes());
|
|
405
398
|
|
|
406
399
|
auto worker = new DecryptFromJsonWorker<Napi::String>(
|
|
407
400
|
env, this, partition_id, input, output);
|
|
@@ -417,42 +410,96 @@ private:
|
|
|
417
410
|
}
|
|
418
411
|
}
|
|
419
412
|
|
|
413
|
+
void SetEnv(const Napi::CallbackInfo &info) {
|
|
414
|
+
Napi::Env env = info.Env();
|
|
415
|
+
Napi::HandleScope scope(env);
|
|
416
|
+
try {
|
|
417
|
+
NapiUtils::RequireParameterCount(info, 1);
|
|
418
|
+
CobhanBufferNapi env_json(env, info[0]);
|
|
419
|
+
::SetEnv(env_json);
|
|
420
|
+
} catch (Napi::Error &e) {
|
|
421
|
+
e.ThrowAsJavaScriptException();
|
|
422
|
+
return;
|
|
423
|
+
} catch (const std::exception &e) {
|
|
424
|
+
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
420
429
|
void SetMaxStackAllocItemSize(const Napi::CallbackInfo &info) {
|
|
421
|
-
|
|
430
|
+
Napi::Env env = info.Env();
|
|
431
|
+
Napi::HandleScope scope(env);
|
|
432
|
+
try {
|
|
433
|
+
NapiUtils::RequireParameterCount(info, 1);
|
|
422
434
|
|
|
423
|
-
|
|
424
|
-
|
|
435
|
+
Napi::Number item_size = info[0].ToNumber();
|
|
436
|
+
auto new_size = (size_t)item_size.Int32Value();
|
|
425
437
|
|
|
426
|
-
|
|
427
|
-
|
|
438
|
+
maximum_stack_alloc_size = new_size;
|
|
439
|
+
} catch (Napi::Error &e) {
|
|
440
|
+
e.ThrowAsJavaScriptException();
|
|
441
|
+
return;
|
|
442
|
+
} catch (const std::exception &e) {
|
|
443
|
+
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
428
446
|
}
|
|
429
447
|
|
|
430
448
|
void SetSafetyPaddingOverhead(const Napi::CallbackInfo &info) {
|
|
431
|
-
|
|
449
|
+
Napi::Env env = info.Env();
|
|
450
|
+
Napi::HandleScope scope(env);
|
|
451
|
+
try {
|
|
452
|
+
NapiUtils::RequireParameterCount(info, 1);
|
|
432
453
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
454
|
+
// Napi::Number safety_padding_number = info[0].ToNumber();
|
|
455
|
+
// auto new_safety_padding_bytes = (size_t)
|
|
456
|
+
// safety_padding_number.Int32Value(); Safety padding size is now fixed -
|
|
457
|
+
// ignore the input set_safety_padding_bytes(new_safety_padding_bytes);
|
|
458
|
+
} catch (Napi::Error &e) {
|
|
459
|
+
e.ThrowAsJavaScriptException();
|
|
460
|
+
return;
|
|
461
|
+
} catch (const std::exception &e) {
|
|
462
|
+
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
437
465
|
}
|
|
438
466
|
|
|
439
467
|
Napi::Value
|
|
440
468
|
GetSetupStatus(const Napi::CallbackInfo
|
|
441
469
|
&info) { // NOLINT(*-convert-member-functions-to-static)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
470
|
+
Napi::Env env = info.Env();
|
|
471
|
+
Napi::HandleScope scope(env);
|
|
472
|
+
try {
|
|
473
|
+
int32_t setup_status = setup_state.load(std::memory_order_acquire);
|
|
474
|
+
return Napi::Boolean::New(info.Env(), setup_status != 0);
|
|
475
|
+
} catch (Napi::Error &e) {
|
|
476
|
+
e.ThrowAsJavaScriptException();
|
|
477
|
+
return env.Undefined();
|
|
478
|
+
} catch (const std::exception &e) {
|
|
479
|
+
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
|
|
480
|
+
return env.Undefined();
|
|
481
|
+
}
|
|
445
482
|
}
|
|
446
483
|
|
|
447
484
|
void SetLogHook(const Napi::CallbackInfo &info) {
|
|
448
|
-
NapiUtils::RequireParameterCount(info, 1);
|
|
449
485
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
486
|
+
Napi::Env env = info.Env();
|
|
487
|
+
Napi::HandleScope scope(env);
|
|
488
|
+
try {
|
|
489
|
+
NapiUtils::RequireParameterCount(info, 1);
|
|
490
|
+
|
|
491
|
+
if (unlikely(!info[0].IsFunction())) {
|
|
492
|
+
NapiUtils::ThrowException(info.Env(), "Expected a function");
|
|
493
|
+
}
|
|
453
494
|
|
|
454
|
-
|
|
455
|
-
|
|
495
|
+
logger.set_log_hook(info[0].As<Napi::Function>());
|
|
496
|
+
} catch (Napi::Error &e) {
|
|
497
|
+
e.ThrowAsJavaScriptException();
|
|
498
|
+
return;
|
|
499
|
+
} catch (const std::exception &e) {
|
|
500
|
+
Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
456
503
|
}
|
|
457
504
|
|
|
458
505
|
void BeginSetupAsherah(const Napi::Env &env, const char *func_name,
|
|
@@ -487,7 +534,8 @@ private:
|
|
|
487
534
|
|
|
488
535
|
auto old_setup_state = setup_state.exchange(1, std::memory_order_acq_rel);
|
|
489
536
|
if (unlikely(old_setup_state != 0)) {
|
|
490
|
-
NapiUtils::ThrowException(
|
|
537
|
+
NapiUtils::ThrowException(
|
|
538
|
+
env, "EndSetupAsherah: lost race to mark setup_state?!");
|
|
491
539
|
}
|
|
492
540
|
}
|
|
493
541
|
|
|
@@ -506,14 +554,15 @@ private:
|
|
|
506
554
|
Napi::String &output_string) {
|
|
507
555
|
CheckResult(env, result);
|
|
508
556
|
|
|
509
|
-
output_string = output.ToString(
|
|
557
|
+
output_string = output.ToString();
|
|
510
558
|
}
|
|
511
559
|
|
|
512
|
-
void
|
|
513
|
-
|
|
560
|
+
[[maybe_unused]] void
|
|
561
|
+
EndEncryptToJson(Napi::Env env, CobhanBufferNapi &output, GoInt32 result,
|
|
562
|
+
Napi::Buffer<unsigned char> &output_buffer) {
|
|
514
563
|
CheckResult(env, result);
|
|
515
564
|
|
|
516
|
-
output_buffer = output.ToBuffer(
|
|
565
|
+
output_buffer = output.ToBuffer();
|
|
517
566
|
}
|
|
518
567
|
|
|
519
568
|
void BeginDecryptFromJson(const Napi::Env &env, const char *func_name,
|
|
@@ -532,14 +581,14 @@ private:
|
|
|
532
581
|
Napi::Buffer<unsigned char> &output_buffer) {
|
|
533
582
|
CheckResult(env, result);
|
|
534
583
|
|
|
535
|
-
output_buffer = output.ToBuffer(
|
|
584
|
+
output_buffer = output.ToBuffer();
|
|
536
585
|
}
|
|
537
586
|
|
|
538
587
|
void EndDecryptFromJson(Napi::Env &env, CobhanBufferNapi &output,
|
|
539
588
|
GoInt32 result, Napi::String &output_string) {
|
|
540
589
|
CheckResult(env, result);
|
|
541
590
|
|
|
542
|
-
output_string = output.ToString(
|
|
591
|
+
output_string = output.ToString();
|
|
543
592
|
}
|
|
544
593
|
|
|
545
594
|
void BeginShutdownAsherah(const Napi::Env &env, const char *func_name,
|
|
@@ -551,7 +600,8 @@ private:
|
|
|
551
600
|
void EndShutdownAsherah(Napi::Env &env) {
|
|
552
601
|
auto old_setup_state = setup_state.exchange(0, std::memory_order_acq_rel);
|
|
553
602
|
if (unlikely(old_setup_state == 0)) {
|
|
554
|
-
NapiUtils::ThrowException(
|
|
603
|
+
NapiUtils::ThrowException(
|
|
604
|
+
env, "EndSetupAsherah: lost race to mark setup_state?!");
|
|
555
605
|
}
|
|
556
606
|
}
|
|
557
607
|
|
|
@@ -626,10 +676,10 @@ private:
|
|
|
626
676
|
Napi::Value OnOKTask(Napi::Env &env) override {
|
|
627
677
|
T output_result;
|
|
628
678
|
asherah->EndDecryptFromJson(env, output, result, output_result);
|
|
629
|
-
return output_result;
|
|
679
|
+
return output_result; // NOLINT(*-slicing)
|
|
630
680
|
}
|
|
631
681
|
|
|
632
|
-
|
|
682
|
+
private:
|
|
633
683
|
CobhanBufferNapi partition_id;
|
|
634
684
|
CobhanBufferNapi input;
|
|
635
685
|
CobhanBufferNapi output;
|
|
@@ -663,18 +713,23 @@ private:
|
|
|
663
713
|
|
|
664
714
|
void RequireAsherahSetup(const Napi::Env &env, const char *func_name) {
|
|
665
715
|
if (unlikely(setup_state.load(std::memory_order_acquire) == 0)) {
|
|
666
|
-
NapiUtils::ThrowException(
|
|
716
|
+
NapiUtils::ThrowException(
|
|
717
|
+
env,
|
|
718
|
+
std::string(func_name) + ": RequireAsherahSetup: setup() not called");
|
|
667
719
|
}
|
|
668
720
|
}
|
|
669
721
|
|
|
670
722
|
void RequireAsherahNotSetup(const Napi::Env &env, const char *func_name) {
|
|
671
723
|
if (unlikely(setup_state.load(std::memory_order_acquire) != 0)) {
|
|
672
|
-
NapiUtils::ThrowException(
|
|
724
|
+
NapiUtils::ThrowException(
|
|
725
|
+
env, std::string(func_name) +
|
|
726
|
+
": RequireAsherahNotSetup: setup() already called");
|
|
673
727
|
}
|
|
674
728
|
}
|
|
675
729
|
|
|
676
|
-
__attribute__((always_inline)) inline size_t
|
|
677
|
-
EstimateAsherahOutputSize(size_t data_byte_len,
|
|
730
|
+
[[nodiscard]] __attribute__((always_inline)) inline size_t
|
|
731
|
+
EstimateAsherahOutputSize(size_t data_byte_len,
|
|
732
|
+
size_t partition_byte_len) const {
|
|
678
733
|
const size_t est_encryption_overhead = 48;
|
|
679
734
|
const size_t est_envelope_overhead = 185;
|
|
680
735
|
const double base64_overhead = 1.34;
|
|
@@ -733,3 +788,5 @@ private:
|
|
|
733
788
|
};
|
|
734
789
|
|
|
735
790
|
NODE_API_NAMED_ADDON(asherah, Asherah)
|
|
791
|
+
|
|
792
|
+
#pragma clang diagnostic pop
|
package/src/asherah.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
// noinspection JSUnusedGlobalSymbols,DuplicatedCode
|
|
2
|
+
|
|
1
3
|
/// <reference types="node" />
|
|
2
4
|
export type AsherahConfig = {
|
|
3
5
|
/** The name of this service (Required) */
|
|
@@ -58,3 +60,4 @@ export declare function set_max_stack_alloc_item_size(max_item_size: number): vo
|
|
|
58
60
|
export declare function set_safety_padding_overhead(safety_padding_overhead: number): void;
|
|
59
61
|
export declare function set_log_hook(logHook: LogHookCallback): void;
|
|
60
62
|
export declare function get_setup_status(): boolean;
|
|
63
|
+
export declare function setenv(environment: string): void;
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
// asherah_async_worker.h
|
|
2
1
|
#ifndef ASHERAH_ASYNC_WORKER_H
|
|
3
2
|
#define ASHERAH_ASYNC_WORKER_H
|
|
4
3
|
|
|
5
4
|
#include <napi.h>
|
|
6
5
|
#include <stdexcept>
|
|
7
6
|
|
|
8
|
-
#ifndef NAPI_CPP_EXCEPTIONS
|
|
9
|
-
#error Support for C++ exceptions is required
|
|
10
|
-
#endif
|
|
11
|
-
|
|
12
7
|
class Asherah;
|
|
13
8
|
|
|
14
9
|
template <typename ResultType>
|
package/src/cobhan_buffer.h
CHANGED
|
@@ -52,16 +52,16 @@ public:
|
|
|
52
52
|
return static_cast<void *>(cbuffer);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
char *get_data_ptr() const { return data_ptr; }
|
|
55
|
+
[[nodiscard]] char *get_data_ptr() const { return data_ptr; }
|
|
56
56
|
|
|
57
|
-
size_t get_data_len_bytes() const { return *data_len_ptr; }
|
|
57
|
+
[[nodiscard]] size_t get_data_len_bytes() const { return *data_len_ptr; }
|
|
58
58
|
|
|
59
59
|
~CobhanBuffer() {
|
|
60
60
|
verify_canaries();
|
|
61
61
|
cleanup();
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
[[nodiscard]] __attribute__((unused)) std::string DebugPrintStdErr() const {
|
|
65
65
|
auto debug_string = std::string(get_data_ptr(), get_data_len_bytes());
|
|
66
66
|
std::ostringstream debug_output;
|
|
67
67
|
debug_output << "CobhanBuffer { " << std::endl
|
|
@@ -127,7 +127,7 @@ protected:
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
size_t get_allocation_size() const { return allocation_size; }
|
|
130
|
+
[[nodiscard]] size_t get_allocation_size() const { return allocation_size; }
|
|
131
131
|
|
|
132
132
|
void set_data_len_bytes(size_t data_len_bytes) {
|
|
133
133
|
if (data_len_bytes > max_int32_size) {
|
package/src/cobhan_buffer_napi.h
CHANGED
|
@@ -6,35 +6,30 @@
|
|
|
6
6
|
#include <napi.h>
|
|
7
7
|
#include <stdexcept>
|
|
8
8
|
|
|
9
|
-
#ifndef NAPI_CPP_EXCEPTIONS
|
|
10
|
-
#error Support for C++ exceptions is required
|
|
11
|
-
#endif
|
|
12
|
-
|
|
13
9
|
class CobhanBufferNapi : public CobhanBuffer {
|
|
14
10
|
public:
|
|
15
11
|
// Constructor from a Napi::String
|
|
16
12
|
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString)
|
|
17
|
-
: CobhanBuffer(NapiUtils::GetUtf8StringLength(env, napiString) +
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
copy_from_string(
|
|
13
|
+
: CobhanBuffer(NapiUtils::GetUtf8StringLength(env, napiString) + 1),
|
|
14
|
+
env(env) { // Add one for possible NULL delimiter due to Node
|
|
15
|
+
// string functions
|
|
16
|
+
copy_from_string(napiString);
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
// Constructor from Napi::Buffer<unsigned char>
|
|
24
20
|
explicit CobhanBufferNapi(const Napi::Env &env,
|
|
25
21
|
const Napi::Buffer<unsigned char> &napiBuffer)
|
|
26
|
-
: CobhanBuffer(napiBuffer.ByteLength()) {
|
|
22
|
+
: CobhanBuffer(napiBuffer.ByteLength()), env(env) {
|
|
27
23
|
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.ByteLength());
|
|
28
24
|
}
|
|
29
25
|
|
|
30
26
|
// Constructor from Napi::Value
|
|
31
27
|
explicit CobhanBufferNapi(const Napi::Env &env, const Napi::Value &napiValue)
|
|
32
|
-
: CobhanBuffer(ValueToDataSize(env, napiValue)) {
|
|
28
|
+
: CobhanBuffer(ValueToDataSize(env, napiValue)), env(env) {
|
|
33
29
|
if (napiValue.IsString()) {
|
|
34
|
-
copy_from_string(
|
|
30
|
+
copy_from_string(napiValue.As<Napi::String>());
|
|
35
31
|
} else if (napiValue.IsBuffer()) {
|
|
36
|
-
Napi::Buffer<unsigned char
|
|
37
|
-
napiValue.As<Napi::Buffer<unsigned char>>();
|
|
32
|
+
auto napiBuffer = napiValue.As<Napi::Buffer<unsigned char>>();
|
|
38
33
|
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
39
34
|
} else {
|
|
40
35
|
NapiUtils::ThrowException(
|
|
@@ -47,26 +42,25 @@ public:
|
|
|
47
42
|
CobhanBufferNapi(const Napi::Env &env,
|
|
48
43
|
const Napi::Buffer<unsigned char> &napiBuffer, char *cbuffer,
|
|
49
44
|
size_t allocation_size)
|
|
50
|
-
: CobhanBuffer(cbuffer, allocation_size) {
|
|
45
|
+
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
51
46
|
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
52
47
|
}
|
|
53
48
|
|
|
54
49
|
// Constructor from a Napi::String to an externally allocated buffer
|
|
55
50
|
CobhanBufferNapi(const Napi::Env &env, const Napi::String &napiString,
|
|
56
51
|
char *cbuffer, size_t allocation_size)
|
|
57
|
-
: CobhanBuffer(cbuffer, allocation_size) {
|
|
58
|
-
copy_from_string(
|
|
52
|
+
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
53
|
+
copy_from_string(napiString);
|
|
59
54
|
}
|
|
60
55
|
|
|
61
56
|
// Constructor from a Napi::String to an externally allocated buffer
|
|
62
57
|
CobhanBufferNapi(const Napi::Env &env, const Napi::Value &napiValue,
|
|
63
58
|
char *cbuffer, size_t allocation_size)
|
|
64
|
-
: CobhanBuffer(cbuffer, allocation_size) {
|
|
59
|
+
: CobhanBuffer(cbuffer, allocation_size), env(env) {
|
|
65
60
|
if (napiValue.IsString()) {
|
|
66
|
-
copy_from_string(
|
|
61
|
+
copy_from_string(napiValue.As<Napi::String>());
|
|
67
62
|
} else if (napiValue.IsBuffer()) {
|
|
68
|
-
Napi::Buffer<unsigned char
|
|
69
|
-
napiValue.As<Napi::Buffer<unsigned char>>();
|
|
63
|
+
auto napiBuffer = napiValue.As<Napi::Buffer<unsigned char>>();
|
|
70
64
|
std::memcpy(get_data_ptr(), napiBuffer.Data(), napiBuffer.Length());
|
|
71
65
|
} else {
|
|
72
66
|
NapiUtils::ThrowException(
|
|
@@ -77,17 +71,18 @@ public:
|
|
|
77
71
|
|
|
78
72
|
// Constructor from size_t representing data length in bytes (not allocation
|
|
79
73
|
// size)
|
|
80
|
-
explicit CobhanBufferNapi(size_t data_len_bytes)
|
|
81
|
-
: CobhanBuffer(data_len_bytes) {}
|
|
74
|
+
explicit CobhanBufferNapi(const Napi::Env &env, size_t data_len_bytes)
|
|
75
|
+
: CobhanBuffer(data_len_bytes), env(env) {}
|
|
82
76
|
|
|
83
77
|
// Constructor from externally allocated char* and size_t representing
|
|
84
78
|
// allocation size in bytes
|
|
85
|
-
explicit CobhanBufferNapi(char *cbuffer,
|
|
86
|
-
|
|
79
|
+
explicit CobhanBufferNapi(const Napi::Env &env, char *cbuffer,
|
|
80
|
+
size_t allocation_size)
|
|
81
|
+
: CobhanBuffer(cbuffer, allocation_size), env(env) {}
|
|
87
82
|
|
|
88
83
|
// Move constructor
|
|
89
84
|
CobhanBufferNapi(CobhanBufferNapi &&other) noexcept
|
|
90
|
-
: CobhanBuffer(std::move(other)) {}
|
|
85
|
+
: CobhanBuffer(std::move(other)), env(other.env) {}
|
|
91
86
|
|
|
92
87
|
// Move assignment operator
|
|
93
88
|
CobhanBufferNapi &operator=(CobhanBufferNapi &&other) noexcept {
|
|
@@ -98,7 +93,7 @@ public:
|
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
// Returns a Napi::String from the buffer using napi_create_string_utf8
|
|
101
|
-
Napi::String ToString(
|
|
96
|
+
[[nodiscard]] Napi::String ToString() const {
|
|
102
97
|
napi_value napiStr;
|
|
103
98
|
napi_status status = napi_create_string_utf8(
|
|
104
99
|
env, get_data_ptr(), get_data_len_bytes(), &napiStr);
|
|
@@ -113,7 +108,7 @@ public:
|
|
|
113
108
|
}
|
|
114
109
|
|
|
115
110
|
// Returns a Napi::Buffer<unsigned char> from the buffer
|
|
116
|
-
Napi::Buffer<unsigned char> ToBuffer(
|
|
111
|
+
[[nodiscard]] Napi::Buffer<unsigned char> ToBuffer() const {
|
|
117
112
|
auto buffer = Napi::Buffer<unsigned char>::Copy(
|
|
118
113
|
env, reinterpret_cast<unsigned char *>(get_data_ptr()),
|
|
119
114
|
get_data_len_bytes());
|
|
@@ -167,9 +162,11 @@ public:
|
|
|
167
162
|
}
|
|
168
163
|
|
|
169
164
|
private:
|
|
170
|
-
|
|
171
|
-
size_t str_len = NapiUtils::GetUtf8StringLength(env, napiString);
|
|
165
|
+
Napi::Env env;
|
|
172
166
|
|
|
167
|
+
void copy_from_string(const Napi::String &napiString) {
|
|
168
|
+
size_t str_len = NapiUtils::GetUtf8StringLength(env, napiString);
|
|
169
|
+
// Add one for NULL delimiter due to napi_get_value_string_utf8
|
|
173
170
|
size_t allocation_size =
|
|
174
171
|
CobhanBuffer::DataSizeToAllocationSize(str_len) + 1;
|
|
175
172
|
|
|
@@ -179,6 +176,7 @@ private:
|
|
|
179
176
|
"Buffer allocation size is insufficient to hold the Napi::String.");
|
|
180
177
|
}
|
|
181
178
|
|
|
179
|
+
// Bytes written is the number of bytes copied, excluding the NULL
|
|
182
180
|
size_t bytes_written;
|
|
183
181
|
napi_status status = napi_get_value_string_utf8(
|
|
184
182
|
env, napiString, get_data_ptr(), str_len + 1, &bytes_written);
|
|
@@ -189,6 +187,7 @@ private:
|
|
|
189
187
|
", Bytes Written: " + std::to_string(bytes_written));
|
|
190
188
|
}
|
|
191
189
|
|
|
190
|
+
// Update our data length to the actual string length
|
|
192
191
|
set_data_len_bytes(str_len);
|
|
193
192
|
}
|
|
194
193
|
};
|
package/src/logging.h
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
+
#pragma clang diagnostic push
|
|
2
|
+
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
|
|
3
|
+
|
|
1
4
|
#ifndef LOGGING_H
|
|
2
5
|
#define LOGGING_H
|
|
6
|
+
|
|
7
|
+
#include <cstddef> // size_t
|
|
8
|
+
#include <cstdint> // int32_t
|
|
3
9
|
#include <sstream> // std::ostringstream
|
|
4
10
|
#include <string> // std::string
|
|
5
|
-
#include <cstdint> // int32_t
|
|
6
|
-
#include <cstddef> // size_t
|
|
7
11
|
|
|
8
12
|
class Logger {
|
|
9
13
|
public:
|
|
10
|
-
|
|
14
|
+
[[maybe_unused]] void set_verbose_flag(int32_t verbose) { verbose_flag = verbose != 0; };
|
|
11
15
|
|
|
12
16
|
virtual void debug_log(const char *function_name,
|
|
13
17
|
const char *message) const = 0;
|
|
@@ -34,21 +38,12 @@ public:
|
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
protected:
|
|
37
|
-
explicit Logger(const std::string &system_name);
|
|
38
|
-
|
|
39
41
|
bool verbose_flag = false;
|
|
40
42
|
std::string system_name;
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
void stderr_debug_log(const char *function_name,
|
|
44
|
-
const std::string &message) const;
|
|
45
|
-
void stderr_debug_log_alloca(const char *function_name,
|
|
46
|
-
const char *variable_name, size_t length) const;
|
|
47
|
-
void stderr_debug_log_new(const char *function_name,
|
|
48
|
-
const char *variable_name, size_t length) const;
|
|
49
|
-
void stderr_error_log(const char *function_name, const char *message) const;
|
|
50
|
-
void stderr_error_log(const char *function_name,
|
|
51
|
-
const std::string &message) const;
|
|
44
|
+
explicit Logger(std::string system_name) : system_name(std::move(system_name)) {}
|
|
52
45
|
};
|
|
53
46
|
|
|
54
47
|
#endif // LOGGING_H
|
|
48
|
+
|
|
49
|
+
#pragma clang diagnostic pop
|
package/src/logging_napi.cc
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
#include "logging_napi.h"
|
|
2
2
|
#include "napi_utils.h"
|
|
3
3
|
|
|
4
|
-
LoggerNapi::LoggerNapi(Napi::Env &env, std::string system_name)
|
|
5
|
-
:
|
|
4
|
+
LoggerNapi::LoggerNapi(Napi::Env &env, const std::string &system_name)
|
|
5
|
+
: StdErrLogger(system_name), log_hook(Napi::FunctionReference()), env(env) {
|
|
6
|
+
}
|
|
6
7
|
|
|
7
|
-
LoggerNapi::LoggerNapi(Napi::Env &env,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
[[maybe_unused]] LoggerNapi::LoggerNapi(Napi::Env &env,
|
|
9
|
+
const std::string &system_name,
|
|
10
|
+
Napi::Function new_log_hook)
|
|
11
|
+
: StdErrLogger(system_name), env(env) {
|
|
10
12
|
if (unlikely(new_log_hook.IsEmpty())) {
|
|
11
|
-
NapiUtils::ThrowException(env,
|
|
13
|
+
NapiUtils::ThrowException(env,
|
|
14
|
+
system_name + ": new_log_hook cannot be nullptr");
|
|
12
15
|
}
|
|
13
16
|
log_hook = Napi::Persistent(new_log_hook);
|
|
14
17
|
}
|
|
@@ -22,7 +25,8 @@ LoggerNapi::~LoggerNapi() {
|
|
|
22
25
|
|
|
23
26
|
void LoggerNapi::set_log_hook(Napi::Function new_log_hook) {
|
|
24
27
|
if (unlikely(new_log_hook.IsUndefined() || new_log_hook.IsEmpty())) {
|
|
25
|
-
NapiUtils::ThrowException(env,
|
|
28
|
+
NapiUtils::ThrowException(env,
|
|
29
|
+
system_name + ": new_log_hook cannot be empty");
|
|
26
30
|
}
|
|
27
31
|
auto old_log_hook = std::exchange(log_hook, Napi::Persistent(new_log_hook));
|
|
28
32
|
if (!old_log_hook.IsEmpty()) {
|
|
@@ -36,17 +40,19 @@ void LoggerNapi::call_log_hook(int level, const std::string &message) const {
|
|
|
36
40
|
}
|
|
37
41
|
Napi::HandleScope scope(env);
|
|
38
42
|
Napi::Function log_hook_function = log_hook.Value();
|
|
39
|
-
log_hook_function.Call(
|
|
40
|
-
|
|
43
|
+
log_hook_function.Call(
|
|
44
|
+
{Napi::Number::New(env, level),
|
|
45
|
+
Napi::String::New(env, system_name + ": " + message)});
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
void LoggerNapi::debug_log(const char *function_name,
|
|
44
49
|
const char *message) const {
|
|
45
50
|
if (unlikely(verbose_flag)) {
|
|
46
51
|
if (unlikely(log_hook.IsEmpty())) {
|
|
47
|
-
|
|
52
|
+
StdErrLogger::debug_log(function_name, message);
|
|
48
53
|
} else {
|
|
49
|
-
call_log_hook(posix_log_level_debug,
|
|
54
|
+
call_log_hook(posix_log_level_debug,
|
|
55
|
+
system_name + ": " + function_name + ": " + message);
|
|
50
56
|
}
|
|
51
57
|
}
|
|
52
58
|
}
|
|
@@ -55,9 +61,10 @@ void LoggerNapi::debug_log(const char *function_name,
|
|
|
55
61
|
const std::string &message) const {
|
|
56
62
|
if (unlikely(verbose_flag)) {
|
|
57
63
|
if (unlikely(log_hook.IsEmpty())) {
|
|
58
|
-
|
|
64
|
+
StdErrLogger::debug_log(function_name, message);
|
|
59
65
|
} else {
|
|
60
|
-
call_log_hook(posix_log_level_debug,
|
|
66
|
+
call_log_hook(posix_log_level_debug,
|
|
67
|
+
system_name + ": " + function_name + ": " + message);
|
|
61
68
|
}
|
|
62
69
|
}
|
|
63
70
|
}
|
|
@@ -67,12 +74,12 @@ void LoggerNapi::debug_log_alloca(const char *function_name,
|
|
|
67
74
|
size_t length) const {
|
|
68
75
|
if (unlikely(verbose_flag)) {
|
|
69
76
|
if (unlikely(log_hook.IsEmpty())) {
|
|
70
|
-
|
|
77
|
+
StdErrLogger::debug_log_alloca(function_name, variable_name, length);
|
|
71
78
|
} else {
|
|
72
|
-
call_log_hook(posix_log_level_debug,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
call_log_hook(posix_log_level_debug,
|
|
80
|
+
system_name + ": " + function_name + ": Calling alloca(" +
|
|
81
|
+
std::to_string(length) + ") (stack) for " +
|
|
82
|
+
variable_name);
|
|
76
83
|
}
|
|
77
84
|
}
|
|
78
85
|
}
|
|
@@ -81,12 +88,12 @@ void LoggerNapi::debug_log_new(const char *function_name,
|
|
|
81
88
|
const char *variable_name, size_t length) const {
|
|
82
89
|
if (unlikely(verbose_flag)) {
|
|
83
90
|
if (unlikely(log_hook.IsEmpty())) {
|
|
84
|
-
|
|
91
|
+
StdErrLogger::debug_log_new(function_name, variable_name, length);
|
|
85
92
|
} else {
|
|
86
93
|
call_log_hook(posix_log_level_debug, system_name + ": " + function_name +
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
": Calling new[" +
|
|
95
|
+
std::to_string(length) +
|
|
96
|
+
"] (heap) for " + variable_name);
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
99
|
}
|
|
@@ -94,13 +101,15 @@ void LoggerNapi::debug_log_new(const char *function_name,
|
|
|
94
101
|
void LoggerNapi::error_log(const char *function_name,
|
|
95
102
|
const char *message) const {
|
|
96
103
|
if (likely(!log_hook.IsEmpty())) {
|
|
97
|
-
call_log_hook(posix_log_level_error,
|
|
104
|
+
call_log_hook(posix_log_level_error,
|
|
105
|
+
system_name + ": " + function_name + ": " + message);
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
|
|
101
109
|
void LoggerNapi::error_log(const char *function_name,
|
|
102
110
|
const std::string &message) const {
|
|
103
111
|
if (likely(!log_hook.IsEmpty())) {
|
|
104
|
-
call_log_hook(posix_log_level_error,
|
|
112
|
+
call_log_hook(posix_log_level_error,
|
|
113
|
+
system_name + ": " + function_name + ": " + message);
|
|
105
114
|
}
|
|
106
115
|
}
|
package/src/logging_napi.h
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#ifndef LOGGING_NAPI_H
|
|
2
2
|
#define LOGGING_NAPI_H
|
|
3
|
+
|
|
3
4
|
#include "hints.h"
|
|
4
5
|
#include "logging.h"
|
|
6
|
+
#include "logging_stderr.h"
|
|
5
7
|
#include <napi.h>
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
#error Support for C++ exceptions is required
|
|
9
|
-
#endif
|
|
10
|
-
|
|
11
|
-
class LoggerNapi : public Logger {
|
|
9
|
+
class LoggerNapi : public StdErrLogger {
|
|
12
10
|
public:
|
|
13
|
-
LoggerNapi(Napi::Env &env, std::string system_name);
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
LoggerNapi(Napi::Env &env, const std::string &system_name);
|
|
12
|
+
|
|
13
|
+
[[maybe_unused]] explicit LoggerNapi(Napi::Env &env,
|
|
14
|
+
const std::string &system_name,
|
|
15
|
+
Napi::Function new_log_hook);
|
|
16
16
|
~LoggerNapi();
|
|
17
17
|
|
|
18
18
|
void set_log_hook(Napi::Function new_log_hook);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
#include "
|
|
1
|
+
#include "logging_stderr.h"
|
|
2
2
|
#include "hints.h"
|
|
3
3
|
#include <iostream>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
StdErrLogger::StdErrLogger(const std::string &system_name)
|
|
6
|
+
: Logger(system_name) {}
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
void Logger::stderr_debug_log(const char *function_name, const char *message) const {
|
|
8
|
+
void StdErrLogger::debug_log(const char *function_name,
|
|
9
|
+
const char *message) const {
|
|
12
10
|
if (unlikely(verbose_flag)) {
|
|
13
11
|
std::cerr << system_name << ": [DEBUG] " << function_name << ": " << message
|
|
14
12
|
<< std::endl
|
|
@@ -16,8 +14,8 @@ void Logger::stderr_debug_log(const char *function_name, const char *message) co
|
|
|
16
14
|
}
|
|
17
15
|
}
|
|
18
16
|
|
|
19
|
-
void
|
|
20
|
-
|
|
17
|
+
void StdErrLogger::debug_log(const char *function_name,
|
|
18
|
+
const std::string &message) const {
|
|
21
19
|
if (unlikely(verbose_flag)) {
|
|
22
20
|
std::cerr << system_name << ": [DEBUG] " << function_name << ": " << message
|
|
23
21
|
<< std::endl
|
|
@@ -25,8 +23,9 @@ void Logger::stderr_debug_log(const char *function_name,
|
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
void
|
|
29
|
-
|
|
26
|
+
void StdErrLogger::debug_log_alloca(const char *function_name,
|
|
27
|
+
const char *variable_name,
|
|
28
|
+
size_t length) const {
|
|
30
29
|
if (unlikely(verbose_flag)) {
|
|
31
30
|
std::cerr << system_name << ": [DEBUG] " << function_name
|
|
32
31
|
<< ": Calling alloca(" << length << ") (stack) for "
|
|
@@ -35,8 +34,9 @@ void Logger::stderr_debug_log_alloca(
|
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
void
|
|
39
|
-
|
|
37
|
+
void StdErrLogger::debug_log_new(const char *function_name,
|
|
38
|
+
const char *variable_name,
|
|
39
|
+
size_t length) const {
|
|
40
40
|
if (unlikely(verbose_flag)) {
|
|
41
41
|
std::cerr << system_name << ": [DEBUG] " << function_name
|
|
42
42
|
<< ": Calling new[" << length << "] (heap) for " << variable_name
|
|
@@ -45,14 +45,15 @@ void Logger::stderr_debug_log_new(const char *function_name,
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
void
|
|
48
|
+
void StdErrLogger::error_log(const char *function_name,
|
|
49
|
+
const char *message) const {
|
|
49
50
|
std::cerr << system_name << ": [ERROR] " << function_name << ": " << message
|
|
50
51
|
<< std::endl
|
|
51
52
|
<< std::flush;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
void
|
|
55
|
-
|
|
55
|
+
void StdErrLogger::error_log(const char *function_name,
|
|
56
|
+
const std::string &message) const {
|
|
56
57
|
std::cerr << system_name << ": [ERROR] " << function_name << ": " << message
|
|
57
58
|
<< std::endl
|
|
58
59
|
<< std::flush;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#ifndef STDERR_LOGGER_H
|
|
2
|
+
#define STDERR_LOGGER_H
|
|
3
|
+
|
|
4
|
+
#include "logging.h"
|
|
5
|
+
|
|
6
|
+
class StdErrLogger : public Logger {
|
|
7
|
+
public:
|
|
8
|
+
StdErrLogger() = delete;
|
|
9
|
+
explicit StdErrLogger(const std::string &system_name);
|
|
10
|
+
|
|
11
|
+
void debug_log(const char *function_name, const char *message) const override;
|
|
12
|
+
void debug_log(const char *function_name,
|
|
13
|
+
const std::string &message) const override;
|
|
14
|
+
void debug_log_alloca(const char *function_name, const char *variable_name,
|
|
15
|
+
size_t length) const override;
|
|
16
|
+
void debug_log_new(const char *function_name, const char *variable_name,
|
|
17
|
+
size_t length) const override;
|
|
18
|
+
void error_log(const char *function_name, const char *message) const override;
|
|
19
|
+
void error_log(const char *function_name,
|
|
20
|
+
const std::string &message) const override;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
#endif // STDERR_LOGGER_H
|
package/src/napi_utils.h
CHANGED
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
#include <napi.h>
|
|
6
6
|
#include <stdexcept>
|
|
7
7
|
#include <string>
|
|
8
|
-
#ifndef NAPI_CPP_EXCEPTIONS
|
|
9
|
-
#error Support for C++ exceptions is required
|
|
10
|
-
#endif
|
|
11
8
|
|
|
12
9
|
class NapiUtils {
|
|
13
10
|
public:
|
|
@@ -26,7 +23,7 @@ public:
|
|
|
26
23
|
|
|
27
24
|
[[noreturn]] static void ThrowException(const Napi::Env &env,
|
|
28
25
|
const std::string &message) {
|
|
29
|
-
//throw std::runtime_error(message);
|
|
26
|
+
// throw std::runtime_error(message);
|
|
30
27
|
throw Napi::Error::New(env, message);
|
|
31
28
|
}
|
|
32
29
|
|
|
@@ -41,12 +38,12 @@ public:
|
|
|
41
38
|
ThrowException(env, "Input value is undefined");
|
|
42
39
|
} else if (value.IsString()) {
|
|
43
40
|
// Convert string to object using JSON.parse
|
|
44
|
-
|
|
41
|
+
auto str = value.As<Napi::String>();
|
|
45
42
|
jsonString = str;
|
|
46
43
|
jsonObject = jsonParse.Call({str}).As<Napi::Object>();
|
|
47
44
|
} else if (value.IsObject()) {
|
|
48
45
|
// Convert object to string using JSON.stringify
|
|
49
|
-
|
|
46
|
+
auto obj = value.As<Napi::Object>();
|
|
50
47
|
if (jsonStringify.IsUndefined()) {
|
|
51
48
|
ThrowException(env, "jsonStringify is undefined");
|
|
52
49
|
} else if (jsonStringify.IsEmpty()) {
|
|
@@ -114,25 +111,31 @@ public:
|
|
|
114
111
|
if (likely(value.IsString())) {
|
|
115
112
|
return value.As<Napi::String>();
|
|
116
113
|
} else if (unlikely(value.IsUndefined())) {
|
|
117
|
-
ThrowException(env, std::string(func_name) +
|
|
114
|
+
ThrowException(env, std::string(func_name) +
|
|
115
|
+
": Expected String but received undefined");
|
|
118
116
|
} else if (unlikely(value.IsNull())) {
|
|
119
|
-
ThrowException(env, std::string(func_name) +
|
|
117
|
+
ThrowException(env, std::string(func_name) +
|
|
118
|
+
": Expected String but received null");
|
|
120
119
|
} else {
|
|
121
|
-
ThrowException(env, std::string(func_name) +
|
|
120
|
+
ThrowException(env, std::string(func_name) +
|
|
121
|
+
": Expected String but received unknown type");
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
__attribute__((unused)) static Napi::Buffer<unsigned char>
|
|
126
126
|
RequireParameterBuffer(const Napi::Env &env, const char *func_name,
|
|
127
127
|
Napi::Value value) {
|
|
128
128
|
if (likely(value.IsBuffer())) {
|
|
129
129
|
return value.As<Napi::Buffer<unsigned char>>();
|
|
130
130
|
} else if (unlikely(value.IsUndefined())) {
|
|
131
|
-
ThrowException(env, std::string(func_name) +
|
|
131
|
+
ThrowException(env, std::string(func_name) +
|
|
132
|
+
": Expected String but received undefined");
|
|
132
133
|
} else if (unlikely(value.IsNull())) {
|
|
133
|
-
ThrowException(env, std::string(func_name) +
|
|
134
|
+
ThrowException(env, std::string(func_name) +
|
|
135
|
+
": Expected String but received null");
|
|
134
136
|
} else {
|
|
135
|
-
ThrowException(env, std::string(func_name) +
|
|
137
|
+
ThrowException(env, std::string(func_name) +
|
|
138
|
+
": Expected String but received unknown type");
|
|
136
139
|
}
|
|
137
140
|
}
|
|
138
141
|
|
|
@@ -144,11 +147,14 @@ public:
|
|
|
144
147
|
} else if (likely(value.IsBuffer())) {
|
|
145
148
|
return value.As<Napi::Buffer<unsigned char>>(); // NOLINT(*-slicing)
|
|
146
149
|
} else if (unlikely(value.IsUndefined())) {
|
|
147
|
-
ThrowException(env, std::string(func_name) +
|
|
150
|
+
ThrowException(env, std::string(func_name) +
|
|
151
|
+
": Expected String but received undefined");
|
|
148
152
|
} else if (unlikely(value.IsNull())) {
|
|
149
|
-
ThrowException(env, std::string(func_name) +
|
|
153
|
+
ThrowException(env, std::string(func_name) +
|
|
154
|
+
": Expected String but received null");
|
|
150
155
|
} else {
|
|
151
|
-
ThrowException(env, std::string(func_name) +
|
|
156
|
+
ThrowException(env, std::string(func_name) +
|
|
157
|
+
": Expected String but received unknown type");
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
|
package/src/scoped_allocate.h
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#ifndef SCOPED_ALLOCATE_H
|
|
2
2
|
#define SCOPED_ALLOCATE_H
|
|
3
3
|
|
|
4
|
+
#ifdef USE_SCOPED_ALLOCATE_BUFFER
|
|
5
|
+
|
|
4
6
|
/*
|
|
5
7
|
This macro allows us to allocate a buffer either on the stack or on the heap.
|
|
6
8
|
If the requested buffer size is less than max_stack_alloc_size, we create the
|
|
@@ -13,36 +15,36 @@
|
|
|
13
15
|
will automatically free the allocated buffer when it goes out of scope.
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
|
-
#define SCOPED_ALLOCATE_BUFFER_UNIQUE_PTR(
|
|
17
|
-
|
|
18
|
-
function_name) \
|
|
18
|
+
#define SCOPED_ALLOCATE_BUFFER_UNIQUE_PTR(buffer, buffer_size, unique_ptr, \
|
|
19
|
+
max_stack_alloc_size, function_name) \
|
|
19
20
|
do { \
|
|
20
21
|
buffer = nullptr; \
|
|
21
22
|
if (buffer_size < max_stack_alloc_size) { \
|
|
22
23
|
/* If the buffer is small enough, allocate it on the stack */ \
|
|
23
|
-
logger.debug_log_alloca(function_name, #buffer, buffer_size); \
|
|
24
24
|
buffer = (char *)alloca(buffer_size); \
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
if (unlikely(buffer == nullptr)) { \
|
|
26
|
+
throw std::runtime_error(std::string(function_name) + " alloca(" + \
|
|
27
|
+
std::to_string(buffer_size) + \
|
|
28
|
+
") returned null"); \
|
|
29
|
+
} \
|
|
27
30
|
} else { \
|
|
28
31
|
/* Otherwise, allocate it on the heap */ \
|
|
29
|
-
logger.debug_log_new(function_name, #buffer, buffer_size); \
|
|
30
32
|
buffer = new (std::nothrow) char[buffer_size]; \
|
|
31
33
|
if (unlikely(buffer == nullptr)) { \
|
|
32
|
-
std::
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
throw std::runtime_error(error_msg); \
|
|
34
|
+
throw std::runtime_error(std::string(function_name) + " new[" + \
|
|
35
|
+
std::to_string(buffer_size) + \
|
|
36
|
+
"] returned null"); \
|
|
36
37
|
} \
|
|
37
38
|
unique_ptr.reset(buffer); \
|
|
38
39
|
} \
|
|
39
40
|
} while (0)
|
|
40
41
|
|
|
41
|
-
#define SCOPED_ALLOCATE_BUFFER(
|
|
42
|
-
|
|
42
|
+
#define SCOPED_ALLOCATE_BUFFER(buffer, buffer_size, max_stack_alloc_size, \
|
|
43
|
+
function_name) \
|
|
43
44
|
std::unique_ptr<char[]> buffer##_unique_ptr; \
|
|
44
|
-
SCOPED_ALLOCATE_BUFFER_UNIQUE_PTR(
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
SCOPED_ALLOCATE_BUFFER_UNIQUE_PTR(buffer, buffer_size, buffer##_unique_ptr, \
|
|
46
|
+
max_stack_alloc_size, function_name)
|
|
47
|
+
|
|
48
|
+
#endif // USE_SCOPED_ALLOCATE_BUFFER
|
|
47
49
|
|
|
48
50
|
#endif // SCOPED_ALLOCATE_H
|