iosignal 4.0.0 → 4.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/.vscode/settings.json +1 -1
- package/README.md +0 -2
- package/dist/io.d.ts +18 -11
- package/dist/io.js +5 -5
- package/dist/io.js.map +1 -1
- package/dist/io.min.js +5 -5
- package/dist/io.min.js.map +1 -1
- package/dist/iosignal.js +291 -251
- package/dist/types/client/IOCore.d.ts +15 -12
- package/dist/types/client/browser/IOWebSocket.d.ts +4 -0
- package/dist/types/common/constants.d.ts +29 -37
- package/index.js +4 -3
- package/package.json +1 -1
- package/src/auth/BohoAuth.js +48 -11
- package/src/auth/{Auth_File.js → key_providers/FileKeyProvider.js} +8 -20
- package/src/auth/{Auth_Redis.js → key_providers/RedisKeyProvider.js} +4 -7
- package/src/auth/key_providers/StringKeyProvider.js +54 -0
- package/src/client/IOCongSocket.js +4 -4
- package/src/client/IOCore.js +71 -70
- package/src/client/IOWS.js +6 -5
- package/src/client/browser/IOWebSocket.js +4 -4
- package/src/common/constants.js +32 -43
- package/src/common/util.js +3 -0
- package/src/server/Manager.js +4 -4
- package/src/server/Remote.js +4 -1
- package/src/server/RemoteCore.js +28 -19
- package/src/server/Server.js +7 -7
- package/README.en.md +0 -56
- package/auth_file_sample.js +0 -23
- package/auth_file_sample.json +0 -13
- package/src/auth/Auth_Env.js +0 -76
package/dist/iosignal.js
CHANGED
|
@@ -9,11 +9,11 @@ import require$$7 from 'url';
|
|
|
9
9
|
import require$$0 from 'zlib';
|
|
10
10
|
import fs, { readFileSync } from 'fs';
|
|
11
11
|
import path from 'path';
|
|
12
|
-
import require$$2 from 'os';
|
|
12
|
+
import require$$2, { networkInterfaces } from 'os';
|
|
13
13
|
import require$$0$1 from 'buffer';
|
|
14
14
|
import { memoryUsage } from 'process';
|
|
15
15
|
|
|
16
|
-
var version$1 = "4.
|
|
16
|
+
var version$1 = "4.6.0";
|
|
17
17
|
var pkg = {
|
|
18
18
|
version: version$1};
|
|
19
19
|
|
|
@@ -381,53 +381,41 @@ var eventemitter3Exports = requireEventemitter3();
|
|
|
381
381
|
var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventemitter3Exports);
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
|
-
* @typedef {object}
|
|
385
|
-
* @property {number}
|
|
384
|
+
* @typedef {object} STATE
|
|
385
|
+
* @property {number} CONNECTING
|
|
386
386
|
* @property {number} OPEN
|
|
387
|
-
* @property {number} CLOSING
|
|
388
|
-
* @property {number} CLOSED
|
|
389
387
|
* @property {number} SERVER_READY
|
|
390
|
-
* @property {number}
|
|
391
|
-
* @property {number}
|
|
388
|
+
* @property {number} AUTH_ACK
|
|
389
|
+
* @property {number} CLOSING
|
|
392
390
|
* @property {number} READY
|
|
391
|
+
* @property {number} AUTH_FAIL
|
|
392
|
+
* @property {number} AUTH_CLEAR
|
|
393
|
+
* @property {number} CLOSING
|
|
394
|
+
* @property {number} CLOSED
|
|
395
|
+
* @property {number} STOP
|
|
393
396
|
* @property {number} REDIRECTING
|
|
394
397
|
*/
|
|
395
|
-
// Client
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
OPEN:
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
398
|
+
// Client STATE: name and number
|
|
399
|
+
const STATE = {
|
|
400
|
+
CONNECTING: 0,
|
|
401
|
+
OPEN: 1,
|
|
402
|
+
SERVER_READY: 10,
|
|
403
|
+
AUTH_REQ: 11,
|
|
404
|
+
AUTH_NONCE: 12,
|
|
405
|
+
AUTH_HMAC: 13,
|
|
406
|
+
AUTH_ACK: 14,
|
|
407
|
+
AUTH_FAIL: 15,
|
|
408
|
+
AUTH_CLEAR: 16,
|
|
409
|
+
CID_REQ: 17,
|
|
410
|
+
CID_RES: 18,
|
|
411
|
+
READY: 19,
|
|
412
|
+
CLOSING: 2,
|
|
413
|
+
CLOSED: 3,
|
|
414
|
+
STOP: 4,
|
|
415
|
+
REDIRECTING: 5
|
|
406
416
|
};
|
|
407
|
-
for (let c in
|
|
417
|
+
for (let c in STATE) { STATE[STATE[c]] = c; }
|
|
408
418
|
|
|
409
|
-
/**
|
|
410
|
-
* @typedef {object} CLIENT_STATE
|
|
411
|
-
* @property {number} INIT
|
|
412
|
-
* @property {number} SENT_SERVER_READY
|
|
413
|
-
* @property {number} RECV_AUTH_REQ
|
|
414
|
-
* @property {number} SENT_SERVER_NONCE
|
|
415
|
-
* @property {number} RECV_AUTH_HMAC
|
|
416
|
-
* @property {number} AUTH_FAIL
|
|
417
|
-
* @property {number} AUTH_READY
|
|
418
|
-
* @property {number} CID_READY
|
|
419
|
-
*/
|
|
420
|
-
const CLIENT_STATE = {
|
|
421
|
-
INIT: 0,
|
|
422
|
-
SENT_SERVER_READY: 1,
|
|
423
|
-
RECV_AUTH_REQ: 2,
|
|
424
|
-
SENT_SERVER_NONCE: 3,
|
|
425
|
-
RECV_AUTH_HMAC: 4,
|
|
426
|
-
AUTH_FAIL: 5,
|
|
427
|
-
AUTH_READY: 6,
|
|
428
|
-
CID_READY: 7
|
|
429
|
-
};
|
|
430
|
-
for (let c in CLIENT_STATE) { CLIENT_STATE[CLIENT_STATE[c]] = c; }
|
|
431
419
|
|
|
432
420
|
/**
|
|
433
421
|
* @typedef {object} ENC_MODE
|
|
@@ -449,6 +437,7 @@ for (let c in ENC_MODE) { ENC_MODE[ENC_MODE[c]] = c; }
|
|
|
449
437
|
* @property {number} TAG_LEN1
|
|
450
438
|
* @property {number} TAG_LEN2
|
|
451
439
|
* @property {number} CONNECTION_CHECKER_PERIOD
|
|
440
|
+
* @property {number} CLIENT_PING_PERIOD
|
|
452
441
|
* @property {number} PROMISE_TIMEOUT
|
|
453
442
|
* @property {number} DID
|
|
454
443
|
* @property {number} CID
|
|
@@ -457,6 +446,7 @@ const SIZE_LIMIT = {
|
|
|
457
446
|
TAG_LEN1: 255,
|
|
458
447
|
TAG_LEN2: 65535,
|
|
459
448
|
CONNECTION_CHECKER_PERIOD: 3000,
|
|
449
|
+
CLIENT_PING_PERIOD: 40000,
|
|
460
450
|
PROMISE_TIMEOUT: 5000,
|
|
461
451
|
DID: 8,
|
|
462
452
|
CID: 12
|
|
@@ -488,7 +478,7 @@ for (let c in PAYLOAD_TYPE) { PAYLOAD_TYPE[PAYLOAD_TYPE[c]] = c; }
|
|
|
488
478
|
* @property {number} CID_REQ
|
|
489
479
|
* @property {number} CID_RES
|
|
490
480
|
* @property {number} QUOTA_LEVEL
|
|
491
|
-
* @property {number}
|
|
481
|
+
* @property {number} AUTH_CLEAR
|
|
492
482
|
* @property {number} SERVER_REDIRECT
|
|
493
483
|
* @property {number} LOOP
|
|
494
484
|
* @property {number} ECHO
|
|
@@ -546,9 +536,8 @@ let IOMsg = {
|
|
|
546
536
|
CID_REQ: 0xC1,
|
|
547
537
|
CID_RES: 0xC2,
|
|
548
538
|
QUOTA_LEVEL: 0xC3,
|
|
549
|
-
|
|
539
|
+
AUTH_CLEAR: 0xC4,
|
|
550
540
|
SERVER_REDIRECT: 0xC5,
|
|
551
|
-
|
|
552
541
|
// ..
|
|
553
542
|
LOOP: 0xCB,
|
|
554
543
|
ECHO: 0xCC,
|
|
@@ -789,7 +778,7 @@ const t=new Uint32Array([1116352408,1899447441,3049323471,3921009573,961987163,1
|
|
|
789
778
|
* @typedef {import('../common/constants.js').PAYLOAD_TYPE} PAYLOAD_TYPE
|
|
790
779
|
* @typedef {import('../common/constants.js').SIZE_LIMIT} SIZE_LIMIT
|
|
791
780
|
* @typedef {import('../common/constants.js').ENC_MODE} ENC_MODE
|
|
792
|
-
* @typedef {import('../common/constants.js').
|
|
781
|
+
* @typedef {import('../common/constants.js').STATE} STATE
|
|
793
782
|
* @typedef {import('../common/quotaTable.js').quotaTable} quotaTable
|
|
794
783
|
|
|
795
784
|
* @typedef {import('boho').Boho} Boho
|
|
@@ -843,7 +832,7 @@ class IOCore extends EventEmitter {
|
|
|
843
832
|
* Current connection state (number).
|
|
844
833
|
* @type {number}
|
|
845
834
|
*/
|
|
846
|
-
this.state =
|
|
835
|
+
this.state = STATE.CLOSED; // Number type
|
|
847
836
|
/**
|
|
848
837
|
* Current connection state (string).
|
|
849
838
|
* @type {string}
|
|
@@ -985,7 +974,7 @@ class IOCore extends EventEmitter {
|
|
|
985
974
|
close() {
|
|
986
975
|
if (this._closed) return;
|
|
987
976
|
this._closed = true;
|
|
988
|
-
// console.log('####### IOCOre.js close() called')
|
|
977
|
+
// console.log('####### IOCOre.js close() called')
|
|
989
978
|
// If auto-reconnect is disabled, we must stop the keep-alive timer.
|
|
990
979
|
if (this.autoReconnect === false) {
|
|
991
980
|
clearInterval(this.connectionCheckerIntervalID);
|
|
@@ -1000,7 +989,7 @@ class IOCore extends EventEmitter {
|
|
|
1000
989
|
// To avoid the error, we wait for the connection to open, then immediately close it.
|
|
1001
990
|
// We also clear other handlers to prevent any other logic from running.
|
|
1002
991
|
const socket = this.socket;
|
|
1003
|
-
socket.onopen = () => { if(socket) socket.close(); };
|
|
992
|
+
socket.onopen = () => { if (socket) socket.close(); };
|
|
1004
993
|
socket.onmessage = null;
|
|
1005
994
|
socket.onerror = null;
|
|
1006
995
|
socket.onclose = null;
|
|
@@ -1008,7 +997,7 @@ class IOCore extends EventEmitter {
|
|
|
1008
997
|
try {
|
|
1009
998
|
// For other sockets (like TCP) or other WebSocket states, close directly.
|
|
1010
999
|
this.socket.close?.();
|
|
1011
|
-
} catch {}
|
|
1000
|
+
} catch { }
|
|
1012
1001
|
}
|
|
1013
1002
|
this.socket = null;
|
|
1014
1003
|
}
|
|
@@ -1016,14 +1005,15 @@ class IOCore extends EventEmitter {
|
|
|
1016
1005
|
this.emit('closed');
|
|
1017
1006
|
this.stateChange('closed');
|
|
1018
1007
|
}
|
|
1019
|
-
|
|
1008
|
+
|
|
1020
1009
|
/**
|
|
1021
1010
|
* Disables auto-reconnect and closes the current connection.
|
|
1022
1011
|
* The instance can be re-opened manually later. For complete cleanup, use destroy().
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1012
|
+
*/
|
|
1013
|
+
stop() {
|
|
1014
|
+
this.autoReconnect = false;
|
|
1015
|
+
this.close();
|
|
1016
|
+
this.stateChange('stop','stop');
|
|
1027
1017
|
}
|
|
1028
1018
|
|
|
1029
1019
|
/**
|
|
@@ -1039,16 +1029,18 @@ class IOCore extends EventEmitter {
|
|
|
1039
1029
|
|
|
1040
1030
|
// Help GC
|
|
1041
1031
|
this.boho = null;
|
|
1042
|
-
}
|
|
1032
|
+
}
|
|
1043
1033
|
|
|
1044
1034
|
/**
|
|
1045
|
-
* The core keep-alive logic.
|
|
1046
|
-
* The
|
|
1035
|
+
* The core keep-alive logic.
|
|
1036
|
+
* The specific logic for checking the socket's state and reconnecting
|
|
1037
|
+
* is implemented keepConnection() in the child classes (IOWS, IOCongSocket, etc.).
|
|
1047
1038
|
*/
|
|
1048
1039
|
keepAlive() {
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1040
|
+
this.keepConnection();
|
|
1041
|
+
if( Date.now() - this.lastTxRxTime > SIZE_LIMIT.CLIENT_PING_PERIOD ){
|
|
1042
|
+
this.ping();
|
|
1043
|
+
}
|
|
1052
1044
|
}
|
|
1053
1045
|
|
|
1054
1046
|
/**
|
|
@@ -1056,8 +1048,8 @@ class IOCore extends EventEmitter {
|
|
|
1056
1048
|
* @param {string} url2 - The new URL to redirect to.
|
|
1057
1049
|
*/
|
|
1058
1050
|
redirect(url2) {
|
|
1051
|
+
this.stateChange('redirecting','redirecting');
|
|
1059
1052
|
this.close();
|
|
1060
|
-
this.stateChange('redirecting');
|
|
1061
1053
|
this.createConnection(url2);
|
|
1062
1054
|
}
|
|
1063
1055
|
|
|
@@ -1114,29 +1106,27 @@ class IOCore extends EventEmitter {
|
|
|
1114
1106
|
|
|
1115
1107
|
/**
|
|
1116
1108
|
* Manually logs in with provided ID and key.
|
|
1117
|
-
* @param {string} id - The user ID.
|
|
1109
|
+
* @param {string} id - The user ID. or 'id.key'
|
|
1118
1110
|
* @param {string} key - The user key.
|
|
1119
|
-
* @returns {
|
|
1111
|
+
* @returns {this}
|
|
1120
1112
|
*/
|
|
1121
1113
|
login(id, key) {
|
|
1122
|
-
|
|
1123
|
-
|
|
1114
|
+
this.auth(id, key);
|
|
1124
1115
|
this.useAuth = true;
|
|
1125
1116
|
let auth_pack = this.boho.auth_req();
|
|
1126
1117
|
this.send(auth_pack);
|
|
1127
|
-
return
|
|
1118
|
+
return this
|
|
1128
1119
|
}
|
|
1129
1120
|
|
|
1130
1121
|
/**
|
|
1131
1122
|
* Sets up authentication for auto-login.
|
|
1132
|
-
* @param {string} id - The user ID.
|
|
1123
|
+
* @param {string} id - The user ID. or 'id.Key'
|
|
1133
1124
|
* @param {string} key - The user key.
|
|
1134
|
-
* @returns {
|
|
1125
|
+
* @returns {this}
|
|
1135
1126
|
*/
|
|
1136
1127
|
auth(id, key) {
|
|
1137
1128
|
if (!id && !key) {
|
|
1138
1129
|
this.emit('error', new Error('auth failed. no id and key.'));
|
|
1139
|
-
return false
|
|
1140
1130
|
}
|
|
1141
1131
|
|
|
1142
1132
|
if (!key && id.includes('.')) {
|
|
@@ -1146,10 +1136,9 @@ class IOCore extends EventEmitter {
|
|
|
1146
1136
|
this.boho.set_key(key);
|
|
1147
1137
|
} else {
|
|
1148
1138
|
this.emit('error', new Error('auth failed. no id or key.'));
|
|
1149
|
-
return false
|
|
1150
1139
|
}
|
|
1151
1140
|
this.useAuth = true;
|
|
1152
|
-
return
|
|
1141
|
+
return this
|
|
1153
1142
|
}
|
|
1154
1143
|
|
|
1155
1144
|
/**
|
|
@@ -1209,13 +1198,13 @@ class IOCore extends EventEmitter {
|
|
|
1209
1198
|
case IOMsg.ECHO:
|
|
1210
1199
|
try {
|
|
1211
1200
|
let str = decoder$4.decode(buffer.subarray(1));
|
|
1212
|
-
|
|
1201
|
+
|
|
1213
1202
|
this.emit('echo', str);
|
|
1214
1203
|
} catch (error) {
|
|
1215
1204
|
this.emit('error', new Error('ECHO data error'));
|
|
1216
1205
|
}
|
|
1217
1206
|
break;
|
|
1218
|
-
|
|
1207
|
+
|
|
1219
1208
|
case IOMsg.IAM_RES:
|
|
1220
1209
|
try {
|
|
1221
1210
|
let str = decoder$4.decode(buffer.subarray(1));
|
|
@@ -1224,7 +1213,7 @@ class IOCore extends EventEmitter {
|
|
|
1224
1213
|
if (jsonInfo.nick) { this.nick = jsonInfo.nick; }
|
|
1225
1214
|
if (jsonInfo.did) { this.did = jsonInfo.did; }
|
|
1226
1215
|
if (jsonInfo.uid) { this.uid = jsonInfo.uid; }
|
|
1227
|
-
this.emit('iam_res', str
|
|
1216
|
+
this.emit('iam_res', str);
|
|
1228
1217
|
} catch (error) {
|
|
1229
1218
|
this.emit('error', new Error('IAM_RES data error'));
|
|
1230
1219
|
}
|
|
@@ -1235,22 +1224,22 @@ class IOCore extends EventEmitter {
|
|
|
1235
1224
|
this.cid = cidStr;
|
|
1236
1225
|
|
|
1237
1226
|
// **IMPORTANT** change state before subscribe.
|
|
1238
|
-
this.stateChange('ready', 'cid_ready');
|
|
1239
|
-
this.subscribe_memory_channels();
|
|
1227
|
+
this.stateChange('ready', 'cid_ready');
|
|
1228
|
+
this.subscribe_memory_channels(); // tags registered by listen() or link().
|
|
1240
1229
|
break;
|
|
1241
1230
|
|
|
1242
1231
|
case IOMsg.QUOTA_LEVEL:
|
|
1243
1232
|
let quotaLevel = buffer[1];
|
|
1244
1233
|
this.level = quotaLevel;
|
|
1245
1234
|
this.quota = quotaTable[quotaLevel];
|
|
1246
|
-
console.log('[QUOTA_LEVEL]', JSON.stringify(this.quota))
|
|
1235
|
+
// console.log('[QUOTA_LEVEL]', JSON.stringify(this.quota))
|
|
1247
1236
|
break;
|
|
1248
1237
|
|
|
1249
|
-
case IOMsg.
|
|
1238
|
+
case IOMsg.AUTH_CLEAR:
|
|
1250
1239
|
this.useAuth = false;
|
|
1251
1240
|
this.boho.clearAuth();
|
|
1241
|
+
this.stateChange('auth_clear', 'server request auth_clear.');
|
|
1252
1242
|
this.stop();
|
|
1253
|
-
console.log('[SERVER_CLEAR_AUTH] io stop.');
|
|
1254
1243
|
break;
|
|
1255
1244
|
|
|
1256
1245
|
case IOMsg.SERVER_REDIRECT:
|
|
@@ -1327,7 +1316,7 @@ class IOCore extends EventEmitter {
|
|
|
1327
1316
|
if (tag.indexOf('@') === 0) this.emit('@', tag, null);
|
|
1328
1317
|
else {
|
|
1329
1318
|
this.emit(tag, tag, null);
|
|
1330
|
-
this.emit('message', tag, null
|
|
1319
|
+
this.emit('message', tag, null);
|
|
1331
1320
|
}
|
|
1332
1321
|
break;
|
|
1333
1322
|
|
|
@@ -1340,7 +1329,7 @@ class IOCore extends EventEmitter {
|
|
|
1340
1329
|
}
|
|
1341
1330
|
let oneString = decoder$4.decode(payloadStringWithoutNull);
|
|
1342
1331
|
if (tag.indexOf('@') === 0) this.emit('@', tag, oneString);
|
|
1343
|
-
if (tag !== '@'){
|
|
1332
|
+
if (tag !== '@') {
|
|
1344
1333
|
this.emit(tag, tag, oneString);
|
|
1345
1334
|
this.emit('message', tag, oneString);
|
|
1346
1335
|
}
|
|
@@ -1348,39 +1337,39 @@ class IOCore extends EventEmitter {
|
|
|
1348
1337
|
|
|
1349
1338
|
case PAYLOAD_TYPE.BINARY:
|
|
1350
1339
|
if (tag.indexOf('@') === 0) this.emit('@', tag, payloadBuffer);
|
|
1351
|
-
if (tag !== '@'){
|
|
1340
|
+
if (tag !== '@') {
|
|
1352
1341
|
this.emit(tag, tag, payloadBuffer);
|
|
1353
1342
|
this.emit('message', tag, payloadBuffer);
|
|
1354
|
-
}
|
|
1343
|
+
}
|
|
1355
1344
|
break;
|
|
1356
1345
|
|
|
1357
1346
|
case PAYLOAD_TYPE.OBJECT:
|
|
1358
1347
|
let oneObjectBuffer = decoder$4.decode(payloadBuffer);
|
|
1359
1348
|
let oneJSONObject = JSON.parse(oneObjectBuffer);
|
|
1360
1349
|
if (tag.indexOf('@') === 0) this.emit('@', tag, oneJSONObject);
|
|
1361
|
-
if (tag !== '@'){
|
|
1350
|
+
if (tag !== '@') {
|
|
1362
1351
|
this.emit(tag, tag, oneJSONObject);
|
|
1363
1352
|
this.emit('message', tag, oneJSONObject);
|
|
1364
|
-
}
|
|
1353
|
+
}
|
|
1365
1354
|
break;
|
|
1366
1355
|
|
|
1367
1356
|
case PAYLOAD_TYPE.MJSON:
|
|
1368
1357
|
let mjsonBuffer = decoder$4.decode(payloadBuffer);
|
|
1369
1358
|
let mjson = JSON.parse(mjsonBuffer);
|
|
1370
1359
|
if (tag.indexOf('@') === 0) this.emit('@', tag, ...mjson);
|
|
1371
|
-
if (tag !== '@'){
|
|
1360
|
+
if (tag !== '@') {
|
|
1372
1361
|
this.emit(tag, tag, ...mjson);
|
|
1373
1362
|
this.emit('message', tag, ...mjson);
|
|
1374
|
-
}
|
|
1363
|
+
}
|
|
1375
1364
|
break;
|
|
1376
1365
|
|
|
1377
1366
|
case PAYLOAD_TYPE.MBA:
|
|
1378
1367
|
let mbaObject = M$1.unpack(payloadBuffer);
|
|
1379
1368
|
if (tag.indexOf('@') === 0) this.emit('@', tag, ...mbaObject.args);
|
|
1380
|
-
if (tag !== '@'){
|
|
1369
|
+
if (tag !== '@') {
|
|
1381
1370
|
this.emit(tag, tag, ...mbaObject.args);
|
|
1382
|
-
this.emit('message', tag, ...mbaObject.args
|
|
1383
|
-
}
|
|
1371
|
+
this.emit('message', tag, ...mbaObject.args);
|
|
1372
|
+
}
|
|
1384
1373
|
break;
|
|
1385
1374
|
|
|
1386
1375
|
default:
|
|
@@ -1388,7 +1377,8 @@ class IOCore extends EventEmitter {
|
|
|
1388
1377
|
}
|
|
1389
1378
|
|
|
1390
1379
|
} catch (err) {
|
|
1391
|
-
this.emit('error', new Error('
|
|
1380
|
+
// this.emit('error', new Error('IOCore IOMsg.SIGNAL parser err', err))
|
|
1381
|
+
console.log('IOCore IOMsg.SIGNAL parser err', err);
|
|
1392
1382
|
}
|
|
1393
1383
|
break;
|
|
1394
1384
|
|
|
@@ -1397,24 +1387,25 @@ class IOCore extends EventEmitter {
|
|
|
1397
1387
|
break;
|
|
1398
1388
|
|
|
1399
1389
|
case tt.BohoMsg.AUTH_NONCE:
|
|
1390
|
+
this.stateChange('auth_nonce','server sent auth_nonce.');
|
|
1400
1391
|
let auth_hmac = this.boho.auth_hmac(buffer);
|
|
1401
1392
|
if (auth_hmac) {
|
|
1402
1393
|
this.send(auth_hmac);
|
|
1403
1394
|
} else {
|
|
1404
|
-
this.stateChange('auth_fail', '
|
|
1395
|
+
this.stateChange('auth_fail', 'boho.auth_hmac() invalid auth_nonce.');
|
|
1405
1396
|
}
|
|
1406
1397
|
break;
|
|
1407
1398
|
|
|
1408
1399
|
case tt.BohoMsg.AUTH_FAIL:
|
|
1409
|
-
this.stateChange('auth_fail', '
|
|
1400
|
+
this.stateChange('auth_fail', 'auth_fail from server.');
|
|
1410
1401
|
break;
|
|
1411
1402
|
|
|
1412
1403
|
case tt.BohoMsg.AUTH_ACK:
|
|
1413
1404
|
if (this.boho.check_auth_ack_hmac(buffer)) {
|
|
1414
|
-
this.stateChange('
|
|
1405
|
+
this.stateChange('auth_ack', 'server sent auth_ack');
|
|
1415
1406
|
this.send(Buffer$1.from([IOMsg.CID_REQ]));
|
|
1416
1407
|
} else {
|
|
1417
|
-
this.stateChange('auth_fail', 'invalid server_hmac');
|
|
1408
|
+
this.stateChange('auth_fail', 'check_auth_ack_hmac() invalid server_hmac');
|
|
1418
1409
|
}
|
|
1419
1410
|
break;
|
|
1420
1411
|
|
|
@@ -1601,14 +1592,15 @@ class IOCore extends EventEmitter {
|
|
|
1601
1592
|
|
|
1602
1593
|
|
|
1603
1594
|
/**
|
|
1604
|
-
*
|
|
1595
|
+
* alias of signal()
|
|
1596
|
+
* Sends a signal with a tag and arguments.
|
|
1597
|
+
* @param {string} tag - The signal tag.
|
|
1605
1598
|
* @param {...any} args - Arguments for the signal.
|
|
1606
1599
|
*/
|
|
1607
|
-
publish(...args) {
|
|
1608
|
-
this.signal(...args);
|
|
1600
|
+
publish(tag, ...args) {
|
|
1601
|
+
this.signal(tag, ...args);
|
|
1609
1602
|
}
|
|
1610
1603
|
|
|
1611
|
-
|
|
1612
1604
|
/**
|
|
1613
1605
|
* Sends a signal with a tag and arguments.
|
|
1614
1606
|
* @param {string} tag - The signal tag.
|
|
@@ -1617,7 +1609,6 @@ class IOCore extends EventEmitter {
|
|
|
1617
1609
|
*/
|
|
1618
1610
|
signal(tag, ...args) {
|
|
1619
1611
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1620
|
-
|
|
1621
1612
|
let signalPack = getSignalPack(tag, ...args);
|
|
1622
1613
|
this.send_enc_mode(signalPack);
|
|
1623
1614
|
}
|
|
@@ -1661,7 +1652,6 @@ class IOCore extends EventEmitter {
|
|
|
1661
1652
|
}
|
|
1662
1653
|
|
|
1663
1654
|
|
|
1664
|
-
|
|
1665
1655
|
/**
|
|
1666
1656
|
* Sets a value in the store.
|
|
1667
1657
|
* @param {string} storeName - The name of the store.
|
|
@@ -1729,8 +1719,8 @@ class IOCore extends EventEmitter {
|
|
|
1729
1719
|
*/
|
|
1730
1720
|
subscribe(tag) {
|
|
1731
1721
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1732
|
-
|
|
1733
|
-
if (this.state !==
|
|
1722
|
+
if (tag.length > SIZE_LIMIT.TAG_LEN1) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN1)
|
|
1723
|
+
if (this.state !== STATE.READY) return
|
|
1734
1724
|
|
|
1735
1725
|
// subscribe 사용시, 사용 'ready' 이벤트시 메뉴얼 등록되므로 여기에 등록하면 2중 호출된다.
|
|
1736
1726
|
// 즉, channels 등록은 listen 같은 자동화 구독시만 사용.
|
|
@@ -1739,7 +1729,7 @@ class IOCore extends EventEmitter {
|
|
|
1739
1729
|
// this.channels.add(tag)
|
|
1740
1730
|
// })
|
|
1741
1731
|
|
|
1742
|
-
try {
|
|
1732
|
+
try {
|
|
1743
1733
|
let tagEncoded = encoder$1.encode(tag);
|
|
1744
1734
|
this.send_enc_mode(
|
|
1745
1735
|
Buffer$1.concat([
|
|
@@ -1759,12 +1749,12 @@ class IOCore extends EventEmitter {
|
|
|
1759
1749
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1760
1750
|
if (tag.length > SIZE_LIMIT.TAG_LEN2) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN2)
|
|
1761
1751
|
|
|
1762
|
-
if (this.state !==
|
|
1752
|
+
if (this.state !== STATE.READY) {
|
|
1763
1753
|
return Promise.reject('subscribe_promise:: connection is not ready')
|
|
1764
1754
|
}
|
|
1765
1755
|
|
|
1766
1756
|
try {
|
|
1767
|
-
let tagEncoded = encoder$1.encode(tag);
|
|
1757
|
+
let tagEncoded = encoder$1.encode(tag);
|
|
1768
1758
|
this.send_enc_mode(
|
|
1769
1759
|
Buffer$1.concat([
|
|
1770
1760
|
M$1.NB('8', IOMsg.SUBSCRIBE_REQ),
|
|
@@ -1834,7 +1824,7 @@ class IOCore extends EventEmitter {
|
|
|
1834
1824
|
}
|
|
1835
1825
|
this.on(tag, handler);
|
|
1836
1826
|
// do not subscribe now.
|
|
1837
|
-
// will subscribe when receive CID_RES
|
|
1827
|
+
// will subscribe when io state is 'ready'. (receive CID_RES from server)
|
|
1838
1828
|
|
|
1839
1829
|
}
|
|
1840
1830
|
|
|
@@ -1945,10 +1935,10 @@ class IOCore extends EventEmitter {
|
|
|
1945
1935
|
*/
|
|
1946
1936
|
getStateName() {
|
|
1947
1937
|
//state <number>
|
|
1948
|
-
//value of constant
|
|
1949
|
-
//type of constant
|
|
1938
|
+
//value of constant STATE.NAME < number >
|
|
1939
|
+
//type of constant STATE.NAME name < string uppercase >
|
|
1950
1940
|
//stateName,eventName <string lowercase>
|
|
1951
|
-
return (
|
|
1941
|
+
return (STATE[this.state]).toLowerCase()
|
|
1952
1942
|
}
|
|
1953
1943
|
|
|
1954
1944
|
/**
|
|
@@ -1976,14 +1966,14 @@ class IOCore extends EventEmitter {
|
|
|
1976
1966
|
* 보통 이벤트 이름과 동일하게 적거나 이벤트 상황 안내문을 넣는다.
|
|
1977
1967
|
*/
|
|
1978
1968
|
stateChange(state, emitEventAndMessage) {
|
|
1979
|
-
//
|
|
1969
|
+
// STATE constant name <string> upperCase
|
|
1980
1970
|
// eventName and .stateName <string> lowerCase
|
|
1981
1971
|
// .state <number>
|
|
1982
1972
|
// console.log('### stateChange reason:', emitEventAndMessage )
|
|
1983
1973
|
let eventName = state.toLowerCase();
|
|
1984
|
-
this.state =
|
|
1974
|
+
this.state = STATE[state.toUpperCase()]; // state: number
|
|
1985
1975
|
|
|
1986
|
-
if (emitEventAndMessage){
|
|
1976
|
+
if (emitEventAndMessage) {
|
|
1987
1977
|
this.emit(eventName, emitEventAndMessage);
|
|
1988
1978
|
}
|
|
1989
1979
|
|
|
@@ -2160,10 +2150,10 @@ class IOCongSocket extends IOCore {
|
|
|
2160
2150
|
|
|
2161
2151
|
|
|
2162
2152
|
|
|
2163
|
-
|
|
2153
|
+
keepConnection() {
|
|
2164
2154
|
if (!this.autoReconnect) return;
|
|
2165
2155
|
// Reconnect only if the socket is fully destroyed and the state is closed.
|
|
2166
|
-
if ((!this.socket || this.socket.destroyed)
|
|
2156
|
+
if ((!this.socket || this.socket.destroyed)) {
|
|
2167
2157
|
this.open();
|
|
2168
2158
|
}
|
|
2169
2159
|
}
|
|
@@ -2176,7 +2166,7 @@ class IOCongSocket extends IOCore {
|
|
|
2176
2166
|
urlObj = new URL('cong://' + url);
|
|
2177
2167
|
}
|
|
2178
2168
|
this.socket = net.createConnection(urlObj.port, urlObj.hostname);
|
|
2179
|
-
this.stateChange('
|
|
2169
|
+
this.stateChange('connecting','connecting');
|
|
2180
2170
|
|
|
2181
2171
|
this.socket.on('connect', () => {
|
|
2182
2172
|
this.congRx = new CongRx();
|
|
@@ -7586,19 +7576,20 @@ class IOWS extends IOCore {
|
|
|
7586
7576
|
super.close();
|
|
7587
7577
|
}
|
|
7588
7578
|
|
|
7589
|
-
|
|
7590
|
-
keepAlive() {
|
|
7579
|
+
keepConnection() {
|
|
7591
7580
|
if (!this.autoReconnect) return;
|
|
7592
7581
|
// Reconnect only if the socket is closed and the state reflects that.
|
|
7593
|
-
if ((!this.socket || this.socket.readyState === WebSocket.CLOSED)
|
|
7582
|
+
if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) ) {
|
|
7594
7583
|
this.open();
|
|
7595
7584
|
}
|
|
7596
7585
|
}
|
|
7597
7586
|
|
|
7587
|
+
|
|
7588
|
+
|
|
7598
7589
|
createConnection(url) {
|
|
7599
7590
|
// node WebSocket
|
|
7600
7591
|
this.socket = new WebSocket(url);
|
|
7601
|
-
this.stateChange('
|
|
7592
|
+
this.stateChange('connecting','connecting');
|
|
7602
7593
|
|
|
7603
7594
|
this.socket.onopen = () => {
|
|
7604
7595
|
this.socket.on('message', this.onWebSocketMessage.bind(this));
|
|
@@ -7724,7 +7715,7 @@ class RemoteCore {
|
|
|
7724
7715
|
|
|
7725
7716
|
this.state;
|
|
7726
7717
|
this.stateLog = [];
|
|
7727
|
-
this.setState(
|
|
7718
|
+
this.setState(STATE.OPEN);
|
|
7728
7719
|
|
|
7729
7720
|
}
|
|
7730
7721
|
|
|
@@ -7733,9 +7724,12 @@ class RemoteCore {
|
|
|
7733
7724
|
setState(state) {
|
|
7734
7725
|
this.state = state;
|
|
7735
7726
|
if (serverOption.debug.showAuthInfo) {
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7727
|
+
this.stateLog.push( state + ":" + STATE[ state] );
|
|
7728
|
+
if( state == STATE.AUTH_ACK){
|
|
7729
|
+
console.log('[auth success]', this.cid, this.stateLog.join('>'));
|
|
7730
|
+
}else if( state == STATE.AUTH_FAIL){
|
|
7731
|
+
console.log('[auth_fail]',this.stateLog.join('>'));
|
|
7732
|
+
}
|
|
7739
7733
|
}
|
|
7740
7734
|
}
|
|
7741
7735
|
|
|
@@ -7744,24 +7738,30 @@ class RemoteCore {
|
|
|
7744
7738
|
}
|
|
7745
7739
|
|
|
7746
7740
|
getStateName() { // <String>
|
|
7747
|
-
return (
|
|
7741
|
+
return (STATE[this.state]).toLowerCase()
|
|
7748
7742
|
}
|
|
7749
7743
|
|
|
7750
7744
|
|
|
7751
7745
|
showMessageLog(message, isBinary) {
|
|
7752
|
-
let
|
|
7746
|
+
let h = '->S ';
|
|
7747
|
+
let from = this.boho.isAuthorized ? ` did: ${this.did} cid: ${this.cid}` : ` cid: ${this.cid}`;
|
|
7748
|
+
let prnLimit = 20;
|
|
7753
7749
|
if (isBinary) {
|
|
7754
7750
|
let msgTypeName = IOMsg[message[0]];
|
|
7755
7751
|
if (!msgTypeName) msgTypeName = tt.BohoMsg[message[0]];
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7752
|
+
|
|
7753
|
+
msgTypeName = '[' + msgTypeName + ']';
|
|
7754
|
+
let size = message.byteLength;
|
|
7755
|
+
if (size < prnLimit) {
|
|
7756
|
+
console.log( h + msgTypeName + from +` [${size}]`, message);
|
|
7759
7757
|
} else {
|
|
7760
|
-
|
|
7758
|
+
let elseLen = size - prnLimit;
|
|
7759
|
+
let some = message.subarray(0,prnLimit);
|
|
7760
|
+
console.log( h + msgTypeName + from +` [${size}]` , some , ' ... else: ', elseLen);
|
|
7761
7761
|
}
|
|
7762
7762
|
|
|
7763
7763
|
} else {
|
|
7764
|
-
console.log(
|
|
7764
|
+
console.log( h + ' [TEXT] %s' + from, message);
|
|
7765
7765
|
}
|
|
7766
7766
|
}
|
|
7767
7767
|
|
|
@@ -7844,7 +7844,7 @@ class RemoteCore {
|
|
|
7844
7844
|
break;
|
|
7845
7845
|
|
|
7846
7846
|
case IOMsg.CID_REQ:
|
|
7847
|
-
if (this.state <
|
|
7847
|
+
if (this.state < STATE.SERVER_READY) {
|
|
7848
7848
|
// Protocol violation: CID_REQ was sent before receiving the SERVER_READY signal.
|
|
7849
7849
|
console.log('CID_REQ before SERVER_READY');
|
|
7850
7850
|
this.close();
|
|
@@ -7861,7 +7861,7 @@ class RemoteCore {
|
|
|
7861
7861
|
MB('#cid', this.cid)
|
|
7862
7862
|
));
|
|
7863
7863
|
|
|
7864
|
-
this.setState(
|
|
7864
|
+
this.setState(STATE.CID_RES);
|
|
7865
7865
|
break;
|
|
7866
7866
|
|
|
7867
7867
|
case IOMsg.ECHO:
|
|
@@ -7967,24 +7967,24 @@ class RemoteCore {
|
|
|
7967
7967
|
// Auth
|
|
7968
7968
|
case tt.BohoMsg.AUTH_REQ:
|
|
7969
7969
|
if (!this.manager.authManager) return
|
|
7970
|
-
if (this.state <
|
|
7970
|
+
if (this.state < STATE.SERVER_READY) {
|
|
7971
7971
|
console.log('protocol error. auth_req before server_ready');
|
|
7972
7972
|
this.close();
|
|
7973
7973
|
}
|
|
7974
|
-
this.setState(
|
|
7974
|
+
this.setState(STATE.AUTH_REQ);
|
|
7975
7975
|
let auth_nonce_pack = this.boho.auth_nonce();
|
|
7976
7976
|
// console.log('## auth_nonce_pack', auth_nonce_pack )
|
|
7977
7977
|
this.send(auth_nonce_pack);
|
|
7978
|
-
this.setState(
|
|
7978
|
+
this.setState(STATE.AUTH_NONCE);
|
|
7979
7979
|
break;
|
|
7980
7980
|
|
|
7981
7981
|
case tt.BohoMsg.AUTH_HMAC:
|
|
7982
7982
|
if (!this.manager.authManager) return
|
|
7983
|
-
if (this.state <
|
|
7983
|
+
if (this.state < STATE.AUTH_NONCE) {
|
|
7984
7984
|
console.log('protocol error. auth_hmac before server_nonce');
|
|
7985
7985
|
this.close();
|
|
7986
7986
|
}
|
|
7987
|
-
this.setState(
|
|
7987
|
+
this.setState(STATE.AUTH_HMAC);
|
|
7988
7988
|
//async
|
|
7989
7989
|
this.manager.authManager.verify_auth_hmac(message, this)
|
|
7990
7990
|
.then(authInfo => {
|
|
@@ -8134,11 +8134,42 @@ function isPrivateIP(ip) {
|
|
|
8134
8134
|
return false
|
|
8135
8135
|
}
|
|
8136
8136
|
|
|
8137
|
+
function numberWithCommas(x) {
|
|
8138
|
+
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|
8139
|
+
}
|
|
8140
|
+
|
|
8137
8141
|
function getIPv4HexString(ipStr) {
|
|
8138
8142
|
let ipv4 = ipStr.split('.');
|
|
8139
8143
|
return Buffer.from(ipv4).toString('hex')
|
|
8140
8144
|
}
|
|
8141
8145
|
|
|
8146
|
+
function getLocalAddress() {
|
|
8147
|
+
const nets = networkInterfaces();
|
|
8148
|
+
// console.log(nets)
|
|
8149
|
+
const results = Object.create(null); // Or just '{}', an empty object
|
|
8150
|
+
let localAddress = '';
|
|
8151
|
+
for (const name of Object.keys(nets)) {
|
|
8152
|
+
for (const net of nets[name]) {
|
|
8153
|
+
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
|
|
8154
|
+
// 'IPv4' is in Node <= 17, from 18 it's a number 4 or 6
|
|
8155
|
+
const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4;
|
|
8156
|
+
if (net.family === familyV4Value && !net.internal) {
|
|
8157
|
+
if (!results[name]) {
|
|
8158
|
+
results[name] = [];
|
|
8159
|
+
}
|
|
8160
|
+
results[name].push(net.address);
|
|
8161
|
+
localAddress = net.address;
|
|
8162
|
+
}
|
|
8163
|
+
}
|
|
8164
|
+
}
|
|
8165
|
+
|
|
8166
|
+
// console.log('localAddress:', localAddress)
|
|
8167
|
+
return localAddress
|
|
8168
|
+
}
|
|
8169
|
+
|
|
8170
|
+
|
|
8171
|
+
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
8172
|
+
|
|
8142
8173
|
const decoder$2 = new TextDecoder();
|
|
8143
8174
|
|
|
8144
8175
|
class Remote extends RemoteCore {
|
|
@@ -8310,6 +8341,7 @@ class Remote extends RemoteCore {
|
|
|
8310
8341
|
}
|
|
8311
8342
|
}
|
|
8312
8343
|
|
|
8344
|
+
// node.js server side remote.
|
|
8313
8345
|
send(message, isBinary) {
|
|
8314
8346
|
this.manager.txBytes += message.byteLength;
|
|
8315
8347
|
this.socket.txCounter++;
|
|
@@ -8321,13 +8353,15 @@ class Remote extends RemoteCore {
|
|
|
8321
8353
|
this.socket.send(message);
|
|
8322
8354
|
}
|
|
8323
8355
|
} else {
|
|
8356
|
+
console.log('server(ws)Remote.send() called. not open state. current readyState:', this.socket.readyState );
|
|
8324
8357
|
this.close(true);
|
|
8325
8358
|
}
|
|
8326
|
-
|
|
8359
|
+
|
|
8327
8360
|
} else { //CongSocket
|
|
8328
8361
|
if (this.socket.readyState == 'open') {
|
|
8329
8362
|
this.socket.write(pack(message));
|
|
8330
8363
|
} else {
|
|
8364
|
+
console.log('server(cong)Remote.send() called. not open state. current readyState:', this.socket.readyState );
|
|
8331
8365
|
this.close(true);
|
|
8332
8366
|
}
|
|
8333
8367
|
}
|
|
@@ -8583,7 +8617,7 @@ class Manager {
|
|
|
8583
8617
|
let remote = new Remote(socket, req, this);
|
|
8584
8618
|
this.remotes.add(remote);
|
|
8585
8619
|
remote.send(Buffer.from([IOMsg.SERVER_READY]));
|
|
8586
|
-
remote.setState(
|
|
8620
|
+
remote.setState(STATE.SERVER_READY);
|
|
8587
8621
|
this.lastSSID = remote.ssid;
|
|
8588
8622
|
let connectionInfo = `+ IP:${remote.ip} #${remote.ssid} ${socket.socketType === 'websocket' ? "WS" : "CS"} `;
|
|
8589
8623
|
// console.log( connectionInfo)
|
|
@@ -8698,8 +8732,8 @@ class Manager {
|
|
|
8698
8732
|
|
|
8699
8733
|
sender(tag, remote, message) {
|
|
8700
8734
|
if (serverOption.membersOnly && !remote.boho.isAuthorized) {
|
|
8701
|
-
console.log("[membersOnly]
|
|
8702
|
-
remote.send(Buffer.from([IOMsg.
|
|
8735
|
+
// console.log("### server reject client signal reason: [membersOnly]" ,tag, remote.cid )
|
|
8736
|
+
remote.send(Buffer.from([IOMsg.AUTH_CLEAR]));
|
|
8703
8737
|
remote.close();
|
|
8704
8738
|
return ['err', 'unAuthorized']
|
|
8705
8739
|
}
|
|
@@ -9027,7 +9061,7 @@ class Server extends require$$0$3 {
|
|
|
9027
9061
|
|
|
9028
9062
|
this.wss.once('listening', () => {
|
|
9029
9063
|
this.port = this.wss.address().port;
|
|
9030
|
-
console.log('wss server bound port:', this.port );
|
|
9064
|
+
// console.log('wss server bound port:', this.port );
|
|
9031
9065
|
this.listeningServerCount++;
|
|
9032
9066
|
if (this.listeningServerCount === this.serverCountToListen) {
|
|
9033
9067
|
this.emit('ready');
|
|
@@ -9043,7 +9077,7 @@ class Server extends require$$0$3 {
|
|
|
9043
9077
|
});
|
|
9044
9078
|
|
|
9045
9079
|
this.wss.on('close', () => {
|
|
9046
|
-
console.log('### WS server is closed.')
|
|
9080
|
+
// console.log('### WS server is closed.')
|
|
9047
9081
|
});
|
|
9048
9082
|
|
|
9049
9083
|
this.wss.on('connection', (ws, req) => {
|
|
@@ -9064,10 +9098,10 @@ class Server extends require$$0$3 {
|
|
|
9064
9098
|
process.exit();
|
|
9065
9099
|
}
|
|
9066
9100
|
}).on('close', () => {
|
|
9067
|
-
console.log('### congsocket server is closed.')
|
|
9101
|
+
// console.log('### congsocket server is closed.')
|
|
9068
9102
|
}).listen(this.congPort, () => {
|
|
9069
9103
|
this.congPort = this.congServer.address().port;
|
|
9070
|
-
console.log('congsocket server bound port:', this.congPort );
|
|
9104
|
+
// console.log('congsocket server bound port:', this.congPort );
|
|
9071
9105
|
this.listeningServerCount++;
|
|
9072
9106
|
if (this.listeningServerCount === this.serverCountToListen) {
|
|
9073
9107
|
this.emit('ready');
|
|
@@ -9102,7 +9136,7 @@ class Server extends require$$0$3 {
|
|
|
9102
9136
|
return
|
|
9103
9137
|
}
|
|
9104
9138
|
if( api.commands.includes( req.topic )){
|
|
9105
|
-
console.log('server api req', req )
|
|
9139
|
+
// console.log('server api req', req )
|
|
9106
9140
|
await api.request(remote, req);
|
|
9107
9141
|
}else {
|
|
9108
9142
|
remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
|
|
@@ -9132,7 +9166,7 @@ class Server extends require$$0$3 {
|
|
|
9132
9166
|
});
|
|
9133
9167
|
}
|
|
9134
9168
|
this.apiNames.add(target);
|
|
9135
|
-
console.log(`[API registed: ${target} ] accept commands: ${api.commands}`)
|
|
9169
|
+
// console.log(`[API registed: ${target} ] accept commands: ${api.commands}`)
|
|
9136
9170
|
return this
|
|
9137
9171
|
}
|
|
9138
9172
|
|
|
@@ -9172,7 +9206,7 @@ class Server extends require$$0$3 {
|
|
|
9172
9206
|
|
|
9173
9207
|
if (this.congServer) {
|
|
9174
9208
|
this.congServer.close((err) => {
|
|
9175
|
-
if (err) console.error('congServer close error', err)
|
|
9209
|
+
// if (err) console.error('congServer close error', err)
|
|
9176
9210
|
// console.log('cong server closed.')
|
|
9177
9211
|
onClosed();
|
|
9178
9212
|
});
|
|
@@ -9183,7 +9217,12 @@ class Server extends require$$0$3 {
|
|
|
9183
9217
|
|
|
9184
9218
|
const decoder = new TextDecoder();
|
|
9185
9219
|
class BohoAuth {
|
|
9186
|
-
constructor() {
|
|
9220
|
+
constructor(keyProvider) {
|
|
9221
|
+
if (!keyProvider) {
|
|
9222
|
+
throw new Error('BohoAuth must be initialized with a keyProvider.');
|
|
9223
|
+
}
|
|
9224
|
+
this.keyProvider = keyProvider;
|
|
9225
|
+
|
|
9187
9226
|
this.authLogger;
|
|
9188
9227
|
if (serverOption.fileLogger.auth.use) {
|
|
9189
9228
|
this.authLogger = new FileLogger(serverOption.fileLogger.auth.path);
|
|
@@ -9197,11 +9236,11 @@ class BohoAuth {
|
|
|
9197
9236
|
this.authLogger.log(peerInfo);
|
|
9198
9237
|
}
|
|
9199
9238
|
// console.log('##### AUTH_FAIL reason: ', reason)
|
|
9200
|
-
peer.setState(
|
|
9239
|
+
peer.setState(STATE.AUTH_FAIL);
|
|
9240
|
+
peer.send(Buffer.from([tt.BohoMsg.AUTH_FAIL]));
|
|
9201
9241
|
// add some delay time.
|
|
9202
|
-
setTimeout(e => {
|
|
9203
|
-
|
|
9204
|
-
}, serverOption.auth.delay_auth_fail);
|
|
9242
|
+
// setTimeout(e => {
|
|
9243
|
+
// }, serverOption.auth.delay_auth_fail)
|
|
9205
9244
|
}
|
|
9206
9245
|
|
|
9207
9246
|
async verify_auth_hmac(auth_hmac, peer) {
|
|
@@ -9222,7 +9261,7 @@ class BohoAuth {
|
|
|
9222
9261
|
}
|
|
9223
9262
|
|
|
9224
9263
|
//2. get key of id from DB
|
|
9225
|
-
let authInfo = await this.getAuth(id);
|
|
9264
|
+
let authInfo = await this.keyProvider.getAuth(id);
|
|
9226
9265
|
|
|
9227
9266
|
if (!authInfo) {
|
|
9228
9267
|
this.send_auth_fail(peer, 'NO ID:' + id);
|
|
@@ -9273,9 +9312,13 @@ class BohoAuth {
|
|
|
9273
9312
|
console.log('## trying RELOGIN with SAME ID. ignored.');
|
|
9274
9313
|
return
|
|
9275
9314
|
}
|
|
9276
|
-
console.log('###
|
|
9277
|
-
|
|
9278
|
-
|
|
9315
|
+
console.log('### DUPLICATE_LOGIN detected.', old.cid);
|
|
9316
|
+
let sigPack = M$1.pack(
|
|
9317
|
+
M$1.MB('#MsgType', '8', IOMsg.AUTH_CLEAR),
|
|
9318
|
+
M$1.MB('#reason', 'duplicate login.')
|
|
9319
|
+
);
|
|
9320
|
+
old.send( sigPack);
|
|
9321
|
+
// old.close() client will close and stop.
|
|
9279
9322
|
peer.close(); // auto relogin
|
|
9280
9323
|
return
|
|
9281
9324
|
}
|
|
@@ -9322,7 +9365,7 @@ class BohoAuth {
|
|
|
9322
9365
|
// console.log("LOGIN: ", `id: ${ peer.did}(${peer.cid})` )
|
|
9323
9366
|
//10. send ack.
|
|
9324
9367
|
peer.send(auth_ack);
|
|
9325
|
-
peer.setState(
|
|
9368
|
+
peer.setState(STATE.AUTH_ACK);
|
|
9326
9369
|
if (this.authLogger) {
|
|
9327
9370
|
let peerInfo = `OK #${peer.ssid} cid: ${peer.cid} did:${peer.did}`;
|
|
9328
9371
|
if (peer.isAdmin) peerInfo = "#ADMIN# " + peerInfo;
|
|
@@ -9335,12 +9378,39 @@ class BohoAuth {
|
|
|
9335
9378
|
|
|
9336
9379
|
}
|
|
9337
9380
|
|
|
9381
|
+
async getAuth(id) {
|
|
9382
|
+
return this.keyProvider.getAuth(id);
|
|
9383
|
+
}
|
|
9384
|
+
|
|
9385
|
+
async getAuthIdList() {
|
|
9386
|
+
if (typeof this.keyProvider.getAuthIdList === 'function') {
|
|
9387
|
+
return this.keyProvider.getAuthIdList();
|
|
9388
|
+
}
|
|
9389
|
+
}
|
|
9390
|
+
|
|
9391
|
+
async addAuth(id, keyStr, cid, level = 0) {
|
|
9392
|
+
if (typeof this.keyProvider.addAuth === 'function') {
|
|
9393
|
+
return this.keyProvider.addAuth(id, keyStr, cid, level);
|
|
9394
|
+
}
|
|
9395
|
+
}
|
|
9396
|
+
|
|
9397
|
+
async delAuth(id) {
|
|
9398
|
+
if (typeof this.keyProvider.delAuth === 'function') {
|
|
9399
|
+
return this.keyProvider.delAuth(id);
|
|
9400
|
+
}
|
|
9401
|
+
}
|
|
9402
|
+
|
|
9403
|
+
async save() {
|
|
9404
|
+
if (typeof this.keyProvider.save === 'function') {
|
|
9405
|
+
return this.keyProvider.save();
|
|
9406
|
+
}
|
|
9407
|
+
}
|
|
9408
|
+
|
|
9338
9409
|
|
|
9339
9410
|
}
|
|
9340
9411
|
|
|
9341
|
-
class
|
|
9412
|
+
class FileKeyProvider {
|
|
9342
9413
|
constructor(_path) {
|
|
9343
|
-
super();
|
|
9344
9414
|
this.AUTH = new Map();
|
|
9345
9415
|
let pathObj = path.parse(_path);
|
|
9346
9416
|
this.path = path.resolve(_path);
|
|
@@ -9358,20 +9428,9 @@ class Auth_File extends BohoAuth {
|
|
|
9358
9428
|
}
|
|
9359
9429
|
}
|
|
9360
9430
|
|
|
9361
|
-
|
|
9362
|
-
async getAuth(id) {
|
|
9363
|
-
return this.AUTH.get(id)
|
|
9364
|
-
}
|
|
9365
|
-
|
|
9366
|
-
async getAuthIdList() {
|
|
9367
|
-
return Array.from(this.AUTH.keys())
|
|
9368
|
-
}
|
|
9369
|
-
|
|
9370
9431
|
//loaded when server start.
|
|
9371
9432
|
loadAuthInfoFile_JS(path) {
|
|
9372
|
-
|
|
9373
9433
|
import(path).then((file) => {
|
|
9374
|
-
|
|
9375
9434
|
console.log(file.authInfo);
|
|
9376
9435
|
file.authInfo.forEach(item => {
|
|
9377
9436
|
this.addAuth(...item);
|
|
@@ -9380,8 +9439,6 @@ class Auth_File extends BohoAuth {
|
|
|
9380
9439
|
}).catch(e => {
|
|
9381
9440
|
console.log(e);
|
|
9382
9441
|
});
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
9442
|
}
|
|
9386
9443
|
|
|
9387
9444
|
loadAuthInfoFile_JSON(path) {
|
|
@@ -9392,81 +9449,12 @@ class Auth_File extends BohoAuth {
|
|
|
9392
9449
|
this.addAuth(...item);
|
|
9393
9450
|
});
|
|
9394
9451
|
console.log('total AUTH INFO size: ', this.AUTH.size);
|
|
9395
|
-
|
|
9396
|
-
}
|
|
9397
|
-
|
|
9398
|
-
addAuth(id, keyStr, cid, level = 0) {
|
|
9399
|
-
let Base64hashKey = Buffer.from(tt.sha256.hash(keyStr)).toString('base64');
|
|
9400
|
-
this.AUTH.set(id, { key: Base64hashKey, cid: cid, level: level });
|
|
9401
|
-
}
|
|
9402
|
-
|
|
9403
|
-
|
|
9404
|
-
|
|
9405
|
-
}
|
|
9406
|
-
|
|
9407
|
-
/**
|
|
9408
|
-
* Auth_Env.js
|
|
9409
|
-
*
|
|
9410
|
-
* You can use environment variable BOHO_AUTH.
|
|
9411
|
-
*
|
|
9412
|
-
* BOHO_AUTH=id1.key1.level,id2:key2.level
|
|
9413
|
-
*
|
|
9414
|
-
* or constructor parameter.
|
|
9415
|
-
*
|
|
9416
|
-
*
|
|
9417
|
-
* [ authInfo ]
|
|
9418
|
-
* id: <String> max 8chars
|
|
9419
|
-
* key: <String>
|
|
9420
|
-
* level: <Numbrer> range: 0~255
|
|
9421
|
-
* separator: ','
|
|
9422
|
-
*
|
|
9423
|
-
* example => process.env.BOHO_AUTH=id1.key1.255,id2.key2.200
|
|
9424
|
-
*/
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
class Auth_Env extends BohoAuth {
|
|
9428
|
-
constructor(authInfo) {
|
|
9429
|
-
super();
|
|
9430
|
-
let id_keys;
|
|
9431
|
-
if (authInfo) {
|
|
9432
|
-
id_keys = authInfo.split(',');
|
|
9433
|
-
} else if (process.env.BOHO_AUTH) {
|
|
9434
|
-
authInfo = process.env.BOHO_AUTH;
|
|
9435
|
-
id_keys = process.env.BOHO_AUTH.split(',');
|
|
9436
|
-
} else {
|
|
9437
|
-
console.log("Auth_Env: None of process.env.BOHO_AUTH or authInfo");
|
|
9438
|
-
process.exit();
|
|
9439
|
-
}
|
|
9440
|
-
|
|
9441
|
-
this.AUTH = new Map();
|
|
9442
|
-
|
|
9443
|
-
if (id_keys.length >= 1) {
|
|
9444
|
-
id_keys.forEach(v => {
|
|
9445
|
-
|
|
9446
|
-
let did = v.split('.')[0];
|
|
9447
|
-
let key = v.split('.')[1];
|
|
9448
|
-
let level = v.split('.')[2];
|
|
9449
|
-
level = parseInt(level);
|
|
9450
|
-
|
|
9451
|
-
if (did && key && typeof level == 'number') {
|
|
9452
|
-
let cid = did;
|
|
9453
|
-
this.addAuth(did, key, cid, level);
|
|
9454
|
-
} else {
|
|
9455
|
-
console.log("Wrong process.env.BOHO_AUTH authentication value.", id, key, level);
|
|
9456
|
-
process.exit();
|
|
9457
|
-
}
|
|
9458
|
-
});
|
|
9459
|
-
|
|
9460
|
-
} else {
|
|
9461
|
-
console.log("Wrong process.env.BOHO_AUTH authentication value.");
|
|
9462
|
-
process.exit();
|
|
9463
|
-
}
|
|
9464
|
-
|
|
9465
9452
|
}
|
|
9466
9453
|
|
|
9467
9454
|
async getAuth(id) {
|
|
9468
9455
|
return this.AUTH.get(id)
|
|
9469
9456
|
}
|
|
9457
|
+
|
|
9470
9458
|
async getAuthIdList() {
|
|
9471
9459
|
return Array.from(this.AUTH.keys())
|
|
9472
9460
|
}
|
|
@@ -9475,16 +9463,14 @@ class Auth_Env extends BohoAuth {
|
|
|
9475
9463
|
let Base64hashKey = Buffer.from(tt.sha256.hash(keyStr)).toString('base64');
|
|
9476
9464
|
this.AUTH.set(id, { key: Base64hashKey, cid: cid, level: level });
|
|
9477
9465
|
}
|
|
9478
|
-
|
|
9479
9466
|
}
|
|
9480
9467
|
|
|
9481
9468
|
const DEVICE_PREFIX = "device:";
|
|
9482
9469
|
|
|
9483
|
-
class
|
|
9470
|
+
class RedisKeyProvider {
|
|
9484
9471
|
constructor(redisClient) {
|
|
9485
|
-
super();
|
|
9486
9472
|
if (!redisClient) {
|
|
9487
|
-
throw new Error("
|
|
9473
|
+
throw new Error("RedisKeyProvider constructor: no redisClient")
|
|
9488
9474
|
}
|
|
9489
9475
|
this.redis = redisClient;
|
|
9490
9476
|
}
|
|
@@ -9493,7 +9479,8 @@ class Auth_Redis extends BohoAuth {
|
|
|
9493
9479
|
async getAuth(id) {
|
|
9494
9480
|
try {
|
|
9495
9481
|
let result = await this.redis.hGetAll(DEVICE_PREFIX + id);
|
|
9496
|
-
if (result.key) return result
|
|
9482
|
+
if (result && result.key) return result
|
|
9483
|
+
else return null;
|
|
9497
9484
|
} catch (error) {
|
|
9498
9485
|
console.log('getAuth', error);
|
|
9499
9486
|
}
|
|
@@ -9522,7 +9509,60 @@ class Auth_Redis extends BohoAuth {
|
|
|
9522
9509
|
async save(id) {
|
|
9523
9510
|
return this.redis.save()
|
|
9524
9511
|
}
|
|
9512
|
+
}
|
|
9513
|
+
|
|
9514
|
+
/**
|
|
9515
|
+
* StringKeyProvider.js
|
|
9516
|
+
*
|
|
9517
|
+
* authInfo <String>
|
|
9518
|
+
* id: max 8chars
|
|
9519
|
+
* key: ~44 base64 chars recomended
|
|
9520
|
+
* cid:
|
|
9521
|
+
* level: range: 0~255
|
|
9522
|
+
* separator: ',' for multiple devices.
|
|
9523
|
+
*
|
|
9524
|
+
* example => authInfo = 'id1.key1.cid1.255,id2.key2.cid2.200'
|
|
9525
|
+
*/
|
|
9526
|
+
|
|
9527
|
+
|
|
9528
|
+
class StringKeyProvider {
|
|
9529
|
+
constructor(authInfo) {
|
|
9530
|
+
|
|
9531
|
+
if (!authInfo) {
|
|
9532
|
+
throw TypeError("StringKeyProvider constructor() missing authInfo.")
|
|
9533
|
+
}
|
|
9534
|
+
|
|
9535
|
+
let id_keys = authInfo.split(',');
|
|
9536
|
+
|
|
9537
|
+
this.AUTH = new Map();
|
|
9538
|
+
|
|
9539
|
+
if (id_keys.length >= 1) {
|
|
9540
|
+
id_keys.forEach(v => {
|
|
9541
|
+
let [ did, key, cid, level ] = v.split('.');
|
|
9542
|
+
level = parseInt(level);
|
|
9543
|
+
if (did && key && cid && typeof level == 'number') {
|
|
9544
|
+
this.addAuth(did, key, cid, level);
|
|
9545
|
+
} else {
|
|
9546
|
+
throw TypeError("StringKeyProvider invalid authInfo.")
|
|
9547
|
+
}
|
|
9548
|
+
});
|
|
9549
|
+
} else {
|
|
9550
|
+
throw TypeError("StringKeyProvider invalid authInfo.")
|
|
9551
|
+
}
|
|
9552
|
+
|
|
9553
|
+
}
|
|
9525
9554
|
|
|
9555
|
+
async getAuth(id) {
|
|
9556
|
+
return this.AUTH.get(id)
|
|
9557
|
+
}
|
|
9558
|
+
async getAuthIdList() {
|
|
9559
|
+
return Array.from(this.AUTH.keys())
|
|
9560
|
+
}
|
|
9561
|
+
|
|
9562
|
+
addAuth(id, keyStr, cid, level = 0) {
|
|
9563
|
+
let Base64hashKey = Buffer.from(tt.sha256.hash(keyStr)).toString('base64');
|
|
9564
|
+
this.AUTH.set(id, { key: Base64hashKey, cid: cid, level: level });
|
|
9565
|
+
}
|
|
9526
9566
|
}
|
|
9527
9567
|
|
|
9528
9568
|
const commands$1 = ['echo', 'date', 'unixtime'];
|
|
@@ -9707,4 +9747,4 @@ class RedisAPI {
|
|
|
9707
9747
|
|
|
9708
9748
|
const version = pkg.version;
|
|
9709
9749
|
|
|
9710
|
-
export { API_TYPE,
|
|
9750
|
+
export { API_TYPE, tt as Boho, BohoAuth, CongRx, ENC_MODE, FileKeyProvider, FileLogger, IOWS as IO, IOCongSocket, IOMsg, M$1 as MBP, PAYLOAD_TYPE, RedisAPI, RedisKeyProvider, SIZE_LIMIT, STATE, STATUS$1 as STATUS, Server, StringKeyProvider, api_reply, api_sudo, delay, getIPv4HexString, getLocalAddress, getPayloadFromSignalPack, getSignalPack, isPrivateIP, numberWithCommas, pack, parsePayload, serverOption, version };
|