Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: socketio/engine.io
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 6.5.0
Choose a base ref
...
head repository: socketio/engine.io
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6.5.2
Choose a head ref
  • 6 commits
  • 8 files changed
  • 3 contributors

Commits on Jun 16, 2023

  1. chore(deps): bump engine.io from 6.2.1 to 6.4.2 in /examples/latency (#…

    …678)
    
    Bumps [engine.io](https://github.com/socketio/engine.io) from 6.2.1 to 6.4.2.
    - [Release notes](https://github.com/socketio/engine.io/releases)
    - [Changelog](https://github.com/socketio/engine.io/blob/main/CHANGELOG.md)
    - [Commits](6.2.1...6.4.2)
    
    ---
    updated-dependencies:
    - dependency-name: engine.io
      dependency-type: direct:production
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Jun 16, 2023
    Copy the full SHA
    9608781 View commit details

Commits on Jun 27, 2023

  1. fix: prevent crash when accessing TextDecoder (#684)

    The TextDecoder object was added on the global object in Node.js
    v11.0.0, so older versions would throw:
    
    > ReferenceError: TextDecoder is not defined
    
    Reference: https://nodejs.org/api/util.html#new-textdecoderencoding-options
    iowaguy authored Jun 27, 2023
    Copy the full SHA
    6dd2bc4 View commit details
  2. chore(release): 6.5.1

    darrachequesne committed Jun 27, 2023
    Copy the full SHA
    98915d0 View commit details

Commits on Jul 9, 2023

  1. docs: update the list of supported Node.js versions

    The server uses `timeout.refresh()` (see [1]), which was added in Node.js 10.2.0.
    
    Reference: https://nodejs.org/api/timers.html#timeoutrefresh
    
    Related: #686
    
    [1]: 37474c7
    darrachequesne committed Jul 9, 2023
    Copy the full SHA
    7dd1350 View commit details

Commits on Aug 1, 2023

  1. fix(webtransport): add proper framing

    WebTransport being a stream-based protocol, the chunking boundaries are
    not necessarily preserved. That's why we need a header indicating the
    type of the payload (plain text or binary) and its length.
    
    We will use a format inspired by the WebSocket frame:
    
    - first bit indicates whether the payload is binary
    - the next 7 bits are either:
      - 125 or less: that's the length of the payload
      - 126: the next 2 bytes represent the length of the payload
      - 127: the next 8 bytes represent the length of the payload
    
    Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers#decoding_payload_length
    
    Related:
    
    - #687
    - #688
    darrachequesne committed Aug 1, 2023
    Copy the full SHA
    a306db0 View commit details

Commits on Aug 2, 2023

  1. chore(release): 6.5.2

    darrachequesne committed Aug 2, 2023
    Copy the full SHA
    12ca32b View commit details
Showing with 196 additions and 139 deletions.
  1. +35 −0 CHANGELOG.md
  2. +36 −21 examples/latency/package-lock.json
  3. +1 −1 examples/latency/package.json
  4. +20 −17 lib/server.ts
  5. +28 −46 lib/transports/webtransport.ts
  6. +25 −8 package-lock.json
  7. +3 −3 package.json
  8. +48 −43 test/webtransport.mjs
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

## 2023

- [6.5.2](#652-2023-08-01) (Aug 2023)
- [6.5.1](#651-2023-06-27) (Jun 2023)
- [6.5.0](#650-2023-06-16) (Jun 2023)
- [6.4.2](#642-2023-05-02) (May 2023)
- [6.4.1](#641-2023-02-20) (Feb 2023)
@@ -48,6 +50,39 @@

# Release notes

## [6.5.2](https://github.com/socketio/engine.io/compare/6.5.1...6.5.2) (2023-08-01)


### Bug Fixes

* **webtransport:** add proper framing ([a306db0](https://github.com/socketio/engine.io/commit/a306db09e8ddb367c7d62f45fec920f979580b7c))


### Dependencies

- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)



## [6.5.1](https://github.com/socketio/engine.io/compare/6.5.0...6.5.1) (2023-06-27)


### Bug Fixes

* prevent crash when accessing TextDecoder ([#684](https://github.com/socketio/engine.io/issues/684)) ([6dd2bc4](https://github.com/socketio/engine.io/commit/6dd2bc4f68edd7575c3844ae8ceadde649be95b2))


### Credits

Huge thanks to [@iowaguy](https://github.com/iowaguy) for helping!


### Dependencies

- [`ws@~8.11.0`](https://github.com/websockets/ws/releases/tag/8.11.0) (no change)



## [6.5.0](https://github.com/socketio/engine.io/compare/6.4.2...6.5.0) (2023-06-16)


57 changes: 36 additions & 21 deletions examples/latency/package-lock.json

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

2 changes: 1 addition & 1 deletion examples/latency/package.json
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
"version": "0.1.0",
"dependencies": {
"enchilada": "0.13.0",
"engine.io": "^6.2.1",
"engine.io": "^6.4.2",
"engine.io-client": "^4.1.4",
"express": "^4.18.2",
"smoothie": "1.19.0"
37 changes: 20 additions & 17 deletions lib/server.ts
Original file line number Diff line number Diff line change
@@ -16,11 +16,11 @@ import type { CookieSerializeOptions } from "cookie";
import type { CorsOptions, CorsOptionsDelegate } from "cors";
import type { Duplex } from "stream";
import { WebTransport } from "./transports/webtransport";
import { createPacketDecoderStream } from "engine.io-parser";

const debug = debugModule("engine");

const kResponseHeaders = Symbol("responseHeaders");
const TEXT_DECODER = new TextDecoder();

type Transport = "polling" | "websocket";

@@ -148,15 +148,13 @@ type Middleware = (
next: (err?: any) => void
) => void;

function parseSessionId(handshake: string) {
if (handshake.startsWith("0{")) {
try {
const parsed = JSON.parse(handshake.substring(1));
if (typeof parsed.sid === "string") {
return parsed.sid;
}
} catch (e) {}
}
function parseSessionId(data: string) {
try {
const parsed = JSON.parse(data);
if (typeof parsed.sid === "string") {
return parsed.sid;
}
} catch (e) {}
}

export abstract class BaseServer extends EventEmitter {
@@ -535,7 +533,11 @@ export abstract class BaseServer extends EventEmitter {
}

const stream = result.value;
const reader = stream.readable.getReader();
const transformStream = createPacketDecoderStream(
this.opts.maxHttpBufferSize,
"nodebuffer"
);
const reader = stream.readable.pipeThrough(transformStream).getReader();

// reading the first packet of the stream
const { value, done } = await reader.read();
@@ -545,12 +547,13 @@ export abstract class BaseServer extends EventEmitter {
}

clearTimeout(timeout);
const handshake = TEXT_DECODER.decode(value);

// handshake is either
// "0" => new session
// '0{"sid":"xxxx"}' => upgrade
if (handshake === "0") {
if (value.type !== "open") {
debug("invalid WebTransport handshake");
return session.close();
}

if (value.data === undefined) {
const transport = new WebTransport(session, stream, reader);

// note: we cannot use "this.generateId()", because there is no "req" argument
@@ -571,7 +574,7 @@ export abstract class BaseServer extends EventEmitter {
return;
}

const sid = parseSessionId(handshake);
const sid = parseSessionId(value.data);

if (!sid) {
debug("invalid WebTransport handshake");
74 changes: 28 additions & 46 deletions lib/transports/webtransport.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
import { Transport } from "../transport";
import debugModule from "debug";
import { createPacketEncoderStream } from "engine.io-parser";

const debug = debugModule("engine:webtransport");

const BINARY_HEADER = Buffer.of(54);

function shouldIncludeBinaryHeader(packet, encoded) {
// 48 === "0".charCodeAt(0) (OPEN packet type)
// 54 === "6".charCodeAt(0) (NOOP packet type)
return (
packet.type === "message" &&
typeof packet.data !== "string" &&
encoded[0] >= 48 &&
encoded[0] <= 54
);
}

/**
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/WebTransport_API
*/
@@ -24,24 +12,24 @@ export class WebTransport extends Transport {

constructor(private readonly session, stream, reader) {
super({ _query: { EIO: "4" } });
this.writer = stream.writable.getWriter();

const transformStream = createPacketEncoderStream();
transformStream.readable.pipeTo(stream.writable);
this.writer = transformStream.writable.getWriter();

(async () => {
let binaryFlag = false;
while (true) {
const { value, done } = await reader.read();
if (done) {
debug("session is closed");
break;
}
debug("received chunk: %o", value);
if (!binaryFlag && value.byteLength === 1 && value[0] === 54) {
binaryFlag = true;
continue;
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
debug("session is closed");
break;
}
debug("received chunk: %o", value);
this.onPacket(value);
}
this.onPacket(
this.parser.decodePacketFromBinary(value, binaryFlag, "nodebuffer")
);
binaryFlag = false;
} catch (e) {
debug("error while reading: %s", e.message);
}
})();

@@ -58,26 +46,20 @@ export class WebTransport extends Transport {
return true;
}

send(packets) {
async send(packets) {
this.writable = false;

for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
const isLast = i + 1 === packets.length;

this.parser.encodePacketToBinary(packet, (data) => {
if (shouldIncludeBinaryHeader(packet, data)) {
debug("writing binary header");
this.writer.write(BINARY_HEADER);
}
debug("writing chunk: %o", data);
this.writer.write(data);
if (isLast) {
this.writable = true;
this.emit("drain");
}
});
try {
for (let i = 0; i < packets.length; i++) {
const packet = packets[i];
await this.writer.write(packet);
}
} catch (e) {
debug("error while writing: %s", e.message);
}

this.writable = true;
this.emit("drain");
}

doClose(fn) {
Loading