@@ -2052,13 +2052,20 @@ var require_dispatcher_base = __commonJS({
20522052 var kOnDestroyed = Symbol("onDestroyed");
20532053 var kOnClosed = Symbol("onClosed");
20542054 var kInterceptedDispatch = Symbol("Intercepted Dispatch");
2055+ var kWebSocketOptions = Symbol("webSocketOptions");
20552056 var DispatcherBase = class extends Dispatcher {
2056- constructor() {
2057+ constructor(opts ) {
20572058 super();
20582059 this[kDestroyed] = false;
20592060 this[kOnDestroyed] = null;
20602061 this[kClosed] = false;
20612062 this[kOnClosed] = [];
2063+ this[kWebSocketOptions] = opts?.webSocket ?? {};
2064+ }
2065+ get webSocketOptions() {
2066+ return {
2067+ maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024
2068+ };
20622069 }
20632070 get destroyed() {
20642071 return this[kDestroyed];
@@ -7491,9 +7498,10 @@ var require_client = __commonJS({
74917498 autoSelectFamilyAttemptTimeout,
74927499 // h2
74937500 maxConcurrentStreams,
7494- allowH2
7501+ allowH2,
7502+ webSocket
74957503 } = {}) {
7496- super();
7504+ super({ webSocket } );
74977505 if (keepAlive !== void 0) {
74987506 throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead");
74997507 }
@@ -7999,8 +8007,8 @@ var require_pool_base = __commonJS({
79998007 var kRemoveClient = Symbol("remove client");
80008008 var kStats = Symbol("stats");
80018009 var PoolBase = class extends DispatcherBase {
8002- constructor() {
8003- super();
8010+ constructor(opts ) {
8011+ super(opts );
80048012 this[kQueue] = new FixedQueue();
80058013 this[kClients] = [];
80068014 this[kQueued] = 0;
@@ -8171,7 +8179,6 @@ var require_pool = __commonJS({
81718179 allowH2,
81728180 ...options
81738181 } = {}) {
8174- super();
81758182 if (connections != null && (!Number.isFinite(connections) || connections < 0)) {
81768183 throw new InvalidArgumentError("invalid connections");
81778184 }
@@ -8192,6 +8199,7 @@ var require_pool = __commonJS({
81928199 ...connect
81938200 });
81948201 }
8202+ super(options);
81958203 this[kInterceptors] = options.interceptors?.Pool && Array.isArray(options.interceptors.Pool) ? options.interceptors.Pool : [];
81968204 this[kConnections] = connections || null;
81978205 this[kUrl] = util.parseOrigin(origin);
@@ -8392,7 +8400,6 @@ var require_agent = __commonJS({
83928400 }
83938401 var Agent = class extends DispatcherBase {
83948402 constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) {
8395- super();
83968403 if (typeof factory !== "function") {
83978404 throw new InvalidArgumentError("factory must be a function.");
83988405 }
@@ -8402,6 +8409,7 @@ var require_agent = __commonJS({
84028409 if (!Number.isInteger(maxRedirections) || maxRedirections < 0) {
84038410 throw new InvalidArgumentError("maxRedirections must be a positive number");
84048411 }
8412+ super(options);
84058413 if (connect && typeof connect !== "function") {
84068414 connect = { ...connect };
84078415 }
@@ -17041,27 +17049,26 @@ var require_permessage_deflate = __commonJS({
1704117049 var tail = Buffer.from([0, 0, 255, 255]);
1704217050 var kBuffer = Symbol("kBuffer");
1704317051 var kLength = Symbol("kLength");
17044- var kDefaultMaxDecompressedSize = 4 * 1024 * 1024;
1704517052 var PerMessageDeflate = class {
1704617053 /** @type {import('node:zlib').InflateRaw} */
1704717054 #inflate;
1704817055 #options = {};
17049- /** @type {boolean} */
17050- #aborted = false;
17051- /** @type {Function|null} */
17052- #currentCallback = null;
17056+ #maxPayloadSize = 0;
1705317057 /**
1705417058 * @param {Map<string, string>} extensions
1705517059 */
17056- constructor(extensions) {
17060+ constructor(extensions, options ) {
1705717061 this.#options.serverNoContextTakeover = extensions.has("server_no_context_takeover");
1705817062 this.#options.serverMaxWindowBits = extensions.get("server_max_window_bits");
17063+ this.#maxPayloadSize = options.maxPayloadSize;
1705917064 }
17065+ /**
17066+ * Decompress a compressed payload.
17067+ * @param {Buffer} chunk Compressed data
17068+ * @param {boolean} fin Final fragment flag
17069+ * @param {Function} callback Callback function
17070+ */
1706017071 decompress(chunk, fin, callback) {
17061- if (this.#aborted) {
17062- callback(new MessageSizeExceededError());
17063- return;
17064- }
1706517072 if (!this.#inflate) {
1706617073 let windowBits = Z_DEFAULT_WINDOWBITS;
1706717074 if (this.#options.serverMaxWindowBits) {
@@ -17080,20 +17087,11 @@ var require_permessage_deflate = __commonJS({
1708017087 this.#inflate[kBuffer] = [];
1708117088 this.#inflate[kLength] = 0;
1708217089 this.#inflate.on("data", (data) => {
17083- if (this.#aborted) {
17084- return;
17085- }
1708617090 this.#inflate[kLength] += data.length;
17087- if (this.#inflate[kLength] > kDefaultMaxDecompressedSize ) {
17088- this.#aborted = true ;
17091+ if (this.#maxPayloadSize > 0 && this.# inflate[kLength] > this.#maxPayloadSize ) {
17092+ callback(new MessageSizeExceededError()) ;
1708917093 this.#inflate.removeAllListeners();
17090- this.#inflate.destroy();
1709117094 this.#inflate = null;
17092- if (this.#currentCallback) {
17093- const cb = this.#currentCallback;
17094- this.#currentCallback = null;
17095- cb(new MessageSizeExceededError());
17096- }
1709717095 return;
1709817096 }
1709917097 this.#inflate[kBuffer].push(data);
@@ -17103,19 +17101,17 @@ var require_permessage_deflate = __commonJS({
1710317101 callback(err);
1710417102 });
1710517103 }
17106- this.#currentCallback = callback;
1710717104 this.#inflate.write(chunk);
1710817105 if (fin) {
1710917106 this.#inflate.write(tail);
1711017107 }
1711117108 this.#inflate.flush(() => {
17112- if (this.#aborted || !this.#inflate) {
17109+ if (!this.#inflate) {
1711317110 return;
1711417111 }
1711517112 const full = Buffer.concat(this.#inflate[kBuffer], this.#inflate[kLength]);
1711617113 this.#inflate[kBuffer].length = 0;
1711717114 this.#inflate[kLength] = 0;
17118- this.#currentCallback = null;
1711917115 callback(null, full);
1712017116 });
1712117117 }
@@ -17146,25 +17142,31 @@ var require_receiver = __commonJS({
1714617142 var { WebsocketFrameSend } = require_frame();
1714717143 var { closeWebSocketConnection } = require_connection();
1714817144 var { PerMessageDeflate } = require_permessage_deflate();
17145+ var { MessageSizeExceededError } = require_errors();
1714917146 var ByteParser = class extends Writable {
1715017147 #buffers = [];
17148+ #fragmentsBytes = 0;
1715117149 #byteOffset = 0;
1715217150 #loop = false;
1715317151 #state = parserStates.INFO;
1715417152 #info = {};
1715517153 #fragments = [];
1715617154 /** @type {Map<string, PerMessageDeflate>} */
1715717155 #extensions;
17156+ /** @type {number} */
17157+ #maxPayloadSize;
1715817158 /**
1715917159 * @param {import('./websocket').WebSocket} ws
1716017160 * @param {Map<string, string>|null} extensions
17161+ * @param {{ maxPayloadSize?: number }} [options]
1716117162 */
17162- constructor(ws, extensions) {
17163+ constructor(ws, extensions, options = {} ) {
1716317164 super();
1716417165 this.ws = ws;
1716517166 this.#extensions = extensions == null ? /* @__PURE__ */ new Map() : extensions;
17167+ this.#maxPayloadSize = options.maxPayloadSize ?? 0;
1716617168 if (this.#extensions.has("permessage-deflate")) {
17167- this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions));
17169+ this.#extensions.set("permessage-deflate", new PerMessageDeflate(extensions, options ));
1716817170 }
1716917171 }
1717017172 /**
@@ -17177,6 +17179,13 @@ var require_receiver = __commonJS({
1717717179 this.#loop = true;
1717817180 this.run(callback);
1717917181 }
17182+ #validatePayloadLength() {
17183+ if (this.#maxPayloadSize > 0 && !isControlFrame(this.#info.opcode) && this.#info.payloadLength > this.#maxPayloadSize) {
17184+ failWebsocketConnection(this.ws, "Payload size exceeds maximum allowed size");
17185+ return false;
17186+ }
17187+ return true;
17188+ }
1718017189 /**
1718117190 * Runs whenever a new chunk is received.
1718217191 * Callback is called whenever there are no more chunks buffering,
@@ -17236,6 +17245,9 @@ var require_receiver = __commonJS({
1723617245 if (payloadLength <= 125) {
1723717246 this.#info.payloadLength = payloadLength;
1723817247 this.#state = parserStates.READ_DATA;
17248+ if (!this.#validatePayloadLength()) {
17249+ return;
17250+ }
1723917251 } else if (payloadLength === 126) {
1724017252 this.#state = parserStates.PAYLOADLENGTH_16;
1724117253 } else if (payloadLength === 127) {
@@ -17256,6 +17268,9 @@ var require_receiver = __commonJS({
1725617268 const buffer = this.consume(2);
1725717269 this.#info.payloadLength = buffer.readUInt16BE(0);
1725817270 this.#state = parserStates.READ_DATA;
17271+ if (!this.#validatePayloadLength()) {
17272+ return;
17273+ }
1725917274 } else if (this.#state === parserStates.PAYLOADLENGTH_64) {
1726017275 if (this.#byteOffset < 8) {
1726117276 return callback();
@@ -17269,6 +17284,9 @@ var require_receiver = __commonJS({
1726917284 }
1727017285 this.#info.payloadLength = lower;
1727117286 this.#state = parserStates.READ_DATA;
17287+ if (!this.#validatePayloadLength()) {
17288+ return;
17289+ }
1727217290 } else if (this.#state === parserStates.READ_DATA) {
1727317291 if (this.#byteOffset < this.#info.payloadLength) {
1727417292 return callback();
@@ -17279,32 +17297,41 @@ var require_receiver = __commonJS({
1727917297 this.#state = parserStates.INFO;
1728017298 } else {
1728117299 if (!this.#info.compressed) {
17282- this.#fragments.push(body);
17300+ this.writeFragments(body);
17301+ if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
17302+ failWebsocketConnection(this.ws, new MessageSizeExceededError().message);
17303+ return;
17304+ }
1728317305 if (!this.#info.fragmented && this.#info.fin) {
17284- const fullMessage = Buffer.concat(this.#fragments);
17285- websocketMessageReceived(this.ws, this.#info.binaryType, fullMessage);
17286- this.#fragments.length = 0;
17306+ websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments());
1728717307 }
1728817308 this.#state = parserStates.INFO;
1728917309 } else {
17290- this.#extensions.get("permessage-deflate").decompress(body, this.#info.fin, (error2, data) => {
17291- if (error2) {
17292- failWebsocketConnection(this.ws, error2.message);
17293- return;
17294- }
17295- this.#fragments.push(data);
17296- if (!this.#info.fin) {
17297- this.#state = parserStates.INFO;
17310+ this.#extensions.get("permessage-deflate").decompress(
17311+ body,
17312+ this.#info.fin,
17313+ (error2, data) => {
17314+ if (error2) {
17315+ failWebsocketConnection(this.ws, error2.message);
17316+ return;
17317+ }
17318+ this.writeFragments(data);
17319+ if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
17320+ failWebsocketConnection(this.ws, new MessageSizeExceededError().message);
17321+ return;
17322+ }
17323+ if (!this.#info.fin) {
17324+ this.#state = parserStates.INFO;
17325+ this.#loop = true;
17326+ this.run(callback);
17327+ return;
17328+ }
17329+ websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments());
1729817330 this.#loop = true;
17331+ this.#state = parserStates.INFO;
1729917332 this.run(callback);
17300- return;
1730117333 }
17302- websocketMessageReceived(this.ws, this.#info.binaryType, Buffer.concat(this.#fragments));
17303- this.#loop = true;
17304- this.#state = parserStates.INFO;
17305- this.#fragments.length = 0;
17306- this.run(callback);
17307- });
17334+ );
1730817335 this.#loop = false;
1730917336 break;
1731017337 }
@@ -17347,6 +17374,21 @@ var require_receiver = __commonJS({
1734717374 this.#byteOffset -= n;
1734817375 return buffer;
1734917376 }
17377+ writeFragments(fragment) {
17378+ this.#fragmentsBytes += fragment.length;
17379+ this.#fragments.push(fragment);
17380+ }
17381+ consumeFragments() {
17382+ const fragments = this.#fragments;
17383+ if (fragments.length === 1) {
17384+ this.#fragmentsBytes = 0;
17385+ return fragments.shift();
17386+ }
17387+ const output = Buffer.concat(fragments, this.#fragmentsBytes);
17388+ this.#fragments = [];
17389+ this.#fragmentsBytes = 0;
17390+ return output;
17391+ }
1735017392 parseCloseBody(data) {
1735117393 assert2(data.length !== 1);
1735217394 let code;
@@ -17784,7 +17826,10 @@ var require_websocket = __commonJS({
1778417826 */
1778517827 #onConnectionEstablished(response, parsedExtensions) {
1778617828 this[kResponse] = response;
17787- const parser2 = new ByteParser(this, parsedExtensions);
17829+ const maxPayloadSize = this[kController]?.dispatcher?.webSocketOptions?.maxPayloadSize;
17830+ const parser2 = new ByteParser(this, parsedExtensions, {
17831+ maxPayloadSize
17832+ });
1778817833 parser2.on("drain", onParserDrain);
1778917834 parser2.on("error", onParserError.bind(this));
1779017835 response.socket.ws = this;
0 commit comments