From 35d45c2a4fead953654ae7bcf029cdf6d2590121 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sun, 19 Dec 2021 20:49:13 +0100 Subject: [PATCH] [perf] Skip masking and unmasking if the masking key is zero --- lib/receiver.js | 8 +++++++- lib/sender.js | 32 ++++++++++++++++++++++---------- test/websocket.test.js | 11 +++++++---- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/lib/receiver.js b/lib/receiver.js index e11e26618..2d29d62bb 100644 --- a/lib/receiver.js +++ b/lib/receiver.js @@ -417,7 +417,13 @@ class Receiver extends Writable { } data = this.consume(this._payloadLength); - if (this._masked) unmask(data, this._mask); + + if ( + this._masked && + (this._mask[0] | this._mask[1] | this._mask[2] | this._mask[3]) !== 0 + ) { + unmask(data, this._mask); + } } if (this._opcode > 0x07) return this.controlMessage(data); diff --git a/lib/sender.js b/lib/sender.js index 82cc662d6..2417656d7 100644 --- a/lib/sender.js +++ b/lib/sender.js @@ -65,8 +65,26 @@ class Sender { * @public */ static frame(data, options) { - const merge = options.mask && options.readOnly; - let offset = options.mask ? 6 : 2; + let mask; + let merge = false; + let offset = 2; + let skipMasking = false; + + if (options.mask) { + mask = options.maskBuffer || maskBuffer; + + if (options.generateMask) { + options.generateMask(mask); + } else { + randomFillSync(mask, 0, 4); + } + + skipMasking = (mask[0] | mask[1] | mask[2] | mask[3]) === 0; + if (options.readOnly && !skipMasking) merge = true; + + offset = 6; + } + let payloadLength = data.length; if (data.length >= 65536) { @@ -93,20 +111,14 @@ class Sender { if (!options.mask) return [target, data]; - const mask = options.maskBuffer ? options.maskBuffer : maskBuffer; - - if (options.generateMask) { - options.generateMask(mask); - } else { - randomFillSync(mask, 0, 4); - } - target[1] |= 0x80; target[offset - 4] = mask[0]; target[offset - 3] = mask[1]; target[offset - 2] = mask[2]; target[offset - 1] = mask[3]; + if (skipMasking) return [target, data]; + if (merge) { applyMask(data, mask, target, offset, data.length); return [target]; diff --git a/test/websocket.test.js b/test/websocket.test.js index 5f9392d84..16cb33c55 100644 --- a/test/websocket.test.js +++ b/test/websocket.test.js @@ -128,13 +128,14 @@ describe('WebSocket', () => { }); it('honors the `generateMask` option', (done) => { + const data = Buffer.from('foo'); const wss = new WebSocket.Server({ port: 0 }, () => { const ws = new WebSocket(`ws://localhost:${wss.address().port}`, { generateMask() {} }); ws.on('open', () => { - ws.send('foo'); + ws.send(data); }); ws.on('close', (code, reason) => { @@ -152,9 +153,11 @@ describe('WebSocket', () => { chunks.push(chunk); }); - ws.on('message', () => { - assert.ok( - Buffer.concat(chunks).slice(2, 6).equals(Buffer.alloc(4)) + ws.on('message', (message) => { + assert.deepStrictEqual(message, data); + assert.deepStrictEqual( + Buffer.concat(chunks).slice(2, 6), + Buffer.alloc(4) ); ws.close();