From dc381b72c6b2f8172001dedd84116122e4cc95b3 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Mon, 10 May 2021 11:05:28 +0200 Subject: [PATCH] perf: add support for the "wsPreEncoded" writing option Packets that are sent to multiple clients will now be pre-encoded for the WebSocket transport (which means simply prepending "4" - which is the "message" packet type in Engine.IO). Note: buffers are not pre-encoded, since they are sent without modification over the WebSocket connection See also: https://github.com/socketio/engine.io/commit/7706b123df914777d19c8179b45ab6932f82916c engine.io diff: https://github.com/socketio/engine.io/compare/5.0.0...5.1.0 --- lib/client.ts | 47 +++++++++++++++++++++++++---------------------- package-lock.json | 12 ++++++------ package.json | 4 ++-- test/socket.io.ts | 22 ++++++++++++++++++++++ 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/lib/client.ts b/lib/client.ts index 7d4ef9151e..3693744cce 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -10,6 +10,12 @@ import type { SocketId } from "socket.io-adapter"; const debug = debugModule("socket.io:client"); +interface WriteOptions { + compress?: boolean; + volatile?: boolean; + wsPreEncoded?: string; +} + export class Client< ListenEvents extends EventsMap, EmitEvents extends EventsMap @@ -180,31 +186,28 @@ export class Client< * @param {Object} opts * @private */ - _packet(packet: Packet, opts?: any): void { - opts = opts || {}; - const self = this; - - // this writes to the actual connection - function writeToEngine(encodedPackets: any) { - // TODO clarify this. - if (opts.volatile && !self.conn.transport.writable) return; - for (let i = 0; i < encodedPackets.length; i++) { - self.conn.write(encodedPackets[i], { compress: opts.compress }); - } + _packet(packet: Packet, opts: WriteOptions = {}): void { + if (this.conn.readyState !== "open") { + debug("ignoring packet write %j", packet); + return; + } + const encodedPackets = this.encoder.encode(packet); + for (const encodedPacket of encodedPackets) { + this.writeToEngine(encodedPacket, opts); } + } - if ("open" === this.conn.readyState) { - debug("writing packet %j", packet); - if (!opts.preEncoded) { - // not broadcasting, need to encode - writeToEngine(this.encoder.encode(packet)); // encode, then write results to engine - } else { - // a broadcast pre-encodes a packet - writeToEngine(packet); - } - } else { - debug("ignoring packet write %j", packet); + private writeToEngine( + encodedPacket: String | Buffer, + opts: WriteOptions + ): void { + if (opts.volatile && !this.conn.transport.writable) { + debug( + "volatile packet is discarded since the transport is not currently writable" + ); + return; } + this.conn.write(encodedPacket, opts); } /** diff --git a/package-lock.json b/package-lock.json index 48a47caf31..0aeea39007 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1206,9 +1206,9 @@ } }, "engine.io": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.0.0.tgz", - "integrity": "sha512-BATIdDV3H1SrE9/u2BAotvsmjJg0t1P4+vGedImSs1lkFAtQdvk4Ev1y4LDiPF7BPWgXWEG+NDY+nLvW3UrMWw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-5.1.0.tgz", + "integrity": "sha512-A2i4kVvOA3qezQLlMz+FayGFdqOo0LP3fYrb0VqXMDXKoXcbgM0KxcEYnsdVzOMJQErIAb1GIStRj7UWFoiqlQ==", "requires": { "accepts": "~1.3.4", "base64id": "2.0.0", @@ -3330,9 +3330,9 @@ } }, "socket.io-adapter": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.2.0.tgz", - "integrity": "sha512-rG49L+FwaVEwuAdeBRq49M97YI3ElVabJPzvHT9S6a2CWhDKnjSFasvwAwSYPRhQzfn4NtDIbCaGYgOCOU/rlg==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.0.tgz", + "integrity": "sha512-jdIbSFRWOkaZpo5mXy8T7rXEN6qo3bOFuq4nVeX1ZS7AtFlkbk39y153xTXEIW7W94vZfhVOux1wTU88YxcM1w==" }, "socket.io-client": { "version": "4.0.2", diff --git a/package.json b/package.json index 1ae020879c..5f62de0bf6 100644 --- a/package.json +++ b/package.json @@ -51,8 +51,8 @@ "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.1", - "engine.io": "~5.0.0", - "socket.io-adapter": "~2.2.0", + "engine.io": "~5.1.0", + "socket.io-adapter": "~2.3.0", "socket.io-parser": "~4.0.3" }, "devDependencies": { diff --git a/test/socket.io.ts b/test/socket.io.ts index 48f4a76cee..84c57d1acb 100644 --- a/test/socket.io.ts +++ b/test/socket.io.ts @@ -2385,6 +2385,28 @@ describe("socket.io", () => { }); }); }); + + it("should pre encode a broadcast packet", (done) => { + const srv = createServer(); + const sio = new Server(srv); + + srv.listen(() => { + const clientSocket = client(srv, { multiplex: false }); + + sio.on("connection", (socket) => { + socket.conn.on("packetCreate", (packet) => { + expect(packet.data).to.eql('2["hello","world"]'); + expect(packet.options.wsPreEncoded).to.eql('42["hello","world"]'); + + clientSocket.close(); + sio.close(); + done(); + }); + + sio.emit("hello", "world"); + }); + }); + }); }); describe("middleware", () => {