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