diff --git a/assets/audio/music/main_menu.mp3 b/assets/audio/music/main_menu.mp3 index 9a2d4da..d34d169 100644 Binary files a/assets/audio/music/main_menu.mp3 and b/assets/audio/music/main_menu.mp3 differ diff --git a/server/node_modules/.package-lock.json b/server/node_modules/.package-lock.json index 96b8be0..89a120d 100644 --- a/server/node_modules/.package-lock.json +++ b/server/node_modules/.package-lock.json @@ -5,9 +5,10 @@ "requires": true, "packages": { "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, diff --git a/server/node_modules/ws/lib/permessage-deflate.js b/server/node_modules/ws/lib/permessage-deflate.js index aa5db76..c51d8f5 100644 --- a/server/node_modules/ws/lib/permessage-deflate.js +++ b/server/node_modules/ws/lib/permessage-deflate.js @@ -167,7 +167,9 @@ class PerMessageDeflate { (typeof opts.serverMaxWindowBits === 'number' && opts.serverMaxWindowBits > params.server_max_window_bits))) || (typeof opts.clientMaxWindowBits === 'number' && - !params.client_max_window_bits) + (typeof params.client_max_window_bits === 'number' + ? opts.clientMaxWindowBits > params.client_max_window_bits + : !params.client_max_window_bits)) ) { return false; } diff --git a/server/node_modules/ws/lib/receiver.js b/server/node_modules/ws/lib/receiver.js index 54d9b4f..784dbe1 100644 --- a/server/node_modules/ws/lib/receiver.js +++ b/server/node_modules/ws/lib/receiver.js @@ -40,6 +40,10 @@ class Receiver extends Writable { * extensions * @param {Boolean} [options.isServer=false] Specifies whether to operate in * client or server mode + * @param {Number} [options.maxBufferedChunks=0] The maximum number of + * buffered data chunks + * @param {Number} [options.maxFragments=0] The maximum number of message + * fragments * @param {Number} [options.maxPayload=0] The maximum allowed message length * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or * not to skip UTF-8 validation for text and close messages @@ -54,6 +58,8 @@ class Receiver extends Writable { this._binaryType = options.binaryType || BINARY_TYPES[0]; this._extensions = options.extensions || {}; this._isServer = !!options.isServer; + this._maxBufferedChunks = options.maxBufferedChunks | 0; + this._maxFragments = options.maxFragments | 0; this._maxPayload = options.maxPayload | 0; this._skipUTF8Validation = !!options.skipUTF8Validation; this[kWebSocket] = undefined; @@ -71,6 +77,7 @@ class Receiver extends Writable { this._totalPayloadLength = 0; this._messageLength = 0; + this._numFragments = 0; this._fragments = []; this._errored = false; @@ -89,6 +96,22 @@ class Receiver extends Writable { _write(chunk, encoding, cb) { if (this._opcode === 0x08 && this._state == GET_INFO) return cb(); + if ( + this._maxBufferedChunks > 0 && + this._buffers.length >= this._maxBufferedChunks + ) { + cb( + this.createError( + RangeError, + 'Too many buffered chunks', + false, + 1008, + 'WS_ERR_TOO_MANY_BUFFERED_PARTS' + ) + ); + return; + } + this._bufferedBytes += chunk.length; this._buffers.push(chunk); this.startLoop(cb); @@ -478,6 +501,19 @@ class Receiver extends Writable { return; } + if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) { + const error = this.createError( + RangeError, + 'Too many message fragments', + false, + 1008, + 'WS_ERR_TOO_MANY_BUFFERED_PARTS' + ); + + cb(error); + return; + } + if (this._compressed) { this._state = INFLATING; this.decompress(data, cb); @@ -550,6 +586,7 @@ class Receiver extends Writable { this._totalPayloadLength = 0; this._messageLength = 0; this._fragmented = 0; + this._numFragments = 0; this._fragments = []; if (this._opcode === 2) { diff --git a/server/node_modules/ws/lib/sender.js b/server/node_modules/ws/lib/sender.js index a8b1da3..2c767e2 100644 --- a/server/node_modules/ws/lib/sender.js +++ b/server/node_modules/ws/lib/sender.js @@ -4,6 +4,9 @@ const { Duplex } = require('stream'); const { randomFillSync } = require('crypto'); +const { + types: { isUint8Array } +} = require('util'); const PerMessageDeflate = require('./permessage-deflate'); const { EMPTY_BUFFER, kWebSocket, NOOP } = require('./constants'); @@ -200,8 +203,10 @@ class Sender { if (typeof data === 'string') { buf.write(data, 2); - } else { + } else if (isUint8Array(data)) { buf.set(data, 2); + } else { + throw new TypeError('Second argument must be a string or a Uint8Array'); } } diff --git a/server/node_modules/ws/lib/websocket-server.js b/server/node_modules/ws/lib/websocket-server.js index 68aa789..4d85919 100644 --- a/server/node_modules/ws/lib/websocket-server.js +++ b/server/node_modules/ws/lib/websocket-server.js @@ -43,6 +43,10 @@ class WebSocketServer extends EventEmitter { * called * @param {Function} [options.handleProtocols] A hook to handle protocols * @param {String} [options.host] The hostname where to bind the server + * @param {Number} [options.maxBufferedChunks=262144] The maximum number of + * buffered data chunks + * @param {Number} [options.maxFragments=16384] The maximum number of message + * fragments * @param {Number} [options.maxPayload=104857600] The maximum allowed message * size * @param {Boolean} [options.noServer=false] Enable no server mode @@ -65,6 +69,8 @@ class WebSocketServer extends EventEmitter { options = { allowSynchronousEvents: true, autoPong: true, + maxBufferedChunks: 256 * 1024, + maxFragments: 16 * 1024, maxPayload: 100 * 1024 * 1024, skipUTF8Validation: false, perMessageDeflate: false, @@ -424,6 +430,8 @@ class WebSocketServer extends EventEmitter { ws.setSocket(socket, head, { allowSynchronousEvents: this.options.allowSynchronousEvents, + maxBufferedChunks: this.options.maxBufferedChunks, + maxFragments: this.options.maxFragments, maxPayload: this.options.maxPayload, skipUTF8Validation: this.options.skipUTF8Validation }); diff --git a/server/node_modules/ws/lib/websocket.js b/server/node_modules/ws/lib/websocket.js index 75d5bb2..52cfd16 100644 --- a/server/node_modules/ws/lib/websocket.js +++ b/server/node_modules/ws/lib/websocket.js @@ -75,11 +75,24 @@ class WebSocket extends EventEmitter { this._redirects = 0; if (protocols === undefined) { - protocols = []; + if (!options || options.protocols === undefined) { + protocols = []; + } else if (Array.isArray(options.protocols)) { + protocols = options.protocols; + } else { + protocols = [options.protocols]; + } } else if (!Array.isArray(protocols)) { if (typeof protocols === 'object' && protocols !== null) { options = protocols; - protocols = []; + + if (options.protocols === undefined) { + protocols = []; + } else if (Array.isArray(options.protocols)) { + protocols = options.protocols; + } else { + protocols = [options.protocols]; + } } else { protocols = [protocols]; } @@ -201,6 +214,10 @@ class WebSocket extends EventEmitter { * multiple times in the same tick * @param {Function} [options.generateMask] The function used to generate the * masking key + * @param {Number} [options.maxBufferedChunks=0] The maximum number of + * buffered data chunks + * @param {Number} [options.maxFragments=0] The maximum number of message + * fragments * @param {Number} [options.maxPayload=0] The maximum allowed message size * @param {Boolean} [options.skipUTF8Validation=false] Specifies whether or * not to skip UTF-8 validation for text and close messages @@ -212,6 +229,8 @@ class WebSocket extends EventEmitter { binaryType: this.binaryType, extensions: this._extensions, isServer: this._isServer, + maxBufferedChunks: options.maxBufferedChunks, + maxFragments: options.maxFragments, maxPayload: options.maxPayload, skipUTF8Validation: options.skipUTF8Validation }); @@ -312,7 +331,6 @@ class WebSocket extends EventEmitter { return; } - this._readyState = WebSocket.CLOSING; this._sender.close(code, data, !this._isServer, (err) => { // // This error is handled by the `'error'` listener on the socket. We only @@ -330,6 +348,7 @@ class WebSocket extends EventEmitter { } }); + this._readyState = WebSocket.CLOSING; setCloseTimer(this); } @@ -640,6 +659,10 @@ module.exports = WebSocket; * masking key * @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the * handshake request + * @param {Number} [options.maxBufferedChunks=262144] The maximum number of + * buffered data chunks + * @param {Number} [options.maxFragments=16384] The maximum number of message + * fragments * @param {Number} [options.maxPayload=104857600] The maximum allowed message * size * @param {Number} [options.maxRedirects=10] The maximum number of redirects @@ -660,6 +683,8 @@ function initAsClient(websocket, address, protocols, options) { autoPong: true, closeTimeout: CLOSE_TIMEOUT, protocolVersion: protocolVersions[1], + maxBufferedChunks: 256 * 1024, + maxFragments: 16 * 1024, maxPayload: 100 * 1024 * 1024, skipUTF8Validation: false, perMessageDeflate: true, @@ -669,6 +694,7 @@ function initAsClient(websocket, address, protocols, options) { socketPath: undefined, hostname: undefined, protocol: undefined, + protocols: undefined, timeout: undefined, method: 'GET', host: undefined, @@ -1017,6 +1043,8 @@ function initAsClient(websocket, address, protocols, options) { websocket.setSocket(socket, head, { allowSynchronousEvents: opts.allowSynchronousEvents, generateMask: opts.generateMask, + maxBufferedChunks: opts.maxBufferedChunks, + maxFragments: opts.maxFragments, maxPayload: opts.maxPayload, skipUTF8Validation: opts.skipUTF8Validation }); diff --git a/server/node_modules/ws/package.json b/server/node_modules/ws/package.json index 3618050..3dad931 100644 --- a/server/node_modules/ws/package.json +++ b/server/node_modules/ws/package.json @@ -1,6 +1,6 @@ { "name": "ws", - "version": "8.20.0", + "version": "8.22.0", "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", "keywords": [ "HyBi", @@ -66,5 +66,9 @@ "nyc": "^15.0.0", "prettier": "^3.0.0", "utf-8-validate": "^6.0.0" + }, + "allowScripts": { + "bufferutil": true, + "utf-8-validate": true } } diff --git a/server/package-lock.json b/server/package-lock.json index 4599bae..a43d05f 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -8,13 +8,14 @@ "name": "ipuzzle-server", "version": "1.0.0", "dependencies": { - "ws": "^8.18.0" + "ws": "^8.22.0" } }, "node_modules/ws": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", - "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "license": "MIT", "engines": { "node": ">=10.0.0" }, diff --git a/server/package.json b/server/package.json index e72ceac..39c5c39 100644 --- a/server/package.json +++ b/server/package.json @@ -4,6 +4,6 @@ "description": "iPuzzle multiplayer WebSocket server", "main": "server.js", "dependencies": { - "ws": "^8.18.0" + "ws": "^8.22.0" } }