@blade-hq/agent-client 2612.0.0-beta.11 → 2612.0.0-beta.13

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 (66) hide show
  1. package/README.md +59 -2
  2. package/dist/{chunk-SCG5SRXE.js → chunk-KPS6X6QX.js} +13 -16
  3. package/dist/chunk-KPS6X6QX.js.map +1 -0
  4. package/dist/index.d.ts +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/internal.d.ts +1 -1
  7. package/dist/internal.js +1 -1
  8. package/dist/resources/sessions.d.ts +42 -6
  9. package/dist/schemas/session.d.ts +1 -42
  10. package/dist/session/agent-session.d.ts +0 -1
  11. package/dist/session/events.d.ts +0 -1
  12. package/node_modules/engine.io-client/build/cjs/globals.node.d.ts +2 -3
  13. package/node_modules/engine.io-client/build/cjs/index.d.ts +3 -3
  14. package/node_modules/engine.io-client/build/cjs/index.js +1 -4
  15. package/node_modules/engine.io-client/build/cjs/socket.d.ts +39 -82
  16. package/node_modules/engine.io-client/build/cjs/socket.js +151 -218
  17. package/node_modules/engine.io-client/build/cjs/transport.d.ts +1 -1
  18. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.d.ts +4 -4
  19. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.js +2 -2
  20. package/node_modules/engine.io-client/build/cjs/transports/polling-xhr.node.js +17 -7
  21. package/node_modules/engine.io-client/build/cjs/transports/websocket.node.js +17 -7
  22. package/node_modules/engine.io-client/build/esm/globals.node.d.ts +2 -3
  23. package/node_modules/engine.io-client/build/esm/index.d.ts +3 -3
  24. package/node_modules/engine.io-client/build/esm/index.js +1 -2
  25. package/node_modules/engine.io-client/build/esm/socket.d.ts +39 -82
  26. package/node_modules/engine.io-client/build/esm/socket.js +141 -206
  27. package/node_modules/engine.io-client/build/esm/transport.d.ts +1 -1
  28. package/node_modules/engine.io-client/build/esm/transports/polling-xhr.d.ts +4 -4
  29. package/node_modules/engine.io-client/build/esm/transports/polling-xhr.js +2 -2
  30. package/node_modules/engine.io-client/build/esm-debug/globals.node.d.ts +2 -3
  31. package/node_modules/engine.io-client/build/esm-debug/index.d.ts +3 -3
  32. package/node_modules/engine.io-client/build/esm-debug/index.js +1 -2
  33. package/node_modules/engine.io-client/build/esm-debug/socket.d.ts +39 -82
  34. package/node_modules/engine.io-client/build/esm-debug/socket.js +150 -215
  35. package/node_modules/engine.io-client/build/esm-debug/transport.d.ts +1 -1
  36. package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.d.ts +4 -4
  37. package/node_modules/engine.io-client/build/esm-debug/transports/polling-xhr.js +2 -2
  38. package/node_modules/engine.io-client/dist/engine.io.esm.min.js +3 -3
  39. package/node_modules/engine.io-client/dist/engine.io.esm.min.js.map +1 -1
  40. package/node_modules/engine.io-client/dist/engine.io.js +164 -239
  41. package/node_modules/engine.io-client/dist/engine.io.js.map +1 -1
  42. package/node_modules/engine.io-client/dist/engine.io.min.js +3 -3
  43. package/node_modules/engine.io-client/dist/engine.io.min.js.map +1 -1
  44. package/node_modules/engine.io-client/package.json +2 -2
  45. package/node_modules/socket.io-parser/build/cjs/binary.js +4 -1
  46. package/node_modules/socket.io-parser/build/cjs/index.d.ts +14 -4
  47. package/node_modules/socket.io-parser/build/cjs/index.js +18 -11
  48. package/node_modules/socket.io-parser/build/esm/binary.js +4 -1
  49. package/node_modules/socket.io-parser/build/esm/index.d.ts +14 -4
  50. package/node_modules/socket.io-parser/build/esm/index.js +14 -10
  51. package/node_modules/socket.io-parser/build/esm-debug/binary.js +4 -1
  52. package/node_modules/socket.io-parser/build/esm-debug/index.d.ts +14 -4
  53. package/node_modules/socket.io-parser/build/esm-debug/index.js +14 -10
  54. package/node_modules/socket.io-parser/package.json +1 -1
  55. package/node_modules/ws/index.js +15 -6
  56. package/node_modules/ws/lib/constants.js +1 -0
  57. package/node_modules/ws/lib/permessage-deflate.js +9 -7
  58. package/node_modules/ws/lib/receiver.js +37 -0
  59. package/node_modules/ws/lib/sender.js +6 -1
  60. package/node_modules/ws/lib/websocket-server.js +18 -6
  61. package/node_modules/ws/lib/websocket.js +50 -17
  62. package/node_modules/ws/package.json +8 -3
  63. package/node_modules/ws/wrapper.mjs +14 -1
  64. package/package.json +4 -4
  65. package/public-api.md +36 -17
  66. package/dist/chunk-SCG5SRXE.js.map +0 -1
@@ -53,20 +53,30 @@ export declare class Encoder {
53
53
  interface DecoderReservedEvents {
54
54
  decoded: (packet: Packet) => void;
55
55
  }
56
+ type JSONReviver = (this: any, key: string, value: any) => any;
57
+ export interface DecoderOptions {
58
+ /**
59
+ * Custom reviver to pass down to JSON.parse()
60
+ */
61
+ reviver?: JSONReviver;
62
+ /**
63
+ * Maximum number of binary attachments per packet
64
+ * @default 10
65
+ */
66
+ maxAttachments?: number;
67
+ }
56
68
  /**
57
69
  * A socket.io Decoder instance
58
70
  *
59
71
  * @return {Object} decoder
60
72
  */
61
73
  export declare class Decoder extends Emitter<{}, {}, DecoderReservedEvents> {
62
- private reviver?;
63
74
  private reconstructor;
75
+ private opts;
64
76
  /**
65
77
  * Decoder constructor
66
- *
67
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
68
78
  */
69
- constructor(reviver?: (this: any, key: string, value: any) => any);
79
+ constructor(opts?: DecoderOptions | JSONReviver);
70
80
  /**
71
81
  * Decodes an encoded packet string into packet JSON.
72
82
  *
@@ -1,11 +1,14 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Decoder = exports.Encoder = exports.PacketType = exports.protocol = void 0;
4
7
  exports.isPacketValid = isPacketValid;
5
8
  const component_emitter_1 = require("@socket.io/component-emitter");
6
9
  const binary_js_1 = require("./binary.js");
7
10
  const is_binary_js_1 = require("./is-binary.js");
8
- const debug_1 = require("debug"); // debug()
11
+ const debug_1 = __importDefault(require("debug")); // debug()
9
12
  const debug = (0, debug_1.default)("socket.io-parser"); // debug()
10
13
  /**
11
14
  * These strings must not be used as event names, as they have a special meaning.
@@ -117,12 +120,13 @@ exports.Encoder = Encoder;
117
120
  class Decoder extends component_emitter_1.Emitter {
118
121
  /**
119
122
  * Decoder constructor
120
- *
121
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
122
123
  */
123
- constructor(reviver) {
124
+ constructor(opts) {
124
125
  super();
125
- this.reviver = reviver;
126
+ this.opts = Object.assign({
127
+ reviver: undefined,
128
+ maxAttachments: 10,
129
+ }, typeof opts === "function" ? { reviver: opts } : opts);
126
130
  }
127
131
  /**
128
132
  * Decodes an encoded packet string into packet JSON.
@@ -141,10 +145,6 @@ class Decoder extends component_emitter_1.Emitter {
141
145
  packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;
142
146
  // binary packet's json
143
147
  this.reconstructor = new BinaryReconstructor(packet);
144
- // no attachments, labeled binary but no binary data to follow
145
- if (packet.attachments === 0) {
146
- super.emitReserved("decoded", packet);
147
- }
148
148
  }
149
149
  else {
150
150
  // non-binary full packet
@@ -193,7 +193,14 @@ class Decoder extends component_emitter_1.Emitter {
193
193
  if (buf != Number(buf) || str.charAt(i) !== "-") {
194
194
  throw new Error("Illegal attachments");
195
195
  }
196
- p.attachments = Number(buf);
196
+ const n = Number(buf);
197
+ if (!isInteger(n) || n < 1) {
198
+ throw new Error("Illegal attachments");
199
+ }
200
+ else if (n > this.opts.maxAttachments) {
201
+ throw new Error("too many attachments");
202
+ }
203
+ p.attachments = n;
197
204
  }
198
205
  // look up namespace (if any)
199
206
  if ("/" === str.charAt(i + 1)) {
@@ -240,7 +247,7 @@ class Decoder extends component_emitter_1.Emitter {
240
247
  }
241
248
  tryParse(str) {
242
249
  try {
243
- return JSON.parse(str, this.reviver);
250
+ return JSON.parse(str, this.opts.reviver);
244
251
  }
245
252
  catch (e) {
246
253
  return false;
@@ -14,7 +14,7 @@ export function deconstructPacket(packet) {
14
14
  pack.attachments = buffers.length; // number of binary 'attachments'
15
15
  return { packet: pack, buffers: buffers };
16
16
  }
17
- function _deconstructPacket(data, buffers) {
17
+ function _deconstructPacket(data, buffers, toJSON) {
18
18
  if (!data)
19
19
  return data;
20
20
  if (isBinary(data)) {
@@ -30,6 +30,9 @@ function _deconstructPacket(data, buffers) {
30
30
  return newData;
31
31
  }
32
32
  else if (typeof data === "object" && !(data instanceof Date)) {
33
+ if (data.toJSON && typeof data.toJSON === "function" && !toJSON) {
34
+ return _deconstructPacket(data.toJSON(), buffers, true);
35
+ }
33
36
  const newData = {};
34
37
  for (const key in data) {
35
38
  if (Object.prototype.hasOwnProperty.call(data, key)) {
@@ -53,20 +53,30 @@ export declare class Encoder {
53
53
  interface DecoderReservedEvents {
54
54
  decoded: (packet: Packet) => void;
55
55
  }
56
+ type JSONReviver = (this: any, key: string, value: any) => any;
57
+ export interface DecoderOptions {
58
+ /**
59
+ * Custom reviver to pass down to JSON.parse()
60
+ */
61
+ reviver?: JSONReviver;
62
+ /**
63
+ * Maximum number of binary attachments per packet
64
+ * @default 10
65
+ */
66
+ maxAttachments?: number;
67
+ }
56
68
  /**
57
69
  * A socket.io Decoder instance
58
70
  *
59
71
  * @return {Object} decoder
60
72
  */
61
73
  export declare class Decoder extends Emitter<{}, {}, DecoderReservedEvents> {
62
- private reviver?;
63
74
  private reconstructor;
75
+ private opts;
64
76
  /**
65
77
  * Decoder constructor
66
- *
67
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
68
78
  */
69
- constructor(reviver?: (this: any, key: string, value: any) => any);
79
+ constructor(opts?: DecoderOptions | JSONReviver);
70
80
  /**
71
81
  * Decodes an encoded packet string into packet JSON.
72
82
  *
@@ -108,12 +108,13 @@ export class Encoder {
108
108
  export class Decoder extends Emitter {
109
109
  /**
110
110
  * Decoder constructor
111
- *
112
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
113
111
  */
114
- constructor(reviver) {
112
+ constructor(opts) {
115
113
  super();
116
- this.reviver = reviver;
114
+ this.opts = Object.assign({
115
+ reviver: undefined,
116
+ maxAttachments: 10,
117
+ }, typeof opts === "function" ? { reviver: opts } : opts);
117
118
  }
118
119
  /**
119
120
  * Decodes an encoded packet string into packet JSON.
@@ -132,10 +133,6 @@ export class Decoder extends Emitter {
132
133
  packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;
133
134
  // binary packet's json
134
135
  this.reconstructor = new BinaryReconstructor(packet);
135
- // no attachments, labeled binary but no binary data to follow
136
- if (packet.attachments === 0) {
137
- super.emitReserved("decoded", packet);
138
- }
139
136
  }
140
137
  else {
141
138
  // non-binary full packet
@@ -184,7 +181,14 @@ export class Decoder extends Emitter {
184
181
  if (buf != Number(buf) || str.charAt(i) !== "-") {
185
182
  throw new Error("Illegal attachments");
186
183
  }
187
- p.attachments = Number(buf);
184
+ const n = Number(buf);
185
+ if (!isInteger(n) || n < 1) {
186
+ throw new Error("Illegal attachments");
187
+ }
188
+ else if (n > this.opts.maxAttachments) {
189
+ throw new Error("too many attachments");
190
+ }
191
+ p.attachments = n;
188
192
  }
189
193
  // look up namespace (if any)
190
194
  if ("/" === str.charAt(i + 1)) {
@@ -230,7 +234,7 @@ export class Decoder extends Emitter {
230
234
  }
231
235
  tryParse(str) {
232
236
  try {
233
- return JSON.parse(str, this.reviver);
237
+ return JSON.parse(str, this.opts.reviver);
234
238
  }
235
239
  catch (e) {
236
240
  return false;
@@ -14,7 +14,7 @@ export function deconstructPacket(packet) {
14
14
  pack.attachments = buffers.length; // number of binary 'attachments'
15
15
  return { packet: pack, buffers: buffers };
16
16
  }
17
- function _deconstructPacket(data, buffers) {
17
+ function _deconstructPacket(data, buffers, toJSON) {
18
18
  if (!data)
19
19
  return data;
20
20
  if (isBinary(data)) {
@@ -30,6 +30,9 @@ function _deconstructPacket(data, buffers) {
30
30
  return newData;
31
31
  }
32
32
  else if (typeof data === "object" && !(data instanceof Date)) {
33
+ if (data.toJSON && typeof data.toJSON === "function" && !toJSON) {
34
+ return _deconstructPacket(data.toJSON(), buffers, true);
35
+ }
33
36
  const newData = {};
34
37
  for (const key in data) {
35
38
  if (Object.prototype.hasOwnProperty.call(data, key)) {
@@ -53,20 +53,30 @@ export declare class Encoder {
53
53
  interface DecoderReservedEvents {
54
54
  decoded: (packet: Packet) => void;
55
55
  }
56
+ type JSONReviver = (this: any, key: string, value: any) => any;
57
+ export interface DecoderOptions {
58
+ /**
59
+ * Custom reviver to pass down to JSON.parse()
60
+ */
61
+ reviver?: JSONReviver;
62
+ /**
63
+ * Maximum number of binary attachments per packet
64
+ * @default 10
65
+ */
66
+ maxAttachments?: number;
67
+ }
56
68
  /**
57
69
  * A socket.io Decoder instance
58
70
  *
59
71
  * @return {Object} decoder
60
72
  */
61
73
  export declare class Decoder extends Emitter<{}, {}, DecoderReservedEvents> {
62
- private reviver?;
63
74
  private reconstructor;
75
+ private opts;
64
76
  /**
65
77
  * Decoder constructor
66
- *
67
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
68
78
  */
69
- constructor(reviver?: (this: any, key: string, value: any) => any);
79
+ constructor(opts?: DecoderOptions | JSONReviver);
70
80
  /**
71
81
  * Decodes an encoded packet string into packet JSON.
72
82
  *
@@ -112,12 +112,13 @@ export class Encoder {
112
112
  export class Decoder extends Emitter {
113
113
  /**
114
114
  * Decoder constructor
115
- *
116
- * @param {function} reviver - custom reviver to pass down to JSON.stringify
117
115
  */
118
- constructor(reviver) {
116
+ constructor(opts) {
119
117
  super();
120
- this.reviver = reviver;
118
+ this.opts = Object.assign({
119
+ reviver: undefined,
120
+ maxAttachments: 10,
121
+ }, typeof opts === "function" ? { reviver: opts } : opts);
121
122
  }
122
123
  /**
123
124
  * Decodes an encoded packet string into packet JSON.
@@ -136,10 +137,6 @@ export class Decoder extends Emitter {
136
137
  packet.type = isBinaryEvent ? PacketType.EVENT : PacketType.ACK;
137
138
  // binary packet's json
138
139
  this.reconstructor = new BinaryReconstructor(packet);
139
- // no attachments, labeled binary but no binary data to follow
140
- if (packet.attachments === 0) {
141
- super.emitReserved("decoded", packet);
142
- }
143
140
  }
144
141
  else {
145
142
  // non-binary full packet
@@ -188,7 +185,14 @@ export class Decoder extends Emitter {
188
185
  if (buf != Number(buf) || str.charAt(i) !== "-") {
189
186
  throw new Error("Illegal attachments");
190
187
  }
191
- p.attachments = Number(buf);
188
+ const n = Number(buf);
189
+ if (!isInteger(n) || n < 1) {
190
+ throw new Error("Illegal attachments");
191
+ }
192
+ else if (n > this.opts.maxAttachments) {
193
+ throw new Error("too many attachments");
194
+ }
195
+ p.attachments = n;
192
196
  }
193
197
  // look up namespace (if any)
194
198
  if ("/" === str.charAt(i + 1)) {
@@ -235,7 +239,7 @@ export class Decoder extends Emitter {
235
239
  }
236
240
  tryParse(str) {
237
241
  try {
238
- return JSON.parse(str, this.reviver);
242
+ return JSON.parse(str, this.opts.reviver);
239
243
  }
240
244
  catch (e) {
241
245
  return false;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "socket.io-parser",
3
- "version": "4.2.5",
3
+ "version": "4.2.7",
4
4
  "description": "socket.io protocol parser",
5
5
  "homepage": "https://github.com/socketio/socket.io/tree/main/packages/socket.io-client#readme",
6
6
  "repository": {
@@ -1,13 +1,22 @@
1
1
  'use strict';
2
2
 
3
+ const createWebSocketStream = require('./lib/stream');
4
+ const extension = require('./lib/extension');
5
+ const PerMessageDeflate = require('./lib/permessage-deflate');
6
+ const Receiver = require('./lib/receiver');
7
+ const Sender = require('./lib/sender');
8
+ const subprotocol = require('./lib/subprotocol');
3
9
  const WebSocket = require('./lib/websocket');
10
+ const WebSocketServer = require('./lib/websocket-server');
4
11
 
5
- WebSocket.createWebSocketStream = require('./lib/stream');
6
- WebSocket.Server = require('./lib/websocket-server');
7
- WebSocket.Receiver = require('./lib/receiver');
8
- WebSocket.Sender = require('./lib/sender');
9
-
12
+ WebSocket.createWebSocketStream = createWebSocketStream;
13
+ WebSocket.extension = extension;
14
+ WebSocket.PerMessageDeflate = PerMessageDeflate;
15
+ WebSocket.Receiver = Receiver;
16
+ WebSocket.Sender = Sender;
17
+ WebSocket.Server = WebSocketServer;
18
+ WebSocket.subprotocol = subprotocol;
10
19
  WebSocket.WebSocket = WebSocket;
11
- WebSocket.WebSocketServer = WebSocket.Server;
20
+ WebSocket.WebSocketServer = WebSocketServer;
12
21
 
13
22
  module.exports = WebSocket;
@@ -7,6 +7,7 @@ if (hasBlob) BINARY_TYPES.push('blob');
7
7
 
8
8
  module.exports = {
9
9
  BINARY_TYPES,
10
+ CLOSE_TIMEOUT: 30000,
10
11
  EMPTY_BUFFER: Buffer.alloc(0),
11
12
  GUID: '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
12
13
  hasBlob,
@@ -37,6 +37,9 @@ class PerMessageDeflate {
37
37
  * acknowledge disabling of client context takeover
38
38
  * @param {Number} [options.concurrencyLimit=10] The number of concurrent
39
39
  * calls to zlib
40
+ * @param {Boolean} [options.isServer=false] Create the instance in either
41
+ * server or client mode
42
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
40
43
  * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
41
44
  * use of a custom server window size
42
45
  * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
@@ -47,16 +50,13 @@ class PerMessageDeflate {
47
50
  * deflate
48
51
  * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
49
52
  * inflate
50
- * @param {Boolean} [isServer=false] Create the instance in either server or
51
- * client mode
52
- * @param {Number} [maxPayload=0] The maximum allowed message length
53
53
  */
54
- constructor(options, isServer, maxPayload) {
55
- this._maxPayload = maxPayload | 0;
54
+ constructor(options) {
56
55
  this._options = options || {};
57
56
  this._threshold =
58
57
  this._options.threshold !== undefined ? this._options.threshold : 1024;
59
- this._isServer = !!isServer;
58
+ this._maxPayload = this._options.maxPayload | 0;
59
+ this._isServer = !!this._options.isServer;
60
60
  this._deflate = null;
61
61
  this._inflate = null;
62
62
 
@@ -167,7 +167,9 @@ class PerMessageDeflate {
167
167
  (typeof opts.serverMaxWindowBits === 'number' &&
168
168
  opts.serverMaxWindowBits > params.server_max_window_bits))) ||
169
169
  (typeof opts.clientMaxWindowBits === 'number' &&
170
- !params.client_max_window_bits)
170
+ (typeof params.client_max_window_bits === 'number'
171
+ ? opts.clientMaxWindowBits > params.client_max_window_bits
172
+ : !params.client_max_window_bits))
171
173
  ) {
172
174
  return false;
173
175
  }
@@ -40,6 +40,10 @@ class Receiver extends Writable {
40
40
  * extensions
41
41
  * @param {Boolean} [options.isServer=false] Specifies whether to operate in
42
42
  * client or server mode
43
+ * @param {Number} [options.maxBufferedChunks=0] The maximum number of
44
+ * buffered data chunks
45
+ * @param {Number} [options.maxFragments=0] The maximum number of message
46
+ * fragments
43
47
  * @param {Number} [options.maxPayload=0] The maximum allowed message length
44
48
  * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or
45
49
  * not to skip UTF-8 validation for text and close messages
@@ -54,6 +58,8 @@ class Receiver extends Writable {
54
58
  this._binaryType = options.binaryType || BINARY_TYPES[0];
55
59
  this._extensions = options.extensions || {};
56
60
  this._isServer = !!options.isServer;
61
+ this._maxBufferedChunks = options.maxBufferedChunks | 0;
62
+ this._maxFragments = options.maxFragments | 0;
57
63
  this._maxPayload = options.maxPayload | 0;
58
64
  this._skipUTF8Validation = !!options.skipUTF8Validation;
59
65
  this[kWebSocket] = undefined;
@@ -71,6 +77,7 @@ class Receiver extends Writable {
71
77
 
72
78
  this._totalPayloadLength = 0;
73
79
  this._messageLength = 0;
80
+ this._numFragments = 0;
74
81
  this._fragments = [];
75
82
 
76
83
  this._errored = false;
@@ -89,6 +96,22 @@ class Receiver extends Writable {
89
96
  _write(chunk, encoding, cb) {
90
97
  if (this._opcode === 0x08 && this._state == GET_INFO) return cb();
91
98
 
99
+ if (
100
+ this._maxBufferedChunks > 0 &&
101
+ this._buffers.length >= this._maxBufferedChunks
102
+ ) {
103
+ cb(
104
+ this.createError(
105
+ RangeError,
106
+ 'Too many buffered chunks',
107
+ false,
108
+ 1008,
109
+ 'WS_ERR_TOO_MANY_BUFFERED_PARTS'
110
+ )
111
+ );
112
+ return;
113
+ }
114
+
92
115
  this._bufferedBytes += chunk.length;
93
116
  this._buffers.push(chunk);
94
117
  this.startLoop(cb);
@@ -478,6 +501,19 @@ class Receiver extends Writable {
478
501
  return;
479
502
  }
480
503
 
504
+ if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) {
505
+ const error = this.createError(
506
+ RangeError,
507
+ 'Too many message fragments',
508
+ false,
509
+ 1008,
510
+ 'WS_ERR_TOO_MANY_BUFFERED_PARTS'
511
+ );
512
+
513
+ cb(error);
514
+ return;
515
+ }
516
+
481
517
  if (this._compressed) {
482
518
  this._state = INFLATING;
483
519
  this.decompress(data, cb);
@@ -550,6 +586,7 @@ class Receiver extends Writable {
550
586
  this._totalPayloadLength = 0;
551
587
  this._messageLength = 0;
552
588
  this._fragmented = 0;
589
+ this._numFragments = 0;
553
590
  this._fragments = [];
554
591
 
555
592
  if (this._opcode === 2) {
@@ -4,6 +4,9 @@
4
4
 
5
5
  const { Duplex } = require('stream');
6
6
  const { randomFillSync } = require('crypto');
7
+ const {
8
+ types: { isUint8Array }
9
+ } = require('util');
7
10
 
8
11
  const PerMessageDeflate = require('./permessage-deflate');
9
12
  const { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants');
@@ -200,8 +203,10 @@ class Sender {
200
203
 
201
204
  if (typeof data === 'string') {
202
205
  buf.write(data, 2);
203
- } else {
206
+ } else if (isUint8Array(data)) {
204
207
  buf.set(data, 2);
208
+ } else {
209
+ throw new TypeError('Second argument must be a string or a Uint8Array');
205
210
  }
206
211
  }
207
212
 
@@ -11,7 +11,7 @@ const extension = require('./extension');
11
11
  const PerMessageDeflate = require('./permessage-deflate');
12
12
  const subprotocol = require('./subprotocol');
13
13
  const WebSocket = require('./websocket');
14
- const { GUID, kWebSocket } = require('./constants');
14
+ const { CLOSE_TIMEOUT, GUID, kWebSocket } = require('./constants');
15
15
 
16
16
  const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
17
17
 
@@ -38,8 +38,15 @@ class WebSocketServer extends EventEmitter {
38
38
  * pending connections
39
39
  * @param {Boolean} [options.clientTracking=true] Specifies whether or not to
40
40
  * track clients
41
+ * @param {Number} [options.closeTimeout=30000] Duration in milliseconds to
42
+ * wait for the closing handshake to finish after `websocket.close()` is
43
+ * called
41
44
  * @param {Function} [options.handleProtocols] A hook to handle protocols
42
45
  * @param {String} [options.host] The hostname where to bind the server
46
+ * @param {Number} [options.maxBufferedChunks=262144] The maximum number of
47
+ * buffered data chunks
48
+ * @param {Number} [options.maxFragments=16384] The maximum number of message
49
+ * fragments
43
50
  * @param {Number} [options.maxPayload=104857600] The maximum allowed message
44
51
  * size
45
52
  * @param {Boolean} [options.noServer=false] Enable no server mode
@@ -62,11 +69,14 @@ class WebSocketServer extends EventEmitter {
62
69
  options = {
63
70
  allowSynchronousEvents: true,
64
71
  autoPong: true,
72
+ maxBufferedChunks: 256 * 1024,
73
+ maxFragments: 16 * 1024,
65
74
  maxPayload: 100 * 1024 * 1024,
66
75
  skipUTF8Validation: false,
67
76
  perMessageDeflate: false,
68
77
  handleProtocols: null,
69
78
  clientTracking: true,
79
+ closeTimeout: CLOSE_TIMEOUT,
70
80
  verifyClient: null,
71
81
  noServer: false,
72
82
  backlog: null, // use default (511 as implemented in net.js)
@@ -289,11 +299,11 @@ class WebSocketServer extends EventEmitter {
289
299
  this.options.perMessageDeflate &&
290
300
  secWebSocketExtensions !== undefined
291
301
  ) {
292
- const perMessageDeflate = new PerMessageDeflate(
293
- this.options.perMessageDeflate,
294
- true,
295
- this.options.maxPayload
296
- );
302
+ const perMessageDeflate = new PerMessageDeflate({
303
+ ...this.options.perMessageDeflate,
304
+ isServer: true,
305
+ maxPayload: this.options.maxPayload
306
+ });
297
307
 
298
308
  try {
299
309
  const offers = extension.parse(secWebSocketExtensions);
@@ -420,6 +430,8 @@ class WebSocketServer extends EventEmitter {
420
430
 
421
431
  ws.setSocket(socket, head, {
422
432
  allowSynchronousEvents: this.options.allowSynchronousEvents,
433
+ maxBufferedChunks: this.options.maxBufferedChunks,
434
+ maxFragments: this.options.maxFragments,
423
435
  maxPayload: this.options.maxPayload,
424
436
  skipUTF8Validation: this.options.skipUTF8Validation
425
437
  });