iosignal 6.1.0 → 6.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +269 -0
- package/README.md +176 -57
- package/dist/browser/esm/io.d.ts +5 -1
- package/dist/browser/esm/io.js +3 -3
- package/dist/browser/esm/io.js.map +1 -1
- package/dist/browser/iife/io.js +3 -3
- package/dist/browser/iife/io.js.map +1 -1
- package/dist/node/iosignal.cjs +74 -35
- package/dist/node/iosignal.js +74 -35
- package/dist/types/client/IOCore.d.ts +5 -1
- package/package.json +1 -1
package/dist/node/iosignal.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var fs = require('fs');
|
|
|
16
16
|
var process$1 = require('process');
|
|
17
17
|
var path = require('path');
|
|
18
18
|
|
|
19
|
-
var version$1 = "6.1.
|
|
19
|
+
var version$1 = "6.1.2";
|
|
20
20
|
var pkg = {
|
|
21
21
|
version: version$1};
|
|
22
22
|
|
|
@@ -834,6 +834,7 @@ class IOCore extends EventEmitter {
|
|
|
834
834
|
* @type {string}
|
|
835
835
|
*/
|
|
836
836
|
this.stateName = this.getStateName(); // String type
|
|
837
|
+
this._stateRevision = 0;
|
|
837
838
|
|
|
838
839
|
/**
|
|
839
840
|
* Transmitted message counter.
|
|
@@ -970,14 +971,14 @@ class IOCore extends EventEmitter {
|
|
|
970
971
|
* If autoReconnect is false, it also clears the keep-alive timer.
|
|
971
972
|
*/
|
|
972
973
|
close() {
|
|
973
|
-
if (this._closed) return;
|
|
974
|
-
this._closed = true;
|
|
975
974
|
// console.log('####### IOCOre.js close() called')
|
|
976
975
|
// If auto-reconnect is disabled, we must stop the keep-alive timer.
|
|
977
976
|
if (this.autoReconnect === false) {
|
|
978
977
|
clearInterval(this.connectionCheckerIntervalID);
|
|
979
978
|
this.connectionCheckerIntervalID = null;
|
|
980
979
|
}
|
|
980
|
+
if (this._closed) return;
|
|
981
|
+
this._closed = true;
|
|
981
982
|
|
|
982
983
|
// socket clean
|
|
983
984
|
if (this.socket) {
|
|
@@ -1000,8 +1001,11 @@ class IOCore extends EventEmitter {
|
|
|
1000
1001
|
this.socket = null;
|
|
1001
1002
|
}
|
|
1002
1003
|
this.promiseMap.clear();
|
|
1003
|
-
this.
|
|
1004
|
-
this.
|
|
1004
|
+
this.cid = '';
|
|
1005
|
+
if (this.boho) this.boho.isAuthorized = false;
|
|
1006
|
+
if (this.state !== STATE.STOP && this.stateChange('closed')) {
|
|
1007
|
+
this.emit('closed');
|
|
1008
|
+
}
|
|
1005
1009
|
}
|
|
1006
1010
|
|
|
1007
1011
|
/**
|
|
@@ -1074,6 +1078,7 @@ class IOCore extends EventEmitter {
|
|
|
1074
1078
|
|
|
1075
1079
|
// The actual connection is created here.
|
|
1076
1080
|
this.createConnection(this.url);
|
|
1081
|
+
if (this._closed) return; // A connecting listener may have stopped the client.
|
|
1077
1082
|
|
|
1078
1083
|
// Ensure the keep-alive timer is running.
|
|
1079
1084
|
if (!this.connectionCheckerIntervalID) {
|
|
@@ -1098,9 +1103,7 @@ class IOCore extends EventEmitter {
|
|
|
1098
1103
|
* Handles the 'close' event of the WebSocket.
|
|
1099
1104
|
*/
|
|
1100
1105
|
onClose() {
|
|
1101
|
-
this.
|
|
1102
|
-
this.cid = "";
|
|
1103
|
-
this.stateChange('closed');
|
|
1106
|
+
this.close();
|
|
1104
1107
|
}
|
|
1105
1108
|
|
|
1106
1109
|
/**
|
|
@@ -1111,11 +1114,11 @@ class IOCore extends EventEmitter {
|
|
|
1111
1114
|
*/
|
|
1112
1115
|
login(id, key) {
|
|
1113
1116
|
if( this.serverTimeNonce ){
|
|
1114
|
-
console.log('iosignal.login serverTimeNonce', this.serverTimeNonce);
|
|
1115
1117
|
this.auth(id, key);
|
|
1116
1118
|
this.useAuth = true;
|
|
1117
1119
|
let auth_pack = this.boho.auth_req(this.serverTimeNonce );
|
|
1118
1120
|
this.send(auth_pack);
|
|
1121
|
+
this.stateChange('auth_req', 'auth_req');
|
|
1119
1122
|
}
|
|
1120
1123
|
return this
|
|
1121
1124
|
}
|
|
@@ -1261,14 +1264,13 @@ class IOCore extends EventEmitter {
|
|
|
1261
1264
|
break;
|
|
1262
1265
|
|
|
1263
1266
|
case it.BohoMsg.SERVER_TIME_NONCE: // SERVER_READY
|
|
1264
|
-
this.
|
|
1267
|
+
buffer.copy(this.serverTimeNonce);
|
|
1268
|
+
if (!this.stateChange('server_ready', 'server_ready')) break;
|
|
1265
1269
|
if (this.useAuth) {
|
|
1266
1270
|
this.send(this.boho.auth_req(buffer));
|
|
1267
1271
|
this.stateChange('auth_req','auth_req');
|
|
1268
1272
|
// CID_REQ will be called, after auth_res.
|
|
1269
1273
|
} else {
|
|
1270
|
-
// keep server_time_nonce for manual login()
|
|
1271
|
-
buffer.copy( this.serverTimeNonce);
|
|
1272
1274
|
// CID_REQ here, if not using auth.
|
|
1273
1275
|
this.send(Buffer$1.from([IOMsg.CID_REQ]));
|
|
1274
1276
|
}
|
|
@@ -1393,14 +1395,16 @@ class IOCore extends EventEmitter {
|
|
|
1393
1395
|
break;
|
|
1394
1396
|
|
|
1395
1397
|
case it.BohoMsg.AUTH_FAIL:
|
|
1398
|
+
this.boho.isAuthorized = false;
|
|
1396
1399
|
this.stateChange('auth_fail', 'auth_fail from server.');
|
|
1397
1400
|
break;
|
|
1398
1401
|
|
|
1399
1402
|
case it.BohoMsg.AUTH_RES:
|
|
1400
1403
|
if (this.boho.verify_auth_res(buffer)) {
|
|
1401
|
-
this.stateChange('auth_res', 'server sent auth_res');
|
|
1404
|
+
if (!this.stateChange('auth_res', 'server sent auth_res')) break;
|
|
1402
1405
|
this.send(Buffer$1.from([IOMsg.CID_REQ]));
|
|
1403
1406
|
} else {
|
|
1407
|
+
this.boho.isAuthorized = false;
|
|
1404
1408
|
this.stateChange('auth_fail', 'verify_auth_res() invalid server_hmac');
|
|
1405
1409
|
}
|
|
1406
1410
|
break;
|
|
@@ -1937,6 +1941,9 @@ class IOCore extends EventEmitter {
|
|
|
1937
1941
|
* 1. 상태가 변경 될 때만 'change' 이벤트 호출된다.
|
|
1938
1942
|
* 2. emitEventAndMessage 옵션 값이 지정되야 해당 이벤트 이름이 호출된다.
|
|
1939
1943
|
* 보통 이벤트 이름과 동일하게 적거나 이벤트 상황 안내문을 넣는다.
|
|
1944
|
+
* 3. 두 상태값 갱신 후 change, 개별 이벤트 순서로 호출한다.
|
|
1945
|
+
* 콜백에서 다른 상태로 전이하면 이전 상태의 개별 이벤트는 생략한다.
|
|
1946
|
+
* @returns {boolean} Whether this transition is still current after callbacks.
|
|
1940
1947
|
*/
|
|
1941
1948
|
stateChange(state, emitEventAndMessage) {
|
|
1942
1949
|
// STATE constant name <string> upperCase
|
|
@@ -1944,16 +1951,19 @@ class IOCore extends EventEmitter {
|
|
|
1944
1951
|
// .state <number>
|
|
1945
1952
|
// console.log('### stateChange reason:', emitEventAndMessage )
|
|
1946
1953
|
let eventName = state.toLowerCase();
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1954
|
+
const nextState = STATE[state.toUpperCase()];
|
|
1955
|
+
if (typeof nextState !== 'number') throw new TypeError('Unknown state: ' + state);
|
|
1956
|
+
const changed = this.state !== nextState;
|
|
1957
|
+
this.state = nextState;
|
|
1958
|
+
this.stateName = eventName;
|
|
1959
|
+
if (changed) this._stateRevision++;
|
|
1960
|
+
const revision = this._stateRevision;
|
|
1961
|
+
if (changed) {
|
|
1955
1962
|
this.emit('change', eventName);
|
|
1956
1963
|
}
|
|
1964
|
+
if (revision !== this._stateRevision) return false;
|
|
1965
|
+
if (emitEventAndMessage) this.emit(eventName, emitEventAndMessage);
|
|
1966
|
+
return revision === this._stateRevision;
|
|
1957
1967
|
}
|
|
1958
1968
|
|
|
1959
1969
|
}
|
|
@@ -2114,6 +2124,7 @@ class IOCongSocket extends IOCore {
|
|
|
2114
2124
|
this.congRx = null;
|
|
2115
2125
|
}
|
|
2116
2126
|
this.socket.removeAllListeners();
|
|
2127
|
+
this.socket.on('error', () => {});
|
|
2117
2128
|
if (!this.socket.destroyed) {
|
|
2118
2129
|
this.socket.destroy(); // destroy() is sufficient for forceful closing
|
|
2119
2130
|
}
|
|
@@ -2138,23 +2149,29 @@ class IOCongSocket extends IOCore {
|
|
|
2138
2149
|
if (urlObj.protocol != "cong:") {
|
|
2139
2150
|
urlObj = new URL('cong://' + url);
|
|
2140
2151
|
}
|
|
2141
|
-
this.socket = net.createConnection(urlObj.port, urlObj.hostname);
|
|
2142
|
-
this.
|
|
2152
|
+
const socket = this.socket = net.createConnection(urlObj.port, urlObj.hostname);
|
|
2153
|
+
this._closed = false;
|
|
2143
2154
|
|
|
2144
2155
|
this.socket.on('connect', () => {
|
|
2156
|
+
if (this.socket !== socket) return;
|
|
2145
2157
|
this.congRx = new CongRx();
|
|
2146
2158
|
this.socket.pipe(this.congRx);
|
|
2147
|
-
this.congRx.on(
|
|
2159
|
+
this.congRx.on('data', data => {
|
|
2160
|
+
if (this.socket === socket) this.onTCPSocketMessage(data);
|
|
2161
|
+
});
|
|
2148
2162
|
this.emit('open');
|
|
2149
2163
|
});
|
|
2150
2164
|
|
|
2151
2165
|
this.socket.on('error', e => {
|
|
2166
|
+
if (this.socket !== socket) return;
|
|
2152
2167
|
this.emit('error', e);
|
|
2153
2168
|
});
|
|
2154
2169
|
|
|
2155
2170
|
this.socket.on('close', () => {
|
|
2171
|
+
if (this.socket !== socket) return;
|
|
2156
2172
|
this.emit('close');
|
|
2157
2173
|
});
|
|
2174
|
+
this.stateChange('connecting','connecting');
|
|
2158
2175
|
|
|
2159
2176
|
}
|
|
2160
2177
|
|
|
@@ -7244,6 +7261,8 @@ class IOWS extends IOCore {
|
|
|
7244
7261
|
close() {
|
|
7245
7262
|
if (this.socket) {
|
|
7246
7263
|
this.socket.removeAllListeners();
|
|
7264
|
+
// Closing a connecting ws can emit an asynchronous error after detachment.
|
|
7265
|
+
this.socket.on('error', () => {});
|
|
7247
7266
|
if (this.socket.readyState !== WebSocket.CLOSED) {
|
|
7248
7267
|
this.socket.close();
|
|
7249
7268
|
}
|
|
@@ -7263,21 +7282,27 @@ class IOWS extends IOCore {
|
|
|
7263
7282
|
|
|
7264
7283
|
createConnection(url) {
|
|
7265
7284
|
// node WebSocket
|
|
7266
|
-
this.socket = new WebSocket(url);
|
|
7267
|
-
this.
|
|
7285
|
+
const socket = this.socket = new WebSocket(url);
|
|
7286
|
+
this._closed = false;
|
|
7268
7287
|
|
|
7269
7288
|
this.socket.onopen = () => {
|
|
7270
|
-
this.socket
|
|
7289
|
+
if (this.socket !== socket) return;
|
|
7290
|
+
socket.on('message', data => {
|
|
7291
|
+
if (this.socket === socket) this.onWebSocketMessage(data);
|
|
7292
|
+
});
|
|
7271
7293
|
this.emit('open');
|
|
7272
7294
|
};
|
|
7273
7295
|
|
|
7274
7296
|
this.socket.onerror = (e) => {
|
|
7297
|
+
if (this.socket !== socket) return;
|
|
7275
7298
|
this.emit('error', e);
|
|
7276
7299
|
};
|
|
7277
7300
|
|
|
7278
7301
|
this.socket.onclose = () => {
|
|
7302
|
+
if (this.socket !== socket) return;
|
|
7279
7303
|
this.emit('close');
|
|
7280
7304
|
};
|
|
7305
|
+
this.stateChange('connecting','connecting');
|
|
7281
7306
|
}
|
|
7282
7307
|
|
|
7283
7308
|
onWebSocketMessage(data) {
|
|
@@ -7396,7 +7421,9 @@ class RemoteCore {
|
|
|
7396
7421
|
static ssid = 1;
|
|
7397
7422
|
|
|
7398
7423
|
setState(state) {
|
|
7424
|
+
const previous = this.state;
|
|
7399
7425
|
this.state = state;
|
|
7426
|
+
if (previous !== state) this.manager.server?.emit('remote:state', this, previous);
|
|
7400
7427
|
if (serverOption.debug.showAuthInfo) {
|
|
7401
7428
|
this.stateLog.push( state + ":" + STATE[ state] );
|
|
7402
7429
|
if( state == STATE.AUTH_RES){
|
|
@@ -7465,6 +7492,8 @@ class RemoteCore {
|
|
|
7465
7492
|
// CongSocket or WebSocket
|
|
7466
7493
|
onSocketMessage(message, isBinary = true) {
|
|
7467
7494
|
|
|
7495
|
+
if (this._closing || this.state === STATE.CLOSED) return;
|
|
7496
|
+
|
|
7468
7497
|
this.receiveMonitor(); // rx-data, ping/pong and timeout check
|
|
7469
7498
|
if (!this.rxQuotaChecker(message)) return
|
|
7470
7499
|
|
|
@@ -7518,10 +7547,11 @@ class RemoteCore {
|
|
|
7518
7547
|
break;
|
|
7519
7548
|
|
|
7520
7549
|
case IOMsg.CID_REQ:
|
|
7521
|
-
if (
|
|
7550
|
+
if (![STATE.SERVER_READY, STATE.AUTH_RES, STATE.AUTH_FAIL, STATE.CID_RES].includes(this.state)) {
|
|
7522
7551
|
// Protocol violation: CID_REQ was sent before receiving the SERVER_READY signal.
|
|
7523
7552
|
console.log('CID_REQ before SERVER_READY');
|
|
7524
7553
|
this.close();
|
|
7554
|
+
return;
|
|
7525
7555
|
}
|
|
7526
7556
|
|
|
7527
7557
|
if (!this.cid) {
|
|
@@ -7641,9 +7671,12 @@ class RemoteCore {
|
|
|
7641
7671
|
// client's auth requst
|
|
7642
7672
|
case it.BohoMsg.AUTH_REQ:
|
|
7643
7673
|
if (!this.manager.authManager) return
|
|
7644
|
-
|
|
7674
|
+
// Do not start overlapping verification on the same connection.
|
|
7675
|
+
if (this.state === STATE.AUTH_REQ) return;
|
|
7676
|
+
if (![STATE.SERVER_READY, STATE.AUTH_RES, STATE.AUTH_FAIL, STATE.CID_RES].includes(this.state)) {
|
|
7645
7677
|
console.log('protocol error. must called auth_req after server_ready');
|
|
7646
7678
|
this.close();
|
|
7679
|
+
return;
|
|
7647
7680
|
}
|
|
7648
7681
|
this.setState(STATE.AUTH_REQ);
|
|
7649
7682
|
//async
|
|
@@ -7992,6 +8025,7 @@ class Remote extends RemoteCore {
|
|
|
7992
8025
|
}
|
|
7993
8026
|
|
|
7994
8027
|
close(terminateNow = false) {
|
|
8028
|
+
this._closing = true;
|
|
7995
8029
|
this.getTraffic();
|
|
7996
8030
|
if (this.socketType === 'websocket') {
|
|
7997
8031
|
if (terminateNow) this.socket.terminate();
|
|
@@ -8257,6 +8291,7 @@ class Manager {
|
|
|
8257
8291
|
if (socket.isAlive === false) {
|
|
8258
8292
|
console.log('## timeout. cid:', remo.cid);
|
|
8259
8293
|
remo.close();
|
|
8294
|
+
return;
|
|
8260
8295
|
}
|
|
8261
8296
|
|
|
8262
8297
|
socket.txCounter++;
|
|
@@ -8296,6 +8331,9 @@ class Manager {
|
|
|
8296
8331
|
|
|
8297
8332
|
removeRemote(remote) {
|
|
8298
8333
|
|
|
8334
|
+
remote._closing = true;
|
|
8335
|
+
remote.setState(STATE.CLOSED);
|
|
8336
|
+
|
|
8299
8337
|
let remoteInfo = `- IP:${remote.ip} #${remote.ssid} cid:${remote.cid} ${remote?.socket.socketType === 'websocket' ? "WS" : "CS"} `;
|
|
8300
8338
|
if (this.connectionLogger) this.connectionLogger.log(remoteInfo);
|
|
8301
8339
|
this.deligateSignal(remote, '@state', 'close');
|
|
@@ -8905,6 +8943,7 @@ class BohoAuth {
|
|
|
8905
8943
|
}
|
|
8906
8944
|
|
|
8907
8945
|
send_auth_fail(peer, reason) {
|
|
8946
|
+
if (peer._closing || peer.state === STATE.CLOSED) return;
|
|
8908
8947
|
peer.boho.isAuthorized = false;
|
|
8909
8948
|
if (this.authLogger) {
|
|
8910
8949
|
let peerInfo = `FAIL #${peer.ssid} reason:${reason} `;
|
|
@@ -8914,7 +8953,9 @@ class BohoAuth {
|
|
|
8914
8953
|
peer.setState(STATE.AUTH_FAIL);
|
|
8915
8954
|
// add some delay time.
|
|
8916
8955
|
setTimeout(e => {
|
|
8917
|
-
peer.
|
|
8956
|
+
if (!peer._closing && peer.state === STATE.AUTH_FAIL) {
|
|
8957
|
+
peer.send(Buffer.from([it.BohoMsg.AUTH_FAIL]));
|
|
8958
|
+
}
|
|
8918
8959
|
}, serverOption.auth.delay_auth_fail);
|
|
8919
8960
|
}
|
|
8920
8961
|
|
|
@@ -8937,6 +8978,7 @@ class BohoAuth {
|
|
|
8937
8978
|
|
|
8938
8979
|
//2. get key of id from DB
|
|
8939
8980
|
let authInfo = await this.keyProvider.getAuth(id);
|
|
8981
|
+
if (peer._closing || peer.state === STATE.CLOSED) return;
|
|
8940
8982
|
if (!authInfo) {
|
|
8941
8983
|
this.send_auth_fail(peer, 'NO ID:' + id);
|
|
8942
8984
|
return
|
|
@@ -8969,14 +9011,10 @@ class BohoAuth {
|
|
|
8969
9011
|
//4. get info
|
|
8970
9012
|
|
|
8971
9013
|
//5. check duplicate login.
|
|
8972
|
-
if (peer.manager.cid2remote.has(authInfo.cid)) {
|
|
9014
|
+
if (peer.manager.cid2remote.has(authInfo.cid) && peer.manager.cid2remote.get(authInfo.cid) !== peer) {
|
|
8973
9015
|
let old = peer.manager.cid2remote.get(authInfo.cid);
|
|
8974
9016
|
console.log('[WARN]DUPLICATE_LOGIN detected.', old.cid);
|
|
8975
9017
|
old.ping(); // check the connection.
|
|
8976
|
-
if (old == peer) {
|
|
8977
|
-
console.log('## trying to RELOGIN after login.');
|
|
8978
|
-
return
|
|
8979
|
-
}
|
|
8980
9018
|
|
|
8981
9019
|
let authClearSignal = $$1.pack(
|
|
8982
9020
|
$$1.MB('#MsgType', '8', IOMsg.AUTH_CLEAR),
|
|
@@ -8989,6 +9027,7 @@ class BohoAuth {
|
|
|
8989
9027
|
if( peer.socketType == 'websocket'){
|
|
8990
9028
|
this.send_auth_fail(peer, 'duplicate login');
|
|
8991
9029
|
}else {
|
|
9030
|
+
peer.setState(STATE.AUTH_FAIL);
|
|
8992
9031
|
peer.close(); //arduino
|
|
8993
9032
|
}
|
|
8994
9033
|
} else {
|