Skip to content

Commit

Permalink
perf: add support for the "wsPreEncoded" writing option
Browse files Browse the repository at this point in the history
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: socketio/engine.io@7706b12

engine.io diff: socketio/engine.io@5.0.0...5.1.0
  • Loading branch information
darrachequesne committed May 10, 2021
1 parent 9fff034 commit dc381b7
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 30 deletions.
47 changes: 25 additions & 22 deletions lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
}

/**
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
22 changes: 22 additions & 0 deletions test/socket.io.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down

0 comments on commit dc381b7

Please sign in to comment.