iosignal 5.3.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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$2 = require('http');
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$1 = require('util');
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 = "5.3.0";
19
+ var version$1 = "6.1.0";
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
@@ -1308,10 +1319,10 @@ class IOCore extends EventEmitter {
1308
1319
  switch (payloadType) {
1309
1320
 
1310
1321
  case PAYLOAD_TYPE.EMPTY:
1311
- if (tag.indexOf('@') === 0) this.emit('@', tag, null);
1322
+ if (tag.indexOf('@') === 0) this.emit('@', tag);
1312
1323
  else {
1313
- this.emit(tag, tag, null);
1314
- this.emit('message', tag, null);
1324
+ this.emit(tag, tag);
1325
+ this.emit('message', tag);
1315
1326
  }
1316
1327
  break;
1317
1328
 
@@ -1595,6 +1606,7 @@ class IOCore extends EventEmitter {
1595
1606
  */
1596
1607
  signal(tag, ...args) {
1597
1608
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1609
+ if (tag.startsWith('@') && this.cid) encodeTag(this.cid + tag);
1598
1610
  let signalPack = getSignalPack(tag, ...args);
1599
1611
  this.send_enc_mode(signalPack);
1600
1612
  }
@@ -1618,9 +1630,9 @@ class IOCore extends EventEmitter {
1618
1630
  */
1619
1631
  signal_e2e(tag, data, key) {
1620
1632
 
1633
+ const tagEncoded = encodeTag(tag);
1634
+ if (tag.startsWith('@') && this.cid) encodeTag(this.cid + tag);
1621
1635
  if( !this.boho.isAuthorized ) return;
1622
- if (typeof tag !== 'string') throw TypeError('tag should be string.')
1623
- let tagEncoded = encoder$1.encode(tag);
1624
1636
  let dataPack = $$1.B8(data);
1625
1637
 
1626
1638
  //encrypt payload area with key
@@ -1705,39 +1717,37 @@ class IOCore extends EventEmitter {
1705
1717
  * @throws {TypeError} If tag is not a string or exceeds length limit.
1706
1718
  */
1707
1719
  subscribe(tag) {
1708
- if (typeof tag !== 'string') throw TypeError('tag should be string.')
1709
- if (tag.length > SIZE_LIMIT.TAG_LEN1) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN1)
1710
-
1711
- try {
1712
- let tagEncoded = encoder$1.encode(tag);
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
-
1720
+ const tagEncoded = encodeTag(tag);
1721
+ this.send_enc_mode(Buffer$1.concat([
1722
+ $$1.NB('8', IOMsg.SUBSCRIBE),
1723
+ $$1.NB('8', tagEncoded.byteLength),
1724
+ tagEncoded]));
1720
1725
  }
1721
1726
 
1722
1727
 
1723
1728
  /**
1724
- * Subscribes stored channels.
1725
- * called client state become 'ready'
1729
+ * Sends subscriptions stored by listen()/link() on each CID-ready transition,
1730
+ * including reconnection. This automates subscription setup for simple clients.
1726
1731
  */
1727
1732
  subscribe_channels() {
1728
- if (this.state !== STATE.READY) return
1729
- if (this.channels.size == 0) return
1730
- let tag = Array.from(this.channels).join(',');
1731
-
1732
- try {
1733
- let tagEncoded = encoder$1.encode(tag);
1734
- this.send_enc_mode(
1735
- Buffer$1.concat([
1736
- $$1.NB('8', IOMsg.SUBSCRIBE),
1737
- $$1.NB('8', tagEncoded.byteLength),
1738
- tagEncoded]));
1739
- } catch (error) { }
1740
-
1733
+ if (this.state !== STATE.READY || this.channels.size === 0) return
1734
+ // Validate the entire list first, then split only at tag boundaries.
1735
+ // Preserve comma-separated entries accepted by existing registration APIs.
1736
+ const tags = Array.from(this.channels).join(',').split(',');
1737
+ const sizes = tags.map(tag => encodeTag(tag).byteLength);
1738
+ const batches = [];
1739
+ let batch = [], bytes = 0;
1740
+ tags.forEach((tag, i) => {
1741
+ if (batch.length && bytes + 1 + sizes[i] > SIZE_LIMIT.TAG_LEN1) {
1742
+ batches.push(batch.join(','));
1743
+ batch = [];
1744
+ bytes = 0;
1745
+ }
1746
+ bytes += (batch.length ? 1 : 0) + sizes[i];
1747
+ batch.push(tag);
1748
+ });
1749
+ if (batch.length) batches.push(batch.join(','));
1750
+ batches.forEach(tag => this.subscribe(tag));
1741
1751
  }
1742
1752
 
1743
1753
  /**
@@ -1746,7 +1756,7 @@ class IOCore extends EventEmitter {
1746
1756
  * @throws {TypeError} If tag is not a string or exceeds length limit.
1747
1757
  */
1748
1758
  unsubscribe(tag = "") {
1749
- if (typeof tag !== 'string') throw TypeError('tag should be string.')
1759
+ const tagEncoded = encodeTag(tag);
1750
1760
 
1751
1761
  if (tag == "") { // blank tag means unsubscribe all
1752
1762
  this.channels.clear();
@@ -1757,8 +1767,6 @@ class IOCore extends EventEmitter {
1757
1767
  });
1758
1768
  }
1759
1769
 
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
1770
 
1763
1771
  this.send_enc_mode(Buffer$1.concat([
1764
1772
  $$1.NB('8', IOMsg.UNSUBSCRIBE),
@@ -1768,22 +1776,28 @@ class IOCore extends EventEmitter {
1768
1776
 
1769
1777
 
1770
1778
  /**
1771
- * Listens for signals on a specific tag.
1779
+ * Convenience API for simple clients (for example, CLI tools): register a
1780
+ * tag handler once and remember its subscription in channels. Register before
1781
+ * connection readiness; the CID-ready flow subscribes on initial connection
1782
+ * and again after reconnect, without application-level ready/subscribe code.
1783
+ * This does not send a subscription immediately, even if already ready.
1784
+ * For precise subscription/send ordering or dynamic subscriptions, use
1785
+ * on() with subscribe() in a ready handler instead. Direct signals use on('@').
1772
1786
  * @param {string} tag - The tag to listen on.
1773
1787
  * @param {Function} handler - The callback function to handle the signal.
1774
1788
  * @throws {TypeError} If tag is not a string, handler is not a function, or tag length is invalid.
1775
1789
  */
1776
1790
  listen(tag, handler) {
1777
1791
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
1778
- if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
1792
+ encodeTag(tag, false);
1779
1793
  if (typeof handler !== 'function') throw TypeError('handler is not a function.')
1780
1794
 
1781
1795
  if (tag.indexOf('@') !== 0) {
1782
1796
  this.channels.add(tag);
1783
1797
  }
1784
1798
  this.on(tag, handler);
1785
- // do not subscribe now.
1786
- // will subscribe when io state is 'ready'. (receive CID_RES from server)
1799
+ // Subscribe from the CID-ready flow, initially and after reconnect.
1800
+ // Keep registration separate from immediate subscription/send ordering.
1787
1801
 
1788
1802
  }
1789
1803
 
@@ -1799,7 +1813,7 @@ class IOCore extends EventEmitter {
1799
1813
  link(to, tag, handler) {
1800
1814
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1801
1815
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
1802
- if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
1816
+ encodeTag(tag, false);
1803
1817
  if (typeof handler !== 'function') throw TypeError('handler is not a function.')
1804
1818
 
1805
1819
  if (tag.indexOf('@') !== 0) {
@@ -1830,7 +1844,7 @@ class IOCore extends EventEmitter {
1830
1844
  unlink(to, tag) {
1831
1845
  if (typeof to !== 'string') throw TypeError('to(local link target) is not a string.')
1832
1846
  if (typeof tag !== 'string') throw TypeError('tag is not a string.')
1833
- if (tag.length > 255 || tag.length == 0) throw TypeError('tag string length range: 1~255')
1847
+ encodeTag(tag, false);
1834
1848
 
1835
1849
  const linkSet = this.linkMap.get(to);
1836
1850
  if (!linkSet || !linkSet.has(tag)) return;
@@ -2195,300 +2209,6 @@ function requireConstants () {
2195
2209
  return constants;
2196
2210
  }
2197
2211
 
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
2212
  var hasRequiredBufferUtil;
2493
2213
 
2494
2214
  function requireBufferUtil () {
@@ -2609,7 +2329,7 @@ function requireBufferUtil () {
2609
2329
  /* istanbul ignore else */
2610
2330
  if (!process.env.WS_NO_BUFFER_UTIL) {
2611
2331
  try {
2612
- const bufferUtil$1 = requireBufferutil();
2332
+ const bufferUtil$1 = require('bufferutil');
2613
2333
 
2614
2334
  bufferUtil.exports.mask = function (source, mask, output, offset, length) {
2615
2335
  if (length < 48) _mask(source, mask, output, offset, length);
@@ -3230,92 +2950,6 @@ function requirePermessageDeflate () {
3230
2950
 
3231
2951
  var validation = {exports: {}};
3232
2952
 
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
2953
  var hasRequiredValidation;
3320
2954
 
3321
2955
  function requireValidation () {
@@ -3463,7 +3097,7 @@ function requireValidation () {
3463
3097
  };
3464
3098
  } /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
3465
3099
  try {
3466
- const isValidUTF8 = requireUtf8Validate();
3100
+ const isValidUTF8 = require('utf-8-validate');
3467
3101
 
3468
3102
  validation.exports.isValidUTF8 = function (buf) {
3469
3103
  return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
@@ -4239,7 +3873,7 @@ function requireSender () {
4239
3873
  const { randomFillSync } = require$$1;
4240
3874
  const {
4241
3875
  types: { isUint8Array }
4242
- } = require$$2$1;
3876
+ } = require$$2;
4243
3877
 
4244
3878
  const PerMessageDeflate = requirePermessageDeflate();
4245
3879
  const { EMPTY_BUFFER, kWebSocket, NOOP } = requireConstants();
@@ -5363,7 +4997,7 @@ function requireWebsocket () {
5363
4997
 
5364
4998
  const EventEmitter = require$$0$3;
5365
4999
  const https = require$$1$1;
5366
- const http = require$$2$2;
5000
+ const http = require$$2$1;
5367
5001
  const net$1 = net;
5368
5002
  const tls = require$$4;
5369
5003
  const { randomBytes, createHash } = require$$1;
@@ -7032,7 +6666,7 @@ function requireWebsocketServer () {
7032
6666
  hasRequiredWebsocketServer = 1;
7033
6667
 
7034
6668
  const EventEmitter = require$$0$3;
7035
- const http = require$$2$2;
6669
+ const http = require$$2$1;
7036
6670
  const { Duplex } = require$$0;
7037
6671
  const { createHash } = require$$1;
7038
6672
 
@@ -8171,7 +7805,7 @@ function getIPv4HexString(ipStr) {
8171
7805
  }
8172
7806
 
8173
7807
  function getLocalAddress() {
8174
- const nets = require$$2.networkInterfaces();
7808
+ const nets = os.networkInterfaces();
8175
7809
  // console.log(nets)
8176
7810
  const results = Object.create(null); // Or just '{}', an empty object
8177
7811
  let localAddress = '';
@@ -8699,7 +8333,7 @@ class Manager {
8699
8333
  }
8700
8334
 
8701
8335
  this.remotes.delete(remote);
8702
- this.cid2remote.delete(remote.cid);
8336
+ if (this.cid2remote.get(remote.cid) === remote) this.cid2remote.delete(remote.cid);
8703
8337
  remote = null;
8704
8338
 
8705
8339
  }
@@ -8729,6 +8363,7 @@ class Manager {
8729
8363
  let tagLen = buffer.readUint8(1);
8730
8364
  let newTagBuf = encoder.encode(newTag);
8731
8365
  let newTagLen = newTagBuf.byteLength;
8366
+ if (newTagLen > SIZE_LIMIT.TAG_LEN1) return null;
8732
8367
  let payloadCunk = buffer.subarray(2 + tagLen);
8733
8368
  let newBuffer = Buffer.concat([Buffer.from([msgType, newTagLen]), newTagBuf, payloadCunk]);
8734
8369
  return newBuffer
@@ -8766,6 +8401,7 @@ class Manager {
8766
8401
  }
8767
8402
 
8768
8403
  sender(tag, remote, message) {
8404
+ if (encoder.encode(tag).byteLength > SIZE_LIMIT.TAG_LEN1) return ['err', 'Tag exceeds 255 UTF-8 bytes']
8769
8405
  if (serverOption.membersOnly && !remote.boho.isAuthorized) {
8770
8406
  // console.log("### server reject client signal reason: [membersOnly]" ,tag, remote.cid )
8771
8407
  remote.send(Buffer.from([IOMsg.AUTH_CLEAR]));
@@ -8782,6 +8418,7 @@ class Manager {
8782
8418
  // modify signalpack with cid_appneded tag.
8783
8419
  tag = remote.cid + tag;
8784
8420
  message = this.getNewSignalTagMessage(message, tag);
8421
+ if (!message) return ['err', 'CID-prefixed tag exceeds 255 UTF-8 bytes']
8785
8422
 
8786
8423
  } else if (cidIndex > 0) {
8787
8424
  // uni-cast.
@@ -8791,6 +8428,7 @@ class Manager {
8791
8428
  let ommitCIdTag = '@' + tag.split('@')[1];
8792
8429
  // console.log('uni-cast tag change from', tag, 'to' , ommitCIdTag )
8793
8430
  message = this.getNewSignalTagMessage(message, ommitCIdTag);
8431
+ if (!message) return ['err', 'Tag exceeds 255 UTF-8 bytes']
8794
8432
  // console.log(`origin tag: ${tag} omitTag: ${this.getSignalTag(message)}`)
8795
8433
  this.cid2remote.get(targetCId).send_enc_mode(message);
8796
8434
  return ['ok', 1]
@@ -9267,6 +8905,7 @@ class BohoAuth {
9267
8905
  }
9268
8906
 
9269
8907
  send_auth_fail(peer, reason) {
8908
+ peer.boho.isAuthorized = false;
9270
8909
  if (this.authLogger) {
9271
8910
  let peerInfo = `FAIL #${peer.ssid} reason:${reason} `;
9272
8911
  this.authLogger.log(peerInfo);
@@ -9344,6 +8983,7 @@ class BohoAuth {
9344
8983
  $$1.MB('#reason', 'duplicate login.')
9345
8984
  );
9346
8985
  if (this.keepOldConnection) { // default true
8986
+ peer.boho.isAuthorized = false;
9347
8987
  // keep old connection. reject new connection by sending auth_fail signal.
9348
8988
  // peer.send(authClearSignal)
9349
8989
  if( peer.socketType == 'websocket'){
@@ -9354,9 +8994,9 @@ class BohoAuth {
9354
8994
  } else {
9355
8995
  // accept new connection. stop the old connection by sending auth_clear signal.
9356
8996
  old.send(authClearSignal);
9357
- peer.close();
8997
+ old.close();
9358
8998
  }
9359
- return
8999
+ if (this.keepOldConnection) return
9360
9000
  }
9361
9001
 
9362
9002
  //6. delete current (or anonymouse)cid if exist.