node_modules: update (#146)

Co-authored-by: dawidd6 <9713907+dawidd6@users.noreply.github.com>
This commit is contained in:
Dawid Dziurla
2026-08-07 08:08:41 +02:00
committed by GitHub
co-authored by dawidd6
parent 6b3dfab4e0
commit 3d5a3a75cc
44 changed files with 660 additions and 284 deletions
+106 -25
View File
@@ -18,6 +18,12 @@ const {
const { WebsocketFrameSend } = require('./frame')
const { closeWebSocketConnection } = require('./connection')
const { PerMessageDeflate } = require('./permessage-deflate')
const { MessageSizeExceededError } = require('../../core/errors')
function failWebsocketConnectionWithCode (ws, code, reason) {
closeWebSocketConnection(ws, code, reason, Buffer.byteLength(reason))
failWebsocketConnection(ws, reason)
}
// This code was influenced by ws released under the MIT license.
// Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
@@ -26,6 +32,7 @@ const { PerMessageDeflate } = require('./permessage-deflate')
class ByteParser extends Writable {
#buffers = []
#fragmentsBytes = 0
#byteOffset = 0
#loop = false
@@ -37,20 +44,24 @@ class ByteParser extends Writable {
/** @type {Map<string, PerMessageDeflate>} */
#extensions
/** @type {{ maxDecompressedMessageSize?: number }} */
#options
/** @type {number} */
#maxFragments
/** @type {number} */
#maxPayloadSize
/**
* @param {import('./websocket').WebSocket} ws
* @param {Map<string, string>|null} extensions
* @param {{ maxDecompressedMessageSize?: number }} [options]
* @param {{ maxFragments?: number, maxPayloadSize?: number }} [options]
*/
constructor (ws, extensions, options = {}) {
super()
this.ws = ws
this.#extensions = extensions == null ? new Map() : extensions
this.#options = options
this.#maxFragments = options.maxFragments ?? 0
this.#maxPayloadSize = options.maxPayloadSize ?? 0
if (this.#extensions.has('permessage-deflate')) {
this.#extensions.set('permessage-deflate', new PerMessageDeflate(extensions, options))
@@ -69,6 +80,19 @@ class ByteParser extends Writable {
this.run(callback)
}
#validatePayloadLength () {
if (
this.#maxPayloadSize > 0 &&
!isControlFrame(this.#info.opcode) &&
this.#info.payloadLength + this.#fragmentsBytes > this.#maxPayloadSize
) {
failWebsocketConnectionWithCode(this.ws, 1009, 'Payload size exceeds maximum allowed size')
return false
}
return true
}
/**
* Runs whenever a new chunk is received.
* Callback is called whenever there are no more chunks buffering,
@@ -157,6 +181,10 @@ class ByteParser extends Writable {
if (payloadLength <= 125) {
this.#info.payloadLength = payloadLength
this.#state = parserStates.READ_DATA
if (!this.#validatePayloadLength()) {
return
}
} else if (payloadLength === 126) {
this.#state = parserStates.PAYLOADLENGTH_16
} else if (payloadLength === 127) {
@@ -181,6 +209,10 @@ class ByteParser extends Writable {
this.#info.payloadLength = buffer.readUInt16BE(0)
this.#state = parserStates.READ_DATA
if (!this.#validatePayloadLength()) {
return
}
} else if (this.#state === parserStates.PAYLOADLENGTH_64) {
if (this.#byteOffset < 8) {
return callback()
@@ -203,6 +235,10 @@ class ByteParser extends Writable {
this.#info.payloadLength = lower
this.#state = parserStates.READ_DATA
if (!this.#validatePayloadLength()) {
return
}
} else if (this.#state === parserStates.READ_DATA) {
if (this.#byteOffset < this.#info.payloadLength) {
return callback()
@@ -215,42 +251,58 @@ class ByteParser extends Writable {
this.#state = parserStates.INFO
} else {
if (!this.#info.compressed) {
this.#fragments.push(body)
if (!this.writeFragments(body)) {
return
}
if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message)
return
}
// If the frame is not fragmented, a message has been received.
// If the frame is fragmented, it will terminate with a fin bit set
// and an opcode of 0 (continuation), therefore we handle that when
// parsing continuation frames, not here.
if (!this.#info.fragmented && this.#info.fin) {
const fullMessage = Buffer.concat(this.#fragments)
websocketMessageReceived(this.ws, this.#info.binaryType, fullMessage)
this.#fragments.length = 0
websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments())
}
this.#state = parserStates.INFO
} else {
this.#extensions.get('permessage-deflate').decompress(body, this.#info.fin, (error, data) => {
if (error) {
failWebsocketConnection(this.ws, error.message)
return
}
this.#extensions.get('permessage-deflate').decompress(
body,
this.#info.fin,
(error, data) => {
if (error) {
const code = error instanceof MessageSizeExceededError ? 1009 : 1007
failWebsocketConnectionWithCode(this.ws, code, error.message)
return
}
this.#fragments.push(data)
if (!this.writeFragments(data)) {
return
}
if (this.#maxPayloadSize > 0 && this.#fragmentsBytes > this.#maxPayloadSize) {
failWebsocketConnectionWithCode(this.ws, 1009, new MessageSizeExceededError().message)
return
}
if (!this.#info.fin) {
this.#state = parserStates.INFO
this.#loop = true
this.run(callback)
return
}
websocketMessageReceived(this.ws, this.#info.binaryType, this.consumeFragments())
if (!this.#info.fin) {
this.#state = parserStates.INFO
this.#loop = true
this.#state = parserStates.INFO
this.run(callback)
return
}
websocketMessageReceived(this.ws, this.#info.binaryType, Buffer.concat(this.#fragments))
this.#loop = true
this.#state = parserStates.INFO
this.#fragments.length = 0
this.run(callback)
})
)
this.#loop = false
break
@@ -302,6 +354,35 @@ class ByteParser extends Writable {
return buffer
}
writeFragments (fragment) {
if (
this.#maxFragments > 0 &&
this.#fragments.length === this.#maxFragments
) {
failWebsocketConnectionWithCode(this.ws, 1008, 'Too many message fragments')
return false
}
this.#fragmentsBytes += fragment.length
this.#fragments.push(fragment)
return true
}
consumeFragments () {
const fragments = this.#fragments
if (fragments.length === 1) {
this.#fragmentsBytes = 0
return fragments.shift()
}
const output = Buffer.concat(fragments, this.#fragmentsBytes)
this.#fragments = []
this.#fragmentsBytes = 0
return output
}
parseCloseBody (data) {
assert(data.length !== 1)