iosignal 3.3.0 → 4.5.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 (82) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/README.md +38 -559
  3. package/dist/io.d.ts +16 -9
  4. package/dist/io.js +5 -5
  5. package/dist/io.js.map +1 -1
  6. package/dist/io.min.js +5 -5
  7. package/dist/io.min.js.map +1 -1
  8. package/dist/iosignal.js +339 -268
  9. package/dist/types/client/IOCore.d.ts +17 -10
  10. package/dist/types/common/constants.d.ts +27 -37
  11. package/index.js +4 -3
  12. package/package.json +3 -4
  13. package/src/auth/BohoAuth.js +48 -11
  14. package/src/auth/{Auth_File.js → key_providers/FileKeyProvider.js} +8 -20
  15. package/src/auth/{Auth_Redis.js → key_providers/RedisKeyProvider.js} +4 -7
  16. package/src/auth/key_providers/StringKeyProvider.js +54 -0
  17. package/src/client/IOCongSocket.js +5 -3
  18. package/src/client/IOCore.js +118 -89
  19. package/src/client/IOWS.js +5 -3
  20. package/src/client/browser/IOWebSocket.js +5 -3
  21. package/src/common/constants.js +31 -44
  22. package/src/common/util.js +3 -0
  23. package/src/server/Manager.js +13 -12
  24. package/src/server/Remote.js +4 -1
  25. package/src/server/RemoteCore.js +23 -17
  26. package/src/server/Server.js +7 -7
  27. package/README.ko.md +0 -566
  28. package/auth_file.js +0 -23
  29. package/auth_file.json +0 -13
  30. package/docs/iosignal_architecture.png +0 -0
  31. package/examples/react-chat-js/dist/assets/index-Cy4qaVcJ.js +0 -56
  32. package/examples/react-chat-js/dist/assets/index-NETrjYhz.css +0 -1
  33. package/examples/react-chat-js/dist/assets/index-e2KOTYW8.js +0 -65
  34. package/examples/react-chat-js/dist/index.html +0 -14
  35. package/examples/react-chat-js/index.html +0 -13
  36. package/examples/react-chat-js/package-lock.json +0 -1723
  37. package/examples/react-chat-js/package.json +0 -20
  38. package/examples/react-chat-js/src/App.css +0 -61
  39. package/examples/react-chat-js/src/App.jsx +0 -125
  40. package/examples/react-chat-js/src/index.css +0 -13
  41. package/examples/react-chat-js/src/main.jsx +0 -13
  42. package/examples/react-chat-js/src/shared_io.js +0 -12
  43. package/examples/react-chat-js/vite.config.js +0 -7
  44. package/examples/server/index.js +0 -65
  45. package/examples/server/package-lock.json +0 -878
  46. package/examples/server/package.json +0 -13
  47. package/examples/server/public/index.html +0 -26
  48. package/examples/svelte-chat-js/.devtools +0 -3
  49. package/examples/svelte-chat-js/README.md +0 -38
  50. package/examples/svelte-chat-js/package-lock.json +0 -1421
  51. package/examples/svelte-chat-js/package.json +0 -23
  52. package/examples/svelte-chat-js/src/app.css +0 -105
  53. package/examples/svelte-chat-js/src/app.d.ts +0 -13
  54. package/examples/svelte-chat-js/src/app.html +0 -13
  55. package/examples/svelte-chat-js/src/lib/images/github.svg +0 -1
  56. package/examples/svelte-chat-js/src/lib/images/svelte-logo.svg +0 -1
  57. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.png +0 -0
  58. package/examples/svelte-chat-js/src/lib/images/svelte-welcome.webp +0 -0
  59. package/examples/svelte-chat-js/src/lib/shared_io.js +0 -12
  60. package/examples/svelte-chat-js/src/routes/+layout.svelte +0 -5
  61. package/examples/svelte-chat-js/src/routes/+page.js +0 -3
  62. package/examples/svelte-chat-js/src/routes/+page.svelte +0 -167
  63. package/examples/svelte-chat-js/static/favicon.svg +0 -1
  64. package/examples/svelte-chat-js/static/global.css +0 -19
  65. package/examples/svelte-chat-js/static/robots.txt +0 -3
  66. package/examples/svelte-chat-js/svelte.config.js +0 -23
  67. package/examples/svelte-chat-js/vite.config.js +0 -6
  68. package/src/auth/Auth_Env.js +0 -76
  69. package/test-browser/favicon.ico +0 -0
  70. package/test-browser/index.html +0 -95
  71. package/test-browser/server.js +0 -12
  72. package/test-nodejs/client-playToggle.js +0 -19
  73. package/test-nodejs/client.js +0 -17
  74. package/test-nodejs/client_api_reply.js +0 -15
  75. package/test-nodejs/server-Auth_Env.js +0 -19
  76. package/test-nodejs/server-Auth_File.js +0 -12
  77. package/test-nodejs/server-api_reply.js +0 -6
  78. package/test-nodejs/server-api_sudo.js +0 -7
  79. package/test-nodejs/server.js +0 -20
  80. package/test-nodejs/signalPack.js +0 -34
  81. package/test-nodejs/signaling.js +0 -61
  82. package/test-nodejs/simple-server.js +0 -13
@@ -1,6 +1,6 @@
1
1
  import MBP from 'meta-buffer-pack'
2
2
  import EventEmitter from "eventemitter3";
3
- import { IOMsg, PAYLOAD_TYPE, SIZE_LIMIT, ENC_MODE, STATES } from '../common/constants.js'
3
+ import { IOMsg, PAYLOAD_TYPE, SIZE_LIMIT, ENC_MODE, STATE } from '../common/constants.js'
4
4
  import { quotaTable } from '../common/quotaTable.js'
5
5
  import { getSignalPack } from '../common/payload.js';
6
6
  import Boho from "boho";
@@ -11,7 +11,7 @@ import Boho from "boho";
11
11
  * @typedef {import('../common/constants.js').PAYLOAD_TYPE} PAYLOAD_TYPE
12
12
  * @typedef {import('../common/constants.js').SIZE_LIMIT} SIZE_LIMIT
13
13
  * @typedef {import('../common/constants.js').ENC_MODE} ENC_MODE
14
- * @typedef {import('../common/constants.js').STATES} STATES
14
+ * @typedef {import('../common/constants.js').STATE} STATE
15
15
  * @typedef {import('../common/quotaTable.js').quotaTable} quotaTable
16
16
 
17
17
  * @typedef {import('boho').Boho} Boho
@@ -65,7 +65,7 @@ export class IOCore extends EventEmitter {
65
65
  * Current connection state (number).
66
66
  * @type {number}
67
67
  */
68
- this.state = STATES.CLOSED; // Number type
68
+ this.state = STATE.CLOSED; // Number type
69
69
  /**
70
70
  * Current connection state (string).
71
71
  * @type {string}
@@ -207,7 +207,7 @@ export class IOCore extends EventEmitter {
207
207
  close() {
208
208
  if (this._closed) return;
209
209
  this._closed = true;
210
- // console.log('####### IOCOre.js close() called')
210
+ // console.log('####### IOCOre.js close() called')
211
211
  // If auto-reconnect is disabled, we must stop the keep-alive timer.
212
212
  if (this.autoReconnect === false) {
213
213
  clearInterval(this.connectionCheckerIntervalID);
@@ -222,7 +222,7 @@ export class IOCore extends EventEmitter {
222
222
  // To avoid the error, we wait for the connection to open, then immediately close it.
223
223
  // We also clear other handlers to prevent any other logic from running.
224
224
  const socket = this.socket;
225
- socket.onopen = () => { if(socket) socket.close(); };
225
+ socket.onopen = () => { if (socket) socket.close(); };
226
226
  socket.onmessage = null;
227
227
  socket.onerror = null;
228
228
  socket.onclose = null;
@@ -230,7 +230,7 @@ export class IOCore extends EventEmitter {
230
230
  try {
231
231
  // For other sockets (like TCP) or other WebSocket states, close directly.
232
232
  this.socket.close?.();
233
- } catch {}
233
+ } catch { }
234
234
  }
235
235
  this.socket = null;
236
236
  }
@@ -238,14 +238,15 @@ export class IOCore extends EventEmitter {
238
238
  this.emit('closed');
239
239
  this.stateChange('closed');
240
240
  }
241
-
241
+
242
242
  /**
243
243
  * Disables auto-reconnect and closes the current connection.
244
244
  * The instance can be re-opened manually later. For complete cleanup, use destroy().
245
- */
246
- stop() {
247
- this.autoReconnect = false;
248
- this.close();
245
+ */
246
+ stop() {
247
+ this.autoReconnect = false;
248
+ this.close();
249
+ this.stateChange('stop','stop');
249
250
  }
250
251
 
251
252
  /**
@@ -261,7 +262,7 @@ export class IOCore extends EventEmitter {
261
262
 
262
263
  // Help GC
263
264
  this.boho = null;
264
- }
265
+ }
265
266
 
266
267
  /**
267
268
  * The core keep-alive logic. It checks if auto-reconnect is enabled.
@@ -278,8 +279,8 @@ export class IOCore extends EventEmitter {
278
279
  * @param {string} url2 - The new URL to redirect to.
279
280
  */
280
281
  redirect(url2) {
282
+ this.stateChange('redirecting','redirecting')
281
283
  this.close()
282
- this.stateChange('redirecting')
283
284
  this.createConnection(url2)
284
285
  }
285
286
 
@@ -336,29 +337,27 @@ export class IOCore extends EventEmitter {
336
337
 
337
338
  /**
338
339
  * Manually logs in with provided ID and key.
339
- * @param {string} id - The user ID.
340
+ * @param {string} id - The user ID. or 'id.key'
340
341
  * @param {string} key - The user key.
341
- * @returns {boolean}
342
+ * @returns {this}
342
343
  */
343
344
  login(id, key) {
344
- if (!this.auth(id, key)) return false;
345
-
345
+ this.auth(id, key)
346
346
  this.useAuth = true
347
347
  let auth_pack = this.boho.auth_req()
348
348
  this.send(auth_pack)
349
- return true
349
+ return this
350
350
  }
351
351
 
352
352
  /**
353
353
  * Sets up authentication for auto-login.
354
- * @param {string} id - The user ID.
354
+ * @param {string} id - The user ID. or 'id.Key'
355
355
  * @param {string} key - The user key.
356
- * @returns {boolean}
356
+ * @returns {this}
357
357
  */
358
358
  auth(id, key) {
359
359
  if (!id && !key) {
360
360
  this.emit('error', new Error('auth failed. no id and key.'))
361
- return false
362
361
  }
363
362
 
364
363
  if (!key && id.includes('.')) {
@@ -368,10 +367,9 @@ export class IOCore extends EventEmitter {
368
367
  this.boho.set_key(key)
369
368
  } else {
370
369
  this.emit('error', new Error('auth failed. no id or key.'))
371
- return false
372
370
  }
373
371
  this.useAuth = true
374
- return true
372
+ return this
375
373
  }
376
374
 
377
375
  /**
@@ -433,13 +431,13 @@ export class IOCore extends EventEmitter {
433
431
  case IOMsg.ECHO:
434
432
  try {
435
433
  let str = decoder.decode(buffer.subarray(1))
436
-
434
+
437
435
  this.emit('echo', str)
438
436
  } catch (error) {
439
437
  this.emit('error', new Error('ECHO data error'))
440
438
  }
441
439
  break;
442
-
440
+
443
441
  case IOMsg.IAM_RES:
444
442
  try {
445
443
  let str = decoder.decode(buffer.subarray(1))
@@ -448,8 +446,7 @@ export class IOCore extends EventEmitter {
448
446
  if (jsonInfo.nick) { this.nick = jsonInfo.nick; }
449
447
  if (jsonInfo.did) { this.did = jsonInfo.did; }
450
448
  if (jsonInfo.uid) { this.uid = jsonInfo.uid; }
451
- // TIP. cid from [CID_RES], level from [QUOTA_LEVEL]
452
- this.emit('iam_res', str )
449
+ this.emit('iam_res', str)
453
450
  } catch (error) {
454
451
  this.emit('error', new Error('IAM_RES data error'))
455
452
  }
@@ -461,21 +458,21 @@ export class IOCore extends EventEmitter {
461
458
 
462
459
  // **IMPORTANT** change state before subscribe.
463
460
  this.stateChange('ready', 'cid_ready')
464
- this.subscribe_memory_channels()
461
+ this.subscribe_memory_channels() // tags registered by listen() or link().
465
462
  break;
466
463
 
467
464
  case IOMsg.QUOTA_LEVEL:
468
465
  let quotaLevel = buffer[1]
469
466
  this.level = quotaLevel;
470
467
  this.quota = quotaTable[quotaLevel];
471
- console.log('[QUOTA_LEVEL]', JSON.stringify(this.quota))
468
+ // console.log('[QUOTA_LEVEL]', JSON.stringify(this.quota))
472
469
  break;
473
470
 
474
- case IOMsg.SERVER_CLEAR_AUTH:
471
+ case IOMsg.AUTH_CLEAR:
475
472
  this.useAuth = false;
476
473
  this.boho.clearAuth();
474
+ this.stateChange('auth_clear', 'server request auth_clear.')
477
475
  this.stop();
478
- console.log('[SERVER_CLEAR_AUTH] io stop.')
479
476
  break;
480
477
 
481
478
  case IOMsg.SERVER_REDIRECT:
@@ -552,8 +549,11 @@ export class IOCore extends EventEmitter {
552
549
  switch (payloadType) {
553
550
 
554
551
  case PAYLOAD_TYPE.EMPTY:
555
- if (tag.indexOf('@') === 0) this.emit('@', null, tag)
556
- else this.emit(tag, null, tag)
552
+ if (tag.indexOf('@') === 0) this.emit('@', tag, null)
553
+ else {
554
+ this.emit(tag, tag, null)
555
+ this.emit('message', tag, null)
556
+ }
557
557
  break;
558
558
 
559
559
  case PAYLOAD_TYPE.TEXT:
@@ -564,33 +564,48 @@ export class IOCore extends EventEmitter {
564
564
  payloadStringWithoutNull = payloadBuffer.subarray(0, payloadBuffer.byteLength - 1)
565
565
  }
566
566
  let oneString = decoder.decode(payloadStringWithoutNull)
567
- if (tag.indexOf('@') === 0) this.emit('@', oneString, tag)
568
- if (tag !== '@') this.emit(tag, oneString, tag)
567
+ if (tag.indexOf('@') === 0) this.emit('@', tag, oneString)
568
+ if (tag !== '@') {
569
+ this.emit(tag, tag, oneString)
570
+ this.emit('message', tag, oneString)
571
+ }
569
572
  break;
570
573
 
571
574
  case PAYLOAD_TYPE.BINARY:
572
- if (tag.indexOf('@') === 0) this.emit('@', payloadBuffer, tag)
573
- if (tag !== '@') this.emit(tag, payloadBuffer, tag)
575
+ if (tag.indexOf('@') === 0) this.emit('@', tag, payloadBuffer)
576
+ if (tag !== '@') {
577
+ this.emit(tag, tag, payloadBuffer)
578
+ this.emit('message', tag, payloadBuffer)
579
+ }
574
580
  break;
575
581
 
576
582
  case PAYLOAD_TYPE.OBJECT:
577
583
  let oneObjectBuffer = decoder.decode(payloadBuffer)
578
584
  let oneJSONObject = JSON.parse(oneObjectBuffer)
579
- if (tag.indexOf('@') === 0) this.emit('@', oneJSONObject, tag)
580
- if (tag !== '@') this.emit(tag, oneJSONObject, tag)
585
+ if (tag.indexOf('@') === 0) this.emit('@', tag, oneJSONObject)
586
+ if (tag !== '@') {
587
+ this.emit(tag, tag, oneJSONObject)
588
+ this.emit('message', tag, oneJSONObject)
589
+ }
581
590
  break;
582
591
 
583
592
  case PAYLOAD_TYPE.MJSON:
584
593
  let mjsonBuffer = decoder.decode(payloadBuffer)
585
594
  let mjson = JSON.parse(mjsonBuffer)
586
- if (tag.indexOf('@') === 0) this.emit('@', ...mjson, tag)
587
- if (tag !== '@') this.emit(tag, ...mjson, tag)
595
+ if (tag.indexOf('@') === 0) this.emit('@', tag, ...mjson)
596
+ if (tag !== '@') {
597
+ this.emit(tag, tag, ...mjson)
598
+ this.emit('message', tag, ...mjson)
599
+ }
588
600
  break;
589
601
 
590
602
  case PAYLOAD_TYPE.MBA:
591
603
  let mbaObject = MBP.unpack(payloadBuffer)
592
- if (tag.indexOf('@') === 0) this.emit('@', ...mbaObject.args, tag)
593
- if (tag !== '@') this.emit(tag, ...mbaObject.args, tag)
604
+ if (tag.indexOf('@') === 0) this.emit('@', tag, ...mbaObject.args)
605
+ if (tag !== '@') {
606
+ this.emit(tag, tag, ...mbaObject.args)
607
+ this.emit('message', tag, ...mbaObject.args)
608
+ }
594
609
  break;
595
610
 
596
611
  default:
@@ -598,7 +613,8 @@ export class IOCore extends EventEmitter {
598
613
  }
599
614
 
600
615
  } catch (err) {
601
- this.emit('error', new Error('signal parse err'))
616
+ // this.emit('error', new Error('IOCore IOMsg.SIGNAL parser err', err))
617
+ console.log('IOCore IOMsg.SIGNAL parser err', err)
602
618
  }
603
619
  break;
604
620
 
@@ -607,24 +623,25 @@ export class IOCore extends EventEmitter {
607
623
  break;
608
624
 
609
625
  case Boho.BohoMsg.AUTH_NONCE:
626
+ this.stateChange('auth_nonce','server sent auth_nonce.')
610
627
  let auth_hmac = this.boho.auth_hmac(buffer)
611
628
  if (auth_hmac) {
612
629
  this.send(auth_hmac)
613
630
  } else {
614
- this.stateChange('auth_fail', 'Invalid local auth_hmac.')
631
+ this.stateChange('auth_fail', 'boho.auth_hmac() invalid auth_nonce.')
615
632
  }
616
633
  break;
617
634
 
618
635
  case Boho.BohoMsg.AUTH_FAIL:
619
- this.stateChange('auth_fail', 'server reject auth.')
636
+ this.stateChange('auth_fail', 'auth_fail from server.')
620
637
  break;
621
638
 
622
639
  case Boho.BohoMsg.AUTH_ACK:
623
640
  if (this.boho.check_auth_ack_hmac(buffer)) {
624
- this.stateChange('auth_ready', 'server sent auth_ack')
641
+ this.stateChange('auth_ack', 'server sent auth_ack')
625
642
  this.send(Buffer.from([IOMsg.CID_REQ]))
626
643
  } else {
627
- this.stateChange('auth_fail', 'invalid server_hmac')
644
+ this.stateChange('auth_fail', 'check_auth_ack_hmac() invalid server_hmac')
628
645
  }
629
646
  break;
630
647
 
@@ -811,14 +828,15 @@ export class IOCore extends EventEmitter {
811
828
 
812
829
 
813
830
  /**
814
- * Publishes a signal.
831
+ * alias of signal()
832
+ * Sends a signal with a tag and arguments.
833
+ * @param {string} tag - The signal tag.
815
834
  * @param {...any} args - Arguments for the signal.
816
835
  */
817
- publish(...args) {
818
- this.signal(...args)
836
+ publish(tag, ...args) {
837
+ this.signal(tag, ...args)
819
838
  }
820
839
 
821
-
822
840
  /**
823
841
  * Sends a signal with a tag and arguments.
824
842
  * @param {string} tag - The signal tag.
@@ -827,7 +845,6 @@ export class IOCore extends EventEmitter {
827
845
  */
828
846
  signal(tag, ...args) {
829
847
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
830
-
831
848
  let signalPack = getSignalPack(tag, ...args)
832
849
  this.send_enc_mode(signalPack)
833
850
  }
@@ -871,7 +888,6 @@ export class IOCore extends EventEmitter {
871
888
  }
872
889
 
873
890
 
874
-
875
891
  /**
876
892
  * Sets a value in the store.
877
893
  * @param {string} storeName - The name of the store.
@@ -939,21 +955,24 @@ export class IOCore extends EventEmitter {
939
955
  */
940
956
  subscribe(tag) {
941
957
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
942
- if (this.state !== STATES.READY) return
943
-
944
- let tagList = tag.split(',')
945
- tagList.forEach(tag => {
946
- this.channels.add(tag)
947
- })
948
-
949
- let tagEncoded = encoder.encode(tag)
950
- if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN1) throw TypeError('please use tag string bytelength below:' + SIZE_LIMIT.TAG_LEN1)
951
-
952
- this.send_enc_mode(
953
- Buffer.concat([
954
- MBP.NB('8', IOMsg.SUBSCRIBE),
955
- MBP.NB('8', tagEncoded.byteLength),
956
- tagEncoded]))
958
+ if (tag.length > SIZE_LIMIT.TAG_LEN1) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN1)
959
+ if (this.state !== STATE.READY) return
960
+
961
+ // subscribe 사용시, 사용 'ready' 이벤트시 메뉴얼 등록되므로 여기에 등록하면 2중 호출된다.
962
+ // 즉, channels 등록은 listen 같은 자동화 구독시만 사용.
963
+ // let tagList = tag.split(',')
964
+ // tagList.forEach(tag => {
965
+ // this.channels.add(tag)
966
+ // })
967
+
968
+ try {
969
+ let tagEncoded = encoder.encode(tag)
970
+ this.send_enc_mode(
971
+ Buffer.concat([
972
+ MBP.NB('8', IOMsg.SUBSCRIBE),
973
+ MBP.NB('8', tagEncoded.byteLength),
974
+ tagEncoded]))
975
+ } catch (error) { }
957
976
  }
958
977
 
959
978
  /**
@@ -964,20 +983,22 @@ export class IOCore extends EventEmitter {
964
983
  */
965
984
  subscribe_promise(tag) {
966
985
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
967
- if (this.state !== STATES.READY) {
986
+ if (tag.length > SIZE_LIMIT.TAG_LEN2) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN2)
987
+
988
+ if (this.state !== STATE.READY) {
968
989
  return Promise.reject('subscribe_promise:: connection is not ready')
969
990
  }
970
991
 
971
- let tagEncoded = encoder.encode(tag)
972
- if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN2) throw TypeError('please use tag string bytelength: ' + SIZE_LIMIT.TAG_LEN2)
973
-
974
- this.send_enc_mode(
975
- Buffer.concat([
976
- MBP.NB('8', IOMsg.SUBSCRIBE_REQ),
977
- MBP.NB('16', ++this.mid),
978
- MBP.NB('16', tagEncoded.byteLength),
979
- tagEncoded]))
980
- return this.setMsgPromise(this.mid)
992
+ try {
993
+ let tagEncoded = encoder.encode(tag)
994
+ this.send_enc_mode(
995
+ Buffer.concat([
996
+ MBP.NB('8', IOMsg.SUBSCRIBE_REQ),
997
+ MBP.NB('16', ++this.mid),
998
+ MBP.NB('16', tagEncoded.byteLength),
999
+ tagEncoded]))
1000
+ return this.setMsgPromise(this.mid)
1001
+ } catch (error) { }
981
1002
  }
982
1003
 
983
1004
  /**
@@ -1039,7 +1060,7 @@ export class IOCore extends EventEmitter {
1039
1060
  }
1040
1061
  this.on(tag, handler)
1041
1062
  // do not subscribe now.
1042
- // will subscribe when receive CID_RES signal from server.
1063
+ // will subscribe when io state is 'ready'. (receive CID_RES from server)
1043
1064
 
1044
1065
  }
1045
1066
 
@@ -1150,10 +1171,10 @@ export class IOCore extends EventEmitter {
1150
1171
  */
1151
1172
  getStateName() {
1152
1173
  //state <number>
1153
- //value of constant STATES.NAME < number >
1154
- //type of constant STATES.NAME name < string uppercase >
1174
+ //value of constant STATE.NAME < number >
1175
+ //type of constant STATE.NAME name < string uppercase >
1155
1176
  //stateName,eventName <string lowercase>
1156
- return (STATES[this.state]).toLowerCase()
1177
+ return (STATE[this.state]).toLowerCase()
1157
1178
  }
1158
1179
 
1159
1180
  /**
@@ -1174,15 +1195,23 @@ export class IOCore extends EventEmitter {
1174
1195
  * Changes the connection state and emits events.
1175
1196
  * @param {string} state - The new state name (e.g., 'ready', 'closed').
1176
1197
  * @param {string} [emitEventAndMessage] - Optional message to emit with the state change event.
1198
+ *
1199
+ * 주의.
1200
+ * 1. 상태가 변경 될 때만 'change' 이벤트 호출된다.
1201
+ * 2. emitEventAndMessage 옵션 값이 지정되야 해당 이벤트 이름이 호출된다.
1202
+ * 보통 이벤트 이름과 동일하게 적거나 이벤트 상황 안내문을 넣는다.
1177
1203
  */
1178
1204
  stateChange(state, emitEventAndMessage) {
1179
- // STATES constant name : string upperCase
1180
- // eventName, .stateName : string lowerCase
1181
- // .state : number
1205
+ // STATE constant name <string> upperCase
1206
+ // eventName and .stateName <string> lowerCase
1207
+ // .state <number>
1182
1208
  // console.log('### stateChange reason:', emitEventAndMessage )
1183
1209
  let eventName = state.toLowerCase()
1184
- this.state = STATES[state.toUpperCase()] // state: number
1185
- if (emitEventAndMessage) this.emit(eventName, emitEventAndMessage)
1210
+ this.state = STATE[state.toUpperCase()] // state: number
1211
+
1212
+ if (emitEventAndMessage) {
1213
+ this.emit(eventName, emitEventAndMessage)
1214
+ }
1186
1215
 
1187
1216
  if (this.stateName !== eventName) {
1188
1217
  this.stateName = eventName
@@ -1,5 +1,5 @@
1
1
  import { IOCore } from "./IOCore.js";
2
- import { STATES } from "../common/constants.js";
2
+ import { STATE } from "../common/constants.js";
3
3
  import { WebSocket } from "ws";
4
4
 
5
5
  // Node.js 'ws' websocket
@@ -28,15 +28,17 @@ export class IOWS extends IOCore {
28
28
  keepAlive() {
29
29
  if (!this.autoReconnect) return;
30
30
  // Reconnect only if the socket is closed and the state reflects that.
31
- if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) && this.state === STATES.CLOSED) {
31
+ if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) ) {
32
32
  this.open();
33
+ }else{
34
+ this.ping();
33
35
  }
34
36
  }
35
37
 
36
38
  createConnection(url) {
37
39
  // node WebSocket
38
40
  this.socket = new WebSocket(url);
39
- this.stateChange('opening')
41
+ this.stateChange('connecting','connecting')
40
42
 
41
43
  this.socket.onopen = () => {
42
44
  this.socket.on('message', this.onWebSocketMessage.bind(this));
@@ -104,13 +104,15 @@ export default class IO extends IOCore {
104
104
 
105
105
 
106
106
  /**
107
- * Keeps the connection alive by re-opening if closed.
107
+ * Keeps the connection alive by re-connecting if closed.
108
108
  */
109
109
  keepAlive() {
110
110
  if (!this.autoReconnect) return;
111
111
  // Reconnect only if the socket is closed and the state reflects that.
112
- if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) && this.state === IO.constants.STATES.CLOSED) {
112
+ if ((!this.socket || this.socket.readyState === WebSocket.CLOSED) ) {
113
113
  this.open();
114
+ }else{
115
+ this.ping();
114
116
  }
115
117
  }
116
118
 
@@ -126,7 +128,7 @@ export default class IO extends IOCore {
126
128
  this.socket = new WebSocket(url);
127
129
  this.socket.binaryType = IO.binaryType
128
130
 
129
- this.stateChange('opening')
131
+ this.stateChange('connecting','connecting')
130
132
 
131
133
  this.socket.onopen = () => {
132
134
 
@@ -1,52 +1,40 @@
1
1
 
2
2
  /**
3
- * @typedef {object} STATES
4
- * @property {number} OPENING
3
+ * @typedef {object} STATE
4
+ * @property {number} CONNECTING
5
5
  * @property {number} OPEN
6
- * @property {number} CLOSING
7
- * @property {number} CLOSED
8
6
  * @property {number} SERVER_READY
9
- * @property {number} AUTH_FAIL
10
- * @property {number} AUTH_READY
7
+ * @property {number} AUTH_ACK
8
+ * @property {number} CLOSING
11
9
  * @property {number} READY
10
+ * @property {number} AUTH_FAIL
11
+ * @property {number} AUTH_CLEAR
12
+ * @property {number} CLOSING
13
+ * @property {number} CLOSED
14
+ * @property {number} STOP
12
15
  * @property {number} REDIRECTING
13
16
  */
14
- // Client STATES: name and number
15
- export const STATES = {
16
- OPENING: 0,
17
- OPEN: 1,
18
- CLOSING: 2,
19
- CLOSED: 3,
20
- SERVER_READY: 4,
21
- AUTH_FAIL: 5,
22
- AUTH_READY: 6,
23
- READY: 7,
24
- REDIRECTING: 8
17
+ // Client STATE: name and number
18
+ export const STATE = {
19
+ CONNECTING: 0,
20
+ OPEN: 1,
21
+ SERVER_READY: 10,
22
+ AUTH_REQ: 11,
23
+ AUTH_NONCE: 12,
24
+ AUTH_HMAC: 13,
25
+ AUTH_ACK: 14,
26
+ AUTH_FAIL: 15,
27
+ AUTH_CLEAR: 16,
28
+ CID_REQ: 17,
29
+ CID_RES: 18,
30
+ READY: 19,
31
+ CLOSING: 2,
32
+ CLOSED: 3,
33
+ STOP: 4,
34
+ REDIRECTING: 5
25
35
  }
26
- for (let c in STATES) { STATES[STATES[c]] = c }
36
+ for (let c in STATE) { STATE[STATE[c]] = c }
27
37
 
28
- /**
29
- * @typedef {object} CLIENT_STATE
30
- * @property {number} INIT
31
- * @property {number} SENT_SERVER_READY
32
- * @property {number} RECV_AUTH_REQ
33
- * @property {number} SENT_SERVER_NONCE
34
- * @property {number} RECV_AUTH_HMAC
35
- * @property {number} AUTH_FAIL
36
- * @property {number} AUTH_READY
37
- * @property {number} CID_READY
38
- */
39
- export const CLIENT_STATE = {
40
- INIT: 0,
41
- SENT_SERVER_READY: 1,
42
- RECV_AUTH_REQ: 2,
43
- SENT_SERVER_NONCE: 3,
44
- RECV_AUTH_HMAC: 4,
45
- AUTH_FAIL: 5,
46
- AUTH_READY: 6,
47
- CID_READY: 7
48
- }
49
- for (let c in CLIENT_STATE) { CLIENT_STATE[CLIENT_STATE[c]] = c }
50
38
 
51
39
  /**
52
40
  * @typedef {object} ENC_MODE
@@ -75,7 +63,7 @@ for (let c in ENC_MODE) { ENC_MODE[ENC_MODE[c]] = c }
75
63
  export const SIZE_LIMIT = {
76
64
  TAG_LEN1: 255,
77
65
  TAG_LEN2: 65535,
78
- CONNECTION_CHECKER_PERIOD: 3000,
66
+ CONNECTION_CHECKER_PERIOD: 30000,
79
67
  PROMISE_TIMEOUT: 5000,
80
68
  DID: 8,
81
69
  CID: 12
@@ -107,7 +95,7 @@ for (let c in PAYLOAD_TYPE) { PAYLOAD_TYPE[PAYLOAD_TYPE[c]] = c }
107
95
  * @property {number} CID_REQ
108
96
  * @property {number} CID_RES
109
97
  * @property {number} QUOTA_LEVEL
110
- * @property {number} SERVER_CLEAR_AUTH
98
+ * @property {number} AUTH_CLEAR
111
99
  * @property {number} SERVER_REDIRECT
112
100
  * @property {number} LOOP
113
101
  * @property {number} ECHO
@@ -165,9 +153,8 @@ export let IOMsg = {
165
153
  CID_REQ: 0xC1,
166
154
  CID_RES: 0xC2,
167
155
  QUOTA_LEVEL: 0xC3,
168
- SERVER_CLEAR_AUTH: 0xC4,
156
+ AUTH_CLEAR: 0xC4,
169
157
  SERVER_REDIRECT: 0xC5,
170
-
171
158
  // ..
172
159
  LOOP: 0xCB,
173
160
  ECHO: 0xCC,
@@ -59,3 +59,6 @@ export function getLocalAddress() {
59
59
  // console.log('localAddress:', localAddress)
60
60
  return localAddress
61
61
  }
62
+
63
+
64
+ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));