From dc81fcf461cfdbb5b34b1a5a96b84373754047d5 Mon Sep 17 00:00:00 2001 From: Damien Arrachequesne Date: Thu, 9 Sep 2021 07:39:59 +0200 Subject: [PATCH] fix: send volatile packets with binary attachments The binary attachments of volatile packets were discarded (only the header packet was sent) due to a bug introduced by [1]. Related: https://github.com/socketio/socket.io/issues/3919 [1]: https://github.com/socketio/socket.io/commit/dc381b72c6b2f8172001dedd84116122e4cc95b3 --- lib/client.ts | 13 ++++++++----- test/socket.io.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/lib/client.ts b/lib/client.ts index f61e46c8b1..46823f691a 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -209,13 +209,11 @@ export class Client< const encodedPackets = opts.preEncoded ? (packet as any[]) // previous versions of the adapter incorrectly used socket.packet() instead of writeToEngine() : this.encoder.encode(packet as Packet); - for (const encodedPacket of encodedPackets) { - this.writeToEngine(encodedPacket, opts); - } + this.writeToEngine(encodedPackets, opts); } private writeToEngine( - encodedPacket: String | Buffer, + encodedPackets: Array, opts: WriteOptions ): void { if (opts.volatile && !this.conn.transport.writable) { @@ -224,7 +222,12 @@ export class Client< ); return; } - this.conn.write(encodedPacket, opts); + const packets = Array.isArray(encodedPackets) + ? encodedPackets + : [encodedPackets]; + for (const encodedPacket of packets) { + this.conn.write(encodedPacket, opts); + } } /** diff --git a/test/socket.io.ts b/test/socket.io.ts index 630fc296f5..2ea7d13f60 100644 --- a/test/socket.io.ts +++ b/test/socket.io.ts @@ -1382,6 +1382,32 @@ describe("socket.io", () => { }, 200); }); + it("should emit only one consecutive volatile event with binary (ws)", (done) => { + const srv = createServer(); + const sio = new Server(srv, { transports: ["websocket"] }); + + let counter = 0; + srv.listen(() => { + sio.on("connection", (s) => { + // Wait to make sure there are no packets being sent for opening the connection + setTimeout(() => { + s.volatile.emit("ev", Buffer.from([1, 2, 3])); + s.volatile.emit("ev", Buffer.from([4, 5, 6])); + }, 20); + }); + + const socket = client(srv, { transports: ["websocket"] }); + socket.on("ev", () => { + counter++; + }); + }); + + setTimeout(() => { + expect(counter).to.be(1); + done(); + }, 200); + }); + it("should emit regular events after trying a failed volatile event (polling)", (done) => { const srv = createServer(); const sio = new Server(srv, { transports: ["polling"] });