iosignal 5.3.0 → 6.1.1
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/dist/browser/esm/io.d.ts +14 -4
- package/dist/browser/esm/io.js +4 -4
- package/dist/browser/esm/io.js.map +1 -1
- package/dist/browser/iife/io.js +4 -4
- package/dist/browser/iife/io.js.map +1 -1
- package/dist/node/iosignal.cjs +149 -470
- package/dist/node/iosignal.js +148 -469
- package/dist/types/client/IOCore.d.ts +14 -4
- package/package.json +2 -2
package/dist/node/iosignal.cjs
CHANGED
|
@@ -4,19 +4,19 @@ var require$$0 = require('stream');
|
|
|
4
4
|
var net = require('net');
|
|
5
5
|
var require$$0$3 = require('events');
|
|
6
6
|
var require$$1$1 = require('https');
|
|
7
|
-
var require$$2$
|
|
7
|
+
var require$$2$1 = require('http');
|
|
8
8
|
var require$$4 = require('tls');
|
|
9
9
|
var require$$1 = require('crypto');
|
|
10
10
|
var require$$7 = require('url');
|
|
11
11
|
var require$$0$1 = require('zlib');
|
|
12
|
-
var fs = require('fs');
|
|
13
|
-
var path = require('path');
|
|
14
|
-
var require$$2 = require('os');
|
|
15
12
|
var require$$0$2 = require('buffer');
|
|
16
|
-
var require$$2
|
|
13
|
+
var require$$2 = require('util');
|
|
14
|
+
var os = require('os');
|
|
15
|
+
var fs = require('fs');
|
|
17
16
|
var process$1 = require('process');
|
|
17
|
+
var path = require('path');
|
|
18
18
|
|
|
19
|
-
var version$1 = "
|
|
19
|
+
var version$1 = "6.1.1";
|
|
20
20
|
var pkg = {
|
|
21
21
|
version: version$1};
|
|
22
22
|
|
|
@@ -667,6 +667,7 @@ const encoder$2 = new TextEncoder();
|
|
|
667
667
|
function getSignalPack(tag, ...args) {
|
|
668
668
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
669
669
|
let tagEncoded = encoder$2.encode(tag);
|
|
670
|
+
if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN1) throw TypeError('tag UTF-8 byte length exceeds 255')
|
|
670
671
|
let payload = parsePayload(args);
|
|
671
672
|
|
|
672
673
|
let sigPack;
|
|
@@ -774,6 +775,16 @@ const Buffer$1 = $$1.Buffer;
|
|
|
774
775
|
const encoder$1 = new TextEncoder();
|
|
775
776
|
const decoder$4 = new TextDecoder();
|
|
776
777
|
|
|
778
|
+
// Wire tag lengths use one byte, regardless of JavaScript string length.
|
|
779
|
+
function encodeTag(tag, allowEmpty = true) {
|
|
780
|
+
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
781
|
+
const encoded = encoder$1.encode(tag);
|
|
782
|
+
if ((!allowEmpty && encoded.byteLength === 0) || encoded.byteLength > SIZE_LIMIT.TAG_LEN1) {
|
|
783
|
+
throw TypeError('tag UTF-8 byte length must be ' + (allowEmpty ? '0' : '1') + '~255')
|
|
784
|
+
}
|
|
785
|
+
return encoded
|
|
786
|
+
}
|
|
787
|
+
|
|
777
788
|
function byteToUrl(buffer) {
|
|
778
789
|
//ipv4(4bytes) , port(2bytes)
|
|
779
790
|
if (buffer.byteLength != 6) return
|
|
@@ -823,6 +834,7 @@ class IOCore extends EventEmitter {
|
|
|
823
834
|
* @type {string}
|
|
824
835
|
*/
|
|
825
836
|
this.stateName = this.getStateName(); // String type
|
|
837
|
+
this._stateRevision = 0;
|
|
826
838
|
|
|
827
839
|
/**
|
|
828
840
|
* Transmitted message counter.
|
|
@@ -959,14 +971,14 @@ class IOCore extends EventEmitter {
|
|
|
959
971
|
* If autoReconnect is false, it also clears the keep-alive timer.
|
|
960
972
|
*/
|
|
961
973
|
close() {
|
|
962
|
-
if (this._closed) return;
|
|
963
|
-
this._closed = true;
|
|
964
974
|
// console.log('####### IOCOre.js close() called')
|
|
965
975
|
// If auto-reconnect is disabled, we must stop the keep-alive timer.
|
|
966
976
|
if (this.autoReconnect === false) {
|
|
967
977
|
clearInterval(this.connectionCheckerIntervalID);
|
|
968
978
|
this.connectionCheckerIntervalID = null;
|
|
969
979
|
}
|
|
980
|
+
if (this._closed) return;
|
|
981
|
+
this._closed = true;
|
|
970
982
|
|
|
971
983
|
// socket clean
|
|
972
984
|
if (this.socket) {
|
|
@@ -989,8 +1001,11 @@ class IOCore extends EventEmitter {
|
|
|
989
1001
|
this.socket = null;
|
|
990
1002
|
}
|
|
991
1003
|
this.promiseMap.clear();
|
|
992
|
-
this.
|
|
993
|
-
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
|
+
}
|
|
994
1009
|
}
|
|
995
1010
|
|
|
996
1011
|
/**
|
|
@@ -1063,6 +1078,7 @@ class IOCore extends EventEmitter {
|
|
|
1063
1078
|
|
|
1064
1079
|
// The actual connection is created here.
|
|
1065
1080
|
this.createConnection(this.url);
|
|
1081
|
+
if (this._closed) return; // A connecting listener may have stopped the client.
|
|
1066
1082
|
|
|
1067
1083
|
// Ensure the keep-alive timer is running.
|
|
1068
1084
|
if (!this.connectionCheckerIntervalID) {
|
|
@@ -1087,9 +1103,7 @@ class IOCore extends EventEmitter {
|
|
|
1087
1103
|
* Handles the 'close' event of the WebSocket.
|
|
1088
1104
|
*/
|
|
1089
1105
|
onClose() {
|
|
1090
|
-
this.
|
|
1091
|
-
this.cid = "";
|
|
1092
|
-
this.stateChange('closed');
|
|
1106
|
+
this.close();
|
|
1093
1107
|
}
|
|
1094
1108
|
|
|
1095
1109
|
/**
|
|
@@ -1100,11 +1114,11 @@ class IOCore extends EventEmitter {
|
|
|
1100
1114
|
*/
|
|
1101
1115
|
login(id, key) {
|
|
1102
1116
|
if( this.serverTimeNonce ){
|
|
1103
|
-
console.log('iosignal.login serverTimeNonce', this.serverTimeNonce);
|
|
1104
1117
|
this.auth(id, key);
|
|
1105
1118
|
this.useAuth = true;
|
|
1106
1119
|
let auth_pack = this.boho.auth_req(this.serverTimeNonce );
|
|
1107
1120
|
this.send(auth_pack);
|
|
1121
|
+
this.stateChange('auth_req', 'auth_req');
|
|
1108
1122
|
}
|
|
1109
1123
|
return this
|
|
1110
1124
|
}
|
|
@@ -1250,14 +1264,13 @@ class IOCore extends EventEmitter {
|
|
|
1250
1264
|
break;
|
|
1251
1265
|
|
|
1252
1266
|
case it.BohoMsg.SERVER_TIME_NONCE: // SERVER_READY
|
|
1253
|
-
this.
|
|
1267
|
+
buffer.copy(this.serverTimeNonce);
|
|
1268
|
+
if (!this.stateChange('server_ready', 'server_ready')) break;
|
|
1254
1269
|
if (this.useAuth) {
|
|
1255
1270
|
this.send(this.boho.auth_req(buffer));
|
|
1256
1271
|
this.stateChange('auth_req','auth_req');
|
|
1257
1272
|
// CID_REQ will be called, after auth_res.
|
|
1258
1273
|
} else {
|
|
1259
|
-
// keep server_time_nonce for manual login()
|
|
1260
|
-
buffer.copy( this.serverTimeNonce);
|
|
1261
1274
|
// CID_REQ here, if not using auth.
|
|
1262
1275
|
this.send(Buffer$1.from([IOMsg.CID_REQ]));
|
|
1263
1276
|
}
|
|
@@ -1308,10 +1321,10 @@ class IOCore extends EventEmitter {
|
|
|
1308
1321
|
switch (payloadType) {
|
|
1309
1322
|
|
|
1310
1323
|
case PAYLOAD_TYPE.EMPTY:
|
|
1311
|
-
if (tag.indexOf('@') === 0) this.emit('@', tag
|
|
1324
|
+
if (tag.indexOf('@') === 0) this.emit('@', tag);
|
|
1312
1325
|
else {
|
|
1313
|
-
this.emit(tag, tag
|
|
1314
|
-
this.emit('message', tag
|
|
1326
|
+
this.emit(tag, tag);
|
|
1327
|
+
this.emit('message', tag);
|
|
1315
1328
|
}
|
|
1316
1329
|
break;
|
|
1317
1330
|
|
|
@@ -1382,14 +1395,16 @@ class IOCore extends EventEmitter {
|
|
|
1382
1395
|
break;
|
|
1383
1396
|
|
|
1384
1397
|
case it.BohoMsg.AUTH_FAIL:
|
|
1398
|
+
this.boho.isAuthorized = false;
|
|
1385
1399
|
this.stateChange('auth_fail', 'auth_fail from server.');
|
|
1386
1400
|
break;
|
|
1387
1401
|
|
|
1388
1402
|
case it.BohoMsg.AUTH_RES:
|
|
1389
1403
|
if (this.boho.verify_auth_res(buffer)) {
|
|
1390
|
-
this.stateChange('auth_res', 'server sent auth_res');
|
|
1404
|
+
if (!this.stateChange('auth_res', 'server sent auth_res')) break;
|
|
1391
1405
|
this.send(Buffer$1.from([IOMsg.CID_REQ]));
|
|
1392
1406
|
} else {
|
|
1407
|
+
this.boho.isAuthorized = false;
|
|
1393
1408
|
this.stateChange('auth_fail', 'verify_auth_res() invalid server_hmac');
|
|
1394
1409
|
}
|
|
1395
1410
|
break;
|
|
@@ -1595,6 +1610,7 @@ class IOCore extends EventEmitter {
|
|
|
1595
1610
|
*/
|
|
1596
1611
|
signal(tag, ...args) {
|
|
1597
1612
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1613
|
+
if (tag.startsWith('@') && this.cid) encodeTag(this.cid + tag);
|
|
1598
1614
|
let signalPack = getSignalPack(tag, ...args);
|
|
1599
1615
|
this.send_enc_mode(signalPack);
|
|
1600
1616
|
}
|
|
@@ -1618,9 +1634,9 @@ class IOCore extends EventEmitter {
|
|
|
1618
1634
|
*/
|
|
1619
1635
|
signal_e2e(tag, data, key) {
|
|
1620
1636
|
|
|
1637
|
+
const tagEncoded = encodeTag(tag);
|
|
1638
|
+
if (tag.startsWith('@') && this.cid) encodeTag(this.cid + tag);
|
|
1621
1639
|
if( !this.boho.isAuthorized ) return;
|
|
1622
|
-
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1623
|
-
let tagEncoded = encoder$1.encode(tag);
|
|
1624
1640
|
let dataPack = $$1.B8(data);
|
|
1625
1641
|
|
|
1626
1642
|
//encrypt payload area with key
|
|
@@ -1705,39 +1721,37 @@ class IOCore extends EventEmitter {
|
|
|
1705
1721
|
* @throws {TypeError} If tag is not a string or exceeds length limit.
|
|
1706
1722
|
*/
|
|
1707
1723
|
subscribe(tag) {
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
this.send_enc_mode(
|
|
1714
|
-
Buffer$1.concat([
|
|
1715
|
-
$$1.NB('8', IOMsg.SUBSCRIBE),
|
|
1716
|
-
$$1.NB('8', tagEncoded.byteLength),
|
|
1717
|
-
tagEncoded]));
|
|
1718
|
-
} catch (error) { }
|
|
1719
|
-
|
|
1724
|
+
const tagEncoded = encodeTag(tag);
|
|
1725
|
+
this.send_enc_mode(Buffer$1.concat([
|
|
1726
|
+
$$1.NB('8', IOMsg.SUBSCRIBE),
|
|
1727
|
+
$$1.NB('8', tagEncoded.byteLength),
|
|
1728
|
+
tagEncoded]));
|
|
1720
1729
|
}
|
|
1721
1730
|
|
|
1722
1731
|
|
|
1723
1732
|
/**
|
|
1724
|
-
*
|
|
1725
|
-
*
|
|
1733
|
+
* Sends subscriptions stored by listen()/link() on each CID-ready transition,
|
|
1734
|
+
* including reconnection. This automates subscription setup for simple clients.
|
|
1726
1735
|
*/
|
|
1727
1736
|
subscribe_channels() {
|
|
1728
|
-
if (this.state !== STATE.READY) return
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1737
|
+
if (this.state !== STATE.READY || this.channels.size === 0) return
|
|
1738
|
+
// Validate the entire list first, then split only at tag boundaries.
|
|
1739
|
+
// Preserve comma-separated entries accepted by existing registration APIs.
|
|
1740
|
+
const tags = Array.from(this.channels).join(',').split(',');
|
|
1741
|
+
const sizes = tags.map(tag => encodeTag(tag).byteLength);
|
|
1742
|
+
const batches = [];
|
|
1743
|
+
let batch = [], bytes = 0;
|
|
1744
|
+
tags.forEach((tag, i) => {
|
|
1745
|
+
if (batch.length && bytes + 1 + sizes[i] > SIZE_LIMIT.TAG_LEN1) {
|
|
1746
|
+
batches.push(batch.join(','));
|
|
1747
|
+
batch = [];
|
|
1748
|
+
bytes = 0;
|
|
1749
|
+
}
|
|
1750
|
+
bytes += (batch.length ? 1 : 0) + sizes[i];
|
|
1751
|
+
batch.push(tag);
|
|
1752
|
+
});
|
|
1753
|
+
if (batch.length) batches.push(batch.join(','));
|
|
1754
|
+
batches.forEach(tag => this.subscribe(tag));
|
|
1741
1755
|
}
|
|
1742
1756
|
|
|
1743
1757
|
/**
|
|
@@ -1746,7 +1760,7 @@ class IOCore extends EventEmitter {
|
|
|
1746
1760
|
* @throws {TypeError} If tag is not a string or exceeds length limit.
|
|
1747
1761
|
*/
|
|
1748
1762
|
unsubscribe(tag = "") {
|
|
1749
|
-
|
|
1763
|
+
const tagEncoded = encodeTag(tag);
|
|
1750
1764
|
|
|
1751
1765
|
if (tag == "") { // blank tag means unsubscribe all
|
|
1752
1766
|
this.channels.clear();
|
|
@@ -1757,8 +1771,6 @@ class IOCore extends EventEmitter {
|
|
|
1757
1771
|
});
|
|
1758
1772
|
}
|
|
1759
1773
|
|
|
1760
|
-
let tagEncoded = encoder$1.encode(tag);
|
|
1761
|
-
if (tagEncoded.byteLength > SIZE_LIMIT.TAG_LEN1) throw TypeError('please use tag string bytelength below:' + SIZE_LIMIT.TAG_LEN1)
|
|
1762
1774
|
|
|
1763
1775
|
this.send_enc_mode(Buffer$1.concat([
|
|
1764
1776
|
$$1.NB('8', IOMsg.UNSUBSCRIBE),
|
|
@@ -1768,22 +1780,28 @@ class IOCore extends EventEmitter {
|
|
|
1768
1780
|
|
|
1769
1781
|
|
|
1770
1782
|
/**
|
|
1771
|
-
*
|
|
1783
|
+
* Convenience API for simple clients (for example, CLI tools): register a
|
|
1784
|
+
* tag handler once and remember its subscription in channels. Register before
|
|
1785
|
+
* connection readiness; the CID-ready flow subscribes on initial connection
|
|
1786
|
+
* and again after reconnect, without application-level ready/subscribe code.
|
|
1787
|
+
* This does not send a subscription immediately, even if already ready.
|
|
1788
|
+
* For precise subscription/send ordering or dynamic subscriptions, use
|
|
1789
|
+
* on() with subscribe() in a ready handler instead. Direct signals use on('@').
|
|
1772
1790
|
* @param {string} tag - The tag to listen on.
|
|
1773
1791
|
* @param {Function} handler - The callback function to handle the signal.
|
|
1774
1792
|
* @throws {TypeError} If tag is not a string, handler is not a function, or tag length is invalid.
|
|
1775
1793
|
*/
|
|
1776
1794
|
listen(tag, handler) {
|
|
1777
1795
|
if (typeof tag !== 'string') throw TypeError('tag should be string.')
|
|
1778
|
-
|
|
1796
|
+
encodeTag(tag, false);
|
|
1779
1797
|
if (typeof handler !== 'function') throw TypeError('handler is not a function.')
|
|
1780
1798
|
|
|
1781
1799
|
if (tag.indexOf('@') !== 0) {
|
|
1782
1800
|
this.channels.add(tag);
|
|
1783
1801
|
}
|
|
1784
1802
|
this.on(tag, handler);
|
|
1785
|
-
//
|
|
1786
|
-
//
|
|
1803
|
+
// Subscribe from the CID-ready flow, initially and after reconnect.
|
|
1804
|
+
// Keep registration separate from immediate subscription/send ordering.
|
|
1787
1805
|
|
|
1788
1806
|
}
|
|
1789
1807
|
|
|
@@ -1799,7 +1817,7 @@ class IOCore extends EventEmitter {
|
|
|
1799
1817
|
link(to, tag, handler) {
|
|
1800
1818
|
if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
|
|
1801
1819
|
if (typeof tag !== 'string') throw TypeError('tag is not a string.')
|
|
1802
|
-
|
|
1820
|
+
encodeTag(tag, false);
|
|
1803
1821
|
if (typeof handler !== 'function') throw TypeError('handler is not a function.')
|
|
1804
1822
|
|
|
1805
1823
|
if (tag.indexOf('@') !== 0) {
|
|
@@ -1830,7 +1848,7 @@ class IOCore extends EventEmitter {
|
|
|
1830
1848
|
unlink(to, tag) {
|
|
1831
1849
|
if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
|
|
1832
1850
|
if (typeof tag !== 'string') throw TypeError('tag is not a string.')
|
|
1833
|
-
|
|
1851
|
+
encodeTag(tag, false);
|
|
1834
1852
|
|
|
1835
1853
|
const linkSet = this.linkMap.get(to);
|
|
1836
1854
|
if (!linkSet || !linkSet.has(tag)) return;
|
|
@@ -1923,6 +1941,9 @@ class IOCore extends EventEmitter {
|
|
|
1923
1941
|
* 1. 상태가 변경 될 때만 'change' 이벤트 호출된다.
|
|
1924
1942
|
* 2. emitEventAndMessage 옵션 값이 지정되야 해당 이벤트 이름이 호출된다.
|
|
1925
1943
|
* 보통 이벤트 이름과 동일하게 적거나 이벤트 상황 안내문을 넣는다.
|
|
1944
|
+
* 3. 두 상태값 갱신 후 change, 개별 이벤트 순서로 호출한다.
|
|
1945
|
+
* 콜백에서 다른 상태로 전이하면 이전 상태의 개별 이벤트는 생략한다.
|
|
1946
|
+
* @returns {boolean} Whether this transition is still current after callbacks.
|
|
1926
1947
|
*/
|
|
1927
1948
|
stateChange(state, emitEventAndMessage) {
|
|
1928
1949
|
// STATE constant name <string> upperCase
|
|
@@ -1930,16 +1951,19 @@ class IOCore extends EventEmitter {
|
|
|
1930
1951
|
// .state <number>
|
|
1931
1952
|
// console.log('### stateChange reason:', emitEventAndMessage )
|
|
1932
1953
|
let eventName = state.toLowerCase();
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
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) {
|
|
1941
1962
|
this.emit('change', eventName);
|
|
1942
1963
|
}
|
|
1964
|
+
if (revision !== this._stateRevision) return false;
|
|
1965
|
+
if (emitEventAndMessage) this.emit(eventName, emitEventAndMessage);
|
|
1966
|
+
return revision === this._stateRevision;
|
|
1943
1967
|
}
|
|
1944
1968
|
|
|
1945
1969
|
}
|
|
@@ -2100,6 +2124,7 @@ class IOCongSocket extends IOCore {
|
|
|
2100
2124
|
this.congRx = null;
|
|
2101
2125
|
}
|
|
2102
2126
|
this.socket.removeAllListeners();
|
|
2127
|
+
this.socket.on('error', () => {});
|
|
2103
2128
|
if (!this.socket.destroyed) {
|
|
2104
2129
|
this.socket.destroy(); // destroy() is sufficient for forceful closing
|
|
2105
2130
|
}
|
|
@@ -2124,23 +2149,29 @@ class IOCongSocket extends IOCore {
|
|
|
2124
2149
|
if (urlObj.protocol != "cong:") {
|
|
2125
2150
|
urlObj = new URL('cong://' + url);
|
|
2126
2151
|
}
|
|
2127
|
-
this.socket = net.createConnection(urlObj.port, urlObj.hostname);
|
|
2128
|
-
this.
|
|
2152
|
+
const socket = this.socket = net.createConnection(urlObj.port, urlObj.hostname);
|
|
2153
|
+
this._closed = false;
|
|
2129
2154
|
|
|
2130
2155
|
this.socket.on('connect', () => {
|
|
2156
|
+
if (this.socket !== socket) return;
|
|
2131
2157
|
this.congRx = new CongRx();
|
|
2132
2158
|
this.socket.pipe(this.congRx);
|
|
2133
|
-
this.congRx.on(
|
|
2159
|
+
this.congRx.on('data', data => {
|
|
2160
|
+
if (this.socket === socket) this.onTCPSocketMessage(data);
|
|
2161
|
+
});
|
|
2134
2162
|
this.emit('open');
|
|
2135
2163
|
});
|
|
2136
2164
|
|
|
2137
2165
|
this.socket.on('error', e => {
|
|
2166
|
+
if (this.socket !== socket) return;
|
|
2138
2167
|
this.emit('error', e);
|
|
2139
2168
|
});
|
|
2140
2169
|
|
|
2141
2170
|
this.socket.on('close', () => {
|
|
2171
|
+
if (this.socket !== socket) return;
|
|
2142
2172
|
this.emit('close');
|
|
2143
2173
|
});
|
|
2174
|
+
this.stateChange('connecting','connecting');
|
|
2144
2175
|
|
|
2145
2176
|
}
|
|
2146
2177
|
|
|
@@ -2195,300 +2226,6 @@ function requireConstants () {
|
|
|
2195
2226
|
return constants;
|
|
2196
2227
|
}
|
|
2197
2228
|
|
|
2198
|
-
var bufferutil = {exports: {}};
|
|
2199
|
-
|
|
2200
|
-
function commonjsRequire(path) {
|
|
2201
|
-
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
2202
|
-
}
|
|
2203
|
-
|
|
2204
|
-
var nodeGypBuild$1 = {exports: {}};
|
|
2205
|
-
|
|
2206
|
-
var nodeGypBuild;
|
|
2207
|
-
var hasRequiredNodeGypBuild$1;
|
|
2208
|
-
|
|
2209
|
-
function requireNodeGypBuild$1 () {
|
|
2210
|
-
if (hasRequiredNodeGypBuild$1) return nodeGypBuild;
|
|
2211
|
-
hasRequiredNodeGypBuild$1 = 1;
|
|
2212
|
-
var fs$1 = fs;
|
|
2213
|
-
var path$1 = path;
|
|
2214
|
-
var os = require$$2;
|
|
2215
|
-
|
|
2216
|
-
// Workaround to fix webpack's build warnings: 'the request of a dependency is an expression'
|
|
2217
|
-
var runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire; // eslint-disable-line
|
|
2218
|
-
|
|
2219
|
-
var vars = (process.config && process.config.variables) || {};
|
|
2220
|
-
var prebuildsOnly = !!process.env.PREBUILDS_ONLY;
|
|
2221
|
-
var abi = process.versions.modules; // TODO: support old node where this is undef
|
|
2222
|
-
var runtime = isElectron() ? 'electron' : (isNwjs() ? 'node-webkit' : 'node');
|
|
2223
|
-
|
|
2224
|
-
var arch = process.env.npm_config_arch || os.arch();
|
|
2225
|
-
var platform = process.env.npm_config_platform || os.platform();
|
|
2226
|
-
var libc = process.env.LIBC || (isAlpine(platform) ? 'musl' : 'glibc');
|
|
2227
|
-
var armv = process.env.ARM_VERSION || (arch === 'arm64' ? '8' : vars.arm_version) || '';
|
|
2228
|
-
var uv = (process.versions.uv || '').split('.')[0];
|
|
2229
|
-
|
|
2230
|
-
nodeGypBuild = load;
|
|
2231
|
-
|
|
2232
|
-
function load (dir) {
|
|
2233
|
-
return runtimeRequire(load.resolve(dir))
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
load.resolve = load.path = function (dir) {
|
|
2237
|
-
dir = path$1.resolve(dir || '.');
|
|
2238
|
-
|
|
2239
|
-
try {
|
|
2240
|
-
var name = runtimeRequire(path$1.join(dir, 'package.json')).name.toUpperCase().replace(/-/g, '_');
|
|
2241
|
-
if (process.env[name + '_PREBUILD']) dir = process.env[name + '_PREBUILD'];
|
|
2242
|
-
} catch (err) {}
|
|
2243
|
-
|
|
2244
|
-
if (!prebuildsOnly) {
|
|
2245
|
-
var release = getFirst(path$1.join(dir, 'build/Release'), matchBuild);
|
|
2246
|
-
if (release) return release
|
|
2247
|
-
|
|
2248
|
-
var debug = getFirst(path$1.join(dir, 'build/Debug'), matchBuild);
|
|
2249
|
-
if (debug) return debug
|
|
2250
|
-
}
|
|
2251
|
-
|
|
2252
|
-
var prebuild = resolve(dir);
|
|
2253
|
-
if (prebuild) return prebuild
|
|
2254
|
-
|
|
2255
|
-
var nearby = resolve(path$1.dirname(process.execPath));
|
|
2256
|
-
if (nearby) return nearby
|
|
2257
|
-
|
|
2258
|
-
var target = [
|
|
2259
|
-
'platform=' + platform,
|
|
2260
|
-
'arch=' + arch,
|
|
2261
|
-
'runtime=' + runtime,
|
|
2262
|
-
'abi=' + abi,
|
|
2263
|
-
'uv=' + uv,
|
|
2264
|
-
armv ? 'armv=' + armv : '',
|
|
2265
|
-
'libc=' + libc,
|
|
2266
|
-
'node=' + process.versions.node,
|
|
2267
|
-
process.versions.electron ? 'electron=' + process.versions.electron : '',
|
|
2268
|
-
typeof __webpack_require__ === 'function' ? 'webpack=true' : '' // eslint-disable-line
|
|
2269
|
-
].filter(Boolean).join(' ');
|
|
2270
|
-
|
|
2271
|
-
throw new Error('No native build was found for ' + target + '\n loaded from: ' + dir + '\n')
|
|
2272
|
-
|
|
2273
|
-
function resolve (dir) {
|
|
2274
|
-
// Find matching "prebuilds/<platform>-<arch>" directory
|
|
2275
|
-
var tuples = readdirSync(path$1.join(dir, 'prebuilds')).map(parseTuple);
|
|
2276
|
-
var tuple = tuples.filter(matchTuple(platform, arch)).sort(compareTuples)[0];
|
|
2277
|
-
if (!tuple) return
|
|
2278
|
-
|
|
2279
|
-
// Find most specific flavor first
|
|
2280
|
-
var prebuilds = path$1.join(dir, 'prebuilds', tuple.name);
|
|
2281
|
-
var parsed = readdirSync(prebuilds).map(parseTags);
|
|
2282
|
-
var candidates = parsed.filter(matchTags(runtime, abi));
|
|
2283
|
-
var winner = candidates.sort(compareTags(runtime))[0];
|
|
2284
|
-
if (winner) return path$1.join(prebuilds, winner.file)
|
|
2285
|
-
}
|
|
2286
|
-
};
|
|
2287
|
-
|
|
2288
|
-
function readdirSync (dir) {
|
|
2289
|
-
try {
|
|
2290
|
-
return fs$1.readdirSync(dir)
|
|
2291
|
-
} catch (err) {
|
|
2292
|
-
return []
|
|
2293
|
-
}
|
|
2294
|
-
}
|
|
2295
|
-
|
|
2296
|
-
function getFirst (dir, filter) {
|
|
2297
|
-
var files = readdirSync(dir).filter(filter);
|
|
2298
|
-
return files[0] && path$1.join(dir, files[0])
|
|
2299
|
-
}
|
|
2300
|
-
|
|
2301
|
-
function matchBuild (name) {
|
|
2302
|
-
return /\.node$/.test(name)
|
|
2303
|
-
}
|
|
2304
|
-
|
|
2305
|
-
function parseTuple (name) {
|
|
2306
|
-
// Example: darwin-x64+arm64
|
|
2307
|
-
var arr = name.split('-');
|
|
2308
|
-
if (arr.length !== 2) return
|
|
2309
|
-
|
|
2310
|
-
var platform = arr[0];
|
|
2311
|
-
var architectures = arr[1].split('+');
|
|
2312
|
-
|
|
2313
|
-
if (!platform) return
|
|
2314
|
-
if (!architectures.length) return
|
|
2315
|
-
if (!architectures.every(Boolean)) return
|
|
2316
|
-
|
|
2317
|
-
return { name, platform, architectures }
|
|
2318
|
-
}
|
|
2319
|
-
|
|
2320
|
-
function matchTuple (platform, arch) {
|
|
2321
|
-
return function (tuple) {
|
|
2322
|
-
if (tuple == null) return false
|
|
2323
|
-
if (tuple.platform !== platform) return false
|
|
2324
|
-
return tuple.architectures.includes(arch)
|
|
2325
|
-
}
|
|
2326
|
-
}
|
|
2327
|
-
|
|
2328
|
-
function compareTuples (a, b) {
|
|
2329
|
-
// Prefer single-arch prebuilds over multi-arch
|
|
2330
|
-
return a.architectures.length - b.architectures.length
|
|
2331
|
-
}
|
|
2332
|
-
|
|
2333
|
-
function parseTags (file) {
|
|
2334
|
-
var arr = file.split('.');
|
|
2335
|
-
var extension = arr.pop();
|
|
2336
|
-
var tags = { file: file, specificity: 0 };
|
|
2337
|
-
|
|
2338
|
-
if (extension !== 'node') return
|
|
2339
|
-
|
|
2340
|
-
for (var i = 0; i < arr.length; i++) {
|
|
2341
|
-
var tag = arr[i];
|
|
2342
|
-
|
|
2343
|
-
if (tag === 'node' || tag === 'electron' || tag === 'node-webkit') {
|
|
2344
|
-
tags.runtime = tag;
|
|
2345
|
-
} else if (tag === 'napi') {
|
|
2346
|
-
tags.napi = true;
|
|
2347
|
-
} else if (tag.slice(0, 3) === 'abi') {
|
|
2348
|
-
tags.abi = tag.slice(3);
|
|
2349
|
-
} else if (tag.slice(0, 2) === 'uv') {
|
|
2350
|
-
tags.uv = tag.slice(2);
|
|
2351
|
-
} else if (tag.slice(0, 4) === 'armv') {
|
|
2352
|
-
tags.armv = tag.slice(4);
|
|
2353
|
-
} else if (tag === 'glibc' || tag === 'musl') {
|
|
2354
|
-
tags.libc = tag;
|
|
2355
|
-
} else {
|
|
2356
|
-
continue
|
|
2357
|
-
}
|
|
2358
|
-
|
|
2359
|
-
tags.specificity++;
|
|
2360
|
-
}
|
|
2361
|
-
|
|
2362
|
-
return tags
|
|
2363
|
-
}
|
|
2364
|
-
|
|
2365
|
-
function matchTags (runtime, abi) {
|
|
2366
|
-
return function (tags) {
|
|
2367
|
-
if (tags == null) return false
|
|
2368
|
-
if (tags.runtime && tags.runtime !== runtime && !runtimeAgnostic(tags)) return false
|
|
2369
|
-
if (tags.abi && tags.abi !== abi && !tags.napi) return false
|
|
2370
|
-
if (tags.uv && tags.uv !== uv) return false
|
|
2371
|
-
if (tags.armv && tags.armv !== armv) return false
|
|
2372
|
-
if (tags.libc && tags.libc !== libc) return false
|
|
2373
|
-
|
|
2374
|
-
return true
|
|
2375
|
-
}
|
|
2376
|
-
}
|
|
2377
|
-
|
|
2378
|
-
function runtimeAgnostic (tags) {
|
|
2379
|
-
return tags.runtime === 'node' && tags.napi
|
|
2380
|
-
}
|
|
2381
|
-
|
|
2382
|
-
function compareTags (runtime) {
|
|
2383
|
-
// Precedence: non-agnostic runtime, abi over napi, then by specificity.
|
|
2384
|
-
return function (a, b) {
|
|
2385
|
-
if (a.runtime !== b.runtime) {
|
|
2386
|
-
return a.runtime === runtime ? -1 : 1
|
|
2387
|
-
} else if (a.abi !== b.abi) {
|
|
2388
|
-
return a.abi ? -1 : 1
|
|
2389
|
-
} else if (a.specificity !== b.specificity) {
|
|
2390
|
-
return a.specificity > b.specificity ? -1 : 1
|
|
2391
|
-
} else {
|
|
2392
|
-
return 0
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2395
|
-
}
|
|
2396
|
-
|
|
2397
|
-
function isNwjs () {
|
|
2398
|
-
return !!(process.versions && process.versions.nw)
|
|
2399
|
-
}
|
|
2400
|
-
|
|
2401
|
-
function isElectron () {
|
|
2402
|
-
if (process.versions && process.versions.electron) return true
|
|
2403
|
-
if (process.env.ELECTRON_RUN_AS_NODE) return true
|
|
2404
|
-
return typeof window !== 'undefined' && window.process && window.process.type === 'renderer'
|
|
2405
|
-
}
|
|
2406
|
-
|
|
2407
|
-
function isAlpine (platform) {
|
|
2408
|
-
return platform === 'linux' && fs$1.existsSync('/etc/alpine-release')
|
|
2409
|
-
}
|
|
2410
|
-
|
|
2411
|
-
// Exposed for unit tests
|
|
2412
|
-
// TODO: move to lib
|
|
2413
|
-
load.parseTags = parseTags;
|
|
2414
|
-
load.matchTags = matchTags;
|
|
2415
|
-
load.compareTags = compareTags;
|
|
2416
|
-
load.parseTuple = parseTuple;
|
|
2417
|
-
load.matchTuple = matchTuple;
|
|
2418
|
-
load.compareTuples = compareTuples;
|
|
2419
|
-
return nodeGypBuild;
|
|
2420
|
-
}
|
|
2421
|
-
|
|
2422
|
-
var hasRequiredNodeGypBuild;
|
|
2423
|
-
|
|
2424
|
-
function requireNodeGypBuild () {
|
|
2425
|
-
if (hasRequiredNodeGypBuild) return nodeGypBuild$1.exports;
|
|
2426
|
-
hasRequiredNodeGypBuild = 1;
|
|
2427
|
-
const runtimeRequire = typeof __webpack_require__ === 'function' ? __non_webpack_require__ : commonjsRequire; // eslint-disable-line
|
|
2428
|
-
if (typeof runtimeRequire.addon === 'function') { // if the platform supports native resolving prefer that
|
|
2429
|
-
nodeGypBuild$1.exports = runtimeRequire.addon.bind(runtimeRequire);
|
|
2430
|
-
} else { // else use the runtime version here
|
|
2431
|
-
nodeGypBuild$1.exports = requireNodeGypBuild$1();
|
|
2432
|
-
}
|
|
2433
|
-
return nodeGypBuild$1.exports;
|
|
2434
|
-
}
|
|
2435
|
-
|
|
2436
|
-
var fallback$1;
|
|
2437
|
-
var hasRequiredFallback$1;
|
|
2438
|
-
|
|
2439
|
-
function requireFallback$1 () {
|
|
2440
|
-
if (hasRequiredFallback$1) return fallback$1;
|
|
2441
|
-
hasRequiredFallback$1 = 1;
|
|
2442
|
-
|
|
2443
|
-
/**
|
|
2444
|
-
* Masks a buffer using the given mask.
|
|
2445
|
-
*
|
|
2446
|
-
* @param {Buffer} source The buffer to mask
|
|
2447
|
-
* @param {Buffer} mask The mask to use
|
|
2448
|
-
* @param {Buffer} output The buffer where to store the result
|
|
2449
|
-
* @param {Number} offset The offset at which to start writing
|
|
2450
|
-
* @param {Number} length The number of bytes to mask.
|
|
2451
|
-
* @public
|
|
2452
|
-
*/
|
|
2453
|
-
const mask = (source, mask, output, offset, length) => {
|
|
2454
|
-
for (var i = 0; i < length; i++) {
|
|
2455
|
-
output[offset + i] = source[i] ^ mask[i & 3];
|
|
2456
|
-
}
|
|
2457
|
-
};
|
|
2458
|
-
|
|
2459
|
-
/**
|
|
2460
|
-
* Unmasks a buffer using the given mask.
|
|
2461
|
-
*
|
|
2462
|
-
* @param {Buffer} buffer The buffer to unmask
|
|
2463
|
-
* @param {Buffer} mask The mask to use
|
|
2464
|
-
* @public
|
|
2465
|
-
*/
|
|
2466
|
-
const unmask = (buffer, mask) => {
|
|
2467
|
-
// Required until https://github.com/nodejs/node/issues/9006 is resolved.
|
|
2468
|
-
const length = buffer.length;
|
|
2469
|
-
for (var i = 0; i < length; i++) {
|
|
2470
|
-
buffer[i] ^= mask[i & 3];
|
|
2471
|
-
}
|
|
2472
|
-
};
|
|
2473
|
-
|
|
2474
|
-
fallback$1 = { mask, unmask };
|
|
2475
|
-
return fallback$1;
|
|
2476
|
-
}
|
|
2477
|
-
|
|
2478
|
-
var hasRequiredBufferutil;
|
|
2479
|
-
|
|
2480
|
-
function requireBufferutil () {
|
|
2481
|
-
if (hasRequiredBufferutil) return bufferutil.exports;
|
|
2482
|
-
hasRequiredBufferutil = 1;
|
|
2483
|
-
|
|
2484
|
-
try {
|
|
2485
|
-
bufferutil.exports = requireNodeGypBuild()(__dirname);
|
|
2486
|
-
} catch (e) {
|
|
2487
|
-
bufferutil.exports = requireFallback$1();
|
|
2488
|
-
}
|
|
2489
|
-
return bufferutil.exports;
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2492
2229
|
var hasRequiredBufferUtil;
|
|
2493
2230
|
|
|
2494
2231
|
function requireBufferUtil () {
|
|
@@ -2609,7 +2346,7 @@ function requireBufferUtil () {
|
|
|
2609
2346
|
/* istanbul ignore else */
|
|
2610
2347
|
if (!process.env.WS_NO_BUFFER_UTIL) {
|
|
2611
2348
|
try {
|
|
2612
|
-
const bufferUtil$1 =
|
|
2349
|
+
const bufferUtil$1 = require('bufferutil');
|
|
2613
2350
|
|
|
2614
2351
|
bufferUtil.exports.mask = function (source, mask, output, offset, length) {
|
|
2615
2352
|
if (length < 48) _mask(source, mask, output, offset, length);
|
|
@@ -3230,92 +2967,6 @@ function requirePermessageDeflate () {
|
|
|
3230
2967
|
|
|
3231
2968
|
var validation = {exports: {}};
|
|
3232
2969
|
|
|
3233
|
-
var utf8Validate = {exports: {}};
|
|
3234
|
-
|
|
3235
|
-
var fallback;
|
|
3236
|
-
var hasRequiredFallback;
|
|
3237
|
-
|
|
3238
|
-
function requireFallback () {
|
|
3239
|
-
if (hasRequiredFallback) return fallback;
|
|
3240
|
-
hasRequiredFallback = 1;
|
|
3241
|
-
|
|
3242
|
-
/**
|
|
3243
|
-
* Checks if a given buffer contains only correct UTF-8.
|
|
3244
|
-
* Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
|
|
3245
|
-
* Markus Kuhn.
|
|
3246
|
-
*
|
|
3247
|
-
* @param {Buffer} buf The buffer to check
|
|
3248
|
-
* @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
|
|
3249
|
-
* @public
|
|
3250
|
-
*/
|
|
3251
|
-
function isValidUTF8(buf) {
|
|
3252
|
-
const len = buf.length;
|
|
3253
|
-
let i = 0;
|
|
3254
|
-
|
|
3255
|
-
while (i < len) {
|
|
3256
|
-
if ((buf[i] & 0x80) === 0x00) { // 0xxxxxxx
|
|
3257
|
-
i++;
|
|
3258
|
-
} else if ((buf[i] & 0xe0) === 0xc0) { // 110xxxxx 10xxxxxx
|
|
3259
|
-
if (
|
|
3260
|
-
i + 1 === len ||
|
|
3261
|
-
(buf[i + 1] & 0xc0) !== 0x80 ||
|
|
3262
|
-
(buf[i] & 0xfe) === 0xc0 // overlong
|
|
3263
|
-
) {
|
|
3264
|
-
return false;
|
|
3265
|
-
}
|
|
3266
|
-
|
|
3267
|
-
i += 2;
|
|
3268
|
-
} else if ((buf[i] & 0xf0) === 0xe0) { // 1110xxxx 10xxxxxx 10xxxxxx
|
|
3269
|
-
if (
|
|
3270
|
-
i + 2 >= len ||
|
|
3271
|
-
(buf[i + 1] & 0xc0) !== 0x80 ||
|
|
3272
|
-
(buf[i + 2] & 0xc0) !== 0x80 ||
|
|
3273
|
-
buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80 || // overlong
|
|
3274
|
-
buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0 // surrogate (U+D800 - U+DFFF)
|
|
3275
|
-
) {
|
|
3276
|
-
return false;
|
|
3277
|
-
}
|
|
3278
|
-
|
|
3279
|
-
i += 3;
|
|
3280
|
-
} else if ((buf[i] & 0xf8) === 0xf0) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
|
3281
|
-
if (
|
|
3282
|
-
i + 3 >= len ||
|
|
3283
|
-
(buf[i + 1] & 0xc0) !== 0x80 ||
|
|
3284
|
-
(buf[i + 2] & 0xc0) !== 0x80 ||
|
|
3285
|
-
(buf[i + 3] & 0xc0) !== 0x80 ||
|
|
3286
|
-
buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80 || // overlong
|
|
3287
|
-
buf[i] === 0xf4 && buf[i + 1] > 0x8f || buf[i] > 0xf4 // > U+10FFFF
|
|
3288
|
-
) {
|
|
3289
|
-
return false;
|
|
3290
|
-
}
|
|
3291
|
-
|
|
3292
|
-
i += 4;
|
|
3293
|
-
} else {
|
|
3294
|
-
return false;
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
|
|
3298
|
-
return true;
|
|
3299
|
-
}
|
|
3300
|
-
|
|
3301
|
-
fallback = isValidUTF8;
|
|
3302
|
-
return fallback;
|
|
3303
|
-
}
|
|
3304
|
-
|
|
3305
|
-
var hasRequiredUtf8Validate;
|
|
3306
|
-
|
|
3307
|
-
function requireUtf8Validate () {
|
|
3308
|
-
if (hasRequiredUtf8Validate) return utf8Validate.exports;
|
|
3309
|
-
hasRequiredUtf8Validate = 1;
|
|
3310
|
-
|
|
3311
|
-
try {
|
|
3312
|
-
utf8Validate.exports = requireNodeGypBuild()(__dirname);
|
|
3313
|
-
} catch (e) {
|
|
3314
|
-
utf8Validate.exports = requireFallback();
|
|
3315
|
-
}
|
|
3316
|
-
return utf8Validate.exports;
|
|
3317
|
-
}
|
|
3318
|
-
|
|
3319
2970
|
var hasRequiredValidation;
|
|
3320
2971
|
|
|
3321
2972
|
function requireValidation () {
|
|
@@ -3463,7 +3114,7 @@ function requireValidation () {
|
|
|
3463
3114
|
};
|
|
3464
3115
|
} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
|
|
3465
3116
|
try {
|
|
3466
|
-
const isValidUTF8 =
|
|
3117
|
+
const isValidUTF8 = require('utf-8-validate');
|
|
3467
3118
|
|
|
3468
3119
|
validation.exports.isValidUTF8 = function (buf) {
|
|
3469
3120
|
return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
|
@@ -4239,7 +3890,7 @@ function requireSender () {
|
|
|
4239
3890
|
const { randomFillSync } = require$$1;
|
|
4240
3891
|
const {
|
|
4241
3892
|
types: { isUint8Array }
|
|
4242
|
-
} = require$$2
|
|
3893
|
+
} = require$$2;
|
|
4243
3894
|
|
|
4244
3895
|
const PerMessageDeflate = requirePermessageDeflate();
|
|
4245
3896
|
const { EMPTY_BUFFER, kWebSocket, NOOP } = requireConstants();
|
|
@@ -5363,7 +5014,7 @@ function requireWebsocket () {
|
|
|
5363
5014
|
|
|
5364
5015
|
const EventEmitter = require$$0$3;
|
|
5365
5016
|
const https = require$$1$1;
|
|
5366
|
-
const http = require$$2$
|
|
5017
|
+
const http = require$$2$1;
|
|
5367
5018
|
const net$1 = net;
|
|
5368
5019
|
const tls = require$$4;
|
|
5369
5020
|
const { randomBytes, createHash } = require$$1;
|
|
@@ -7032,7 +6683,7 @@ function requireWebsocketServer () {
|
|
|
7032
6683
|
hasRequiredWebsocketServer = 1;
|
|
7033
6684
|
|
|
7034
6685
|
const EventEmitter = require$$0$3;
|
|
7035
|
-
const http = require$$2$
|
|
6686
|
+
const http = require$$2$1;
|
|
7036
6687
|
const { Duplex } = require$$0;
|
|
7037
6688
|
const { createHash } = require$$1;
|
|
7038
6689
|
|
|
@@ -7610,6 +7261,8 @@ class IOWS extends IOCore {
|
|
|
7610
7261
|
close() {
|
|
7611
7262
|
if (this.socket) {
|
|
7612
7263
|
this.socket.removeAllListeners();
|
|
7264
|
+
// Closing a connecting ws can emit an asynchronous error after detachment.
|
|
7265
|
+
this.socket.on('error', () => {});
|
|
7613
7266
|
if (this.socket.readyState !== WebSocket.CLOSED) {
|
|
7614
7267
|
this.socket.close();
|
|
7615
7268
|
}
|
|
@@ -7629,21 +7282,27 @@ class IOWS extends IOCore {
|
|
|
7629
7282
|
|
|
7630
7283
|
createConnection(url) {
|
|
7631
7284
|
// node WebSocket
|
|
7632
|
-
this.socket = new WebSocket(url);
|
|
7633
|
-
this.
|
|
7285
|
+
const socket = this.socket = new WebSocket(url);
|
|
7286
|
+
this._closed = false;
|
|
7634
7287
|
|
|
7635
7288
|
this.socket.onopen = () => {
|
|
7636
|
-
this.socket
|
|
7289
|
+
if (this.socket !== socket) return;
|
|
7290
|
+
socket.on('message', data => {
|
|
7291
|
+
if (this.socket === socket) this.onWebSocketMessage(data);
|
|
7292
|
+
});
|
|
7637
7293
|
this.emit('open');
|
|
7638
7294
|
};
|
|
7639
7295
|
|
|
7640
7296
|
this.socket.onerror = (e) => {
|
|
7297
|
+
if (this.socket !== socket) return;
|
|
7641
7298
|
this.emit('error', e);
|
|
7642
7299
|
};
|
|
7643
7300
|
|
|
7644
7301
|
this.socket.onclose = () => {
|
|
7302
|
+
if (this.socket !== socket) return;
|
|
7645
7303
|
this.emit('close');
|
|
7646
7304
|
};
|
|
7305
|
+
this.stateChange('connecting','connecting');
|
|
7647
7306
|
}
|
|
7648
7307
|
|
|
7649
7308
|
onWebSocketMessage(data) {
|
|
@@ -7762,7 +7421,9 @@ class RemoteCore {
|
|
|
7762
7421
|
static ssid = 1;
|
|
7763
7422
|
|
|
7764
7423
|
setState(state) {
|
|
7424
|
+
const previous = this.state;
|
|
7765
7425
|
this.state = state;
|
|
7426
|
+
if (previous !== state) this.manager.server?.emit('remote:state', this, previous);
|
|
7766
7427
|
if (serverOption.debug.showAuthInfo) {
|
|
7767
7428
|
this.stateLog.push( state + ":" + STATE[ state] );
|
|
7768
7429
|
if( state == STATE.AUTH_RES){
|
|
@@ -7831,6 +7492,8 @@ class RemoteCore {
|
|
|
7831
7492
|
// CongSocket or WebSocket
|
|
7832
7493
|
onSocketMessage(message, isBinary = true) {
|
|
7833
7494
|
|
|
7495
|
+
if (this._closing || this.state === STATE.CLOSED) return;
|
|
7496
|
+
|
|
7834
7497
|
this.receiveMonitor(); // rx-data, ping/pong and timeout check
|
|
7835
7498
|
if (!this.rxQuotaChecker(message)) return
|
|
7836
7499
|
|
|
@@ -7884,10 +7547,11 @@ class RemoteCore {
|
|
|
7884
7547
|
break;
|
|
7885
7548
|
|
|
7886
7549
|
case IOMsg.CID_REQ:
|
|
7887
|
-
if (
|
|
7550
|
+
if (![STATE.SERVER_READY, STATE.AUTH_RES, STATE.AUTH_FAIL, STATE.CID_RES].includes(this.state)) {
|
|
7888
7551
|
// Protocol violation: CID_REQ was sent before receiving the SERVER_READY signal.
|
|
7889
7552
|
console.log('CID_REQ before SERVER_READY');
|
|
7890
7553
|
this.close();
|
|
7554
|
+
return;
|
|
7891
7555
|
}
|
|
7892
7556
|
|
|
7893
7557
|
if (!this.cid) {
|
|
@@ -8007,9 +7671,12 @@ class RemoteCore {
|
|
|
8007
7671
|
// client's auth requst
|
|
8008
7672
|
case it.BohoMsg.AUTH_REQ:
|
|
8009
7673
|
if (!this.manager.authManager) return
|
|
8010
|
-
|
|
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)) {
|
|
8011
7677
|
console.log('protocol error. must called auth_req after server_ready');
|
|
8012
7678
|
this.close();
|
|
7679
|
+
return;
|
|
8013
7680
|
}
|
|
8014
7681
|
this.setState(STATE.AUTH_REQ);
|
|
8015
7682
|
//async
|
|
@@ -8171,7 +7838,7 @@ function getIPv4HexString(ipStr) {
|
|
|
8171
7838
|
}
|
|
8172
7839
|
|
|
8173
7840
|
function getLocalAddress() {
|
|
8174
|
-
const nets =
|
|
7841
|
+
const nets = os.networkInterfaces();
|
|
8175
7842
|
// console.log(nets)
|
|
8176
7843
|
const results = Object.create(null); // Or just '{}', an empty object
|
|
8177
7844
|
let localAddress = '';
|
|
@@ -8358,6 +8025,7 @@ class Remote extends RemoteCore {
|
|
|
8358
8025
|
}
|
|
8359
8026
|
|
|
8360
8027
|
close(terminateNow = false) {
|
|
8028
|
+
this._closing = true;
|
|
8361
8029
|
this.getTraffic();
|
|
8362
8030
|
if (this.socketType === 'websocket') {
|
|
8363
8031
|
if (terminateNow) this.socket.terminate();
|
|
@@ -8623,6 +8291,7 @@ class Manager {
|
|
|
8623
8291
|
if (socket.isAlive === false) {
|
|
8624
8292
|
console.log('## timeout. cid:', remo.cid);
|
|
8625
8293
|
remo.close();
|
|
8294
|
+
return;
|
|
8626
8295
|
}
|
|
8627
8296
|
|
|
8628
8297
|
socket.txCounter++;
|
|
@@ -8662,6 +8331,9 @@ class Manager {
|
|
|
8662
8331
|
|
|
8663
8332
|
removeRemote(remote) {
|
|
8664
8333
|
|
|
8334
|
+
remote._closing = true;
|
|
8335
|
+
remote.setState(STATE.CLOSED);
|
|
8336
|
+
|
|
8665
8337
|
let remoteInfo = `- IP:${remote.ip} #${remote.ssid} cid:${remote.cid} ${remote?.socket.socketType === 'websocket' ? "WS" : "CS"} `;
|
|
8666
8338
|
if (this.connectionLogger) this.connectionLogger.log(remoteInfo);
|
|
8667
8339
|
this.deligateSignal(remote, '@state', 'close');
|
|
@@ -8699,7 +8371,7 @@ class Manager {
|
|
|
8699
8371
|
}
|
|
8700
8372
|
|
|
8701
8373
|
this.remotes.delete(remote);
|
|
8702
|
-
this.cid2remote.delete(remote.cid);
|
|
8374
|
+
if (this.cid2remote.get(remote.cid) === remote) this.cid2remote.delete(remote.cid);
|
|
8703
8375
|
remote = null;
|
|
8704
8376
|
|
|
8705
8377
|
}
|
|
@@ -8729,6 +8401,7 @@ class Manager {
|
|
|
8729
8401
|
let tagLen = buffer.readUint8(1);
|
|
8730
8402
|
let newTagBuf = encoder.encode(newTag);
|
|
8731
8403
|
let newTagLen = newTagBuf.byteLength;
|
|
8404
|
+
if (newTagLen > SIZE_LIMIT.TAG_LEN1) return null;
|
|
8732
8405
|
let payloadCunk = buffer.subarray(2 + tagLen);
|
|
8733
8406
|
let newBuffer = Buffer.concat([Buffer.from([msgType, newTagLen]), newTagBuf, payloadCunk]);
|
|
8734
8407
|
return newBuffer
|
|
@@ -8766,6 +8439,7 @@ class Manager {
|
|
|
8766
8439
|
}
|
|
8767
8440
|
|
|
8768
8441
|
sender(tag, remote, message) {
|
|
8442
|
+
if (encoder.encode(tag).byteLength > SIZE_LIMIT.TAG_LEN1) return ['err', 'Tag exceeds 255 UTF-8 bytes']
|
|
8769
8443
|
if (serverOption.membersOnly && !remote.boho.isAuthorized) {
|
|
8770
8444
|
// console.log("### server reject client signal reason: [membersOnly]" ,tag, remote.cid )
|
|
8771
8445
|
remote.send(Buffer.from([IOMsg.AUTH_CLEAR]));
|
|
@@ -8782,6 +8456,7 @@ class Manager {
|
|
|
8782
8456
|
// modify signalpack with cid_appneded tag.
|
|
8783
8457
|
tag = remote.cid + tag;
|
|
8784
8458
|
message = this.getNewSignalTagMessage(message, tag);
|
|
8459
|
+
if (!message) return ['err', 'CID-prefixed tag exceeds 255 UTF-8 bytes']
|
|
8785
8460
|
|
|
8786
8461
|
} else if (cidIndex > 0) {
|
|
8787
8462
|
// uni-cast.
|
|
@@ -8791,6 +8466,7 @@ class Manager {
|
|
|
8791
8466
|
let ommitCIdTag = '@' + tag.split('@')[1];
|
|
8792
8467
|
// console.log('uni-cast tag change from', tag, 'to' , ommitCIdTag )
|
|
8793
8468
|
message = this.getNewSignalTagMessage(message, ommitCIdTag);
|
|
8469
|
+
if (!message) return ['err', 'Tag exceeds 255 UTF-8 bytes']
|
|
8794
8470
|
// console.log(`origin tag: ${tag} omitTag: ${this.getSignalTag(message)}`)
|
|
8795
8471
|
this.cid2remote.get(targetCId).send_enc_mode(message);
|
|
8796
8472
|
return ['ok', 1]
|
|
@@ -9267,6 +8943,8 @@ class BohoAuth {
|
|
|
9267
8943
|
}
|
|
9268
8944
|
|
|
9269
8945
|
send_auth_fail(peer, reason) {
|
|
8946
|
+
if (peer._closing || peer.state === STATE.CLOSED) return;
|
|
8947
|
+
peer.boho.isAuthorized = false;
|
|
9270
8948
|
if (this.authLogger) {
|
|
9271
8949
|
let peerInfo = `FAIL #${peer.ssid} reason:${reason} `;
|
|
9272
8950
|
this.authLogger.log(peerInfo);
|
|
@@ -9275,7 +8953,9 @@ class BohoAuth {
|
|
|
9275
8953
|
peer.setState(STATE.AUTH_FAIL);
|
|
9276
8954
|
// add some delay time.
|
|
9277
8955
|
setTimeout(e => {
|
|
9278
|
-
peer.
|
|
8956
|
+
if (!peer._closing && peer.state === STATE.AUTH_FAIL) {
|
|
8957
|
+
peer.send(Buffer.from([it.BohoMsg.AUTH_FAIL]));
|
|
8958
|
+
}
|
|
9279
8959
|
}, serverOption.auth.delay_auth_fail);
|
|
9280
8960
|
}
|
|
9281
8961
|
|
|
@@ -9298,6 +8978,7 @@ class BohoAuth {
|
|
|
9298
8978
|
|
|
9299
8979
|
//2. get key of id from DB
|
|
9300
8980
|
let authInfo = await this.keyProvider.getAuth(id);
|
|
8981
|
+
if (peer._closing || peer.state === STATE.CLOSED) return;
|
|
9301
8982
|
if (!authInfo) {
|
|
9302
8983
|
this.send_auth_fail(peer, 'NO ID:' + id);
|
|
9303
8984
|
return
|
|
@@ -9330,33 +9011,31 @@ class BohoAuth {
|
|
|
9330
9011
|
//4. get info
|
|
9331
9012
|
|
|
9332
9013
|
//5. check duplicate login.
|
|
9333
|
-
if (peer.manager.cid2remote.has(authInfo.cid)) {
|
|
9014
|
+
if (peer.manager.cid2remote.has(authInfo.cid) && peer.manager.cid2remote.get(authInfo.cid) !== peer) {
|
|
9334
9015
|
let old = peer.manager.cid2remote.get(authInfo.cid);
|
|
9335
9016
|
console.log('[WARN]DUPLICATE_LOGIN detected.', old.cid);
|
|
9336
9017
|
old.ping(); // check the connection.
|
|
9337
|
-
if (old == peer) {
|
|
9338
|
-
console.log('## trying to RELOGIN after login.');
|
|
9339
|
-
return
|
|
9340
|
-
}
|
|
9341
9018
|
|
|
9342
9019
|
let authClearSignal = $$1.pack(
|
|
9343
9020
|
$$1.MB('#MsgType', '8', IOMsg.AUTH_CLEAR),
|
|
9344
9021
|
$$1.MB('#reason', 'duplicate login.')
|
|
9345
9022
|
);
|
|
9346
9023
|
if (this.keepOldConnection) { // default true
|
|
9024
|
+
peer.boho.isAuthorized = false;
|
|
9347
9025
|
// keep old connection. reject new connection by sending auth_fail signal.
|
|
9348
9026
|
// peer.send(authClearSignal)
|
|
9349
9027
|
if( peer.socketType == 'websocket'){
|
|
9350
9028
|
this.send_auth_fail(peer, 'duplicate login');
|
|
9351
9029
|
}else {
|
|
9030
|
+
peer.setState(STATE.AUTH_FAIL);
|
|
9352
9031
|
peer.close(); //arduino
|
|
9353
9032
|
}
|
|
9354
9033
|
} else {
|
|
9355
9034
|
// accept new connection. stop the old connection by sending auth_clear signal.
|
|
9356
9035
|
old.send(authClearSignal);
|
|
9357
|
-
|
|
9036
|
+
old.close();
|
|
9358
9037
|
}
|
|
9359
|
-
return
|
|
9038
|
+
if (this.keepOldConnection) return
|
|
9360
9039
|
}
|
|
9361
9040
|
|
|
9362
9041
|
//6. delete current (or anonymouse)cid if exist.
|