@babylonjs/inspector 9.5.0 → 9.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/inspector-bridge.mjs +1604 -973
- package/bin/inspector-cli.mjs +1395 -1372
- package/lib/components/properties/materials/openpbrMaterialProperties.d.ts +8 -0
- package/lib/{extensionsListService-BKejb6t7.js → extensionsListService-C33SU1_a.js} +2 -2
- package/lib/{extensionsListService-BKejb6t7.js.map → extensionsListService-C33SU1_a.js.map} +1 -1
- package/lib/{index-BMRc-fS9.js → index-D0JXVQQf.js} +108 -80
- package/lib/{index-BMRc-fS9.js.map → index-D0JXVQQf.js.map} +1 -1
- package/lib/index.js +1 -1
- package/lib/{quickCreateToolsService-ACqRLMi-.js → quickCreateToolsService-pBNUavZe.js} +2 -2
- package/lib/{quickCreateToolsService-ACqRLMi-.js.map → quickCreateToolsService-pBNUavZe.js.map} +1 -1
- package/lib/{reflectorService-rMnq6uTv.js → reflectorService-CAi2NPRy.js} +2 -2
- package/lib/{reflectorService-rMnq6uTv.js.map → reflectorService-CAi2NPRy.js.map} +1 -1
- package/package.json +1 -1
package/bin/inspector-bridge.mjs
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import require$$7, { fileURLToPath } from 'url';
|
|
2
|
-
import require$$0$
|
|
3
|
-
import require$$1$
|
|
2
|
+
import require$$0$4 from 'events';
|
|
3
|
+
import require$$1$2 from 'https';
|
|
4
4
|
import require$$2$1 from 'http';
|
|
5
5
|
import require$$3 from 'net';
|
|
6
6
|
import require$$4 from 'tls';
|
|
7
|
-
import require$$
|
|
8
|
-
import require$$0$
|
|
7
|
+
import require$$1$1 from 'crypto';
|
|
8
|
+
import require$$0$3 from 'stream';
|
|
9
9
|
import require$$0$1 from 'zlib';
|
|
10
10
|
import require$$0, { readFileSync, existsSync } from 'fs';
|
|
11
11
|
import require$$1, { join, dirname } from 'path';
|
|
12
12
|
import require$$2 from 'os';
|
|
13
|
+
import require$$0$2 from 'buffer';
|
|
13
14
|
|
|
14
15
|
function getDefaultExportFromCjs (x) {
|
|
15
16
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
@@ -17,12 +18,21 @@ function getDefaultExportFromCjs (x) {
|
|
|
17
18
|
|
|
18
19
|
var bufferUtil$1 = {exports: {}};
|
|
19
20
|
|
|
21
|
+
const BINARY_TYPES$2 = ['nodebuffer', 'arraybuffer', 'fragments'];
|
|
22
|
+
const hasBlob$1 = typeof Blob !== 'undefined';
|
|
23
|
+
|
|
24
|
+
if (hasBlob$1) BINARY_TYPES$2.push('blob');
|
|
25
|
+
|
|
20
26
|
var constants = {
|
|
21
|
-
BINARY_TYPES:
|
|
27
|
+
BINARY_TYPES: BINARY_TYPES$2,
|
|
28
|
+
CLOSE_TIMEOUT: 30000,
|
|
29
|
+
EMPTY_BUFFER: Buffer.alloc(0),
|
|
22
30
|
GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
|
|
31
|
+
hasBlob: hasBlob$1,
|
|
32
|
+
kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),
|
|
33
|
+
kListener: Symbol('kListener'),
|
|
23
34
|
kStatusCode: Symbol('status-code'),
|
|
24
35
|
kWebSocket: Symbol('websocket'),
|
|
25
|
-
EMPTY_BUFFER: Buffer.alloc(0),
|
|
26
36
|
NOOP: () => {}
|
|
27
37
|
};
|
|
28
38
|
|
|
@@ -320,8 +330,13 @@ function requireBufferutil () {
|
|
|
320
330
|
return bufferutil.exports;
|
|
321
331
|
}
|
|
322
332
|
|
|
333
|
+
var unmask$1;
|
|
334
|
+
var mask;
|
|
335
|
+
|
|
323
336
|
const { EMPTY_BUFFER: EMPTY_BUFFER$3 } = constants;
|
|
324
337
|
|
|
338
|
+
const FastBuffer$2 = Buffer[Symbol.species];
|
|
339
|
+
|
|
325
340
|
/**
|
|
326
341
|
* Merges an array of buffers into a new buffer.
|
|
327
342
|
*
|
|
@@ -343,7 +358,9 @@ function concat$1(list, totalLength) {
|
|
|
343
358
|
offset += buf.length;
|
|
344
359
|
}
|
|
345
360
|
|
|
346
|
-
if (offset < totalLength)
|
|
361
|
+
if (offset < totalLength) {
|
|
362
|
+
return new FastBuffer$2(target.buffer, target.byteOffset, offset);
|
|
363
|
+
}
|
|
347
364
|
|
|
348
365
|
return target;
|
|
349
366
|
}
|
|
@@ -372,9 +389,7 @@ function _mask(source, mask, output, offset, length) {
|
|
|
372
389
|
* @public
|
|
373
390
|
*/
|
|
374
391
|
function _unmask(buffer, mask) {
|
|
375
|
-
|
|
376
|
-
const length = buffer.length;
|
|
377
|
-
for (let i = 0; i < length; i++) {
|
|
392
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
378
393
|
buffer[i] ^= mask[i & 3];
|
|
379
394
|
}
|
|
380
395
|
}
|
|
@@ -387,11 +402,11 @@ function _unmask(buffer, mask) {
|
|
|
387
402
|
* @public
|
|
388
403
|
*/
|
|
389
404
|
function toArrayBuffer$1(buf) {
|
|
390
|
-
if (buf.
|
|
405
|
+
if (buf.length === buf.buffer.byteLength) {
|
|
391
406
|
return buf.buffer;
|
|
392
407
|
}
|
|
393
408
|
|
|
394
|
-
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.
|
|
409
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
|
|
395
410
|
}
|
|
396
411
|
|
|
397
412
|
/**
|
|
@@ -410,9 +425,9 @@ function toBuffer$2(data) {
|
|
|
410
425
|
let buf;
|
|
411
426
|
|
|
412
427
|
if (data instanceof ArrayBuffer) {
|
|
413
|
-
buf =
|
|
428
|
+
buf = new FastBuffer$2(data);
|
|
414
429
|
} else if (ArrayBuffer.isView(data)) {
|
|
415
|
-
buf =
|
|
430
|
+
buf = new FastBuffer$2(data.buffer, data.byteOffset, data.byteLength);
|
|
416
431
|
} else {
|
|
417
432
|
buf = Buffer.from(data);
|
|
418
433
|
toBuffer$2.readOnly = false;
|
|
@@ -421,31 +436,31 @@ function toBuffer$2(data) {
|
|
|
421
436
|
return buf;
|
|
422
437
|
}
|
|
423
438
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
439
|
+
bufferUtil$1.exports = {
|
|
440
|
+
concat: concat$1,
|
|
441
|
+
mask: _mask,
|
|
442
|
+
toArrayBuffer: toArrayBuffer$1,
|
|
443
|
+
toBuffer: toBuffer$2,
|
|
444
|
+
unmask: _unmask
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
/* istanbul ignore else */
|
|
448
|
+
if (!process.env.WS_NO_BUFFER_UTIL) {
|
|
449
|
+
try {
|
|
450
|
+
const bufferUtil = requireBufferutil();
|
|
427
451
|
|
|
428
|
-
|
|
429
|
-
concat: concat$1,
|
|
430
|
-
mask(source, mask, output, offset, length) {
|
|
452
|
+
mask = bufferUtil$1.exports.mask = function (source, mask, output, offset, length) {
|
|
431
453
|
if (length < 48) _mask(source, mask, output, offset, length);
|
|
432
|
-
else
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
unmask(buffer, mask) {
|
|
454
|
+
else bufferUtil.mask(source, mask, output, offset, length);
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
unmask$1 = bufferUtil$1.exports.unmask = function (buffer, mask) {
|
|
437
458
|
if (buffer.length < 32) _unmask(buffer, mask);
|
|
438
|
-
else
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
concat: concat$1,
|
|
444
|
-
mask: _mask,
|
|
445
|
-
toArrayBuffer: toArrayBuffer$1,
|
|
446
|
-
toBuffer: toBuffer$2,
|
|
447
|
-
unmask: _unmask
|
|
448
|
-
};
|
|
459
|
+
else bufferUtil.unmask(buffer, mask);
|
|
460
|
+
};
|
|
461
|
+
} catch (e) {
|
|
462
|
+
// Continue regardless of the error.
|
|
463
|
+
}
|
|
449
464
|
}
|
|
450
465
|
|
|
451
466
|
var bufferUtilExports = bufferUtil$1.exports;
|
|
@@ -508,14 +523,15 @@ const zlib = require$$0$1;
|
|
|
508
523
|
|
|
509
524
|
const bufferUtil = bufferUtilExports;
|
|
510
525
|
const Limiter = limiter;
|
|
511
|
-
const { kStatusCode: kStatusCode$2
|
|
526
|
+
const { kStatusCode: kStatusCode$2 } = constants;
|
|
512
527
|
|
|
528
|
+
const FastBuffer$1 = Buffer[Symbol.species];
|
|
513
529
|
const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
|
|
514
530
|
const kPerMessageDeflate = Symbol('permessage-deflate');
|
|
515
531
|
const kTotalLength = Symbol('total-length');
|
|
516
532
|
const kCallback = Symbol('callback');
|
|
517
533
|
const kBuffers = Symbol('buffers');
|
|
518
|
-
const kError = Symbol('error');
|
|
534
|
+
const kError$1 = Symbol('error');
|
|
519
535
|
|
|
520
536
|
//
|
|
521
537
|
// We limit zlib concurrency, which prevents severe memory fragmentation
|
|
@@ -534,32 +550,32 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
534
550
|
* Creates a PerMessageDeflate instance.
|
|
535
551
|
*
|
|
536
552
|
* @param {Object} [options] Configuration options
|
|
537
|
-
* @param {Boolean} [options.
|
|
538
|
-
*
|
|
553
|
+
* @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
|
|
554
|
+
* for, or request, a custom client window size
|
|
539
555
|
* @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
|
|
540
556
|
* acknowledge disabling of client context takeover
|
|
557
|
+
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
|
|
558
|
+
* calls to zlib
|
|
559
|
+
* @param {Boolean} [options.isServer=false] Create the instance in either
|
|
560
|
+
* server or client mode
|
|
561
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
541
562
|
* @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
|
|
542
563
|
* use of a custom server window size
|
|
543
|
-
* @param {
|
|
544
|
-
*
|
|
564
|
+
* @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
|
|
565
|
+
* disabling of server context takeover
|
|
566
|
+
* @param {Number} [options.threshold=1024] Size (in bytes) below which
|
|
567
|
+
* messages should not be compressed if context takeover is disabled
|
|
545
568
|
* @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
|
|
546
569
|
* deflate
|
|
547
570
|
* @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
|
|
548
571
|
* inflate
|
|
549
|
-
* @param {Number} [options.threshold=1024] Size (in bytes) below which
|
|
550
|
-
* messages should not be compressed
|
|
551
|
-
* @param {Number} [options.concurrencyLimit=10] The number of concurrent
|
|
552
|
-
* calls to zlib
|
|
553
|
-
* @param {Boolean} [isServer=false] Create the instance in either server or
|
|
554
|
-
* client mode
|
|
555
|
-
* @param {Number} [maxPayload=0] The maximum allowed message length
|
|
556
572
|
*/
|
|
557
|
-
constructor(options
|
|
558
|
-
this._maxPayload = maxPayload | 0;
|
|
573
|
+
constructor(options) {
|
|
559
574
|
this._options = options || {};
|
|
560
575
|
this._threshold =
|
|
561
576
|
this._options.threshold !== undefined ? this._options.threshold : 1024;
|
|
562
|
-
this.
|
|
577
|
+
this._maxPayload = this._options.maxPayload | 0;
|
|
578
|
+
this._isServer = !!this._options.isServer;
|
|
563
579
|
this._deflate = null;
|
|
564
580
|
this._inflate = null;
|
|
565
581
|
|
|
@@ -817,7 +833,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
817
833
|
/**
|
|
818
834
|
* Compress data. Concurrency limited.
|
|
819
835
|
*
|
|
820
|
-
* @param {Buffer} data Data to compress
|
|
836
|
+
* @param {(Buffer|String)} data Data to compress
|
|
821
837
|
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
|
822
838
|
* @param {Function} callback Callback
|
|
823
839
|
* @public
|
|
@@ -866,7 +882,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
866
882
|
if (fin) this._inflate.write(TRAILER);
|
|
867
883
|
|
|
868
884
|
this._inflate.flush(() => {
|
|
869
|
-
const err = this._inflate[kError];
|
|
885
|
+
const err = this._inflate[kError$1];
|
|
870
886
|
|
|
871
887
|
if (err) {
|
|
872
888
|
this._inflate.close();
|
|
@@ -899,7 +915,7 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
899
915
|
/**
|
|
900
916
|
* Compress data.
|
|
901
917
|
*
|
|
902
|
-
* @param {Buffer} data Data to compress
|
|
918
|
+
* @param {(Buffer|String)} data Data to compress
|
|
903
919
|
* @param {Boolean} fin Specifies whether or not this is the last fragment
|
|
904
920
|
* @param {Function} callback Callback
|
|
905
921
|
* @private
|
|
@@ -922,13 +938,6 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
922
938
|
this._deflate[kTotalLength] = 0;
|
|
923
939
|
this._deflate[kBuffers] = [];
|
|
924
940
|
|
|
925
|
-
//
|
|
926
|
-
// An `'error'` event is emitted, only on Node.js < 10.0.0, if the
|
|
927
|
-
// `zlib.DeflateRaw` instance is closed while data is being processed.
|
|
928
|
-
// This can happen if `PerMessageDeflate#cleanup()` is called at the wrong
|
|
929
|
-
// time due to an abnormal WebSocket closure.
|
|
930
|
-
//
|
|
931
|
-
this._deflate.on('error', NOOP$1);
|
|
932
941
|
this._deflate.on('data', deflateOnData);
|
|
933
942
|
}
|
|
934
943
|
|
|
@@ -948,7 +957,9 @@ let PerMessageDeflate$4 = class PerMessageDeflate {
|
|
|
948
957
|
this._deflate[kTotalLength]
|
|
949
958
|
);
|
|
950
959
|
|
|
951
|
-
if (fin)
|
|
960
|
+
if (fin) {
|
|
961
|
+
data = new FastBuffer$1(data.buffer, data.byteOffset, data.length - 4);
|
|
962
|
+
}
|
|
952
963
|
|
|
953
964
|
//
|
|
954
965
|
// Ensure that the callback will not be called again in
|
|
@@ -998,10 +1009,18 @@ function inflateOnData(chunk) {
|
|
|
998
1009
|
return;
|
|
999
1010
|
}
|
|
1000
1011
|
|
|
1001
|
-
this[kError] = new RangeError('Max payload size exceeded');
|
|
1002
|
-
this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
|
|
1003
|
-
this[kError][kStatusCode$2] = 1009;
|
|
1012
|
+
this[kError$1] = new RangeError('Max payload size exceeded');
|
|
1013
|
+
this[kError$1].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
|
|
1014
|
+
this[kError$1][kStatusCode$2] = 1009;
|
|
1004
1015
|
this.removeListener('data', inflateOnData);
|
|
1016
|
+
|
|
1017
|
+
//
|
|
1018
|
+
// The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the
|
|
1019
|
+
// fact that in Node.js versions prior to 13.10.0, the callback for
|
|
1020
|
+
// `zlib.flush()` is not called if `zlib.close()` is used. Utilizing
|
|
1021
|
+
// `zlib.reset()` ensures that either the callback is invoked or an error is
|
|
1022
|
+
// emitted.
|
|
1023
|
+
//
|
|
1005
1024
|
this.reset();
|
|
1006
1025
|
}
|
|
1007
1026
|
|
|
@@ -1017,6 +1036,12 @@ function inflateOnError(err) {
|
|
|
1017
1036
|
// closed when an error is emitted.
|
|
1018
1037
|
//
|
|
1019
1038
|
this[kPerMessageDeflate]._inflate = null;
|
|
1039
|
+
|
|
1040
|
+
if (this[kError$1]) {
|
|
1041
|
+
this[kCallback](this[kError$1]);
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1020
1045
|
err[kStatusCode$2] = 1007;
|
|
1021
1046
|
this[kCallback](err);
|
|
1022
1047
|
}
|
|
@@ -1109,6 +1134,35 @@ function requireUtf8Validate () {
|
|
|
1109
1134
|
return utf8Validate.exports;
|
|
1110
1135
|
}
|
|
1111
1136
|
|
|
1137
|
+
var isValidUTF8_1;
|
|
1138
|
+
|
|
1139
|
+
const { isUtf8 } = require$$0$2;
|
|
1140
|
+
|
|
1141
|
+
const { hasBlob } = constants;
|
|
1142
|
+
|
|
1143
|
+
//
|
|
1144
|
+
// Allowed token characters:
|
|
1145
|
+
//
|
|
1146
|
+
// '!', '#', '$', '%', '&', ''', '*', '+', '-',
|
|
1147
|
+
// '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
|
|
1148
|
+
//
|
|
1149
|
+
// tokenChars[32] === 0 // ' '
|
|
1150
|
+
// tokenChars[33] === 1 // '!'
|
|
1151
|
+
// tokenChars[34] === 0 // '"'
|
|
1152
|
+
// ...
|
|
1153
|
+
//
|
|
1154
|
+
// prettier-ignore
|
|
1155
|
+
const tokenChars$2 = [
|
|
1156
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
|
|
1157
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
|
|
1158
|
+
0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
|
|
1159
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
|
|
1160
|
+
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
|
1161
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
|
|
1162
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
|
1163
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
|
|
1164
|
+
];
|
|
1165
|
+
|
|
1112
1166
|
/**
|
|
1113
1167
|
* Checks if a status code is allowed in a close frame.
|
|
1114
1168
|
*
|
|
@@ -1191,47 +1245,71 @@ function _isValidUTF8(buf) {
|
|
|
1191
1245
|
return true;
|
|
1192
1246
|
}
|
|
1193
1247
|
|
|
1194
|
-
|
|
1195
|
-
|
|
1248
|
+
/**
|
|
1249
|
+
* Determines whether a value is a `Blob`.
|
|
1250
|
+
*
|
|
1251
|
+
* @param {*} value The value to be tested
|
|
1252
|
+
* @return {Boolean} `true` if `value` is a `Blob`, else `false`
|
|
1253
|
+
* @private
|
|
1254
|
+
*/
|
|
1255
|
+
function isBlob$2(value) {
|
|
1256
|
+
return (
|
|
1257
|
+
hasBlob &&
|
|
1258
|
+
typeof value === 'object' &&
|
|
1259
|
+
typeof value.arrayBuffer === 'function' &&
|
|
1260
|
+
typeof value.type === 'string' &&
|
|
1261
|
+
typeof value.stream === 'function' &&
|
|
1262
|
+
(value[Symbol.toStringTag] === 'Blob' ||
|
|
1263
|
+
value[Symbol.toStringTag] === 'File')
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1196
1266
|
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1267
|
+
validation.exports = {
|
|
1268
|
+
isBlob: isBlob$2,
|
|
1269
|
+
isValidStatusCode: isValidStatusCode$2,
|
|
1270
|
+
isValidUTF8: _isValidUTF8,
|
|
1271
|
+
tokenChars: tokenChars$2
|
|
1272
|
+
};
|
|
1201
1273
|
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
return buf.length < 150 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
|
1206
|
-
}
|
|
1207
|
-
};
|
|
1208
|
-
} catch (e) /* istanbul ignore next */ {
|
|
1209
|
-
validation.exports = {
|
|
1210
|
-
isValidStatusCode: isValidStatusCode$2,
|
|
1211
|
-
isValidUTF8: _isValidUTF8
|
|
1274
|
+
if (isUtf8) {
|
|
1275
|
+
isValidUTF8_1 = validation.exports.isValidUTF8 = function (buf) {
|
|
1276
|
+
return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
|
|
1212
1277
|
};
|
|
1278
|
+
} /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
|
|
1279
|
+
try {
|
|
1280
|
+
const isValidUTF8 = requireUtf8Validate();
|
|
1281
|
+
|
|
1282
|
+
isValidUTF8_1 = validation.exports.isValidUTF8 = function (buf) {
|
|
1283
|
+
return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
|
|
1284
|
+
};
|
|
1285
|
+
} catch (e) {
|
|
1286
|
+
// Continue regardless of the error.
|
|
1287
|
+
}
|
|
1213
1288
|
}
|
|
1214
1289
|
|
|
1215
1290
|
var validationExports = validation.exports;
|
|
1216
1291
|
|
|
1217
|
-
const { Writable } = require$$0$
|
|
1292
|
+
const { Writable } = require$$0$3;
|
|
1218
1293
|
|
|
1219
1294
|
const PerMessageDeflate$3 = permessageDeflate;
|
|
1220
1295
|
const {
|
|
1221
1296
|
BINARY_TYPES: BINARY_TYPES$1,
|
|
1222
1297
|
EMPTY_BUFFER: EMPTY_BUFFER$2,
|
|
1223
1298
|
kStatusCode: kStatusCode$1,
|
|
1224
|
-
kWebSocket: kWebSocket$
|
|
1299
|
+
kWebSocket: kWebSocket$3
|
|
1225
1300
|
} = constants;
|
|
1226
1301
|
const { concat, toArrayBuffer, unmask } = bufferUtilExports;
|
|
1227
1302
|
const { isValidStatusCode: isValidStatusCode$1, isValidUTF8 } = validationExports;
|
|
1228
1303
|
|
|
1304
|
+
const FastBuffer = Buffer[Symbol.species];
|
|
1305
|
+
|
|
1229
1306
|
const GET_INFO = 0;
|
|
1230
1307
|
const GET_PAYLOAD_LENGTH_16 = 1;
|
|
1231
1308
|
const GET_PAYLOAD_LENGTH_64 = 2;
|
|
1232
1309
|
const GET_MASK = 3;
|
|
1233
1310
|
const GET_DATA = 4;
|
|
1234
1311
|
const INFLATING = 5;
|
|
1312
|
+
const DEFER_EVENT = 6;
|
|
1235
1313
|
|
|
1236
1314
|
/**
|
|
1237
1315
|
* HyBi Receiver implementation.
|
|
@@ -1242,20 +1320,32 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1242
1320
|
/**
|
|
1243
1321
|
* Creates a Receiver instance.
|
|
1244
1322
|
*
|
|
1245
|
-
* @param {
|
|
1246
|
-
* @param {
|
|
1247
|
-
*
|
|
1248
|
-
*
|
|
1249
|
-
* @param {
|
|
1323
|
+
* @param {Object} [options] Options object
|
|
1324
|
+
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
|
|
1325
|
+
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
|
1326
|
+
* multiple times in the same tick
|
|
1327
|
+
* @param {String} [options.binaryType=nodebuffer] The type for binary data
|
|
1328
|
+
* @param {Object} [options.extensions] An object containing the negotiated
|
|
1329
|
+
* extensions
|
|
1330
|
+
* @param {Boolean} [options.isServer=false] Specifies whether to operate in
|
|
1331
|
+
* client or server mode
|
|
1332
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message length
|
|
1333
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
1334
|
+
* not to skip UTF-8 validation for text and close messages
|
|
1250
1335
|
*/
|
|
1251
|
-
constructor(
|
|
1336
|
+
constructor(options = {}) {
|
|
1252
1337
|
super();
|
|
1253
1338
|
|
|
1254
|
-
this.
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
this.
|
|
1339
|
+
this._allowSynchronousEvents =
|
|
1340
|
+
options.allowSynchronousEvents !== undefined
|
|
1341
|
+
? options.allowSynchronousEvents
|
|
1342
|
+
: true;
|
|
1343
|
+
this._binaryType = options.binaryType || BINARY_TYPES$1[0];
|
|
1344
|
+
this._extensions = options.extensions || {};
|
|
1345
|
+
this._isServer = !!options.isServer;
|
|
1346
|
+
this._maxPayload = options.maxPayload | 0;
|
|
1347
|
+
this._skipUTF8Validation = !!options.skipUTF8Validation;
|
|
1348
|
+
this[kWebSocket$3] = undefined;
|
|
1259
1349
|
|
|
1260
1350
|
this._bufferedBytes = 0;
|
|
1261
1351
|
this._buffers = [];
|
|
@@ -1272,8 +1362,9 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1272
1362
|
this._messageLength = 0;
|
|
1273
1363
|
this._fragments = [];
|
|
1274
1364
|
|
|
1275
|
-
this.
|
|
1365
|
+
this._errored = false;
|
|
1276
1366
|
this._loop = false;
|
|
1367
|
+
this._state = GET_INFO;
|
|
1277
1368
|
}
|
|
1278
1369
|
|
|
1279
1370
|
/**
|
|
@@ -1306,8 +1397,13 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1306
1397
|
|
|
1307
1398
|
if (n < this._buffers[0].length) {
|
|
1308
1399
|
const buf = this._buffers[0];
|
|
1309
|
-
this._buffers[0] =
|
|
1310
|
-
|
|
1400
|
+
this._buffers[0] = new FastBuffer(
|
|
1401
|
+
buf.buffer,
|
|
1402
|
+
buf.byteOffset + n,
|
|
1403
|
+
buf.length - n
|
|
1404
|
+
);
|
|
1405
|
+
|
|
1406
|
+
return new FastBuffer(buf.buffer, buf.byteOffset, n);
|
|
1311
1407
|
}
|
|
1312
1408
|
|
|
1313
1409
|
const dst = Buffer.allocUnsafe(n);
|
|
@@ -1320,7 +1416,11 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1320
1416
|
dst.set(this._buffers.shift(), offset);
|
|
1321
1417
|
} else {
|
|
1322
1418
|
dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
|
|
1323
|
-
this._buffers[0] =
|
|
1419
|
+
this._buffers[0] = new FastBuffer(
|
|
1420
|
+
buf.buffer,
|
|
1421
|
+
buf.byteOffset + n,
|
|
1422
|
+
buf.length - n
|
|
1423
|
+
);
|
|
1324
1424
|
}
|
|
1325
1425
|
|
|
1326
1426
|
n -= buf.length;
|
|
@@ -1336,43 +1436,42 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1336
1436
|
* @private
|
|
1337
1437
|
*/
|
|
1338
1438
|
startLoop(cb) {
|
|
1339
|
-
let err;
|
|
1340
1439
|
this._loop = true;
|
|
1341
1440
|
|
|
1342
1441
|
do {
|
|
1343
1442
|
switch (this._state) {
|
|
1344
1443
|
case GET_INFO:
|
|
1345
|
-
|
|
1444
|
+
this.getInfo(cb);
|
|
1346
1445
|
break;
|
|
1347
1446
|
case GET_PAYLOAD_LENGTH_16:
|
|
1348
|
-
|
|
1447
|
+
this.getPayloadLength16(cb);
|
|
1349
1448
|
break;
|
|
1350
1449
|
case GET_PAYLOAD_LENGTH_64:
|
|
1351
|
-
|
|
1450
|
+
this.getPayloadLength64(cb);
|
|
1352
1451
|
break;
|
|
1353
1452
|
case GET_MASK:
|
|
1354
1453
|
this.getMask();
|
|
1355
1454
|
break;
|
|
1356
1455
|
case GET_DATA:
|
|
1357
|
-
|
|
1456
|
+
this.getData(cb);
|
|
1358
1457
|
break;
|
|
1359
|
-
|
|
1360
|
-
|
|
1458
|
+
case INFLATING:
|
|
1459
|
+
case DEFER_EVENT:
|
|
1361
1460
|
this._loop = false;
|
|
1362
1461
|
return;
|
|
1363
1462
|
}
|
|
1364
1463
|
} while (this._loop);
|
|
1365
1464
|
|
|
1366
|
-
cb(
|
|
1465
|
+
if (!this._errored) cb();
|
|
1367
1466
|
}
|
|
1368
1467
|
|
|
1369
1468
|
/**
|
|
1370
1469
|
* Reads the first two bytes of a frame.
|
|
1371
1470
|
*
|
|
1372
|
-
* @
|
|
1471
|
+
* @param {Function} cb Callback
|
|
1373
1472
|
* @private
|
|
1374
1473
|
*/
|
|
1375
|
-
getInfo() {
|
|
1474
|
+
getInfo(cb) {
|
|
1376
1475
|
if (this._bufferedBytes < 2) {
|
|
1377
1476
|
this._loop = false;
|
|
1378
1477
|
return;
|
|
@@ -1381,27 +1480,31 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1381
1480
|
const buf = this.consume(2);
|
|
1382
1481
|
|
|
1383
1482
|
if ((buf[0] & 0x30) !== 0x00) {
|
|
1384
|
-
|
|
1385
|
-
return error(
|
|
1483
|
+
const error = this.createError(
|
|
1386
1484
|
RangeError,
|
|
1387
1485
|
'RSV2 and RSV3 must be clear',
|
|
1388
1486
|
true,
|
|
1389
1487
|
1002,
|
|
1390
1488
|
'WS_ERR_UNEXPECTED_RSV_2_3'
|
|
1391
1489
|
);
|
|
1490
|
+
|
|
1491
|
+
cb(error);
|
|
1492
|
+
return;
|
|
1392
1493
|
}
|
|
1393
1494
|
|
|
1394
1495
|
const compressed = (buf[0] & 0x40) === 0x40;
|
|
1395
1496
|
|
|
1396
1497
|
if (compressed && !this._extensions[PerMessageDeflate$3.extensionName]) {
|
|
1397
|
-
|
|
1398
|
-
return error(
|
|
1498
|
+
const error = this.createError(
|
|
1399
1499
|
RangeError,
|
|
1400
1500
|
'RSV1 must be clear',
|
|
1401
1501
|
true,
|
|
1402
1502
|
1002,
|
|
1403
1503
|
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1404
1504
|
);
|
|
1505
|
+
|
|
1506
|
+
cb(error);
|
|
1507
|
+
return;
|
|
1405
1508
|
}
|
|
1406
1509
|
|
|
1407
1510
|
this._fin = (buf[0] & 0x80) === 0x80;
|
|
@@ -1410,83 +1513,100 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1410
1513
|
|
|
1411
1514
|
if (this._opcode === 0x00) {
|
|
1412
1515
|
if (compressed) {
|
|
1413
|
-
|
|
1414
|
-
return error(
|
|
1516
|
+
const error = this.createError(
|
|
1415
1517
|
RangeError,
|
|
1416
1518
|
'RSV1 must be clear',
|
|
1417
1519
|
true,
|
|
1418
1520
|
1002,
|
|
1419
1521
|
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1420
1522
|
);
|
|
1523
|
+
|
|
1524
|
+
cb(error);
|
|
1525
|
+
return;
|
|
1421
1526
|
}
|
|
1422
1527
|
|
|
1423
1528
|
if (!this._fragmented) {
|
|
1424
|
-
|
|
1425
|
-
return error(
|
|
1529
|
+
const error = this.createError(
|
|
1426
1530
|
RangeError,
|
|
1427
1531
|
'invalid opcode 0',
|
|
1428
1532
|
true,
|
|
1429
1533
|
1002,
|
|
1430
1534
|
'WS_ERR_INVALID_OPCODE'
|
|
1431
1535
|
);
|
|
1536
|
+
|
|
1537
|
+
cb(error);
|
|
1538
|
+
return;
|
|
1432
1539
|
}
|
|
1433
1540
|
|
|
1434
1541
|
this._opcode = this._fragmented;
|
|
1435
1542
|
} else if (this._opcode === 0x01 || this._opcode === 0x02) {
|
|
1436
1543
|
if (this._fragmented) {
|
|
1437
|
-
|
|
1438
|
-
return error(
|
|
1544
|
+
const error = this.createError(
|
|
1439
1545
|
RangeError,
|
|
1440
1546
|
`invalid opcode ${this._opcode}`,
|
|
1441
1547
|
true,
|
|
1442
1548
|
1002,
|
|
1443
1549
|
'WS_ERR_INVALID_OPCODE'
|
|
1444
1550
|
);
|
|
1551
|
+
|
|
1552
|
+
cb(error);
|
|
1553
|
+
return;
|
|
1445
1554
|
}
|
|
1446
1555
|
|
|
1447
1556
|
this._compressed = compressed;
|
|
1448
1557
|
} else if (this._opcode > 0x07 && this._opcode < 0x0b) {
|
|
1449
1558
|
if (!this._fin) {
|
|
1450
|
-
|
|
1451
|
-
return error(
|
|
1559
|
+
const error = this.createError(
|
|
1452
1560
|
RangeError,
|
|
1453
1561
|
'FIN must be set',
|
|
1454
1562
|
true,
|
|
1455
1563
|
1002,
|
|
1456
1564
|
'WS_ERR_EXPECTED_FIN'
|
|
1457
1565
|
);
|
|
1566
|
+
|
|
1567
|
+
cb(error);
|
|
1568
|
+
return;
|
|
1458
1569
|
}
|
|
1459
1570
|
|
|
1460
1571
|
if (compressed) {
|
|
1461
|
-
|
|
1462
|
-
return error(
|
|
1572
|
+
const error = this.createError(
|
|
1463
1573
|
RangeError,
|
|
1464
1574
|
'RSV1 must be clear',
|
|
1465
1575
|
true,
|
|
1466
1576
|
1002,
|
|
1467
1577
|
'WS_ERR_UNEXPECTED_RSV_1'
|
|
1468
1578
|
);
|
|
1579
|
+
|
|
1580
|
+
cb(error);
|
|
1581
|
+
return;
|
|
1469
1582
|
}
|
|
1470
1583
|
|
|
1471
|
-
if (
|
|
1472
|
-
this.
|
|
1473
|
-
|
|
1584
|
+
if (
|
|
1585
|
+
this._payloadLength > 0x7d ||
|
|
1586
|
+
(this._opcode === 0x08 && this._payloadLength === 1)
|
|
1587
|
+
) {
|
|
1588
|
+
const error = this.createError(
|
|
1474
1589
|
RangeError,
|
|
1475
1590
|
`invalid payload length ${this._payloadLength}`,
|
|
1476
1591
|
true,
|
|
1477
1592
|
1002,
|
|
1478
1593
|
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
|
1479
1594
|
);
|
|
1595
|
+
|
|
1596
|
+
cb(error);
|
|
1597
|
+
return;
|
|
1480
1598
|
}
|
|
1481
1599
|
} else {
|
|
1482
|
-
|
|
1483
|
-
return error(
|
|
1600
|
+
const error = this.createError(
|
|
1484
1601
|
RangeError,
|
|
1485
1602
|
`invalid opcode ${this._opcode}`,
|
|
1486
1603
|
true,
|
|
1487
1604
|
1002,
|
|
1488
1605
|
'WS_ERR_INVALID_OPCODE'
|
|
1489
1606
|
);
|
|
1607
|
+
|
|
1608
|
+
cb(error);
|
|
1609
|
+
return;
|
|
1490
1610
|
}
|
|
1491
1611
|
|
|
1492
1612
|
if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
|
|
@@ -1494,54 +1614,58 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1494
1614
|
|
|
1495
1615
|
if (this._isServer) {
|
|
1496
1616
|
if (!this._masked) {
|
|
1497
|
-
|
|
1498
|
-
return error(
|
|
1617
|
+
const error = this.createError(
|
|
1499
1618
|
RangeError,
|
|
1500
1619
|
'MASK must be set',
|
|
1501
1620
|
true,
|
|
1502
1621
|
1002,
|
|
1503
1622
|
'WS_ERR_EXPECTED_MASK'
|
|
1504
1623
|
);
|
|
1624
|
+
|
|
1625
|
+
cb(error);
|
|
1626
|
+
return;
|
|
1505
1627
|
}
|
|
1506
1628
|
} else if (this._masked) {
|
|
1507
|
-
|
|
1508
|
-
return error(
|
|
1629
|
+
const error = this.createError(
|
|
1509
1630
|
RangeError,
|
|
1510
1631
|
'MASK must be clear',
|
|
1511
1632
|
true,
|
|
1512
1633
|
1002,
|
|
1513
1634
|
'WS_ERR_UNEXPECTED_MASK'
|
|
1514
1635
|
);
|
|
1636
|
+
|
|
1637
|
+
cb(error);
|
|
1638
|
+
return;
|
|
1515
1639
|
}
|
|
1516
1640
|
|
|
1517
1641
|
if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
|
|
1518
1642
|
else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
|
|
1519
|
-
else
|
|
1643
|
+
else this.haveLength(cb);
|
|
1520
1644
|
}
|
|
1521
1645
|
|
|
1522
1646
|
/**
|
|
1523
1647
|
* Gets extended payload length (7+16).
|
|
1524
1648
|
*
|
|
1525
|
-
* @
|
|
1649
|
+
* @param {Function} cb Callback
|
|
1526
1650
|
* @private
|
|
1527
1651
|
*/
|
|
1528
|
-
getPayloadLength16() {
|
|
1652
|
+
getPayloadLength16(cb) {
|
|
1529
1653
|
if (this._bufferedBytes < 2) {
|
|
1530
1654
|
this._loop = false;
|
|
1531
1655
|
return;
|
|
1532
1656
|
}
|
|
1533
1657
|
|
|
1534
1658
|
this._payloadLength = this.consume(2).readUInt16BE(0);
|
|
1535
|
-
|
|
1659
|
+
this.haveLength(cb);
|
|
1536
1660
|
}
|
|
1537
1661
|
|
|
1538
1662
|
/**
|
|
1539
1663
|
* Gets extended payload length (7+64).
|
|
1540
1664
|
*
|
|
1541
|
-
* @
|
|
1665
|
+
* @param {Function} cb Callback
|
|
1542
1666
|
* @private
|
|
1543
1667
|
*/
|
|
1544
|
-
getPayloadLength64() {
|
|
1668
|
+
getPayloadLength64(cb) {
|
|
1545
1669
|
if (this._bufferedBytes < 8) {
|
|
1546
1670
|
this._loop = false;
|
|
1547
1671
|
return;
|
|
@@ -1555,38 +1679,42 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1555
1679
|
// if payload length is greater than this number.
|
|
1556
1680
|
//
|
|
1557
1681
|
if (num > Math.pow(2, 53 - 32) - 1) {
|
|
1558
|
-
|
|
1559
|
-
return error(
|
|
1682
|
+
const error = this.createError(
|
|
1560
1683
|
RangeError,
|
|
1561
1684
|
'Unsupported WebSocket frame: payload length > 2^53 - 1',
|
|
1562
1685
|
false,
|
|
1563
1686
|
1009,
|
|
1564
1687
|
'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
|
|
1565
1688
|
);
|
|
1689
|
+
|
|
1690
|
+
cb(error);
|
|
1691
|
+
return;
|
|
1566
1692
|
}
|
|
1567
1693
|
|
|
1568
1694
|
this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
|
|
1569
|
-
|
|
1695
|
+
this.haveLength(cb);
|
|
1570
1696
|
}
|
|
1571
1697
|
|
|
1572
1698
|
/**
|
|
1573
1699
|
* Payload length has been read.
|
|
1574
1700
|
*
|
|
1575
|
-
* @
|
|
1701
|
+
* @param {Function} cb Callback
|
|
1576
1702
|
* @private
|
|
1577
1703
|
*/
|
|
1578
|
-
haveLength() {
|
|
1704
|
+
haveLength(cb) {
|
|
1579
1705
|
if (this._payloadLength && this._opcode < 0x08) {
|
|
1580
1706
|
this._totalPayloadLength += this._payloadLength;
|
|
1581
1707
|
if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
|
|
1582
|
-
|
|
1583
|
-
return error(
|
|
1708
|
+
const error = this.createError(
|
|
1584
1709
|
RangeError,
|
|
1585
1710
|
'Max payload size exceeded',
|
|
1586
1711
|
false,
|
|
1587
1712
|
1009,
|
|
1588
1713
|
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
|
1589
1714
|
);
|
|
1715
|
+
|
|
1716
|
+
cb(error);
|
|
1717
|
+
return;
|
|
1590
1718
|
}
|
|
1591
1719
|
}
|
|
1592
1720
|
|
|
@@ -1613,7 +1741,6 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1613
1741
|
* Reads data bytes.
|
|
1614
1742
|
*
|
|
1615
1743
|
* @param {Function} cb Callback
|
|
1616
|
-
* @return {(Error|RangeError|undefined)} A possible error
|
|
1617
1744
|
* @private
|
|
1618
1745
|
*/
|
|
1619
1746
|
getData(cb) {
|
|
@@ -1626,10 +1753,19 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1626
1753
|
}
|
|
1627
1754
|
|
|
1628
1755
|
data = this.consume(this._payloadLength);
|
|
1629
|
-
|
|
1756
|
+
|
|
1757
|
+
if (
|
|
1758
|
+
this._masked &&
|
|
1759
|
+
(this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0
|
|
1760
|
+
) {
|
|
1761
|
+
unmask(data, this._mask);
|
|
1762
|
+
}
|
|
1630
1763
|
}
|
|
1631
1764
|
|
|
1632
|
-
if (this._opcode > 0x07)
|
|
1765
|
+
if (this._opcode > 0x07) {
|
|
1766
|
+
this.controlMessage(data, cb);
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1633
1769
|
|
|
1634
1770
|
if (this._compressed) {
|
|
1635
1771
|
this._state = INFLATING;
|
|
@@ -1639,14 +1775,14 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1639
1775
|
|
|
1640
1776
|
if (data.length) {
|
|
1641
1777
|
//
|
|
1642
|
-
// This message is not compressed so its
|
|
1778
|
+
// This message is not compressed so its length is the sum of the payload
|
|
1643
1779
|
// length of all fragments.
|
|
1644
1780
|
//
|
|
1645
1781
|
this._messageLength = this._totalPayloadLength;
|
|
1646
1782
|
this._fragments.push(data);
|
|
1647
1783
|
}
|
|
1648
1784
|
|
|
1649
|
-
|
|
1785
|
+
this.dataMessage(cb);
|
|
1650
1786
|
}
|
|
1651
1787
|
|
|
1652
1788
|
/**
|
|
@@ -1665,74 +1801,98 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1665
1801
|
if (buf.length) {
|
|
1666
1802
|
this._messageLength += buf.length;
|
|
1667
1803
|
if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
|
1675
|
-
)
|
|
1804
|
+
const error = this.createError(
|
|
1805
|
+
RangeError,
|
|
1806
|
+
'Max payload size exceeded',
|
|
1807
|
+
false,
|
|
1808
|
+
1009,
|
|
1809
|
+
'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
|
|
1676
1810
|
);
|
|
1811
|
+
|
|
1812
|
+
cb(error);
|
|
1813
|
+
return;
|
|
1677
1814
|
}
|
|
1678
1815
|
|
|
1679
1816
|
this._fragments.push(buf);
|
|
1680
1817
|
}
|
|
1681
1818
|
|
|
1682
|
-
|
|
1683
|
-
if (
|
|
1684
|
-
|
|
1685
|
-
this.startLoop(cb);
|
|
1819
|
+
this.dataMessage(cb);
|
|
1820
|
+
if (this._state === GET_INFO) this.startLoop(cb);
|
|
1686
1821
|
});
|
|
1687
1822
|
}
|
|
1688
1823
|
|
|
1689
1824
|
/**
|
|
1690
1825
|
* Handles a data message.
|
|
1691
1826
|
*
|
|
1692
|
-
* @
|
|
1827
|
+
* @param {Function} cb Callback
|
|
1693
1828
|
* @private
|
|
1694
1829
|
*/
|
|
1695
|
-
dataMessage() {
|
|
1696
|
-
if (this._fin) {
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
if (this._binaryType === 'nodebuffer') {
|
|
1709
|
-
data = concat(fragments, messageLength);
|
|
1710
|
-
} else if (this._binaryType === 'arraybuffer') {
|
|
1711
|
-
data = toArrayBuffer(concat(fragments, messageLength));
|
|
1712
|
-
} else {
|
|
1713
|
-
data = fragments;
|
|
1714
|
-
}
|
|
1830
|
+
dataMessage(cb) {
|
|
1831
|
+
if (!this._fin) {
|
|
1832
|
+
this._state = GET_INFO;
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
|
|
1836
|
+
const messageLength = this._messageLength;
|
|
1837
|
+
const fragments = this._fragments;
|
|
1838
|
+
|
|
1839
|
+
this._totalPayloadLength = 0;
|
|
1840
|
+
this._messageLength = 0;
|
|
1841
|
+
this._fragmented = 0;
|
|
1842
|
+
this._fragments = [];
|
|
1715
1843
|
|
|
1716
|
-
|
|
1844
|
+
if (this._opcode === 2) {
|
|
1845
|
+
let data;
|
|
1846
|
+
|
|
1847
|
+
if (this._binaryType === 'nodebuffer') {
|
|
1848
|
+
data = concat(fragments, messageLength);
|
|
1849
|
+
} else if (this._binaryType === 'arraybuffer') {
|
|
1850
|
+
data = toArrayBuffer(concat(fragments, messageLength));
|
|
1851
|
+
} else if (this._binaryType === 'blob') {
|
|
1852
|
+
data = new Blob(fragments);
|
|
1717
1853
|
} else {
|
|
1718
|
-
|
|
1854
|
+
data = fragments;
|
|
1855
|
+
}
|
|
1719
1856
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
);
|
|
1729
|
-
}
|
|
1857
|
+
if (this._allowSynchronousEvents) {
|
|
1858
|
+
this.emit('message', data, true);
|
|
1859
|
+
this._state = GET_INFO;
|
|
1860
|
+
} else {
|
|
1861
|
+
this._state = DEFER_EVENT;
|
|
1862
|
+
setImmediate(() => {
|
|
1863
|
+
this.emit('message', data, true);
|
|
1864
|
+
this._state = GET_INFO;
|
|
1865
|
+
this.startLoop(cb);
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
} else {
|
|
1869
|
+
const buf = concat(fragments, messageLength);
|
|
1870
|
+
|
|
1871
|
+
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
|
|
1872
|
+
const error = this.createError(
|
|
1873
|
+
Error,
|
|
1874
|
+
'invalid UTF-8 sequence',
|
|
1875
|
+
true,
|
|
1876
|
+
1007,
|
|
1877
|
+
'WS_ERR_INVALID_UTF8'
|
|
1878
|
+
);
|
|
1730
1879
|
|
|
1731
|
-
|
|
1880
|
+
cb(error);
|
|
1881
|
+
return;
|
|
1732
1882
|
}
|
|
1733
|
-
}
|
|
1734
1883
|
|
|
1735
|
-
|
|
1884
|
+
if (this._state === INFLATING || this._allowSynchronousEvents) {
|
|
1885
|
+
this.emit('message', buf, false);
|
|
1886
|
+
this._state = GET_INFO;
|
|
1887
|
+
} else {
|
|
1888
|
+
this._state = DEFER_EVENT;
|
|
1889
|
+
setImmediate(() => {
|
|
1890
|
+
this.emit('message', buf, false);
|
|
1891
|
+
this._state = GET_INFO;
|
|
1892
|
+
this.startLoop(cb);
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1736
1896
|
}
|
|
1737
1897
|
|
|
1738
1898
|
/**
|
|
@@ -1742,93 +1902,117 @@ let Receiver$1 = class Receiver extends Writable {
|
|
|
1742
1902
|
* @return {(Error|RangeError|undefined)} A possible error
|
|
1743
1903
|
* @private
|
|
1744
1904
|
*/
|
|
1745
|
-
controlMessage(data) {
|
|
1905
|
+
controlMessage(data, cb) {
|
|
1746
1906
|
if (this._opcode === 0x08) {
|
|
1747
|
-
this._loop = false;
|
|
1748
|
-
|
|
1749
1907
|
if (data.length === 0) {
|
|
1750
|
-
this.
|
|
1908
|
+
this._loop = false;
|
|
1909
|
+
this.emit('conclude', 1005, EMPTY_BUFFER$2);
|
|
1751
1910
|
this.end();
|
|
1752
|
-
} else if (data.length === 1) {
|
|
1753
|
-
return error(
|
|
1754
|
-
RangeError,
|
|
1755
|
-
'invalid payload length 1',
|
|
1756
|
-
true,
|
|
1757
|
-
1002,
|
|
1758
|
-
'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
|
|
1759
|
-
);
|
|
1760
1911
|
} else {
|
|
1761
1912
|
const code = data.readUInt16BE(0);
|
|
1762
1913
|
|
|
1763
1914
|
if (!isValidStatusCode$1(code)) {
|
|
1764
|
-
|
|
1915
|
+
const error = this.createError(
|
|
1765
1916
|
RangeError,
|
|
1766
1917
|
`invalid status code ${code}`,
|
|
1767
1918
|
true,
|
|
1768
1919
|
1002,
|
|
1769
1920
|
'WS_ERR_INVALID_CLOSE_CODE'
|
|
1770
1921
|
);
|
|
1922
|
+
|
|
1923
|
+
cb(error);
|
|
1924
|
+
return;
|
|
1771
1925
|
}
|
|
1772
1926
|
|
|
1773
|
-
const buf =
|
|
1927
|
+
const buf = new FastBuffer(
|
|
1928
|
+
data.buffer,
|
|
1929
|
+
data.byteOffset + 2,
|
|
1930
|
+
data.length - 2
|
|
1931
|
+
);
|
|
1774
1932
|
|
|
1775
|
-
if (!isValidUTF8(buf)) {
|
|
1776
|
-
|
|
1933
|
+
if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
|
|
1934
|
+
const error = this.createError(
|
|
1777
1935
|
Error,
|
|
1778
1936
|
'invalid UTF-8 sequence',
|
|
1779
1937
|
true,
|
|
1780
1938
|
1007,
|
|
1781
1939
|
'WS_ERR_INVALID_UTF8'
|
|
1782
1940
|
);
|
|
1941
|
+
|
|
1942
|
+
cb(error);
|
|
1943
|
+
return;
|
|
1783
1944
|
}
|
|
1784
1945
|
|
|
1785
|
-
this.
|
|
1946
|
+
this._loop = false;
|
|
1947
|
+
this.emit('conclude', code, buf);
|
|
1786
1948
|
this.end();
|
|
1787
1949
|
}
|
|
1788
|
-
|
|
1789
|
-
this.
|
|
1950
|
+
|
|
1951
|
+
this._state = GET_INFO;
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
if (this._allowSynchronousEvents) {
|
|
1956
|
+
this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
|
|
1957
|
+
this._state = GET_INFO;
|
|
1790
1958
|
} else {
|
|
1791
|
-
this.
|
|
1959
|
+
this._state = DEFER_EVENT;
|
|
1960
|
+
setImmediate(() => {
|
|
1961
|
+
this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
|
|
1962
|
+
this._state = GET_INFO;
|
|
1963
|
+
this.startLoop(cb);
|
|
1964
|
+
});
|
|
1792
1965
|
}
|
|
1966
|
+
}
|
|
1793
1967
|
|
|
1794
|
-
|
|
1968
|
+
/**
|
|
1969
|
+
* Builds an error object.
|
|
1970
|
+
*
|
|
1971
|
+
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
|
|
1972
|
+
* @param {String} message The error message
|
|
1973
|
+
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
|
|
1974
|
+
* `message`
|
|
1975
|
+
* @param {Number} statusCode The status code
|
|
1976
|
+
* @param {String} errorCode The exposed error code
|
|
1977
|
+
* @return {(Error|RangeError)} The error
|
|
1978
|
+
* @private
|
|
1979
|
+
*/
|
|
1980
|
+
createError(ErrorCtor, message, prefix, statusCode, errorCode) {
|
|
1981
|
+
this._loop = false;
|
|
1982
|
+
this._errored = true;
|
|
1983
|
+
|
|
1984
|
+
const err = new ErrorCtor(
|
|
1985
|
+
prefix ? `Invalid WebSocket frame: ${message}` : message
|
|
1986
|
+
);
|
|
1987
|
+
|
|
1988
|
+
Error.captureStackTrace(err, this.createError);
|
|
1989
|
+
err.code = errorCode;
|
|
1990
|
+
err[kStatusCode$1] = statusCode;
|
|
1991
|
+
return err;
|
|
1795
1992
|
}
|
|
1796
1993
|
};
|
|
1797
1994
|
|
|
1798
1995
|
var receiver = Receiver$1;
|
|
1799
1996
|
|
|
1800
|
-
|
|
1801
|
-
* Builds an error object.
|
|
1802
|
-
*
|
|
1803
|
-
* @param {function(new:Error|RangeError)} ErrorCtor The error constructor
|
|
1804
|
-
* @param {String} message The error message
|
|
1805
|
-
* @param {Boolean} prefix Specifies whether or not to add a default prefix to
|
|
1806
|
-
* `message`
|
|
1807
|
-
* @param {Number} statusCode The status code
|
|
1808
|
-
* @param {String} errorCode The exposed error code
|
|
1809
|
-
* @return {(Error|RangeError)} The error
|
|
1810
|
-
* @private
|
|
1811
|
-
*/
|
|
1812
|
-
function error(ErrorCtor, message, prefix, statusCode, errorCode) {
|
|
1813
|
-
const err = new ErrorCtor(
|
|
1814
|
-
prefix ? `Invalid WebSocket frame: ${message}` : message
|
|
1815
|
-
);
|
|
1816
|
-
|
|
1817
|
-
Error.captureStackTrace(err, error);
|
|
1818
|
-
err.code = errorCode;
|
|
1819
|
-
err[kStatusCode$1] = statusCode;
|
|
1820
|
-
return err;
|
|
1821
|
-
}
|
|
1997
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex" }] */
|
|
1822
1998
|
|
|
1823
|
-
|
|
1824
|
-
const { randomFillSync } = require$$
|
|
1999
|
+
const { Duplex: Duplex$3 } = require$$0$3;
|
|
2000
|
+
const { randomFillSync } = require$$1$1;
|
|
1825
2001
|
|
|
1826
2002
|
const PerMessageDeflate$2 = permessageDeflate;
|
|
1827
|
-
const { EMPTY_BUFFER: EMPTY_BUFFER$1 } = constants;
|
|
1828
|
-
const { isValidStatusCode } = validationExports;
|
|
2003
|
+
const { EMPTY_BUFFER: EMPTY_BUFFER$1, kWebSocket: kWebSocket$2, NOOP: NOOP$1 } = constants;
|
|
2004
|
+
const { isBlob: isBlob$1, isValidStatusCode } = validationExports;
|
|
1829
2005
|
const { mask: applyMask, toBuffer: toBuffer$1 } = bufferUtilExports;
|
|
1830
2006
|
|
|
1831
|
-
const
|
|
2007
|
+
const kByteLength = Symbol('kByteLength');
|
|
2008
|
+
const maskBuffer = Buffer.alloc(4);
|
|
2009
|
+
const RANDOM_POOL_SIZE = 8 * 1024;
|
|
2010
|
+
let randomPool;
|
|
2011
|
+
let randomPoolPointer = RANDOM_POOL_SIZE;
|
|
2012
|
+
|
|
2013
|
+
const DEFAULT = 0;
|
|
2014
|
+
const DEFLATING = 1;
|
|
2015
|
+
const GET_BLOB_DATA = 2;
|
|
1832
2016
|
|
|
1833
2017
|
/**
|
|
1834
2018
|
* HyBi Sender implementation.
|
|
@@ -1837,52 +2021,116 @@ let Sender$1 = class Sender {
|
|
|
1837
2021
|
/**
|
|
1838
2022
|
* Creates a Sender instance.
|
|
1839
2023
|
*
|
|
1840
|
-
* @param {
|
|
2024
|
+
* @param {Duplex} socket The connection socket
|
|
1841
2025
|
* @param {Object} [extensions] An object containing the negotiated extensions
|
|
2026
|
+
* @param {Function} [generateMask] The function used to generate the masking
|
|
2027
|
+
* key
|
|
1842
2028
|
*/
|
|
1843
|
-
constructor(socket, extensions) {
|
|
2029
|
+
constructor(socket, extensions, generateMask) {
|
|
1844
2030
|
this._extensions = extensions || {};
|
|
2031
|
+
|
|
2032
|
+
if (generateMask) {
|
|
2033
|
+
this._generateMask = generateMask;
|
|
2034
|
+
this._maskBuffer = Buffer.alloc(4);
|
|
2035
|
+
}
|
|
2036
|
+
|
|
1845
2037
|
this._socket = socket;
|
|
1846
2038
|
|
|
1847
2039
|
this._firstFragment = true;
|
|
1848
2040
|
this._compress = false;
|
|
1849
2041
|
|
|
1850
2042
|
this._bufferedBytes = 0;
|
|
1851
|
-
this._deflating = false;
|
|
1852
2043
|
this._queue = [];
|
|
2044
|
+
this._state = DEFAULT;
|
|
2045
|
+
this.onerror = NOOP$1;
|
|
2046
|
+
this[kWebSocket$2] = undefined;
|
|
1853
2047
|
}
|
|
1854
2048
|
|
|
1855
2049
|
/**
|
|
1856
2050
|
* Frames a piece of data according to the HyBi WebSocket protocol.
|
|
1857
2051
|
*
|
|
1858
|
-
* @param {Buffer} data The data to frame
|
|
2052
|
+
* @param {(Buffer|String)} data The data to frame
|
|
1859
2053
|
* @param {Object} options Options object
|
|
1860
|
-
* @param {Number} options.opcode The opcode
|
|
1861
|
-
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
|
1862
|
-
* modified
|
|
1863
2054
|
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
|
|
1864
2055
|
* FIN bit
|
|
2056
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
2057
|
+
* masking key
|
|
1865
2058
|
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
|
1866
2059
|
* `data`
|
|
2060
|
+
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
|
|
2061
|
+
* key
|
|
2062
|
+
* @param {Number} options.opcode The opcode
|
|
2063
|
+
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
|
2064
|
+
* modified
|
|
1867
2065
|
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
|
|
1868
2066
|
* RSV1 bit
|
|
1869
|
-
* @return {Buffer[]} The framed data
|
|
2067
|
+
* @return {(Buffer|String)[]} The framed data
|
|
1870
2068
|
* @public
|
|
1871
2069
|
*/
|
|
1872
2070
|
static frame(data, options) {
|
|
1873
|
-
|
|
1874
|
-
let
|
|
1875
|
-
let
|
|
2071
|
+
let mask;
|
|
2072
|
+
let merge = false;
|
|
2073
|
+
let offset = 2;
|
|
2074
|
+
let skipMasking = false;
|
|
2075
|
+
|
|
2076
|
+
if (options.mask) {
|
|
2077
|
+
mask = options.maskBuffer || maskBuffer;
|
|
2078
|
+
|
|
2079
|
+
if (options.generateMask) {
|
|
2080
|
+
options.generateMask(mask);
|
|
2081
|
+
} else {
|
|
2082
|
+
if (randomPoolPointer === RANDOM_POOL_SIZE) {
|
|
2083
|
+
/* istanbul ignore else */
|
|
2084
|
+
if (randomPool === undefined) {
|
|
2085
|
+
//
|
|
2086
|
+
// This is lazily initialized because server-sent frames must not
|
|
2087
|
+
// be masked so it may never be used.
|
|
2088
|
+
//
|
|
2089
|
+
randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2092
|
+
randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
|
|
2093
|
+
randomPoolPointer = 0;
|
|
2094
|
+
}
|
|
2095
|
+
|
|
2096
|
+
mask[0] = randomPool[randomPoolPointer++];
|
|
2097
|
+
mask[1] = randomPool[randomPoolPointer++];
|
|
2098
|
+
mask[2] = randomPool[randomPoolPointer++];
|
|
2099
|
+
mask[3] = randomPool[randomPoolPointer++];
|
|
2100
|
+
}
|
|
1876
2101
|
|
|
1877
|
-
|
|
2102
|
+
skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
|
|
2103
|
+
offset = 6;
|
|
2104
|
+
}
|
|
2105
|
+
|
|
2106
|
+
let dataLength;
|
|
2107
|
+
|
|
2108
|
+
if (typeof data === 'string') {
|
|
2109
|
+
if (
|
|
2110
|
+
(!options.mask || skipMasking) &&
|
|
2111
|
+
options[kByteLength] !== undefined
|
|
2112
|
+
) {
|
|
2113
|
+
dataLength = options[kByteLength];
|
|
2114
|
+
} else {
|
|
2115
|
+
data = Buffer.from(data);
|
|
2116
|
+
dataLength = data.length;
|
|
2117
|
+
}
|
|
2118
|
+
} else {
|
|
2119
|
+
dataLength = data.length;
|
|
2120
|
+
merge = options.mask && options.readOnly && !skipMasking;
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
let payloadLength = dataLength;
|
|
2124
|
+
|
|
2125
|
+
if (dataLength >= 65536) {
|
|
1878
2126
|
offset += 8;
|
|
1879
2127
|
payloadLength = 127;
|
|
1880
|
-
} else if (
|
|
2128
|
+
} else if (dataLength > 125) {
|
|
1881
2129
|
offset += 2;
|
|
1882
2130
|
payloadLength = 126;
|
|
1883
2131
|
}
|
|
1884
2132
|
|
|
1885
|
-
const target = Buffer.allocUnsafe(merge ?
|
|
2133
|
+
const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
|
|
1886
2134
|
|
|
1887
2135
|
target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
|
|
1888
2136
|
if (options.rsv1) target[0] |= 0x40;
|
|
@@ -1890,28 +2138,28 @@ let Sender$1 = class Sender {
|
|
|
1890
2138
|
target[1] = payloadLength;
|
|
1891
2139
|
|
|
1892
2140
|
if (payloadLength === 126) {
|
|
1893
|
-
target.writeUInt16BE(
|
|
2141
|
+
target.writeUInt16BE(dataLength, 2);
|
|
1894
2142
|
} else if (payloadLength === 127) {
|
|
1895
|
-
target
|
|
1896
|
-
target.
|
|
2143
|
+
target[2] = target[3] = 0;
|
|
2144
|
+
target.writeUIntBE(dataLength, 4, 6);
|
|
1897
2145
|
}
|
|
1898
2146
|
|
|
1899
2147
|
if (!options.mask) return [target, data];
|
|
1900
2148
|
|
|
1901
|
-
randomFillSync(mask, 0, 4);
|
|
1902
|
-
|
|
1903
2149
|
target[1] |= 0x80;
|
|
1904
2150
|
target[offset - 4] = mask[0];
|
|
1905
2151
|
target[offset - 3] = mask[1];
|
|
1906
2152
|
target[offset - 2] = mask[2];
|
|
1907
2153
|
target[offset - 1] = mask[3];
|
|
1908
2154
|
|
|
2155
|
+
if (skipMasking) return [target, data];
|
|
2156
|
+
|
|
1909
2157
|
if (merge) {
|
|
1910
|
-
applyMask(data, mask, target, offset,
|
|
2158
|
+
applyMask(data, mask, target, offset, dataLength);
|
|
1911
2159
|
return [target];
|
|
1912
2160
|
}
|
|
1913
2161
|
|
|
1914
|
-
applyMask(data, mask, data, 0,
|
|
2162
|
+
applyMask(data, mask, data, 0, dataLength);
|
|
1915
2163
|
return [target, data];
|
|
1916
2164
|
}
|
|
1917
2165
|
|
|
@@ -1919,7 +2167,7 @@ let Sender$1 = class Sender {
|
|
|
1919
2167
|
* Sends a close message to the other peer.
|
|
1920
2168
|
*
|
|
1921
2169
|
* @param {Number} [code] The status code component of the body
|
|
1922
|
-
* @param {String} [data] The message component of the body
|
|
2170
|
+
* @param {(String|Buffer)} [data] The message component of the body
|
|
1923
2171
|
* @param {Boolean} [mask=false] Specifies whether or not to mask the message
|
|
1924
2172
|
* @param {Function} [cb] Callback
|
|
1925
2173
|
* @public
|
|
@@ -1931,7 +2179,7 @@ let Sender$1 = class Sender {
|
|
|
1931
2179
|
buf = EMPTY_BUFFER$1;
|
|
1932
2180
|
} else if (typeof code !== 'number' || !isValidStatusCode(code)) {
|
|
1933
2181
|
throw new TypeError('First argument must be a valid error code number');
|
|
1934
|
-
} else if (data === undefined || data
|
|
2182
|
+
} else if (data === undefined || !data.length) {
|
|
1935
2183
|
buf = Buffer.allocUnsafe(2);
|
|
1936
2184
|
buf.writeUInt16BE(code, 0);
|
|
1937
2185
|
} else {
|
|
@@ -1943,37 +2191,32 @@ let Sender$1 = class Sender {
|
|
|
1943
2191
|
|
|
1944
2192
|
buf = Buffer.allocUnsafe(2 + length);
|
|
1945
2193
|
buf.writeUInt16BE(code, 0);
|
|
1946
|
-
|
|
2194
|
+
|
|
2195
|
+
if (typeof data === 'string') {
|
|
2196
|
+
buf.write(data, 2);
|
|
2197
|
+
} else {
|
|
2198
|
+
buf.set(data, 2);
|
|
2199
|
+
}
|
|
1947
2200
|
}
|
|
1948
2201
|
|
|
1949
|
-
|
|
1950
|
-
|
|
2202
|
+
const options = {
|
|
2203
|
+
[kByteLength]: buf.length,
|
|
2204
|
+
fin: true,
|
|
2205
|
+
generateMask: this._generateMask,
|
|
2206
|
+
mask,
|
|
2207
|
+
maskBuffer: this._maskBuffer,
|
|
2208
|
+
opcode: 0x08,
|
|
2209
|
+
readOnly: false,
|
|
2210
|
+
rsv1: false
|
|
2211
|
+
};
|
|
2212
|
+
|
|
2213
|
+
if (this._state !== DEFAULT) {
|
|
2214
|
+
this.enqueue([this.dispatch, buf, false, options, cb]);
|
|
1951
2215
|
} else {
|
|
1952
|
-
this.
|
|
2216
|
+
this.sendFrame(Sender.frame(buf, options), cb);
|
|
1953
2217
|
}
|
|
1954
2218
|
}
|
|
1955
2219
|
|
|
1956
|
-
/**
|
|
1957
|
-
* Frames and sends a close message.
|
|
1958
|
-
*
|
|
1959
|
-
* @param {Buffer} data The message to send
|
|
1960
|
-
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
|
1961
|
-
* @param {Function} [cb] Callback
|
|
1962
|
-
* @private
|
|
1963
|
-
*/
|
|
1964
|
-
doClose(data, mask, cb) {
|
|
1965
|
-
this.sendFrame(
|
|
1966
|
-
Sender.frame(data, {
|
|
1967
|
-
fin: true,
|
|
1968
|
-
rsv1: false,
|
|
1969
|
-
opcode: 0x08,
|
|
1970
|
-
mask,
|
|
1971
|
-
readOnly: false
|
|
1972
|
-
}),
|
|
1973
|
-
cb
|
|
1974
|
-
);
|
|
1975
|
-
}
|
|
1976
|
-
|
|
1977
2220
|
/**
|
|
1978
2221
|
* Sends a ping message to the other peer.
|
|
1979
2222
|
*
|
|
@@ -1983,41 +2226,49 @@ let Sender$1 = class Sender {
|
|
|
1983
2226
|
* @public
|
|
1984
2227
|
*/
|
|
1985
2228
|
ping(data, mask, cb) {
|
|
1986
|
-
|
|
2229
|
+
let byteLength;
|
|
2230
|
+
let readOnly;
|
|
2231
|
+
|
|
2232
|
+
if (typeof data === 'string') {
|
|
2233
|
+
byteLength = Buffer.byteLength(data);
|
|
2234
|
+
readOnly = false;
|
|
2235
|
+
} else if (isBlob$1(data)) {
|
|
2236
|
+
byteLength = data.size;
|
|
2237
|
+
readOnly = false;
|
|
2238
|
+
} else {
|
|
2239
|
+
data = toBuffer$1(data);
|
|
2240
|
+
byteLength = data.length;
|
|
2241
|
+
readOnly = toBuffer$1.readOnly;
|
|
2242
|
+
}
|
|
1987
2243
|
|
|
1988
|
-
if (
|
|
2244
|
+
if (byteLength > 125) {
|
|
1989
2245
|
throw new RangeError('The data size must not be greater than 125 bytes');
|
|
1990
2246
|
}
|
|
1991
2247
|
|
|
1992
|
-
|
|
1993
|
-
|
|
2248
|
+
const options = {
|
|
2249
|
+
[kByteLength]: byteLength,
|
|
2250
|
+
fin: true,
|
|
2251
|
+
generateMask: this._generateMask,
|
|
2252
|
+
mask,
|
|
2253
|
+
maskBuffer: this._maskBuffer,
|
|
2254
|
+
opcode: 0x09,
|
|
2255
|
+
readOnly,
|
|
2256
|
+
rsv1: false
|
|
2257
|
+
};
|
|
2258
|
+
|
|
2259
|
+
if (isBlob$1(data)) {
|
|
2260
|
+
if (this._state !== DEFAULT) {
|
|
2261
|
+
this.enqueue([this.getBlobData, data, false, options, cb]);
|
|
2262
|
+
} else {
|
|
2263
|
+
this.getBlobData(data, false, options, cb);
|
|
2264
|
+
}
|
|
2265
|
+
} else if (this._state !== DEFAULT) {
|
|
2266
|
+
this.enqueue([this.dispatch, data, false, options, cb]);
|
|
1994
2267
|
} else {
|
|
1995
|
-
this.
|
|
2268
|
+
this.sendFrame(Sender.frame(data, options), cb);
|
|
1996
2269
|
}
|
|
1997
2270
|
}
|
|
1998
2271
|
|
|
1999
|
-
/**
|
|
2000
|
-
* Frames and sends a ping message.
|
|
2001
|
-
*
|
|
2002
|
-
* @param {Buffer} data The message to send
|
|
2003
|
-
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
|
2004
|
-
* @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
|
|
2005
|
-
* @param {Function} [cb] Callback
|
|
2006
|
-
* @private
|
|
2007
|
-
*/
|
|
2008
|
-
doPing(data, mask, readOnly, cb) {
|
|
2009
|
-
this.sendFrame(
|
|
2010
|
-
Sender.frame(data, {
|
|
2011
|
-
fin: true,
|
|
2012
|
-
rsv1: false,
|
|
2013
|
-
opcode: 0x09,
|
|
2014
|
-
mask,
|
|
2015
|
-
readOnly
|
|
2016
|
-
}),
|
|
2017
|
-
cb
|
|
2018
|
-
);
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
2272
|
/**
|
|
2022
2273
|
* Sends a pong message to the other peer.
|
|
2023
2274
|
*
|
|
@@ -2027,50 +2278,58 @@ let Sender$1 = class Sender {
|
|
|
2027
2278
|
* @public
|
|
2028
2279
|
*/
|
|
2029
2280
|
pong(data, mask, cb) {
|
|
2030
|
-
|
|
2281
|
+
let byteLength;
|
|
2282
|
+
let readOnly;
|
|
2283
|
+
|
|
2284
|
+
if (typeof data === 'string') {
|
|
2285
|
+
byteLength = Buffer.byteLength(data);
|
|
2286
|
+
readOnly = false;
|
|
2287
|
+
} else if (isBlob$1(data)) {
|
|
2288
|
+
byteLength = data.size;
|
|
2289
|
+
readOnly = false;
|
|
2290
|
+
} else {
|
|
2291
|
+
data = toBuffer$1(data);
|
|
2292
|
+
byteLength = data.length;
|
|
2293
|
+
readOnly = toBuffer$1.readOnly;
|
|
2294
|
+
}
|
|
2031
2295
|
|
|
2032
|
-
if (
|
|
2296
|
+
if (byteLength > 125) {
|
|
2033
2297
|
throw new RangeError('The data size must not be greater than 125 bytes');
|
|
2034
2298
|
}
|
|
2035
2299
|
|
|
2036
|
-
|
|
2037
|
-
|
|
2300
|
+
const options = {
|
|
2301
|
+
[kByteLength]: byteLength,
|
|
2302
|
+
fin: true,
|
|
2303
|
+
generateMask: this._generateMask,
|
|
2304
|
+
mask,
|
|
2305
|
+
maskBuffer: this._maskBuffer,
|
|
2306
|
+
opcode: 0x0a,
|
|
2307
|
+
readOnly,
|
|
2308
|
+
rsv1: false
|
|
2309
|
+
};
|
|
2310
|
+
|
|
2311
|
+
if (isBlob$1(data)) {
|
|
2312
|
+
if (this._state !== DEFAULT) {
|
|
2313
|
+
this.enqueue([this.getBlobData, data, false, options, cb]);
|
|
2314
|
+
} else {
|
|
2315
|
+
this.getBlobData(data, false, options, cb);
|
|
2316
|
+
}
|
|
2317
|
+
} else if (this._state !== DEFAULT) {
|
|
2318
|
+
this.enqueue([this.dispatch, data, false, options, cb]);
|
|
2038
2319
|
} else {
|
|
2039
|
-
this.
|
|
2320
|
+
this.sendFrame(Sender.frame(data, options), cb);
|
|
2040
2321
|
}
|
|
2041
2322
|
}
|
|
2042
2323
|
|
|
2043
|
-
/**
|
|
2044
|
-
* Frames and sends a pong message.
|
|
2045
|
-
*
|
|
2046
|
-
* @param {Buffer} data The message to send
|
|
2047
|
-
* @param {Boolean} [mask=false] Specifies whether or not to mask `data`
|
|
2048
|
-
* @param {Boolean} [readOnly=false] Specifies whether `data` can be modified
|
|
2049
|
-
* @param {Function} [cb] Callback
|
|
2050
|
-
* @private
|
|
2051
|
-
*/
|
|
2052
|
-
doPong(data, mask, readOnly, cb) {
|
|
2053
|
-
this.sendFrame(
|
|
2054
|
-
Sender.frame(data, {
|
|
2055
|
-
fin: true,
|
|
2056
|
-
rsv1: false,
|
|
2057
|
-
opcode: 0x0a,
|
|
2058
|
-
mask,
|
|
2059
|
-
readOnly
|
|
2060
|
-
}),
|
|
2061
|
-
cb
|
|
2062
|
-
);
|
|
2063
|
-
}
|
|
2064
|
-
|
|
2065
2324
|
/**
|
|
2066
2325
|
* Sends a data message to the other peer.
|
|
2067
2326
|
*
|
|
2068
2327
|
* @param {*} data The message to send
|
|
2069
2328
|
* @param {Object} options Options object
|
|
2070
|
-
* @param {Boolean} [options.compress=false] Specifies whether or not to
|
|
2071
|
-
* compress `data`
|
|
2072
2329
|
* @param {Boolean} [options.binary=false] Specifies whether `data` is binary
|
|
2073
2330
|
* or text
|
|
2331
|
+
* @param {Boolean} [options.compress=false] Specifies whether or not to
|
|
2332
|
+
* compress `data`
|
|
2074
2333
|
* @param {Boolean} [options.fin=false] Specifies whether the fragment is the
|
|
2075
2334
|
* last one
|
|
2076
2335
|
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
|
@@ -2079,15 +2338,37 @@ let Sender$1 = class Sender {
|
|
|
2079
2338
|
* @public
|
|
2080
2339
|
*/
|
|
2081
2340
|
send(data, options, cb) {
|
|
2082
|
-
const buf = toBuffer$1(data);
|
|
2083
2341
|
const perMessageDeflate = this._extensions[PerMessageDeflate$2.extensionName];
|
|
2084
2342
|
let opcode = options.binary ? 2 : 1;
|
|
2085
2343
|
let rsv1 = options.compress;
|
|
2086
2344
|
|
|
2345
|
+
let byteLength;
|
|
2346
|
+
let readOnly;
|
|
2347
|
+
|
|
2348
|
+
if (typeof data === 'string') {
|
|
2349
|
+
byteLength = Buffer.byteLength(data);
|
|
2350
|
+
readOnly = false;
|
|
2351
|
+
} else if (isBlob$1(data)) {
|
|
2352
|
+
byteLength = data.size;
|
|
2353
|
+
readOnly = false;
|
|
2354
|
+
} else {
|
|
2355
|
+
data = toBuffer$1(data);
|
|
2356
|
+
byteLength = data.length;
|
|
2357
|
+
readOnly = toBuffer$1.readOnly;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2087
2360
|
if (this._firstFragment) {
|
|
2088
2361
|
this._firstFragment = false;
|
|
2089
|
-
if (
|
|
2090
|
-
rsv1
|
|
2362
|
+
if (
|
|
2363
|
+
rsv1 &&
|
|
2364
|
+
perMessageDeflate &&
|
|
2365
|
+
perMessageDeflate.params[
|
|
2366
|
+
perMessageDeflate._isServer
|
|
2367
|
+
? 'server_no_context_takeover'
|
|
2368
|
+
: 'client_no_context_takeover'
|
|
2369
|
+
]
|
|
2370
|
+
) {
|
|
2371
|
+
rsv1 = byteLength >= perMessageDeflate._threshold;
|
|
2091
2372
|
}
|
|
2092
2373
|
this._compress = rsv1;
|
|
2093
2374
|
} else {
|
|
@@ -2097,48 +2378,112 @@ let Sender$1 = class Sender {
|
|
|
2097
2378
|
|
|
2098
2379
|
if (options.fin) this._firstFragment = true;
|
|
2099
2380
|
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2381
|
+
const opts = {
|
|
2382
|
+
[kByteLength]: byteLength,
|
|
2383
|
+
fin: options.fin,
|
|
2384
|
+
generateMask: this._generateMask,
|
|
2385
|
+
mask: options.mask,
|
|
2386
|
+
maskBuffer: this._maskBuffer,
|
|
2387
|
+
opcode,
|
|
2388
|
+
readOnly,
|
|
2389
|
+
rsv1
|
|
2390
|
+
};
|
|
2108
2391
|
|
|
2109
|
-
|
|
2110
|
-
|
|
2392
|
+
if (isBlob$1(data)) {
|
|
2393
|
+
if (this._state !== DEFAULT) {
|
|
2394
|
+
this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
|
|
2111
2395
|
} else {
|
|
2112
|
-
this.
|
|
2396
|
+
this.getBlobData(data, this._compress, opts, cb);
|
|
2113
2397
|
}
|
|
2398
|
+
} else if (this._state !== DEFAULT) {
|
|
2399
|
+
this.enqueue([this.dispatch, data, this._compress, opts, cb]);
|
|
2114
2400
|
} else {
|
|
2115
|
-
this.
|
|
2116
|
-
Sender.frame(buf, {
|
|
2117
|
-
fin: options.fin,
|
|
2118
|
-
rsv1: false,
|
|
2119
|
-
opcode,
|
|
2120
|
-
mask: options.mask,
|
|
2121
|
-
readOnly: toBuffer$1.readOnly
|
|
2122
|
-
}),
|
|
2123
|
-
cb
|
|
2124
|
-
);
|
|
2401
|
+
this.dispatch(data, this._compress, opts, cb);
|
|
2125
2402
|
}
|
|
2126
2403
|
}
|
|
2127
2404
|
|
|
2128
2405
|
/**
|
|
2129
|
-
*
|
|
2406
|
+
* Gets the contents of a blob as binary data.
|
|
2130
2407
|
*
|
|
2131
|
-
* @param {
|
|
2408
|
+
* @param {Blob} blob The blob
|
|
2132
2409
|
* @param {Boolean} [compress=false] Specifies whether or not to compress
|
|
2133
|
-
*
|
|
2410
|
+
* the data
|
|
2134
2411
|
* @param {Object} options Options object
|
|
2412
|
+
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
|
|
2413
|
+
* FIN bit
|
|
2414
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
2415
|
+
* masking key
|
|
2416
|
+
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
|
2417
|
+
* `data`
|
|
2418
|
+
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
|
|
2419
|
+
* key
|
|
2135
2420
|
* @param {Number} options.opcode The opcode
|
|
2136
2421
|
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
|
2137
2422
|
* modified
|
|
2423
|
+
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
|
|
2424
|
+
* RSV1 bit
|
|
2425
|
+
* @param {Function} [cb] Callback
|
|
2426
|
+
* @private
|
|
2427
|
+
*/
|
|
2428
|
+
getBlobData(blob, compress, options, cb) {
|
|
2429
|
+
this._bufferedBytes += options[kByteLength];
|
|
2430
|
+
this._state = GET_BLOB_DATA;
|
|
2431
|
+
|
|
2432
|
+
blob
|
|
2433
|
+
.arrayBuffer()
|
|
2434
|
+
.then((arrayBuffer) => {
|
|
2435
|
+
if (this._socket.destroyed) {
|
|
2436
|
+
const err = new Error(
|
|
2437
|
+
'The socket was closed while the blob was being read'
|
|
2438
|
+
);
|
|
2439
|
+
|
|
2440
|
+
//
|
|
2441
|
+
// `callCallbacks` is called in the next tick to ensure that errors
|
|
2442
|
+
// that might be thrown in the callbacks behave like errors thrown
|
|
2443
|
+
// outside the promise chain.
|
|
2444
|
+
//
|
|
2445
|
+
process.nextTick(callCallbacks, this, err, cb);
|
|
2446
|
+
return;
|
|
2447
|
+
}
|
|
2448
|
+
|
|
2449
|
+
this._bufferedBytes -= options[kByteLength];
|
|
2450
|
+
const data = toBuffer$1(arrayBuffer);
|
|
2451
|
+
|
|
2452
|
+
if (!compress) {
|
|
2453
|
+
this._state = DEFAULT;
|
|
2454
|
+
this.sendFrame(Sender.frame(data, options), cb);
|
|
2455
|
+
this.dequeue();
|
|
2456
|
+
} else {
|
|
2457
|
+
this.dispatch(data, compress, options, cb);
|
|
2458
|
+
}
|
|
2459
|
+
})
|
|
2460
|
+
.catch((err) => {
|
|
2461
|
+
//
|
|
2462
|
+
// `onError` is called in the next tick for the same reason that
|
|
2463
|
+
// `callCallbacks` above is.
|
|
2464
|
+
//
|
|
2465
|
+
process.nextTick(onError, this, err, cb);
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
/**
|
|
2470
|
+
* Dispatches a message.
|
|
2471
|
+
*
|
|
2472
|
+
* @param {(Buffer|String)} data The message to send
|
|
2473
|
+
* @param {Boolean} [compress=false] Specifies whether or not to compress
|
|
2474
|
+
* `data`
|
|
2475
|
+
* @param {Object} options Options object
|
|
2138
2476
|
* @param {Boolean} [options.fin=false] Specifies whether or not to set the
|
|
2139
2477
|
* FIN bit
|
|
2478
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
2479
|
+
* masking key
|
|
2140
2480
|
* @param {Boolean} [options.mask=false] Specifies whether or not to mask
|
|
2141
2481
|
* `data`
|
|
2482
|
+
* @param {Buffer} [options.maskBuffer] The buffer used to store the masking
|
|
2483
|
+
* key
|
|
2484
|
+
* @param {Number} options.opcode The opcode
|
|
2485
|
+
* @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
|
|
2486
|
+
* modified
|
|
2142
2487
|
* @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
|
|
2143
2488
|
* RSV1 bit
|
|
2144
2489
|
* @param {Function} [cb] Callback
|
|
@@ -2152,27 +2497,20 @@ let Sender$1 = class Sender {
|
|
|
2152
2497
|
|
|
2153
2498
|
const perMessageDeflate = this._extensions[PerMessageDeflate$2.extensionName];
|
|
2154
2499
|
|
|
2155
|
-
this._bufferedBytes +=
|
|
2156
|
-
this.
|
|
2500
|
+
this._bufferedBytes += options[kByteLength];
|
|
2501
|
+
this._state = DEFLATING;
|
|
2157
2502
|
perMessageDeflate.compress(data, options.fin, (_, buf) => {
|
|
2158
2503
|
if (this._socket.destroyed) {
|
|
2159
2504
|
const err = new Error(
|
|
2160
2505
|
'The socket was closed while data was being compressed'
|
|
2161
2506
|
);
|
|
2162
2507
|
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
for (let i = 0; i < this._queue.length; i++) {
|
|
2166
|
-
const callback = this._queue[i][4];
|
|
2167
|
-
|
|
2168
|
-
if (typeof callback === 'function') callback(err);
|
|
2169
|
-
}
|
|
2170
|
-
|
|
2508
|
+
callCallbacks(this, err, cb);
|
|
2171
2509
|
return;
|
|
2172
2510
|
}
|
|
2173
2511
|
|
|
2174
|
-
this._bufferedBytes -=
|
|
2175
|
-
this.
|
|
2512
|
+
this._bufferedBytes -= options[kByteLength];
|
|
2513
|
+
this._state = DEFAULT;
|
|
2176
2514
|
options.readOnly = false;
|
|
2177
2515
|
this.sendFrame(Sender.frame(buf, options), cb);
|
|
2178
2516
|
this.dequeue();
|
|
@@ -2185,10 +2523,10 @@ let Sender$1 = class Sender {
|
|
|
2185
2523
|
* @private
|
|
2186
2524
|
*/
|
|
2187
2525
|
dequeue() {
|
|
2188
|
-
while (
|
|
2526
|
+
while (this._state === DEFAULT && this._queue.length) {
|
|
2189
2527
|
const params = this._queue.shift();
|
|
2190
2528
|
|
|
2191
|
-
this._bufferedBytes -= params[
|
|
2529
|
+
this._bufferedBytes -= params[3][kByteLength];
|
|
2192
2530
|
Reflect.apply(params[0], this, params.slice(1));
|
|
2193
2531
|
}
|
|
2194
2532
|
}
|
|
@@ -2200,14 +2538,14 @@ let Sender$1 = class Sender {
|
|
|
2200
2538
|
* @private
|
|
2201
2539
|
*/
|
|
2202
2540
|
enqueue(params) {
|
|
2203
|
-
this._bufferedBytes += params[
|
|
2541
|
+
this._bufferedBytes += params[3][kByteLength];
|
|
2204
2542
|
this._queue.push(params);
|
|
2205
2543
|
}
|
|
2206
2544
|
|
|
2207
2545
|
/**
|
|
2208
2546
|
* Sends a frame.
|
|
2209
2547
|
*
|
|
2210
|
-
* @param {Buffer[]} list The frame to send
|
|
2548
|
+
* @param {(Buffer | String)[]} list The frame to send
|
|
2211
2549
|
* @param {Function} [cb] Callback
|
|
2212
2550
|
* @private
|
|
2213
2551
|
*/
|
|
@@ -2226,111 +2564,204 @@ let Sender$1 = class Sender {
|
|
|
2226
2564
|
var sender = Sender$1;
|
|
2227
2565
|
|
|
2228
2566
|
/**
|
|
2229
|
-
*
|
|
2567
|
+
* Calls queued callbacks with an error.
|
|
2230
2568
|
*
|
|
2569
|
+
* @param {Sender} sender The `Sender` instance
|
|
2570
|
+
* @param {Error} err The error to call the callbacks with
|
|
2571
|
+
* @param {Function} [cb] The first callback
|
|
2231
2572
|
* @private
|
|
2232
2573
|
*/
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
constructor(type, target) {
|
|
2242
|
-
this.target = target;
|
|
2243
|
-
this.type = type;
|
|
2574
|
+
function callCallbacks(sender, err, cb) {
|
|
2575
|
+
if (typeof cb === 'function') cb(err);
|
|
2576
|
+
|
|
2577
|
+
for (let i = 0; i < sender._queue.length; i++) {
|
|
2578
|
+
const params = sender._queue[i];
|
|
2579
|
+
const callback = params[params.length - 1];
|
|
2580
|
+
|
|
2581
|
+
if (typeof callback === 'function') callback(err);
|
|
2244
2582
|
}
|
|
2245
2583
|
}
|
|
2246
2584
|
|
|
2247
2585
|
/**
|
|
2248
|
-
*
|
|
2586
|
+
* Handles a `Sender` error.
|
|
2249
2587
|
*
|
|
2250
|
-
* @
|
|
2588
|
+
* @param {Sender} sender The `Sender` instance
|
|
2589
|
+
* @param {Error} err The error
|
|
2590
|
+
* @param {Function} [cb] The first pending callback
|
|
2251
2591
|
* @private
|
|
2252
2592
|
*/
|
|
2253
|
-
|
|
2593
|
+
function onError(sender, err, cb) {
|
|
2594
|
+
callCallbacks(sender, err, cb);
|
|
2595
|
+
sender.onerror(err);
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
const { kForOnEventAttribute: kForOnEventAttribute$1, kListener: kListener$1 } = constants;
|
|
2599
|
+
|
|
2600
|
+
const kCode = Symbol('kCode');
|
|
2601
|
+
const kData = Symbol('kData');
|
|
2602
|
+
const kError = Symbol('kError');
|
|
2603
|
+
const kMessage = Symbol('kMessage');
|
|
2604
|
+
const kReason = Symbol('kReason');
|
|
2605
|
+
const kTarget = Symbol('kTarget');
|
|
2606
|
+
const kType = Symbol('kType');
|
|
2607
|
+
const kWasClean = Symbol('kWasClean');
|
|
2608
|
+
|
|
2609
|
+
/**
|
|
2610
|
+
* Class representing an event.
|
|
2611
|
+
*/
|
|
2612
|
+
class Event {
|
|
2254
2613
|
/**
|
|
2255
|
-
* Create a new `
|
|
2614
|
+
* Create a new `Event`.
|
|
2256
2615
|
*
|
|
2257
|
-
* @param {
|
|
2258
|
-
* @
|
|
2259
|
-
* dispatched
|
|
2616
|
+
* @param {String} type The name of the event
|
|
2617
|
+
* @throws {TypeError} If the `type` argument is not specified
|
|
2260
2618
|
*/
|
|
2261
|
-
constructor(
|
|
2262
|
-
|
|
2619
|
+
constructor(type) {
|
|
2620
|
+
this[kTarget] = null;
|
|
2621
|
+
this[kType] = type;
|
|
2622
|
+
}
|
|
2263
2623
|
|
|
2264
|
-
|
|
2624
|
+
/**
|
|
2625
|
+
* @type {*}
|
|
2626
|
+
*/
|
|
2627
|
+
get target() {
|
|
2628
|
+
return this[kTarget];
|
|
2629
|
+
}
|
|
2630
|
+
|
|
2631
|
+
/**
|
|
2632
|
+
* @type {String}
|
|
2633
|
+
*/
|
|
2634
|
+
get type() {
|
|
2635
|
+
return this[kType];
|
|
2265
2636
|
}
|
|
2266
2637
|
}
|
|
2267
2638
|
|
|
2639
|
+
Object.defineProperty(Event.prototype, 'target', { enumerable: true });
|
|
2640
|
+
Object.defineProperty(Event.prototype, 'type', { enumerable: true });
|
|
2641
|
+
|
|
2268
2642
|
/**
|
|
2269
2643
|
* Class representing a close event.
|
|
2270
2644
|
*
|
|
2271
2645
|
* @extends Event
|
|
2272
|
-
* @private
|
|
2273
2646
|
*/
|
|
2274
2647
|
class CloseEvent extends Event {
|
|
2275
2648
|
/**
|
|
2276
2649
|
* Create a new `CloseEvent`.
|
|
2277
2650
|
*
|
|
2278
|
-
* @param {
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2281
|
-
*
|
|
2282
|
-
*
|
|
2283
|
-
*
|
|
2651
|
+
* @param {String} type The name of the event
|
|
2652
|
+
* @param {Object} [options] A dictionary object that allows for setting
|
|
2653
|
+
* attributes via object members of the same name
|
|
2654
|
+
* @param {Number} [options.code=0] The status code explaining why the
|
|
2655
|
+
* connection was closed
|
|
2656
|
+
* @param {String} [options.reason=''] A human-readable string explaining why
|
|
2657
|
+
* the connection was closed
|
|
2658
|
+
* @param {Boolean} [options.wasClean=false] Indicates whether or not the
|
|
2659
|
+
* connection was cleanly closed
|
|
2284
2660
|
*/
|
|
2285
|
-
constructor(
|
|
2286
|
-
super(
|
|
2661
|
+
constructor(type, options = {}) {
|
|
2662
|
+
super(type);
|
|
2287
2663
|
|
|
2288
|
-
this
|
|
2289
|
-
this.reason
|
|
2290
|
-
this
|
|
2664
|
+
this[kCode] = options.code === undefined ? 0 : options.code;
|
|
2665
|
+
this[kReason] = options.reason === undefined ? '' : options.reason;
|
|
2666
|
+
this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
/**
|
|
2670
|
+
* @type {Number}
|
|
2671
|
+
*/
|
|
2672
|
+
get code() {
|
|
2673
|
+
return this[kCode];
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
/**
|
|
2677
|
+
* @type {String}
|
|
2678
|
+
*/
|
|
2679
|
+
get reason() {
|
|
2680
|
+
return this[kReason];
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
/**
|
|
2684
|
+
* @type {Boolean}
|
|
2685
|
+
*/
|
|
2686
|
+
get wasClean() {
|
|
2687
|
+
return this[kWasClean];
|
|
2291
2688
|
}
|
|
2292
2689
|
}
|
|
2293
2690
|
|
|
2691
|
+
Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });
|
|
2692
|
+
Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });
|
|
2693
|
+
Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });
|
|
2694
|
+
|
|
2294
2695
|
/**
|
|
2295
|
-
* Class representing an
|
|
2696
|
+
* Class representing an error event.
|
|
2296
2697
|
*
|
|
2297
2698
|
* @extends Event
|
|
2298
|
-
* @private
|
|
2299
2699
|
*/
|
|
2300
|
-
class
|
|
2700
|
+
class ErrorEvent extends Event {
|
|
2301
2701
|
/**
|
|
2302
|
-
* Create a new `
|
|
2702
|
+
* Create a new `ErrorEvent`.
|
|
2303
2703
|
*
|
|
2304
|
-
* @param {
|
|
2305
|
-
*
|
|
2704
|
+
* @param {String} type The name of the event
|
|
2705
|
+
* @param {Object} [options] A dictionary object that allows for setting
|
|
2706
|
+
* attributes via object members of the same name
|
|
2707
|
+
* @param {*} [options.error=null] The error that generated this event
|
|
2708
|
+
* @param {String} [options.message=''] The error message
|
|
2709
|
+
*/
|
|
2710
|
+
constructor(type, options = {}) {
|
|
2711
|
+
super(type);
|
|
2712
|
+
|
|
2713
|
+
this[kError] = options.error === undefined ? null : options.error;
|
|
2714
|
+
this[kMessage] = options.message === undefined ? '' : options.message;
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
/**
|
|
2718
|
+
* @type {*}
|
|
2306
2719
|
*/
|
|
2307
|
-
|
|
2308
|
-
|
|
2720
|
+
get error() {
|
|
2721
|
+
return this[kError];
|
|
2722
|
+
}
|
|
2723
|
+
|
|
2724
|
+
/**
|
|
2725
|
+
* @type {String}
|
|
2726
|
+
*/
|
|
2727
|
+
get message() {
|
|
2728
|
+
return this[kMessage];
|
|
2309
2729
|
}
|
|
2310
2730
|
}
|
|
2311
2731
|
|
|
2732
|
+
Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });
|
|
2733
|
+
Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });
|
|
2734
|
+
|
|
2312
2735
|
/**
|
|
2313
|
-
* Class representing
|
|
2736
|
+
* Class representing a message event.
|
|
2314
2737
|
*
|
|
2315
2738
|
* @extends Event
|
|
2316
|
-
* @private
|
|
2317
2739
|
*/
|
|
2318
|
-
class
|
|
2740
|
+
class MessageEvent extends Event {
|
|
2319
2741
|
/**
|
|
2320
|
-
* Create a new `
|
|
2742
|
+
* Create a new `MessageEvent`.
|
|
2321
2743
|
*
|
|
2322
|
-
* @param {
|
|
2323
|
-
* @param {
|
|
2324
|
-
*
|
|
2744
|
+
* @param {String} type The name of the event
|
|
2745
|
+
* @param {Object} [options] A dictionary object that allows for setting
|
|
2746
|
+
* attributes via object members of the same name
|
|
2747
|
+
* @param {*} [options.data=null] The message content
|
|
2325
2748
|
*/
|
|
2326
|
-
constructor(
|
|
2327
|
-
super(
|
|
2749
|
+
constructor(type, options = {}) {
|
|
2750
|
+
super(type);
|
|
2328
2751
|
|
|
2329
|
-
this
|
|
2330
|
-
|
|
2752
|
+
this[kData] = options.data === undefined ? null : options.data;
|
|
2753
|
+
}
|
|
2754
|
+
|
|
2755
|
+
/**
|
|
2756
|
+
* @type {*}
|
|
2757
|
+
*/
|
|
2758
|
+
get data() {
|
|
2759
|
+
return this[kData];
|
|
2331
2760
|
}
|
|
2332
2761
|
}
|
|
2333
2762
|
|
|
2763
|
+
Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });
|
|
2764
|
+
|
|
2334
2765
|
/**
|
|
2335
2766
|
* This provides methods for emulating the `EventTarget` interface. It's not
|
|
2336
2767
|
* meant to be used directly.
|
|
@@ -2342,49 +2773,75 @@ const EventTarget = {
|
|
|
2342
2773
|
* Register an event listener.
|
|
2343
2774
|
*
|
|
2344
2775
|
* @param {String} type A string representing the event type to listen for
|
|
2345
|
-
* @param {Function}
|
|
2776
|
+
* @param {(Function|Object)} handler The listener to add
|
|
2346
2777
|
* @param {Object} [options] An options object specifies characteristics about
|
|
2347
2778
|
* the event listener
|
|
2348
|
-
* @param {Boolean} [options.once=false] A `Boolean
|
|
2779
|
+
* @param {Boolean} [options.once=false] A `Boolean` indicating that the
|
|
2349
2780
|
* listener should be invoked at most once after being added. If `true`,
|
|
2350
2781
|
* the listener would be automatically removed when invoked.
|
|
2351
2782
|
* @public
|
|
2352
2783
|
*/
|
|
2353
|
-
addEventListener(type,
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
}
|
|
2363
|
-
|
|
2364
|
-
function onError(error) {
|
|
2365
|
-
listener.call(this, new ErrorEvent(error, this));
|
|
2366
|
-
}
|
|
2367
|
-
|
|
2368
|
-
function onOpen() {
|
|
2369
|
-
listener.call(this, new OpenEvent(this));
|
|
2784
|
+
addEventListener(type, handler, options = {}) {
|
|
2785
|
+
for (const listener of this.listeners(type)) {
|
|
2786
|
+
if (
|
|
2787
|
+
!options[kForOnEventAttribute$1] &&
|
|
2788
|
+
listener[kListener$1] === handler &&
|
|
2789
|
+
!listener[kForOnEventAttribute$1]
|
|
2790
|
+
) {
|
|
2791
|
+
return;
|
|
2792
|
+
}
|
|
2370
2793
|
}
|
|
2371
2794
|
|
|
2372
|
-
|
|
2795
|
+
let wrapper;
|
|
2373
2796
|
|
|
2374
2797
|
if (type === 'message') {
|
|
2375
|
-
|
|
2376
|
-
|
|
2798
|
+
wrapper = function onMessage(data, isBinary) {
|
|
2799
|
+
const event = new MessageEvent('message', {
|
|
2800
|
+
data: isBinary ? data : data.toString()
|
|
2801
|
+
});
|
|
2802
|
+
|
|
2803
|
+
event[kTarget] = this;
|
|
2804
|
+
callListener(handler, this, event);
|
|
2805
|
+
};
|
|
2377
2806
|
} else if (type === 'close') {
|
|
2378
|
-
|
|
2379
|
-
|
|
2807
|
+
wrapper = function onClose(code, message) {
|
|
2808
|
+
const event = new CloseEvent('close', {
|
|
2809
|
+
code,
|
|
2810
|
+
reason: message.toString(),
|
|
2811
|
+
wasClean: this._closeFrameReceived && this._closeFrameSent
|
|
2812
|
+
});
|
|
2813
|
+
|
|
2814
|
+
event[kTarget] = this;
|
|
2815
|
+
callListener(handler, this, event);
|
|
2816
|
+
};
|
|
2380
2817
|
} else if (type === 'error') {
|
|
2381
|
-
|
|
2382
|
-
|
|
2818
|
+
wrapper = function onError(error) {
|
|
2819
|
+
const event = new ErrorEvent('error', {
|
|
2820
|
+
error,
|
|
2821
|
+
message: error.message
|
|
2822
|
+
});
|
|
2823
|
+
|
|
2824
|
+
event[kTarget] = this;
|
|
2825
|
+
callListener(handler, this, event);
|
|
2826
|
+
};
|
|
2383
2827
|
} else if (type === 'open') {
|
|
2384
|
-
|
|
2385
|
-
|
|
2828
|
+
wrapper = function onOpen() {
|
|
2829
|
+
const event = new Event('open');
|
|
2830
|
+
|
|
2831
|
+
event[kTarget] = this;
|
|
2832
|
+
callListener(handler, this, event);
|
|
2833
|
+
};
|
|
2386
2834
|
} else {
|
|
2387
|
-
|
|
2835
|
+
return;
|
|
2836
|
+
}
|
|
2837
|
+
|
|
2838
|
+
wrapper[kForOnEventAttribute$1] = !!options[kForOnEventAttribute$1];
|
|
2839
|
+
wrapper[kListener$1] = handler;
|
|
2840
|
+
|
|
2841
|
+
if (options.once) {
|
|
2842
|
+
this.once(type, wrapper);
|
|
2843
|
+
} else {
|
|
2844
|
+
this.on(type, wrapper);
|
|
2388
2845
|
}
|
|
2389
2846
|
},
|
|
2390
2847
|
|
|
@@ -2392,44 +2849,39 @@ const EventTarget = {
|
|
|
2392
2849
|
* Remove an event listener.
|
|
2393
2850
|
*
|
|
2394
2851
|
* @param {String} type A string representing the event type to remove
|
|
2395
|
-
* @param {Function}
|
|
2852
|
+
* @param {(Function|Object)} handler The listener to remove
|
|
2396
2853
|
* @public
|
|
2397
2854
|
*/
|
|
2398
|
-
removeEventListener(type,
|
|
2399
|
-
const
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
this.removeListener(type, listeners[i]);
|
|
2855
|
+
removeEventListener(type, handler) {
|
|
2856
|
+
for (const listener of this.listeners(type)) {
|
|
2857
|
+
if (listener[kListener$1] === handler && !listener[kForOnEventAttribute$1]) {
|
|
2858
|
+
this.removeListener(type, listener);
|
|
2859
|
+
break;
|
|
2404
2860
|
}
|
|
2405
2861
|
}
|
|
2406
2862
|
}
|
|
2407
2863
|
};
|
|
2408
2864
|
|
|
2409
|
-
var eventTarget =
|
|
2865
|
+
var eventTarget = {
|
|
2866
|
+
EventTarget};
|
|
2410
2867
|
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
|
|
2429
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
|
|
2430
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
|
|
2431
|
-
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
|
|
2432
|
-
];
|
|
2868
|
+
/**
|
|
2869
|
+
* Call an event listener
|
|
2870
|
+
*
|
|
2871
|
+
* @param {(Function|Object)} listener The listener to call
|
|
2872
|
+
* @param {*} thisArg The value to use as `this`` when calling the listener
|
|
2873
|
+
* @param {Event} event The event to pass to the listener
|
|
2874
|
+
* @private
|
|
2875
|
+
*/
|
|
2876
|
+
function callListener(listener, thisArg, event) {
|
|
2877
|
+
if (typeof listener === 'object' && listener.handleEvent) {
|
|
2878
|
+
listener.handleEvent.call(listener, event);
|
|
2879
|
+
} else {
|
|
2880
|
+
listener.call(thisArg, event);
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
|
|
2884
|
+
const { tokenChars: tokenChars$1 } = validationExports;
|
|
2433
2885
|
|
|
2434
2886
|
/**
|
|
2435
2887
|
* Adds an offer to the map of extension offers or a parameter to the map of
|
|
@@ -2455,9 +2907,6 @@ function push(dest, name, elem) {
|
|
|
2455
2907
|
*/
|
|
2456
2908
|
function parse$2(header) {
|
|
2457
2909
|
const offers = Object.create(null);
|
|
2458
|
-
|
|
2459
|
-
if (header === undefined || header === '') return offers;
|
|
2460
|
-
|
|
2461
2910
|
let params = Object.create(null);
|
|
2462
2911
|
let mustUnescape = false;
|
|
2463
2912
|
let isEscaping = false;
|
|
@@ -2465,16 +2914,20 @@ function parse$2(header) {
|
|
|
2465
2914
|
let extensionName;
|
|
2466
2915
|
let paramName;
|
|
2467
2916
|
let start = -1;
|
|
2917
|
+
let code = -1;
|
|
2468
2918
|
let end = -1;
|
|
2469
2919
|
let i = 0;
|
|
2470
2920
|
|
|
2471
2921
|
for (; i < header.length; i++) {
|
|
2472
|
-
|
|
2922
|
+
code = header.charCodeAt(i);
|
|
2473
2923
|
|
|
2474
2924
|
if (extensionName === undefined) {
|
|
2475
|
-
if (end === -1 && tokenChars[code] === 1) {
|
|
2925
|
+
if (end === -1 && tokenChars$1[code] === 1) {
|
|
2476
2926
|
if (start === -1) start = i;
|
|
2477
|
-
} else if (
|
|
2927
|
+
} else if (
|
|
2928
|
+
i !== 0 &&
|
|
2929
|
+
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
|
2930
|
+
) {
|
|
2478
2931
|
if (end === -1 && start !== -1) end = i;
|
|
2479
2932
|
} else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
|
|
2480
2933
|
if (start === -1) {
|
|
@@ -2495,7 +2948,7 @@ function parse$2(header) {
|
|
|
2495
2948
|
throw new SyntaxError(`Unexpected character at index ${i}`);
|
|
2496
2949
|
}
|
|
2497
2950
|
} else if (paramName === undefined) {
|
|
2498
|
-
if (end === -1 && tokenChars[code] === 1) {
|
|
2951
|
+
if (end === -1 && tokenChars$1[code] === 1) {
|
|
2499
2952
|
if (start === -1) start = i;
|
|
2500
2953
|
} else if (code === 0x20 || code === 0x09) {
|
|
2501
2954
|
if (end === -1 && start !== -1) end = i;
|
|
@@ -2526,14 +2979,14 @@ function parse$2(header) {
|
|
|
2526
2979
|
// Ref: https://tools.ietf.org/html/rfc6455#section-9.1
|
|
2527
2980
|
//
|
|
2528
2981
|
if (isEscaping) {
|
|
2529
|
-
if (tokenChars[code] !== 1) {
|
|
2982
|
+
if (tokenChars$1[code] !== 1) {
|
|
2530
2983
|
throw new SyntaxError(`Unexpected character at index ${i}`);
|
|
2531
2984
|
}
|
|
2532
2985
|
if (start === -1) start = i;
|
|
2533
2986
|
else if (!mustUnescape) mustUnescape = true;
|
|
2534
2987
|
isEscaping = false;
|
|
2535
2988
|
} else if (inQuotes) {
|
|
2536
|
-
if (tokenChars[code] === 1) {
|
|
2989
|
+
if (tokenChars$1[code] === 1) {
|
|
2537
2990
|
if (start === -1) start = i;
|
|
2538
2991
|
} else if (code === 0x22 /* '"' */ && start !== -1) {
|
|
2539
2992
|
inQuotes = false;
|
|
@@ -2545,7 +2998,7 @@ function parse$2(header) {
|
|
|
2545
2998
|
}
|
|
2546
2999
|
} else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
|
|
2547
3000
|
inQuotes = true;
|
|
2548
|
-
} else if (end === -1 && tokenChars[code] === 1) {
|
|
3001
|
+
} else if (end === -1 && tokenChars$1[code] === 1) {
|
|
2549
3002
|
if (start === -1) start = i;
|
|
2550
3003
|
} else if (start !== -1 && (code === 0x20 || code === 0x09)) {
|
|
2551
3004
|
if (end === -1) end = i;
|
|
@@ -2575,7 +3028,7 @@ function parse$2(header) {
|
|
|
2575
3028
|
}
|
|
2576
3029
|
}
|
|
2577
3030
|
|
|
2578
|
-
if (start === -1 || inQuotes) {
|
|
3031
|
+
if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
|
|
2579
3032
|
throw new SyntaxError('Unexpected end of input');
|
|
2580
3033
|
}
|
|
2581
3034
|
|
|
@@ -2604,7 +3057,7 @@ function parse$2(header) {
|
|
|
2604
3057
|
* @return {String} A string representing the given object
|
|
2605
3058
|
* @public
|
|
2606
3059
|
*/
|
|
2607
|
-
function format$
|
|
3060
|
+
function format$1(extensions) {
|
|
2608
3061
|
return Object.keys(extensions)
|
|
2609
3062
|
.map((extension) => {
|
|
2610
3063
|
let configurations = extensions[extension];
|
|
@@ -2628,44 +3081,52 @@ function format$2(extensions) {
|
|
|
2628
3081
|
.join(', ');
|
|
2629
3082
|
}
|
|
2630
3083
|
|
|
2631
|
-
var extension = { format: format$
|
|
3084
|
+
var extension$1 = { format: format$1, parse: parse$2 };
|
|
2632
3085
|
|
|
2633
|
-
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Readable$" }] */
|
|
3086
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
|
|
2634
3087
|
|
|
2635
|
-
const EventEmitter$1 = require$$0$
|
|
2636
|
-
const https = require$$1$
|
|
3088
|
+
const EventEmitter$1 = require$$0$4;
|
|
3089
|
+
const https = require$$1$2;
|
|
2637
3090
|
const http$1 = require$$2$1;
|
|
2638
3091
|
const net = require$$3;
|
|
2639
3092
|
const tls = require$$4;
|
|
2640
|
-
const { randomBytes, createHash: createHash$1 } = require$$
|
|
2641
|
-
const { Readable } = require$$0$
|
|
3093
|
+
const { randomBytes, createHash: createHash$1 } = require$$1$1;
|
|
3094
|
+
const { Duplex: Duplex$2, Readable } = require$$0$3;
|
|
2642
3095
|
const { URL } = require$$7;
|
|
2643
3096
|
|
|
2644
3097
|
const PerMessageDeflate$1 = permessageDeflate;
|
|
2645
3098
|
const Receiver = receiver;
|
|
2646
3099
|
const Sender = sender;
|
|
3100
|
+
const { isBlob } = validationExports;
|
|
3101
|
+
|
|
2647
3102
|
const {
|
|
2648
3103
|
BINARY_TYPES,
|
|
3104
|
+
CLOSE_TIMEOUT: CLOSE_TIMEOUT$1,
|
|
2649
3105
|
EMPTY_BUFFER,
|
|
2650
3106
|
GUID: GUID$1,
|
|
3107
|
+
kForOnEventAttribute,
|
|
3108
|
+
kListener,
|
|
2651
3109
|
kStatusCode,
|
|
2652
3110
|
kWebSocket: kWebSocket$1,
|
|
2653
3111
|
NOOP
|
|
2654
3112
|
} = constants;
|
|
2655
|
-
const {
|
|
2656
|
-
|
|
3113
|
+
const {
|
|
3114
|
+
EventTarget: { addEventListener, removeEventListener }
|
|
3115
|
+
} = eventTarget;
|
|
3116
|
+
const { format, parse: parse$1 } = extension$1;
|
|
2657
3117
|
const { toBuffer } = bufferUtilExports;
|
|
2658
3118
|
|
|
2659
|
-
const
|
|
3119
|
+
const kAborted = Symbol('kAborted');
|
|
2660
3120
|
const protocolVersions = [8, 13];
|
|
2661
|
-
const
|
|
3121
|
+
const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
|
|
3122
|
+
const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
2662
3123
|
|
|
2663
3124
|
/**
|
|
2664
3125
|
* Class representing a WebSocket.
|
|
2665
3126
|
*
|
|
2666
3127
|
* @extends EventEmitter
|
|
2667
3128
|
*/
|
|
2668
|
-
let WebSocket$
|
|
3129
|
+
let WebSocket$1 = class WebSocket extends EventEmitter$1 {
|
|
2669
3130
|
/**
|
|
2670
3131
|
* Create a new `WebSocket`.
|
|
2671
3132
|
*
|
|
@@ -2680,9 +3141,11 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2680
3141
|
this._closeCode = 1006;
|
|
2681
3142
|
this._closeFrameReceived = false;
|
|
2682
3143
|
this._closeFrameSent = false;
|
|
2683
|
-
this._closeMessage =
|
|
3144
|
+
this._closeMessage = EMPTY_BUFFER;
|
|
2684
3145
|
this._closeTimer = null;
|
|
3146
|
+
this._errorEmitted = false;
|
|
2685
3147
|
this._extensions = {};
|
|
3148
|
+
this._paused = false;
|
|
2686
3149
|
this._protocol = '';
|
|
2687
3150
|
this._readyState = WebSocket.CONNECTING;
|
|
2688
3151
|
this._receiver = null;
|
|
@@ -2694,23 +3157,28 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2694
3157
|
this._isServer = false;
|
|
2695
3158
|
this._redirects = 0;
|
|
2696
3159
|
|
|
2697
|
-
if (
|
|
2698
|
-
protocols =
|
|
2699
|
-
} else if (
|
|
2700
|
-
|
|
2701
|
-
|
|
3160
|
+
if (protocols === undefined) {
|
|
3161
|
+
protocols = [];
|
|
3162
|
+
} else if (!Array.isArray(protocols)) {
|
|
3163
|
+
if (typeof protocols === 'object' && protocols !== null) {
|
|
3164
|
+
options = protocols;
|
|
3165
|
+
protocols = [];
|
|
3166
|
+
} else {
|
|
3167
|
+
protocols = [protocols];
|
|
3168
|
+
}
|
|
2702
3169
|
}
|
|
2703
3170
|
|
|
2704
3171
|
initAsClient(this, address, protocols, options);
|
|
2705
3172
|
} else {
|
|
3173
|
+
this._autoPong = options.autoPong;
|
|
3174
|
+
this._closeTimeout = options.closeTimeout;
|
|
2706
3175
|
this._isServer = true;
|
|
2707
3176
|
}
|
|
2708
3177
|
}
|
|
2709
3178
|
|
|
2710
3179
|
/**
|
|
2711
|
-
*
|
|
2712
|
-
*
|
|
2713
|
-
* type).
|
|
3180
|
+
* For historical reasons, the custom "nodebuffer" type is used by the default
|
|
3181
|
+
* instead of "blob".
|
|
2714
3182
|
*
|
|
2715
3183
|
* @type {String}
|
|
2716
3184
|
*/
|
|
@@ -2745,50 +3213,45 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2745
3213
|
return Object.keys(this._extensions).join();
|
|
2746
3214
|
}
|
|
2747
3215
|
|
|
3216
|
+
/**
|
|
3217
|
+
* @type {Boolean}
|
|
3218
|
+
*/
|
|
3219
|
+
get isPaused() {
|
|
3220
|
+
return this._paused;
|
|
3221
|
+
}
|
|
3222
|
+
|
|
2748
3223
|
/**
|
|
2749
3224
|
* @type {Function}
|
|
2750
3225
|
*/
|
|
2751
3226
|
/* istanbul ignore next */
|
|
2752
3227
|
get onclose() {
|
|
2753
|
-
return
|
|
3228
|
+
return null;
|
|
2754
3229
|
}
|
|
2755
3230
|
|
|
2756
|
-
/* istanbul ignore next */
|
|
2757
|
-
set onclose(listener) {}
|
|
2758
|
-
|
|
2759
3231
|
/**
|
|
2760
3232
|
* @type {Function}
|
|
2761
3233
|
*/
|
|
2762
3234
|
/* istanbul ignore next */
|
|
2763
3235
|
get onerror() {
|
|
2764
|
-
return
|
|
3236
|
+
return null;
|
|
2765
3237
|
}
|
|
2766
3238
|
|
|
2767
|
-
/* istanbul ignore next */
|
|
2768
|
-
set onerror(listener) {}
|
|
2769
|
-
|
|
2770
3239
|
/**
|
|
2771
3240
|
* @type {Function}
|
|
2772
3241
|
*/
|
|
2773
3242
|
/* istanbul ignore next */
|
|
2774
3243
|
get onopen() {
|
|
2775
|
-
return
|
|
3244
|
+
return null;
|
|
2776
3245
|
}
|
|
2777
3246
|
|
|
2778
|
-
/* istanbul ignore next */
|
|
2779
|
-
set onopen(listener) {}
|
|
2780
|
-
|
|
2781
3247
|
/**
|
|
2782
3248
|
* @type {Function}
|
|
2783
3249
|
*/
|
|
2784
3250
|
/* istanbul ignore next */
|
|
2785
3251
|
get onmessage() {
|
|
2786
|
-
return
|
|
3252
|
+
return null;
|
|
2787
3253
|
}
|
|
2788
3254
|
|
|
2789
|
-
/* istanbul ignore next */
|
|
2790
|
-
set onmessage(listener) {}
|
|
2791
|
-
|
|
2792
3255
|
/**
|
|
2793
3256
|
* @type {String}
|
|
2794
3257
|
*/
|
|
@@ -2813,25 +3276,37 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2813
3276
|
/**
|
|
2814
3277
|
* Set up the socket and the internal resources.
|
|
2815
3278
|
*
|
|
2816
|
-
* @param {
|
|
2817
|
-
* server and client
|
|
3279
|
+
* @param {Duplex} socket The network socket between the server and client
|
|
2818
3280
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
2819
|
-
* @param {
|
|
3281
|
+
* @param {Object} options Options object
|
|
3282
|
+
* @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
|
|
3283
|
+
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
|
3284
|
+
* multiple times in the same tick
|
|
3285
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
3286
|
+
* masking key
|
|
3287
|
+
* @param {Number} [options.maxPayload=0] The maximum allowed message size
|
|
3288
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
3289
|
+
* not to skip UTF-8 validation for text and close messages
|
|
2820
3290
|
* @private
|
|
2821
3291
|
*/
|
|
2822
|
-
setSocket(socket, head,
|
|
2823
|
-
const receiver = new Receiver(
|
|
2824
|
-
|
|
2825
|
-
this.
|
|
2826
|
-
this.
|
|
2827
|
-
|
|
2828
|
-
|
|
3292
|
+
setSocket(socket, head, options) {
|
|
3293
|
+
const receiver = new Receiver({
|
|
3294
|
+
allowSynchronousEvents: options.allowSynchronousEvents,
|
|
3295
|
+
binaryType: this.binaryType,
|
|
3296
|
+
extensions: this._extensions,
|
|
3297
|
+
isServer: this._isServer,
|
|
3298
|
+
maxPayload: options.maxPayload,
|
|
3299
|
+
skipUTF8Validation: options.skipUTF8Validation
|
|
3300
|
+
});
|
|
3301
|
+
|
|
3302
|
+
const sender = new Sender(socket, this._extensions, options.generateMask);
|
|
2829
3303
|
|
|
2830
|
-
this._sender = new Sender(socket, this._extensions);
|
|
2831
3304
|
this._receiver = receiver;
|
|
3305
|
+
this._sender = sender;
|
|
2832
3306
|
this._socket = socket;
|
|
2833
3307
|
|
|
2834
3308
|
receiver[kWebSocket$1] = this;
|
|
3309
|
+
sender[kWebSocket$1] = this;
|
|
2835
3310
|
socket[kWebSocket$1] = this;
|
|
2836
3311
|
|
|
2837
3312
|
receiver.on('conclude', receiverOnConclude);
|
|
@@ -2841,8 +3316,13 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2841
3316
|
receiver.on('ping', receiverOnPing);
|
|
2842
3317
|
receiver.on('pong', receiverOnPong);
|
|
2843
3318
|
|
|
2844
|
-
|
|
2845
|
-
|
|
3319
|
+
sender.onerror = senderOnError;
|
|
3320
|
+
|
|
3321
|
+
//
|
|
3322
|
+
// These methods may not be available if `socket` is just a `Duplex`.
|
|
3323
|
+
//
|
|
3324
|
+
if (socket.setTimeout) socket.setTimeout(0);
|
|
3325
|
+
if (socket.setNoDelay) socket.setNoDelay();
|
|
2846
3326
|
|
|
2847
3327
|
if (head.length > 0) socket.unshift(head);
|
|
2848
3328
|
|
|
@@ -2892,14 +3372,16 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2892
3372
|
* +---+
|
|
2893
3373
|
*
|
|
2894
3374
|
* @param {Number} [code] Status code explaining why the connection is closing
|
|
2895
|
-
* @param {String} [data]
|
|
3375
|
+
* @param {(String|Buffer)} [data] The reason why the connection is
|
|
3376
|
+
* closing
|
|
2896
3377
|
* @public
|
|
2897
3378
|
*/
|
|
2898
3379
|
close(code, data) {
|
|
2899
3380
|
if (this.readyState === WebSocket.CLOSED) return;
|
|
2900
3381
|
if (this.readyState === WebSocket.CONNECTING) {
|
|
2901
3382
|
const msg = 'WebSocket was closed before the connection was established';
|
|
2902
|
-
|
|
3383
|
+
abortHandshake$1(this, this._req, msg);
|
|
3384
|
+
return;
|
|
2903
3385
|
}
|
|
2904
3386
|
|
|
2905
3387
|
if (this.readyState === WebSocket.CLOSING) {
|
|
@@ -2931,13 +3413,24 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
2931
3413
|
}
|
|
2932
3414
|
});
|
|
2933
3415
|
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
3416
|
+
setCloseTimer(this);
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
/**
|
|
3420
|
+
* Pause the socket.
|
|
3421
|
+
*
|
|
3422
|
+
* @public
|
|
3423
|
+
*/
|
|
3424
|
+
pause() {
|
|
3425
|
+
if (
|
|
3426
|
+
this.readyState === WebSocket.CONNECTING ||
|
|
3427
|
+
this.readyState === WebSocket.CLOSED
|
|
3428
|
+
) {
|
|
3429
|
+
return;
|
|
3430
|
+
}
|
|
3431
|
+
|
|
3432
|
+
this._paused = true;
|
|
3433
|
+
this._socket.pause();
|
|
2941
3434
|
}
|
|
2942
3435
|
|
|
2943
3436
|
/**
|
|
@@ -3004,15 +3497,32 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
3004
3497
|
this._sender.pong(data || EMPTY_BUFFER, mask, cb);
|
|
3005
3498
|
}
|
|
3006
3499
|
|
|
3500
|
+
/**
|
|
3501
|
+
* Resume the socket.
|
|
3502
|
+
*
|
|
3503
|
+
* @public
|
|
3504
|
+
*/
|
|
3505
|
+
resume() {
|
|
3506
|
+
if (
|
|
3507
|
+
this.readyState === WebSocket.CONNECTING ||
|
|
3508
|
+
this.readyState === WebSocket.CLOSED
|
|
3509
|
+
) {
|
|
3510
|
+
return;
|
|
3511
|
+
}
|
|
3512
|
+
|
|
3513
|
+
this._paused = false;
|
|
3514
|
+
if (!this._receiver._writableState.needDrain) this._socket.resume();
|
|
3515
|
+
}
|
|
3516
|
+
|
|
3007
3517
|
/**
|
|
3008
3518
|
* Send a data message.
|
|
3009
3519
|
*
|
|
3010
3520
|
* @param {*} data The message to send
|
|
3011
3521
|
* @param {Object} [options] Options object
|
|
3012
|
-
* @param {Boolean} [options.compress] Specifies whether or not to compress
|
|
3013
|
-
* `data`
|
|
3014
3522
|
* @param {Boolean} [options.binary] Specifies whether `data` is binary or
|
|
3015
3523
|
* text
|
|
3524
|
+
* @param {Boolean} [options.compress] Specifies whether or not to compress
|
|
3525
|
+
* `data`
|
|
3016
3526
|
* @param {Boolean} [options.fin=true] Specifies whether the fragment is the
|
|
3017
3527
|
* last one
|
|
3018
3528
|
* @param {Boolean} [options.mask] Specifies whether or not to mask `data`
|
|
@@ -3060,7 +3570,8 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
3060
3570
|
if (this.readyState === WebSocket.CLOSED) return;
|
|
3061
3571
|
if (this.readyState === WebSocket.CONNECTING) {
|
|
3062
3572
|
const msg = 'WebSocket was closed before the connection was established';
|
|
3063
|
-
|
|
3573
|
+
abortHandshake$1(this, this._req, msg);
|
|
3574
|
+
return;
|
|
3064
3575
|
}
|
|
3065
3576
|
|
|
3066
3577
|
if (this._socket) {
|
|
@@ -3074,7 +3585,7 @@ let WebSocket$2 = class WebSocket extends EventEmitter$1 {
|
|
|
3074
3585
|
* @constant {Number} CONNECTING
|
|
3075
3586
|
* @memberof WebSocket
|
|
3076
3587
|
*/
|
|
3077
|
-
Object.defineProperty(WebSocket$
|
|
3588
|
+
Object.defineProperty(WebSocket$1, 'CONNECTING', {
|
|
3078
3589
|
enumerable: true,
|
|
3079
3590
|
value: readyStates.indexOf('CONNECTING')
|
|
3080
3591
|
});
|
|
@@ -3083,7 +3594,7 @@ Object.defineProperty(WebSocket$2, 'CONNECTING', {
|
|
|
3083
3594
|
* @constant {Number} CONNECTING
|
|
3084
3595
|
* @memberof WebSocket.prototype
|
|
3085
3596
|
*/
|
|
3086
|
-
Object.defineProperty(WebSocket$
|
|
3597
|
+
Object.defineProperty(WebSocket$1.prototype, 'CONNECTING', {
|
|
3087
3598
|
enumerable: true,
|
|
3088
3599
|
value: readyStates.indexOf('CONNECTING')
|
|
3089
3600
|
});
|
|
@@ -3092,7 +3603,7 @@ Object.defineProperty(WebSocket$2.prototype, 'CONNECTING', {
|
|
|
3092
3603
|
* @constant {Number} OPEN
|
|
3093
3604
|
* @memberof WebSocket
|
|
3094
3605
|
*/
|
|
3095
|
-
Object.defineProperty(WebSocket$
|
|
3606
|
+
Object.defineProperty(WebSocket$1, 'OPEN', {
|
|
3096
3607
|
enumerable: true,
|
|
3097
3608
|
value: readyStates.indexOf('OPEN')
|
|
3098
3609
|
});
|
|
@@ -3101,7 +3612,7 @@ Object.defineProperty(WebSocket$2, 'OPEN', {
|
|
|
3101
3612
|
* @constant {Number} OPEN
|
|
3102
3613
|
* @memberof WebSocket.prototype
|
|
3103
3614
|
*/
|
|
3104
|
-
Object.defineProperty(WebSocket$
|
|
3615
|
+
Object.defineProperty(WebSocket$1.prototype, 'OPEN', {
|
|
3105
3616
|
enumerable: true,
|
|
3106
3617
|
value: readyStates.indexOf('OPEN')
|
|
3107
3618
|
});
|
|
@@ -3110,7 +3621,7 @@ Object.defineProperty(WebSocket$2.prototype, 'OPEN', {
|
|
|
3110
3621
|
* @constant {Number} CLOSING
|
|
3111
3622
|
* @memberof WebSocket
|
|
3112
3623
|
*/
|
|
3113
|
-
Object.defineProperty(WebSocket$
|
|
3624
|
+
Object.defineProperty(WebSocket$1, 'CLOSING', {
|
|
3114
3625
|
enumerable: true,
|
|
3115
3626
|
value: readyStates.indexOf('CLOSING')
|
|
3116
3627
|
});
|
|
@@ -3119,7 +3630,7 @@ Object.defineProperty(WebSocket$2, 'CLOSING', {
|
|
|
3119
3630
|
* @constant {Number} CLOSING
|
|
3120
3631
|
* @memberof WebSocket.prototype
|
|
3121
3632
|
*/
|
|
3122
|
-
Object.defineProperty(WebSocket$
|
|
3633
|
+
Object.defineProperty(WebSocket$1.prototype, 'CLOSING', {
|
|
3123
3634
|
enumerable: true,
|
|
3124
3635
|
value: readyStates.indexOf('CLOSING')
|
|
3125
3636
|
});
|
|
@@ -3128,7 +3639,7 @@ Object.defineProperty(WebSocket$2.prototype, 'CLOSING', {
|
|
|
3128
3639
|
* @constant {Number} CLOSED
|
|
3129
3640
|
* @memberof WebSocket
|
|
3130
3641
|
*/
|
|
3131
|
-
Object.defineProperty(WebSocket$
|
|
3642
|
+
Object.defineProperty(WebSocket$1, 'CLOSED', {
|
|
3132
3643
|
enumerable: true,
|
|
3133
3644
|
value: readyStates.indexOf('CLOSED')
|
|
3134
3645
|
});
|
|
@@ -3137,7 +3648,7 @@ Object.defineProperty(WebSocket$2, 'CLOSED', {
|
|
|
3137
3648
|
* @constant {Number} CLOSED
|
|
3138
3649
|
* @memberof WebSocket.prototype
|
|
3139
3650
|
*/
|
|
3140
|
-
Object.defineProperty(WebSocket$
|
|
3651
|
+
Object.defineProperty(WebSocket$1.prototype, 'CLOSED', {
|
|
3141
3652
|
enumerable: true,
|
|
3142
3653
|
value: readyStates.indexOf('CLOSED')
|
|
3143
3654
|
});
|
|
@@ -3146,11 +3657,12 @@ Object.defineProperty(WebSocket$2.prototype, 'CLOSED', {
|
|
|
3146
3657
|
'binaryType',
|
|
3147
3658
|
'bufferedAmount',
|
|
3148
3659
|
'extensions',
|
|
3660
|
+
'isPaused',
|
|
3149
3661
|
'protocol',
|
|
3150
3662
|
'readyState',
|
|
3151
3663
|
'url'
|
|
3152
3664
|
].forEach((property) => {
|
|
3153
|
-
Object.defineProperty(WebSocket$
|
|
3665
|
+
Object.defineProperty(WebSocket$1.prototype, property, { enumerable: true });
|
|
3154
3666
|
});
|
|
3155
3667
|
|
|
3156
3668
|
//
|
|
@@ -3158,76 +3670,98 @@ Object.defineProperty(WebSocket$2.prototype, 'CLOSED', {
|
|
|
3158
3670
|
// See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
|
|
3159
3671
|
//
|
|
3160
3672
|
['open', 'error', 'close', 'message'].forEach((method) => {
|
|
3161
|
-
Object.defineProperty(WebSocket$
|
|
3673
|
+
Object.defineProperty(WebSocket$1.prototype, `on${method}`, {
|
|
3162
3674
|
enumerable: true,
|
|
3163
3675
|
get() {
|
|
3164
|
-
const
|
|
3165
|
-
|
|
3166
|
-
if (listeners[i]._listener) return listeners[i]._listener;
|
|
3676
|
+
for (const listener of this.listeners(method)) {
|
|
3677
|
+
if (listener[kForOnEventAttribute]) return listener[kListener];
|
|
3167
3678
|
}
|
|
3168
3679
|
|
|
3169
|
-
return
|
|
3680
|
+
return null;
|
|
3170
3681
|
},
|
|
3171
|
-
set(
|
|
3172
|
-
const
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
if (listeners[i]._listener) this.removeListener(method, listeners[i]);
|
|
3682
|
+
set(handler) {
|
|
3683
|
+
for (const listener of this.listeners(method)) {
|
|
3684
|
+
if (listener[kForOnEventAttribute]) {
|
|
3685
|
+
this.removeListener(method, listener);
|
|
3686
|
+
break;
|
|
3687
|
+
}
|
|
3178
3688
|
}
|
|
3179
|
-
|
|
3689
|
+
|
|
3690
|
+
if (typeof handler !== 'function') return;
|
|
3691
|
+
|
|
3692
|
+
this.addEventListener(method, handler, {
|
|
3693
|
+
[kForOnEventAttribute]: true
|
|
3694
|
+
});
|
|
3180
3695
|
}
|
|
3181
3696
|
});
|
|
3182
3697
|
});
|
|
3183
3698
|
|
|
3184
|
-
WebSocket$
|
|
3185
|
-
WebSocket$
|
|
3699
|
+
WebSocket$1.prototype.addEventListener = addEventListener;
|
|
3700
|
+
WebSocket$1.prototype.removeEventListener = removeEventListener;
|
|
3186
3701
|
|
|
3187
|
-
var websocket = WebSocket$
|
|
3702
|
+
var websocket = WebSocket$1;
|
|
3188
3703
|
|
|
3189
3704
|
/**
|
|
3190
3705
|
* Initialize a WebSocket client.
|
|
3191
3706
|
*
|
|
3192
3707
|
* @param {WebSocket} websocket The client to initialize
|
|
3193
3708
|
* @param {(String|URL)} address The URL to which to connect
|
|
3194
|
-
* @param {
|
|
3709
|
+
* @param {Array} protocols The subprotocols
|
|
3195
3710
|
* @param {Object} [options] Connection options
|
|
3196
|
-
* @param {
|
|
3197
|
-
*
|
|
3711
|
+
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
|
|
3712
|
+
* of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
|
|
3713
|
+
* times in the same tick
|
|
3714
|
+
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
|
|
3715
|
+
* automatically send a pong in response to a ping
|
|
3716
|
+
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to wait
|
|
3717
|
+
* for the closing handshake to finish after `websocket.close()` is called
|
|
3718
|
+
* @param {Function} [options.finishRequest] A function which can be used to
|
|
3719
|
+
* customize the headers of each http request before it is sent
|
|
3720
|
+
* @param {Boolean} [options.followRedirects=false] Whether or not to follow
|
|
3721
|
+
* redirects
|
|
3722
|
+
* @param {Function} [options.generateMask] The function used to generate the
|
|
3723
|
+
* masking key
|
|
3198
3724
|
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
|
|
3199
3725
|
* handshake request
|
|
3200
|
-
* @param {Number} [options.protocolVersion=13] Value of the
|
|
3201
|
-
* `Sec-WebSocket-Version` header
|
|
3202
|
-
* @param {String} [options.origin] Value of the `Origin` or
|
|
3203
|
-
* `Sec-WebSocket-Origin` header
|
|
3204
3726
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
3205
3727
|
* size
|
|
3206
|
-
* @param {Boolean} [options.followRedirects=false] Whether or not to follow
|
|
3207
|
-
* redirects
|
|
3208
3728
|
* @param {Number} [options.maxRedirects=10] The maximum number of redirects
|
|
3209
3729
|
* allowed
|
|
3730
|
+
* @param {String} [options.origin] Value of the `Origin` or
|
|
3731
|
+
* `Sec-WebSocket-Origin` header
|
|
3732
|
+
* @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
|
|
3733
|
+
* permessage-deflate
|
|
3734
|
+
* @param {Number} [options.protocolVersion=13] Value of the
|
|
3735
|
+
* `Sec-WebSocket-Version` header
|
|
3736
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
3737
|
+
* not to skip UTF-8 validation for text and close messages
|
|
3210
3738
|
* @private
|
|
3211
3739
|
*/
|
|
3212
3740
|
function initAsClient(websocket, address, protocols, options) {
|
|
3213
3741
|
const opts = {
|
|
3742
|
+
allowSynchronousEvents: true,
|
|
3743
|
+
autoPong: true,
|
|
3744
|
+
closeTimeout: CLOSE_TIMEOUT$1,
|
|
3214
3745
|
protocolVersion: protocolVersions[1],
|
|
3215
3746
|
maxPayload: 100 * 1024 * 1024,
|
|
3747
|
+
skipUTF8Validation: false,
|
|
3216
3748
|
perMessageDeflate: true,
|
|
3217
3749
|
followRedirects: false,
|
|
3218
3750
|
maxRedirects: 10,
|
|
3219
3751
|
...options,
|
|
3220
|
-
createConnection: undefined,
|
|
3221
3752
|
socketPath: undefined,
|
|
3222
3753
|
hostname: undefined,
|
|
3223
3754
|
protocol: undefined,
|
|
3224
3755
|
timeout: undefined,
|
|
3225
|
-
method:
|
|
3756
|
+
method: 'GET',
|
|
3226
3757
|
host: undefined,
|
|
3227
3758
|
path: undefined,
|
|
3228
3759
|
port: undefined
|
|
3229
3760
|
};
|
|
3230
3761
|
|
|
3762
|
+
websocket._autoPong = opts.autoPong;
|
|
3763
|
+
websocket._closeTimeout = opts.closeTimeout;
|
|
3764
|
+
|
|
3231
3765
|
if (!protocolVersions.includes(opts.protocolVersion)) {
|
|
3232
3766
|
throw new RangeError(
|
|
3233
3767
|
`Unsupported protocol version: ${opts.protocolVersion} ` +
|
|
@@ -3239,16 +3773,38 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3239
3773
|
|
|
3240
3774
|
if (address instanceof URL) {
|
|
3241
3775
|
parsedUrl = address;
|
|
3242
|
-
websocket._url = address.href;
|
|
3243
3776
|
} else {
|
|
3244
|
-
|
|
3245
|
-
|
|
3777
|
+
try {
|
|
3778
|
+
parsedUrl = new URL(address);
|
|
3779
|
+
} catch {
|
|
3780
|
+
throw new SyntaxError(`Invalid URL: ${address}`);
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3784
|
+
if (parsedUrl.protocol === 'http:') {
|
|
3785
|
+
parsedUrl.protocol = 'ws:';
|
|
3786
|
+
} else if (parsedUrl.protocol === 'https:') {
|
|
3787
|
+
parsedUrl.protocol = 'wss:';
|
|
3246
3788
|
}
|
|
3247
3789
|
|
|
3248
|
-
|
|
3790
|
+
websocket._url = parsedUrl.href;
|
|
3791
|
+
|
|
3792
|
+
const isSecure = parsedUrl.protocol === 'wss:';
|
|
3793
|
+
const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
|
|
3794
|
+
let invalidUrlMessage;
|
|
3249
3795
|
|
|
3250
|
-
if (
|
|
3251
|
-
|
|
3796
|
+
if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
|
|
3797
|
+
invalidUrlMessage =
|
|
3798
|
+
'The URL\'s protocol must be one of "ws:", "wss:", ' +
|
|
3799
|
+
'"http:", "https:", or "ws+unix:"';
|
|
3800
|
+
} else if (isIpcUrl && !parsedUrl.pathname) {
|
|
3801
|
+
invalidUrlMessage = "The URL's pathname is empty";
|
|
3802
|
+
} else if (parsedUrl.hash) {
|
|
3803
|
+
invalidUrlMessage = 'The URL contains a fragment identifier';
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3806
|
+
if (invalidUrlMessage) {
|
|
3807
|
+
const err = new SyntaxError(invalidUrlMessage);
|
|
3252
3808
|
|
|
3253
3809
|
if (websocket._redirects === 0) {
|
|
3254
3810
|
throw err;
|
|
@@ -3258,41 +3814,55 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3258
3814
|
}
|
|
3259
3815
|
}
|
|
3260
3816
|
|
|
3261
|
-
const isSecure =
|
|
3262
|
-
parsedUrl.protocol === 'wss:' || parsedUrl.protocol === 'https:';
|
|
3263
3817
|
const defaultPort = isSecure ? 443 : 80;
|
|
3264
3818
|
const key = randomBytes(16).toString('base64');
|
|
3265
|
-
const
|
|
3819
|
+
const request = isSecure ? https.request : http$1.request;
|
|
3820
|
+
const protocolSet = new Set();
|
|
3266
3821
|
let perMessageDeflate;
|
|
3267
3822
|
|
|
3268
|
-
opts.createConnection =
|
|
3823
|
+
opts.createConnection =
|
|
3824
|
+
opts.createConnection || (isSecure ? tlsConnect : netConnect);
|
|
3269
3825
|
opts.defaultPort = opts.defaultPort || defaultPort;
|
|
3270
3826
|
opts.port = parsedUrl.port || defaultPort;
|
|
3271
3827
|
opts.host = parsedUrl.hostname.startsWith('[')
|
|
3272
3828
|
? parsedUrl.hostname.slice(1, -1)
|
|
3273
3829
|
: parsedUrl.hostname;
|
|
3274
3830
|
opts.headers = {
|
|
3831
|
+
...opts.headers,
|
|
3275
3832
|
'Sec-WebSocket-Version': opts.protocolVersion,
|
|
3276
3833
|
'Sec-WebSocket-Key': key,
|
|
3277
3834
|
Connection: 'Upgrade',
|
|
3278
|
-
Upgrade: 'websocket'
|
|
3279
|
-
...opts.headers
|
|
3835
|
+
Upgrade: 'websocket'
|
|
3280
3836
|
};
|
|
3281
3837
|
opts.path = parsedUrl.pathname + parsedUrl.search;
|
|
3282
3838
|
opts.timeout = opts.handshakeTimeout;
|
|
3283
3839
|
|
|
3284
3840
|
if (opts.perMessageDeflate) {
|
|
3285
|
-
perMessageDeflate = new PerMessageDeflate$1(
|
|
3286
|
-
opts.perMessageDeflate
|
|
3287
|
-
false,
|
|
3288
|
-
opts.maxPayload
|
|
3289
|
-
);
|
|
3290
|
-
opts.headers['Sec-WebSocket-Extensions'] = format
|
|
3841
|
+
perMessageDeflate = new PerMessageDeflate$1({
|
|
3842
|
+
...opts.perMessageDeflate,
|
|
3843
|
+
isServer: false,
|
|
3844
|
+
maxPayload: opts.maxPayload
|
|
3845
|
+
});
|
|
3846
|
+
opts.headers['Sec-WebSocket-Extensions'] = format({
|
|
3291
3847
|
[PerMessageDeflate$1.extensionName]: perMessageDeflate.offer()
|
|
3292
3848
|
});
|
|
3293
3849
|
}
|
|
3294
|
-
if (protocols) {
|
|
3295
|
-
|
|
3850
|
+
if (protocols.length) {
|
|
3851
|
+
for (const protocol of protocols) {
|
|
3852
|
+
if (
|
|
3853
|
+
typeof protocol !== 'string' ||
|
|
3854
|
+
!subprotocolRegex.test(protocol) ||
|
|
3855
|
+
protocolSet.has(protocol)
|
|
3856
|
+
) {
|
|
3857
|
+
throw new SyntaxError(
|
|
3858
|
+
'An invalid or duplicated subprotocol was specified'
|
|
3859
|
+
);
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
protocolSet.add(protocol);
|
|
3863
|
+
}
|
|
3864
|
+
|
|
3865
|
+
opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');
|
|
3296
3866
|
}
|
|
3297
3867
|
if (opts.origin) {
|
|
3298
3868
|
if (opts.protocolVersion < 13) {
|
|
@@ -3305,18 +3875,20 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3305
3875
|
opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
|
|
3306
3876
|
}
|
|
3307
3877
|
|
|
3308
|
-
if (
|
|
3878
|
+
if (isIpcUrl) {
|
|
3309
3879
|
const parts = opts.path.split(':');
|
|
3310
3880
|
|
|
3311
3881
|
opts.socketPath = parts[0];
|
|
3312
3882
|
opts.path = parts[1];
|
|
3313
3883
|
}
|
|
3314
3884
|
|
|
3885
|
+
let req;
|
|
3886
|
+
|
|
3315
3887
|
if (opts.followRedirects) {
|
|
3316
3888
|
if (websocket._redirects === 0) {
|
|
3317
|
-
websocket.
|
|
3889
|
+
websocket._originalIpc = isIpcUrl;
|
|
3318
3890
|
websocket._originalSecure = isSecure;
|
|
3319
|
-
websocket._originalHostOrSocketPath =
|
|
3891
|
+
websocket._originalHostOrSocketPath = isIpcUrl
|
|
3320
3892
|
? opts.socketPath
|
|
3321
3893
|
: parsedUrl.host;
|
|
3322
3894
|
|
|
@@ -3333,14 +3905,14 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3333
3905
|
options.headers[key.toLowerCase()] = value;
|
|
3334
3906
|
}
|
|
3335
3907
|
}
|
|
3336
|
-
} else {
|
|
3337
|
-
const isSameHost =
|
|
3338
|
-
? websocket.
|
|
3908
|
+
} else if (websocket.listenerCount('redirect') === 0) {
|
|
3909
|
+
const isSameHost = isIpcUrl
|
|
3910
|
+
? websocket._originalIpc
|
|
3339
3911
|
? opts.socketPath === websocket._originalHostOrSocketPath
|
|
3340
3912
|
: false
|
|
3341
|
-
: websocket.
|
|
3342
|
-
|
|
3343
|
-
|
|
3913
|
+
: websocket._originalIpc
|
|
3914
|
+
? false
|
|
3915
|
+
: parsedUrl.host === websocket._originalHostOrSocketPath;
|
|
3344
3916
|
|
|
3345
3917
|
if (!isSameHost || (websocket._originalSecure && !isSecure)) {
|
|
3346
3918
|
//
|
|
@@ -3365,9 +3937,24 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3365
3937
|
options.headers.authorization =
|
|
3366
3938
|
'Basic ' + Buffer.from(opts.auth).toString('base64');
|
|
3367
3939
|
}
|
|
3368
|
-
}
|
|
3369
3940
|
|
|
3370
|
-
|
|
3941
|
+
req = websocket._req = request(opts);
|
|
3942
|
+
|
|
3943
|
+
if (websocket._redirects) {
|
|
3944
|
+
//
|
|
3945
|
+
// Unlike what is done for the `'upgrade'` event, no early exit is
|
|
3946
|
+
// triggered here if the user calls `websocket.close()` or
|
|
3947
|
+
// `websocket.terminate()` from a listener of the `'redirect'` event. This
|
|
3948
|
+
// is because the user can also call `request.destroy()` with an error
|
|
3949
|
+
// before calling `websocket.close()` or `websocket.terminate()` and this
|
|
3950
|
+
// would result in an error being emitted on the `request` object with no
|
|
3951
|
+
// `'error'` event listeners attached.
|
|
3952
|
+
//
|
|
3953
|
+
websocket.emit('redirect', websocket.url, req);
|
|
3954
|
+
}
|
|
3955
|
+
} else {
|
|
3956
|
+
req = websocket._req = request(opts);
|
|
3957
|
+
}
|
|
3371
3958
|
|
|
3372
3959
|
if (opts.timeout) {
|
|
3373
3960
|
req.on('timeout', () => {
|
|
@@ -3376,7 +3963,7 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3376
3963
|
}
|
|
3377
3964
|
|
|
3378
3965
|
req.on('error', (err) => {
|
|
3379
|
-
if (req === null || req
|
|
3966
|
+
if (req === null || req[kAborted]) return;
|
|
3380
3967
|
|
|
3381
3968
|
req = websocket._req = null;
|
|
3382
3969
|
emitErrorAndClose(websocket, err);
|
|
@@ -3403,7 +3990,8 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3403
3990
|
|
|
3404
3991
|
try {
|
|
3405
3992
|
addr = new URL(location, address);
|
|
3406
|
-
} catch (
|
|
3993
|
+
} catch (e) {
|
|
3994
|
+
const err = new SyntaxError(`Invalid URL: ${location}`);
|
|
3407
3995
|
emitErrorAndClose(websocket, err);
|
|
3408
3996
|
return;
|
|
3409
3997
|
}
|
|
@@ -3422,10 +4010,10 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3422
4010
|
websocket.emit('upgrade', res);
|
|
3423
4011
|
|
|
3424
4012
|
//
|
|
3425
|
-
// The user may have closed the connection from a listener of the
|
|
3426
|
-
// event.
|
|
4013
|
+
// The user may have closed the connection from a listener of the
|
|
4014
|
+
// `'upgrade'` event.
|
|
3427
4015
|
//
|
|
3428
|
-
if (websocket.readyState !== WebSocket$
|
|
4016
|
+
if (websocket.readyState !== WebSocket$1.CONNECTING) return;
|
|
3429
4017
|
|
|
3430
4018
|
req = websocket._req = null;
|
|
3431
4019
|
|
|
@@ -3446,15 +4034,16 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3446
4034
|
}
|
|
3447
4035
|
|
|
3448
4036
|
const serverProt = res.headers['sec-websocket-protocol'];
|
|
3449
|
-
const protList = (protocols || '').split(/, */);
|
|
3450
4037
|
let protError;
|
|
3451
4038
|
|
|
3452
|
-
if (
|
|
3453
|
-
|
|
3454
|
-
|
|
4039
|
+
if (serverProt !== undefined) {
|
|
4040
|
+
if (!protocolSet.size) {
|
|
4041
|
+
protError = 'Server sent a subprotocol but none was requested';
|
|
4042
|
+
} else if (!protocolSet.has(serverProt)) {
|
|
4043
|
+
protError = 'Server sent an invalid subprotocol';
|
|
4044
|
+
}
|
|
4045
|
+
} else if (protocolSet.size) {
|
|
3455
4046
|
protError = 'Server sent no subprotocol';
|
|
3456
|
-
} else if (serverProt && !protList.includes(serverProt)) {
|
|
3457
|
-
protError = 'Server sent an invalid subprotocol';
|
|
3458
4047
|
}
|
|
3459
4048
|
|
|
3460
4049
|
if (protError) {
|
|
@@ -3487,43 +4076,56 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
3487
4076
|
|
|
3488
4077
|
const extensionNames = Object.keys(extensions);
|
|
3489
4078
|
|
|
3490
|
-
if (
|
|
3491
|
-
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
return;
|
|
3499
|
-
}
|
|
3500
|
-
|
|
3501
|
-
try {
|
|
3502
|
-
perMessageDeflate.accept(extensions[PerMessageDeflate$1.extensionName]);
|
|
3503
|
-
} catch (err) {
|
|
3504
|
-
const message = 'Invalid Sec-WebSocket-Extensions header';
|
|
3505
|
-
abortHandshake$1(websocket, socket, message);
|
|
3506
|
-
return;
|
|
3507
|
-
}
|
|
4079
|
+
if (
|
|
4080
|
+
extensionNames.length !== 1 ||
|
|
4081
|
+
extensionNames[0] !== PerMessageDeflate$1.extensionName
|
|
4082
|
+
) {
|
|
4083
|
+
const message = 'Server indicated an extension that was not requested';
|
|
4084
|
+
abortHandshake$1(websocket, socket, message);
|
|
4085
|
+
return;
|
|
4086
|
+
}
|
|
3508
4087
|
|
|
3509
|
-
|
|
3510
|
-
|
|
4088
|
+
try {
|
|
4089
|
+
perMessageDeflate.accept(extensions[PerMessageDeflate$1.extensionName]);
|
|
4090
|
+
} catch (err) {
|
|
4091
|
+
const message = 'Invalid Sec-WebSocket-Extensions header';
|
|
4092
|
+
abortHandshake$1(websocket, socket, message);
|
|
4093
|
+
return;
|
|
3511
4094
|
}
|
|
4095
|
+
|
|
4096
|
+
websocket._extensions[PerMessageDeflate$1.extensionName] =
|
|
4097
|
+
perMessageDeflate;
|
|
3512
4098
|
}
|
|
3513
4099
|
|
|
3514
|
-
websocket.setSocket(socket, head,
|
|
4100
|
+
websocket.setSocket(socket, head, {
|
|
4101
|
+
allowSynchronousEvents: opts.allowSynchronousEvents,
|
|
4102
|
+
generateMask: opts.generateMask,
|
|
4103
|
+
maxPayload: opts.maxPayload,
|
|
4104
|
+
skipUTF8Validation: opts.skipUTF8Validation
|
|
4105
|
+
});
|
|
3515
4106
|
});
|
|
4107
|
+
|
|
4108
|
+
if (opts.finishRequest) {
|
|
4109
|
+
opts.finishRequest(req, websocket);
|
|
4110
|
+
} else {
|
|
4111
|
+
req.end();
|
|
4112
|
+
}
|
|
3516
4113
|
}
|
|
3517
4114
|
|
|
3518
4115
|
/**
|
|
3519
|
-
* Emit the `'error'` and `'close'`
|
|
4116
|
+
* Emit the `'error'` and `'close'` events.
|
|
3520
4117
|
*
|
|
3521
4118
|
* @param {WebSocket} websocket The WebSocket instance
|
|
3522
4119
|
* @param {Error} The error to emit
|
|
3523
4120
|
* @private
|
|
3524
4121
|
*/
|
|
3525
4122
|
function emitErrorAndClose(websocket, err) {
|
|
3526
|
-
websocket._readyState = WebSocket$
|
|
4123
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
4124
|
+
//
|
|
4125
|
+
// The following assignment is practically useless and is done only for
|
|
4126
|
+
// consistency.
|
|
4127
|
+
//
|
|
4128
|
+
websocket._errorEmitted = true;
|
|
3527
4129
|
websocket.emit('error', err);
|
|
3528
4130
|
websocket.emitClose();
|
|
3529
4131
|
}
|
|
@@ -3567,12 +4169,13 @@ function tlsConnect(options) {
|
|
|
3567
4169
|
* @private
|
|
3568
4170
|
*/
|
|
3569
4171
|
function abortHandshake$1(websocket, stream, message) {
|
|
3570
|
-
websocket._readyState = WebSocket$
|
|
4172
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
3571
4173
|
|
|
3572
4174
|
const err = new Error(message);
|
|
3573
4175
|
Error.captureStackTrace(err, abortHandshake$1);
|
|
3574
4176
|
|
|
3575
4177
|
if (stream.setHeader) {
|
|
4178
|
+
stream[kAborted] = true;
|
|
3576
4179
|
stream.abort();
|
|
3577
4180
|
|
|
3578
4181
|
if (stream.socket && !stream.socket.destroyed) {
|
|
@@ -3584,8 +4187,7 @@ function abortHandshake$1(websocket, stream, message) {
|
|
|
3584
4187
|
stream.socket.destroy();
|
|
3585
4188
|
}
|
|
3586
4189
|
|
|
3587
|
-
|
|
3588
|
-
websocket.emit('error', err);
|
|
4190
|
+
process.nextTick(emitErrorAndClose, websocket, err);
|
|
3589
4191
|
} else {
|
|
3590
4192
|
stream.destroy(err);
|
|
3591
4193
|
stream.once('error', websocket.emit.bind(websocket, 'error'));
|
|
@@ -3604,7 +4206,7 @@ function abortHandshake$1(websocket, stream, message) {
|
|
|
3604
4206
|
*/
|
|
3605
4207
|
function sendAfterClose(websocket, data, cb) {
|
|
3606
4208
|
if (data) {
|
|
3607
|
-
const length = toBuffer(data).length;
|
|
4209
|
+
const length = isBlob(data) ? data.size : toBuffer(data).length;
|
|
3608
4210
|
|
|
3609
4211
|
//
|
|
3610
4212
|
// The `_bufferedAmount` property is used only when the peer is a client and
|
|
@@ -3621,7 +4223,7 @@ function sendAfterClose(websocket, data, cb) {
|
|
|
3621
4223
|
`WebSocket is not open: readyState ${websocket.readyState} ` +
|
|
3622
4224
|
`(${readyStates[websocket.readyState]})`
|
|
3623
4225
|
);
|
|
3624
|
-
cb
|
|
4226
|
+
process.nextTick(cb, err);
|
|
3625
4227
|
}
|
|
3626
4228
|
}
|
|
3627
4229
|
|
|
@@ -3629,7 +4231,7 @@ function sendAfterClose(websocket, data, cb) {
|
|
|
3629
4231
|
* The listener of the `Receiver` `'conclude'` event.
|
|
3630
4232
|
*
|
|
3631
4233
|
* @param {Number} code The status code
|
|
3632
|
-
* @param {
|
|
4234
|
+
* @param {Buffer} reason The reason for closing
|
|
3633
4235
|
* @private
|
|
3634
4236
|
*/
|
|
3635
4237
|
function receiverOnConclude(code, reason) {
|
|
@@ -3654,7 +4256,9 @@ function receiverOnConclude(code, reason) {
|
|
|
3654
4256
|
* @private
|
|
3655
4257
|
*/
|
|
3656
4258
|
function receiverOnDrain() {
|
|
3657
|
-
this[kWebSocket$1]
|
|
4259
|
+
const websocket = this[kWebSocket$1];
|
|
4260
|
+
|
|
4261
|
+
if (!websocket.isPaused) websocket._socket.resume();
|
|
3658
4262
|
}
|
|
3659
4263
|
|
|
3660
4264
|
/**
|
|
@@ -3678,7 +4282,10 @@ function receiverOnError(err) {
|
|
|
3678
4282
|
websocket.close(err[kStatusCode]);
|
|
3679
4283
|
}
|
|
3680
4284
|
|
|
3681
|
-
websocket.
|
|
4285
|
+
if (!websocket._errorEmitted) {
|
|
4286
|
+
websocket._errorEmitted = true;
|
|
4287
|
+
websocket.emit('error', err);
|
|
4288
|
+
}
|
|
3682
4289
|
}
|
|
3683
4290
|
|
|
3684
4291
|
/**
|
|
@@ -3693,11 +4300,12 @@ function receiverOnFinish() {
|
|
|
3693
4300
|
/**
|
|
3694
4301
|
* The listener of the `Receiver` `'message'` event.
|
|
3695
4302
|
*
|
|
3696
|
-
* @param {
|
|
4303
|
+
* @param {Buffer|ArrayBuffer|Buffer[])} data The message
|
|
4304
|
+
* @param {Boolean} isBinary Specifies whether the message is binary or not
|
|
3697
4305
|
* @private
|
|
3698
4306
|
*/
|
|
3699
|
-
function receiverOnMessage(data) {
|
|
3700
|
-
this[kWebSocket$1].emit('message', data);
|
|
4307
|
+
function receiverOnMessage(data, isBinary) {
|
|
4308
|
+
this[kWebSocket$1].emit('message', data, isBinary);
|
|
3701
4309
|
}
|
|
3702
4310
|
|
|
3703
4311
|
/**
|
|
@@ -3709,7 +4317,7 @@ function receiverOnMessage(data) {
|
|
|
3709
4317
|
function receiverOnPing(data) {
|
|
3710
4318
|
const websocket = this[kWebSocket$1];
|
|
3711
4319
|
|
|
3712
|
-
websocket.pong(data, !
|
|
4320
|
+
if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
|
|
3713
4321
|
websocket.emit('ping', data);
|
|
3714
4322
|
}
|
|
3715
4323
|
|
|
@@ -3734,7 +4342,48 @@ function resume(stream) {
|
|
|
3734
4342
|
}
|
|
3735
4343
|
|
|
3736
4344
|
/**
|
|
3737
|
-
* The
|
|
4345
|
+
* The `Sender` error event handler.
|
|
4346
|
+
*
|
|
4347
|
+
* @param {Error} The error
|
|
4348
|
+
* @private
|
|
4349
|
+
*/
|
|
4350
|
+
function senderOnError(err) {
|
|
4351
|
+
const websocket = this[kWebSocket$1];
|
|
4352
|
+
|
|
4353
|
+
if (websocket.readyState === WebSocket$1.CLOSED) return;
|
|
4354
|
+
if (websocket.readyState === WebSocket$1.OPEN) {
|
|
4355
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
4356
|
+
setCloseTimer(websocket);
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
//
|
|
4360
|
+
// `socket.end()` is used instead of `socket.destroy()` to allow the other
|
|
4361
|
+
// peer to finish sending queued data. There is no need to set a timer here
|
|
4362
|
+
// because `CLOSING` means that it is already set or not needed.
|
|
4363
|
+
//
|
|
4364
|
+
this._socket.end();
|
|
4365
|
+
|
|
4366
|
+
if (!websocket._errorEmitted) {
|
|
4367
|
+
websocket._errorEmitted = true;
|
|
4368
|
+
websocket.emit('error', err);
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
|
|
4372
|
+
/**
|
|
4373
|
+
* Set a timer to destroy the underlying raw socket of a WebSocket.
|
|
4374
|
+
*
|
|
4375
|
+
* @param {WebSocket} websocket The WebSocket instance
|
|
4376
|
+
* @private
|
|
4377
|
+
*/
|
|
4378
|
+
function setCloseTimer(websocket) {
|
|
4379
|
+
websocket._closeTimer = setTimeout(
|
|
4380
|
+
websocket._socket.destroy.bind(websocket._socket),
|
|
4381
|
+
websocket._closeTimeout
|
|
4382
|
+
);
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4385
|
+
/**
|
|
4386
|
+
* The listener of the socket `'close'` event.
|
|
3738
4387
|
*
|
|
3739
4388
|
* @private
|
|
3740
4389
|
*/
|
|
@@ -3745,25 +4394,25 @@ function socketOnClose() {
|
|
|
3745
4394
|
this.removeListener('data', socketOnData);
|
|
3746
4395
|
this.removeListener('end', socketOnEnd);
|
|
3747
4396
|
|
|
3748
|
-
websocket._readyState = WebSocket$
|
|
3749
|
-
|
|
3750
|
-
let chunk;
|
|
4397
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
3751
4398
|
|
|
3752
4399
|
//
|
|
3753
4400
|
// The close frame might not have been received or the `'end'` event emitted,
|
|
3754
4401
|
// for example, if the socket was destroyed due to an error. Ensure that the
|
|
3755
4402
|
// `receiver` stream is closed after writing any remaining buffered data to
|
|
3756
4403
|
// it. If the readable side of the socket is in flowing mode then there is no
|
|
3757
|
-
// buffered data as everything has been already written
|
|
3758
|
-
//
|
|
3759
|
-
//
|
|
4404
|
+
// buffered data as everything has been already written. If instead, the
|
|
4405
|
+
// socket is paused, any possible buffered data will be read as a single
|
|
4406
|
+
// chunk.
|
|
3760
4407
|
//
|
|
3761
4408
|
if (
|
|
3762
4409
|
!this._readableState.endEmitted &&
|
|
3763
4410
|
!websocket._closeFrameReceived &&
|
|
3764
4411
|
!websocket._receiver._writableState.errorEmitted &&
|
|
3765
|
-
|
|
4412
|
+
this._readableState.length !== 0
|
|
3766
4413
|
) {
|
|
4414
|
+
const chunk = this.read(this._readableState.length);
|
|
4415
|
+
|
|
3767
4416
|
websocket._receiver.write(chunk);
|
|
3768
4417
|
}
|
|
3769
4418
|
|
|
@@ -3785,7 +4434,7 @@ function socketOnClose() {
|
|
|
3785
4434
|
}
|
|
3786
4435
|
|
|
3787
4436
|
/**
|
|
3788
|
-
* The listener of the
|
|
4437
|
+
* The listener of the socket `'data'` event.
|
|
3789
4438
|
*
|
|
3790
4439
|
* @param {Buffer} chunk A chunk of data
|
|
3791
4440
|
* @private
|
|
@@ -3797,20 +4446,20 @@ function socketOnData(chunk) {
|
|
|
3797
4446
|
}
|
|
3798
4447
|
|
|
3799
4448
|
/**
|
|
3800
|
-
* The listener of the
|
|
4449
|
+
* The listener of the socket `'end'` event.
|
|
3801
4450
|
*
|
|
3802
4451
|
* @private
|
|
3803
4452
|
*/
|
|
3804
4453
|
function socketOnEnd() {
|
|
3805
4454
|
const websocket = this[kWebSocket$1];
|
|
3806
4455
|
|
|
3807
|
-
websocket._readyState = WebSocket$
|
|
4456
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
3808
4457
|
websocket._receiver.end();
|
|
3809
4458
|
this.end();
|
|
3810
4459
|
}
|
|
3811
4460
|
|
|
3812
4461
|
/**
|
|
3813
|
-
* The listener of the
|
|
4462
|
+
* The listener of the socket `'error'` event.
|
|
3814
4463
|
*
|
|
3815
4464
|
* @private
|
|
3816
4465
|
*/
|
|
@@ -3821,200 +4470,87 @@ function socketOnError$1() {
|
|
|
3821
4470
|
this.on('error', NOOP);
|
|
3822
4471
|
|
|
3823
4472
|
if (websocket) {
|
|
3824
|
-
websocket._readyState = WebSocket$
|
|
4473
|
+
websocket._readyState = WebSocket$1.CLOSING;
|
|
3825
4474
|
this.destroy();
|
|
3826
4475
|
}
|
|
3827
4476
|
}
|
|
3828
4477
|
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
/**
|
|
3832
|
-
* Emits the `'close'` event on a stream.
|
|
3833
|
-
*
|
|
3834
|
-
* @param {Duplex} stream The stream.
|
|
3835
|
-
* @private
|
|
3836
|
-
*/
|
|
3837
|
-
function emitClose$1(stream) {
|
|
3838
|
-
stream.emit('close');
|
|
3839
|
-
}
|
|
3840
|
-
|
|
3841
|
-
/**
|
|
3842
|
-
* The listener of the `'end'` event.
|
|
3843
|
-
*
|
|
3844
|
-
* @private
|
|
3845
|
-
*/
|
|
3846
|
-
function duplexOnEnd() {
|
|
3847
|
-
if (!this.destroyed && this._writableState.finished) {
|
|
3848
|
-
this.destroy();
|
|
3849
|
-
}
|
|
3850
|
-
}
|
|
4478
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^WebSocket$" }] */
|
|
4479
|
+
const { Duplex: Duplex$1 } = require$$0$3;
|
|
3851
4480
|
|
|
3852
|
-
|
|
3853
|
-
* The listener of the `'error'` event.
|
|
3854
|
-
*
|
|
3855
|
-
* @param {Error} err The error
|
|
3856
|
-
* @private
|
|
3857
|
-
*/
|
|
3858
|
-
function duplexOnError(err) {
|
|
3859
|
-
this.removeListener('error', duplexOnError);
|
|
3860
|
-
this.destroy();
|
|
3861
|
-
if (this.listenerCount('error') === 0) {
|
|
3862
|
-
// Do not suppress the throwing behavior.
|
|
3863
|
-
this.emit('error', err);
|
|
3864
|
-
}
|
|
3865
|
-
}
|
|
4481
|
+
const { tokenChars } = validationExports;
|
|
3866
4482
|
|
|
3867
4483
|
/**
|
|
3868
|
-
*
|
|
4484
|
+
* Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
|
|
3869
4485
|
*
|
|
3870
|
-
* @param {
|
|
3871
|
-
* @
|
|
3872
|
-
* @return {Duplex} The duplex stream
|
|
4486
|
+
* @param {String} header The field value of the header
|
|
4487
|
+
* @return {Set} The subprotocol names
|
|
3873
4488
|
* @public
|
|
3874
4489
|
*/
|
|
3875
|
-
function
|
|
3876
|
-
|
|
3877
|
-
let
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
if (resumeOnReceiverDrain) ws._socket.resume();
|
|
3881
|
-
}
|
|
3882
|
-
|
|
3883
|
-
if (ws.readyState === ws.CONNECTING) {
|
|
3884
|
-
ws.once('open', function open() {
|
|
3885
|
-
ws._receiver.removeAllListeners('drain');
|
|
3886
|
-
ws._receiver.on('drain', receiverOnDrain);
|
|
3887
|
-
});
|
|
3888
|
-
} else {
|
|
3889
|
-
ws._receiver.removeAllListeners('drain');
|
|
3890
|
-
ws._receiver.on('drain', receiverOnDrain);
|
|
3891
|
-
}
|
|
3892
|
-
|
|
3893
|
-
const duplex = new Duplex({
|
|
3894
|
-
...options,
|
|
3895
|
-
autoDestroy: false,
|
|
3896
|
-
emitClose: false,
|
|
3897
|
-
objectMode: false,
|
|
3898
|
-
writableObjectMode: false
|
|
3899
|
-
});
|
|
3900
|
-
|
|
3901
|
-
ws.on('message', function message(msg) {
|
|
3902
|
-
if (!duplex.push(msg)) {
|
|
3903
|
-
resumeOnReceiverDrain = false;
|
|
3904
|
-
ws._socket.pause();
|
|
3905
|
-
}
|
|
3906
|
-
});
|
|
3907
|
-
|
|
3908
|
-
ws.once('error', function error(err) {
|
|
3909
|
-
if (duplex.destroyed) return;
|
|
3910
|
-
|
|
3911
|
-
// Prevent `ws.terminate()` from being called by `duplex._destroy()`.
|
|
3912
|
-
//
|
|
3913
|
-
// - If the `'error'` event is emitted before the `'open'` event, then
|
|
3914
|
-
// `ws.terminate()` is a noop as no socket is assigned.
|
|
3915
|
-
// - Otherwise, the error is re-emitted by the listener of the `'error'`
|
|
3916
|
-
// event of the `Receiver` object. The listener already closes the
|
|
3917
|
-
// connection by calling `ws.close()`. This allows a close frame to be
|
|
3918
|
-
// sent to the other peer. If `ws.terminate()` is called right after this,
|
|
3919
|
-
// then the close frame might not be sent.
|
|
3920
|
-
terminateOnDestroy = false;
|
|
3921
|
-
duplex.destroy(err);
|
|
3922
|
-
});
|
|
3923
|
-
|
|
3924
|
-
ws.once('close', function close() {
|
|
3925
|
-
if (duplex.destroyed) return;
|
|
3926
|
-
|
|
3927
|
-
duplex.push(null);
|
|
3928
|
-
});
|
|
3929
|
-
|
|
3930
|
-
duplex._destroy = function (err, callback) {
|
|
3931
|
-
if (ws.readyState === ws.CLOSED) {
|
|
3932
|
-
callback(err);
|
|
3933
|
-
process.nextTick(emitClose$1, duplex);
|
|
3934
|
-
return;
|
|
3935
|
-
}
|
|
3936
|
-
|
|
3937
|
-
let called = false;
|
|
4490
|
+
function parse(header) {
|
|
4491
|
+
const protocols = new Set();
|
|
4492
|
+
let start = -1;
|
|
4493
|
+
let end = -1;
|
|
4494
|
+
let i = 0;
|
|
3938
4495
|
|
|
3939
|
-
|
|
3940
|
-
|
|
3941
|
-
callback(err);
|
|
3942
|
-
});
|
|
4496
|
+
for (i; i < header.length; i++) {
|
|
4497
|
+
const code = header.charCodeAt(i);
|
|
3943
4498
|
|
|
3944
|
-
|
|
3945
|
-
if (
|
|
3946
|
-
|
|
3947
|
-
|
|
4499
|
+
if (end === -1 && tokenChars[code] === 1) {
|
|
4500
|
+
if (start === -1) start = i;
|
|
4501
|
+
} else if (
|
|
4502
|
+
i !== 0 &&
|
|
4503
|
+
(code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
|
|
4504
|
+
) {
|
|
4505
|
+
if (end === -1 && start !== -1) end = i;
|
|
4506
|
+
} else if (code === 0x2c /* ',' */) {
|
|
4507
|
+
if (start === -1) {
|
|
4508
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
|
4509
|
+
}
|
|
3948
4510
|
|
|
3949
|
-
|
|
3950
|
-
};
|
|
4511
|
+
if (end === -1) end = i;
|
|
3951
4512
|
|
|
3952
|
-
|
|
3953
|
-
if (ws.readyState === ws.CONNECTING) {
|
|
3954
|
-
ws.once('open', function open() {
|
|
3955
|
-
duplex._final(callback);
|
|
3956
|
-
});
|
|
3957
|
-
return;
|
|
3958
|
-
}
|
|
4513
|
+
const protocol = header.slice(start, end);
|
|
3959
4514
|
|
|
3960
|
-
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
// that will be emitted by the websocket.
|
|
3964
|
-
if (ws._socket === null) return;
|
|
4515
|
+
if (protocols.has(protocol)) {
|
|
4516
|
+
throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
|
|
4517
|
+
}
|
|
3965
4518
|
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
if (duplex._readableState.endEmitted) duplex.destroy();
|
|
4519
|
+
protocols.add(protocol);
|
|
4520
|
+
start = end = -1;
|
|
3969
4521
|
} else {
|
|
3970
|
-
|
|
3971
|
-
// `duplex` is not destroyed here because the `'end'` event will be
|
|
3972
|
-
// emitted on `duplex` after this `'finish'` event. The EOF signaling
|
|
3973
|
-
// `null` chunk is, in fact, pushed when the websocket emits `'close'`.
|
|
3974
|
-
callback();
|
|
3975
|
-
});
|
|
3976
|
-
ws.close();
|
|
4522
|
+
throw new SyntaxError(`Unexpected character at index ${i}`);
|
|
3977
4523
|
}
|
|
3978
|
-
}
|
|
4524
|
+
}
|
|
3979
4525
|
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
!resumeOnReceiverDrain
|
|
3984
|
-
) {
|
|
3985
|
-
resumeOnReceiverDrain = true;
|
|
3986
|
-
if (!ws._receiver._writableState.needDrain) ws._socket.resume();
|
|
3987
|
-
}
|
|
3988
|
-
};
|
|
4526
|
+
if (start === -1 || end !== -1) {
|
|
4527
|
+
throw new SyntaxError('Unexpected end of input');
|
|
4528
|
+
}
|
|
3989
4529
|
|
|
3990
|
-
|
|
3991
|
-
if (ws.readyState === ws.CONNECTING) {
|
|
3992
|
-
ws.once('open', function open() {
|
|
3993
|
-
duplex._write(chunk, encoding, callback);
|
|
3994
|
-
});
|
|
3995
|
-
return;
|
|
3996
|
-
}
|
|
4530
|
+
const protocol = header.slice(start, i);
|
|
3997
4531
|
|
|
3998
|
-
|
|
3999
|
-
|
|
4532
|
+
if (protocols.has(protocol)) {
|
|
4533
|
+
throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
|
|
4534
|
+
}
|
|
4000
4535
|
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
return duplex;
|
|
4536
|
+
protocols.add(protocol);
|
|
4537
|
+
return protocols;
|
|
4004
4538
|
}
|
|
4005
4539
|
|
|
4006
|
-
var
|
|
4540
|
+
var subprotocol$1 = { parse };
|
|
4007
4541
|
|
|
4008
|
-
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^
|
|
4542
|
+
/* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */
|
|
4009
4543
|
|
|
4010
|
-
const EventEmitter = require$$0$
|
|
4544
|
+
const EventEmitter = require$$0$4;
|
|
4011
4545
|
const http = require$$2$1;
|
|
4012
|
-
const {
|
|
4546
|
+
const { Duplex } = require$$0$3;
|
|
4547
|
+
const { createHash } = require$$1$1;
|
|
4013
4548
|
|
|
4549
|
+
const extension = extension$1;
|
|
4014
4550
|
const PerMessageDeflate = permessageDeflate;
|
|
4015
|
-
const
|
|
4016
|
-
const
|
|
4017
|
-
const { GUID, kWebSocket } = constants;
|
|
4551
|
+
const subprotocol = subprotocol$1;
|
|
4552
|
+
const WebSocket = websocket;
|
|
4553
|
+
const { CLOSE_TIMEOUT, GUID, kWebSocket } = constants;
|
|
4018
4554
|
|
|
4019
4555
|
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
|
|
4020
4556
|
|
|
@@ -4032,10 +4568,18 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4032
4568
|
* Create a `WebSocketServer` instance.
|
|
4033
4569
|
*
|
|
4034
4570
|
* @param {Object} options Configuration options
|
|
4571
|
+
* @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
|
|
4572
|
+
* any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
|
|
4573
|
+
* multiple times in the same tick
|
|
4574
|
+
* @param {Boolean} [options.autoPong=true] Specifies whether or not to
|
|
4575
|
+
* automatically send a pong in response to a ping
|
|
4035
4576
|
* @param {Number} [options.backlog=511] The maximum length of the queue of
|
|
4036
4577
|
* pending connections
|
|
4037
4578
|
* @param {Boolean} [options.clientTracking=true] Specifies whether or not to
|
|
4038
4579
|
* track clients
|
|
4580
|
+
* @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
|
|
4581
|
+
* wait for the closing handshake to finish after `websocket.close()` is
|
|
4582
|
+
* called
|
|
4039
4583
|
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
|
4040
4584
|
* @param {String} [options.host] The hostname where to bind the server
|
|
4041
4585
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
@@ -4047,17 +4591,25 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4047
4591
|
* @param {Number} [options.port] The port where to bind the server
|
|
4048
4592
|
* @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
|
|
4049
4593
|
* server to use
|
|
4594
|
+
* @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
|
|
4595
|
+
* not to skip UTF-8 validation for text and close messages
|
|
4050
4596
|
* @param {Function} [options.verifyClient] A hook to reject connections
|
|
4597
|
+
* @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
|
|
4598
|
+
* class to use. It must be the `WebSocket` class or class that extends it
|
|
4051
4599
|
* @param {Function} [callback] A listener for the `listening` event
|
|
4052
4600
|
*/
|
|
4053
4601
|
constructor(options, callback) {
|
|
4054
4602
|
super();
|
|
4055
4603
|
|
|
4056
4604
|
options = {
|
|
4605
|
+
allowSynchronousEvents: true,
|
|
4606
|
+
autoPong: true,
|
|
4057
4607
|
maxPayload: 100 * 1024 * 1024,
|
|
4608
|
+
skipUTF8Validation: false,
|
|
4058
4609
|
perMessageDeflate: false,
|
|
4059
4610
|
handleProtocols: null,
|
|
4060
4611
|
clientTracking: true,
|
|
4612
|
+
closeTimeout: CLOSE_TIMEOUT,
|
|
4061
4613
|
verifyClient: null,
|
|
4062
4614
|
noServer: false,
|
|
4063
4615
|
backlog: null, // use default (511 as implemented in net.js)
|
|
@@ -4065,6 +4617,7 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4065
4617
|
host: null,
|
|
4066
4618
|
path: null,
|
|
4067
4619
|
port: null,
|
|
4620
|
+
WebSocket,
|
|
4068
4621
|
...options
|
|
4069
4622
|
};
|
|
4070
4623
|
|
|
@@ -4112,7 +4665,11 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4112
4665
|
}
|
|
4113
4666
|
|
|
4114
4667
|
if (options.perMessageDeflate === true) options.perMessageDeflate = {};
|
|
4115
|
-
if (options.clientTracking)
|
|
4668
|
+
if (options.clientTracking) {
|
|
4669
|
+
this.clients = new Set();
|
|
4670
|
+
this._shouldEmitClose = false;
|
|
4671
|
+
}
|
|
4672
|
+
|
|
4116
4673
|
this.options = options;
|
|
4117
4674
|
this._state = RUNNING;
|
|
4118
4675
|
}
|
|
@@ -4136,45 +4693,58 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4136
4693
|
}
|
|
4137
4694
|
|
|
4138
4695
|
/**
|
|
4139
|
-
*
|
|
4696
|
+
* Stop the server from accepting new connections and emit the `'close'` event
|
|
4697
|
+
* when all existing connections are closed.
|
|
4140
4698
|
*
|
|
4141
|
-
* @param {Function} [cb]
|
|
4699
|
+
* @param {Function} [cb] A one-time listener for the `'close'` event
|
|
4142
4700
|
* @public
|
|
4143
4701
|
*/
|
|
4144
4702
|
close(cb) {
|
|
4145
|
-
if (cb) this.once('close', cb);
|
|
4146
|
-
|
|
4147
4703
|
if (this._state === CLOSED) {
|
|
4704
|
+
if (cb) {
|
|
4705
|
+
this.once('close', () => {
|
|
4706
|
+
cb(new Error('The server is not running'));
|
|
4707
|
+
});
|
|
4708
|
+
}
|
|
4709
|
+
|
|
4148
4710
|
process.nextTick(emitClose, this);
|
|
4149
4711
|
return;
|
|
4150
4712
|
}
|
|
4151
4713
|
|
|
4714
|
+
if (cb) this.once('close', cb);
|
|
4715
|
+
|
|
4152
4716
|
if (this._state === CLOSING) return;
|
|
4153
4717
|
this._state = CLOSING;
|
|
4154
4718
|
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
}
|
|
4719
|
+
if (this.options.noServer || this.options.server) {
|
|
4720
|
+
if (this._server) {
|
|
4721
|
+
this._removeListeners();
|
|
4722
|
+
this._removeListeners = this._server = null;
|
|
4723
|
+
}
|
|
4161
4724
|
|
|
4162
|
-
|
|
4725
|
+
if (this.clients) {
|
|
4726
|
+
if (!this.clients.size) {
|
|
4727
|
+
process.nextTick(emitClose, this);
|
|
4728
|
+
} else {
|
|
4729
|
+
this._shouldEmitClose = true;
|
|
4730
|
+
}
|
|
4731
|
+
} else {
|
|
4732
|
+
process.nextTick(emitClose, this);
|
|
4733
|
+
}
|
|
4734
|
+
} else {
|
|
4735
|
+
const server = this._server;
|
|
4163
4736
|
|
|
4164
|
-
if (server) {
|
|
4165
4737
|
this._removeListeners();
|
|
4166
4738
|
this._removeListeners = this._server = null;
|
|
4167
4739
|
|
|
4168
4740
|
//
|
|
4169
|
-
//
|
|
4741
|
+
// The HTTP/S server was created internally. Close it, and rely on its
|
|
4742
|
+
// `'close'` event.
|
|
4170
4743
|
//
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
}
|
|
4744
|
+
server.close(() => {
|
|
4745
|
+
emitClose(this);
|
|
4746
|
+
});
|
|
4175
4747
|
}
|
|
4176
|
-
|
|
4177
|
-
process.nextTick(emitClose, this);
|
|
4178
4748
|
}
|
|
4179
4749
|
|
|
4180
4750
|
/**
|
|
@@ -4199,8 +4769,7 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4199
4769
|
* Handle a HTTP Upgrade request.
|
|
4200
4770
|
*
|
|
4201
4771
|
* @param {http.IncomingMessage} req The request object
|
|
4202
|
-
* @param {
|
|
4203
|
-
* server and client
|
|
4772
|
+
* @param {Duplex} socket The network socket between the server and client
|
|
4204
4773
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
4205
4774
|
* @param {Function} cb Callback
|
|
4206
4775
|
* @public
|
|
@@ -4208,42 +4777,79 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4208
4777
|
handleUpgrade(req, socket, head, cb) {
|
|
4209
4778
|
socket.on('error', socketOnError);
|
|
4210
4779
|
|
|
4211
|
-
const key =
|
|
4212
|
-
req.headers['sec-websocket-key'] !== undefined
|
|
4213
|
-
? req.headers['sec-websocket-key'].trim()
|
|
4214
|
-
: false;
|
|
4780
|
+
const key = req.headers['sec-websocket-key'];
|
|
4215
4781
|
const upgrade = req.headers.upgrade;
|
|
4216
4782
|
const version = +req.headers['sec-websocket-version'];
|
|
4783
|
+
|
|
4784
|
+
if (req.method !== 'GET') {
|
|
4785
|
+
const message = 'Invalid HTTP method';
|
|
4786
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
|
|
4787
|
+
return;
|
|
4788
|
+
}
|
|
4789
|
+
|
|
4790
|
+
if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
|
|
4791
|
+
const message = 'Invalid Upgrade header';
|
|
4792
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
4793
|
+
return;
|
|
4794
|
+
}
|
|
4795
|
+
|
|
4796
|
+
if (key === undefined || !keyRegex.test(key)) {
|
|
4797
|
+
const message = 'Missing or invalid Sec-WebSocket-Key header';
|
|
4798
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
4799
|
+
return;
|
|
4800
|
+
}
|
|
4801
|
+
|
|
4802
|
+
if (version !== 13 && version !== 8) {
|
|
4803
|
+
const message = 'Missing or invalid Sec-WebSocket-Version header';
|
|
4804
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message, {
|
|
4805
|
+
'Sec-WebSocket-Version': '13, 8'
|
|
4806
|
+
});
|
|
4807
|
+
return;
|
|
4808
|
+
}
|
|
4809
|
+
|
|
4810
|
+
if (!this.shouldHandle(req)) {
|
|
4811
|
+
abortHandshake(socket, 400);
|
|
4812
|
+
return;
|
|
4813
|
+
}
|
|
4814
|
+
|
|
4815
|
+
const secWebSocketProtocol = req.headers['sec-websocket-protocol'];
|
|
4816
|
+
let protocols = new Set();
|
|
4817
|
+
|
|
4818
|
+
if (secWebSocketProtocol !== undefined) {
|
|
4819
|
+
try {
|
|
4820
|
+
protocols = subprotocol.parse(secWebSocketProtocol);
|
|
4821
|
+
} catch (err) {
|
|
4822
|
+
const message = 'Invalid Sec-WebSocket-Protocol header';
|
|
4823
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
4824
|
+
return;
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4827
|
+
|
|
4828
|
+
const secWebSocketExtensions = req.headers['sec-websocket-extensions'];
|
|
4217
4829
|
const extensions = {};
|
|
4218
4830
|
|
|
4219
4831
|
if (
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
upgrade.toLowerCase() !== 'websocket' ||
|
|
4223
|
-
!key ||
|
|
4224
|
-
!keyRegex.test(key) ||
|
|
4225
|
-
(version !== 8 && version !== 13) ||
|
|
4226
|
-
!this.shouldHandle(req)
|
|
4832
|
+
this.options.perMessageDeflate &&
|
|
4833
|
+
secWebSocketExtensions !== undefined
|
|
4227
4834
|
) {
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
this.options.perMessageDeflate,
|
|
4234
|
-
true,
|
|
4235
|
-
this.options.maxPayload
|
|
4236
|
-
);
|
|
4835
|
+
const perMessageDeflate = new PerMessageDeflate({
|
|
4836
|
+
...this.options.perMessageDeflate,
|
|
4837
|
+
isServer: true,
|
|
4838
|
+
maxPayload: this.options.maxPayload
|
|
4839
|
+
});
|
|
4237
4840
|
|
|
4238
4841
|
try {
|
|
4239
|
-
const offers = parse(
|
|
4842
|
+
const offers = extension.parse(secWebSocketExtensions);
|
|
4240
4843
|
|
|
4241
4844
|
if (offers[PerMessageDeflate.extensionName]) {
|
|
4242
4845
|
perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
|
|
4243
4846
|
extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
|
|
4244
4847
|
}
|
|
4245
4848
|
} catch (err) {
|
|
4246
|
-
|
|
4849
|
+
const message =
|
|
4850
|
+
'Invalid or unacceptable Sec-WebSocket-Extensions header';
|
|
4851
|
+
abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
|
|
4852
|
+
return;
|
|
4247
4853
|
}
|
|
4248
4854
|
}
|
|
4249
4855
|
|
|
@@ -4264,7 +4870,15 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4264
4870
|
return abortHandshake(socket, code || 401, message, headers);
|
|
4265
4871
|
}
|
|
4266
4872
|
|
|
4267
|
-
this.completeUpgrade(
|
|
4873
|
+
this.completeUpgrade(
|
|
4874
|
+
extensions,
|
|
4875
|
+
key,
|
|
4876
|
+
protocols,
|
|
4877
|
+
req,
|
|
4878
|
+
socket,
|
|
4879
|
+
head,
|
|
4880
|
+
cb
|
|
4881
|
+
);
|
|
4268
4882
|
});
|
|
4269
4883
|
return;
|
|
4270
4884
|
}
|
|
@@ -4272,23 +4886,23 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4272
4886
|
if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
|
|
4273
4887
|
}
|
|
4274
4888
|
|
|
4275
|
-
this.completeUpgrade(key,
|
|
4889
|
+
this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
|
|
4276
4890
|
}
|
|
4277
4891
|
|
|
4278
4892
|
/**
|
|
4279
4893
|
* Upgrade the connection to WebSocket.
|
|
4280
4894
|
*
|
|
4281
|
-
* @param {String} key The value of the `Sec-WebSocket-Key` header
|
|
4282
4895
|
* @param {Object} extensions The accepted extensions
|
|
4896
|
+
* @param {String} key The value of the `Sec-WebSocket-Key` header
|
|
4897
|
+
* @param {Set} protocols The subprotocols
|
|
4283
4898
|
* @param {http.IncomingMessage} req The request object
|
|
4284
|
-
* @param {
|
|
4285
|
-
* server and client
|
|
4899
|
+
* @param {Duplex} socket The network socket between the server and client
|
|
4286
4900
|
* @param {Buffer} head The first packet of the upgraded stream
|
|
4287
4901
|
* @param {Function} cb Callback
|
|
4288
4902
|
* @throws {Error} If called more than once with the same socket
|
|
4289
4903
|
* @private
|
|
4290
4904
|
*/
|
|
4291
|
-
completeUpgrade(key,
|
|
4905
|
+
completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
|
|
4292
4906
|
//
|
|
4293
4907
|
// Destroy the socket if the client has already sent a FIN packet.
|
|
4294
4908
|
//
|
|
@@ -4314,20 +4928,15 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4314
4928
|
`Sec-WebSocket-Accept: ${digest}`
|
|
4315
4929
|
];
|
|
4316
4930
|
|
|
4317
|
-
const ws = new WebSocket
|
|
4318
|
-
let protocol = req.headers['sec-websocket-protocol'];
|
|
4319
|
-
|
|
4320
|
-
if (protocol) {
|
|
4321
|
-
protocol = protocol.split(',').map(trim);
|
|
4931
|
+
const ws = new this.options.WebSocket(null, undefined, this.options);
|
|
4322
4932
|
|
|
4933
|
+
if (protocols.size) {
|
|
4323
4934
|
//
|
|
4324
4935
|
// Optionally call external protocol selection handler.
|
|
4325
4936
|
//
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
protocol = protocol[0];
|
|
4330
|
-
}
|
|
4937
|
+
const protocol = this.options.handleProtocols
|
|
4938
|
+
? this.options.handleProtocols(protocols, req)
|
|
4939
|
+
: protocols.values().next().value;
|
|
4331
4940
|
|
|
4332
4941
|
if (protocol) {
|
|
4333
4942
|
headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
|
|
@@ -4337,7 +4946,7 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4337
4946
|
|
|
4338
4947
|
if (extensions[PerMessageDeflate.extensionName]) {
|
|
4339
4948
|
const params = extensions[PerMessageDeflate.extensionName].params;
|
|
4340
|
-
const value = format({
|
|
4949
|
+
const value = extension.format({
|
|
4341
4950
|
[PerMessageDeflate.extensionName]: [params]
|
|
4342
4951
|
});
|
|
4343
4952
|
headers.push(`Sec-WebSocket-Extensions: ${value}`);
|
|
@@ -4352,11 +4961,21 @@ let WebSocketServer$1 = class WebSocketServer extends EventEmitter {
|
|
|
4352
4961
|
socket.write(headers.concat('\r\n').join('\r\n'));
|
|
4353
4962
|
socket.removeListener('error', socketOnError);
|
|
4354
4963
|
|
|
4355
|
-
ws.setSocket(socket, head,
|
|
4964
|
+
ws.setSocket(socket, head, {
|
|
4965
|
+
allowSynchronousEvents: this.options.allowSynchronousEvents,
|
|
4966
|
+
maxPayload: this.options.maxPayload,
|
|
4967
|
+
skipUTF8Validation: this.options.skipUTF8Validation
|
|
4968
|
+
});
|
|
4356
4969
|
|
|
4357
4970
|
if (this.clients) {
|
|
4358
4971
|
this.clients.add(ws);
|
|
4359
|
-
ws.on('close', () =>
|
|
4972
|
+
ws.on('close', () => {
|
|
4973
|
+
this.clients.delete(ws);
|
|
4974
|
+
|
|
4975
|
+
if (this._shouldEmitClose && !this.clients.size) {
|
|
4976
|
+
process.nextTick(emitClose, this);
|
|
4977
|
+
}
|
|
4978
|
+
});
|
|
4360
4979
|
}
|
|
4361
4980
|
|
|
4362
4981
|
cb(ws, req);
|
|
@@ -4397,7 +5016,7 @@ function emitClose(server) {
|
|
|
4397
5016
|
}
|
|
4398
5017
|
|
|
4399
5018
|
/**
|
|
4400
|
-
* Handle
|
|
5019
|
+
* Handle socket errors.
|
|
4401
5020
|
*
|
|
4402
5021
|
* @private
|
|
4403
5022
|
*/
|
|
@@ -4408,68 +5027,80 @@ function socketOnError() {
|
|
|
4408
5027
|
/**
|
|
4409
5028
|
* Close the connection when preconditions are not fulfilled.
|
|
4410
5029
|
*
|
|
4411
|
-
* @param {
|
|
5030
|
+
* @param {Duplex} socket The socket of the upgrade request
|
|
4412
5031
|
* @param {Number} code The HTTP response status code
|
|
4413
5032
|
* @param {String} [message] The HTTP response body
|
|
4414
5033
|
* @param {Object} [headers] Additional HTTP response headers
|
|
4415
5034
|
* @private
|
|
4416
5035
|
*/
|
|
4417
5036
|
function abortHandshake(socket, code, message, headers) {
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
5037
|
+
//
|
|
5038
|
+
// The socket is writable unless the user destroyed or ended it before calling
|
|
5039
|
+
// `server.handleUpgrade()` or in the `verifyClient` function, which is a user
|
|
5040
|
+
// error. Handling this does not make much sense as the worst that can happen
|
|
5041
|
+
// is that some of the data written by the user might be discarded due to the
|
|
5042
|
+
// call to `socket.end()` below, which triggers an `'error'` event that in
|
|
5043
|
+
// turn causes the socket to be destroyed.
|
|
5044
|
+
//
|
|
5045
|
+
message = message || http.STATUS_CODES[code];
|
|
5046
|
+
headers = {
|
|
5047
|
+
Connection: 'close',
|
|
5048
|
+
'Content-Type': 'text/html',
|
|
5049
|
+
'Content-Length': Buffer.byteLength(message),
|
|
5050
|
+
...headers
|
|
5051
|
+
};
|
|
4426
5052
|
|
|
4427
|
-
|
|
4428
|
-
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
|
|
4429
|
-
Object.keys(headers)
|
|
4430
|
-
.map((h) => `${h}: ${headers[h]}`)
|
|
4431
|
-
.join('\r\n') +
|
|
4432
|
-
'\r\n\r\n' +
|
|
4433
|
-
message
|
|
4434
|
-
);
|
|
4435
|
-
}
|
|
5053
|
+
socket.once('finish', socket.destroy);
|
|
4436
5054
|
|
|
4437
|
-
socket.
|
|
4438
|
-
|
|
5055
|
+
socket.end(
|
|
5056
|
+
`HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
|
|
5057
|
+
Object.keys(headers)
|
|
5058
|
+
.map((h) => `${h}: ${headers[h]}`)
|
|
5059
|
+
.join('\r\n') +
|
|
5060
|
+
'\r\n\r\n' +
|
|
5061
|
+
message
|
|
5062
|
+
);
|
|
4439
5063
|
}
|
|
4440
5064
|
|
|
4441
5065
|
/**
|
|
4442
|
-
*
|
|
5066
|
+
* Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least
|
|
5067
|
+
* one listener for it, otherwise call `abortHandshake()`.
|
|
4443
5068
|
*
|
|
4444
|
-
* @param {
|
|
4445
|
-
* @
|
|
4446
|
-
*
|
|
5069
|
+
* @param {WebSocketServer} server The WebSocket server
|
|
5070
|
+
* @param {http.IncomingMessage} req The request object
|
|
5071
|
+
* @param {Duplex} socket The socket of the upgrade request
|
|
5072
|
+
* @param {Number} code The HTTP response status code
|
|
5073
|
+
* @param {String} message The HTTP response body
|
|
5074
|
+
* @param {Object} [headers] The HTTP response headers
|
|
4447
5075
|
* @private
|
|
4448
5076
|
*/
|
|
4449
|
-
function
|
|
4450
|
-
|
|
5077
|
+
function abortHandshakeOrEmitwsClientError(
|
|
5078
|
+
server,
|
|
5079
|
+
req,
|
|
5080
|
+
socket,
|
|
5081
|
+
code,
|
|
5082
|
+
message,
|
|
5083
|
+
headers
|
|
5084
|
+
) {
|
|
5085
|
+
if (server.listenerCount('wsClientError')) {
|
|
5086
|
+
const err = new Error(message);
|
|
5087
|
+
Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
|
|
5088
|
+
|
|
5089
|
+
server.emit('wsClientError', err, socket, req);
|
|
5090
|
+
} else {
|
|
5091
|
+
abortHandshake(socket, code, message, headers);
|
|
5092
|
+
}
|
|
4451
5093
|
}
|
|
4452
5094
|
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
WebSocket.createWebSocketStream = stream;
|
|
4456
|
-
WebSocket.Server = websocketServer;
|
|
4457
|
-
WebSocket.Receiver = receiver;
|
|
4458
|
-
WebSocket.Sender = sender;
|
|
4459
|
-
|
|
4460
|
-
var ws = WebSocket;
|
|
4461
|
-
|
|
4462
|
-
var ws$1 = /*@__PURE__*/getDefaultExportFromCjs(ws);
|
|
5095
|
+
var websocketServer_default = /*@__PURE__*/getDefaultExportFromCjs(websocketServer);
|
|
4463
5096
|
|
|
4464
5097
|
/**
|
|
4465
5098
|
* Re-exports WebSocket and WebSocketServer from the ws package.
|
|
4466
5099
|
*
|
|
4467
|
-
* ws is a CJS module
|
|
4468
|
-
*
|
|
4469
|
-
* around that by extracting them from the default export and re-exporting
|
|
4470
|
-
* them as merged type+value pairs.
|
|
5100
|
+
* ws is a CJS module with different shapes for default and namespace imports.
|
|
5101
|
+
* This module normalizes those imports and re-exports them as merged type+value pairs.
|
|
4471
5102
|
*/
|
|
4472
|
-
const WebSocketServer =
|
|
5103
|
+
const WebSocketServer = websocketServer_default;
|
|
4473
5104
|
|
|
4474
5105
|
const CONFIG_FILENAME = ".babyloninspector";
|
|
4475
5106
|
const DefaultBrowserPort = 4400;
|