{"version":3,"file":"H3Transport.cjs","sources":["../../src/transport/H3Transport.ts"],"sourcesContent":["import { encode, decode, type Iterator } from '@colyseus/schema';\nimport { CloseCode } from '@colyseus/shared-types';\nimport type { ITransport, ITransportEventMap } from \"./ITransport.ts\";\n\n// 9 bytes is the maximum length of a variable-length integer prefix\nconst MAX_LENGTH_PREFIX_BYTES = 9;\n\ntype Channel = 'reliable' | 'unreliable';\n\n/**\n * Reassembles length-prefixed frames from arbitrary byte chunks.\n *\n * A single WebTransport `reader.read()` may:\n *   - deliver multiple whole frames in one chunk\n *   - split a frame (or its length prefix) across multiple chunks\n *\n * This reassembler buffers partial data across reads so each dispatched\n * frame is exactly one complete message.\n */\nexport class FrameReassembler {\n    private pending: Uint8Array = new Uint8Array(0);\n\n    push(chunk: Uint8Array | undefined): Uint8Array[] {\n        if (!chunk || chunk.byteLength === 0) { return []; }\n\n        const bytes = (this.pending.byteLength === 0)\n            ? chunk\n            : concatBytes(this.pending, chunk);\n\n        const frames: Uint8Array[] = [];\n        let offset = 0;\n\n        while (offset < bytes.byteLength) {\n            const it: Iterator = { offset };\n            let length: number;\n\n            try {\n                length = decode.number(bytes as any, it);\n            } catch (e) {\n                // length prefix is incomplete — wait for more bytes\n                if (bytes.byteLength - offset <= MAX_LENGTH_PREFIX_BYTES) { break; }\n                throw e;\n            }\n\n            const frameEnd = it.offset + length;\n            if (frameEnd > bytes.byteLength) {\n                // payload is incomplete — wait for more bytes\n                break;\n            }\n\n            frames.push(bytes.subarray(it.offset, frameEnd));\n            offset = frameEnd;\n        }\n\n        this.pending = (offset < bytes.byteLength)\n            ? bytes.slice(offset)\n            : new Uint8Array(0);\n\n        return frames;\n    }\n}\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n    const out = new Uint8Array(a.byteLength + b.byteLength);\n    out.set(a, 0);\n    out.set(b, a.byteLength);\n    return out;\n}\n\nexport class H3TransportTransport implements ITransport {\n    wt: WebTransport;\n    /** Connect URL — exposed so tooling (e.g. the debug panel) can show the\n     *  endpoint, mirroring `WebSocketTransport.ws.url`. */\n    url?: string;\n    isOpen: boolean = false;\n    events: ITransportEventMap;\n\n    reader: ReadableStreamDefaultReader;\n    writer: WritableStreamDefaultWriter;\n\n    unreliableReader: ReadableStreamDefaultReader<Uint8Array>;\n    unreliableWriter: WritableStreamDefaultWriter<Uint8Array>;\n\n    private lengthPrefixBuffer = new Uint8Array(9); // 9 bytes is the maximum length of a length prefix\n\n    private reliableReassembler = new FrameReassembler();\n    private unreliableReassembler = new FrameReassembler();\n\n    constructor(events: ITransportEventMap) {\n        this.events = events;\n    }\n\n    public connect(url: string, options: any = {}) {\n        this.url = url;\n        const wtOpts: WebTransportOptions = options.fingerprint && ({\n            // requireUnreliable: true,\n            // congestionControl: \"default\", // \"low-latency\" || \"throughput\"\n\n            serverCertificateHashes: [{\n                algorithm: 'sha-256',\n                // Pass the Uint8Array VIEW, not `.buffer`: the @fails-components Node client\n                // (1.6) rejects a raw ArrayBuffer here, silently failing the cert-hash match\n                // → \"Opening handshake failed\". Browsers accept either; Node wants the view.\n                value: new Uint8Array(options.fingerprint)\n            }]\n        }) || undefined;\n\n        this.wt = new WebTransport(url, wtOpts);\n\n        this.wt.ready.then((e) => {\n            console.log(\"WebTransport ready!\", e)\n            this.isOpen = true;\n\n            this.unreliableReader = this.wt.datagrams.readable.getReader();\n            // Datagram writer differs by runtime: the browser's native WebTransport\n            // exposes `datagrams.writable` (a WritableStream); @fails-components/webtransport\n            // 1.6 (Node) deprecates that in favor of `createWritable()`. Prefer the method\n            // when present (silences the Node deprecation), else the standard property.\n            const datagrams = this.wt.datagrams as any;\n            this.unreliableWriter = (datagrams.createWritable ? datagrams.createWritable() : datagrams.writable).getWriter();\n\n            const incomingBidi = this.wt.incomingBidirectionalStreams.getReader();\n            incomingBidi.read().then((stream) => {\n                this.reader = stream.value.readable.getReader();\n                this.writer = stream.value.writable.getWriter();\n\n                // immediately write room/sessionId for establishing the room connection\n                this.sendSeatReservation(options.roomId, options.sessionId, options.reconnectionToken, options.skipHandshake);\n\n                // start reading incoming data\n                this.readIncomingData();\n                this.readIncomingUnreliableData();\n\n            }).catch((e) => {\n                console.error(\"failed to read incoming stream\", e);\n                console.error(\"TODO: close the connection\");\n            });\n\n            // this.events.onopen(e);\n        }).catch((e: WebTransportCloseInfo) => {\n            // this.events.onerror(e);\n            // this.events.onclose({ code: e.closeCode, reason: e.reason });\n            console.log(\"WebTransport not ready!\", e)\n            this._close();\n        });\n\n        this.wt.closed.then((e: WebTransportCloseInfo) => {\n            console.log(\"WebTransport closed w/ success\", e)\n            this.events.onclose({ code: e.closeCode, reason: e.reason });\n\n        }).catch((e: WebTransportCloseInfo) => {\n            console.log(\"WebTransport closed w/ error\", e)\n            this.events.onerror(e);\n            this.events.onclose({ code: e.closeCode, reason: e.reason });\n        }).finally(() => {\n            this._close();\n        });\n    }\n\n    public send(data: Buffer | Uint8Array): void {\n        this.writer.write(this.frame(data));\n    }\n\n    public sendUnreliable(data: Buffer | Uint8Array): void {\n        this.unreliableWriter.write(this.frame(data));\n    }\n\n    /**\n     * Length-prefix a payload for the wire. Normalizes the input to a typed array\n     * first: unlike `ws.send()` (which accepts an ArrayBuffer directly), we frame\n     * manually — reading `.length` and copying via `.set()` — so a bare ArrayBuffer\n     * (e.g. the debug panel's latency-sim clone) must be wrapped, or `.length` is\n     * `undefined` and the allocation/copy goes out of bounds.\n     */\n    protected frame(data: Buffer | Uint8Array | ArrayBuffer): Uint8Array {\n        const bytes = data instanceof Uint8Array ? data : new Uint8Array(data as ArrayBuffer);\n        const prefixLength = encode.number(this.lengthPrefixBuffer as any, bytes.length, { offset: 0 });\n        const out = new Uint8Array(prefixLength + bytes.length);\n        out.set(this.lengthPrefixBuffer.subarray(0, prefixLength), 0);\n        out.set(bytes, prefixLength);\n        return out;\n    }\n\n    public close(code?: number, reason?: string) {\n        this.isOpen = false; // stop the reader loops; mark closed before tearing down\n        try {\n            // close() is void in the browser but can reject async (e.g. \"session is\n            // closed\" when already closing/closed) in some impls — swallow both the\n            // sync throw and any rejected promise so it doesn't surface as uncaught.\n            const ret = this.wt?.close({ closeCode: code, reason: reason }) as unknown as Promise<void> | void;\n            if (ret && typeof (ret as Promise<void>).catch === \"function\") {\n                (ret as Promise<void>).catch(() => { /* already closed — benign */ });\n            }\n        } catch (e) {\n            /* already closed / invalid state — benign during a simulated drop */\n        }\n    }\n\n    protected readIncomingData() {\n        return this.readLoop(this.reader, this.reliableReassembler, \"reliable\");\n    }\n\n    protected readIncomingUnreliableData() {\n        return this.readLoop(this.unreliableReader, this.unreliableReassembler, \"unreliable\");\n    }\n\n    protected async readLoop(\n        reader: ReadableStreamDefaultReader<Uint8Array>,\n        reassembler: FrameReassembler,\n        channel: Channel,\n    ) {\n        while (this.isOpen) {\n            let result: ReadableStreamReadResult<Uint8Array>;\n\n            try {\n                result = await reader.read();\n\n            } catch (e: any) {\n                await this.onChannelFailure(channel, e);\n                return;\n            }\n\n            // Stream ended (close/drop): a `done` read has no `value` — bail\n            // before decoding, or `decode.number(undefined)` throws on teardown.\n            if (result.done || !result.value) { return; }\n\n            //\n            // a single read may contain multiple messages\n            // each message is prefixed with its length\n            // a read may also deliver a partial frame; buffer across reads\n            //\n            for (const frame of reassembler.push(result.value)) {\n                this.events.onmessage({ data: frame });\n            }\n        }\n    }\n\n    /**\n     * Drops the connection after a read loop failed.\n     *\n     * A rejected `read()` is the end of that channel, never a hiccup: an errored\n     * ReadableStream stays errored, so retrying re-raises the same rejection (a\n     * busy loop) and a fresh reader taken off the same stream is born errored.\n     * With nothing to recover, the only alternative to closing is a transport\n     * that reports itself open but can never deliver another frame.\n     */\n    protected async onChannelFailure(channel: Channel, e: any) {\n        // Yield one turn before deciding. An implementation settles `wt.closed`\n        // in the same turn it errors the streams, and this rejection lands\n        // first, so letting that path flip `isOpen` keeps an ordinary\n        // disconnect quiet. `WebTransport` exposes no session state to read\n        // instead — the server side checks `_wtSession.state` synchronously.\n        await new Promise<void>((resolve) => setTimeout(resolve, 0));\n        if (!this.isOpen) { return; }\n\n        console.error(`H3Transport: stopped reading the ${channel} channel while the session was open`, e);\n\n        // ABNORMAL_CLOSURE so the room treats it as a drop and reconnects,\n        // rather than a consented leave.\n        this.close(CloseCode.ABNORMAL_CLOSURE, `h3 ${channel} channel failed`);\n    }\n\n    protected sendSeatReservation (roomId: string, sessionId: string, reconnectionToken?: string, skipHandshake?: boolean) {\n        const it: Iterator = { offset: 0 };\n        const bytes: number[] = [];\n\n        encode.string(bytes, roomId, it);\n        encode.string(bytes, sessionId, it);\n\n        if (reconnectionToken) {\n            encode.string(bytes, reconnectionToken, it);\n        }\n\n        if (skipHandshake) {\n            encode.boolean(bytes, 1, it);\n        }\n\n        this.writer.write(new Uint8Array(bytes).buffer);\n    }\n\n    protected _close() {\n        this.isOpen = false;\n    }\n\n}\n"],"names":["decode","encode","CloseCode"],"mappings":"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"}