iosignal 3.2.0 → 4.0.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.
Files changed (76) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/README.en.md +56 -0
  3. package/README.md +39 -782
  4. package/dist/io.d.ts +10 -3
  5. package/dist/io.js +4 -4
  6. package/dist/io.js.map +1 -1
  7. package/dist/io.min.js +4 -4
  8. package/dist/io.min.js.map +1 -1
  9. package/dist/iosignal.js +266 -217
  10. package/dist/types/client/IOCore.d.ts +10 -3
  11. package/package.json +3 -4
  12. package/src/api/RedisAPI.js +19 -31
  13. package/src/api/api_reply.js +14 -6
  14. package/src/api/api_sudo.js +2 -8
  15. package/src/auth/Auth_Redis.js +8 -3
  16. package/src/auth/BohoAuth.js +12 -12
  17. package/src/client/CongPacket.js +2 -0
  18. package/src/client/IOCore.js +98 -52
  19. package/src/server/Manager.js +12 -12
  20. package/src/server/Metric.js +1 -2
  21. package/src/server/RemoteCore.js +27 -34
  22. package/src/server/Server.js +69 -60
  23. package/src/server/serverOption.js +3 -2
  24. package/README.ko.md +0 -566
  25. package/docs/iosignal_architecture.png +0 -0
  26. package/examples/react-chat-js/dist/assets/index-Cy4qaVcJ.js +0 -56
  27. package/examples/react-chat-js/dist/assets/index-NETrjYhz.css +0 -1
  28. package/examples/react-chat-js/dist/index.html +0 -14
  29. package/examples/react-chat-js/index.html +0 -13
  30. package/examples/react-chat-js/package-lock.json +0 -1723
  31. package/examples/react-chat-js/package.json +0 -20
  32. package/examples/react-chat-js/src/App.css +0 -61
  33. package/examples/react-chat-js/src/App.jsx +0 -125
  34. package/examples/react-chat-js/src/index.css +0 -13
  35. package/examples/react-chat-js/src/main.jsx +0 -13
  36. package/examples/react-chat-js/src/shared_io.js +0 -12
  37. package/examples/react-chat-js/vite.config.js +0 -7
  38. package/examples/server/index.js +0 -12
  39. package/examples/server/package-lock.json +0 -47
  40. package/examples/server/package.json +0 -12
  41. package/examples/svelte-chat-js/.devtools +0 -3
  42. package/examples/svelte-chat-js/README.md +0 -38
  43. package/examples/svelte-chat-js/package-lock.json +0 -1505
  44. package/examples/svelte-chat-js/package.json +0 -22
  45. package/examples/svelte-chat-js/src/app.css +0 -105
  46. package/examples/svelte-chat-js/src/app.d.ts +0 -13
  47. package/examples/svelte-chat-js/src/app.html +0 -12
  48. package/examples/svelte-chat-js/src/lib/images/github.svg +0 -1
  49. package/examples/svelte-chat-js/src/lib/images/svelte-logo.svg +0 -1
  50. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.png +0 -0
  51. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.webp +0 -0
  52. package/examples/svelte-chat-js/src/lib/shared_io.js +0 -12
  53. package/examples/svelte-chat-js/src/routes/+layout.svelte +0 -9
  54. package/examples/svelte-chat-js/src/routes/+page.js +0 -3
  55. package/examples/svelte-chat-js/src/routes/+page.svelte +0 -162
  56. package/examples/svelte-chat-js/static/favicon.svg +0 -1
  57. package/examples/svelte-chat-js/static/global.css +0 -19
  58. package/examples/svelte-chat-js/static/robots.txt +0 -3
  59. package/examples/svelte-chat-js/svelte.config.js +0 -15
  60. package/examples/svelte-chat-js/vite.config.js +0 -6
  61. package/test-browser/favicon.ico +0 -0
  62. package/test-browser/index.html +0 -95
  63. package/test-browser/server.js +0 -12
  64. package/test-nodejs/client-playToggle.js +0 -19
  65. package/test-nodejs/client.js +0 -17
  66. package/test-nodejs/client_api_reply.js +0 -15
  67. package/test-nodejs/server-Auth_Env.js +0 -19
  68. package/test-nodejs/server-Auth_File.js +0 -12
  69. package/test-nodejs/server-api_reply.js +0 -6
  70. package/test-nodejs/server-api_sudo.js +0 -7
  71. package/test-nodejs/server.js +0 -20
  72. package/test-nodejs/signalPack.js +0 -34
  73. package/test-nodejs/signaling.js +0 -61
  74. package/test-nodejs/simple-server.js +0 -13
  75. /package/{auth_file.js → auth_file_sample.js} +0 -0
  76. /package/{auth_file.json → auth_file_sample.json} +0 -0
package/dist/iosignal.js CHANGED
@@ -13,7 +13,7 @@ import require$$2 from 'os';
13
13
  import require$$0$1 from 'buffer';
14
14
  import { memoryUsage } from 'process';
15
15
 
16
- var version$1 = "3.2.0";
16
+ var version$1 = "4.0.0";
17
17
  var pkg = {
18
18
  version: version$1};
19
19
 
@@ -985,7 +985,7 @@ class IOCore extends EventEmitter {
985
985
  close() {
986
986
  if (this._closed) return;
987
987
  this._closed = true;
988
-
988
+ // console.log('####### IOCOre.js close() called')
989
989
  // If auto-reconnect is disabled, we must stop the keep-alive timer.
990
990
  if (this.autoReconnect === false) {
991
991
  clearInterval(this.connectionCheckerIntervalID);
@@ -1206,13 +1206,25 @@ class IOCore extends EventEmitter {
1206
1206
  case IOMsg.PONG:
1207
1207
  break;
1208
1208
 
1209
+ case IOMsg.ECHO:
1210
+ try {
1211
+ let str = decoder$4.decode(buffer.subarray(1));
1212
+
1213
+ this.emit('echo', str);
1214
+ } catch (error) {
1215
+ this.emit('error', new Error('ECHO data error'));
1216
+ }
1217
+ break;
1218
+
1209
1219
  case IOMsg.IAM_RES:
1210
1220
  try {
1211
1221
  let str = decoder$4.decode(buffer.subarray(1));
1212
1222
  let jsonInfo = JSON.parse(str);
1213
- if (jsonInfo.ip) {
1214
- this.ip = jsonInfo.ip;
1215
- }
1223
+ if (jsonInfo.ip) { this.ip = jsonInfo.ip; }
1224
+ if (jsonInfo.nick) { this.nick = jsonInfo.nick; }
1225
+ if (jsonInfo.did) { this.did = jsonInfo.did; }
1226
+ if (jsonInfo.uid) { this.uid = jsonInfo.uid; }
1227
+ this.emit('iam_res', str );
1216
1228
  } catch (error) {
1217
1229
  this.emit('error', new Error('IAM_RES data error'));
1218
1230
  }
@@ -1223,7 +1235,7 @@ class IOCore extends EventEmitter {
1223
1235
  this.cid = cidStr;
1224
1236
 
1225
1237
  // **IMPORTANT** change state before subscribe.
1226
- this.stateChange('ready', 'cid_ready');
1238
+ this.stateChange('ready', 'cid_ready');
1227
1239
  this.subscribe_memory_channels();
1228
1240
  break;
1229
1241
 
@@ -1231,13 +1243,14 @@ class IOCore extends EventEmitter {
1231
1243
  let quotaLevel = buffer[1];
1232
1244
  this.level = quotaLevel;
1233
1245
  this.quota = quotaTable[quotaLevel];
1234
- console.log('## QUOTA:', quotaLevel, JSON.stringify(this.quota));
1246
+ console.log('[QUOTA_LEVEL]', JSON.stringify(this.quota));
1235
1247
  break;
1236
1248
 
1237
1249
  case IOMsg.SERVER_CLEAR_AUTH:
1238
1250
  this.useAuth = false;
1239
1251
  this.boho.clearAuth();
1240
1252
  this.stop();
1253
+ console.log('[SERVER_CLEAR_AUTH] io stop.');
1241
1254
  break;
1242
1255
 
1243
1256
  case IOMsg.SERVER_REDIRECT:
@@ -1311,8 +1324,11 @@ class IOCore extends EventEmitter {
1311
1324
  switch (payloadType) {
1312
1325
 
1313
1326
  case PAYLOAD_TYPE.EMPTY:
1314
- if (tag.indexOf('@') === 0) this.emit('@', null, tag);
1315
- else this.emit(tag, null, tag);
1327
+ if (tag.indexOf('@') === 0) this.emit('@', tag, null);
1328
+ else {
1329
+ this.emit(tag, tag, null);
1330
+ this.emit('message', tag, null );
1331
+ }
1316
1332
  break;
1317
1333
 
1318
1334
  case PAYLOAD_TYPE.TEXT:
@@ -1323,33 +1339,48 @@ class IOCore extends EventEmitter {
1323
1339
  payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1);
1324
1340
  }
1325
1341
  let oneString = decoder$4.decode(payloadStringWithoutNull);
1326
- if (tag.indexOf('@') === 0) this.emit('@', oneString, tag);
1327
- if (tag !== '@') this.emit(tag, oneString, tag);
1342
+ if (tag.indexOf('@') === 0) this.emit('@', tag, oneString);
1343
+ if (tag !== '@'){
1344
+ this.emit(tag, tag, oneString);
1345
+ this.emit('message', tag, oneString);
1346
+ }
1328
1347
  break;
1329
1348
 
1330
1349
  case PAYLOAD_TYPE.BINARY:
1331
- if (tag.indexOf('@') === 0) this.emit('@', payloadBuffer, tag);
1332
- if (tag !== '@') this.emit(tag, payloadBuffer, tag);
1350
+ if (tag.indexOf('@') === 0) this.emit('@', tag, payloadBuffer);
1351
+ if (tag !== '@'){
1352
+ this.emit(tag, tag, payloadBuffer);
1353
+ this.emit('message', tag, payloadBuffer);
1354
+ }
1333
1355
  break;
1334
1356
 
1335
1357
  case PAYLOAD_TYPE.OBJECT:
1336
1358
  let oneObjectBuffer = decoder$4.decode(payloadBuffer);
1337
1359
  let oneJSONObject = JSON.parse(oneObjectBuffer);
1338
- if (tag.indexOf('@') === 0) this.emit('@', oneJSONObject, tag);
1339
- if (tag !== '@') this.emit(tag, oneJSONObject, tag);
1360
+ if (tag.indexOf('@') === 0) this.emit('@', tag, oneJSONObject);
1361
+ if (tag !== '@'){
1362
+ this.emit(tag, tag, oneJSONObject);
1363
+ this.emit('message', tag, oneJSONObject);
1364
+ }
1340
1365
  break;
1341
1366
 
1342
1367
  case PAYLOAD_TYPE.MJSON:
1343
1368
  let mjsonBuffer = decoder$4.decode(payloadBuffer);
1344
1369
  let mjson = JSON.parse(mjsonBuffer);
1345
- if (tag.indexOf('@') === 0) this.emit('@', ...mjson, tag);
1346
- if (tag !== '@') this.emit(tag, ...mjson, tag);
1370
+ if (tag.indexOf('@') === 0) this.emit('@', tag, ...mjson);
1371
+ if (tag !== '@'){
1372
+ this.emit(tag, tag, ...mjson);
1373
+ this.emit('message', tag, ...mjson);
1374
+ }
1347
1375
  break;
1348
1376
 
1349
1377
  case PAYLOAD_TYPE.MBA:
1350
1378
  let mbaObject = M$1.unpack(payloadBuffer);
1351
- if (tag.indexOf('@') === 0) this.emit('@', ...mbaObject.args, tag);
1352
- if (tag !== '@') this.emit(tag, ...mbaObject.args, tag);
1379
+ if (tag.indexOf('@') === 0) this.emit('@', tag, ...mbaObject.args);
1380
+ if (tag !== '@'){
1381
+ this.emit(tag, tag, ...mbaObject.args);
1382
+ this.emit('message', tag, ...mbaObject.args );
1383
+ }
1353
1384
  break;
1354
1385
 
1355
1386
  default:
@@ -1441,7 +1472,7 @@ class IOCore extends EventEmitter {
1441
1472
  */
1442
1473
  echo(args) {
1443
1474
  if (args) {
1444
- console.log('echo args:', args);
1475
+ // console.log('send echo args:', args)
1445
1476
  this.send_enc_mode(M$1.pack(
1446
1477
  M$1.MB('#MsgType', '8', IOMsg.ECHO),
1447
1478
  M$1.MB('#msg', args)
@@ -1530,13 +1561,13 @@ class IOCore extends EventEmitter {
1530
1561
  */
1531
1562
  setMsgPromise(mid) {
1532
1563
  return new Promise((resolve, reject) => {
1533
- this.promiseMap.set(mid, [resolve, reject]);
1534
- setTimeout(e => {
1564
+ const timeoutId = setTimeout(e => {
1535
1565
  if (this.promiseMap.has(mid)) {
1536
1566
  reject('timeout');
1537
1567
  this.promiseMap.delete(mid);
1538
1568
  }
1539
1569
  }, this.promiseTimeOut);
1570
+ this.promiseMap.set(mid, [resolve, reject, timeoutId]);
1540
1571
  })
1541
1572
  }
1542
1573
 
@@ -1550,7 +1581,8 @@ class IOCore extends EventEmitter {
1550
1581
  if (!res) return
1551
1582
 
1552
1583
  if (this.promiseMap.has(res.mid)) {
1553
- let [resolve, reject] = this.promiseMap.get(res.mid);
1584
+ let [resolve, reject, timeoutId] = this.promiseMap.get(res.mid);
1585
+ clearTimeout(timeoutId);
1554
1586
  this.promiseMap.delete(res.mid);
1555
1587
 
1556
1588
  if (res.status < 128) {
@@ -1659,9 +1691,9 @@ class IOCore extends EventEmitter {
1659
1691
 
1660
1692
 
1661
1693
  /**
1662
- * Sends a request to a target and topic.
1663
- * @param {string} target - The target of the request.
1664
- * @param {string} topic - The topic of the request.
1694
+ * Sends a request to a target and topic.(remote api call)
1695
+ * @param {string} target - The target(api name) of the request.
1696
+ * @param {string} topic - The topic(api function name) of the request.
1665
1697
  * @param {...any} args - Optional arguments for the request.
1666
1698
  * @returns {Promise<any>}
1667
1699
  */
@@ -1697,21 +1729,24 @@ class IOCore extends EventEmitter {
1697
1729
  */
1698
1730
  subscribe(tag) {
1699
1731
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1732
+ if (tag.length > SIZE_LIMIT.TAG_LEN1) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN1)
1700
1733
  if (this.state !== STATES.READY) return
1701
1734
 
1702
- let tagList = tag.split(',');
1703
- tagList.forEach(tag => {
1704
- this.channels.add(tag);
1705
- });
1706
-
1707
- let tagEncoded = encoder$1.encode(tag);
1708
- if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN1) throw TypeError('please use tag string bytelength below:' + SIZE_LIMIT.TAG_LEN1)
1735
+ // subscribe 사용시, 사용 'ready' 이벤트시 메뉴얼 등록되므로 여기에 등록하면 2중 호출된다.
1736
+ // 즉, channels 등록은 listen 같은 자동화 구독시만 사용.
1737
+ // let tagList = tag.split(',')
1738
+ // tagList.forEach(tag => {
1739
+ // this.channels.add(tag)
1740
+ // })
1709
1741
 
1710
- this.send_enc_mode(
1711
- Buffer$1.concat([
1712
- M$1.NB('8', IOMsg.SUBSCRIBE),
1713
- M$1.NB('8', tagEncoded.byteLength),
1714
- tagEncoded]));
1742
+ try {
1743
+ let tagEncoded = encoder$1.encode(tag);
1744
+ this.send_enc_mode(
1745
+ Buffer$1.concat([
1746
+ M$1.NB('8', IOMsg.SUBSCRIBE),
1747
+ M$1.NB('8', tagEncoded.byteLength),
1748
+ tagEncoded]));
1749
+ } catch (error) { }
1715
1750
  }
1716
1751
 
1717
1752
  /**
@@ -1722,20 +1757,22 @@ class IOCore extends EventEmitter {
1722
1757
  */
1723
1758
  subscribe_promise(tag) {
1724
1759
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1760
+ if (tag.length > SIZE_LIMIT.TAG_LEN2) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN2)
1761
+
1725
1762
  if (this.state !== STATES.READY) {
1726
1763
  return Promise.reject('subscribe_promise:: connection is not ready')
1727
1764
  }
1728
1765
 
1729
- let tagEncoded = encoder$1.encode(tag);
1730
- if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN2) throw TypeError('please use tag string bytelength: ' + SIZE_LIMIT.TAG_LEN2)
1731
-
1732
- this.send_enc_mode(
1733
- Buffer$1.concat([
1734
- M$1.NB('8', IOMsg.SUBSCRIBE_REQ),
1735
- M$1.NB('16', ++this.mid),
1736
- M$1.NB('16', tagEncoded.byteLength),
1737
- tagEncoded]));
1738
- return this.setMsgPromise(this.mid)
1766
+ try {
1767
+ let tagEncoded = encoder$1.encode(tag);
1768
+ this.send_enc_mode(
1769
+ Buffer$1.concat([
1770
+ M$1.NB('8', IOMsg.SUBSCRIBE_REQ),
1771
+ M$1.NB('16', ++this.mid),
1772
+ M$1.NB('16', tagEncoded.byteLength),
1773
+ tagEncoded]));
1774
+ return this.setMsgPromise(this.mid)
1775
+ } catch (error) { }
1739
1776
  }
1740
1777
 
1741
1778
  /**
@@ -1932,14 +1969,23 @@ class IOCore extends EventEmitter {
1932
1969
  * Changes the connection state and emits events.
1933
1970
  * @param {string} state - The new state name (e.g., 'ready', 'closed').
1934
1971
  * @param {string} [emitEventAndMessage] - Optional message to emit with the state change event.
1972
+ *
1973
+ * 주의.
1974
+ * 1. 상태가 변경 될 때만 'change' 이벤트 호출된다.
1975
+ * 2. emitEventAndMessage 옵션 값이 지정되야 해당 이벤트 이름이 호출된다.
1976
+ * 보통 이벤트 이름과 동일하게 적거나 이벤트 상황 안내문을 넣는다.
1935
1977
  */
1936
1978
  stateChange(state, emitEventAndMessage) {
1937
- // STATES constant name : string upperCase
1938
- // eventName, .stateName : string lowerCase
1939
- // .state : number
1979
+ // STATES constant name <string> upperCase
1980
+ // eventName and .stateName <string> lowerCase
1981
+ // .state <number>
1982
+ // console.log('### stateChange reason:', emitEventAndMessage )
1940
1983
  let eventName = state.toLowerCase();
1941
1984
  this.state = STATES[state.toUpperCase()]; // state: number
1942
- if (emitEventAndMessage) this.emit(eventName, emitEventAndMessage);
1985
+
1986
+ if (emitEventAndMessage){
1987
+ this.emit(eventName, emitEventAndMessage);
1988
+ }
1943
1989
 
1944
1990
  if (this.stateName !== eventName) {
1945
1991
  this.stateName = eventName;
@@ -1959,6 +2005,8 @@ const CongType = {
1959
2005
  // support LittleEndian system.
1960
2006
  function pack(payload) {
1961
2007
 
2008
+ if( payload.byteLength == undefined ) payload = Buffer.from(payload);
2009
+
1962
2010
  if (payload.byteLength < 256) { //one byte len
1963
2011
  return M$1.pack(
1964
2012
  M$1.MB('#type', '8', CongType.TYPE_LEN1),
@@ -7591,6 +7639,7 @@ let serverOption = {
7591
7639
  port: null, // WebSocket
7592
7640
  congPort: null, // CongSocket
7593
7641
  httpServer: null,
7642
+ wsPath: null,
7594
7643
  timeout: 50000,
7595
7644
  showMessage: 'none',
7596
7645
  showMetric: 0,
@@ -7632,10 +7681,10 @@ let serverOption = {
7632
7681
  },
7633
7682
 
7634
7683
  auth: {
7635
- delay_auth_fail: 1000,
7684
+ delay_auth_fail: 600,
7636
7685
  },
7637
7686
 
7638
- memberOnly: false
7687
+ membersOnly: false
7639
7688
 
7640
7689
  };
7641
7690
 
@@ -7662,15 +7711,13 @@ class RemoteCore {
7662
7711
  this.ssid = RemoteCore.ssid++; // ordered index number
7663
7712
  this.manager = manager;
7664
7713
 
7665
- this.cid; // Communication Id
7666
- this.did; // Device Id
7667
- this.uid; // User Id
7668
- this.nick = "";
7669
-
7714
+ this.cid = ''; // Communication Id
7715
+ this.did = ''; // Device Id
7716
+ this.uid = ''; // User Id
7717
+ this.nick = '';
7670
7718
 
7671
- this.lastEchoMessage = "N";
7672
7719
  this.privateNode = false;
7673
- this.HOME_CHANNEL = "";
7720
+ this.HOME_CHANNEL = '';
7674
7721
  this.level = serverOption.defaultQuotaIndex;
7675
7722
  this.quota = quotaTable[this.level];
7676
7723
  this.isAdmin = false;
@@ -7686,7 +7733,8 @@ class RemoteCore {
7686
7733
  setState(state) {
7687
7734
  this.state = state;
7688
7735
  if (serverOption.debug.showAuthInfo) {
7689
- this.stateLog.push(state);
7736
+ // let s = state + ":" + CLIENT_STATE[ state]
7737
+ this.stateLog.push( state );
7690
7738
  console.log(this.stateLog.join('>'));
7691
7739
  }
7692
7740
  }
@@ -7701,7 +7749,7 @@ class RemoteCore {
7701
7749
 
7702
7750
 
7703
7751
  showMessageLog(message, isBinary) {
7704
- let from = this.boho.isAuthorized ? `did: ${this.did} ${this.cid}@` : `${this.cid}@`;
7752
+ let from = this.boho.isAuthorized ? `[FROM]did: ${this.did} cid:${this.cid}` : `[FROM]cid:${this.cid}`;
7705
7753
  if (isBinary) {
7706
7754
  let msgTypeName = IOMsg[message[0]];
7707
7755
  if (!msgTypeName) msgTypeName = tt.BohoMsg[message[0]];
@@ -7798,6 +7846,7 @@ class RemoteCore {
7798
7846
  case IOMsg.CID_REQ:
7799
7847
  if (this.state < CLIENT_STATE.SENT_SERVER_READY) {
7800
7848
  // Protocol violation: CID_REQ was sent before receiving the SERVER_READY signal.
7849
+ console.log('CID_REQ before SERVER_READY');
7801
7850
  this.close();
7802
7851
  }
7803
7852
 
@@ -7815,22 +7864,16 @@ class RemoteCore {
7815
7864
  this.setState(CLIENT_STATE.CID_READY);
7816
7865
  break;
7817
7866
 
7818
-
7819
- case IOMsg.ECHO: // TEXT only
7820
- try {
7821
- let msg = decoder$3.decode(message.subarray(1));
7822
- this.lastEchoMessage = msg;
7823
- } catch (error) {
7824
- // console.log('ECHO message is not a text')
7867
+ case IOMsg.ECHO:
7868
+ if( message.byteLength < 30) {
7869
+ this.send(message, isBinary);
7825
7870
  }
7826
- this.send(message, isBinary);
7827
7871
  break;
7828
7872
 
7829
7873
  case IOMsg.IAM:
7830
- if (message.byteLength > 1) {
7831
- let iamInfo = message.subarray(1);
7832
- this.nick = decoder$3.decode(iamInfo);
7833
- console.log('iam nick reset', this.nick);
7874
+ if (message.byteLength > 1 && message.byteLength < 30) {
7875
+ // if iam request has a text message then reset the nick property.
7876
+ this.nick = decoder$3.decode(message.subarray(1));
7834
7877
  }
7835
7878
  this.iamResponse();
7836
7879
  break;
@@ -7851,7 +7894,7 @@ class RemoteCore {
7851
7894
 
7852
7895
  case IOMsg.UNSUBSCRIBE:
7853
7896
  if (message.byteLength == 2) {
7854
- this.manager.unsubscribe([""], this);
7897
+ this.manager.unsubscribe([''], this);
7855
7898
  } else if (message.byteLength >= 3) {
7856
7899
  let tagLen = message.readUInt8(1);
7857
7900
 
@@ -7925,7 +7968,7 @@ class RemoteCore {
7925
7968
  case tt.BohoMsg.AUTH_REQ:
7926
7969
  if (!this.manager.authManager) return
7927
7970
  if (this.state < CLIENT_STATE.SENT_SERVER_READY) {
7928
- // console.log('protocol error. auth_req before server_ready')
7971
+ console.log('protocol error. auth_req before server_ready');
7929
7972
  this.close();
7930
7973
  }
7931
7974
  this.setState(CLIENT_STATE.RECV_AUTH_REQ);
@@ -7938,22 +7981,23 @@ class RemoteCore {
7938
7981
  case tt.BohoMsg.AUTH_HMAC:
7939
7982
  if (!this.manager.authManager) return
7940
7983
  if (this.state < CLIENT_STATE.SENT_SERVER_NONCE) {
7941
- // console.log('protocol error. auth_hmac before server_nonce')
7984
+ console.log('protocol error. auth_hmac before server_nonce');
7942
7985
  this.close();
7943
7986
  }
7944
7987
  this.setState(CLIENT_STATE.RECV_AUTH_HMAC);
7945
7988
  //async
7946
7989
  this.manager.authManager.verify_auth_hmac(message, this)
7947
7990
  .then(authInfo => {
7948
- if (authInfo) {
7949
- this.manager.deligateSignal(remote, '@$name', authInfo.name);
7991
+ if (authInfo?.name) {
7992
+ this.manager.deligateSignal(this, '@$name', authInfo.name);
7950
7993
  // console.log('device login success authInfo', authInfo)
7951
7994
  // this.manager.sender('@$name', authInfo.name )
7952
7995
  }
7953
7996
 
7997
+ // console.log('[VERIFY AUTH_HMAC] SubClass of BohoAuth return authInfo:', authInfo )
7954
7998
  })
7955
7999
  .catch(e => {
7956
-
8000
+ console.log('authInfo return fail.', e );
7957
8001
  });
7958
8002
 
7959
8003
  return;
@@ -7979,23 +8023,19 @@ class RemoteCore {
7979
8023
  response(msgId, statusCode, body) {
7980
8024
  // console.log('response body', body)
7981
8025
  if (body) {
7982
-
7983
8026
  this.send_enc_mode(M$1.pack(
7984
8027
  MB('#type', '8', IOMsg.RESPONSE_MBP),
7985
8028
  MB('status', '8', statusCode),
7986
8029
  MB('mid', '16', msgId),
7987
8030
  MB('body', body)
7988
8031
  ));
7989
-
7990
8032
  } else {
7991
8033
  this.send_enc_mode(M$1.pack(
7992
8034
  MB('#type', '8', IOMsg.RESPONSE_MBP),
7993
8035
  MB('status', '8', statusCode),
7994
8036
  MB('mid', '16', msgId)
7995
8037
  ));
7996
-
7997
8038
  }
7998
-
7999
8039
  }
8000
8040
 
8001
8041
 
@@ -8036,9 +8076,9 @@ class RemoteCore {
8036
8076
 
8037
8077
 
8038
8078
 
8039
- iamResponse(info = "") {
8079
+ iamResponse(info = '') {
8040
8080
 
8041
- if (info == "") {
8081
+ if (info == '') {
8042
8082
  let channels = [];
8043
8083
  for (let tag of this.channels.keys()) {
8044
8084
  channels.push(tag);
@@ -8046,15 +8086,17 @@ class RemoteCore {
8046
8086
 
8047
8087
  info = {
8048
8088
  "ssid": this.ssid,
8049
- "uid": this.uid,
8050
8089
  "cid": this.cid,
8051
8090
  "did": this.did,
8091
+ "uid": this.uid,
8092
+ "level": this.level,
8052
8093
  "nick": this.nick,
8053
8094
  "ip": this.ip
8054
8095
  , 'tag': channels
8055
8096
  };
8056
8097
  }
8057
8098
 
8099
+ // console.log( 'iam res info', info )
8058
8100
  let pack = M$1.pack(
8059
8101
  MB('#MsgType', '8', IOMsg.IAM_RES),
8060
8102
  MB('#info', info)
@@ -8440,8 +8482,7 @@ class Metric {
8440
8482
  ip: remote.ip,
8441
8483
  uptime: Math.trunc((Date.now() - remote.socket.openTime) / 1000),
8442
8484
  nick: remote.nick,
8443
- ssid: remote.ssid,
8444
- echo: remote.lastEchoMessage
8485
+ ssid: remote.ssid
8445
8486
  }
8446
8487
  } else if (mode == 3) {
8447
8488
  return {
@@ -8644,8 +8685,8 @@ class Manager {
8644
8685
  serverSignalTo(tag, ...args) {
8645
8686
  let cid = tag.split('@')[0];
8646
8687
  let topic = tag.split('@')[1];
8647
- let sigPack = getSignalPack('@' + topic, ...args);
8648
8688
  if (cid && this.cid2remote.has(cid)) {
8689
+ let sigPack = getSignalPack('@' + topic, ...args);
8649
8690
  let targetRemote = this.cid2remote.get(cid);
8650
8691
  console.log('target', targetRemote.state, targetRemote.cid);
8651
8692
  targetRemote.send_enc_mode(sigPack);
@@ -8656,11 +8697,11 @@ class Manager {
8656
8697
  }
8657
8698
 
8658
8699
  sender(tag, remote, message) {
8659
- if (serverOption.memberOnly && !remote.boho.isAuthorized) {
8660
- // console.log("## MemberOnly, reject unAuthorized remote." )
8700
+ if (serverOption.membersOnly && !remote.boho.isAuthorized) {
8701
+ console.log("[membersOnly] unAuthorized remote.",tag );
8661
8702
  remote.send(Buffer.from([IOMsg.SERVER_CLEAR_AUTH]));
8662
8703
  remote.close();
8663
- return ['err', 'not autrized']
8704
+ return ['err', 'unAuthorized']
8664
8705
  }
8665
8706
 
8666
8707
  if (tag.indexOf('$') == 0) return ['err', 'prefix $ is reserved for userSet tag.']
@@ -8742,13 +8783,18 @@ class Manager {
8742
8783
  // console.log('## null remote' )
8743
8784
  break;
8744
8785
  }
8745
- if (c !== remote) {
8786
+ // change: from v4.x allow receiveSelfMessages.
8787
+ // if (c !== remote) {
8746
8788
  c.send_enc_mode(message);
8747
8789
  sentCounter++;
8748
- }
8790
+ // }
8749
8791
  }
8750
8792
 
8751
- if (serverOption.useQuota.publishCounter) ;
8793
+ // if (serverOption.useQuota.publishCounter) {
8794
+ // // console.log(`pub >> [${tag}] sent: ${sentCounter} [use quota limit: ${remote.quota.publishCounter }] total: ${remotes.size} subscribers. ` )
8795
+ // } else {
8796
+ // // console.log(`pub >> [${tag}] sent: ${sentCounter} [no quota limit] total: ${remotes.size} subscribers. ` )
8797
+ // }
8752
8798
  return ['ok', sentCounter]
8753
8799
  }
8754
8800
  }
@@ -8895,7 +8941,6 @@ class Manager {
8895
8941
  this.retain_messages.clear();
8896
8942
  this.channel_map.clear();
8897
8943
 
8898
- console.log('Manager closed');
8899
8944
  }
8900
8945
  }
8901
8946
 
@@ -8919,20 +8964,20 @@ class Server extends require$$0$3 {
8919
8964
  let pingT = parseInt(options.timeout);
8920
8965
  if (pingT && pingT >= 1000) serverOption.timeout = pingT;
8921
8966
  }
8922
-
8923
8967
  if (options.monitorPeriod) {
8924
8968
  let monitorT = parseInt(options.monitorPeriod);
8925
8969
  if (monitorT && monitorT >= 1000) serverOption.monitorPeriod = monitorT;
8926
8970
  }
8927
-
8928
-
8929
8971
  if (options.showMessage) {
8930
8972
  serverOption.showMessage = options.showMessage;
8931
8973
  }
8932
-
8933
8974
  if (options.showMetric) {
8934
8975
  serverOption.showMetric = options.showMetric;
8935
8976
  }
8977
+ if (options.membersOnly) {
8978
+ serverOption.membersOnly = options.membersOnly;
8979
+ }
8980
+
8936
8981
 
8937
8982
  if (options.port || options.port == 0) {
8938
8983
  this.port = parseInt(options.port);
@@ -8942,6 +8987,10 @@ class Server extends require$$0$3 {
8942
8987
  this.httpServer = options.httpServer;
8943
8988
  }
8944
8989
 
8990
+ if (options.wsPath) {
8991
+ this.wsPath = options.wsPath;
8992
+ }
8993
+
8945
8994
  if (options.congPort || options.congPort == 0) {
8946
8995
  this.congPort = parseInt(options.congPort);
8947
8996
  }
@@ -8954,7 +9003,7 @@ class Server extends require$$0$3 {
8954
9003
  if (this.congPort || this.congPort == 0) this.serverCountToListen++;
8955
9004
 
8956
9005
  if (this.serverCountToListen === 0) {
8957
- process.nextTick(() => this.emit('ready'));
9006
+ throw new Error('Cannot create Server: At least one of "port", "httpServer", or "congPort" must be specified.');
8958
9007
  } else {
8959
9008
  if (this.port || this.port == 0 || this.httpServer) this.startWSServer();
8960
9009
  if (this.congPort || this.congPort == 0) this.startCongServer();
@@ -8964,14 +9013,11 @@ class Server extends require$$0$3 {
8964
9013
 
8965
9014
 
8966
9015
  startWSServer() {
8967
-
8968
9016
  // console.log('optoins', options )
8969
9017
  if (this.port || this.port == 0) {
8970
- console.log('opening WebSocket Server port:', this.port);
8971
- this.wss = new WebSocketServer({ port: this.port });
8972
- } else if (this.httpServer) {
8973
- console.log('opening WebSocket Server external httpServer:');
8974
- this.wss = new WebSocketServer({ server: this.httpServer });
9018
+ this.wss = new WebSocketServer({ port: this.port , path: this.wsPath });
9019
+ } else if (this.httpServer ) {
9020
+ this.wss = new WebSocketServer({ server: this.httpServer, path: this.wsPath });
8975
9021
  } else {
8976
9022
  throw new TypeError(
8977
9023
  'One and only one of the "port", "httpServer"' +
@@ -8979,7 +9025,6 @@ class Server extends require$$0$3 {
8979
9025
  );
8980
9026
  }
8981
9027
 
8982
-
8983
9028
  this.wss.once('listening', () => {
8984
9029
  this.port = this.wss.address().port;
8985
9030
  console.log('wss server bound port:', this.port );
@@ -8990,7 +9035,6 @@ class Server extends require$$0$3 {
8990
9035
  });
8991
9036
 
8992
9037
  // this.wss.setMaxListeners(0)
8993
-
8994
9038
  this.wss.on('error', (err) => {
8995
9039
  console.error('### ws server error:', err.message);
8996
9040
  if (err.code == 'EADDRINUSE') {
@@ -8998,8 +9042,8 @@ class Server extends require$$0$3 {
8998
9042
  }
8999
9043
  });
9000
9044
 
9001
- this.wss.on('close', (err) => {
9002
- console.log('### WS server closed.', err);
9045
+ this.wss.on('close', () => {
9046
+ console.log('### WS server is closed.');
9003
9047
  });
9004
9048
 
9005
9049
  this.wss.on('connection', (ws, req) => {
@@ -9011,8 +9055,6 @@ class Server extends require$$0$3 {
9011
9055
  }
9012
9056
 
9013
9057
  startCongServer() {
9014
- console.log('opening CongSocket Server port:', this.congPort);
9015
-
9016
9058
  this.congServer = net.createServer((socket) => {
9017
9059
  this.manager.addRemote(socket);
9018
9060
  })
@@ -9022,7 +9064,7 @@ class Server extends require$$0$3 {
9022
9064
  process.exit();
9023
9065
  }
9024
9066
  }).on('close', () => {
9025
- console.log('### cong server closed.');
9067
+ console.log('### congsocket server is closed.');
9026
9068
  }).listen(this.congPort, () => {
9027
9069
  this.congPort = this.congServer.address().port;
9028
9070
  console.log('congsocket server bound port:', this.congPort );
@@ -9033,64 +9075,76 @@ class Server extends require$$0$3 {
9033
9075
  });
9034
9076
  }
9035
9077
 
9036
-
9037
-
9078
+ /**
9079
+ * API register.
9080
+ * target: api_name <string>
9081
+ * api: api_module <function module|class instance>
9082
+ * return this
9083
+ */
9038
9084
  api(target, api) {
9039
9085
 
9040
- this.apiNames.add(target);
9041
-
9086
+ if( typeof target !== 'string'){
9087
+ throw new Error(`api( target ,api ) target name is not a string.`)
9088
+ }
9042
9089
  if (!api.checkPermission || typeof api.checkPermission != 'function') {
9043
- throw new Error('wrong api interface. no checkPermission function.')
9090
+ throw new Error(`API ${target} : no checkPermission or not a function.`)
9044
9091
  }
9045
-
9046
-
9047
- if (typeof api.request == 'function' && Array.isArray(api.commands)) {
9048
- console.log(`API TYPE1. A Class with one request function. target: ${target} list: ${api.commands}`);
9049
-
9050
- this.on(target, (remote, req) => {
9051
- if (api.checkPermission(remote, req)) {
9052
- api.request(remote, req);
9053
- } else {
9054
- remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.");
9092
+ if(!api.commands || !Array.isArray(api.commands) ){
9093
+ throw new Error(`API ${target} : no commands or !Array.`)
9094
+ }
9095
+
9096
+ // API TYPE 1. single request() function.
9097
+ if ( api.request && typeof api.request == 'function' ) {
9098
+ this.on(target, async (remote, req) => {
9099
+ try {
9100
+ if (!api.checkPermission(remote, req)) {
9101
+ remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.");
9102
+ return
9103
+ }
9104
+ if( api.commands.includes( req.topic )){
9105
+ console.log('server api req', req );
9106
+ await api.request(remote, req);
9107
+ }else {
9108
+ remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
9109
+ }
9110
+ } catch (error) {
9111
+ console.error(`Unhandled API Error in target [${target}]:`, error);
9112
+ remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
9055
9113
  }
9056
9114
  });
9057
-
9058
9115
  } else {
9059
- let apiList = [];
9060
- Object.keys(api).forEach(v => {
9061
- if (typeof api[v] === 'function') apiList.push(v);
9062
- console.log('api list', typeof api[v], v);
9063
- });
9064
-
9065
- console.log(`API TYPE2. Multiple function list. target: ${target} list:${apiList}`);
9066
-
9067
- this.on(target, (remote, req) => {
9068
- let r;
9069
- if (!api.checkPermission(remote, req)) {
9070
- r = "NO_PERMISSION.";
9071
- } else {
9072
- if (api[req.topic]) {
9073
- console.log(`API TYPE2. request target: ${target} has topic:${req.topic}`);
9074
- api[req.topic](remote, req);
9116
+ // API TYPE 2. multiple functions.
9117
+ this.on(target, async (remote, req) => {
9118
+ try {
9119
+ if (!api.checkPermission(remote, req)) {
9120
+ remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.");
9075
9121
  return
9076
- } else {
9077
- r = `target: ${req.target} has not topic name: ${req.topic}`;
9078
9122
  }
9123
+ if( api.commands.includes( req.topic )){
9124
+ await api[req.topic](remote, req);
9125
+ }else {
9126
+ remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
9127
+ }
9128
+ } catch (error) {
9129
+ console.error(`Unhandled API Error in target [${target}]:`, error);
9130
+ remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
9079
9131
  }
9080
-
9081
- remote.response(req.mid, STATUS.ERROR, r);
9082
9132
  });
9083
9133
  }
9084
-
9134
+ this.apiNames.add(target);
9135
+ console.log(`[API registed: ${target} ] accept commands: ${api.commands}`);
9085
9136
  return this
9086
9137
  }
9087
9138
 
9088
9139
  close(callback) {
9089
- console.log('closing io-signal server...');
9140
+ console.log('closing iosignal server...');
9090
9141
  if (this.manager) {
9091
9142
  this.manager.close();
9092
9143
  }
9093
9144
 
9145
+ this.apiNames.forEach(v => this.removeAllListeners(v));
9146
+ this.apiNames.clear();
9147
+
9094
9148
  let serverCount = 0;
9095
9149
  if (this.wss) serverCount++;
9096
9150
  if (this.congServer) serverCount++;
@@ -9104,14 +9158,14 @@ class Server extends require$$0$3 {
9104
9158
  const onClosed = () => {
9105
9159
  closedCount++;
9106
9160
  if (closedCount === serverCount) {
9107
- console.log('io-signal server closed.');
9161
+ console.log('IOSignal server is closed.');
9108
9162
  if (callback) callback();
9109
9163
  }
9110
9164
  };
9111
9165
 
9112
9166
  if (this.wss) {
9113
9167
  this.wss.close(() => {
9114
- console.log('wss server closed.');
9168
+ // console.log('wss server closed.')
9115
9169
  onClosed();
9116
9170
  });
9117
9171
  }
@@ -9119,7 +9173,7 @@ class Server extends require$$0$3 {
9119
9173
  if (this.congServer) {
9120
9174
  this.congServer.close((err) => {
9121
9175
  if (err) console.error('congServer close error', err);
9122
- console.log('cong server closed.');
9176
+ // console.log('cong server closed.')
9123
9177
  onClosed();
9124
9178
  });
9125
9179
  }
@@ -9142,10 +9196,9 @@ class BohoAuth {
9142
9196
  let peerInfo = `FAIL #${peer.ssid} reason:${reason} `;
9143
9197
  this.authLogger.log(peerInfo);
9144
9198
  }
9145
-
9146
- console.log('## AUTH_FAIL reason:', reason);
9147
- // peer.send( Buffer.from( [Boho.BohoMsg.AUTH_FAIL] ))
9199
+ // console.log('##### AUTH_FAIL reason: ', reason)
9148
9200
  peer.setState(CLIENT_STATE.AUTH_FAIL);
9201
+ // add some delay time.
9149
9202
  setTimeout(e => {
9150
9203
  peer.send(Buffer.from([tt.BohoMsg.AUTH_FAIL]));
9151
9204
  }, serverOption.auth.delay_auth_fail);
@@ -9155,30 +9208,31 @@ class BohoAuth {
9155
9208
  try {
9156
9209
  //1. unpack
9157
9210
  let infoPack = M$1.unpack(auth_hmac, tt.Meta.AUTH_HMAC);
9211
+
9158
9212
  if (!infoPack) {
9159
9213
  this.send_auth_fail(peer, 'unpack auth_pack fail');
9160
9214
  return
9161
9215
  }
9162
-
9216
+
9163
9217
  let id = "";
9164
9218
  if (infoPack.id8.includes(0)) {
9165
9219
  id = decoder.decode(infoPack.id8.subarray(0, infoPack.id8.indexOf(0)));
9166
9220
  } else {
9167
9221
  id = decoder.decode(infoPack.id8);
9168
9222
  }
9169
-
9223
+
9170
9224
  //2. get key of id from DB
9171
9225
  let authInfo = await this.getAuth(id);
9172
9226
 
9173
- // console.log('##### authInfo',authInfo )
9174
- if (serverOption.debug.showAuthInfo) {
9175
- }
9176
-
9177
9227
  if (!authInfo) {
9178
9228
  this.send_auth_fail(peer, 'NO ID:' + id);
9179
9229
  return
9180
9230
  }
9181
9231
 
9232
+ if (serverOption.debug.showAuthInfo) {
9233
+ console.log('[debug]showAuthInfo',authInfo );
9234
+ }
9235
+
9182
9236
  // console.log('db authInfo.key: ', authInfo.key)
9183
9237
  peer.boho.copy_id8(infoPack.id8);
9184
9238
  // type of key
@@ -9229,6 +9283,7 @@ class BohoAuth {
9229
9283
 
9230
9284
  //6. delete current (temp rand)cid if exist.
9231
9285
  if (peer.cid) {
9286
+ console.log('duplicate cid');
9232
9287
  peer.manager.cid2remote.delete(peer.cid);
9233
9288
  }
9234
9289
 
@@ -9236,6 +9291,7 @@ class BohoAuth {
9236
9291
  peer.did = id;
9237
9292
  peer.cid = authInfo.cid;
9238
9293
  peer.nick = authInfo.cid; // temporary: nick as cid
9294
+ if( authInfo.uid ) peer.uid = authInfo.uid;
9239
9295
 
9240
9296
  //8. setting quota level.
9241
9297
  let quotaLevel = serverOption.defaultQuotaIndex;
@@ -9274,14 +9330,12 @@ class BohoAuth {
9274
9330
  }
9275
9331
  return authInfo
9276
9332
  } catch (error) {
9277
- this.send_auth_fail(peer, 'caught: unknown error' + error);
9333
+ this.send_auth_fail(peer, '[BohoAuth]caught: unknown error:' + error);
9278
9334
  }
9279
9335
 
9280
9336
  }
9281
9337
 
9282
9338
 
9283
-
9284
-
9285
9339
  }
9286
9340
 
9287
9341
  class Auth_File extends BohoAuth {
@@ -9437,11 +9491,15 @@ class Auth_Redis extends BohoAuth {
9437
9491
 
9438
9492
  // get device key from DB. (for Boho auth.)
9439
9493
  async getAuth(id) {
9440
- let result = await this.redis.hGetAll(DEVICE_PREFIX + id);
9441
- if (result.key) return result
9494
+ try {
9495
+ let result = await this.redis.hGetAll(DEVICE_PREFIX + id);
9496
+ if (result.key) return result
9497
+ } catch (error) {
9498
+ console.log('getAuth', error);
9499
+ }
9442
9500
  }
9443
9501
 
9444
-
9502
+ //api_sudo call
9445
9503
  async getAuthIdList() {
9446
9504
  let result = await this.redis.keys(DEVICE_PREFIX + '*');
9447
9505
  result = result.map(v => {
@@ -9456,6 +9514,7 @@ class Auth_Redis extends BohoAuth {
9456
9514
  return this.redis.hSet(DEVICE_PREFIX + id, { 'key': Base64hashKey, 'cid': cid, 'level': level })
9457
9515
  }
9458
9516
 
9517
+ //api_sudo call
9459
9518
  async delAuth(id) {
9460
9519
  return this.redis.del(DEVICE_PREFIX + id)
9461
9520
  }
@@ -9466,16 +9525,16 @@ class Auth_Redis extends BohoAuth {
9466
9525
 
9467
9526
  }
9468
9527
 
9469
- const MIN_LEVEL$2 = 0;
9528
+ const commands$1 = ['echo', 'date', 'unixtime'];
9470
9529
 
9530
+ const MIN_LEVEL$2 = 0;
9471
9531
  function checkPermission$1(remote) {
9472
- if (remote.level >= MIN_LEVEL$2) {
9473
- return true
9474
- } else {
9475
- return false
9476
- }
9532
+ return (remote.level >= MIN_LEVEL$2) ? true : false;
9477
9533
  }
9478
9534
 
9535
+ /**
9536
+ * client api call example: await io.req('reply','echo','hello')
9537
+ */
9479
9538
  async function echo(remote, req) {
9480
9539
  if (!req.args)
9481
9540
  remote.response(req.mid, STATUS.ERROR, 'no message to echo');
@@ -9483,11 +9542,17 @@ async function echo(remote, req) {
9483
9542
  remote.response(req.mid, STATUS.OK, req.args);
9484
9543
  }
9485
9544
 
9545
+ /**
9546
+ * client api call example: await io.req('reply','date')
9547
+ */
9486
9548
  async function date(remote, req) {
9487
9549
  let r = new Date().toUTCString();
9488
9550
  remote.response(req.mid, STATUS.OK, r);
9489
9551
  }
9490
9552
 
9553
+ /**
9554
+ * client api call example: await io.req('reply','unixtime')
9555
+ */
9491
9556
  async function unixtime(remote, req) {
9492
9557
  let r = Math.floor(Date.now() / 1000);
9493
9558
  remote.response(req.mid, STATUS.OK, r);
@@ -9496,13 +9561,12 @@ async function unixtime(remote, req) {
9496
9561
  var api_reply = /*#__PURE__*/Object.freeze({
9497
9562
  __proto__: null,
9498
9563
  checkPermission: checkPermission$1,
9564
+ commands: commands$1,
9499
9565
  date: date,
9500
9566
  echo: echo,
9501
9567
  unixtime: unixtime
9502
9568
  });
9503
9569
 
9504
- const MIN_LEVEL$1 = 255;
9505
-
9506
9570
  const commands = [
9507
9571
  'cid', 'remotes', 'clients',
9508
9572
  'channels', 'subscribers',
@@ -9512,13 +9576,9 @@ const commands = [
9512
9576
  'adddevice', 'getdevice', 'deldevice'
9513
9577
  ];
9514
9578
 
9515
-
9579
+ const MIN_LEVEL$1 = 255;
9516
9580
  function checkPermission(remote) {
9517
- if (remote.level >= MIN_LEVEL$1) {
9518
- return true
9519
- } else {
9520
- return false
9521
- }
9581
+ return (remote.level >= MIN_LEVEL$1) ? true : false;
9522
9582
  }
9523
9583
 
9524
9584
  async function request(remote, req) {
@@ -9595,15 +9655,23 @@ var api_sudo = /*#__PURE__*/Object.freeze({
9595
9655
  request: request
9596
9656
  });
9597
9657
 
9658
+ /**
9659
+ * RedisAPI <IOSignal API>
9660
+ *
9661
+ * iosignal 클라이언트의 redis 질의 요청을 받으면,
9662
+ * redisClient 로 연결된 redis-server 에게 질의 후 결과를 되돌려 준다.
9663
+ *
9664
+ * client ex:
9665
+ * await io.req('redis','hget','user:id' )
9666
+ *
9667
+ */
9668
+
9598
9669
  const MIN_LEVEL = 200;
9599
9670
  const COMMANDS = [
9600
- 'GET', 'SET',
9601
- 'HGETALL', 'HGET',
9602
- 'HSET', 'SADD',
9603
- 'SISMEMBER', 'SMEMBERS',
9604
- 'EXISTS', 'SREM',
9605
- 'DEL', 'KEYS',
9606
- 'SAVE'
9671
+ 'GET', 'SET', 'HGETALL', 'HGET', 'HSET', 'SADD', 'SISMEMBER',
9672
+ 'SMEMBERS', 'EXISTS', 'SREM', 'DEL', 'KEYS', 'SAVE',
9673
+ 'get', 'set', 'hGetAll', 'hGet', 'hSet', 'sAdd', 'sIsMember',
9674
+ 'sMembers', 'exists', 'sRem', 'del', 'keys', 'save'
9607
9675
  ];
9608
9676
 
9609
9677
  class RedisAPI {
@@ -9616,42 +9684,23 @@ class RedisAPI {
9616
9684
  this.commands = COMMANDS;
9617
9685
  }
9618
9686
 
9619
-
9620
9687
  checkPermission(remote, req) {
9621
- console.log('checkPermission', remote.level, 'vs', this.minLevel);
9622
- if (remote.level >= this.minLevel) {
9623
- return true
9624
- } else {
9625
- return false
9626
- }
9688
+ return (remote.level >= this.minLevel) ? true : false;
9627
9689
  }
9628
9690
 
9629
-
9630
9691
  async request(remote, req) {
9631
-
9632
9692
  let result;
9633
- let status = STATUS.OK;
9634
9693
  try {
9635
9694
  let cmd = req.topic;
9636
- cmd = cmd.toUpperCase();
9637
- if (COMMANDS.includes(cmd)) {
9638
- console.log('RedisAPI call:', cmd, req.args);
9639
-
9640
- if (req.args.length > 0) {
9641
- result = await this.redisClient[cmd](...req.args);
9642
- } else {
9643
- result = await this.redisClient[cmd]();
9644
- }
9645
-
9646
-
9695
+ if (req.args?.length > 0) {
9696
+ result = await this.redisClient[cmd](...req.args);
9647
9697
  } else {
9648
- status = STATUS.ERROR;
9698
+ result = await this.redisClient[cmd]();
9649
9699
  }
9650
- remote.response(req.mid, status, result);
9700
+ remote.response(req.mid, STATUS.OK, result);
9651
9701
  } catch (e) {
9652
9702
  remote.response(req.mid, STATUS.ERROR, e.message);
9653
9703
  }
9654
-
9655
9704
  }
9656
9705
 
9657
9706
  }