crossws 0.4.1 → 0.4.3

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.
Files changed (53) hide show
  1. package/dist/_chunks/_request.mjs +82 -0
  2. package/dist/_chunks/_types.d.mts +24 -0
  3. package/dist/_chunks/adapter.d.mts +174 -0
  4. package/dist/_chunks/adapter.mjs +93 -0
  5. package/dist/_chunks/bun.d.mts +38 -0
  6. package/dist/_chunks/cloudflare.d.mts +45 -0
  7. package/dist/_chunks/deno.d.mts +17 -0
  8. package/dist/_chunks/error.mjs +10 -0
  9. package/dist/_chunks/libs/ws.mjs +3531 -0
  10. package/dist/_chunks/node.d.mts +299 -0
  11. package/dist/_chunks/peer.mjs +244 -0
  12. package/dist/_chunks/rolldown-runtime.mjs +32 -0
  13. package/dist/_chunks/sse.d.mts +12 -0
  14. package/dist/_chunks/web.d.mts +298 -0
  15. package/dist/adapters/bun.d.mts +2 -41
  16. package/dist/adapters/bun.mjs +83 -93
  17. package/dist/adapters/cloudflare.d.mts +2 -46
  18. package/dist/adapters/cloudflare.mjs +173 -218
  19. package/dist/adapters/deno.d.mts +2 -19
  20. package/dist/adapters/deno.mjs +65 -74
  21. package/dist/adapters/node.d.mts +2 -299
  22. package/dist/adapters/node.mjs +119 -156
  23. package/dist/adapters/sse.d.mts +2 -13
  24. package/dist/adapters/sse.mjs +98 -118
  25. package/dist/adapters/uws.d.mts +44 -44
  26. package/dist/adapters/uws.mjs +152 -175
  27. package/dist/index.d.mts +2 -170
  28. package/dist/index.mjs +3 -1
  29. package/dist/server/bun.d.mts +8 -21
  30. package/dist/server/bun.mjs +24 -31
  31. package/dist/server/cloudflare.d.mts +8 -21
  32. package/dist/server/cloudflare.mjs +21 -30
  33. package/dist/server/default.d.mts +8 -21
  34. package/dist/server/default.mjs +22 -26
  35. package/dist/server/deno.d.mts +8 -21
  36. package/dist/server/deno.mjs +21 -24
  37. package/dist/server/node.d.mts +8 -21
  38. package/dist/server/node.mjs +32 -43
  39. package/dist/websocket/native.d.mts +3 -2
  40. package/dist/websocket/native.mjs +4 -1
  41. package/dist/websocket/node.d.mts +3 -2
  42. package/dist/websocket/node.mjs +7 -13
  43. package/dist/websocket/sse.d.mts +34 -34
  44. package/dist/websocket/sse.mjs +112 -123
  45. package/package.json +36 -28
  46. package/adapters/cloudflare-durable.d.ts +0 -2
  47. package/dist/shared/crossws.95-eYp2D.d.mts +0 -23
  48. package/dist/shared/crossws.B31KJMcF.mjs +0 -83
  49. package/dist/shared/crossws.BQXMA5bH.d.mts +0 -297
  50. package/dist/shared/crossws.By9qWDAI.mjs +0 -8
  51. package/dist/shared/crossws.CPlNx7g8.mjs +0 -105
  52. package/dist/shared/crossws.CipVM6lf.mjs +0 -4973
  53. package/dist/shared/crossws.WpyOHUXc.mjs +0 -330
@@ -1,4973 +0,0 @@
1
- import require$$0$2 from 'stream';
2
- import require$$0$3 from 'events';
3
- import require$$2 from 'http';
4
- import require$$1 from 'crypto';
5
- import require$$0$1 from 'buffer';
6
- import require$$0 from 'zlib';
7
- import require$$1$1 from 'https';
8
- import require$$3 from 'net';
9
- import require$$4 from 'tls';
10
- import require$$7 from 'url';
11
-
12
- function getDefaultExportFromCjs (x) {
13
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
14
- }
15
-
16
- var bufferUtil = {exports: {}};
17
-
18
- var constants;
19
- var hasRequiredConstants;
20
-
21
- function requireConstants () {
22
- if (hasRequiredConstants) return constants;
23
- hasRequiredConstants = 1;
24
-
25
- const BINARY_TYPES = ['nodebuffer', 'arraybuffer', 'fragments'];
26
- const hasBlob = typeof Blob !== 'undefined';
27
-
28
- if (hasBlob) BINARY_TYPES.push('blob');
29
-
30
- constants = {
31
- BINARY_TYPES,
32
- EMPTY_BUFFER: Buffer.alloc(0),
33
- GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
34
- hasBlob,
35
- kForOnEventAttribute: Symbol('kIsForOnEventAttribute'),
36
- kListener: Symbol('kListener'),
37
- kStatusCode: Symbol('status-code'),
38
- kWebSocket: Symbol('websocket'),
39
- NOOP: () => {}
40
- };
41
- return constants;
42
- }
43
-
44
- var hasRequiredBufferUtil;
45
-
46
- function requireBufferUtil () {
47
- if (hasRequiredBufferUtil) return bufferUtil.exports;
48
- hasRequiredBufferUtil = 1;
49
-
50
- const { EMPTY_BUFFER } = requireConstants();
51
-
52
- const FastBuffer = Buffer[Symbol.species];
53
-
54
- /**
55
- * Merges an array of buffers into a new buffer.
56
- *
57
- * @param {Buffer[]} list The array of buffers to concat
58
- * @param {Number} totalLength The total length of buffers in the list
59
- * @return {Buffer} The resulting buffer
60
- * @public
61
- */
62
- function concat(list, totalLength) {
63
- if (list.length === 0) return EMPTY_BUFFER;
64
- if (list.length === 1) return list[0];
65
-
66
- const target = Buffer.allocUnsafe(totalLength);
67
- let offset = 0;
68
-
69
- for (let i = 0; i < list.length; i++) {
70
- const buf = list[i];
71
- target.set(buf, offset);
72
- offset += buf.length;
73
- }
74
-
75
- if (offset < totalLength) {
76
- return new FastBuffer(target.buffer, target.byteOffset, offset);
77
- }
78
-
79
- return target;
80
- }
81
-
82
- /**
83
- * Masks a buffer using the given mask.
84
- *
85
- * @param {Buffer} source The buffer to mask
86
- * @param {Buffer} mask The mask to use
87
- * @param {Buffer} output The buffer where to store the result
88
- * @param {Number} offset The offset at which to start writing
89
- * @param {Number} length The number of bytes to mask.
90
- * @public
91
- */
92
- function _mask(source, mask, output, offset, length) {
93
- for (let i = 0; i < length; i++) {
94
- output[offset + i] = source[i] ^ mask[i & 3];
95
- }
96
- }
97
-
98
- /**
99
- * Unmasks a buffer using the given mask.
100
- *
101
- * @param {Buffer} buffer The buffer to unmask
102
- * @param {Buffer} mask The mask to use
103
- * @public
104
- */
105
- function _unmask(buffer, mask) {
106
- for (let i = 0; i < buffer.length; i++) {
107
- buffer[i] ^= mask[i & 3];
108
- }
109
- }
110
-
111
- /**
112
- * Converts a buffer to an `ArrayBuffer`.
113
- *
114
- * @param {Buffer} buf The buffer to convert
115
- * @return {ArrayBuffer} Converted buffer
116
- * @public
117
- */
118
- function toArrayBuffer(buf) {
119
- if (buf.length === buf.buffer.byteLength) {
120
- return buf.buffer;
121
- }
122
-
123
- return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
124
- }
125
-
126
- /**
127
- * Converts `data` to a `Buffer`.
128
- *
129
- * @param {*} data The data to convert
130
- * @return {Buffer} The buffer
131
- * @throws {TypeError}
132
- * @public
133
- */
134
- function toBuffer(data) {
135
- toBuffer.readOnly = true;
136
-
137
- if (Buffer.isBuffer(data)) return data;
138
-
139
- let buf;
140
-
141
- if (data instanceof ArrayBuffer) {
142
- buf = new FastBuffer(data);
143
- } else if (ArrayBuffer.isView(data)) {
144
- buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
145
- } else {
146
- buf = Buffer.from(data);
147
- toBuffer.readOnly = false;
148
- }
149
-
150
- return buf;
151
- }
152
-
153
- bufferUtil.exports = {
154
- concat,
155
- mask: _mask,
156
- toArrayBuffer,
157
- toBuffer,
158
- unmask: _unmask
159
- };
160
-
161
- /* istanbul ignore else */
162
- if (!process.env.WS_NO_BUFFER_UTIL) {
163
- try {
164
- const bufferUtil$1 = require('bufferutil');
165
-
166
- bufferUtil.exports.mask = function (source, mask, output, offset, length) {
167
- if (length < 48) _mask(source, mask, output, offset, length);
168
- else bufferUtil$1.mask(source, mask, output, offset, length);
169
- };
170
-
171
- bufferUtil.exports.unmask = function (buffer, mask) {
172
- if (buffer.length < 32) _unmask(buffer, mask);
173
- else bufferUtil$1.unmask(buffer, mask);
174
- };
175
- } catch (e) {
176
- // Continue regardless of the error.
177
- }
178
- }
179
- return bufferUtil.exports;
180
- }
181
-
182
- var limiter;
183
- var hasRequiredLimiter;
184
-
185
- function requireLimiter () {
186
- if (hasRequiredLimiter) return limiter;
187
- hasRequiredLimiter = 1;
188
-
189
- const kDone = Symbol('kDone');
190
- const kRun = Symbol('kRun');
191
-
192
- /**
193
- * A very simple job queue with adjustable concurrency. Adapted from
194
- * https://github.com/STRML/async-limiter
195
- */
196
- class Limiter {
197
- /**
198
- * Creates a new `Limiter`.
199
- *
200
- * @param {Number} [concurrency=Infinity] The maximum number of jobs allowed
201
- * to run concurrently
202
- */
203
- constructor(concurrency) {
204
- this[kDone] = () => {
205
- this.pending--;
206
- this[kRun]();
207
- };
208
- this.concurrency = concurrency || Infinity;
209
- this.jobs = [];
210
- this.pending = 0;
211
- }
212
-
213
- /**
214
- * Adds a job to the queue.
215
- *
216
- * @param {Function} job The job to run
217
- * @public
218
- */
219
- add(job) {
220
- this.jobs.push(job);
221
- this[kRun]();
222
- }
223
-
224
- /**
225
- * Removes a job from the queue and runs it if possible.
226
- *
227
- * @private
228
- */
229
- [kRun]() {
230
- if (this.pending === this.concurrency) return;
231
-
232
- if (this.jobs.length) {
233
- const job = this.jobs.shift();
234
-
235
- this.pending++;
236
- job(this[kDone]);
237
- }
238
- }
239
- }
240
-
241
- limiter = Limiter;
242
- return limiter;
243
- }
244
-
245
- var permessageDeflate;
246
- var hasRequiredPermessageDeflate;
247
-
248
- function requirePermessageDeflate () {
249
- if (hasRequiredPermessageDeflate) return permessageDeflate;
250
- hasRequiredPermessageDeflate = 1;
251
-
252
- const zlib = require$$0;
253
-
254
- const bufferUtil = requireBufferUtil();
255
- const Limiter = requireLimiter();
256
- const { kStatusCode } = requireConstants();
257
-
258
- const FastBuffer = Buffer[Symbol.species];
259
- const TRAILER = Buffer.from([0x00, 0x00, 0xff, 0xff]);
260
- const kPerMessageDeflate = Symbol('permessage-deflate');
261
- const kTotalLength = Symbol('total-length');
262
- const kCallback = Symbol('callback');
263
- const kBuffers = Symbol('buffers');
264
- const kError = Symbol('error');
265
-
266
- //
267
- // We limit zlib concurrency, which prevents severe memory fragmentation
268
- // as documented in https://github.com/nodejs/node/issues/8871#issuecomment-250915913
269
- // and https://github.com/websockets/ws/issues/1202
270
- //
271
- // Intentionally global; it's the global thread pool that's an issue.
272
- //
273
- let zlibLimiter;
274
-
275
- /**
276
- * permessage-deflate implementation.
277
- */
278
- class PerMessageDeflate {
279
- /**
280
- * Creates a PerMessageDeflate instance.
281
- *
282
- * @param {Object} [options] Configuration options
283
- * @param {(Boolean|Number)} [options.clientMaxWindowBits] Advertise support
284
- * for, or request, a custom client window size
285
- * @param {Boolean} [options.clientNoContextTakeover=false] Advertise/
286
- * acknowledge disabling of client context takeover
287
- * @param {Number} [options.concurrencyLimit=10] The number of concurrent
288
- * calls to zlib
289
- * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
290
- * use of a custom server window size
291
- * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
292
- * disabling of server context takeover
293
- * @param {Number} [options.threshold=1024] Size (in bytes) below which
294
- * messages should not be compressed if context takeover is disabled
295
- * @param {Object} [options.zlibDeflateOptions] Options to pass to zlib on
296
- * deflate
297
- * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
298
- * inflate
299
- * @param {Boolean} [isServer=false] Create the instance in either server or
300
- * client mode
301
- * @param {Number} [maxPayload=0] The maximum allowed message length
302
- */
303
- constructor(options, isServer, maxPayload) {
304
- this._maxPayload = maxPayload | 0;
305
- this._options = options || {};
306
- this._threshold =
307
- this._options.threshold !== undefined ? this._options.threshold : 1024;
308
- this._isServer = !!isServer;
309
- this._deflate = null;
310
- this._inflate = null;
311
-
312
- this.params = null;
313
-
314
- if (!zlibLimiter) {
315
- const concurrency =
316
- this._options.concurrencyLimit !== undefined
317
- ? this._options.concurrencyLimit
318
- : 10;
319
- zlibLimiter = new Limiter(concurrency);
320
- }
321
- }
322
-
323
- /**
324
- * @type {String}
325
- */
326
- static get extensionName() {
327
- return 'permessage-deflate';
328
- }
329
-
330
- /**
331
- * Create an extension negotiation offer.
332
- *
333
- * @return {Object} Extension parameters
334
- * @public
335
- */
336
- offer() {
337
- const params = {};
338
-
339
- if (this._options.serverNoContextTakeover) {
340
- params.server_no_context_takeover = true;
341
- }
342
- if (this._options.clientNoContextTakeover) {
343
- params.client_no_context_takeover = true;
344
- }
345
- if (this._options.serverMaxWindowBits) {
346
- params.server_max_window_bits = this._options.serverMaxWindowBits;
347
- }
348
- if (this._options.clientMaxWindowBits) {
349
- params.client_max_window_bits = this._options.clientMaxWindowBits;
350
- } else if (this._options.clientMaxWindowBits == null) {
351
- params.client_max_window_bits = true;
352
- }
353
-
354
- return params;
355
- }
356
-
357
- /**
358
- * Accept an extension negotiation offer/response.
359
- *
360
- * @param {Array} configurations The extension negotiation offers/reponse
361
- * @return {Object} Accepted configuration
362
- * @public
363
- */
364
- accept(configurations) {
365
- configurations = this.normalizeParams(configurations);
366
-
367
- this.params = this._isServer
368
- ? this.acceptAsServer(configurations)
369
- : this.acceptAsClient(configurations);
370
-
371
- return this.params;
372
- }
373
-
374
- /**
375
- * Releases all resources used by the extension.
376
- *
377
- * @public
378
- */
379
- cleanup() {
380
- if (this._inflate) {
381
- this._inflate.close();
382
- this._inflate = null;
383
- }
384
-
385
- if (this._deflate) {
386
- const callback = this._deflate[kCallback];
387
-
388
- this._deflate.close();
389
- this._deflate = null;
390
-
391
- if (callback) {
392
- callback(
393
- new Error(
394
- 'The deflate stream was closed while data was being processed'
395
- )
396
- );
397
- }
398
- }
399
- }
400
-
401
- /**
402
- * Accept an extension negotiation offer.
403
- *
404
- * @param {Array} offers The extension negotiation offers
405
- * @return {Object} Accepted configuration
406
- * @private
407
- */
408
- acceptAsServer(offers) {
409
- const opts = this._options;
410
- const accepted = offers.find((params) => {
411
- if (
412
- (opts.serverNoContextTakeover === false &&
413
- params.server_no_context_takeover) ||
414
- (params.server_max_window_bits &&
415
- (opts.serverMaxWindowBits === false ||
416
- (typeof opts.serverMaxWindowBits === 'number' &&
417
- opts.serverMaxWindowBits > params.server_max_window_bits))) ||
418
- (typeof opts.clientMaxWindowBits === 'number' &&
419
- !params.client_max_window_bits)
420
- ) {
421
- return false;
422
- }
423
-
424
- return true;
425
- });
426
-
427
- if (!accepted) {
428
- throw new Error('None of the extension offers can be accepted');
429
- }
430
-
431
- if (opts.serverNoContextTakeover) {
432
- accepted.server_no_context_takeover = true;
433
- }
434
- if (opts.clientNoContextTakeover) {
435
- accepted.client_no_context_takeover = true;
436
- }
437
- if (typeof opts.serverMaxWindowBits === 'number') {
438
- accepted.server_max_window_bits = opts.serverMaxWindowBits;
439
- }
440
- if (typeof opts.clientMaxWindowBits === 'number') {
441
- accepted.client_max_window_bits = opts.clientMaxWindowBits;
442
- } else if (
443
- accepted.client_max_window_bits === true ||
444
- opts.clientMaxWindowBits === false
445
- ) {
446
- delete accepted.client_max_window_bits;
447
- }
448
-
449
- return accepted;
450
- }
451
-
452
- /**
453
- * Accept the extension negotiation response.
454
- *
455
- * @param {Array} response The extension negotiation response
456
- * @return {Object} Accepted configuration
457
- * @private
458
- */
459
- acceptAsClient(response) {
460
- const params = response[0];
461
-
462
- if (
463
- this._options.clientNoContextTakeover === false &&
464
- params.client_no_context_takeover
465
- ) {
466
- throw new Error('Unexpected parameter "client_no_context_takeover"');
467
- }
468
-
469
- if (!params.client_max_window_bits) {
470
- if (typeof this._options.clientMaxWindowBits === 'number') {
471
- params.client_max_window_bits = this._options.clientMaxWindowBits;
472
- }
473
- } else if (
474
- this._options.clientMaxWindowBits === false ||
475
- (typeof this._options.clientMaxWindowBits === 'number' &&
476
- params.client_max_window_bits > this._options.clientMaxWindowBits)
477
- ) {
478
- throw new Error(
479
- 'Unexpected or invalid parameter "client_max_window_bits"'
480
- );
481
- }
482
-
483
- return params;
484
- }
485
-
486
- /**
487
- * Normalize parameters.
488
- *
489
- * @param {Array} configurations The extension negotiation offers/reponse
490
- * @return {Array} The offers/response with normalized parameters
491
- * @private
492
- */
493
- normalizeParams(configurations) {
494
- configurations.forEach((params) => {
495
- Object.keys(params).forEach((key) => {
496
- let value = params[key];
497
-
498
- if (value.length > 1) {
499
- throw new Error(`Parameter "${key}" must have only a single value`);
500
- }
501
-
502
- value = value[0];
503
-
504
- if (key === 'client_max_window_bits') {
505
- if (value !== true) {
506
- const num = +value;
507
- if (!Number.isInteger(num) || num < 8 || num > 15) {
508
- throw new TypeError(
509
- `Invalid value for parameter "${key}": ${value}`
510
- );
511
- }
512
- value = num;
513
- } else if (!this._isServer) {
514
- throw new TypeError(
515
- `Invalid value for parameter "${key}": ${value}`
516
- );
517
- }
518
- } else if (key === 'server_max_window_bits') {
519
- const num = +value;
520
- if (!Number.isInteger(num) || num < 8 || num > 15) {
521
- throw new TypeError(
522
- `Invalid value for parameter "${key}": ${value}`
523
- );
524
- }
525
- value = num;
526
- } else if (
527
- key === 'client_no_context_takeover' ||
528
- key === 'server_no_context_takeover'
529
- ) {
530
- if (value !== true) {
531
- throw new TypeError(
532
- `Invalid value for parameter "${key}": ${value}`
533
- );
534
- }
535
- } else {
536
- throw new Error(`Unknown parameter "${key}"`);
537
- }
538
-
539
- params[key] = value;
540
- });
541
- });
542
-
543
- return configurations;
544
- }
545
-
546
- /**
547
- * Decompress data. Concurrency limited.
548
- *
549
- * @param {Buffer} data Compressed data
550
- * @param {Boolean} fin Specifies whether or not this is the last fragment
551
- * @param {Function} callback Callback
552
- * @public
553
- */
554
- decompress(data, fin, callback) {
555
- zlibLimiter.add((done) => {
556
- this._decompress(data, fin, (err, result) => {
557
- done();
558
- callback(err, result);
559
- });
560
- });
561
- }
562
-
563
- /**
564
- * Compress data. Concurrency limited.
565
- *
566
- * @param {(Buffer|String)} data Data to compress
567
- * @param {Boolean} fin Specifies whether or not this is the last fragment
568
- * @param {Function} callback Callback
569
- * @public
570
- */
571
- compress(data, fin, callback) {
572
- zlibLimiter.add((done) => {
573
- this._compress(data, fin, (err, result) => {
574
- done();
575
- callback(err, result);
576
- });
577
- });
578
- }
579
-
580
- /**
581
- * Decompress data.
582
- *
583
- * @param {Buffer} data Compressed data
584
- * @param {Boolean} fin Specifies whether or not this is the last fragment
585
- * @param {Function} callback Callback
586
- * @private
587
- */
588
- _decompress(data, fin, callback) {
589
- const endpoint = this._isServer ? 'client' : 'server';
590
-
591
- if (!this._inflate) {
592
- const key = `${endpoint}_max_window_bits`;
593
- const windowBits =
594
- typeof this.params[key] !== 'number'
595
- ? zlib.Z_DEFAULT_WINDOWBITS
596
- : this.params[key];
597
-
598
- this._inflate = zlib.createInflateRaw({
599
- ...this._options.zlibInflateOptions,
600
- windowBits
601
- });
602
- this._inflate[kPerMessageDeflate] = this;
603
- this._inflate[kTotalLength] = 0;
604
- this._inflate[kBuffers] = [];
605
- this._inflate.on('error', inflateOnError);
606
- this._inflate.on('data', inflateOnData);
607
- }
608
-
609
- this._inflate[kCallback] = callback;
610
-
611
- this._inflate.write(data);
612
- if (fin) this._inflate.write(TRAILER);
613
-
614
- this._inflate.flush(() => {
615
- const err = this._inflate[kError];
616
-
617
- if (err) {
618
- this._inflate.close();
619
- this._inflate = null;
620
- callback(err);
621
- return;
622
- }
623
-
624
- const data = bufferUtil.concat(
625
- this._inflate[kBuffers],
626
- this._inflate[kTotalLength]
627
- );
628
-
629
- if (this._inflate._readableState.endEmitted) {
630
- this._inflate.close();
631
- this._inflate = null;
632
- } else {
633
- this._inflate[kTotalLength] = 0;
634
- this._inflate[kBuffers] = [];
635
-
636
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
637
- this._inflate.reset();
638
- }
639
- }
640
-
641
- callback(null, data);
642
- });
643
- }
644
-
645
- /**
646
- * Compress data.
647
- *
648
- * @param {(Buffer|String)} data Data to compress
649
- * @param {Boolean} fin Specifies whether or not this is the last fragment
650
- * @param {Function} callback Callback
651
- * @private
652
- */
653
- _compress(data, fin, callback) {
654
- const endpoint = this._isServer ? 'server' : 'client';
655
-
656
- if (!this._deflate) {
657
- const key = `${endpoint}_max_window_bits`;
658
- const windowBits =
659
- typeof this.params[key] !== 'number'
660
- ? zlib.Z_DEFAULT_WINDOWBITS
661
- : this.params[key];
662
-
663
- this._deflate = zlib.createDeflateRaw({
664
- ...this._options.zlibDeflateOptions,
665
- windowBits
666
- });
667
-
668
- this._deflate[kTotalLength] = 0;
669
- this._deflate[kBuffers] = [];
670
-
671
- this._deflate.on('data', deflateOnData);
672
- }
673
-
674
- this._deflate[kCallback] = callback;
675
-
676
- this._deflate.write(data);
677
- this._deflate.flush(zlib.Z_SYNC_FLUSH, () => {
678
- if (!this._deflate) {
679
- //
680
- // The deflate stream was closed while data was being processed.
681
- //
682
- return;
683
- }
684
-
685
- let data = bufferUtil.concat(
686
- this._deflate[kBuffers],
687
- this._deflate[kTotalLength]
688
- );
689
-
690
- if (fin) {
691
- data = new FastBuffer(data.buffer, data.byteOffset, data.length - 4);
692
- }
693
-
694
- //
695
- // Ensure that the callback will not be called again in
696
- // `PerMessageDeflate#cleanup()`.
697
- //
698
- this._deflate[kCallback] = null;
699
-
700
- this._deflate[kTotalLength] = 0;
701
- this._deflate[kBuffers] = [];
702
-
703
- if (fin && this.params[`${endpoint}_no_context_takeover`]) {
704
- this._deflate.reset();
705
- }
706
-
707
- callback(null, data);
708
- });
709
- }
710
- }
711
-
712
- permessageDeflate = PerMessageDeflate;
713
-
714
- /**
715
- * The listener of the `zlib.DeflateRaw` stream `'data'` event.
716
- *
717
- * @param {Buffer} chunk A chunk of data
718
- * @private
719
- */
720
- function deflateOnData(chunk) {
721
- this[kBuffers].push(chunk);
722
- this[kTotalLength] += chunk.length;
723
- }
724
-
725
- /**
726
- * The listener of the `zlib.InflateRaw` stream `'data'` event.
727
- *
728
- * @param {Buffer} chunk A chunk of data
729
- * @private
730
- */
731
- function inflateOnData(chunk) {
732
- this[kTotalLength] += chunk.length;
733
-
734
- if (
735
- this[kPerMessageDeflate]._maxPayload < 1 ||
736
- this[kTotalLength] <= this[kPerMessageDeflate]._maxPayload
737
- ) {
738
- this[kBuffers].push(chunk);
739
- return;
740
- }
741
-
742
- this[kError] = new RangeError('Max payload size exceeded');
743
- this[kError].code = 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH';
744
- this[kError][kStatusCode] = 1009;
745
- this.removeListener('data', inflateOnData);
746
-
747
- //
748
- // The choice to employ `zlib.reset()` over `zlib.close()` is dictated by the
749
- // fact that in Node.js versions prior to 13.10.0, the callback for
750
- // `zlib.flush()` is not called if `zlib.close()` is used. Utilizing
751
- // `zlib.reset()` ensures that either the callback is invoked or an error is
752
- // emitted.
753
- //
754
- this.reset();
755
- }
756
-
757
- /**
758
- * The listener of the `zlib.InflateRaw` stream `'error'` event.
759
- *
760
- * @param {Error} err The emitted error
761
- * @private
762
- */
763
- function inflateOnError(err) {
764
- //
765
- // There is no need to call `Zlib#close()` as the handle is automatically
766
- // closed when an error is emitted.
767
- //
768
- this[kPerMessageDeflate]._inflate = null;
769
-
770
- if (this[kError]) {
771
- this[kCallback](this[kError]);
772
- return;
773
- }
774
-
775
- err[kStatusCode] = 1007;
776
- this[kCallback](err);
777
- }
778
- return permessageDeflate;
779
- }
780
-
781
- var validation = {exports: {}};
782
-
783
- var hasRequiredValidation;
784
-
785
- function requireValidation () {
786
- if (hasRequiredValidation) return validation.exports;
787
- hasRequiredValidation = 1;
788
-
789
- const { isUtf8 } = require$$0$1;
790
-
791
- const { hasBlob } = requireConstants();
792
-
793
- //
794
- // Allowed token characters:
795
- //
796
- // '!', '#', '$', '%', '&', ''', '*', '+', '-',
797
- // '.', 0-9, A-Z, '^', '_', '`', a-z, '|', '~'
798
- //
799
- // tokenChars[32] === 0 // ' '
800
- // tokenChars[33] === 1 // '!'
801
- // tokenChars[34] === 0 // '"'
802
- // ...
803
- //
804
- // prettier-ignore
805
- const tokenChars = [
806
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 15
807
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16 - 31
808
- 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, // 32 - 47
809
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // 48 - 63
810
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 64 - 79
811
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, // 80 - 95
812
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 96 - 111
813
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 // 112 - 127
814
- ];
815
-
816
- /**
817
- * Checks if a status code is allowed in a close frame.
818
- *
819
- * @param {Number} code The status code
820
- * @return {Boolean} `true` if the status code is valid, else `false`
821
- * @public
822
- */
823
- function isValidStatusCode(code) {
824
- return (
825
- (code >= 1000 &&
826
- code <= 1014 &&
827
- code !== 1004 &&
828
- code !== 1005 &&
829
- code !== 1006) ||
830
- (code >= 3000 && code <= 4999)
831
- );
832
- }
833
-
834
- /**
835
- * Checks if a given buffer contains only correct UTF-8.
836
- * Ported from https://www.cl.cam.ac.uk/%7Emgk25/ucs/utf8_check.c by
837
- * Markus Kuhn.
838
- *
839
- * @param {Buffer} buf The buffer to check
840
- * @return {Boolean} `true` if `buf` contains only correct UTF-8, else `false`
841
- * @public
842
- */
843
- function _isValidUTF8(buf) {
844
- const len = buf.length;
845
- let i = 0;
846
-
847
- while (i < len) {
848
- if ((buf[i] & 0x80) === 0) {
849
- // 0xxxxxxx
850
- i++;
851
- } else if ((buf[i] & 0xe0) === 0xc0) {
852
- // 110xxxxx 10xxxxxx
853
- if (
854
- i + 1 === len ||
855
- (buf[i + 1] & 0xc0) !== 0x80 ||
856
- (buf[i] & 0xfe) === 0xc0 // Overlong
857
- ) {
858
- return false;
859
- }
860
-
861
- i += 2;
862
- } else if ((buf[i] & 0xf0) === 0xe0) {
863
- // 1110xxxx 10xxxxxx 10xxxxxx
864
- if (
865
- i + 2 >= len ||
866
- (buf[i + 1] & 0xc0) !== 0x80 ||
867
- (buf[i + 2] & 0xc0) !== 0x80 ||
868
- (buf[i] === 0xe0 && (buf[i + 1] & 0xe0) === 0x80) || // Overlong
869
- (buf[i] === 0xed && (buf[i + 1] & 0xe0) === 0xa0) // Surrogate (U+D800 - U+DFFF)
870
- ) {
871
- return false;
872
- }
873
-
874
- i += 3;
875
- } else if ((buf[i] & 0xf8) === 0xf0) {
876
- // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
877
- if (
878
- i + 3 >= len ||
879
- (buf[i + 1] & 0xc0) !== 0x80 ||
880
- (buf[i + 2] & 0xc0) !== 0x80 ||
881
- (buf[i + 3] & 0xc0) !== 0x80 ||
882
- (buf[i] === 0xf0 && (buf[i + 1] & 0xf0) === 0x80) || // Overlong
883
- (buf[i] === 0xf4 && buf[i + 1] > 0x8f) ||
884
- buf[i] > 0xf4 // > U+10FFFF
885
- ) {
886
- return false;
887
- }
888
-
889
- i += 4;
890
- } else {
891
- return false;
892
- }
893
- }
894
-
895
- return true;
896
- }
897
-
898
- /**
899
- * Determines whether a value is a `Blob`.
900
- *
901
- * @param {*} value The value to be tested
902
- * @return {Boolean} `true` if `value` is a `Blob`, else `false`
903
- * @private
904
- */
905
- function isBlob(value) {
906
- return (
907
- hasBlob &&
908
- typeof value === 'object' &&
909
- typeof value.arrayBuffer === 'function' &&
910
- typeof value.type === 'string' &&
911
- typeof value.stream === 'function' &&
912
- (value[Symbol.toStringTag] === 'Blob' ||
913
- value[Symbol.toStringTag] === 'File')
914
- );
915
- }
916
-
917
- validation.exports = {
918
- isBlob,
919
- isValidStatusCode,
920
- isValidUTF8: _isValidUTF8,
921
- tokenChars
922
- };
923
-
924
- if (isUtf8) {
925
- validation.exports.isValidUTF8 = function (buf) {
926
- return buf.length < 24 ? _isValidUTF8(buf) : isUtf8(buf);
927
- };
928
- } /* istanbul ignore else */ else if (!process.env.WS_NO_UTF_8_VALIDATE) {
929
- try {
930
- const isValidUTF8 = require('utf-8-validate');
931
-
932
- validation.exports.isValidUTF8 = function (buf) {
933
- return buf.length < 32 ? _isValidUTF8(buf) : isValidUTF8(buf);
934
- };
935
- } catch (e) {
936
- // Continue regardless of the error.
937
- }
938
- }
939
- return validation.exports;
940
- }
941
-
942
- var receiver;
943
- var hasRequiredReceiver;
944
-
945
- function requireReceiver () {
946
- if (hasRequiredReceiver) return receiver;
947
- hasRequiredReceiver = 1;
948
-
949
- const { Writable } = require$$0$2;
950
-
951
- const PerMessageDeflate = requirePermessageDeflate();
952
- const {
953
- BINARY_TYPES,
954
- EMPTY_BUFFER,
955
- kStatusCode,
956
- kWebSocket
957
- } = requireConstants();
958
- const { concat, toArrayBuffer, unmask } = requireBufferUtil();
959
- const { isValidStatusCode, isValidUTF8 } = requireValidation();
960
-
961
- const FastBuffer = Buffer[Symbol.species];
962
-
963
- const GET_INFO = 0;
964
- const GET_PAYLOAD_LENGTH_16 = 1;
965
- const GET_PAYLOAD_LENGTH_64 = 2;
966
- const GET_MASK = 3;
967
- const GET_DATA = 4;
968
- const INFLATING = 5;
969
- const DEFER_EVENT = 6;
970
-
971
- /**
972
- * HyBi Receiver implementation.
973
- *
974
- * @extends Writable
975
- */
976
- class Receiver extends Writable {
977
- /**
978
- * Creates a Receiver instance.
979
- *
980
- * @param {Object} [options] Options object
981
- * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
982
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
983
- * multiple times in the same tick
984
- * @param {String} [options.binaryType=nodebuffer] The type for binary data
985
- * @param {Object} [options.extensions] An object containing the negotiated
986
- * extensions
987
- * @param {Boolean} [options.isServer=false] Specifies whether to operate in
988
- * client or server mode
989
- * @param {Number} [options.maxPayload=0] The maximum allowed message length
990
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
991
- * not to skip UTF-8 validation for text and close messages
992
- */
993
- constructor(options = {}) {
994
- super();
995
-
996
- this._allowSynchronousEvents =
997
- options.allowSynchronousEvents !== undefined
998
- ? options.allowSynchronousEvents
999
- : true;
1000
- this._binaryType = options.binaryType || BINARY_TYPES[0];
1001
- this._extensions = options.extensions || {};
1002
- this._isServer = !!options.isServer;
1003
- this._maxPayload = options.maxPayload | 0;
1004
- this._skipUTF8Validation = !!options.skipUTF8Validation;
1005
- this[kWebSocket] = undefined;
1006
-
1007
- this._bufferedBytes = 0;
1008
- this._buffers = [];
1009
-
1010
- this._compressed = false;
1011
- this._payloadLength = 0;
1012
- this._mask = undefined;
1013
- this._fragmented = 0;
1014
- this._masked = false;
1015
- this._fin = false;
1016
- this._opcode = 0;
1017
-
1018
- this._totalPayloadLength = 0;
1019
- this._messageLength = 0;
1020
- this._fragments = [];
1021
-
1022
- this._errored = false;
1023
- this._loop = false;
1024
- this._state = GET_INFO;
1025
- }
1026
-
1027
- /**
1028
- * Implements `Writable.prototype._write()`.
1029
- *
1030
- * @param {Buffer} chunk The chunk of data to write
1031
- * @param {String} encoding The character encoding of `chunk`
1032
- * @param {Function} cb Callback
1033
- * @private
1034
- */
1035
- _write(chunk, encoding, cb) {
1036
- if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
1037
-
1038
- this._bufferedBytes += chunk.length;
1039
- this._buffers.push(chunk);
1040
- this.startLoop(cb);
1041
- }
1042
-
1043
- /**
1044
- * Consumes `n` bytes from the buffered data.
1045
- *
1046
- * @param {Number} n The number of bytes to consume
1047
- * @return {Buffer} The consumed bytes
1048
- * @private
1049
- */
1050
- consume(n) {
1051
- this._bufferedBytes -= n;
1052
-
1053
- if (n === this._buffers[0].length) return this._buffers.shift();
1054
-
1055
- if (n < this._buffers[0].length) {
1056
- const buf = this._buffers[0];
1057
- this._buffers[0] = new FastBuffer(
1058
- buf.buffer,
1059
- buf.byteOffset + n,
1060
- buf.length - n
1061
- );
1062
-
1063
- return new FastBuffer(buf.buffer, buf.byteOffset, n);
1064
- }
1065
-
1066
- const dst = Buffer.allocUnsafe(n);
1067
-
1068
- do {
1069
- const buf = this._buffers[0];
1070
- const offset = dst.length - n;
1071
-
1072
- if (n >= buf.length) {
1073
- dst.set(this._buffers.shift(), offset);
1074
- } else {
1075
- dst.set(new Uint8Array(buf.buffer, buf.byteOffset, n), offset);
1076
- this._buffers[0] = new FastBuffer(
1077
- buf.buffer,
1078
- buf.byteOffset + n,
1079
- buf.length - n
1080
- );
1081
- }
1082
-
1083
- n -= buf.length;
1084
- } while (n > 0);
1085
-
1086
- return dst;
1087
- }
1088
-
1089
- /**
1090
- * Starts the parsing loop.
1091
- *
1092
- * @param {Function} cb Callback
1093
- * @private
1094
- */
1095
- startLoop(cb) {
1096
- this._loop = true;
1097
-
1098
- do {
1099
- switch (this._state) {
1100
- case GET_INFO:
1101
- this.getInfo(cb);
1102
- break;
1103
- case GET_PAYLOAD_LENGTH_16:
1104
- this.getPayloadLength16(cb);
1105
- break;
1106
- case GET_PAYLOAD_LENGTH_64:
1107
- this.getPayloadLength64(cb);
1108
- break;
1109
- case GET_MASK:
1110
- this.getMask();
1111
- break;
1112
- case GET_DATA:
1113
- this.getData(cb);
1114
- break;
1115
- case INFLATING:
1116
- case DEFER_EVENT:
1117
- this._loop = false;
1118
- return;
1119
- }
1120
- } while (this._loop);
1121
-
1122
- if (!this._errored) cb();
1123
- }
1124
-
1125
- /**
1126
- * Reads the first two bytes of a frame.
1127
- *
1128
- * @param {Function} cb Callback
1129
- * @private
1130
- */
1131
- getInfo(cb) {
1132
- if (this._bufferedBytes < 2) {
1133
- this._loop = false;
1134
- return;
1135
- }
1136
-
1137
- const buf = this.consume(2);
1138
-
1139
- if ((buf[0] & 0x30) !== 0x00) {
1140
- const error = this.createError(
1141
- RangeError,
1142
- 'RSV2 and RSV3 must be clear',
1143
- true,
1144
- 1002,
1145
- 'WS_ERR_UNEXPECTED_RSV_2_3'
1146
- );
1147
-
1148
- cb(error);
1149
- return;
1150
- }
1151
-
1152
- const compressed = (buf[0] & 0x40) === 0x40;
1153
-
1154
- if (compressed && !this._extensions[PerMessageDeflate.extensionName]) {
1155
- const error = this.createError(
1156
- RangeError,
1157
- 'RSV1 must be clear',
1158
- true,
1159
- 1002,
1160
- 'WS_ERR_UNEXPECTED_RSV_1'
1161
- );
1162
-
1163
- cb(error);
1164
- return;
1165
- }
1166
-
1167
- this._fin = (buf[0] & 0x80) === 0x80;
1168
- this._opcode = buf[0] & 0x0f;
1169
- this._payloadLength = buf[1] & 0x7f;
1170
-
1171
- if (this._opcode === 0x00) {
1172
- if (compressed) {
1173
- const error = this.createError(
1174
- RangeError,
1175
- 'RSV1 must be clear',
1176
- true,
1177
- 1002,
1178
- 'WS_ERR_UNEXPECTED_RSV_1'
1179
- );
1180
-
1181
- cb(error);
1182
- return;
1183
- }
1184
-
1185
- if (!this._fragmented) {
1186
- const error = this.createError(
1187
- RangeError,
1188
- 'invalid opcode 0',
1189
- true,
1190
- 1002,
1191
- 'WS_ERR_INVALID_OPCODE'
1192
- );
1193
-
1194
- cb(error);
1195
- return;
1196
- }
1197
-
1198
- this._opcode = this._fragmented;
1199
- } else if (this._opcode === 0x01 || this._opcode === 0x02) {
1200
- if (this._fragmented) {
1201
- const error = this.createError(
1202
- RangeError,
1203
- `invalid opcode ${this._opcode}`,
1204
- true,
1205
- 1002,
1206
- 'WS_ERR_INVALID_OPCODE'
1207
- );
1208
-
1209
- cb(error);
1210
- return;
1211
- }
1212
-
1213
- this._compressed = compressed;
1214
- } else if (this._opcode > 0x07 && this._opcode < 0x0b) {
1215
- if (!this._fin) {
1216
- const error = this.createError(
1217
- RangeError,
1218
- 'FIN must be set',
1219
- true,
1220
- 1002,
1221
- 'WS_ERR_EXPECTED_FIN'
1222
- );
1223
-
1224
- cb(error);
1225
- return;
1226
- }
1227
-
1228
- if (compressed) {
1229
- const error = this.createError(
1230
- RangeError,
1231
- 'RSV1 must be clear',
1232
- true,
1233
- 1002,
1234
- 'WS_ERR_UNEXPECTED_RSV_1'
1235
- );
1236
-
1237
- cb(error);
1238
- return;
1239
- }
1240
-
1241
- if (
1242
- this._payloadLength > 0x7d ||
1243
- (this._opcode === 0x08 && this._payloadLength === 1)
1244
- ) {
1245
- const error = this.createError(
1246
- RangeError,
1247
- `invalid payload length ${this._payloadLength}`,
1248
- true,
1249
- 1002,
1250
- 'WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH'
1251
- );
1252
-
1253
- cb(error);
1254
- return;
1255
- }
1256
- } else {
1257
- const error = this.createError(
1258
- RangeError,
1259
- `invalid opcode ${this._opcode}`,
1260
- true,
1261
- 1002,
1262
- 'WS_ERR_INVALID_OPCODE'
1263
- );
1264
-
1265
- cb(error);
1266
- return;
1267
- }
1268
-
1269
- if (!this._fin && !this._fragmented) this._fragmented = this._opcode;
1270
- this._masked = (buf[1] & 0x80) === 0x80;
1271
-
1272
- if (this._isServer) {
1273
- if (!this._masked) {
1274
- const error = this.createError(
1275
- RangeError,
1276
- 'MASK must be set',
1277
- true,
1278
- 1002,
1279
- 'WS_ERR_EXPECTED_MASK'
1280
- );
1281
-
1282
- cb(error);
1283
- return;
1284
- }
1285
- } else if (this._masked) {
1286
- const error = this.createError(
1287
- RangeError,
1288
- 'MASK must be clear',
1289
- true,
1290
- 1002,
1291
- 'WS_ERR_UNEXPECTED_MASK'
1292
- );
1293
-
1294
- cb(error);
1295
- return;
1296
- }
1297
-
1298
- if (this._payloadLength === 126) this._state = GET_PAYLOAD_LENGTH_16;
1299
- else if (this._payloadLength === 127) this._state = GET_PAYLOAD_LENGTH_64;
1300
- else this.haveLength(cb);
1301
- }
1302
-
1303
- /**
1304
- * Gets extended payload length (7+16).
1305
- *
1306
- * @param {Function} cb Callback
1307
- * @private
1308
- */
1309
- getPayloadLength16(cb) {
1310
- if (this._bufferedBytes < 2) {
1311
- this._loop = false;
1312
- return;
1313
- }
1314
-
1315
- this._payloadLength = this.consume(2).readUInt16BE(0);
1316
- this.haveLength(cb);
1317
- }
1318
-
1319
- /**
1320
- * Gets extended payload length (7+64).
1321
- *
1322
- * @param {Function} cb Callback
1323
- * @private
1324
- */
1325
- getPayloadLength64(cb) {
1326
- if (this._bufferedBytes < 8) {
1327
- this._loop = false;
1328
- return;
1329
- }
1330
-
1331
- const buf = this.consume(8);
1332
- const num = buf.readUInt32BE(0);
1333
-
1334
- //
1335
- // The maximum safe integer in JavaScript is 2^53 - 1. An error is returned
1336
- // if payload length is greater than this number.
1337
- //
1338
- if (num > Math.pow(2, 53 - 32) - 1) {
1339
- const error = this.createError(
1340
- RangeError,
1341
- 'Unsupported WebSocket frame: payload length > 2^53 - 1',
1342
- false,
1343
- 1009,
1344
- 'WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH'
1345
- );
1346
-
1347
- cb(error);
1348
- return;
1349
- }
1350
-
1351
- this._payloadLength = num * Math.pow(2, 32) + buf.readUInt32BE(4);
1352
- this.haveLength(cb);
1353
- }
1354
-
1355
- /**
1356
- * Payload length has been read.
1357
- *
1358
- * @param {Function} cb Callback
1359
- * @private
1360
- */
1361
- haveLength(cb) {
1362
- if (this._payloadLength && this._opcode < 0x08) {
1363
- this._totalPayloadLength += this._payloadLength;
1364
- if (this._totalPayloadLength > this._maxPayload && this._maxPayload > 0) {
1365
- const error = this.createError(
1366
- RangeError,
1367
- 'Max payload size exceeded',
1368
- false,
1369
- 1009,
1370
- 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
1371
- );
1372
-
1373
- cb(error);
1374
- return;
1375
- }
1376
- }
1377
-
1378
- if (this._masked) this._state = GET_MASK;
1379
- else this._state = GET_DATA;
1380
- }
1381
-
1382
- /**
1383
- * Reads mask bytes.
1384
- *
1385
- * @private
1386
- */
1387
- getMask() {
1388
- if (this._bufferedBytes < 4) {
1389
- this._loop = false;
1390
- return;
1391
- }
1392
-
1393
- this._mask = this.consume(4);
1394
- this._state = GET_DATA;
1395
- }
1396
-
1397
- /**
1398
- * Reads data bytes.
1399
- *
1400
- * @param {Function} cb Callback
1401
- * @private
1402
- */
1403
- getData(cb) {
1404
- let data = EMPTY_BUFFER;
1405
-
1406
- if (this._payloadLength) {
1407
- if (this._bufferedBytes < this._payloadLength) {
1408
- this._loop = false;
1409
- return;
1410
- }
1411
-
1412
- data = this.consume(this._payloadLength);
1413
-
1414
- if (
1415
- this._masked &&
1416
- (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0
1417
- ) {
1418
- unmask(data, this._mask);
1419
- }
1420
- }
1421
-
1422
- if (this._opcode > 0x07) {
1423
- this.controlMessage(data, cb);
1424
- return;
1425
- }
1426
-
1427
- if (this._compressed) {
1428
- this._state = INFLATING;
1429
- this.decompress(data, cb);
1430
- return;
1431
- }
1432
-
1433
- if (data.length) {
1434
- //
1435
- // This message is not compressed so its length is the sum of the payload
1436
- // length of all fragments.
1437
- //
1438
- this._messageLength = this._totalPayloadLength;
1439
- this._fragments.push(data);
1440
- }
1441
-
1442
- this.dataMessage(cb);
1443
- }
1444
-
1445
- /**
1446
- * Decompresses data.
1447
- *
1448
- * @param {Buffer} data Compressed data
1449
- * @param {Function} cb Callback
1450
- * @private
1451
- */
1452
- decompress(data, cb) {
1453
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
1454
-
1455
- perMessageDeflate.decompress(data, this._fin, (err, buf) => {
1456
- if (err) return cb(err);
1457
-
1458
- if (buf.length) {
1459
- this._messageLength += buf.length;
1460
- if (this._messageLength > this._maxPayload && this._maxPayload > 0) {
1461
- const error = this.createError(
1462
- RangeError,
1463
- 'Max payload size exceeded',
1464
- false,
1465
- 1009,
1466
- 'WS_ERR_UNSUPPORTED_MESSAGE_LENGTH'
1467
- );
1468
-
1469
- cb(error);
1470
- return;
1471
- }
1472
-
1473
- this._fragments.push(buf);
1474
- }
1475
-
1476
- this.dataMessage(cb);
1477
- if (this._state === GET_INFO) this.startLoop(cb);
1478
- });
1479
- }
1480
-
1481
- /**
1482
- * Handles a data message.
1483
- *
1484
- * @param {Function} cb Callback
1485
- * @private
1486
- */
1487
- dataMessage(cb) {
1488
- if (!this._fin) {
1489
- this._state = GET_INFO;
1490
- return;
1491
- }
1492
-
1493
- const messageLength = this._messageLength;
1494
- const fragments = this._fragments;
1495
-
1496
- this._totalPayloadLength = 0;
1497
- this._messageLength = 0;
1498
- this._fragmented = 0;
1499
- this._fragments = [];
1500
-
1501
- if (this._opcode === 2) {
1502
- let data;
1503
-
1504
- if (this._binaryType === 'nodebuffer') {
1505
- data = concat(fragments, messageLength);
1506
- } else if (this._binaryType === 'arraybuffer') {
1507
- data = toArrayBuffer(concat(fragments, messageLength));
1508
- } else if (this._binaryType === 'blob') {
1509
- data = new Blob(fragments);
1510
- } else {
1511
- data = fragments;
1512
- }
1513
-
1514
- if (this._allowSynchronousEvents) {
1515
- this.emit('message', data, true);
1516
- this._state = GET_INFO;
1517
- } else {
1518
- this._state = DEFER_EVENT;
1519
- setImmediate(() => {
1520
- this.emit('message', data, true);
1521
- this._state = GET_INFO;
1522
- this.startLoop(cb);
1523
- });
1524
- }
1525
- } else {
1526
- const buf = concat(fragments, messageLength);
1527
-
1528
- if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1529
- const error = this.createError(
1530
- Error,
1531
- 'invalid UTF-8 sequence',
1532
- true,
1533
- 1007,
1534
- 'WS_ERR_INVALID_UTF8'
1535
- );
1536
-
1537
- cb(error);
1538
- return;
1539
- }
1540
-
1541
- if (this._state === INFLATING || this._allowSynchronousEvents) {
1542
- this.emit('message', buf, false);
1543
- this._state = GET_INFO;
1544
- } else {
1545
- this._state = DEFER_EVENT;
1546
- setImmediate(() => {
1547
- this.emit('message', buf, false);
1548
- this._state = GET_INFO;
1549
- this.startLoop(cb);
1550
- });
1551
- }
1552
- }
1553
- }
1554
-
1555
- /**
1556
- * Handles a control message.
1557
- *
1558
- * @param {Buffer} data Data to handle
1559
- * @return {(Error|RangeError|undefined)} A possible error
1560
- * @private
1561
- */
1562
- controlMessage(data, cb) {
1563
- if (this._opcode === 0x08) {
1564
- if (data.length === 0) {
1565
- this._loop = false;
1566
- this.emit('conclude', 1005, EMPTY_BUFFER);
1567
- this.end();
1568
- } else {
1569
- const code = data.readUInt16BE(0);
1570
-
1571
- if (!isValidStatusCode(code)) {
1572
- const error = this.createError(
1573
- RangeError,
1574
- `invalid status code ${code}`,
1575
- true,
1576
- 1002,
1577
- 'WS_ERR_INVALID_CLOSE_CODE'
1578
- );
1579
-
1580
- cb(error);
1581
- return;
1582
- }
1583
-
1584
- const buf = new FastBuffer(
1585
- data.buffer,
1586
- data.byteOffset + 2,
1587
- data.length - 2
1588
- );
1589
-
1590
- if (!this._skipUTF8Validation && !isValidUTF8(buf)) {
1591
- const error = this.createError(
1592
- Error,
1593
- 'invalid UTF-8 sequence',
1594
- true,
1595
- 1007,
1596
- 'WS_ERR_INVALID_UTF8'
1597
- );
1598
-
1599
- cb(error);
1600
- return;
1601
- }
1602
-
1603
- this._loop = false;
1604
- this.emit('conclude', code, buf);
1605
- this.end();
1606
- }
1607
-
1608
- this._state = GET_INFO;
1609
- return;
1610
- }
1611
-
1612
- if (this._allowSynchronousEvents) {
1613
- this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
1614
- this._state = GET_INFO;
1615
- } else {
1616
- this._state = DEFER_EVENT;
1617
- setImmediate(() => {
1618
- this.emit(this._opcode === 0x09 ? 'ping' : 'pong', data);
1619
- this._state = GET_INFO;
1620
- this.startLoop(cb);
1621
- });
1622
- }
1623
- }
1624
-
1625
- /**
1626
- * Builds an error object.
1627
- *
1628
- * @param {function(new:Error|RangeError)} ErrorCtor The error constructor
1629
- * @param {String} message The error message
1630
- * @param {Boolean} prefix Specifies whether or not to add a default prefix to
1631
- * `message`
1632
- * @param {Number} statusCode The status code
1633
- * @param {String} errorCode The exposed error code
1634
- * @return {(Error|RangeError)} The error
1635
- * @private
1636
- */
1637
- createError(ErrorCtor, message, prefix, statusCode, errorCode) {
1638
- this._loop = false;
1639
- this._errored = true;
1640
-
1641
- const err = new ErrorCtor(
1642
- prefix ? `Invalid WebSocket frame: ${message}` : message
1643
- );
1644
-
1645
- Error.captureStackTrace(err, this.createError);
1646
- err.code = errorCode;
1647
- err[kStatusCode] = statusCode;
1648
- return err;
1649
- }
1650
- }
1651
-
1652
- receiver = Receiver;
1653
- return receiver;
1654
- }
1655
-
1656
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex" }] */
1657
-
1658
- var sender;
1659
- var hasRequiredSender;
1660
-
1661
- function requireSender () {
1662
- if (hasRequiredSender) return sender;
1663
- hasRequiredSender = 1;
1664
-
1665
- const { Duplex } = require$$0$2;
1666
- const { randomFillSync } = require$$1;
1667
-
1668
- const PerMessageDeflate = requirePermessageDeflate();
1669
- const { EMPTY_BUFFER, kWebSocket, NOOP } = requireConstants();
1670
- const { isBlob, isValidStatusCode } = requireValidation();
1671
- const { mask: applyMask, toBuffer } = requireBufferUtil();
1672
-
1673
- const kByteLength = Symbol('kByteLength');
1674
- const maskBuffer = Buffer.alloc(4);
1675
- const RANDOM_POOL_SIZE = 8 * 1024;
1676
- let randomPool;
1677
- let randomPoolPointer = RANDOM_POOL_SIZE;
1678
-
1679
- const DEFAULT = 0;
1680
- const DEFLATING = 1;
1681
- const GET_BLOB_DATA = 2;
1682
-
1683
- /**
1684
- * HyBi Sender implementation.
1685
- */
1686
- class Sender {
1687
- /**
1688
- * Creates a Sender instance.
1689
- *
1690
- * @param {Duplex} socket The connection socket
1691
- * @param {Object} [extensions] An object containing the negotiated extensions
1692
- * @param {Function} [generateMask] The function used to generate the masking
1693
- * key
1694
- */
1695
- constructor(socket, extensions, generateMask) {
1696
- this._extensions = extensions || {};
1697
-
1698
- if (generateMask) {
1699
- this._generateMask = generateMask;
1700
- this._maskBuffer = Buffer.alloc(4);
1701
- }
1702
-
1703
- this._socket = socket;
1704
-
1705
- this._firstFragment = true;
1706
- this._compress = false;
1707
-
1708
- this._bufferedBytes = 0;
1709
- this._queue = [];
1710
- this._state = DEFAULT;
1711
- this.onerror = NOOP;
1712
- this[kWebSocket] = undefined;
1713
- }
1714
-
1715
- /**
1716
- * Frames a piece of data according to the HyBi WebSocket protocol.
1717
- *
1718
- * @param {(Buffer|String)} data The data to frame
1719
- * @param {Object} options Options object
1720
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
1721
- * FIN bit
1722
- * @param {Function} [options.generateMask] The function used to generate the
1723
- * masking key
1724
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
1725
- * `data`
1726
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
1727
- * key
1728
- * @param {Number} options.opcode The opcode
1729
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
1730
- * modified
1731
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
1732
- * RSV1 bit
1733
- * @return {(Buffer|String)[]} The framed data
1734
- * @public
1735
- */
1736
- static frame(data, options) {
1737
- let mask;
1738
- let merge = false;
1739
- let offset = 2;
1740
- let skipMasking = false;
1741
-
1742
- if (options.mask) {
1743
- mask = options.maskBuffer || maskBuffer;
1744
-
1745
- if (options.generateMask) {
1746
- options.generateMask(mask);
1747
- } else {
1748
- if (randomPoolPointer === RANDOM_POOL_SIZE) {
1749
- /* istanbul ignore else */
1750
- if (randomPool === undefined) {
1751
- //
1752
- // This is lazily initialized because server-sent frames must not
1753
- // be masked so it may never be used.
1754
- //
1755
- randomPool = Buffer.alloc(RANDOM_POOL_SIZE);
1756
- }
1757
-
1758
- randomFillSync(randomPool, 0, RANDOM_POOL_SIZE);
1759
- randomPoolPointer = 0;
1760
- }
1761
-
1762
- mask[0] = randomPool[randomPoolPointer++];
1763
- mask[1] = randomPool[randomPoolPointer++];
1764
- mask[2] = randomPool[randomPoolPointer++];
1765
- mask[3] = randomPool[randomPoolPointer++];
1766
- }
1767
-
1768
- skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0;
1769
- offset = 6;
1770
- }
1771
-
1772
- let dataLength;
1773
-
1774
- if (typeof data === 'string') {
1775
- if (
1776
- (!options.mask || skipMasking) &&
1777
- options[kByteLength] !== undefined
1778
- ) {
1779
- dataLength = options[kByteLength];
1780
- } else {
1781
- data = Buffer.from(data);
1782
- dataLength = data.length;
1783
- }
1784
- } else {
1785
- dataLength = data.length;
1786
- merge = options.mask && options.readOnly && !skipMasking;
1787
- }
1788
-
1789
- let payloadLength = dataLength;
1790
-
1791
- if (dataLength >= 65536) {
1792
- offset += 8;
1793
- payloadLength = 127;
1794
- } else if (dataLength > 125) {
1795
- offset += 2;
1796
- payloadLength = 126;
1797
- }
1798
-
1799
- const target = Buffer.allocUnsafe(merge ? dataLength + offset : offset);
1800
-
1801
- target[0] = options.fin ? options.opcode | 0x80 : options.opcode;
1802
- if (options.rsv1) target[0] |= 0x40;
1803
-
1804
- target[1] = payloadLength;
1805
-
1806
- if (payloadLength === 126) {
1807
- target.writeUInt16BE(dataLength, 2);
1808
- } else if (payloadLength === 127) {
1809
- target[2] = target[3] = 0;
1810
- target.writeUIntBE(dataLength, 4, 6);
1811
- }
1812
-
1813
- if (!options.mask) return [target, data];
1814
-
1815
- target[1] |= 0x80;
1816
- target[offset - 4] = mask[0];
1817
- target[offset - 3] = mask[1];
1818
- target[offset - 2] = mask[2];
1819
- target[offset - 1] = mask[3];
1820
-
1821
- if (skipMasking) return [target, data];
1822
-
1823
- if (merge) {
1824
- applyMask(data, mask, target, offset, dataLength);
1825
- return [target];
1826
- }
1827
-
1828
- applyMask(data, mask, data, 0, dataLength);
1829
- return [target, data];
1830
- }
1831
-
1832
- /**
1833
- * Sends a close message to the other peer.
1834
- *
1835
- * @param {Number} [code] The status code component of the body
1836
- * @param {(String|Buffer)} [data] The message component of the body
1837
- * @param {Boolean} [mask=false] Specifies whether or not to mask the message
1838
- * @param {Function} [cb] Callback
1839
- * @public
1840
- */
1841
- close(code, data, mask, cb) {
1842
- let buf;
1843
-
1844
- if (code === undefined) {
1845
- buf = EMPTY_BUFFER;
1846
- } else if (typeof code !== 'number' || !isValidStatusCode(code)) {
1847
- throw new TypeError('First argument must be a valid error code number');
1848
- } else if (data === undefined || !data.length) {
1849
- buf = Buffer.allocUnsafe(2);
1850
- buf.writeUInt16BE(code, 0);
1851
- } else {
1852
- const length = Buffer.byteLength(data);
1853
-
1854
- if (length > 123) {
1855
- throw new RangeError('The message must not be greater than 123 bytes');
1856
- }
1857
-
1858
- buf = Buffer.allocUnsafe(2 + length);
1859
- buf.writeUInt16BE(code, 0);
1860
-
1861
- if (typeof data === 'string') {
1862
- buf.write(data, 2);
1863
- } else {
1864
- buf.set(data, 2);
1865
- }
1866
- }
1867
-
1868
- const options = {
1869
- [kByteLength]: buf.length,
1870
- fin: true,
1871
- generateMask: this._generateMask,
1872
- mask,
1873
- maskBuffer: this._maskBuffer,
1874
- opcode: 0x08,
1875
- readOnly: false,
1876
- rsv1: false
1877
- };
1878
-
1879
- if (this._state !== DEFAULT) {
1880
- this.enqueue([this.dispatch, buf, false, options, cb]);
1881
- } else {
1882
- this.sendFrame(Sender.frame(buf, options), cb);
1883
- }
1884
- }
1885
-
1886
- /**
1887
- * Sends a ping message to the other peer.
1888
- *
1889
- * @param {*} data The message to send
1890
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1891
- * @param {Function} [cb] Callback
1892
- * @public
1893
- */
1894
- ping(data, mask, cb) {
1895
- let byteLength;
1896
- let readOnly;
1897
-
1898
- if (typeof data === 'string') {
1899
- byteLength = Buffer.byteLength(data);
1900
- readOnly = false;
1901
- } else if (isBlob(data)) {
1902
- byteLength = data.size;
1903
- readOnly = false;
1904
- } else {
1905
- data = toBuffer(data);
1906
- byteLength = data.length;
1907
- readOnly = toBuffer.readOnly;
1908
- }
1909
-
1910
- if (byteLength > 125) {
1911
- throw new RangeError('The data size must not be greater than 125 bytes');
1912
- }
1913
-
1914
- const options = {
1915
- [kByteLength]: byteLength,
1916
- fin: true,
1917
- generateMask: this._generateMask,
1918
- mask,
1919
- maskBuffer: this._maskBuffer,
1920
- opcode: 0x09,
1921
- readOnly,
1922
- rsv1: false
1923
- };
1924
-
1925
- if (isBlob(data)) {
1926
- if (this._state !== DEFAULT) {
1927
- this.enqueue([this.getBlobData, data, false, options, cb]);
1928
- } else {
1929
- this.getBlobData(data, false, options, cb);
1930
- }
1931
- } else if (this._state !== DEFAULT) {
1932
- this.enqueue([this.dispatch, data, false, options, cb]);
1933
- } else {
1934
- this.sendFrame(Sender.frame(data, options), cb);
1935
- }
1936
- }
1937
-
1938
- /**
1939
- * Sends a pong message to the other peer.
1940
- *
1941
- * @param {*} data The message to send
1942
- * @param {Boolean} [mask=false] Specifies whether or not to mask `data`
1943
- * @param {Function} [cb] Callback
1944
- * @public
1945
- */
1946
- pong(data, mask, cb) {
1947
- let byteLength;
1948
- let readOnly;
1949
-
1950
- if (typeof data === 'string') {
1951
- byteLength = Buffer.byteLength(data);
1952
- readOnly = false;
1953
- } else if (isBlob(data)) {
1954
- byteLength = data.size;
1955
- readOnly = false;
1956
- } else {
1957
- data = toBuffer(data);
1958
- byteLength = data.length;
1959
- readOnly = toBuffer.readOnly;
1960
- }
1961
-
1962
- if (byteLength > 125) {
1963
- throw new RangeError('The data size must not be greater than 125 bytes');
1964
- }
1965
-
1966
- const options = {
1967
- [kByteLength]: byteLength,
1968
- fin: true,
1969
- generateMask: this._generateMask,
1970
- mask,
1971
- maskBuffer: this._maskBuffer,
1972
- opcode: 0x0a,
1973
- readOnly,
1974
- rsv1: false
1975
- };
1976
-
1977
- if (isBlob(data)) {
1978
- if (this._state !== DEFAULT) {
1979
- this.enqueue([this.getBlobData, data, false, options, cb]);
1980
- } else {
1981
- this.getBlobData(data, false, options, cb);
1982
- }
1983
- } else if (this._state !== DEFAULT) {
1984
- this.enqueue([this.dispatch, data, false, options, cb]);
1985
- } else {
1986
- this.sendFrame(Sender.frame(data, options), cb);
1987
- }
1988
- }
1989
-
1990
- /**
1991
- * Sends a data message to the other peer.
1992
- *
1993
- * @param {*} data The message to send
1994
- * @param {Object} options Options object
1995
- * @param {Boolean} [options.binary=false] Specifies whether `data` is binary
1996
- * or text
1997
- * @param {Boolean} [options.compress=false] Specifies whether or not to
1998
- * compress `data`
1999
- * @param {Boolean} [options.fin=false] Specifies whether the fragment is the
2000
- * last one
2001
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
2002
- * `data`
2003
- * @param {Function} [cb] Callback
2004
- * @public
2005
- */
2006
- send(data, options, cb) {
2007
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
2008
- let opcode = options.binary ? 2 : 1;
2009
- let rsv1 = options.compress;
2010
-
2011
- let byteLength;
2012
- let readOnly;
2013
-
2014
- if (typeof data === 'string') {
2015
- byteLength = Buffer.byteLength(data);
2016
- readOnly = false;
2017
- } else if (isBlob(data)) {
2018
- byteLength = data.size;
2019
- readOnly = false;
2020
- } else {
2021
- data = toBuffer(data);
2022
- byteLength = data.length;
2023
- readOnly = toBuffer.readOnly;
2024
- }
2025
-
2026
- if (this._firstFragment) {
2027
- this._firstFragment = false;
2028
- if (
2029
- rsv1 &&
2030
- perMessageDeflate &&
2031
- perMessageDeflate.params[
2032
- perMessageDeflate._isServer
2033
- ? 'server_no_context_takeover'
2034
- : 'client_no_context_takeover'
2035
- ]
2036
- ) {
2037
- rsv1 = byteLength >= perMessageDeflate._threshold;
2038
- }
2039
- this._compress = rsv1;
2040
- } else {
2041
- rsv1 = false;
2042
- opcode = 0;
2043
- }
2044
-
2045
- if (options.fin) this._firstFragment = true;
2046
-
2047
- const opts = {
2048
- [kByteLength]: byteLength,
2049
- fin: options.fin,
2050
- generateMask: this._generateMask,
2051
- mask: options.mask,
2052
- maskBuffer: this._maskBuffer,
2053
- opcode,
2054
- readOnly,
2055
- rsv1
2056
- };
2057
-
2058
- if (isBlob(data)) {
2059
- if (this._state !== DEFAULT) {
2060
- this.enqueue([this.getBlobData, data, this._compress, opts, cb]);
2061
- } else {
2062
- this.getBlobData(data, this._compress, opts, cb);
2063
- }
2064
- } else if (this._state !== DEFAULT) {
2065
- this.enqueue([this.dispatch, data, this._compress, opts, cb]);
2066
- } else {
2067
- this.dispatch(data, this._compress, opts, cb);
2068
- }
2069
- }
2070
-
2071
- /**
2072
- * Gets the contents of a blob as binary data.
2073
- *
2074
- * @param {Blob} blob The blob
2075
- * @param {Boolean} [compress=false] Specifies whether or not to compress
2076
- * the data
2077
- * @param {Object} options Options object
2078
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
2079
- * FIN bit
2080
- * @param {Function} [options.generateMask] The function used to generate the
2081
- * masking key
2082
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
2083
- * `data`
2084
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
2085
- * key
2086
- * @param {Number} options.opcode The opcode
2087
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
2088
- * modified
2089
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
2090
- * RSV1 bit
2091
- * @param {Function} [cb] Callback
2092
- * @private
2093
- */
2094
- getBlobData(blob, compress, options, cb) {
2095
- this._bufferedBytes += options[kByteLength];
2096
- this._state = GET_BLOB_DATA;
2097
-
2098
- blob
2099
- .arrayBuffer()
2100
- .then((arrayBuffer) => {
2101
- if (this._socket.destroyed) {
2102
- const err = new Error(
2103
- 'The socket was closed while the blob was being read'
2104
- );
2105
-
2106
- //
2107
- // `callCallbacks` is called in the next tick to ensure that errors
2108
- // that might be thrown in the callbacks behave like errors thrown
2109
- // outside the promise chain.
2110
- //
2111
- process.nextTick(callCallbacks, this, err, cb);
2112
- return;
2113
- }
2114
-
2115
- this._bufferedBytes -= options[kByteLength];
2116
- const data = toBuffer(arrayBuffer);
2117
-
2118
- if (!compress) {
2119
- this._state = DEFAULT;
2120
- this.sendFrame(Sender.frame(data, options), cb);
2121
- this.dequeue();
2122
- } else {
2123
- this.dispatch(data, compress, options, cb);
2124
- }
2125
- })
2126
- .catch((err) => {
2127
- //
2128
- // `onError` is called in the next tick for the same reason that
2129
- // `callCallbacks` above is.
2130
- //
2131
- process.nextTick(onError, this, err, cb);
2132
- });
2133
- }
2134
-
2135
- /**
2136
- * Dispatches a message.
2137
- *
2138
- * @param {(Buffer|String)} data The message to send
2139
- * @param {Boolean} [compress=false] Specifies whether or not to compress
2140
- * `data`
2141
- * @param {Object} options Options object
2142
- * @param {Boolean} [options.fin=false] Specifies whether or not to set the
2143
- * FIN bit
2144
- * @param {Function} [options.generateMask] The function used to generate the
2145
- * masking key
2146
- * @param {Boolean} [options.mask=false] Specifies whether or not to mask
2147
- * `data`
2148
- * @param {Buffer} [options.maskBuffer] The buffer used to store the masking
2149
- * key
2150
- * @param {Number} options.opcode The opcode
2151
- * @param {Boolean} [options.readOnly=false] Specifies whether `data` can be
2152
- * modified
2153
- * @param {Boolean} [options.rsv1=false] Specifies whether or not to set the
2154
- * RSV1 bit
2155
- * @param {Function} [cb] Callback
2156
- * @private
2157
- */
2158
- dispatch(data, compress, options, cb) {
2159
- if (!compress) {
2160
- this.sendFrame(Sender.frame(data, options), cb);
2161
- return;
2162
- }
2163
-
2164
- const perMessageDeflate = this._extensions[PerMessageDeflate.extensionName];
2165
-
2166
- this._bufferedBytes += options[kByteLength];
2167
- this._state = DEFLATING;
2168
- perMessageDeflate.compress(data, options.fin, (_, buf) => {
2169
- if (this._socket.destroyed) {
2170
- const err = new Error(
2171
- 'The socket was closed while data was being compressed'
2172
- );
2173
-
2174
- callCallbacks(this, err, cb);
2175
- return;
2176
- }
2177
-
2178
- this._bufferedBytes -= options[kByteLength];
2179
- this._state = DEFAULT;
2180
- options.readOnly = false;
2181
- this.sendFrame(Sender.frame(buf, options), cb);
2182
- this.dequeue();
2183
- });
2184
- }
2185
-
2186
- /**
2187
- * Executes queued send operations.
2188
- *
2189
- * @private
2190
- */
2191
- dequeue() {
2192
- while (this._state === DEFAULT && this._queue.length) {
2193
- const params = this._queue.shift();
2194
-
2195
- this._bufferedBytes -= params[3][kByteLength];
2196
- Reflect.apply(params[0], this, params.slice(1));
2197
- }
2198
- }
2199
-
2200
- /**
2201
- * Enqueues a send operation.
2202
- *
2203
- * @param {Array} params Send operation parameters.
2204
- * @private
2205
- */
2206
- enqueue(params) {
2207
- this._bufferedBytes += params[3][kByteLength];
2208
- this._queue.push(params);
2209
- }
2210
-
2211
- /**
2212
- * Sends a frame.
2213
- *
2214
- * @param {(Buffer | String)[]} list The frame to send
2215
- * @param {Function} [cb] Callback
2216
- * @private
2217
- */
2218
- sendFrame(list, cb) {
2219
- if (list.length === 2) {
2220
- this._socket.cork();
2221
- this._socket.write(list[0]);
2222
- this._socket.write(list[1], cb);
2223
- this._socket.uncork();
2224
- } else {
2225
- this._socket.write(list[0], cb);
2226
- }
2227
- }
2228
- }
2229
-
2230
- sender = Sender;
2231
-
2232
- /**
2233
- * Calls queued callbacks with an error.
2234
- *
2235
- * @param {Sender} sender The `Sender` instance
2236
- * @param {Error} err The error to call the callbacks with
2237
- * @param {Function} [cb] The first callback
2238
- * @private
2239
- */
2240
- function callCallbacks(sender, err, cb) {
2241
- if (typeof cb === 'function') cb(err);
2242
-
2243
- for (let i = 0; i < sender._queue.length; i++) {
2244
- const params = sender._queue[i];
2245
- const callback = params[params.length - 1];
2246
-
2247
- if (typeof callback === 'function') callback(err);
2248
- }
2249
- }
2250
-
2251
- /**
2252
- * Handles a `Sender` error.
2253
- *
2254
- * @param {Sender} sender The `Sender` instance
2255
- * @param {Error} err The error
2256
- * @param {Function} [cb] The first pending callback
2257
- * @private
2258
- */
2259
- function onError(sender, err, cb) {
2260
- callCallbacks(sender, err, cb);
2261
- sender.onerror(err);
2262
- }
2263
- return sender;
2264
- }
2265
-
2266
- var eventTarget;
2267
- var hasRequiredEventTarget;
2268
-
2269
- function requireEventTarget () {
2270
- if (hasRequiredEventTarget) return eventTarget;
2271
- hasRequiredEventTarget = 1;
2272
-
2273
- const { kForOnEventAttribute, kListener } = requireConstants();
2274
-
2275
- const kCode = Symbol('kCode');
2276
- const kData = Symbol('kData');
2277
- const kError = Symbol('kError');
2278
- const kMessage = Symbol('kMessage');
2279
- const kReason = Symbol('kReason');
2280
- const kTarget = Symbol('kTarget');
2281
- const kType = Symbol('kType');
2282
- const kWasClean = Symbol('kWasClean');
2283
-
2284
- /**
2285
- * Class representing an event.
2286
- */
2287
- class Event {
2288
- /**
2289
- * Create a new `Event`.
2290
- *
2291
- * @param {String} type The name of the event
2292
- * @throws {TypeError} If the `type` argument is not specified
2293
- */
2294
- constructor(type) {
2295
- this[kTarget] = null;
2296
- this[kType] = type;
2297
- }
2298
-
2299
- /**
2300
- * @type {*}
2301
- */
2302
- get target() {
2303
- return this[kTarget];
2304
- }
2305
-
2306
- /**
2307
- * @type {String}
2308
- */
2309
- get type() {
2310
- return this[kType];
2311
- }
2312
- }
2313
-
2314
- Object.defineProperty(Event.prototype, 'target', { enumerable: true });
2315
- Object.defineProperty(Event.prototype, 'type', { enumerable: true });
2316
-
2317
- /**
2318
- * Class representing a close event.
2319
- *
2320
- * @extends Event
2321
- */
2322
- class CloseEvent extends Event {
2323
- /**
2324
- * Create a new `CloseEvent`.
2325
- *
2326
- * @param {String} type The name of the event
2327
- * @param {Object} [options] A dictionary object that allows for setting
2328
- * attributes via object members of the same name
2329
- * @param {Number} [options.code=0] The status code explaining why the
2330
- * connection was closed
2331
- * @param {String} [options.reason=''] A human-readable string explaining why
2332
- * the connection was closed
2333
- * @param {Boolean} [options.wasClean=false] Indicates whether or not the
2334
- * connection was cleanly closed
2335
- */
2336
- constructor(type, options = {}) {
2337
- super(type);
2338
-
2339
- this[kCode] = options.code === undefined ? 0 : options.code;
2340
- this[kReason] = options.reason === undefined ? '' : options.reason;
2341
- this[kWasClean] = options.wasClean === undefined ? false : options.wasClean;
2342
- }
2343
-
2344
- /**
2345
- * @type {Number}
2346
- */
2347
- get code() {
2348
- return this[kCode];
2349
- }
2350
-
2351
- /**
2352
- * @type {String}
2353
- */
2354
- get reason() {
2355
- return this[kReason];
2356
- }
2357
-
2358
- /**
2359
- * @type {Boolean}
2360
- */
2361
- get wasClean() {
2362
- return this[kWasClean];
2363
- }
2364
- }
2365
-
2366
- Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true });
2367
- Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true });
2368
- Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true });
2369
-
2370
- /**
2371
- * Class representing an error event.
2372
- *
2373
- * @extends Event
2374
- */
2375
- class ErrorEvent extends Event {
2376
- /**
2377
- * Create a new `ErrorEvent`.
2378
- *
2379
- * @param {String} type The name of the event
2380
- * @param {Object} [options] A dictionary object that allows for setting
2381
- * attributes via object members of the same name
2382
- * @param {*} [options.error=null] The error that generated this event
2383
- * @param {String} [options.message=''] The error message
2384
- */
2385
- constructor(type, options = {}) {
2386
- super(type);
2387
-
2388
- this[kError] = options.error === undefined ? null : options.error;
2389
- this[kMessage] = options.message === undefined ? '' : options.message;
2390
- }
2391
-
2392
- /**
2393
- * @type {*}
2394
- */
2395
- get error() {
2396
- return this[kError];
2397
- }
2398
-
2399
- /**
2400
- * @type {String}
2401
- */
2402
- get message() {
2403
- return this[kMessage];
2404
- }
2405
- }
2406
-
2407
- Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true });
2408
- Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true });
2409
-
2410
- /**
2411
- * Class representing a message event.
2412
- *
2413
- * @extends Event
2414
- */
2415
- class MessageEvent extends Event {
2416
- /**
2417
- * Create a new `MessageEvent`.
2418
- *
2419
- * @param {String} type The name of the event
2420
- * @param {Object} [options] A dictionary object that allows for setting
2421
- * attributes via object members of the same name
2422
- * @param {*} [options.data=null] The message content
2423
- */
2424
- constructor(type, options = {}) {
2425
- super(type);
2426
-
2427
- this[kData] = options.data === undefined ? null : options.data;
2428
- }
2429
-
2430
- /**
2431
- * @type {*}
2432
- */
2433
- get data() {
2434
- return this[kData];
2435
- }
2436
- }
2437
-
2438
- Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true });
2439
-
2440
- /**
2441
- * This provides methods for emulating the `EventTarget` interface. It's not
2442
- * meant to be used directly.
2443
- *
2444
- * @mixin
2445
- */
2446
- const EventTarget = {
2447
- /**
2448
- * Register an event listener.
2449
- *
2450
- * @param {String} type A string representing the event type to listen for
2451
- * @param {(Function|Object)} handler The listener to add
2452
- * @param {Object} [options] An options object specifies characteristics about
2453
- * the event listener
2454
- * @param {Boolean} [options.once=false] A `Boolean` indicating that the
2455
- * listener should be invoked at most once after being added. If `true`,
2456
- * the listener would be automatically removed when invoked.
2457
- * @public
2458
- */
2459
- addEventListener(type, handler, options = {}) {
2460
- for (const listener of this.listeners(type)) {
2461
- if (
2462
- !options[kForOnEventAttribute] &&
2463
- listener[kListener] === handler &&
2464
- !listener[kForOnEventAttribute]
2465
- ) {
2466
- return;
2467
- }
2468
- }
2469
-
2470
- let wrapper;
2471
-
2472
- if (type === 'message') {
2473
- wrapper = function onMessage(data, isBinary) {
2474
- const event = new MessageEvent('message', {
2475
- data: isBinary ? data : data.toString()
2476
- });
2477
-
2478
- event[kTarget] = this;
2479
- callListener(handler, this, event);
2480
- };
2481
- } else if (type === 'close') {
2482
- wrapper = function onClose(code, message) {
2483
- const event = new CloseEvent('close', {
2484
- code,
2485
- reason: message.toString(),
2486
- wasClean: this._closeFrameReceived && this._closeFrameSent
2487
- });
2488
-
2489
- event[kTarget] = this;
2490
- callListener(handler, this, event);
2491
- };
2492
- } else if (type === 'error') {
2493
- wrapper = function onError(error) {
2494
- const event = new ErrorEvent('error', {
2495
- error,
2496
- message: error.message
2497
- });
2498
-
2499
- event[kTarget] = this;
2500
- callListener(handler, this, event);
2501
- };
2502
- } else if (type === 'open') {
2503
- wrapper = function onOpen() {
2504
- const event = new Event('open');
2505
-
2506
- event[kTarget] = this;
2507
- callListener(handler, this, event);
2508
- };
2509
- } else {
2510
- return;
2511
- }
2512
-
2513
- wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute];
2514
- wrapper[kListener] = handler;
2515
-
2516
- if (options.once) {
2517
- this.once(type, wrapper);
2518
- } else {
2519
- this.on(type, wrapper);
2520
- }
2521
- },
2522
-
2523
- /**
2524
- * Remove an event listener.
2525
- *
2526
- * @param {String} type A string representing the event type to remove
2527
- * @param {(Function|Object)} handler The listener to remove
2528
- * @public
2529
- */
2530
- removeEventListener(type, handler) {
2531
- for (const listener of this.listeners(type)) {
2532
- if (listener[kListener] === handler && !listener[kForOnEventAttribute]) {
2533
- this.removeListener(type, listener);
2534
- break;
2535
- }
2536
- }
2537
- }
2538
- };
2539
-
2540
- eventTarget = {
2541
- CloseEvent,
2542
- ErrorEvent,
2543
- Event,
2544
- EventTarget,
2545
- MessageEvent
2546
- };
2547
-
2548
- /**
2549
- * Call an event listener
2550
- *
2551
- * @param {(Function|Object)} listener The listener to call
2552
- * @param {*} thisArg The value to use as `this`` when calling the listener
2553
- * @param {Event} event The event to pass to the listener
2554
- * @private
2555
- */
2556
- function callListener(listener, thisArg, event) {
2557
- if (typeof listener === 'object' && listener.handleEvent) {
2558
- listener.handleEvent.call(listener, event);
2559
- } else {
2560
- listener.call(thisArg, event);
2561
- }
2562
- }
2563
- return eventTarget;
2564
- }
2565
-
2566
- var extension;
2567
- var hasRequiredExtension;
2568
-
2569
- function requireExtension () {
2570
- if (hasRequiredExtension) return extension;
2571
- hasRequiredExtension = 1;
2572
-
2573
- const { tokenChars } = requireValidation();
2574
-
2575
- /**
2576
- * Adds an offer to the map of extension offers or a parameter to the map of
2577
- * parameters.
2578
- *
2579
- * @param {Object} dest The map of extension offers or parameters
2580
- * @param {String} name The extension or parameter name
2581
- * @param {(Object|Boolean|String)} elem The extension parameters or the
2582
- * parameter value
2583
- * @private
2584
- */
2585
- function push(dest, name, elem) {
2586
- if (dest[name] === undefined) dest[name] = [elem];
2587
- else dest[name].push(elem);
2588
- }
2589
-
2590
- /**
2591
- * Parses the `Sec-WebSocket-Extensions` header into an object.
2592
- *
2593
- * @param {String} header The field value of the header
2594
- * @return {Object} The parsed object
2595
- * @public
2596
- */
2597
- function parse(header) {
2598
- const offers = Object.create(null);
2599
- let params = Object.create(null);
2600
- let mustUnescape = false;
2601
- let isEscaping = false;
2602
- let inQuotes = false;
2603
- let extensionName;
2604
- let paramName;
2605
- let start = -1;
2606
- let code = -1;
2607
- let end = -1;
2608
- let i = 0;
2609
-
2610
- for (; i < header.length; i++) {
2611
- code = header.charCodeAt(i);
2612
-
2613
- if (extensionName === undefined) {
2614
- if (end === -1 && tokenChars[code] === 1) {
2615
- if (start === -1) start = i;
2616
- } else if (
2617
- i !== 0 &&
2618
- (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
2619
- ) {
2620
- if (end === -1 && start !== -1) end = i;
2621
- } else if (code === 0x3b /* ';' */ || code === 0x2c /* ',' */) {
2622
- if (start === -1) {
2623
- throw new SyntaxError(`Unexpected character at index ${i}`);
2624
- }
2625
-
2626
- if (end === -1) end = i;
2627
- const name = header.slice(start, end);
2628
- if (code === 0x2c) {
2629
- push(offers, name, params);
2630
- params = Object.create(null);
2631
- } else {
2632
- extensionName = name;
2633
- }
2634
-
2635
- start = end = -1;
2636
- } else {
2637
- throw new SyntaxError(`Unexpected character at index ${i}`);
2638
- }
2639
- } else if (paramName === undefined) {
2640
- if (end === -1 && tokenChars[code] === 1) {
2641
- if (start === -1) start = i;
2642
- } else if (code === 0x20 || code === 0x09) {
2643
- if (end === -1 && start !== -1) end = i;
2644
- } else if (code === 0x3b || code === 0x2c) {
2645
- if (start === -1) {
2646
- throw new SyntaxError(`Unexpected character at index ${i}`);
2647
- }
2648
-
2649
- if (end === -1) end = i;
2650
- push(params, header.slice(start, end), true);
2651
- if (code === 0x2c) {
2652
- push(offers, extensionName, params);
2653
- params = Object.create(null);
2654
- extensionName = undefined;
2655
- }
2656
-
2657
- start = end = -1;
2658
- } else if (code === 0x3d /* '=' */ && start !== -1 && end === -1) {
2659
- paramName = header.slice(start, i);
2660
- start = end = -1;
2661
- } else {
2662
- throw new SyntaxError(`Unexpected character at index ${i}`);
2663
- }
2664
- } else {
2665
- //
2666
- // The value of a quoted-string after unescaping must conform to the
2667
- // token ABNF, so only token characters are valid.
2668
- // Ref: https://tools.ietf.org/html/rfc6455#section-9.1
2669
- //
2670
- if (isEscaping) {
2671
- if (tokenChars[code] !== 1) {
2672
- throw new SyntaxError(`Unexpected character at index ${i}`);
2673
- }
2674
- if (start === -1) start = i;
2675
- else if (!mustUnescape) mustUnescape = true;
2676
- isEscaping = false;
2677
- } else if (inQuotes) {
2678
- if (tokenChars[code] === 1) {
2679
- if (start === -1) start = i;
2680
- } else if (code === 0x22 /* '"' */ && start !== -1) {
2681
- inQuotes = false;
2682
- end = i;
2683
- } else if (code === 0x5c /* '\' */) {
2684
- isEscaping = true;
2685
- } else {
2686
- throw new SyntaxError(`Unexpected character at index ${i}`);
2687
- }
2688
- } else if (code === 0x22 && header.charCodeAt(i - 1) === 0x3d) {
2689
- inQuotes = true;
2690
- } else if (end === -1 && tokenChars[code] === 1) {
2691
- if (start === -1) start = i;
2692
- } else if (start !== -1 && (code === 0x20 || code === 0x09)) {
2693
- if (end === -1) end = i;
2694
- } else if (code === 0x3b || code === 0x2c) {
2695
- if (start === -1) {
2696
- throw new SyntaxError(`Unexpected character at index ${i}`);
2697
- }
2698
-
2699
- if (end === -1) end = i;
2700
- let value = header.slice(start, end);
2701
- if (mustUnescape) {
2702
- value = value.replace(/\\/g, '');
2703
- mustUnescape = false;
2704
- }
2705
- push(params, paramName, value);
2706
- if (code === 0x2c) {
2707
- push(offers, extensionName, params);
2708
- params = Object.create(null);
2709
- extensionName = undefined;
2710
- }
2711
-
2712
- paramName = undefined;
2713
- start = end = -1;
2714
- } else {
2715
- throw new SyntaxError(`Unexpected character at index ${i}`);
2716
- }
2717
- }
2718
- }
2719
-
2720
- if (start === -1 || inQuotes || code === 0x20 || code === 0x09) {
2721
- throw new SyntaxError('Unexpected end of input');
2722
- }
2723
-
2724
- if (end === -1) end = i;
2725
- const token = header.slice(start, end);
2726
- if (extensionName === undefined) {
2727
- push(offers, token, params);
2728
- } else {
2729
- if (paramName === undefined) {
2730
- push(params, token, true);
2731
- } else if (mustUnescape) {
2732
- push(params, paramName, token.replace(/\\/g, ''));
2733
- } else {
2734
- push(params, paramName, token);
2735
- }
2736
- push(offers, extensionName, params);
2737
- }
2738
-
2739
- return offers;
2740
- }
2741
-
2742
- /**
2743
- * Builds the `Sec-WebSocket-Extensions` header field value.
2744
- *
2745
- * @param {Object} extensions The map of extensions and parameters to format
2746
- * @return {String} A string representing the given object
2747
- * @public
2748
- */
2749
- function format(extensions) {
2750
- return Object.keys(extensions)
2751
- .map((extension) => {
2752
- let configurations = extensions[extension];
2753
- if (!Array.isArray(configurations)) configurations = [configurations];
2754
- return configurations
2755
- .map((params) => {
2756
- return [extension]
2757
- .concat(
2758
- Object.keys(params).map((k) => {
2759
- let values = params[k];
2760
- if (!Array.isArray(values)) values = [values];
2761
- return values
2762
- .map((v) => (v === true ? k : `${k}=${v}`))
2763
- .join('; ');
2764
- })
2765
- )
2766
- .join('; ');
2767
- })
2768
- .join(', ');
2769
- })
2770
- .join(', ');
2771
- }
2772
-
2773
- extension = { format, parse };
2774
- return extension;
2775
- }
2776
-
2777
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex|Readable$", "caughtErrors": "none" }] */
2778
-
2779
- var websocket;
2780
- var hasRequiredWebsocket;
2781
-
2782
- function requireWebsocket () {
2783
- if (hasRequiredWebsocket) return websocket;
2784
- hasRequiredWebsocket = 1;
2785
-
2786
- const EventEmitter = require$$0$3;
2787
- const https = require$$1$1;
2788
- const http = require$$2;
2789
- const net = require$$3;
2790
- const tls = require$$4;
2791
- const { randomBytes, createHash } = require$$1;
2792
- const { Duplex, Readable } = require$$0$2;
2793
- const { URL } = require$$7;
2794
-
2795
- const PerMessageDeflate = requirePermessageDeflate();
2796
- const Receiver = requireReceiver();
2797
- const Sender = requireSender();
2798
- const { isBlob } = requireValidation();
2799
-
2800
- const {
2801
- BINARY_TYPES,
2802
- EMPTY_BUFFER,
2803
- GUID,
2804
- kForOnEventAttribute,
2805
- kListener,
2806
- kStatusCode,
2807
- kWebSocket,
2808
- NOOP
2809
- } = requireConstants();
2810
- const {
2811
- EventTarget: { addEventListener, removeEventListener }
2812
- } = requireEventTarget();
2813
- const { format, parse } = requireExtension();
2814
- const { toBuffer } = requireBufferUtil();
2815
-
2816
- const closeTimeout = 30 * 1000;
2817
- const kAborted = Symbol('kAborted');
2818
- const protocolVersions = [8, 13];
2819
- const readyStates = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'];
2820
- const subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
2821
-
2822
- /**
2823
- * Class representing a WebSocket.
2824
- *
2825
- * @extends EventEmitter
2826
- */
2827
- class WebSocket extends EventEmitter {
2828
- /**
2829
- * Create a new `WebSocket`.
2830
- *
2831
- * @param {(String|URL)} address The URL to which to connect
2832
- * @param {(String|String[])} [protocols] The subprotocols
2833
- * @param {Object} [options] Connection options
2834
- */
2835
- constructor(address, protocols, options) {
2836
- super();
2837
-
2838
- this._binaryType = BINARY_TYPES[0];
2839
- this._closeCode = 1006;
2840
- this._closeFrameReceived = false;
2841
- this._closeFrameSent = false;
2842
- this._closeMessage = EMPTY_BUFFER;
2843
- this._closeTimer = null;
2844
- this._errorEmitted = false;
2845
- this._extensions = {};
2846
- this._paused = false;
2847
- this._protocol = '';
2848
- this._readyState = WebSocket.CONNECTING;
2849
- this._receiver = null;
2850
- this._sender = null;
2851
- this._socket = null;
2852
-
2853
- if (address !== null) {
2854
- this._bufferedAmount = 0;
2855
- this._isServer = false;
2856
- this._redirects = 0;
2857
-
2858
- if (protocols === undefined) {
2859
- protocols = [];
2860
- } else if (!Array.isArray(protocols)) {
2861
- if (typeof protocols === 'object' && protocols !== null) {
2862
- options = protocols;
2863
- protocols = [];
2864
- } else {
2865
- protocols = [protocols];
2866
- }
2867
- }
2868
-
2869
- initAsClient(this, address, protocols, options);
2870
- } else {
2871
- this._autoPong = options.autoPong;
2872
- this._isServer = true;
2873
- }
2874
- }
2875
-
2876
- /**
2877
- * For historical reasons, the custom "nodebuffer" type is used by the default
2878
- * instead of "blob".
2879
- *
2880
- * @type {String}
2881
- */
2882
- get binaryType() {
2883
- return this._binaryType;
2884
- }
2885
-
2886
- set binaryType(type) {
2887
- if (!BINARY_TYPES.includes(type)) return;
2888
-
2889
- this._binaryType = type;
2890
-
2891
- //
2892
- // Allow to change `binaryType` on the fly.
2893
- //
2894
- if (this._receiver) this._receiver._binaryType = type;
2895
- }
2896
-
2897
- /**
2898
- * @type {Number}
2899
- */
2900
- get bufferedAmount() {
2901
- if (!this._socket) return this._bufferedAmount;
2902
-
2903
- return this._socket._writableState.length + this._sender._bufferedBytes;
2904
- }
2905
-
2906
- /**
2907
- * @type {String}
2908
- */
2909
- get extensions() {
2910
- return Object.keys(this._extensions).join();
2911
- }
2912
-
2913
- /**
2914
- * @type {Boolean}
2915
- */
2916
- get isPaused() {
2917
- return this._paused;
2918
- }
2919
-
2920
- /**
2921
- * @type {Function}
2922
- */
2923
- /* istanbul ignore next */
2924
- get onclose() {
2925
- return null;
2926
- }
2927
-
2928
- /**
2929
- * @type {Function}
2930
- */
2931
- /* istanbul ignore next */
2932
- get onerror() {
2933
- return null;
2934
- }
2935
-
2936
- /**
2937
- * @type {Function}
2938
- */
2939
- /* istanbul ignore next */
2940
- get onopen() {
2941
- return null;
2942
- }
2943
-
2944
- /**
2945
- * @type {Function}
2946
- */
2947
- /* istanbul ignore next */
2948
- get onmessage() {
2949
- return null;
2950
- }
2951
-
2952
- /**
2953
- * @type {String}
2954
- */
2955
- get protocol() {
2956
- return this._protocol;
2957
- }
2958
-
2959
- /**
2960
- * @type {Number}
2961
- */
2962
- get readyState() {
2963
- return this._readyState;
2964
- }
2965
-
2966
- /**
2967
- * @type {String}
2968
- */
2969
- get url() {
2970
- return this._url;
2971
- }
2972
-
2973
- /**
2974
- * Set up the socket and the internal resources.
2975
- *
2976
- * @param {Duplex} socket The network socket between the server and client
2977
- * @param {Buffer} head The first packet of the upgraded stream
2978
- * @param {Object} options Options object
2979
- * @param {Boolean} [options.allowSynchronousEvents=false] Specifies whether
2980
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
2981
- * multiple times in the same tick
2982
- * @param {Function} [options.generateMask] The function used to generate the
2983
- * masking key
2984
- * @param {Number} [options.maxPayload=0] The maximum allowed message size
2985
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
2986
- * not to skip UTF-8 validation for text and close messages
2987
- * @private
2988
- */
2989
- setSocket(socket, head, options) {
2990
- const receiver = new Receiver({
2991
- allowSynchronousEvents: options.allowSynchronousEvents,
2992
- binaryType: this.binaryType,
2993
- extensions: this._extensions,
2994
- isServer: this._isServer,
2995
- maxPayload: options.maxPayload,
2996
- skipUTF8Validation: options.skipUTF8Validation
2997
- });
2998
-
2999
- const sender = new Sender(socket, this._extensions, options.generateMask);
3000
-
3001
- this._receiver = receiver;
3002
- this._sender = sender;
3003
- this._socket = socket;
3004
-
3005
- receiver[kWebSocket] = this;
3006
- sender[kWebSocket] = this;
3007
- socket[kWebSocket] = this;
3008
-
3009
- receiver.on('conclude', receiverOnConclude);
3010
- receiver.on('drain', receiverOnDrain);
3011
- receiver.on('error', receiverOnError);
3012
- receiver.on('message', receiverOnMessage);
3013
- receiver.on('ping', receiverOnPing);
3014
- receiver.on('pong', receiverOnPong);
3015
-
3016
- sender.onerror = senderOnError;
3017
-
3018
- //
3019
- // These methods may not be available if `socket` is just a `Duplex`.
3020
- //
3021
- if (socket.setTimeout) socket.setTimeout(0);
3022
- if (socket.setNoDelay) socket.setNoDelay();
3023
-
3024
- if (head.length > 0) socket.unshift(head);
3025
-
3026
- socket.on('close', socketOnClose);
3027
- socket.on('data', socketOnData);
3028
- socket.on('end', socketOnEnd);
3029
- socket.on('error', socketOnError);
3030
-
3031
- this._readyState = WebSocket.OPEN;
3032
- this.emit('open');
3033
- }
3034
-
3035
- /**
3036
- * Emit the `'close'` event.
3037
- *
3038
- * @private
3039
- */
3040
- emitClose() {
3041
- if (!this._socket) {
3042
- this._readyState = WebSocket.CLOSED;
3043
- this.emit('close', this._closeCode, this._closeMessage);
3044
- return;
3045
- }
3046
-
3047
- if (this._extensions[PerMessageDeflate.extensionName]) {
3048
- this._extensions[PerMessageDeflate.extensionName].cleanup();
3049
- }
3050
-
3051
- this._receiver.removeAllListeners();
3052
- this._readyState = WebSocket.CLOSED;
3053
- this.emit('close', this._closeCode, this._closeMessage);
3054
- }
3055
-
3056
- /**
3057
- * Start a closing handshake.
3058
- *
3059
- * +----------+ +-----------+ +----------+
3060
- * - - -|ws.close()|-->|close frame|-->|ws.close()|- - -
3061
- * | +----------+ +-----------+ +----------+ |
3062
- * +----------+ +-----------+ |
3063
- * CLOSING |ws.close()|<--|close frame|<--+-----+ CLOSING
3064
- * +----------+ +-----------+ |
3065
- * | | | +---+ |
3066
- * +------------------------+-->|fin| - - - -
3067
- * | +---+ | +---+
3068
- * - - - - -|fin|<---------------------+
3069
- * +---+
3070
- *
3071
- * @param {Number} [code] Status code explaining why the connection is closing
3072
- * @param {(String|Buffer)} [data] The reason why the connection is
3073
- * closing
3074
- * @public
3075
- */
3076
- close(code, data) {
3077
- if (this.readyState === WebSocket.CLOSED) return;
3078
- if (this.readyState === WebSocket.CONNECTING) {
3079
- const msg = 'WebSocket was closed before the connection was established';
3080
- abortHandshake(this, this._req, msg);
3081
- return;
3082
- }
3083
-
3084
- if (this.readyState === WebSocket.CLOSING) {
3085
- if (
3086
- this._closeFrameSent &&
3087
- (this._closeFrameReceived || this._receiver._writableState.errorEmitted)
3088
- ) {
3089
- this._socket.end();
3090
- }
3091
-
3092
- return;
3093
- }
3094
-
3095
- this._readyState = WebSocket.CLOSING;
3096
- this._sender.close(code, data, !this._isServer, (err) => {
3097
- //
3098
- // This error is handled by the `'error'` listener on the socket. We only
3099
- // want to know if the close frame has been sent here.
3100
- //
3101
- if (err) return;
3102
-
3103
- this._closeFrameSent = true;
3104
-
3105
- if (
3106
- this._closeFrameReceived ||
3107
- this._receiver._writableState.errorEmitted
3108
- ) {
3109
- this._socket.end();
3110
- }
3111
- });
3112
-
3113
- setCloseTimer(this);
3114
- }
3115
-
3116
- /**
3117
- * Pause the socket.
3118
- *
3119
- * @public
3120
- */
3121
- pause() {
3122
- if (
3123
- this.readyState === WebSocket.CONNECTING ||
3124
- this.readyState === WebSocket.CLOSED
3125
- ) {
3126
- return;
3127
- }
3128
-
3129
- this._paused = true;
3130
- this._socket.pause();
3131
- }
3132
-
3133
- /**
3134
- * Send a ping.
3135
- *
3136
- * @param {*} [data] The data to send
3137
- * @param {Boolean} [mask] Indicates whether or not to mask `data`
3138
- * @param {Function} [cb] Callback which is executed when the ping is sent
3139
- * @public
3140
- */
3141
- ping(data, mask, cb) {
3142
- if (this.readyState === WebSocket.CONNECTING) {
3143
- throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
3144
- }
3145
-
3146
- if (typeof data === 'function') {
3147
- cb = data;
3148
- data = mask = undefined;
3149
- } else if (typeof mask === 'function') {
3150
- cb = mask;
3151
- mask = undefined;
3152
- }
3153
-
3154
- if (typeof data === 'number') data = data.toString();
3155
-
3156
- if (this.readyState !== WebSocket.OPEN) {
3157
- sendAfterClose(this, data, cb);
3158
- return;
3159
- }
3160
-
3161
- if (mask === undefined) mask = !this._isServer;
3162
- this._sender.ping(data || EMPTY_BUFFER, mask, cb);
3163
- }
3164
-
3165
- /**
3166
- * Send a pong.
3167
- *
3168
- * @param {*} [data] The data to send
3169
- * @param {Boolean} [mask] Indicates whether or not to mask `data`
3170
- * @param {Function} [cb] Callback which is executed when the pong is sent
3171
- * @public
3172
- */
3173
- pong(data, mask, cb) {
3174
- if (this.readyState === WebSocket.CONNECTING) {
3175
- throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
3176
- }
3177
-
3178
- if (typeof data === 'function') {
3179
- cb = data;
3180
- data = mask = undefined;
3181
- } else if (typeof mask === 'function') {
3182
- cb = mask;
3183
- mask = undefined;
3184
- }
3185
-
3186
- if (typeof data === 'number') data = data.toString();
3187
-
3188
- if (this.readyState !== WebSocket.OPEN) {
3189
- sendAfterClose(this, data, cb);
3190
- return;
3191
- }
3192
-
3193
- if (mask === undefined) mask = !this._isServer;
3194
- this._sender.pong(data || EMPTY_BUFFER, mask, cb);
3195
- }
3196
-
3197
- /**
3198
- * Resume the socket.
3199
- *
3200
- * @public
3201
- */
3202
- resume() {
3203
- if (
3204
- this.readyState === WebSocket.CONNECTING ||
3205
- this.readyState === WebSocket.CLOSED
3206
- ) {
3207
- return;
3208
- }
3209
-
3210
- this._paused = false;
3211
- if (!this._receiver._writableState.needDrain) this._socket.resume();
3212
- }
3213
-
3214
- /**
3215
- * Send a data message.
3216
- *
3217
- * @param {*} data The message to send
3218
- * @param {Object} [options] Options object
3219
- * @param {Boolean} [options.binary] Specifies whether `data` is binary or
3220
- * text
3221
- * @param {Boolean} [options.compress] Specifies whether or not to compress
3222
- * `data`
3223
- * @param {Boolean} [options.fin=true] Specifies whether the fragment is the
3224
- * last one
3225
- * @param {Boolean} [options.mask] Specifies whether or not to mask `data`
3226
- * @param {Function} [cb] Callback which is executed when data is written out
3227
- * @public
3228
- */
3229
- send(data, options, cb) {
3230
- if (this.readyState === WebSocket.CONNECTING) {
3231
- throw new Error('WebSocket is not open: readyState 0 (CONNECTING)');
3232
- }
3233
-
3234
- if (typeof options === 'function') {
3235
- cb = options;
3236
- options = {};
3237
- }
3238
-
3239
- if (typeof data === 'number') data = data.toString();
3240
-
3241
- if (this.readyState !== WebSocket.OPEN) {
3242
- sendAfterClose(this, data, cb);
3243
- return;
3244
- }
3245
-
3246
- const opts = {
3247
- binary: typeof data !== 'string',
3248
- mask: !this._isServer,
3249
- compress: true,
3250
- fin: true,
3251
- ...options
3252
- };
3253
-
3254
- if (!this._extensions[PerMessageDeflate.extensionName]) {
3255
- opts.compress = false;
3256
- }
3257
-
3258
- this._sender.send(data || EMPTY_BUFFER, opts, cb);
3259
- }
3260
-
3261
- /**
3262
- * Forcibly close the connection.
3263
- *
3264
- * @public
3265
- */
3266
- terminate() {
3267
- if (this.readyState === WebSocket.CLOSED) return;
3268
- if (this.readyState === WebSocket.CONNECTING) {
3269
- const msg = 'WebSocket was closed before the connection was established';
3270
- abortHandshake(this, this._req, msg);
3271
- return;
3272
- }
3273
-
3274
- if (this._socket) {
3275
- this._readyState = WebSocket.CLOSING;
3276
- this._socket.destroy();
3277
- }
3278
- }
3279
- }
3280
-
3281
- /**
3282
- * @constant {Number} CONNECTING
3283
- * @memberof WebSocket
3284
- */
3285
- Object.defineProperty(WebSocket, 'CONNECTING', {
3286
- enumerable: true,
3287
- value: readyStates.indexOf('CONNECTING')
3288
- });
3289
-
3290
- /**
3291
- * @constant {Number} CONNECTING
3292
- * @memberof WebSocket.prototype
3293
- */
3294
- Object.defineProperty(WebSocket.prototype, 'CONNECTING', {
3295
- enumerable: true,
3296
- value: readyStates.indexOf('CONNECTING')
3297
- });
3298
-
3299
- /**
3300
- * @constant {Number} OPEN
3301
- * @memberof WebSocket
3302
- */
3303
- Object.defineProperty(WebSocket, 'OPEN', {
3304
- enumerable: true,
3305
- value: readyStates.indexOf('OPEN')
3306
- });
3307
-
3308
- /**
3309
- * @constant {Number} OPEN
3310
- * @memberof WebSocket.prototype
3311
- */
3312
- Object.defineProperty(WebSocket.prototype, 'OPEN', {
3313
- enumerable: true,
3314
- value: readyStates.indexOf('OPEN')
3315
- });
3316
-
3317
- /**
3318
- * @constant {Number} CLOSING
3319
- * @memberof WebSocket
3320
- */
3321
- Object.defineProperty(WebSocket, 'CLOSING', {
3322
- enumerable: true,
3323
- value: readyStates.indexOf('CLOSING')
3324
- });
3325
-
3326
- /**
3327
- * @constant {Number} CLOSING
3328
- * @memberof WebSocket.prototype
3329
- */
3330
- Object.defineProperty(WebSocket.prototype, 'CLOSING', {
3331
- enumerable: true,
3332
- value: readyStates.indexOf('CLOSING')
3333
- });
3334
-
3335
- /**
3336
- * @constant {Number} CLOSED
3337
- * @memberof WebSocket
3338
- */
3339
- Object.defineProperty(WebSocket, 'CLOSED', {
3340
- enumerable: true,
3341
- value: readyStates.indexOf('CLOSED')
3342
- });
3343
-
3344
- /**
3345
- * @constant {Number} CLOSED
3346
- * @memberof WebSocket.prototype
3347
- */
3348
- Object.defineProperty(WebSocket.prototype, 'CLOSED', {
3349
- enumerable: true,
3350
- value: readyStates.indexOf('CLOSED')
3351
- });
3352
-
3353
- [
3354
- 'binaryType',
3355
- 'bufferedAmount',
3356
- 'extensions',
3357
- 'isPaused',
3358
- 'protocol',
3359
- 'readyState',
3360
- 'url'
3361
- ].forEach((property) => {
3362
- Object.defineProperty(WebSocket.prototype, property, { enumerable: true });
3363
- });
3364
-
3365
- //
3366
- // Add the `onopen`, `onerror`, `onclose`, and `onmessage` attributes.
3367
- // See https://html.spec.whatwg.org/multipage/comms.html#the-websocket-interface
3368
- //
3369
- ['open', 'error', 'close', 'message'].forEach((method) => {
3370
- Object.defineProperty(WebSocket.prototype, `on${method}`, {
3371
- enumerable: true,
3372
- get() {
3373
- for (const listener of this.listeners(method)) {
3374
- if (listener[kForOnEventAttribute]) return listener[kListener];
3375
- }
3376
-
3377
- return null;
3378
- },
3379
- set(handler) {
3380
- for (const listener of this.listeners(method)) {
3381
- if (listener[kForOnEventAttribute]) {
3382
- this.removeListener(method, listener);
3383
- break;
3384
- }
3385
- }
3386
-
3387
- if (typeof handler !== 'function') return;
3388
-
3389
- this.addEventListener(method, handler, {
3390
- [kForOnEventAttribute]: true
3391
- });
3392
- }
3393
- });
3394
- });
3395
-
3396
- WebSocket.prototype.addEventListener = addEventListener;
3397
- WebSocket.prototype.removeEventListener = removeEventListener;
3398
-
3399
- websocket = WebSocket;
3400
-
3401
- /**
3402
- * Initialize a WebSocket client.
3403
- *
3404
- * @param {WebSocket} websocket The client to initialize
3405
- * @param {(String|URL)} address The URL to which to connect
3406
- * @param {Array} protocols The subprotocols
3407
- * @param {Object} [options] Connection options
3408
- * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether any
3409
- * of the `'message'`, `'ping'`, and `'pong'` events can be emitted multiple
3410
- * times in the same tick
3411
- * @param {Boolean} [options.autoPong=true] Specifies whether or not to
3412
- * automatically send a pong in response to a ping
3413
- * @param {Function} [options.finishRequest] A function which can be used to
3414
- * customize the headers of each http request before it is sent
3415
- * @param {Boolean} [options.followRedirects=false] Whether or not to follow
3416
- * redirects
3417
- * @param {Function} [options.generateMask] The function used to generate the
3418
- * masking key
3419
- * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
3420
- * handshake request
3421
- * @param {Number} [options.maxPayload=104857600] The maximum allowed message
3422
- * size
3423
- * @param {Number} [options.maxRedirects=10] The maximum number of redirects
3424
- * allowed
3425
- * @param {String} [options.origin] Value of the `Origin` or
3426
- * `Sec-WebSocket-Origin` header
3427
- * @param {(Boolean|Object)} [options.perMessageDeflate=true] Enable/disable
3428
- * permessage-deflate
3429
- * @param {Number} [options.protocolVersion=13] Value of the
3430
- * `Sec-WebSocket-Version` header
3431
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
3432
- * not to skip UTF-8 validation for text and close messages
3433
- * @private
3434
- */
3435
- function initAsClient(websocket, address, protocols, options) {
3436
- const opts = {
3437
- allowSynchronousEvents: true,
3438
- autoPong: true,
3439
- protocolVersion: protocolVersions[1],
3440
- maxPayload: 100 * 1024 * 1024,
3441
- skipUTF8Validation: false,
3442
- perMessageDeflate: true,
3443
- followRedirects: false,
3444
- maxRedirects: 10,
3445
- ...options,
3446
- socketPath: undefined,
3447
- hostname: undefined,
3448
- protocol: undefined,
3449
- timeout: undefined,
3450
- method: 'GET',
3451
- host: undefined,
3452
- path: undefined,
3453
- port: undefined
3454
- };
3455
-
3456
- websocket._autoPong = opts.autoPong;
3457
-
3458
- if (!protocolVersions.includes(opts.protocolVersion)) {
3459
- throw new RangeError(
3460
- `Unsupported protocol version: ${opts.protocolVersion} ` +
3461
- `(supported versions: ${protocolVersions.join(', ')})`
3462
- );
3463
- }
3464
-
3465
- let parsedUrl;
3466
-
3467
- if (address instanceof URL) {
3468
- parsedUrl = address;
3469
- } else {
3470
- try {
3471
- parsedUrl = new URL(address);
3472
- } catch (e) {
3473
- throw new SyntaxError(`Invalid URL: ${address}`);
3474
- }
3475
- }
3476
-
3477
- if (parsedUrl.protocol === 'http:') {
3478
- parsedUrl.protocol = 'ws:';
3479
- } else if (parsedUrl.protocol === 'https:') {
3480
- parsedUrl.protocol = 'wss:';
3481
- }
3482
-
3483
- websocket._url = parsedUrl.href;
3484
-
3485
- const isSecure = parsedUrl.protocol === 'wss:';
3486
- const isIpcUrl = parsedUrl.protocol === 'ws+unix:';
3487
- let invalidUrlMessage;
3488
-
3489
- if (parsedUrl.protocol !== 'ws:' && !isSecure && !isIpcUrl) {
3490
- invalidUrlMessage =
3491
- 'The URL\'s protocol must be one of "ws:", "wss:", ' +
3492
- '"http:", "https:", or "ws+unix:"';
3493
- } else if (isIpcUrl && !parsedUrl.pathname) {
3494
- invalidUrlMessage = "The URL's pathname is empty";
3495
- } else if (parsedUrl.hash) {
3496
- invalidUrlMessage = 'The URL contains a fragment identifier';
3497
- }
3498
-
3499
- if (invalidUrlMessage) {
3500
- const err = new SyntaxError(invalidUrlMessage);
3501
-
3502
- if (websocket._redirects === 0) {
3503
- throw err;
3504
- } else {
3505
- emitErrorAndClose(websocket, err);
3506
- return;
3507
- }
3508
- }
3509
-
3510
- const defaultPort = isSecure ? 443 : 80;
3511
- const key = randomBytes(16).toString('base64');
3512
- const request = isSecure ? https.request : http.request;
3513
- const protocolSet = new Set();
3514
- let perMessageDeflate;
3515
-
3516
- opts.createConnection =
3517
- opts.createConnection || (isSecure ? tlsConnect : netConnect);
3518
- opts.defaultPort = opts.defaultPort || defaultPort;
3519
- opts.port = parsedUrl.port || defaultPort;
3520
- opts.host = parsedUrl.hostname.startsWith('[')
3521
- ? parsedUrl.hostname.slice(1, -1)
3522
- : parsedUrl.hostname;
3523
- opts.headers = {
3524
- ...opts.headers,
3525
- 'Sec-WebSocket-Version': opts.protocolVersion,
3526
- 'Sec-WebSocket-Key': key,
3527
- Connection: 'Upgrade',
3528
- Upgrade: 'websocket'
3529
- };
3530
- opts.path = parsedUrl.pathname + parsedUrl.search;
3531
- opts.timeout = opts.handshakeTimeout;
3532
-
3533
- if (opts.perMessageDeflate) {
3534
- perMessageDeflate = new PerMessageDeflate(
3535
- opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
3536
- false,
3537
- opts.maxPayload
3538
- );
3539
- opts.headers['Sec-WebSocket-Extensions'] = format({
3540
- [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
3541
- });
3542
- }
3543
- if (protocols.length) {
3544
- for (const protocol of protocols) {
3545
- if (
3546
- typeof protocol !== 'string' ||
3547
- !subprotocolRegex.test(protocol) ||
3548
- protocolSet.has(protocol)
3549
- ) {
3550
- throw new SyntaxError(
3551
- 'An invalid or duplicated subprotocol was specified'
3552
- );
3553
- }
3554
-
3555
- protocolSet.add(protocol);
3556
- }
3557
-
3558
- opts.headers['Sec-WebSocket-Protocol'] = protocols.join(',');
3559
- }
3560
- if (opts.origin) {
3561
- if (opts.protocolVersion < 13) {
3562
- opts.headers['Sec-WebSocket-Origin'] = opts.origin;
3563
- } else {
3564
- opts.headers.Origin = opts.origin;
3565
- }
3566
- }
3567
- if (parsedUrl.username || parsedUrl.password) {
3568
- opts.auth = `${parsedUrl.username}:${parsedUrl.password}`;
3569
- }
3570
-
3571
- if (isIpcUrl) {
3572
- const parts = opts.path.split(':');
3573
-
3574
- opts.socketPath = parts[0];
3575
- opts.path = parts[1];
3576
- }
3577
-
3578
- let req;
3579
-
3580
- if (opts.followRedirects) {
3581
- if (websocket._redirects === 0) {
3582
- websocket._originalIpc = isIpcUrl;
3583
- websocket._originalSecure = isSecure;
3584
- websocket._originalHostOrSocketPath = isIpcUrl
3585
- ? opts.socketPath
3586
- : parsedUrl.host;
3587
-
3588
- const headers = options && options.headers;
3589
-
3590
- //
3591
- // Shallow copy the user provided options so that headers can be changed
3592
- // without mutating the original object.
3593
- //
3594
- options = { ...options, headers: {} };
3595
-
3596
- if (headers) {
3597
- for (const [key, value] of Object.entries(headers)) {
3598
- options.headers[key.toLowerCase()] = value;
3599
- }
3600
- }
3601
- } else if (websocket.listenerCount('redirect') === 0) {
3602
- const isSameHost = isIpcUrl
3603
- ? websocket._originalIpc
3604
- ? opts.socketPath === websocket._originalHostOrSocketPath
3605
- : false
3606
- : websocket._originalIpc
3607
- ? false
3608
- : parsedUrl.host === websocket._originalHostOrSocketPath;
3609
-
3610
- if (!isSameHost || (websocket._originalSecure && !isSecure)) {
3611
- //
3612
- // Match curl 7.77.0 behavior and drop the following headers. These
3613
- // headers are also dropped when following a redirect to a subdomain.
3614
- //
3615
- delete opts.headers.authorization;
3616
- delete opts.headers.cookie;
3617
-
3618
- if (!isSameHost) delete opts.headers.host;
3619
-
3620
- opts.auth = undefined;
3621
- }
3622
- }
3623
-
3624
- //
3625
- // Match curl 7.77.0 behavior and make the first `Authorization` header win.
3626
- // If the `Authorization` header is set, then there is nothing to do as it
3627
- // will take precedence.
3628
- //
3629
- if (opts.auth && !options.headers.authorization) {
3630
- options.headers.authorization =
3631
- 'Basic ' + Buffer.from(opts.auth).toString('base64');
3632
- }
3633
-
3634
- req = websocket._req = request(opts);
3635
-
3636
- if (websocket._redirects) {
3637
- //
3638
- // Unlike what is done for the `'upgrade'` event, no early exit is
3639
- // triggered here if the user calls `websocket.close()` or
3640
- // `websocket.terminate()` from a listener of the `'redirect'` event. This
3641
- // is because the user can also call `request.destroy()` with an error
3642
- // before calling `websocket.close()` or `websocket.terminate()` and this
3643
- // would result in an error being emitted on the `request` object with no
3644
- // `'error'` event listeners attached.
3645
- //
3646
- websocket.emit('redirect', websocket.url, req);
3647
- }
3648
- } else {
3649
- req = websocket._req = request(opts);
3650
- }
3651
-
3652
- if (opts.timeout) {
3653
- req.on('timeout', () => {
3654
- abortHandshake(websocket, req, 'Opening handshake has timed out');
3655
- });
3656
- }
3657
-
3658
- req.on('error', (err) => {
3659
- if (req === null || req[kAborted]) return;
3660
-
3661
- req = websocket._req = null;
3662
- emitErrorAndClose(websocket, err);
3663
- });
3664
-
3665
- req.on('response', (res) => {
3666
- const location = res.headers.location;
3667
- const statusCode = res.statusCode;
3668
-
3669
- if (
3670
- location &&
3671
- opts.followRedirects &&
3672
- statusCode >= 300 &&
3673
- statusCode < 400
3674
- ) {
3675
- if (++websocket._redirects > opts.maxRedirects) {
3676
- abortHandshake(websocket, req, 'Maximum redirects exceeded');
3677
- return;
3678
- }
3679
-
3680
- req.abort();
3681
-
3682
- let addr;
3683
-
3684
- try {
3685
- addr = new URL(location, address);
3686
- } catch (e) {
3687
- const err = new SyntaxError(`Invalid URL: ${location}`);
3688
- emitErrorAndClose(websocket, err);
3689
- return;
3690
- }
3691
-
3692
- initAsClient(websocket, addr, protocols, options);
3693
- } else if (!websocket.emit('unexpected-response', req, res)) {
3694
- abortHandshake(
3695
- websocket,
3696
- req,
3697
- `Unexpected server response: ${res.statusCode}`
3698
- );
3699
- }
3700
- });
3701
-
3702
- req.on('upgrade', (res, socket, head) => {
3703
- websocket.emit('upgrade', res);
3704
-
3705
- //
3706
- // The user may have closed the connection from a listener of the
3707
- // `'upgrade'` event.
3708
- //
3709
- if (websocket.readyState !== WebSocket.CONNECTING) return;
3710
-
3711
- req = websocket._req = null;
3712
-
3713
- const upgrade = res.headers.upgrade;
3714
-
3715
- if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
3716
- abortHandshake(websocket, socket, 'Invalid Upgrade header');
3717
- return;
3718
- }
3719
-
3720
- const digest = createHash('sha1')
3721
- .update(key + GUID)
3722
- .digest('base64');
3723
-
3724
- if (res.headers['sec-websocket-accept'] !== digest) {
3725
- abortHandshake(websocket, socket, 'Invalid Sec-WebSocket-Accept header');
3726
- return;
3727
- }
3728
-
3729
- const serverProt = res.headers['sec-websocket-protocol'];
3730
- let protError;
3731
-
3732
- if (serverProt !== undefined) {
3733
- if (!protocolSet.size) {
3734
- protError = 'Server sent a subprotocol but none was requested';
3735
- } else if (!protocolSet.has(serverProt)) {
3736
- protError = 'Server sent an invalid subprotocol';
3737
- }
3738
- } else if (protocolSet.size) {
3739
- protError = 'Server sent no subprotocol';
3740
- }
3741
-
3742
- if (protError) {
3743
- abortHandshake(websocket, socket, protError);
3744
- return;
3745
- }
3746
-
3747
- if (serverProt) websocket._protocol = serverProt;
3748
-
3749
- const secWebSocketExtensions = res.headers['sec-websocket-extensions'];
3750
-
3751
- if (secWebSocketExtensions !== undefined) {
3752
- if (!perMessageDeflate) {
3753
- const message =
3754
- 'Server sent a Sec-WebSocket-Extensions header but no extension ' +
3755
- 'was requested';
3756
- abortHandshake(websocket, socket, message);
3757
- return;
3758
- }
3759
-
3760
- let extensions;
3761
-
3762
- try {
3763
- extensions = parse(secWebSocketExtensions);
3764
- } catch (err) {
3765
- const message = 'Invalid Sec-WebSocket-Extensions header';
3766
- abortHandshake(websocket, socket, message);
3767
- return;
3768
- }
3769
-
3770
- const extensionNames = Object.keys(extensions);
3771
-
3772
- if (
3773
- extensionNames.length !== 1 ||
3774
- extensionNames[0] !== PerMessageDeflate.extensionName
3775
- ) {
3776
- const message = 'Server indicated an extension that was not requested';
3777
- abortHandshake(websocket, socket, message);
3778
- return;
3779
- }
3780
-
3781
- try {
3782
- perMessageDeflate.accept(extensions[PerMessageDeflate.extensionName]);
3783
- } catch (err) {
3784
- const message = 'Invalid Sec-WebSocket-Extensions header';
3785
- abortHandshake(websocket, socket, message);
3786
- return;
3787
- }
3788
-
3789
- websocket._extensions[PerMessageDeflate.extensionName] =
3790
- perMessageDeflate;
3791
- }
3792
-
3793
- websocket.setSocket(socket, head, {
3794
- allowSynchronousEvents: opts.allowSynchronousEvents,
3795
- generateMask: opts.generateMask,
3796
- maxPayload: opts.maxPayload,
3797
- skipUTF8Validation: opts.skipUTF8Validation
3798
- });
3799
- });
3800
-
3801
- if (opts.finishRequest) {
3802
- opts.finishRequest(req, websocket);
3803
- } else {
3804
- req.end();
3805
- }
3806
- }
3807
-
3808
- /**
3809
- * Emit the `'error'` and `'close'` events.
3810
- *
3811
- * @param {WebSocket} websocket The WebSocket instance
3812
- * @param {Error} The error to emit
3813
- * @private
3814
- */
3815
- function emitErrorAndClose(websocket, err) {
3816
- websocket._readyState = WebSocket.CLOSING;
3817
- //
3818
- // The following assignment is practically useless and is done only for
3819
- // consistency.
3820
- //
3821
- websocket._errorEmitted = true;
3822
- websocket.emit('error', err);
3823
- websocket.emitClose();
3824
- }
3825
-
3826
- /**
3827
- * Create a `net.Socket` and initiate a connection.
3828
- *
3829
- * @param {Object} options Connection options
3830
- * @return {net.Socket} The newly created socket used to start the connection
3831
- * @private
3832
- */
3833
- function netConnect(options) {
3834
- options.path = options.socketPath;
3835
- return net.connect(options);
3836
- }
3837
-
3838
- /**
3839
- * Create a `tls.TLSSocket` and initiate a connection.
3840
- *
3841
- * @param {Object} options Connection options
3842
- * @return {tls.TLSSocket} The newly created socket used to start the connection
3843
- * @private
3844
- */
3845
- function tlsConnect(options) {
3846
- options.path = undefined;
3847
-
3848
- if (!options.servername && options.servername !== '') {
3849
- options.servername = net.isIP(options.host) ? '' : options.host;
3850
- }
3851
-
3852
- return tls.connect(options);
3853
- }
3854
-
3855
- /**
3856
- * Abort the handshake and emit an error.
3857
- *
3858
- * @param {WebSocket} websocket The WebSocket instance
3859
- * @param {(http.ClientRequest|net.Socket|tls.Socket)} stream The request to
3860
- * abort or the socket to destroy
3861
- * @param {String} message The error message
3862
- * @private
3863
- */
3864
- function abortHandshake(websocket, stream, message) {
3865
- websocket._readyState = WebSocket.CLOSING;
3866
-
3867
- const err = new Error(message);
3868
- Error.captureStackTrace(err, abortHandshake);
3869
-
3870
- if (stream.setHeader) {
3871
- stream[kAborted] = true;
3872
- stream.abort();
3873
-
3874
- if (stream.socket && !stream.socket.destroyed) {
3875
- //
3876
- // On Node.js >= 14.3.0 `request.abort()` does not destroy the socket if
3877
- // called after the request completed. See
3878
- // https://github.com/websockets/ws/issues/1869.
3879
- //
3880
- stream.socket.destroy();
3881
- }
3882
-
3883
- process.nextTick(emitErrorAndClose, websocket, err);
3884
- } else {
3885
- stream.destroy(err);
3886
- stream.once('error', websocket.emit.bind(websocket, 'error'));
3887
- stream.once('close', websocket.emitClose.bind(websocket));
3888
- }
3889
- }
3890
-
3891
- /**
3892
- * Handle cases where the `ping()`, `pong()`, or `send()` methods are called
3893
- * when the `readyState` attribute is `CLOSING` or `CLOSED`.
3894
- *
3895
- * @param {WebSocket} websocket The WebSocket instance
3896
- * @param {*} [data] The data to send
3897
- * @param {Function} [cb] Callback
3898
- * @private
3899
- */
3900
- function sendAfterClose(websocket, data, cb) {
3901
- if (data) {
3902
- const length = isBlob(data) ? data.size : toBuffer(data).length;
3903
-
3904
- //
3905
- // The `_bufferedAmount` property is used only when the peer is a client and
3906
- // the opening handshake fails. Under these circumstances, in fact, the
3907
- // `setSocket()` method is not called, so the `_socket` and `_sender`
3908
- // properties are set to `null`.
3909
- //
3910
- if (websocket._socket) websocket._sender._bufferedBytes += length;
3911
- else websocket._bufferedAmount += length;
3912
- }
3913
-
3914
- if (cb) {
3915
- const err = new Error(
3916
- `WebSocket is not open: readyState ${websocket.readyState} ` +
3917
- `(${readyStates[websocket.readyState]})`
3918
- );
3919
- process.nextTick(cb, err);
3920
- }
3921
- }
3922
-
3923
- /**
3924
- * The listener of the `Receiver` `'conclude'` event.
3925
- *
3926
- * @param {Number} code The status code
3927
- * @param {Buffer} reason The reason for closing
3928
- * @private
3929
- */
3930
- function receiverOnConclude(code, reason) {
3931
- const websocket = this[kWebSocket];
3932
-
3933
- websocket._closeFrameReceived = true;
3934
- websocket._closeMessage = reason;
3935
- websocket._closeCode = code;
3936
-
3937
- if (websocket._socket[kWebSocket] === undefined) return;
3938
-
3939
- websocket._socket.removeListener('data', socketOnData);
3940
- process.nextTick(resume, websocket._socket);
3941
-
3942
- if (code === 1005) websocket.close();
3943
- else websocket.close(code, reason);
3944
- }
3945
-
3946
- /**
3947
- * The listener of the `Receiver` `'drain'` event.
3948
- *
3949
- * @private
3950
- */
3951
- function receiverOnDrain() {
3952
- const websocket = this[kWebSocket];
3953
-
3954
- if (!websocket.isPaused) websocket._socket.resume();
3955
- }
3956
-
3957
- /**
3958
- * The listener of the `Receiver` `'error'` event.
3959
- *
3960
- * @param {(RangeError|Error)} err The emitted error
3961
- * @private
3962
- */
3963
- function receiverOnError(err) {
3964
- const websocket = this[kWebSocket];
3965
-
3966
- if (websocket._socket[kWebSocket] !== undefined) {
3967
- websocket._socket.removeListener('data', socketOnData);
3968
-
3969
- //
3970
- // On Node.js < 14.0.0 the `'error'` event is emitted synchronously. See
3971
- // https://github.com/websockets/ws/issues/1940.
3972
- //
3973
- process.nextTick(resume, websocket._socket);
3974
-
3975
- websocket.close(err[kStatusCode]);
3976
- }
3977
-
3978
- if (!websocket._errorEmitted) {
3979
- websocket._errorEmitted = true;
3980
- websocket.emit('error', err);
3981
- }
3982
- }
3983
-
3984
- /**
3985
- * The listener of the `Receiver` `'finish'` event.
3986
- *
3987
- * @private
3988
- */
3989
- function receiverOnFinish() {
3990
- this[kWebSocket].emitClose();
3991
- }
3992
-
3993
- /**
3994
- * The listener of the `Receiver` `'message'` event.
3995
- *
3996
- * @param {Buffer|ArrayBuffer|Buffer[])} data The message
3997
- * @param {Boolean} isBinary Specifies whether the message is binary or not
3998
- * @private
3999
- */
4000
- function receiverOnMessage(data, isBinary) {
4001
- this[kWebSocket].emit('message', data, isBinary);
4002
- }
4003
-
4004
- /**
4005
- * The listener of the `Receiver` `'ping'` event.
4006
- *
4007
- * @param {Buffer} data The data included in the ping frame
4008
- * @private
4009
- */
4010
- function receiverOnPing(data) {
4011
- const websocket = this[kWebSocket];
4012
-
4013
- if (websocket._autoPong) websocket.pong(data, !this._isServer, NOOP);
4014
- websocket.emit('ping', data);
4015
- }
4016
-
4017
- /**
4018
- * The listener of the `Receiver` `'pong'` event.
4019
- *
4020
- * @param {Buffer} data The data included in the pong frame
4021
- * @private
4022
- */
4023
- function receiverOnPong(data) {
4024
- this[kWebSocket].emit('pong', data);
4025
- }
4026
-
4027
- /**
4028
- * Resume a readable stream
4029
- *
4030
- * @param {Readable} stream The readable stream
4031
- * @private
4032
- */
4033
- function resume(stream) {
4034
- stream.resume();
4035
- }
4036
-
4037
- /**
4038
- * The `Sender` error event handler.
4039
- *
4040
- * @param {Error} The error
4041
- * @private
4042
- */
4043
- function senderOnError(err) {
4044
- const websocket = this[kWebSocket];
4045
-
4046
- if (websocket.readyState === WebSocket.CLOSED) return;
4047
- if (websocket.readyState === WebSocket.OPEN) {
4048
- websocket._readyState = WebSocket.CLOSING;
4049
- setCloseTimer(websocket);
4050
- }
4051
-
4052
- //
4053
- // `socket.end()` is used instead of `socket.destroy()` to allow the other
4054
- // peer to finish sending queued data. There is no need to set a timer here
4055
- // because `CLOSING` means that it is already set or not needed.
4056
- //
4057
- this._socket.end();
4058
-
4059
- if (!websocket._errorEmitted) {
4060
- websocket._errorEmitted = true;
4061
- websocket.emit('error', err);
4062
- }
4063
- }
4064
-
4065
- /**
4066
- * Set a timer to destroy the underlying raw socket of a WebSocket.
4067
- *
4068
- * @param {WebSocket} websocket The WebSocket instance
4069
- * @private
4070
- */
4071
- function setCloseTimer(websocket) {
4072
- websocket._closeTimer = setTimeout(
4073
- websocket._socket.destroy.bind(websocket._socket),
4074
- closeTimeout
4075
- );
4076
- }
4077
-
4078
- /**
4079
- * The listener of the socket `'close'` event.
4080
- *
4081
- * @private
4082
- */
4083
- function socketOnClose() {
4084
- const websocket = this[kWebSocket];
4085
-
4086
- this.removeListener('close', socketOnClose);
4087
- this.removeListener('data', socketOnData);
4088
- this.removeListener('end', socketOnEnd);
4089
-
4090
- websocket._readyState = WebSocket.CLOSING;
4091
-
4092
- let chunk;
4093
-
4094
- //
4095
- // The close frame might not have been received or the `'end'` event emitted,
4096
- // for example, if the socket was destroyed due to an error. Ensure that the
4097
- // `receiver` stream is closed after writing any remaining buffered data to
4098
- // it. If the readable side of the socket is in flowing mode then there is no
4099
- // buffered data as everything has been already written and `readable.read()`
4100
- // will return `null`. If instead, the socket is paused, any possible buffered
4101
- // data will be read as a single chunk.
4102
- //
4103
- if (
4104
- !this._readableState.endEmitted &&
4105
- !websocket._closeFrameReceived &&
4106
- !websocket._receiver._writableState.errorEmitted &&
4107
- (chunk = websocket._socket.read()) !== null
4108
- ) {
4109
- websocket._receiver.write(chunk);
4110
- }
4111
-
4112
- websocket._receiver.end();
4113
-
4114
- this[kWebSocket] = undefined;
4115
-
4116
- clearTimeout(websocket._closeTimer);
4117
-
4118
- if (
4119
- websocket._receiver._writableState.finished ||
4120
- websocket._receiver._writableState.errorEmitted
4121
- ) {
4122
- websocket.emitClose();
4123
- } else {
4124
- websocket._receiver.on('error', receiverOnFinish);
4125
- websocket._receiver.on('finish', receiverOnFinish);
4126
- }
4127
- }
4128
-
4129
- /**
4130
- * The listener of the socket `'data'` event.
4131
- *
4132
- * @param {Buffer} chunk A chunk of data
4133
- * @private
4134
- */
4135
- function socketOnData(chunk) {
4136
- if (!this[kWebSocket]._receiver.write(chunk)) {
4137
- this.pause();
4138
- }
4139
- }
4140
-
4141
- /**
4142
- * The listener of the socket `'end'` event.
4143
- *
4144
- * @private
4145
- */
4146
- function socketOnEnd() {
4147
- const websocket = this[kWebSocket];
4148
-
4149
- websocket._readyState = WebSocket.CLOSING;
4150
- websocket._receiver.end();
4151
- this.end();
4152
- }
4153
-
4154
- /**
4155
- * The listener of the socket `'error'` event.
4156
- *
4157
- * @private
4158
- */
4159
- function socketOnError() {
4160
- const websocket = this[kWebSocket];
4161
-
4162
- this.removeListener('error', socketOnError);
4163
- this.on('error', NOOP);
4164
-
4165
- if (websocket) {
4166
- websocket._readyState = WebSocket.CLOSING;
4167
- this.destroy();
4168
- }
4169
- }
4170
- return websocket;
4171
- }
4172
-
4173
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^WebSocket$" }] */
4174
-
4175
- var stream;
4176
- var hasRequiredStream;
4177
-
4178
- function requireStream () {
4179
- if (hasRequiredStream) return stream;
4180
- hasRequiredStream = 1;
4181
-
4182
- requireWebsocket();
4183
- const { Duplex } = require$$0$2;
4184
-
4185
- /**
4186
- * Emits the `'close'` event on a stream.
4187
- *
4188
- * @param {Duplex} stream The stream.
4189
- * @private
4190
- */
4191
- function emitClose(stream) {
4192
- stream.emit('close');
4193
- }
4194
-
4195
- /**
4196
- * The listener of the `'end'` event.
4197
- *
4198
- * @private
4199
- */
4200
- function duplexOnEnd() {
4201
- if (!this.destroyed && this._writableState.finished) {
4202
- this.destroy();
4203
- }
4204
- }
4205
-
4206
- /**
4207
- * The listener of the `'error'` event.
4208
- *
4209
- * @param {Error} err The error
4210
- * @private
4211
- */
4212
- function duplexOnError(err) {
4213
- this.removeListener('error', duplexOnError);
4214
- this.destroy();
4215
- if (this.listenerCount('error') === 0) {
4216
- // Do not suppress the throwing behavior.
4217
- this.emit('error', err);
4218
- }
4219
- }
4220
-
4221
- /**
4222
- * Wraps a `WebSocket` in a duplex stream.
4223
- *
4224
- * @param {WebSocket} ws The `WebSocket` to wrap
4225
- * @param {Object} [options] The options for the `Duplex` constructor
4226
- * @return {Duplex} The duplex stream
4227
- * @public
4228
- */
4229
- function createWebSocketStream(ws, options) {
4230
- let terminateOnDestroy = true;
4231
-
4232
- const duplex = new Duplex({
4233
- ...options,
4234
- autoDestroy: false,
4235
- emitClose: false,
4236
- objectMode: false,
4237
- writableObjectMode: false
4238
- });
4239
-
4240
- ws.on('message', function message(msg, isBinary) {
4241
- const data =
4242
- !isBinary && duplex._readableState.objectMode ? msg.toString() : msg;
4243
-
4244
- if (!duplex.push(data)) ws.pause();
4245
- });
4246
-
4247
- ws.once('error', function error(err) {
4248
- if (duplex.destroyed) return;
4249
-
4250
- // Prevent `ws.terminate()` from being called by `duplex._destroy()`.
4251
- //
4252
- // - If the `'error'` event is emitted before the `'open'` event, then
4253
- // `ws.terminate()` is a noop as no socket is assigned.
4254
- // - Otherwise, the error is re-emitted by the listener of the `'error'`
4255
- // event of the `Receiver` object. The listener already closes the
4256
- // connection by calling `ws.close()`. This allows a close frame to be
4257
- // sent to the other peer. If `ws.terminate()` is called right after this,
4258
- // then the close frame might not be sent.
4259
- terminateOnDestroy = false;
4260
- duplex.destroy(err);
4261
- });
4262
-
4263
- ws.once('close', function close() {
4264
- if (duplex.destroyed) return;
4265
-
4266
- duplex.push(null);
4267
- });
4268
-
4269
- duplex._destroy = function (err, callback) {
4270
- if (ws.readyState === ws.CLOSED) {
4271
- callback(err);
4272
- process.nextTick(emitClose, duplex);
4273
- return;
4274
- }
4275
-
4276
- let called = false;
4277
-
4278
- ws.once('error', function error(err) {
4279
- called = true;
4280
- callback(err);
4281
- });
4282
-
4283
- ws.once('close', function close() {
4284
- if (!called) callback(err);
4285
- process.nextTick(emitClose, duplex);
4286
- });
4287
-
4288
- if (terminateOnDestroy) ws.terminate();
4289
- };
4290
-
4291
- duplex._final = function (callback) {
4292
- if (ws.readyState === ws.CONNECTING) {
4293
- ws.once('open', function open() {
4294
- duplex._final(callback);
4295
- });
4296
- return;
4297
- }
4298
-
4299
- // If the value of the `_socket` property is `null` it means that `ws` is a
4300
- // client websocket and the handshake failed. In fact, when this happens, a
4301
- // socket is never assigned to the websocket. Wait for the `'error'` event
4302
- // that will be emitted by the websocket.
4303
- if (ws._socket === null) return;
4304
-
4305
- if (ws._socket._writableState.finished) {
4306
- callback();
4307
- if (duplex._readableState.endEmitted) duplex.destroy();
4308
- } else {
4309
- ws._socket.once('finish', function finish() {
4310
- // `duplex` is not destroyed here because the `'end'` event will be
4311
- // emitted on `duplex` after this `'finish'` event. The EOF signaling
4312
- // `null` chunk is, in fact, pushed when the websocket emits `'close'`.
4313
- callback();
4314
- });
4315
- ws.close();
4316
- }
4317
- };
4318
-
4319
- duplex._read = function () {
4320
- if (ws.isPaused) ws.resume();
4321
- };
4322
-
4323
- duplex._write = function (chunk, encoding, callback) {
4324
- if (ws.readyState === ws.CONNECTING) {
4325
- ws.once('open', function open() {
4326
- duplex._write(chunk, encoding, callback);
4327
- });
4328
- return;
4329
- }
4330
-
4331
- ws.send(chunk, callback);
4332
- };
4333
-
4334
- duplex.on('end', duplexOnEnd);
4335
- duplex.on('error', duplexOnError);
4336
- return duplex;
4337
- }
4338
-
4339
- stream = createWebSocketStream;
4340
- return stream;
4341
- }
4342
-
4343
- requireStream();
4344
-
4345
- requireReceiver();
4346
-
4347
- requireSender();
4348
-
4349
- var websocketExports = requireWebsocket();
4350
- const _WebSocket = /*@__PURE__*/getDefaultExportFromCjs(websocketExports);
4351
-
4352
- var subprotocol;
4353
- var hasRequiredSubprotocol;
4354
-
4355
- function requireSubprotocol () {
4356
- if (hasRequiredSubprotocol) return subprotocol;
4357
- hasRequiredSubprotocol = 1;
4358
-
4359
- const { tokenChars } = requireValidation();
4360
-
4361
- /**
4362
- * Parses the `Sec-WebSocket-Protocol` header into a set of subprotocol names.
4363
- *
4364
- * @param {String} header The field value of the header
4365
- * @return {Set} The subprotocol names
4366
- * @public
4367
- */
4368
- function parse(header) {
4369
- const protocols = new Set();
4370
- let start = -1;
4371
- let end = -1;
4372
- let i = 0;
4373
-
4374
- for (i; i < header.length; i++) {
4375
- const code = header.charCodeAt(i);
4376
-
4377
- if (end === -1 && tokenChars[code] === 1) {
4378
- if (start === -1) start = i;
4379
- } else if (
4380
- i !== 0 &&
4381
- (code === 0x20 /* ' ' */ || code === 0x09) /* '\t' */
4382
- ) {
4383
- if (end === -1 && start !== -1) end = i;
4384
- } else if (code === 0x2c /* ',' */) {
4385
- if (start === -1) {
4386
- throw new SyntaxError(`Unexpected character at index ${i}`);
4387
- }
4388
-
4389
- if (end === -1) end = i;
4390
-
4391
- const protocol = header.slice(start, end);
4392
-
4393
- if (protocols.has(protocol)) {
4394
- throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
4395
- }
4396
-
4397
- protocols.add(protocol);
4398
- start = end = -1;
4399
- } else {
4400
- throw new SyntaxError(`Unexpected character at index ${i}`);
4401
- }
4402
- }
4403
-
4404
- if (start === -1 || end !== -1) {
4405
- throw new SyntaxError('Unexpected end of input');
4406
- }
4407
-
4408
- const protocol = header.slice(start, i);
4409
-
4410
- if (protocols.has(protocol)) {
4411
- throw new SyntaxError(`The "${protocol}" subprotocol is duplicated`);
4412
- }
4413
-
4414
- protocols.add(protocol);
4415
- return protocols;
4416
- }
4417
-
4418
- subprotocol = { parse };
4419
- return subprotocol;
4420
- }
4421
-
4422
- /* eslint no-unused-vars: ["error", { "varsIgnorePattern": "^Duplex$", "caughtErrors": "none" }] */
4423
-
4424
- var websocketServer;
4425
- var hasRequiredWebsocketServer;
4426
-
4427
- function requireWebsocketServer () {
4428
- if (hasRequiredWebsocketServer) return websocketServer;
4429
- hasRequiredWebsocketServer = 1;
4430
-
4431
- const EventEmitter = require$$0$3;
4432
- const http = require$$2;
4433
- const { Duplex } = require$$0$2;
4434
- const { createHash } = require$$1;
4435
-
4436
- const extension = requireExtension();
4437
- const PerMessageDeflate = requirePermessageDeflate();
4438
- const subprotocol = requireSubprotocol();
4439
- const WebSocket = requireWebsocket();
4440
- const { GUID, kWebSocket } = requireConstants();
4441
-
4442
- const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
4443
-
4444
- const RUNNING = 0;
4445
- const CLOSING = 1;
4446
- const CLOSED = 2;
4447
-
4448
- /**
4449
- * Class representing a WebSocket server.
4450
- *
4451
- * @extends EventEmitter
4452
- */
4453
- class WebSocketServer extends EventEmitter {
4454
- /**
4455
- * Create a `WebSocketServer` instance.
4456
- *
4457
- * @param {Object} options Configuration options
4458
- * @param {Boolean} [options.allowSynchronousEvents=true] Specifies whether
4459
- * any of the `'message'`, `'ping'`, and `'pong'` events can be emitted
4460
- * multiple times in the same tick
4461
- * @param {Boolean} [options.autoPong=true] Specifies whether or not to
4462
- * automatically send a pong in response to a ping
4463
- * @param {Number} [options.backlog=511] The maximum length of the queue of
4464
- * pending connections
4465
- * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
4466
- * track clients
4467
- * @param {Function} [options.handleProtocols] A hook to handle protocols
4468
- * @param {String} [options.host] The hostname where to bind the server
4469
- * @param {Number} [options.maxPayload=104857600] The maximum allowed message
4470
- * size
4471
- * @param {Boolean} [options.noServer=false] Enable no server mode
4472
- * @param {String} [options.path] Accept only connections matching this path
4473
- * @param {(Boolean|Object)} [options.perMessageDeflate=false] Enable/disable
4474
- * permessage-deflate
4475
- * @param {Number} [options.port] The port where to bind the server
4476
- * @param {(http.Server|https.Server)} [options.server] A pre-created HTTP/S
4477
- * server to use
4478
- * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
4479
- * not to skip UTF-8 validation for text and close messages
4480
- * @param {Function} [options.verifyClient] A hook to reject connections
4481
- * @param {Function} [options.WebSocket=WebSocket] Specifies the `WebSocket`
4482
- * class to use. It must be the `WebSocket` class or class that extends it
4483
- * @param {Function} [callback] A listener for the `listening` event
4484
- */
4485
- constructor(options, callback) {
4486
- super();
4487
-
4488
- options = {
4489
- allowSynchronousEvents: true,
4490
- autoPong: true,
4491
- maxPayload: 100 * 1024 * 1024,
4492
- skipUTF8Validation: false,
4493
- perMessageDeflate: false,
4494
- handleProtocols: null,
4495
- clientTracking: true,
4496
- verifyClient: null,
4497
- noServer: false,
4498
- backlog: null, // use default (511 as implemented in net.js)
4499
- server: null,
4500
- host: null,
4501
- path: null,
4502
- port: null,
4503
- WebSocket,
4504
- ...options
4505
- };
4506
-
4507
- if (
4508
- (options.port == null && !options.server && !options.noServer) ||
4509
- (options.port != null && (options.server || options.noServer)) ||
4510
- (options.server && options.noServer)
4511
- ) {
4512
- throw new TypeError(
4513
- 'One and only one of the "port", "server", or "noServer" options ' +
4514
- 'must be specified'
4515
- );
4516
- }
4517
-
4518
- if (options.port != null) {
4519
- this._server = http.createServer((req, res) => {
4520
- const body = http.STATUS_CODES[426];
4521
-
4522
- res.writeHead(426, {
4523
- 'Content-Length': body.length,
4524
- 'Content-Type': 'text/plain'
4525
- });
4526
- res.end(body);
4527
- });
4528
- this._server.listen(
4529
- options.port,
4530
- options.host,
4531
- options.backlog,
4532
- callback
4533
- );
4534
- } else if (options.server) {
4535
- this._server = options.server;
4536
- }
4537
-
4538
- if (this._server) {
4539
- const emitConnection = this.emit.bind(this, 'connection');
4540
-
4541
- this._removeListeners = addListeners(this._server, {
4542
- listening: this.emit.bind(this, 'listening'),
4543
- error: this.emit.bind(this, 'error'),
4544
- upgrade: (req, socket, head) => {
4545
- this.handleUpgrade(req, socket, head, emitConnection);
4546
- }
4547
- });
4548
- }
4549
-
4550
- if (options.perMessageDeflate === true) options.perMessageDeflate = {};
4551
- if (options.clientTracking) {
4552
- this.clients = new Set();
4553
- this._shouldEmitClose = false;
4554
- }
4555
-
4556
- this.options = options;
4557
- this._state = RUNNING;
4558
- }
4559
-
4560
- /**
4561
- * Returns the bound address, the address family name, and port of the server
4562
- * as reported by the operating system if listening on an IP socket.
4563
- * If the server is listening on a pipe or UNIX domain socket, the name is
4564
- * returned as a string.
4565
- *
4566
- * @return {(Object|String|null)} The address of the server
4567
- * @public
4568
- */
4569
- address() {
4570
- if (this.options.noServer) {
4571
- throw new Error('The server is operating in "noServer" mode');
4572
- }
4573
-
4574
- if (!this._server) return null;
4575
- return this._server.address();
4576
- }
4577
-
4578
- /**
4579
- * Stop the server from accepting new connections and emit the `'close'` event
4580
- * when all existing connections are closed.
4581
- *
4582
- * @param {Function} [cb] A one-time listener for the `'close'` event
4583
- * @public
4584
- */
4585
- close(cb) {
4586
- if (this._state === CLOSED) {
4587
- if (cb) {
4588
- this.once('close', () => {
4589
- cb(new Error('The server is not running'));
4590
- });
4591
- }
4592
-
4593
- process.nextTick(emitClose, this);
4594
- return;
4595
- }
4596
-
4597
- if (cb) this.once('close', cb);
4598
-
4599
- if (this._state === CLOSING) return;
4600
- this._state = CLOSING;
4601
-
4602
- if (this.options.noServer || this.options.server) {
4603
- if (this._server) {
4604
- this._removeListeners();
4605
- this._removeListeners = this._server = null;
4606
- }
4607
-
4608
- if (this.clients) {
4609
- if (!this.clients.size) {
4610
- process.nextTick(emitClose, this);
4611
- } else {
4612
- this._shouldEmitClose = true;
4613
- }
4614
- } else {
4615
- process.nextTick(emitClose, this);
4616
- }
4617
- } else {
4618
- const server = this._server;
4619
-
4620
- this._removeListeners();
4621
- this._removeListeners = this._server = null;
4622
-
4623
- //
4624
- // The HTTP/S server was created internally. Close it, and rely on its
4625
- // `'close'` event.
4626
- //
4627
- server.close(() => {
4628
- emitClose(this);
4629
- });
4630
- }
4631
- }
4632
-
4633
- /**
4634
- * See if a given request should be handled by this server instance.
4635
- *
4636
- * @param {http.IncomingMessage} req Request object to inspect
4637
- * @return {Boolean} `true` if the request is valid, else `false`
4638
- * @public
4639
- */
4640
- shouldHandle(req) {
4641
- if (this.options.path) {
4642
- const index = req.url.indexOf('?');
4643
- const pathname = index !== -1 ? req.url.slice(0, index) : req.url;
4644
-
4645
- if (pathname !== this.options.path) return false;
4646
- }
4647
-
4648
- return true;
4649
- }
4650
-
4651
- /**
4652
- * Handle a HTTP Upgrade request.
4653
- *
4654
- * @param {http.IncomingMessage} req The request object
4655
- * @param {Duplex} socket The network socket between the server and client
4656
- * @param {Buffer} head The first packet of the upgraded stream
4657
- * @param {Function} cb Callback
4658
- * @public
4659
- */
4660
- handleUpgrade(req, socket, head, cb) {
4661
- socket.on('error', socketOnError);
4662
-
4663
- const key = req.headers['sec-websocket-key'];
4664
- const upgrade = req.headers.upgrade;
4665
- const version = +req.headers['sec-websocket-version'];
4666
-
4667
- if (req.method !== 'GET') {
4668
- const message = 'Invalid HTTP method';
4669
- abortHandshakeOrEmitwsClientError(this, req, socket, 405, message);
4670
- return;
4671
- }
4672
-
4673
- if (upgrade === undefined || upgrade.toLowerCase() !== 'websocket') {
4674
- const message = 'Invalid Upgrade header';
4675
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4676
- return;
4677
- }
4678
-
4679
- if (key === undefined || !keyRegex.test(key)) {
4680
- const message = 'Missing or invalid Sec-WebSocket-Key header';
4681
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4682
- return;
4683
- }
4684
-
4685
- if (version !== 8 && version !== 13) {
4686
- const message = 'Missing or invalid Sec-WebSocket-Version header';
4687
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4688
- return;
4689
- }
4690
-
4691
- if (!this.shouldHandle(req)) {
4692
- abortHandshake(socket, 400);
4693
- return;
4694
- }
4695
-
4696
- const secWebSocketProtocol = req.headers['sec-websocket-protocol'];
4697
- let protocols = new Set();
4698
-
4699
- if (secWebSocketProtocol !== undefined) {
4700
- try {
4701
- protocols = subprotocol.parse(secWebSocketProtocol);
4702
- } catch (err) {
4703
- const message = 'Invalid Sec-WebSocket-Protocol header';
4704
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4705
- return;
4706
- }
4707
- }
4708
-
4709
- const secWebSocketExtensions = req.headers['sec-websocket-extensions'];
4710
- const extensions = {};
4711
-
4712
- if (
4713
- this.options.perMessageDeflate &&
4714
- secWebSocketExtensions !== undefined
4715
- ) {
4716
- const perMessageDeflate = new PerMessageDeflate(
4717
- this.options.perMessageDeflate,
4718
- true,
4719
- this.options.maxPayload
4720
- );
4721
-
4722
- try {
4723
- const offers = extension.parse(secWebSocketExtensions);
4724
-
4725
- if (offers[PerMessageDeflate.extensionName]) {
4726
- perMessageDeflate.accept(offers[PerMessageDeflate.extensionName]);
4727
- extensions[PerMessageDeflate.extensionName] = perMessageDeflate;
4728
- }
4729
- } catch (err) {
4730
- const message =
4731
- 'Invalid or unacceptable Sec-WebSocket-Extensions header';
4732
- abortHandshakeOrEmitwsClientError(this, req, socket, 400, message);
4733
- return;
4734
- }
4735
- }
4736
-
4737
- //
4738
- // Optionally call external client verification handler.
4739
- //
4740
- if (this.options.verifyClient) {
4741
- const info = {
4742
- origin:
4743
- req.headers[`${version === 8 ? 'sec-websocket-origin' : 'origin'}`],
4744
- secure: !!(req.socket.authorized || req.socket.encrypted),
4745
- req
4746
- };
4747
-
4748
- if (this.options.verifyClient.length === 2) {
4749
- this.options.verifyClient(info, (verified, code, message, headers) => {
4750
- if (!verified) {
4751
- return abortHandshake(socket, code || 401, message, headers);
4752
- }
4753
-
4754
- this.completeUpgrade(
4755
- extensions,
4756
- key,
4757
- protocols,
4758
- req,
4759
- socket,
4760
- head,
4761
- cb
4762
- );
4763
- });
4764
- return;
4765
- }
4766
-
4767
- if (!this.options.verifyClient(info)) return abortHandshake(socket, 401);
4768
- }
4769
-
4770
- this.completeUpgrade(extensions, key, protocols, req, socket, head, cb);
4771
- }
4772
-
4773
- /**
4774
- * Upgrade the connection to WebSocket.
4775
- *
4776
- * @param {Object} extensions The accepted extensions
4777
- * @param {String} key The value of the `Sec-WebSocket-Key` header
4778
- * @param {Set} protocols The subprotocols
4779
- * @param {http.IncomingMessage} req The request object
4780
- * @param {Duplex} socket The network socket between the server and client
4781
- * @param {Buffer} head The first packet of the upgraded stream
4782
- * @param {Function} cb Callback
4783
- * @throws {Error} If called more than once with the same socket
4784
- * @private
4785
- */
4786
- completeUpgrade(extensions, key, protocols, req, socket, head, cb) {
4787
- //
4788
- // Destroy the socket if the client has already sent a FIN packet.
4789
- //
4790
- if (!socket.readable || !socket.writable) return socket.destroy();
4791
-
4792
- if (socket[kWebSocket]) {
4793
- throw new Error(
4794
- 'server.handleUpgrade() was called more than once with the same ' +
4795
- 'socket, possibly due to a misconfiguration'
4796
- );
4797
- }
4798
-
4799
- if (this._state > RUNNING) return abortHandshake(socket, 503);
4800
-
4801
- const digest = createHash('sha1')
4802
- .update(key + GUID)
4803
- .digest('base64');
4804
-
4805
- const headers = [
4806
- 'HTTP/1.1 101 Switching Protocols',
4807
- 'Upgrade: websocket',
4808
- 'Connection: Upgrade',
4809
- `Sec-WebSocket-Accept: ${digest}`
4810
- ];
4811
-
4812
- const ws = new this.options.WebSocket(null, undefined, this.options);
4813
-
4814
- if (protocols.size) {
4815
- //
4816
- // Optionally call external protocol selection handler.
4817
- //
4818
- const protocol = this.options.handleProtocols
4819
- ? this.options.handleProtocols(protocols, req)
4820
- : protocols.values().next().value;
4821
-
4822
- if (protocol) {
4823
- headers.push(`Sec-WebSocket-Protocol: ${protocol}`);
4824
- ws._protocol = protocol;
4825
- }
4826
- }
4827
-
4828
- if (extensions[PerMessageDeflate.extensionName]) {
4829
- const params = extensions[PerMessageDeflate.extensionName].params;
4830
- const value = extension.format({
4831
- [PerMessageDeflate.extensionName]: [params]
4832
- });
4833
- headers.push(`Sec-WebSocket-Extensions: ${value}`);
4834
- ws._extensions = extensions;
4835
- }
4836
-
4837
- //
4838
- // Allow external modification/inspection of handshake headers.
4839
- //
4840
- this.emit('headers', headers, req);
4841
-
4842
- socket.write(headers.concat('\r\n').join('\r\n'));
4843
- socket.removeListener('error', socketOnError);
4844
-
4845
- ws.setSocket(socket, head, {
4846
- allowSynchronousEvents: this.options.allowSynchronousEvents,
4847
- maxPayload: this.options.maxPayload,
4848
- skipUTF8Validation: this.options.skipUTF8Validation
4849
- });
4850
-
4851
- if (this.clients) {
4852
- this.clients.add(ws);
4853
- ws.on('close', () => {
4854
- this.clients.delete(ws);
4855
-
4856
- if (this._shouldEmitClose && !this.clients.size) {
4857
- process.nextTick(emitClose, this);
4858
- }
4859
- });
4860
- }
4861
-
4862
- cb(ws, req);
4863
- }
4864
- }
4865
-
4866
- websocketServer = WebSocketServer;
4867
-
4868
- /**
4869
- * Add event listeners on an `EventEmitter` using a map of <event, listener>
4870
- * pairs.
4871
- *
4872
- * @param {EventEmitter} server The event emitter
4873
- * @param {Object.<String, Function>} map The listeners to add
4874
- * @return {Function} A function that will remove the added listeners when
4875
- * called
4876
- * @private
4877
- */
4878
- function addListeners(server, map) {
4879
- for (const event of Object.keys(map)) server.on(event, map[event]);
4880
-
4881
- return function removeListeners() {
4882
- for (const event of Object.keys(map)) {
4883
- server.removeListener(event, map[event]);
4884
- }
4885
- };
4886
- }
4887
-
4888
- /**
4889
- * Emit a `'close'` event on an `EventEmitter`.
4890
- *
4891
- * @param {EventEmitter} server The event emitter
4892
- * @private
4893
- */
4894
- function emitClose(server) {
4895
- server._state = CLOSED;
4896
- server.emit('close');
4897
- }
4898
-
4899
- /**
4900
- * Handle socket errors.
4901
- *
4902
- * @private
4903
- */
4904
- function socketOnError() {
4905
- this.destroy();
4906
- }
4907
-
4908
- /**
4909
- * Close the connection when preconditions are not fulfilled.
4910
- *
4911
- * @param {Duplex} socket The socket of the upgrade request
4912
- * @param {Number} code The HTTP response status code
4913
- * @param {String} [message] The HTTP response body
4914
- * @param {Object} [headers] Additional HTTP response headers
4915
- * @private
4916
- */
4917
- function abortHandshake(socket, code, message, headers) {
4918
- //
4919
- // The socket is writable unless the user destroyed or ended it before calling
4920
- // `server.handleUpgrade()` or in the `verifyClient` function, which is a user
4921
- // error. Handling this does not make much sense as the worst that can happen
4922
- // is that some of the data written by the user might be discarded due to the
4923
- // call to `socket.end()` below, which triggers an `'error'` event that in
4924
- // turn causes the socket to be destroyed.
4925
- //
4926
- message = message || http.STATUS_CODES[code];
4927
- headers = {
4928
- Connection: 'close',
4929
- 'Content-Type': 'text/html',
4930
- 'Content-Length': Buffer.byteLength(message),
4931
- ...headers
4932
- };
4933
-
4934
- socket.once('finish', socket.destroy);
4935
-
4936
- socket.end(
4937
- `HTTP/1.1 ${code} ${http.STATUS_CODES[code]}\r\n` +
4938
- Object.keys(headers)
4939
- .map((h) => `${h}: ${headers[h]}`)
4940
- .join('\r\n') +
4941
- '\r\n\r\n' +
4942
- message
4943
- );
4944
- }
4945
-
4946
- /**
4947
- * Emit a `'wsClientError'` event on a `WebSocketServer` if there is at least
4948
- * one listener for it, otherwise call `abortHandshake()`.
4949
- *
4950
- * @param {WebSocketServer} server The WebSocket server
4951
- * @param {http.IncomingMessage} req The request object
4952
- * @param {Duplex} socket The socket of the upgrade request
4953
- * @param {Number} code The HTTP response status code
4954
- * @param {String} message The HTTP response body
4955
- * @private
4956
- */
4957
- function abortHandshakeOrEmitwsClientError(server, req, socket, code, message) {
4958
- if (server.listenerCount('wsClientError')) {
4959
- const err = new Error(message);
4960
- Error.captureStackTrace(err, abortHandshakeOrEmitwsClientError);
4961
-
4962
- server.emit('wsClientError', err, socket, req);
4963
- } else {
4964
- abortHandshake(socket, code, message);
4965
- }
4966
- }
4967
- return websocketServer;
4968
- }
4969
-
4970
- var websocketServerExports = requireWebsocketServer();
4971
- const _WebSocketServer = /*@__PURE__*/getDefaultExportFromCjs(websocketServerExports);
4972
-
4973
- export { _WebSocketServer as _, _WebSocket as a };