@norskvideo/moq-net 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/announced.d.ts +111 -21
- package/announced.d.ts.map +1 -1
- package/announced.js +213 -40
- package/announced.js.map +1 -1
- package/broadcast.d.ts +80 -25
- package/broadcast.d.ts.map +1 -1
- package/broadcast.js +270 -49
- package/broadcast.js.map +1 -1
- package/connection/accept.d.ts +6 -0
- package/connection/accept.d.ts.map +1 -1
- package/connection/accept.js +42 -13
- package/connection/accept.js.map +1 -1
- package/connection/browser.d.ts +5 -0
- package/connection/browser.d.ts.map +1 -0
- package/connection/browser.js +31 -0
- package/connection/browser.js.map +1 -0
- package/connection/connect.d.ts +43 -1
- package/connection/connect.d.ts.map +1 -1
- package/connection/connect.js +118 -123
- package/connection/connect.js.map +1 -1
- package/connection/established.d.ts +43 -16
- package/connection/established.d.ts.map +1 -1
- package/connection/established.js.map +1 -1
- package/connection/handshake.d.ts +12 -1
- package/connection/handshake.d.ts.map +1 -1
- package/connection/handshake.js +30 -14
- package/connection/handshake.js.map +1 -1
- package/connection/index.d.ts +8 -0
- package/connection/index.d.ts.map +1 -1
- package/connection/index.js +6 -0
- package/connection/index.js.map +1 -1
- package/connection/reload.d.ts +66 -9
- package/connection/reload.d.ts.map +1 -1
- package/connection/reload.js +192 -66
- package/connection/reload.js.map +1 -1
- package/connection/stats.d.ts +92 -0
- package/connection/stats.d.ts.map +1 -0
- package/connection/stats.js +35 -0
- package/connection/stats.js.map +1 -0
- package/connection/transport.d.ts +10 -0
- package/connection/transport.d.ts.map +1 -0
- package/connection/transport.js +12 -0
- package/connection/transport.js.map +1 -0
- package/consume.d.ts +44 -0
- package/consume.d.ts.map +1 -0
- package/consume.js +60 -0
- package/consume.js.map +1 -0
- package/datagram.d.ts +23 -0
- package/datagram.d.ts.map +1 -0
- package/datagram.js +3 -0
- package/datagram.js.map +1 -0
- package/error.d.ts +76 -0
- package/error.d.ts.map +1 -0
- package/error.js +107 -0
- package/error.js.map +1 -0
- package/group.d.ts +143 -38
- package/group.d.ts.map +1 -1
- package/group.js +270 -68
- package/group.js.map +1 -1
- package/ietf/adapter.d.ts +2 -2
- package/ietf/adapter.d.ts.map +1 -1
- package/ietf/adapter.js +20 -10
- package/ietf/adapter.js.map +1 -1
- package/ietf/aliases.d.ts +73 -5
- package/ietf/aliases.d.ts.map +1 -1
- package/ietf/aliases.js +121 -14
- package/ietf/aliases.js.map +1 -1
- package/ietf/cluster.d.ts +141 -0
- package/ietf/cluster.d.ts.map +1 -0
- package/ietf/cluster.js +204 -0
- package/ietf/cluster.js.map +1 -0
- package/ietf/connection.d.ts +39 -6
- package/ietf/connection.d.ts.map +1 -1
- package/ietf/connection.js +73 -12
- package/ietf/connection.js.map +1 -1
- package/ietf/fetch.d.ts +17 -0
- package/ietf/fetch.d.ts.map +1 -1
- package/ietf/fetch.js +21 -0
- package/ietf/fetch.js.map +1 -1
- package/ietf/filter.d.ts +87 -0
- package/ietf/filter.d.ts.map +1 -0
- package/ietf/filter.js +292 -0
- package/ietf/filter.js.map +1 -0
- package/ietf/index.d.ts +2 -0
- package/ietf/index.d.ts.map +1 -1
- package/ietf/index.js +3 -0
- package/ietf/index.js.map +1 -1
- package/ietf/namespace.d.ts +6 -0
- package/ietf/namespace.d.ts.map +1 -1
- package/ietf/namespace.js +27 -2
- package/ietf/namespace.js.map +1 -1
- package/ietf/object.d.ts +54 -6
- package/ietf/object.d.ts.map +1 -1
- package/ietf/object.js +178 -25
- package/ietf/object.js.map +1 -1
- package/ietf/parameters.d.ts +35 -10
- package/ietf/parameters.d.ts.map +1 -1
- package/ietf/parameters.js +236 -45
- package/ietf/parameters.js.map +1 -1
- package/ietf/priority.d.ts +5 -0
- package/ietf/priority.d.ts.map +1 -0
- package/ietf/priority.js +10 -0
- package/ietf/priority.js.map +1 -0
- package/ietf/properties.d.ts +13 -2
- package/ietf/properties.d.ts.map +1 -1
- package/ietf/properties.js +65 -8
- package/ietf/properties.js.map +1 -1
- package/ietf/publish.d.ts.map +1 -1
- package/ietf/publish.js +13 -3
- package/ietf/publish.js.map +1 -1
- package/ietf/publish_namespace.d.ts +16 -2
- package/ietf/publish_namespace.d.ts.map +1 -1
- package/ietf/publish_namespace.js +25 -6
- package/ietf/publish_namespace.js.map +1 -1
- package/ietf/publisher.d.ts +40 -7
- package/ietf/publisher.d.ts.map +1 -1
- package/ietf/publisher.js +751 -134
- package/ietf/publisher.js.map +1 -1
- package/ietf/request.js +1 -1
- package/ietf/request.js.map +1 -1
- package/ietf/solicit.d.ts +41 -0
- package/ietf/solicit.d.ts.map +1 -0
- package/ietf/solicit.js +47 -0
- package/ietf/solicit.js.map +1 -0
- package/ietf/subscribe.d.ts +41 -2
- package/ietf/subscribe.d.ts.map +1 -1
- package/ietf/subscribe.js +103 -22
- package/ietf/subscribe.js.map +1 -1
- package/ietf/subscribe_namespace.d.ts +21 -7
- package/ietf/subscribe_namespace.d.ts.map +1 -1
- package/ietf/subscribe_namespace.js +31 -14
- package/ietf/subscribe_namespace.js.map +1 -1
- package/ietf/subscriber.d.ts +20 -7
- package/ietf/subscriber.d.ts.map +1 -1
- package/ietf/subscriber.js +512 -142
- package/ietf/subscriber.js.map +1 -1
- package/ietf/version.d.ts +7 -1
- package/ietf/version.d.ts.map +1 -1
- package/ietf/version.js +7 -0
- package/ietf/version.js.map +1 -1
- package/index.d.ts +10 -5
- package/index.d.ts.map +1 -1
- package/index.js +10 -5
- package/index.js.map +1 -1
- package/internal.d.ts +29 -0
- package/internal.d.ts.map +1 -0
- package/internal.js +8 -0
- package/internal.js.map +1 -0
- package/lite/announce.d.ts +62 -15
- package/lite/announce.d.ts.map +1 -1
- package/lite/announce.js +230 -94
- package/lite/announce.js.map +1 -1
- package/lite/connection.d.ts +69 -20
- package/lite/connection.d.ts.map +1 -1
- package/lite/connection.js +128 -81
- package/lite/connection.js.map +1 -1
- package/lite/datagram.d.ts +23 -0
- package/lite/datagram.d.ts.map +1 -0
- package/lite/datagram.js +57 -0
- package/lite/datagram.js.map +1 -0
- package/lite/datagram_stream.d.ts +8 -0
- package/lite/datagram_stream.d.ts.map +1 -0
- package/lite/datagram_stream.js +44 -0
- package/lite/datagram_stream.js.map +1 -0
- package/lite/fetch.d.ts.map +1 -1
- package/lite/fetch.js +2 -2
- package/lite/fetch.js.map +1 -1
- package/lite/index.d.ts +3 -0
- package/lite/index.d.ts.map +1 -1
- package/lite/index.js +3 -0
- package/lite/index.js.map +1 -1
- package/lite/priority.d.ts +67 -0
- package/lite/priority.d.ts.map +1 -0
- package/lite/priority.js +114 -0
- package/lite/priority.js.map +1 -0
- package/lite/probe.d.ts +18 -2
- package/lite/probe.d.ts.map +1 -1
- package/lite/probe.js +24 -22
- package/lite/probe.js.map +1 -1
- package/lite/publisher.d.ts +14 -7
- package/lite/publisher.d.ts.map +1 -1
- package/lite/publisher.js +406 -84
- package/lite/publisher.js.map +1 -1
- package/lite/setup.d.ts +83 -6
- package/lite/setup.d.ts.map +1 -1
- package/lite/setup.js +203 -31
- package/lite/setup.js.map +1 -1
- package/lite/stream.d.ts +12 -3
- package/lite/stream.d.ts.map +1 -1
- package/lite/stream.js +7 -4
- package/lite/stream.js.map +1 -1
- package/lite/subscribe.d.ts +37 -23
- package/lite/subscribe.d.ts.map +1 -1
- package/lite/subscribe.js +70 -55
- package/lite/subscribe.js.map +1 -1
- package/lite/subscriber.d.ts +29 -23
- package/lite/subscriber.d.ts.map +1 -1
- package/lite/subscriber.js +689 -112
- package/lite/subscriber.js.map +1 -1
- package/lite/track.d.ts +25 -13
- package/lite/track.d.ts.map +1 -1
- package/lite/track.js +60 -35
- package/lite/track.js.map +1 -1
- package/lite/version.d.ts +39 -4
- package/lite/version.d.ts.map +1 -1
- package/lite/version.js +139 -17
- package/lite/version.js.map +1 -1
- package/mock.d.ts +53 -3
- package/mock.d.ts.map +1 -1
- package/mock.js +110 -21
- package/mock.js.map +1 -1
- package/{lite/origin.d.ts → origin.d.ts} +25 -1
- package/origin.d.ts.map +1 -0
- package/{lite/origin.js → origin.js} +25 -1
- package/origin.js.map +1 -0
- package/package.json +6 -4
- package/path.d.ts +67 -0
- package/path.d.ts.map +1 -1
- package/path.js +128 -0
- package/path.js.map +1 -1
- package/stream.d.ts +94 -4
- package/stream.d.ts.map +1 -1
- package/stream.js +128 -17
- package/stream.js.map +1 -1
- package/time.d.ts +109 -86
- package/time.d.ts.map +1 -1
- package/time.js +80 -30
- package/time.js.map +1 -1
- package/track.d.ts +298 -47
- package/track.d.ts.map +1 -1
- package/track.js +721 -109
- package/track.js.map +1 -1
- package/util/timeout.d.ts +5 -0
- package/util/timeout.d.ts.map +1 -0
- package/util/timeout.js +18 -0
- package/util/timeout.js.map +1 -0
- package/util/utf8.d.ts +3 -0
- package/util/utf8.d.ts.map +1 -0
- package/util/utf8.js +7 -0
- package/util/utf8.js.map +1 -0
- package/varint.d.ts +14 -3
- package/varint.d.ts.map +1 -1
- package/varint.js +23 -12
- package/varint.js.map +1 -1
- package/zod.d.ts +5 -5
- package/zod.d.ts.map +1 -1
- package/zod.js.map +1 -1
- package/bandwidth.d.ts +0 -11
- package/bandwidth.d.ts.map +0 -1
- package/bandwidth.js +0 -7
- package/bandwidth.js.map +0 -1
- package/connection/cert.test.d.ts +0 -2
- package/connection/cert.test.d.ts.map +0 -1
- package/connection/cert.test.js +0 -26
- package/connection/cert.test.js.map +0 -1
- package/connection/reload.test.d.ts +0 -2
- package/connection/reload.test.d.ts.map +0 -1
- package/connection/reload.test.js +0 -39
- package/connection/reload.test.js.map +0 -1
- package/group.test.d.ts +0 -2
- package/group.test.d.ts.map +0 -1
- package/group.test.js +0 -66
- package/group.test.js.map +0 -1
- package/ietf/aliases.test.d.ts +0 -2
- package/ietf/aliases.test.d.ts.map +0 -1
- package/ietf/aliases.test.js +0 -30
- package/ietf/aliases.test.js.map +0 -1
- package/ietf/ietf.test.d.ts +0 -2
- package/ietf/ietf.test.d.ts.map +0 -1
- package/ietf/ietf.test.js +0 -873
- package/ietf/ietf.test.js.map +0 -1
- package/integration.test.d.ts +0 -2
- package/integration.test.d.ts.map +0 -1
- package/integration.test.js +0 -90
- package/integration.test.js.map +0 -1
- package/lite/origin.d.ts.map +0 -1
- package/lite/origin.js.map +0 -1
- package/lite/subscriber.test.d.ts +0 -2
- package/lite/subscriber.test.d.ts.map +0 -1
- package/lite/subscriber.test.js +0 -30
- package/lite/subscriber.test.js.map +0 -1
- package/lite/track.test.d.ts +0 -2
- package/lite/track.test.d.ts.map +0 -1
- package/lite/track.test.js +0 -53
- package/lite/track.test.js.map +0 -1
- package/path.test.d.ts +0 -2
- package/path.test.d.ts.map +0 -1
- package/path.test.js +0 -169
- package/path.test.js.map +0 -1
- package/stream.test.d.ts +0 -2
- package/stream.test.d.ts.map +0 -1
- package/stream.test.js +0 -210
- package/stream.test.js.map +0 -1
- package/track.test.d.ts +0 -2
- package/track.test.d.ts.map +0 -1
- package/track.test.js +0 -56
- package/track.test.js.map +0 -1
- package/util/error.d.ts +0 -3
- package/util/error.d.ts.map +0 -1
- package/util/error.js +0 -9
- package/util/error.js.map +0 -1
- package/util/index.d.ts +0 -2
- package/util/index.d.ts.map +0 -1
- package/util/index.js +0 -3
- package/util/index.js.map +0 -1
- package/varint.test.d.ts +0 -2
- package/varint.test.d.ts.map +0 -1
- package/varint.test.js +0 -106
- package/varint.test.js.map +0 -1
package/ietf/adapter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/ietf/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from \"async-mutex\";\nimport { Reader, Stream, type Writer } from \"../stream.ts\";\nimport * as Varint from \"../varint.ts\";\nimport * as Namespace from \"./namespace.ts\";\nimport { type IetfVersion, Version } from \"./version.ts\";\n\n/**\n * Interface for opening outgoing bidi streams and allocating request IDs.\n * Implemented by both ControlStreamAdapter (v14-v16) and NativeSession (v17).\n */\nexport interface Session {\n\topenBi(): Stream | Promise<Stream>;\n\topenNativeBi?(): Promise<Stream>;\n\tacceptBi(): Promise<Stream | undefined>;\n\tnextRequestId(): Promise<bigint | undefined>;\n\tclose(): void;\n\treadonly version: IetfVersion;\n}\n\n/**\n * v17 native session — thin wrapper around WebTransport.\n * Each request gets its own real bidi stream; no control stream multiplexing.\n */\nexport class NativeSession implements Session {\n\t#quic: WebTransport;\n\t#requestId = 0n;\n\treadonly version: IetfVersion;\n\n\tconstructor(quic: WebTransport, version: IetfVersion) {\n\t\tthis.#quic = quic;\n\t\tthis.version = version;\n\t}\n\n\tasync openBi(): Promise<Stream> {\n\t\treturn Stream.open(this.#quic, this.version);\n\t}\n\n\tasync acceptBi(): Promise<Stream | undefined> {\n\t\treturn Stream.accept(this.#quic, this.version);\n\t}\n\n\tasync nextRequestId(): Promise<bigint | undefined> {\n\t\tconst id = this.#requestId;\n\t\tthis.#requestId += 2n;\n\t\treturn id;\n\t}\n\n\t/** Closes the underlying WebTransport session. */\n\tclose() {\n\t\tthis.#quic.close();\n\t}\n}\n\n// Route classification for control stream messages.\nconst Route = {\n\tNewRequest: 0, // Create virtual bidi stream, push initial message\n\tResponse: 1, // Push message to existing stream (keep open)\n\tErrorResponse: 2, // Push message to existing stream, then close\n\tCloseStream: 3, // Close stream recv (no bytes pushed)\n\tFollowUp: 4, // Push follow-up message to existing stream\n\tMaxRequestId: 5, // Update flow control\n\tIgnore: 6, // Connection-level, no routing\n\tGoAway: 7, // Terminal\n} as const;\ntype Route = (typeof Route)[keyof typeof Route];\n\ninterface StreamEntry {\n\tcontroller: ReadableStreamDefaultController<Uint8Array>;\n}\n\n/**\n * Converts v14-v16 control stream multiplexing into virtual bidi streams.\n *\n * Reads control messages, classifies them, and routes to virtual Stream objects.\n * Each request/response pair gets its own virtual Stream, making all versions\n * look like v17's stream-per-request model.\n */\nexport class ControlStreamAdapter implements Session {\n\t// WebTransport session (for opening real bidi streams in v16)\n\t#quic: WebTransport;\n\n\t// Control stream\n\t#reader: Reader;\n\t#writer: Writer;\n\t#writeMutex = new Mutex();\n\treadonly version: IetfVersion;\n\n\t// Virtual streams keyed by requestId\n\t#streams = new Map<bigint, StreamEntry>();\n\n\t// Namespace → requestId reverse lookup (v14/v15 namespace-keyed messages)\n\t#namespaces = new Map<string, bigint>();\n\n\t// requestId → namespace reverse lookup (for cleanup in #closeStream)\n\t#namespacesByRequestId = new Map<bigint, string>();\n\n\t// SubscribeNamespace requestIds — for routing 0x08/0x0E entries that lack requestId (v14/v15)\n\t#subscribeNamespaces = new Set<bigint>();\n\n\t// Incoming stream queue (for acceptBi)\n\t#incomingQueue: Stream[] = [];\n\t#incomingWaiters: ((stream: Stream | undefined) => void)[] = [];\n\n\t// Request ID flow control\n\t#requestId = 0n;\n\t#maxRequestId: bigint;\n\t#maxRequestIdResolves: (() => void)[] = [];\n\n\t#closed = false;\n\n\tconstructor(quic: WebTransport, controlStream: Stream, version: IetfVersion, maxRequestId: bigint) {\n\t\tthis.#quic = quic;\n\t\tthis.#reader = controlStream.reader;\n\t\tthis.#reader.version = version;\n\t\tthis.#writer = controlStream.writer;\n\t\tthis.#writer.version = version;\n\t\tthis.version = version;\n\t\tthis.#maxRequestId = maxRequestId;\n\t}\n\n\t/**\n\t * Accept the next incoming virtual bidi stream.\n\t * Blocks until a new request arrives on the control stream.\n\t */\n\tasync acceptBi(): Promise<Stream | undefined> {\n\t\tif (this.#closed) return undefined;\n\n\t\tconst queued = this.#incomingQueue.shift();\n\t\tif (queued) return queued;\n\n\t\treturn new Promise<Stream | undefined>((resolve) => {\n\t\t\tthis.#incomingWaiters.push(resolve);\n\t\t});\n\t}\n\n\t/**\n\t * Open an outgoing virtual bidi stream.\n\t * Buffers writes until the first full message is available, parses the\n\t * requestId (and namespace for PublishNamespace), self-registers, then\n\t * flushes. Subsequent writes go directly to the control stream.\n\t */\n\topenBi(): Stream {\n\t\tlet controller!: ReadableStreamDefaultController<Uint8Array>;\n\t\tlet registeredRequestId: bigint | undefined;\n\n\t\tconst readable = new ReadableStream<Uint8Array>({\n\t\t\tstart(c) {\n\t\t\t\tcontroller = c;\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tif (registeredRequestId !== undefined) {\n\t\t\t\t\tthis.#streams.delete(registeredRequestId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tlet buffer = new Uint8Array(0);\n\t\tlet registered = false;\n\n\t\tconst sendWritable = new WritableStream<Uint8Array>({\n\t\t\twrite: async (chunk) => {\n\t\t\t\t// Always accumulate bytes and flush only complete messages\n\t\t\t\t// to prevent interleaving of partial messages from concurrent virtual streams.\n\t\t\t\tconst newBuf = new Uint8Array(buffer.length + chunk.length);\n\t\t\t\tnewBuf.set(buffer);\n\t\t\t\tnewBuf.set(chunk, buffer.length);\n\t\t\t\tbuffer = newBuf;\n\n\t\t\t\t// Try to flush complete messages from the buffer\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst boundary = this.#messageSize(buffer);\n\t\t\t\t\tif (boundary === undefined) break;\n\n\t\t\t\t\tconst toFlush = buffer.subarray(0, boundary);\n\t\t\t\t\tbuffer = buffer.subarray(boundary);\n\n\t\t\t\t\tif (!registered) {\n\t\t\t\t\t\t// First message: extract requestId and register before flushing\n\t\t\t\t\t\tconst parsed = this.#tryParseOutgoing(toFlush);\n\t\t\t\t\t\tif (parsed) {\n\t\t\t\t\t\t\tregisteredRequestId = parsed.requestId;\n\t\t\t\t\t\t\tthis.#streams.set(parsed.requestId, { controller });\n\t\t\t\t\t\t\tregistered = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.#writeMutex.runExclusive(() => this.#writer.write(toFlush));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tconst stream = new Stream({ readable, writable: sendWritable });\n\t\tstream.reader.version = this.version;\n\t\tstream.writer.version = this.version;\n\t\treturn stream;\n\t}\n\n\t/**\n\t * Open a real WebTransport bidi stream (for v16 SubscribeNamespace).\n\t */\n\tasync openNativeBi(): Promise<Stream> {\n\t\treturn Stream.open(this.#quic, this.version);\n\t}\n\n\t/**\n\t * Allocate the next request ID, blocking if flow control limit reached.\n\t */\n\tasync nextRequestId(): Promise<bigint | undefined> {\n\t\tfor (;;) {\n\t\t\tif (this.#closed) return undefined;\n\t\t\tconst id = this.#requestId;\n\t\t\tif (id < this.#maxRequestId) {\n\t\t\t\tthis.#requestId += 2n;\n\t\t\t\treturn id;\n\t\t\t}\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.#maxRequestIdResolves.push(resolve);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Main run loop — reads control stream messages and routes to virtual streams.\n\t * Must be called after construction. Runs until the control stream closes.\n\t */\n\tasync run(): Promise<void> {\n\t\ttry {\n\t\t\t// v16: also accept real bidi streams (for SubscribeNamespace)\n\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\tvoid this.#acceptNativeBidis();\n\t\t\t}\n\n\t\t\tfor (;;) {\n\t\t\t\tconst done = await this.#reader.done();\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst typeId = await this.#reader.u53();\n\t\t\t\tconst size = await this.#reader.u16();\n\t\t\t\tconst body = await this.#reader.read(size);\n\n\t\t\t\tconst classified = await this.#classify(typeId, body);\n\n\t\t\t\tif (classified.route === Route.GoAway) {\n\t\t\t\t\tconsole.warn(\"received GOAWAY on control stream\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { route, requestId } = classified;\n\n\t\t\t\tswitch (route) {\n\t\t\t\t\tcase Route.NewRequest:\n\t\t\t\t\t\tthis.#newRequest(typeId, size, body, requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.Response:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.ErrorResponse:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tthis.#closeStream(requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.CloseStream:\n\t\t\t\t\t\tthis.#closeStream(requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.FollowUp:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.MaxRequestId:\n\t\t\t\t\t\tthis.#maxRequestId = requestId;\n\t\t\t\t\t\tfor (const resolve of this.#maxRequestIdResolves) resolve();\n\t\t\t\t\t\tthis.#maxRequestIdResolves = [];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** Accept real WebTransport bidi streams and queue them for acceptBi (v16). */\n\tasync #acceptNativeBidis(): Promise<void> {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst stream = await Stream.accept(this.#quic, this.version);\n\t\t\t\tif (!stream) break;\n\n\t\t\t\tconst waiter = this.#incomingWaiters.shift();\n\t\t\t\tif (waiter) {\n\t\t\t\t\twaiter(stream);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#incomingQueue.push(stream);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Session closed\n\t\t}\n\t}\n\n\t#newRequest(typeId: number, size: number, body: Uint8Array, requestId: bigint) {\n\t\tlet controller!: ReadableStreamDefaultController<Uint8Array>;\n\t\tconst readable = new ReadableStream<Uint8Array>({\n\t\t\tstart(c) {\n\t\t\t\tcontroller = c;\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tthis.#streams.delete(requestId);\n\t\t\t},\n\t\t});\n\n\t\tconst sendWritable = this.#createSendWritable();\n\n\t\tconst stream = new Stream({ readable, writable: sendWritable });\n\t\tstream.reader.version = this.version;\n\t\tstream.writer.version = this.version;\n\n\t\tthis.#streams.set(requestId, { controller });\n\n\t\t// Push initial message bytes so the dispatcher can read typeId + decode\n\t\tcontroller.enqueue(this.#encodeRaw(typeId, size, body));\n\n\t\t// Queue for acceptBi\n\t\tconst waiter = this.#incomingWaiters.shift();\n\t\tif (waiter) {\n\t\t\twaiter(stream);\n\t\t} else {\n\t\t\tthis.#incomingQueue.push(stream);\n\t\t}\n\t}\n\n\t#pushMessage(requestId: bigint, typeId: number, size: number, body: Uint8Array) {\n\t\tconst entry = this.#streams.get(requestId);\n\t\tif (!entry) {\n\t\t\tconsole.warn(`adapter: no stream for requestId=${requestId} typeId=0x${typeId.toString(16)}`);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tentry.controller.enqueue(this.#encodeRaw(typeId, size, body));\n\t\t} catch {\n\t\t\t// Stream already closed\n\t\t}\n\t}\n\n\t#closeStream(requestId: bigint) {\n\t\tconst entry = this.#streams.get(requestId);\n\t\tif (!entry) return;\n\t\tconsole.debug(`adapter: closing stream requestId=${requestId}`);\n\t\tthis.#streams.delete(requestId);\n\t\tthis.#subscribeNamespaces.delete(requestId);\n\t\tconst namespace = this.#namespacesByRequestId.get(requestId);\n\t\tif (namespace !== undefined) {\n\t\t\tthis.#namespaces.delete(namespace);\n\t\t\tthis.#namespacesByRequestId.delete(requestId);\n\t\t}\n\t\ttry {\n\t\t\tentry.controller.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\t}\n\n\t/**\n\t * Returns the total byte size of the first complete message in buffer,\n\t * or undefined if the buffer doesn't contain a complete message yet.\n\t * Message format: [typeId varint][size u16 BE][body of `size` bytes]\n\t */\n\t#messageSize(buffer: Uint8Array): number | undefined {\n\t\tif (buffer.length === 0) return undefined;\n\n\t\tconst typeSize = 1 << ((buffer[0] & 0xc0) >> 6);\n\t\tif (buffer.length < typeSize) return undefined;\n\n\t\tconst [, afterType] = Varint.decode(buffer);\n\t\tif (afterType.length < 2) return undefined;\n\n\t\tconst size = (afterType[0] << 8) | afterType[1];\n\t\tconst totalSize = buffer.length - afterType.length + 2 + size;\n\t\tif (buffer.length < totalSize) return undefined;\n\n\t\treturn totalSize;\n\t}\n\n\t/**\n\t * Try to parse the first outgoing message from accumulated bytes.\n\t * Returns the requestId if enough data is available, undefined otherwise.\n\t */\n\t#tryParseOutgoing(buffer: Uint8Array): { requestId: bigint } | undefined {\n\t\tif (buffer.length === 0) return undefined;\n\n\t\t// Check typeId varint size before decoding\n\t\tconst typeSize = 1 << ((buffer[0] & 0xc0) >> 6);\n\t\tif (buffer.length < typeSize) return undefined;\n\n\t\tconst [typeId, afterType] = Varint.decode(buffer);\n\n\t\t// Need 2 bytes for u16 size\n\t\tif (afterType.length < 2) return undefined;\n\n\t\tconst size = (afterType[0] << 8) | afterType[1];\n\t\tconst bodyStart = afterType.subarray(2);\n\n\t\t// Need full body\n\t\tif (bodyStart.length < size) return undefined;\n\n\t\tconst body = bodyStart.subarray(0, size);\n\n\t\t// Decode requestId from body (QUIC varint)\n\t\tconst [reqId] = Varint.decode(body);\n\t\tconst requestId = BigInt(reqId);\n\n\t\t// PublishNamespace (0x06): also parse namespace for v14/v15 reverse lookup\n\t\tif (typeId === 0x06) {\n\t\t\ttry {\n\t\t\t\tconst [, afterReqId] = Varint.decode(body);\n\t\t\t\tthis.#parseAndRegisterNamespace(afterReqId, requestId);\n\t\t\t} catch {\n\t\t\t\t// Non-critical: only needed for v14/v15 PublishNamespaceDone/Cancel\n\t\t\t}\n\t\t}\n\n\t\t// SubscribeNamespace (0x11): register for follow-up routing\n\t\tif (typeId === 0x11) {\n\t\t\tthis.#subscribeNamespaces.add(requestId);\n\t\t}\n\n\t\treturn { requestId };\n\t}\n\n\t/**\n\t * Parse a namespace from raw bytes and register it for reverse lookup.\n\t */\n\t#parseAndRegisterNamespace(buf: Uint8Array, requestId: bigint) {\n\t\tconst decoder = new TextDecoder();\n\t\tconst [partCount, afterCount] = Varint.decode(buf);\n\t\tlet cursor = afterCount;\n\t\tconst parts: string[] = [];\n\t\tfor (let i = 0; i < partCount; i++) {\n\t\t\tconst [len, afterLen] = Varint.decode(cursor);\n\t\t\tparts.push(decoder.decode(afterLen.subarray(0, len)));\n\t\t\tcursor = afterLen.subarray(len);\n\t\t}\n\t\tconst namespace = parts.join(\"/\");\n\t\tthis.#namespaces.set(namespace, requestId);\n\t\tthis.#namespacesByRequestId.set(requestId, namespace);\n\t}\n\n\t/** Create a WritableStream that buffers and writes complete messages to the control stream under mutex. */\n\t#createSendWritable(): WritableStream<Uint8Array> {\n\t\tlet buffer = new Uint8Array(0);\n\t\treturn new WritableStream<Uint8Array>({\n\t\t\twrite: async (chunk) => {\n\t\t\t\tconst newBuf = new Uint8Array(buffer.length + chunk.length);\n\t\t\t\tnewBuf.set(buffer);\n\t\t\t\tnewBuf.set(chunk, buffer.length);\n\t\t\t\tbuffer = newBuf;\n\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst boundary = this.#messageSize(buffer);\n\t\t\t\t\tif (boundary === undefined) break;\n\n\t\t\t\t\tconst toFlush = buffer.subarray(0, boundary);\n\t\t\t\t\tbuffer = buffer.subarray(boundary);\n\t\t\t\t\tawait this.#writeMutex.runExclusive(() => this.#writer.write(toFlush));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\t/** Encode raw message bytes: [typeId varint][size u16 BE][body] */\n\t#encodeRaw(typeId: number, size: number, body: Uint8Array): Uint8Array {\n\t\t// v14-v16 always use QUIC varint\n\t\tconst typeIdBytes = Varint.encodeTo(new ArrayBuffer(9), typeId);\n\t\tconst result = new Uint8Array(typeIdBytes.byteLength + 2 + body.byteLength);\n\t\tresult.set(typeIdBytes, 0);\n\t\tconst sizeView = new DataView(result.buffer, typeIdBytes.byteLength, 2);\n\t\tsizeView.setUint16(0, size);\n\t\tresult.set(body, typeIdBytes.byteLength + 2);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Classify a control message and extract its requestId for routing.\n\t */\n\tasync #classify(\n\t\ttypeId: number,\n\t\tbody: Uint8Array,\n\t): Promise<{ route: typeof Route.GoAway } | { route: Exclude<Route, typeof Route.GoAway>; requestId: bigint }> {\n\t\tconst readRequestId = async (): Promise<bigint> => {\n\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\treturn await r.u62();\n\t\t};\n\n\t\tconst readNamespaceRequestId = async (): Promise<bigint> => {\n\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\tconst namespace = await Namespace.decode(r);\n\t\t\tconst requestId = this.#namespaces.get(namespace);\n\t\t\tif (requestId === undefined) throw new Error(`unknown namespace: ${namespace}`);\n\t\t\tthis.#namespaces.delete(namespace);\n\t\t\treturn requestId;\n\t\t};\n\n\t\tswitch (typeId) {\n\t\t\t// === FollowUp: route to existing stream ===\n\t\t\tcase 0x02: {\n\t\t\t\t// SubscribeUpdate / REQUEST_UPDATE\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.FollowUp, requestId };\n\t\t\t}\n\n\t\t\t// === NewRequest: create virtual stream ===\n\t\t\tcase 0x03: // Subscribe\n\t\t\tcase 0x16: // Fetch\n\t\t\tcase 0x1d: // Publish\n\t\t\tcase 0x0d: {\n\t\t\t\t// TrackStatusRequest\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\t\t\tcase 0x06: {\n\t\t\t\t// PublishNamespace — also store namespace for v14/v15 reverse lookup\n\t\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\t\tconst requestId = await r.u62();\n\t\t\t\tconst namespace = await Namespace.decode(r);\n\t\t\t\tthis.#namespaces.set(namespace, requestId);\n\t\t\t\tthis.#namespacesByRequestId.set(requestId, namespace);\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\t\t\tcase 0x11: {\n\t\t\t\t// SubscribeNamespace (v14/v15 only on control stream)\n\t\t\t\tif (this.version !== Version.DRAFT_14 && this.version !== Version.DRAFT_15) {\n\t\t\t\t\tthrow new Error(\"unexpected SubscribeNamespace on control stream\");\n\t\t\t\t}\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\n\t\t\t// === Response: push bytes, keep stream open ===\n\t\t\tcase 0x04: {\n\t\t\t\t// SubscribeOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x18: {\n\t\t\t\t// FetchOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x1e: {\n\t\t\t\t// PublishOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x07: {\n\t\t\t\t// v14: PublishNamespaceOk, v15+: RequestOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x12: {\n\t\t\t\t// SubscribeNamespaceOk (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected SubscribeNamespaceOk\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\n\t\t\t// === ErrorResponse: push bytes + close ===\n\t\t\tcase 0x05: {\n\t\t\t\t// SubscribeError (v14) / RequestError (v15+)\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x19: {\n\t\t\t\t// FetchError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected FetchError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x1f: {\n\t\t\t\t// PublishError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected PublishError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x08: {\n\t\t\t\tif (this.version === Version.DRAFT_14) {\n\t\t\t\t\t// PublishNamespaceError\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t\t}\n\t\t\t\t// v15: Namespace entry (no requestId) — route to SubscribeNamespace stream\n\t\t\t\tconst subNs08 = this.#subscribeNamespaces.values().next().value;\n\t\t\t\tif (subNs08 === undefined) throw new Error(\"unexpected message 0x08: no SubscribeNamespace stream\");\n\t\t\t\treturn { route: Route.FollowUp, requestId: subNs08 };\n\t\t\t}\n\t\t\tcase 0x0e: {\n\t\t\t\t// v15: NamespaceDone entry (no requestId) — route to SubscribeNamespace stream\n\t\t\t\tconst subNs0e = this.#subscribeNamespaces.values().next().value;\n\t\t\t\tif (subNs0e === undefined) throw new Error(\"unexpected message 0x0e: no SubscribeNamespace stream\");\n\t\t\t\treturn { route: Route.FollowUp, requestId: subNs0e };\n\t\t\t}\n\t\t\tcase 0x13: {\n\t\t\t\t// SubscribeNamespaceError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected SubscribeNamespaceError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\n\t\t\t// === CloseStream: close recv (no bytes pushed) ===\n\t\t\tcase 0x0a: {\n\t\t\t\t// Unsubscribe\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x0b: {\n\t\t\t\t// PublishDone\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x17: {\n\t\t\t\t// FetchCancel\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x09: {\n\t\t\t\t// PublishNamespaceDone: v16 uses requestId, v14/v15 uses namespace\n\t\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t\t}\n\t\t\t\tconst requestId = await readNamespaceRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x0c: {\n\t\t\t\t// PublishNamespaceCancel: v16 uses requestId, v14/v15 uses namespace\n\t\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t\t}\n\t\t\t\tconst requestId = await readNamespaceRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x14: {\n\t\t\t\t// UnsubscribeNamespace (v14/v15 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14 && this.version !== Version.DRAFT_15) {\n\t\t\t\t\tthrow new Error(\"unexpected UnsubscribeNamespace\");\n\t\t\t\t}\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\n\t\t\t// === Utility ===\n\t\t\tcase 0x15: {\n\t\t\t\t// MaxRequestId\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.MaxRequestId, requestId };\n\t\t\t}\n\t\t\tcase 0x1a: {\n\t\t\t\t// RequestsBlocked — connection-level, consume and ignore\n\t\t\t\tawait readRequestId();\n\t\t\t\treturn { route: Route.Ignore, requestId: 0n };\n\t\t\t}\n\n\t\t\t// === Terminal ===\n\t\t\tcase 0x10: // GoAway\n\t\t\t\treturn { route: Route.GoAway };\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`unknown control message type: 0x${typeId.toString(16)}`);\n\t\t}\n\t}\n\n\tclose() {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tconsole.debug(\"adapter: close() called\");\n\n\t\t// Close all virtual streams\n\t\tfor (const entry of this.#streams.values()) {\n\t\t\ttry {\n\t\t\t\tentry.controller.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t}\n\t\tthis.#streams.clear();\n\n\t\t// Resolve any waiting acceptBi callers\n\t\tfor (const waiter of this.#incomingWaiters) {\n\t\t\twaiter(undefined);\n\t\t}\n\t\tthis.#incomingWaiters = [];\n\n\t\t// Clear namespace mappings\n\t\tthis.#namespaces.clear();\n\t\tthis.#namespacesByRequestId.clear();\n\t\tthis.#subscribeNamespaces.clear();\n\n\t\t// Unblock maxRequestId waiters\n\t\tfor (const resolve of this.#maxRequestIdResolves) resolve();\n\t\tthis.#maxRequestIdResolves = [];\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/ietf/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import { Mutex } from \"async-mutex\";\nimport { Reader, Stream, type Writer } from \"../stream.ts\";\nimport { decodeUtf8 } from \"../util/utf8.ts\";\nimport * as Varint from \"../varint.ts\";\nimport * as Namespace from \"./namespace.ts\";\nimport { type IetfVersion, Version } from \"./version.ts\";\n\n/**\n * Interface for opening outgoing bidi streams and allocating request IDs.\n * Implemented by both ControlStreamAdapter (v14-v16) and NativeSession (v17).\n */\nexport interface Session {\n\topenBi(): Stream | Promise<Stream>;\n\topenNativeBi?(): Promise<Stream>;\n\tacceptBi(): Promise<Stream | undefined>;\n\tnextRequestId(): Promise<bigint | undefined>;\n\tclose(): void;\n\treadonly version: IetfVersion;\n}\n\n/**\n * v17 native session — thin wrapper around WebTransport.\n * Each request gets its own real bidi stream; no control stream multiplexing.\n */\nexport class NativeSession implements Session {\n\t#quic: WebTransport;\n\t// moq-transport reserves even request IDs for the client and odd for the server,\n\t// so the two peers' ID spaces never overlap.\n\t#requestId: bigint;\n\treadonly version: IetfVersion;\n\n\tconstructor(quic: WebTransport, version: IetfVersion, client: boolean) {\n\t\tthis.#quic = quic;\n\t\tthis.version = version;\n\t\tthis.#requestId = client ? 0n : 1n;\n\t}\n\n\tasync openBi(): Promise<Stream> {\n\t\treturn Stream.open(this.#quic, { version: this.version });\n\t}\n\n\tasync acceptBi(): Promise<Stream | undefined> {\n\t\treturn Stream.accept(this.#quic, this.version);\n\t}\n\n\tasync nextRequestId(): Promise<bigint | undefined> {\n\t\tconst id = this.#requestId;\n\t\tthis.#requestId += 2n;\n\t\treturn id;\n\t}\n\n\t/** Closes the underlying WebTransport session. */\n\tclose() {\n\t\tthis.#quic.close();\n\t}\n}\n\n// Route classification for control stream messages.\nconst Route = {\n\tNewRequest: 0, // Create virtual bidi stream, push initial message\n\tResponse: 1, // Push message to existing stream (keep open)\n\tErrorResponse: 2, // Push message to existing stream, then close\n\tCloseStream: 3, // Close stream recv (no bytes pushed)\n\tFollowUp: 4, // Push follow-up message to existing stream\n\tMaxRequestId: 5, // Update flow control\n\tIgnore: 6, // Connection-level, no routing\n\tGoAway: 7, // Terminal\n} as const;\ntype Route = (typeof Route)[keyof typeof Route];\n\ninterface StreamEntry {\n\tcontroller: ReadableStreamDefaultController<Uint8Array>;\n}\n\n/**\n * Converts v14-v16 control stream multiplexing into virtual bidi streams.\n *\n * Reads control messages, classifies them, and routes to virtual Stream objects.\n * Each request/response pair gets its own virtual Stream, making all versions\n * look like v17's stream-per-request model.\n */\nexport class ControlStreamAdapter implements Session {\n\t// WebTransport session (for opening real bidi streams in v16)\n\t#quic: WebTransport;\n\n\t// Control stream\n\t#reader: Reader;\n\t#writer: Writer;\n\t#writeMutex = new Mutex();\n\treadonly version: IetfVersion;\n\n\t// Virtual streams keyed by requestId\n\t#streams = new Map<bigint, StreamEntry>();\n\n\t// Namespace → requestId reverse lookup (v14/v15 namespace-keyed messages)\n\t#namespaces = new Map<string, bigint>();\n\n\t// requestId → namespace reverse lookup (for cleanup in #closeStream)\n\t#namespacesByRequestId = new Map<bigint, string>();\n\n\t// SubscribeNamespace requestIds — for routing 0x08/0x0E entries that lack requestId (v14/v15)\n\t#subscribeNamespaces = new Set<bigint>();\n\n\t// Incoming stream queue (for acceptBi)\n\t#incomingQueue: Stream[] = [];\n\t#incomingWaiters: ((stream: Stream | undefined) => void)[] = [];\n\n\t// Request ID flow control. moq-transport reserves even request IDs for the\n\t// client and odd for the server, so the two peers' ID spaces never overlap.\n\t// This matters here because a single `#streams` map routes every request by\n\t// ID: overlapping spaces would let an inbound request clobber the routing\n\t// entry of an outbound one with the same number (e.g. an inbound\n\t// PUBLISH_NAMESPACE stealing a pending SUBSCRIBE's slot, so SUBSCRIBE_OK is\n\t// delivered to the wrong virtual stream).\n\t#requestId: bigint;\n\t#maxRequestId: bigint;\n\t#maxRequestIdResolves: (() => void)[] = [];\n\n\t#closed = false;\n\n\tconstructor(\n\t\tquic: WebTransport,\n\t\tcontrolStream: Stream,\n\t\tversion: IetfVersion,\n\t\tmaxRequestId: bigint,\n\t\tclient: boolean,\n\t) {\n\t\tthis.#quic = quic;\n\t\tthis.#reader = controlStream.reader;\n\t\tthis.#reader.version = version;\n\t\tthis.#writer = controlStream.writer;\n\t\tthis.#writer.version = version;\n\t\tthis.version = version;\n\t\tthis.#maxRequestId = maxRequestId;\n\t\tthis.#requestId = client ? 0n : 1n;\n\t}\n\n\t/**\n\t * Accept the next incoming virtual bidi stream.\n\t * Blocks until a new request arrives on the control stream.\n\t */\n\tasync acceptBi(): Promise<Stream | undefined> {\n\t\tif (this.#closed) return undefined;\n\n\t\tconst queued = this.#incomingQueue.shift();\n\t\tif (queued) return queued;\n\n\t\treturn new Promise<Stream | undefined>((resolve) => {\n\t\t\tthis.#incomingWaiters.push(resolve);\n\t\t});\n\t}\n\n\t/**\n\t * Open an outgoing virtual bidi stream.\n\t * Buffers writes until the first full message is available, parses the\n\t * requestId (and namespace for PublishNamespace), self-registers, then\n\t * flushes. Subsequent writes go directly to the control stream.\n\t */\n\topenBi(): Stream {\n\t\tlet controller!: ReadableStreamDefaultController<Uint8Array>;\n\t\tlet registeredRequestId: bigint | undefined;\n\n\t\tconst readable = new ReadableStream<Uint8Array>({\n\t\t\tstart(c) {\n\t\t\t\tcontroller = c;\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tif (registeredRequestId !== undefined) {\n\t\t\t\t\tthis.#streams.delete(registeredRequestId);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tlet buffer = new Uint8Array(0);\n\t\tlet registered = false;\n\n\t\tconst sendWritable = new WritableStream<Uint8Array>({\n\t\t\twrite: async (chunk) => {\n\t\t\t\t// Always accumulate bytes and flush only complete messages\n\t\t\t\t// to prevent interleaving of partial messages from concurrent virtual streams.\n\t\t\t\tconst newBuf = new Uint8Array(buffer.length + chunk.length);\n\t\t\t\tnewBuf.set(buffer);\n\t\t\t\tnewBuf.set(chunk, buffer.length);\n\t\t\t\tbuffer = newBuf;\n\n\t\t\t\t// Try to flush complete messages from the buffer\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst boundary = this.#messageSize(buffer);\n\t\t\t\t\tif (boundary === undefined) break;\n\n\t\t\t\t\tconst toFlush = buffer.subarray(0, boundary);\n\t\t\t\t\tbuffer = buffer.subarray(boundary);\n\n\t\t\t\t\tif (!registered) {\n\t\t\t\t\t\t// First message: extract requestId and register before flushing\n\t\t\t\t\t\tconst parsed = this.#tryParseOutgoing(toFlush);\n\t\t\t\t\t\tif (parsed) {\n\t\t\t\t\t\t\tregisteredRequestId = parsed.requestId;\n\t\t\t\t\t\t\tthis.#streams.set(parsed.requestId, { controller });\n\t\t\t\t\t\t\tregistered = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tawait this.#writeMutex.runExclusive(() => this.#writer.write(toFlush));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\tconst stream = new Stream({ readable, writable: sendWritable });\n\t\tstream.reader.version = this.version;\n\t\tstream.writer.version = this.version;\n\t\treturn stream;\n\t}\n\n\t/**\n\t * Open a real WebTransport bidi stream (for v16 SubscribeNamespace).\n\t */\n\tasync openNativeBi(): Promise<Stream> {\n\t\treturn Stream.open(this.#quic, { version: this.version });\n\t}\n\n\t/**\n\t * Allocate the next request ID, blocking if flow control limit reached.\n\t */\n\tasync nextRequestId(): Promise<bigint | undefined> {\n\t\tfor (;;) {\n\t\t\tif (this.#closed) return undefined;\n\t\t\tconst id = this.#requestId;\n\t\t\tif (id < this.#maxRequestId) {\n\t\t\t\tthis.#requestId += 2n;\n\t\t\t\treturn id;\n\t\t\t}\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\tthis.#maxRequestIdResolves.push(resolve);\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Main run loop — reads control stream messages and routes to virtual streams.\n\t * Must be called after construction. Runs until the control stream closes.\n\t */\n\tasync run(): Promise<void> {\n\t\ttry {\n\t\t\t// v16: also accept real bidi streams (for SubscribeNamespace)\n\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\tvoid this.#acceptNativeBidis();\n\t\t\t}\n\n\t\t\tfor (;;) {\n\t\t\t\tconst done = await this.#reader.done();\n\t\t\t\tif (done) break;\n\n\t\t\t\tconst typeId = await this.#reader.u53();\n\t\t\t\tconst size = await this.#reader.u16();\n\t\t\t\tconst body = await this.#reader.read(size);\n\n\t\t\t\tconst classified = await this.#classify(typeId, body);\n\n\t\t\t\tif (classified.route === Route.GoAway) {\n\t\t\t\t\tconsole.warn(\"received GOAWAY on control stream\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { route, requestId } = classified;\n\n\t\t\t\tswitch (route) {\n\t\t\t\t\tcase Route.NewRequest:\n\t\t\t\t\t\tthis.#newRequest(typeId, size, body, requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.Response:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.ErrorResponse:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tthis.#closeStream(requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.CloseStream:\n\t\t\t\t\t\tthis.#closeStream(requestId);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.FollowUp:\n\t\t\t\t\t\tthis.#pushMessage(requestId, typeId, size, body);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase Route.MaxRequestId:\n\t\t\t\t\t\tthis.#maxRequestId = requestId;\n\t\t\t\t\t\tfor (const resolve of this.#maxRequestIdResolves) resolve();\n\t\t\t\t\t\tthis.#maxRequestIdResolves = [];\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\t/** Accept real WebTransport bidi streams and queue them for acceptBi (v16). */\n\tasync #acceptNativeBidis(): Promise<void> {\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst stream = await Stream.accept(this.#quic, this.version);\n\t\t\t\tif (!stream) break;\n\n\t\t\t\tconst waiter = this.#incomingWaiters.shift();\n\t\t\t\tif (waiter) {\n\t\t\t\t\twaiter(stream);\n\t\t\t\t} else {\n\t\t\t\t\tthis.#incomingQueue.push(stream);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Session closed\n\t\t}\n\t}\n\n\t#newRequest(typeId: number, size: number, body: Uint8Array, requestId: bigint) {\n\t\tlet controller!: ReadableStreamDefaultController<Uint8Array>;\n\t\tconst readable = new ReadableStream<Uint8Array>({\n\t\t\tstart(c) {\n\t\t\t\tcontroller = c;\n\t\t\t},\n\t\t\tcancel: () => {\n\t\t\t\tthis.#streams.delete(requestId);\n\t\t\t},\n\t\t});\n\n\t\tconst sendWritable = this.#createSendWritable();\n\n\t\tconst stream = new Stream({ readable, writable: sendWritable });\n\t\tstream.reader.version = this.version;\n\t\tstream.writer.version = this.version;\n\n\t\tthis.#streams.set(requestId, { controller });\n\n\t\t// Push initial message bytes so the dispatcher can read typeId + decode\n\t\tcontroller.enqueue(this.#encodeRaw(typeId, size, body));\n\n\t\t// Queue for acceptBi\n\t\tconst waiter = this.#incomingWaiters.shift();\n\t\tif (waiter) {\n\t\t\twaiter(stream);\n\t\t} else {\n\t\t\tthis.#incomingQueue.push(stream);\n\t\t}\n\t}\n\n\t#pushMessage(requestId: bigint, typeId: number, size: number, body: Uint8Array) {\n\t\tconst entry = this.#streams.get(requestId);\n\t\tif (!entry) {\n\t\t\tconsole.warn(`adapter: no stream for requestId=${requestId} typeId=0x${typeId.toString(16)}`);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tentry.controller.enqueue(this.#encodeRaw(typeId, size, body));\n\t\t} catch {\n\t\t\t// Stream already closed\n\t\t}\n\t}\n\n\t#closeStream(requestId: bigint) {\n\t\tconst entry = this.#streams.get(requestId);\n\t\tif (!entry) return;\n\t\tconsole.debug(`adapter: closing stream requestId=${requestId}`);\n\t\tthis.#streams.delete(requestId);\n\t\tthis.#subscribeNamespaces.delete(requestId);\n\t\tconst namespace = this.#namespacesByRequestId.get(requestId);\n\t\tif (namespace !== undefined) {\n\t\t\tthis.#namespaces.delete(namespace);\n\t\t\tthis.#namespacesByRequestId.delete(requestId);\n\t\t}\n\t\ttry {\n\t\t\tentry.controller.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\t}\n\n\t/**\n\t * Returns the total byte size of the first complete message in buffer,\n\t * or undefined if the buffer doesn't contain a complete message yet.\n\t * Message format: [typeId varint][size u16 BE][body of `size` bytes]\n\t */\n\t#messageSize(buffer: Uint8Array): number | undefined {\n\t\tif (buffer.length === 0) return undefined;\n\n\t\tconst typeSize = 1 << ((buffer[0] & 0xc0) >> 6);\n\t\tif (buffer.length < typeSize) return undefined;\n\n\t\tconst [, afterType] = Varint.decode(buffer);\n\t\tif (afterType.length < 2) return undefined;\n\n\t\tconst size = (afterType[0] << 8) | afterType[1];\n\t\tconst totalSize = buffer.length - afterType.length + 2 + size;\n\t\tif (buffer.length < totalSize) return undefined;\n\n\t\treturn totalSize;\n\t}\n\n\t/**\n\t * Try to parse the first outgoing message from accumulated bytes.\n\t * Returns the requestId if enough data is available, undefined otherwise.\n\t */\n\t#tryParseOutgoing(buffer: Uint8Array): { requestId: bigint } | undefined {\n\t\tif (buffer.length === 0) return undefined;\n\n\t\t// Check typeId varint size before decoding\n\t\tconst typeSize = 1 << ((buffer[0] & 0xc0) >> 6);\n\t\tif (buffer.length < typeSize) return undefined;\n\n\t\tconst [typeId, afterType] = Varint.decode(buffer);\n\n\t\t// Need 2 bytes for u16 size\n\t\tif (afterType.length < 2) return undefined;\n\n\t\tconst size = (afterType[0] << 8) | afterType[1];\n\t\tconst bodyStart = afterType.subarray(2);\n\n\t\t// Need full body\n\t\tif (bodyStart.length < size) return undefined;\n\n\t\tconst body = bodyStart.subarray(0, size);\n\n\t\t// Decode requestId from body (QUIC varint)\n\t\tconst [reqId] = Varint.decode(body);\n\t\tconst requestId = BigInt(reqId);\n\n\t\t// PublishNamespace (0x06): also parse namespace for v14/v15 reverse lookup\n\t\tif (typeId === 0x06) {\n\t\t\ttry {\n\t\t\t\tconst [, afterReqId] = Varint.decode(body);\n\t\t\t\tthis.#parseAndRegisterNamespace(afterReqId, requestId);\n\t\t\t} catch {\n\t\t\t\t// Non-critical: only needed for v14/v15 PublishNamespaceDone/Cancel\n\t\t\t}\n\t\t}\n\n\t\t// SubscribeNamespace (0x11): register for follow-up routing\n\t\tif (typeId === 0x11) {\n\t\t\tthis.#subscribeNamespaces.add(requestId);\n\t\t}\n\n\t\treturn { requestId };\n\t}\n\n\t/**\n\t * Parse a namespace from raw bytes and register it for reverse lookup.\n\t */\n\t#parseAndRegisterNamespace(buf: Uint8Array, requestId: bigint) {\n\t\tconst [partCount, afterCount] = Varint.decode(buf);\n\t\tlet cursor = afterCount;\n\t\tconst parts: string[] = [];\n\t\tfor (let i = 0; i < partCount; i++) {\n\t\t\tconst [len, afterLen] = Varint.decode(cursor);\n\t\t\tparts.push(decodeUtf8(afterLen.subarray(0, len)));\n\t\t\tcursor = afterLen.subarray(len);\n\t\t}\n\t\tconst namespace = Namespace.fromTuple(parts);\n\t\tthis.#namespaces.set(namespace, requestId);\n\t\tthis.#namespacesByRequestId.set(requestId, namespace);\n\t}\n\n\t/** Create a WritableStream that buffers and writes complete messages to the control stream under mutex. */\n\t#createSendWritable(): WritableStream<Uint8Array> {\n\t\tlet buffer = new Uint8Array(0);\n\t\treturn new WritableStream<Uint8Array>({\n\t\t\twrite: async (chunk) => {\n\t\t\t\tconst newBuf = new Uint8Array(buffer.length + chunk.length);\n\t\t\t\tnewBuf.set(buffer);\n\t\t\t\tnewBuf.set(chunk, buffer.length);\n\t\t\t\tbuffer = newBuf;\n\n\t\t\t\tfor (;;) {\n\t\t\t\t\tconst boundary = this.#messageSize(buffer);\n\t\t\t\t\tif (boundary === undefined) break;\n\n\t\t\t\t\tconst toFlush = buffer.subarray(0, boundary);\n\t\t\t\t\tbuffer = buffer.subarray(boundary);\n\t\t\t\t\tawait this.#writeMutex.runExclusive(() => this.#writer.write(toFlush));\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t}\n\n\t/** Encode raw message bytes: [typeId varint][size u16 BE][body] */\n\t#encodeRaw(typeId: number, size: number, body: Uint8Array): Uint8Array {\n\t\t// v14-v16 always use QUIC varint\n\t\tconst typeIdBytes = Varint.encodeTo(new ArrayBuffer(9), typeId);\n\t\tconst result = new Uint8Array(typeIdBytes.byteLength + 2 + body.byteLength);\n\t\tresult.set(typeIdBytes, 0);\n\t\tconst sizeView = new DataView(result.buffer, typeIdBytes.byteLength, 2);\n\t\tsizeView.setUint16(0, size);\n\t\tresult.set(body, typeIdBytes.byteLength + 2);\n\t\treturn result;\n\t}\n\n\t/**\n\t * Classify a control message and extract its requestId for routing.\n\t */\n\tasync #classify(\n\t\ttypeId: number,\n\t\tbody: Uint8Array,\n\t): Promise<{ route: typeof Route.GoAway } | { route: Exclude<Route, typeof Route.GoAway>; requestId: bigint }> {\n\t\tconst readRequestId = async (): Promise<bigint> => {\n\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\treturn await r.u62();\n\t\t};\n\n\t\tconst readNamespaceRequestId = async (): Promise<bigint> => {\n\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\tconst namespace = await Namespace.decode(r);\n\t\t\tconst requestId = this.#namespaces.get(namespace);\n\t\t\tif (requestId === undefined) throw new Error(`unknown namespace: ${namespace}`);\n\t\t\tthis.#namespaces.delete(namespace);\n\t\t\treturn requestId;\n\t\t};\n\n\t\tswitch (typeId) {\n\t\t\t// === FollowUp: route to existing stream ===\n\t\t\tcase 0x02: {\n\t\t\t\t// SubscribeUpdate / REQUEST_UPDATE\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.FollowUp, requestId };\n\t\t\t}\n\n\t\t\t// === NewRequest: create virtual stream ===\n\t\t\tcase 0x03: // Subscribe\n\t\t\tcase 0x16: // Fetch\n\t\t\tcase 0x1d: // Publish\n\t\t\tcase 0x0d: {\n\t\t\t\t// TrackStatusRequest\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\t\t\tcase 0x06: {\n\t\t\t\t// PublishNamespace — also store namespace for v14/v15 reverse lookup\n\t\t\t\tconst r = new Reader(undefined, body, this.version);\n\t\t\t\tconst requestId = await r.u62();\n\t\t\t\tconst namespace = await Namespace.decode(r);\n\t\t\t\tthis.#namespaces.set(namespace, requestId);\n\t\t\t\tthis.#namespacesByRequestId.set(requestId, namespace);\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\t\t\tcase 0x11: {\n\t\t\t\t// SubscribeNamespace (v14/v15 only on control stream)\n\t\t\t\tif (this.version !== Version.DRAFT_14 && this.version !== Version.DRAFT_15) {\n\t\t\t\t\tthrow new Error(\"unexpected SubscribeNamespace on control stream\");\n\t\t\t\t}\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.NewRequest, requestId };\n\t\t\t}\n\n\t\t\t// === Response: push bytes, keep stream open ===\n\t\t\tcase 0x04: {\n\t\t\t\t// SubscribeOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x18: {\n\t\t\t\t// FetchOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x1e: {\n\t\t\t\t// PublishOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x07: {\n\t\t\t\t// v14: PublishNamespaceOk, v15+: RequestOk\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\t\t\tcase 0x12: {\n\t\t\t\t// SubscribeNamespaceOk (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected SubscribeNamespaceOk\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.Response, requestId };\n\t\t\t}\n\n\t\t\t// === ErrorResponse: push bytes + close ===\n\t\t\tcase 0x05: {\n\t\t\t\t// SubscribeError (v14) / RequestError (v15+)\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x19: {\n\t\t\t\t// FetchError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected FetchError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x1f: {\n\t\t\t\t// PublishError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected PublishError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\t\t\tcase 0x08: {\n\t\t\t\tif (this.version === Version.DRAFT_14) {\n\t\t\t\t\t// PublishNamespaceError\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t\t}\n\t\t\t\t// v15: Namespace entry (no requestId) — route to SubscribeNamespace stream\n\t\t\t\tconst subNs08 = this.#subscribeNamespaces.values().next().value;\n\t\t\t\tif (subNs08 === undefined) throw new Error(\"unexpected message 0x08: no SubscribeNamespace stream\");\n\t\t\t\treturn { route: Route.FollowUp, requestId: subNs08 };\n\t\t\t}\n\t\t\tcase 0x0e: {\n\t\t\t\t// v15: NamespaceDone entry (no requestId) — route to SubscribeNamespace stream\n\t\t\t\tconst subNs0e = this.#subscribeNamespaces.values().next().value;\n\t\t\t\tif (subNs0e === undefined) throw new Error(\"unexpected message 0x0e: no SubscribeNamespace stream\");\n\t\t\t\treturn { route: Route.FollowUp, requestId: subNs0e };\n\t\t\t}\n\t\t\tcase 0x13: {\n\t\t\t\t// SubscribeNamespaceError (v14 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14) throw new Error(\"unexpected SubscribeNamespaceError\");\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.ErrorResponse, requestId };\n\t\t\t}\n\n\t\t\t// === CloseStream: close recv (no bytes pushed) ===\n\t\t\tcase 0x0a: {\n\t\t\t\t// Unsubscribe\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x0b: {\n\t\t\t\t// PublishDone\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x17: {\n\t\t\t\t// FetchCancel\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x09: {\n\t\t\t\t// PublishNamespaceDone: v16 uses requestId, v14/v15 uses namespace\n\t\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t\t}\n\t\t\t\tconst requestId = await readNamespaceRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x0c: {\n\t\t\t\t// PublishNamespaceCancel: v16 uses requestId, v14/v15 uses namespace\n\t\t\t\tif (this.version === Version.DRAFT_16) {\n\t\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t\t}\n\t\t\t\tconst requestId = await readNamespaceRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\t\t\tcase 0x14: {\n\t\t\t\t// UnsubscribeNamespace (v14/v15 only)\n\t\t\t\tif (this.version !== Version.DRAFT_14 && this.version !== Version.DRAFT_15) {\n\t\t\t\t\tthrow new Error(\"unexpected UnsubscribeNamespace\");\n\t\t\t\t}\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.CloseStream, requestId };\n\t\t\t}\n\n\t\t\t// === Utility ===\n\t\t\tcase 0x15: {\n\t\t\t\t// MaxRequestId\n\t\t\t\tconst requestId = await readRequestId();\n\t\t\t\treturn { route: Route.MaxRequestId, requestId };\n\t\t\t}\n\t\t\tcase 0x1a: {\n\t\t\t\t// RequestsBlocked — connection-level, consume and ignore\n\t\t\t\tawait readRequestId();\n\t\t\t\treturn { route: Route.Ignore, requestId: 0n };\n\t\t\t}\n\n\t\t\t// === Terminal ===\n\t\t\tcase 0x10: // GoAway\n\t\t\t\treturn { route: Route.GoAway };\n\n\t\t\tdefault:\n\t\t\t\tthrow new Error(`unknown control message type: 0x${typeId.toString(16)}`);\n\t\t}\n\t}\n\n\tclose() {\n\t\tif (this.#closed) return;\n\t\tthis.#closed = true;\n\t\tconsole.debug(\"adapter: close() called\");\n\n\t\t// Close all virtual streams\n\t\tfor (const entry of this.#streams.values()) {\n\t\t\ttry {\n\t\t\t\tentry.controller.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t}\n\t\tthis.#streams.clear();\n\n\t\t// Resolve any waiting acceptBi callers\n\t\tfor (const waiter of this.#incomingWaiters) {\n\t\t\twaiter(undefined);\n\t\t}\n\t\tthis.#incomingWaiters = [];\n\n\t\t// Clear namespace mappings\n\t\tthis.#namespaces.clear();\n\t\tthis.#namespacesByRequestId.clear();\n\t\tthis.#subscribeNamespaces.clear();\n\n\t\t// Unblock maxRequestId waiters\n\t\tfor (const resolve of this.#maxRequestIdResolves) resolve();\n\t\tthis.#maxRequestIdResolves = [];\n\t}\n}\n"]}
|
package/ietf/aliases.d.ts
CHANGED
|
@@ -1,11 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The full track name an alias is bound to.
|
|
3
|
+
*
|
|
4
|
+
* Kept as two components rather than one joined string: a track name may contain the same
|
|
5
|
+
* separator a broadcast path uses, so `a` + `b/c` and `a/b` + `c` would otherwise compare
|
|
6
|
+
* equal and turn a genuine collision into apparent sharing.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export type TrackIdentity = {
|
|
10
|
+
broadcast: string;
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Thrown when a group arrives for a subscription we already cancelled.
|
|
15
|
+
*
|
|
16
|
+
* The publisher only stops once our cancellation reaches it, so objects keep arriving for
|
|
17
|
+
* at least a round trip afterwards. Draft-19 section 11.1 asks us to keep enough state to
|
|
18
|
+
* discard them quickly "rather than treating them as belonging to an unknown Track Alias".
|
|
19
|
+
*
|
|
20
|
+
* This makes the window quiet, not safe. Once a publisher reassigns the alias the tombstone
|
|
21
|
+
* is reclaimed, and nothing on a group stream distinguishes the old subscription's objects
|
|
22
|
+
* from the new one's. Cancelling promptly is what bounds the exposure to a round trip.
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
export declare class RetiredTrackAlias extends Error {
|
|
26
|
+
constructor(alias: bigint);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Thrown when a publisher gives one alias to two subscriptions of the same track.
|
|
30
|
+
*
|
|
31
|
+
* Draft-19 section 5.1 permits this and expects the subscriber to demux by re-applying
|
|
32
|
+
* each subscription's filter. Ours are all LargestObject, so they are indistinguishable and
|
|
33
|
+
* we cannot, which costs the one subscription. It is not a protocol error, so it must not
|
|
34
|
+
* take the session down with it.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export declare class SharedTrackAlias extends Error {
|
|
38
|
+
constructor(alias: bigint);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Thrown when a publisher points one alias at two different tracks at once, which
|
|
42
|
+
* draft-19 section 11.1 makes fatal to the session.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export declare class DuplicateTrackAlias extends Error {
|
|
46
|
+
constructor(alias: bigint);
|
|
47
|
+
}
|
|
1
48
|
/** Resolves publisher-chosen track aliases after control/data stream reordering. @internal */
|
|
2
49
|
export declare class TrackAliases<T> {
|
|
3
50
|
#private;
|
|
4
|
-
/**
|
|
51
|
+
/**
|
|
52
|
+
* Waits briefly for an alias to be established by SUBSCRIBE_OK or PUBLISH.
|
|
53
|
+
*
|
|
54
|
+
* Throws {@link RetiredTrackAlias} at once for an alias we cancelled, rather than
|
|
55
|
+
* waiting out the timeout for a binding that is never coming.
|
|
56
|
+
*/
|
|
5
57
|
get(alias: bigint): Promise<T>;
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Establishes an alias and releases any data streams waiting for it.
|
|
60
|
+
*
|
|
61
|
+
* `track` is the full track name the alias was bound to, which is what decides whether a
|
|
62
|
+
* repeat is the legal sharing of an alias across subscriptions to one track
|
|
63
|
+
* ({@link SharedTrackAlias}) or the collision that must fail the session
|
|
64
|
+
* ({@link DuplicateTrackAlias}).
|
|
65
|
+
*/
|
|
66
|
+
set(alias: bigint, value: T, track: TrackIdentity): void;
|
|
67
|
+
/**
|
|
68
|
+
* Retires an alias whose subscription was cancelled, so groups still in flight for it
|
|
69
|
+
* are discarded promptly instead of reported as unknown.
|
|
70
|
+
*
|
|
71
|
+
* Only retires an alias that still belongs to the supplied value: a later subscription
|
|
72
|
+
* may already have reclaimed it, and that binding outranks a departing owner.
|
|
73
|
+
*
|
|
74
|
+
* Returns whether this caller still owned the binding, so metadata keyed by the alias is
|
|
75
|
+
* only torn down by the owner and never out from under whoever reclaimed it.
|
|
76
|
+
*/
|
|
77
|
+
retire(alias: bigint, value: T): boolean;
|
|
10
78
|
}
|
|
11
79
|
//# sourceMappingURL=aliases.d.ts.map
|
package/ietf/aliases.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../src/ietf/aliases.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"aliases.d.ts","sourceRoot":"","sources":["../../src/ietf/aliases.ts"],"names":[],"mappings":"AAiBA;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAMhE;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC3C,YAAY,KAAK,EAAE,MAAM,EAGxB;CACD;AAED;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IAC1C,YAAY,KAAK,EAAE,MAAM,EAGxB;CACD;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;IAC7C,YAAY,KAAK,EAAE,MAAM,EAGxB;CACD;AAED,8FAA8F;AAC9F,qBAAa,YAAY,CAAC,CAAC;;IAQ1B;;;;;OAKG;IACG,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAyBnC;IAED;;;;;;;OAOG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,aAAa,QAehD;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAcvC;CAOD"}
|
package/ietf/aliases.js
CHANGED
|
@@ -1,13 +1,83 @@
|
|
|
1
1
|
/* @ts-self-types="./aliases.d.ts" */
|
|
2
2
|
const TRACK_ALIAS_TIMEOUT_MS = 1000;
|
|
3
|
+
/**
|
|
4
|
+
* How many cancelled aliases to remember. Objects keep arriving for about a round trip
|
|
5
|
+
* after we cancel, so a handful covers the window, while the cap keeps a long session with
|
|
6
|
+
* heavy subscription churn from accumulating tombstones for its whole lifetime.
|
|
7
|
+
*
|
|
8
|
+
* The bound is a count rather than a deadline, so eviction stays synchronous with
|
|
9
|
+
* retirement instead of needing a timer. The trade is that a session cancelling more than
|
|
10
|
+
* this many distinct aliases inside one round trip evicts a tombstone whose objects are
|
|
11
|
+
* still arriving; those fall back to the unknown-alias wait, which is the old behavior
|
|
12
|
+
* rather than a new failure.
|
|
13
|
+
*/
|
|
14
|
+
const RETIRED_ALIAS_CAPACITY = 64;
|
|
15
|
+
function sameTrack(a, b) {
|
|
16
|
+
return a.broadcast === b.broadcast && a.name === b.name;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Thrown when a group arrives for a subscription we already cancelled.
|
|
20
|
+
*
|
|
21
|
+
* The publisher only stops once our cancellation reaches it, so objects keep arriving for
|
|
22
|
+
* at least a round trip afterwards. Draft-19 section 11.1 asks us to keep enough state to
|
|
23
|
+
* discard them quickly "rather than treating them as belonging to an unknown Track Alias".
|
|
24
|
+
*
|
|
25
|
+
* This makes the window quiet, not safe. Once a publisher reassigns the alias the tombstone
|
|
26
|
+
* is reclaimed, and nothing on a group stream distinguishes the old subscription's objects
|
|
27
|
+
* from the new one's. Cancelling promptly is what bounds the exposure to a round trip.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export class RetiredTrackAlias extends Error {
|
|
31
|
+
constructor(alias) {
|
|
32
|
+
super(`track alias retired: ${alias}`);
|
|
33
|
+
this.name = "RetiredTrackAlias";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Thrown when a publisher gives one alias to two subscriptions of the same track.
|
|
38
|
+
*
|
|
39
|
+
* Draft-19 section 5.1 permits this and expects the subscriber to demux by re-applying
|
|
40
|
+
* each subscription's filter. Ours are all LargestObject, so they are indistinguishable and
|
|
41
|
+
* we cannot, which costs the one subscription. It is not a protocol error, so it must not
|
|
42
|
+
* take the session down with it.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
export class SharedTrackAlias extends Error {
|
|
46
|
+
constructor(alias) {
|
|
47
|
+
super(`track alias shared by another subscription: ${alias}`);
|
|
48
|
+
this.name = "SharedTrackAlias";
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Thrown when a publisher points one alias at two different tracks at once, which
|
|
53
|
+
* draft-19 section 11.1 makes fatal to the session.
|
|
54
|
+
* @internal
|
|
55
|
+
*/
|
|
56
|
+
export class DuplicateTrackAlias extends Error {
|
|
57
|
+
constructor(alias) {
|
|
58
|
+
super(`duplicate track alias: ${alias}`);
|
|
59
|
+
this.name = "DuplicateTrackAlias";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
3
62
|
/** Resolves publisher-chosen track aliases after control/data stream reordering. @internal */
|
|
4
63
|
export class TrackAliases {
|
|
5
64
|
#active = new Map();
|
|
6
65
|
#pending = new Map();
|
|
7
|
-
/**
|
|
66
|
+
/** Aliases whose subscription we cancelled, in retirement order so the oldest is forgotten first. */
|
|
67
|
+
#retired = [];
|
|
68
|
+
#retiredSet = new Set();
|
|
69
|
+
/**
|
|
70
|
+
* Waits briefly for an alias to be established by SUBSCRIBE_OK or PUBLISH.
|
|
71
|
+
*
|
|
72
|
+
* Throws {@link RetiredTrackAlias} at once for an alias we cancelled, rather than
|
|
73
|
+
* waiting out the timeout for a binding that is never coming.
|
|
74
|
+
*/
|
|
8
75
|
async get(alias) {
|
|
9
|
-
|
|
10
|
-
|
|
76
|
+
const bound = this.#active.get(alias);
|
|
77
|
+
if (bound !== undefined)
|
|
78
|
+
return bound.value;
|
|
79
|
+
if (this.#retiredSet.has(alias))
|
|
80
|
+
throw new RetiredTrackAlias(alias);
|
|
11
81
|
const { promise, resolve } = Promise.withResolvers();
|
|
12
82
|
let resolvers = this.#pending.get(alias);
|
|
13
83
|
if (!resolvers) {
|
|
@@ -29,24 +99,61 @@ export class TrackAliases {
|
|
|
29
99
|
this.#pending.delete(alias);
|
|
30
100
|
}
|
|
31
101
|
}
|
|
32
|
-
/**
|
|
33
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Establishes an alias and releases any data streams waiting for it.
|
|
104
|
+
*
|
|
105
|
+
* `track` is the full track name the alias was bound to, which is what decides whether a
|
|
106
|
+
* repeat is the legal sharing of an alias across subscriptions to one track
|
|
107
|
+
* ({@link SharedTrackAlias}) or the collision that must fail the session
|
|
108
|
+
* ({@link DuplicateTrackAlias}).
|
|
109
|
+
*/
|
|
110
|
+
set(alias, value, track) {
|
|
34
111
|
const active = this.#active.get(alias);
|
|
35
|
-
if (
|
|
36
|
-
if (active
|
|
37
|
-
|
|
38
|
-
|
|
112
|
+
if (active !== undefined) {
|
|
113
|
+
if (active.value === value)
|
|
114
|
+
return;
|
|
115
|
+
throw sameTrack(active.track, track) ? new SharedTrackAlias(alias) : new DuplicateTrackAlias(alias);
|
|
39
116
|
}
|
|
40
|
-
|
|
117
|
+
// Our subscription is gone, so the publisher is free to point the alias somewhere
|
|
118
|
+
// new. Reclaiming it also drops the tombstone early.
|
|
119
|
+
this.#forget(alias);
|
|
120
|
+
this.#active.set(alias, { value, track });
|
|
41
121
|
const resolvers = this.#pending.get(alias);
|
|
42
122
|
this.#pending.delete(alias);
|
|
43
123
|
for (const resolve of resolvers ?? [])
|
|
44
124
|
resolve(value);
|
|
45
125
|
}
|
|
46
|
-
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Retires an alias whose subscription was cancelled, so groups still in flight for it
|
|
128
|
+
* are discarded promptly instead of reported as unknown.
|
|
129
|
+
*
|
|
130
|
+
* Only retires an alias that still belongs to the supplied value: a later subscription
|
|
131
|
+
* may already have reclaimed it, and that binding outranks a departing owner.
|
|
132
|
+
*
|
|
133
|
+
* Returns whether this caller still owned the binding, so metadata keyed by the alias is
|
|
134
|
+
* only torn down by the owner and never out from under whoever reclaimed it.
|
|
135
|
+
*/
|
|
136
|
+
retire(alias, value) {
|
|
137
|
+
if (this.#active.get(alias)?.value !== value)
|
|
138
|
+
return false;
|
|
139
|
+
this.#active.delete(alias);
|
|
140
|
+
if (this.#retiredSet.has(alias))
|
|
141
|
+
return true;
|
|
142
|
+
this.#retiredSet.add(alias);
|
|
143
|
+
this.#retired.push(alias);
|
|
144
|
+
while (this.#retired.length > RETIRED_ALIAS_CAPACITY) {
|
|
145
|
+
const oldest = this.#retired.shift();
|
|
146
|
+
if (oldest !== undefined)
|
|
147
|
+
this.#retiredSet.delete(oldest);
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
#forget(alias) {
|
|
152
|
+
if (!this.#retiredSet.delete(alias))
|
|
153
|
+
return;
|
|
154
|
+
const at = this.#retired.indexOf(alias);
|
|
155
|
+
if (at !== -1)
|
|
156
|
+
this.#retired.splice(at, 1);
|
|
50
157
|
}
|
|
51
158
|
}
|
|
52
159
|
//# sourceMappingURL=aliases.js.map
|
package/ietf/aliases.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aliases.js","sourceRoot":"","sources":["../../src/ietf/aliases.ts"],"names":[],"mappings":"AAAA,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAIpC,8FAA8F;AAC9F,MAAM,OAAO,YAAY;IACxB,OAAO,GAAG,IAAI,GAAG,EAAa,CAAC;IAC/B,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAE/C,+EAA+E;IAC/E,KAAK,CAAC,GAAG,CAAC,KAAa;QACtB,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAM,CAAC;QAEjE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,EAAK,CAAC;QACxD,IAAI,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS,EAAE,CAAC;YAChB,SAAS,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACrC,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEvB,IAAI,KAAgD,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YAChD,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,KAAK,EAAE,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC;YACJ,OAAO,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjG,CAAC;IACF,CAAC;IAED,yEAAyE;IACzE,GAAG,CAAC,KAAa,EAAE,KAAQ;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,MAAM,KAAK,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAC;YACzE,OAAO;QACR,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,KAAK,MAAM,OAAO,IAAI,SAAS,IAAI,EAAE;YAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACvD,CAAC;IAED,uEAAuE;IACvE,MAAM,CAAC,KAAa,EAAE,KAAQ;QAC7B,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,KAAK;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnE,CAAC;CACD","sourcesContent":["const TRACK_ALIAS_TIMEOUT_MS = 1000;\n\ntype Resolver<T> = PromiseWithResolvers<T>[\"resolve\"];\n\n/** Resolves publisher-chosen track aliases after control/data stream reordering. @internal */\nexport class TrackAliases<T> {\n\t#active = new Map<bigint, T>();\n\t#pending = new Map<bigint, Set<Resolver<T>>>();\n\n\t/** Waits briefly for an alias to be established by SUBSCRIBE_OK or PUBLISH. */\n\tasync get(alias: bigint): Promise<T> {\n\t\tif (this.#active.has(alias)) return this.#active.get(alias) as T;\n\n\t\tconst { promise, resolve } = Promise.withResolvers<T>();\n\t\tlet resolvers = this.#pending.get(alias);\n\t\tif (!resolvers) {\n\t\t\tresolvers = new Set();\n\t\t\tthis.#pending.set(alias, resolvers);\n\t\t}\n\t\tresolvers.add(resolve);\n\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst timeout = new Promise<never>((_, reject) => {\n\t\t\ttimer = setTimeout(() => reject(new Error(`unknown track alias: ${alias}`)), TRACK_ALIAS_TIMEOUT_MS);\n\t\t});\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, timeout]);\n\t\t} finally {\n\t\t\tclearTimeout(timer);\n\t\t\tresolvers.delete(resolve);\n\t\t\tif (this.#pending.get(alias) === resolvers && resolvers.size === 0) this.#pending.delete(alias);\n\t\t}\n\t}\n\n\t/** Establishes an alias and releases any data streams waiting for it. */\n\tset(alias: bigint, value: T) {\n\t\tconst active = this.#active.get(alias);\n\t\tif (this.#active.has(alias)) {\n\t\t\tif (active !== value) throw new Error(`duplicate track alias: ${alias}`);\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#active.set(alias, value);\n\t\tconst resolvers = this.#pending.get(alias);\n\t\tthis.#pending.delete(alias);\n\t\tfor (const resolve of resolvers ?? []) resolve(value);\n\t}\n\n\t/** Removes an alias only if it still belongs to the supplied value. */\n\tdelete(alias: bigint, value: T) {\n\t\tif (this.#active.get(alias) === value) this.#active.delete(alias);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"aliases.js","sourceRoot":"","sources":["../../src/ietf/aliases.ts"],"names":[],"mappings":"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","sourcesContent":["const TRACK_ALIAS_TIMEOUT_MS = 1000;\n\n/**\n * How many cancelled aliases to remember. Objects keep arriving for about a round trip\n * after we cancel, so a handful covers the window, while the cap keeps a long session with\n * heavy subscription churn from accumulating tombstones for its whole lifetime.\n *\n * The bound is a count rather than a deadline, so eviction stays synchronous with\n * retirement instead of needing a timer. The trade is that a session cancelling more than\n * this many distinct aliases inside one round trip evicts a tombstone whose objects are\n * still arriving; those fall back to the unknown-alias wait, which is the old behavior\n * rather than a new failure.\n */\nconst RETIRED_ALIAS_CAPACITY = 64;\n\ntype Resolver<T> = PromiseWithResolvers<T>[\"resolve\"];\n\n/**\n * The full track name an alias is bound to.\n *\n * Kept as two components rather than one joined string: a track name may contain the same\n * separator a broadcast path uses, so `a` + `b/c` and `a/b` + `c` would otherwise compare\n * equal and turn a genuine collision into apparent sharing.\n * @internal\n */\nexport type TrackIdentity = { broadcast: string; name: string };\n\nfunction sameTrack(a: TrackIdentity, b: TrackIdentity): boolean {\n\treturn a.broadcast === b.broadcast && a.name === b.name;\n}\n\n/**\n * Thrown when a group arrives for a subscription we already cancelled.\n *\n * The publisher only stops once our cancellation reaches it, so objects keep arriving for\n * at least a round trip afterwards. Draft-19 section 11.1 asks us to keep enough state to\n * discard them quickly \"rather than treating them as belonging to an unknown Track Alias\".\n *\n * This makes the window quiet, not safe. Once a publisher reassigns the alias the tombstone\n * is reclaimed, and nothing on a group stream distinguishes the old subscription's objects\n * from the new one's. Cancelling promptly is what bounds the exposure to a round trip.\n * @internal\n */\nexport class RetiredTrackAlias extends Error {\n\tconstructor(alias: bigint) {\n\t\tsuper(`track alias retired: ${alias}`);\n\t\tthis.name = \"RetiredTrackAlias\";\n\t}\n}\n\n/**\n * Thrown when a publisher gives one alias to two subscriptions of the same track.\n *\n * Draft-19 section 5.1 permits this and expects the subscriber to demux by re-applying\n * each subscription's filter. Ours are all LargestObject, so they are indistinguishable and\n * we cannot, which costs the one subscription. It is not a protocol error, so it must not\n * take the session down with it.\n * @internal\n */\nexport class SharedTrackAlias extends Error {\n\tconstructor(alias: bigint) {\n\t\tsuper(`track alias shared by another subscription: ${alias}`);\n\t\tthis.name = \"SharedTrackAlias\";\n\t}\n}\n\n/**\n * Thrown when a publisher points one alias at two different tracks at once, which\n * draft-19 section 11.1 makes fatal to the session.\n * @internal\n */\nexport class DuplicateTrackAlias extends Error {\n\tconstructor(alias: bigint) {\n\t\tsuper(`duplicate track alias: ${alias}`);\n\t\tthis.name = \"DuplicateTrackAlias\";\n\t}\n}\n\n/** Resolves publisher-chosen track aliases after control/data stream reordering. @internal */\nexport class TrackAliases<T> {\n\t#active = new Map<bigint, { value: T; track: TrackIdentity }>();\n\t#pending = new Map<bigint, Set<Resolver<T>>>();\n\n\t/** Aliases whose subscription we cancelled, in retirement order so the oldest is forgotten first. */\n\t#retired: bigint[] = [];\n\t#retiredSet = new Set<bigint>();\n\n\t/**\n\t * Waits briefly for an alias to be established by SUBSCRIBE_OK or PUBLISH.\n\t *\n\t * Throws {@link RetiredTrackAlias} at once for an alias we cancelled, rather than\n\t * waiting out the timeout for a binding that is never coming.\n\t */\n\tasync get(alias: bigint): Promise<T> {\n\t\tconst bound = this.#active.get(alias);\n\t\tif (bound !== undefined) return bound.value;\n\t\tif (this.#retiredSet.has(alias)) throw new RetiredTrackAlias(alias);\n\n\t\tconst { promise, resolve } = Promise.withResolvers<T>();\n\t\tlet resolvers = this.#pending.get(alias);\n\t\tif (!resolvers) {\n\t\t\tresolvers = new Set();\n\t\t\tthis.#pending.set(alias, resolvers);\n\t\t}\n\t\tresolvers.add(resolve);\n\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\tconst timeout = new Promise<never>((_, reject) => {\n\t\t\ttimer = setTimeout(() => reject(new Error(`unknown track alias: ${alias}`)), TRACK_ALIAS_TIMEOUT_MS);\n\t\t});\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, timeout]);\n\t\t} finally {\n\t\t\tclearTimeout(timer);\n\t\t\tresolvers.delete(resolve);\n\t\t\tif (this.#pending.get(alias) === resolvers && resolvers.size === 0) this.#pending.delete(alias);\n\t\t}\n\t}\n\n\t/**\n\t * Establishes an alias and releases any data streams waiting for it.\n\t *\n\t * `track` is the full track name the alias was bound to, which is what decides whether a\n\t * repeat is the legal sharing of an alias across subscriptions to one track\n\t * ({@link SharedTrackAlias}) or the collision that must fail the session\n\t * ({@link DuplicateTrackAlias}).\n\t */\n\tset(alias: bigint, value: T, track: TrackIdentity) {\n\t\tconst active = this.#active.get(alias);\n\t\tif (active !== undefined) {\n\t\t\tif (active.value === value) return;\n\t\t\tthrow sameTrack(active.track, track) ? new SharedTrackAlias(alias) : new DuplicateTrackAlias(alias);\n\t\t}\n\n\t\t// Our subscription is gone, so the publisher is free to point the alias somewhere\n\t\t// new. Reclaiming it also drops the tombstone early.\n\t\tthis.#forget(alias);\n\n\t\tthis.#active.set(alias, { value, track });\n\t\tconst resolvers = this.#pending.get(alias);\n\t\tthis.#pending.delete(alias);\n\t\tfor (const resolve of resolvers ?? []) resolve(value);\n\t}\n\n\t/**\n\t * Retires an alias whose subscription was cancelled, so groups still in flight for it\n\t * are discarded promptly instead of reported as unknown.\n\t *\n\t * Only retires an alias that still belongs to the supplied value: a later subscription\n\t * may already have reclaimed it, and that binding outranks a departing owner.\n\t *\n\t * Returns whether this caller still owned the binding, so metadata keyed by the alias is\n\t * only torn down by the owner and never out from under whoever reclaimed it.\n\t */\n\tretire(alias: bigint, value: T): boolean {\n\t\tif (this.#active.get(alias)?.value !== value) return false;\n\t\tthis.#active.delete(alias);\n\n\t\tif (this.#retiredSet.has(alias)) return true;\n\t\tthis.#retiredSet.add(alias);\n\t\tthis.#retired.push(alias);\n\n\t\twhile (this.#retired.length > RETIRED_ALIAS_CAPACITY) {\n\t\t\tconst oldest = this.#retired.shift();\n\t\t\tif (oldest !== undefined) this.#retiredSet.delete(oldest);\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t#forget(alias: bigint) {\n\t\tif (!this.#retiredSet.delete(alias)) return;\n\t\tconst at = this.#retired.indexOf(alias);\n\t\tif (at !== -1) this.#retired.splice(at, 1);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The MoQ Cluster extension (draft-lcurley-moq-cluster-00).
|
|
3
|
+
*
|
|
4
|
+
* moq-transport carries no routing information, so a peer cannot tell whether an
|
|
5
|
+
* advertisement already passed through us. This extension adds it:
|
|
6
|
+
*
|
|
7
|
+
* - each endpoint declares its own Hop ID via the RELAY_HOPS Setup Option, which is also
|
|
8
|
+
* what negotiates the extension;
|
|
9
|
+
* - every advertisement carries the HOP_PATH it traversed and the accumulated ROUTE_COST
|
|
10
|
+
* of that path, as Key-Value-Pair message parameters on PUBLISH_NAMESPACE and NAMESPACE.
|
|
11
|
+
*
|
|
12
|
+
* These are the semantics moq-lite carries natively on every announcement (see
|
|
13
|
+
* `lite/announce.ts`); this module is the moq-transport binding, negotiated on draft-17+
|
|
14
|
+
* only, where SETUP is a Key-Value-Pair block.
|
|
15
|
+
*
|
|
16
|
+
* We are a leaf, never a relay: the only path we can advertise is our own, so we stamp a
|
|
17
|
+
* single-entry HOP_PATH and seed the cost at 0. What we get out of declaring is the other
|
|
18
|
+
* direction. A relay that knows our Hop ID withholds the advertisements that already flowed
|
|
19
|
+
* through us, so publishing a broadcast no longer announces it back to us, which is what
|
|
20
|
+
* moq-lite has always done with its own hop chain.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
* @internal
|
|
24
|
+
*/
|
|
25
|
+
import { type Origin } from "../origin";
|
|
26
|
+
import type { Reader } from "../stream";
|
|
27
|
+
import { Parameters, type SetupOptions } from "./parameters";
|
|
28
|
+
import { type IetfVersion } from "./version";
|
|
29
|
+
/**
|
|
30
|
+
* Whether a version can negotiate the extension.
|
|
31
|
+
*
|
|
32
|
+
* Draft-17 is the first with the unified SETUP: a bare Key-Value-Pair block that a new
|
|
33
|
+
* option slots into without touching the message shape. Earlier drafts exchange SETUP over
|
|
34
|
+
* the legacy control stream, which this extension does not cover.
|
|
35
|
+
*
|
|
36
|
+
* @internal
|
|
37
|
+
*/
|
|
38
|
+
export declare function supported(version: IetfVersion): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The Hop IDs this session declared, one per direction.
|
|
41
|
+
*
|
|
42
|
+
* @internal
|
|
43
|
+
*/
|
|
44
|
+
export interface Hops {
|
|
45
|
+
/** Our own Hop ID, declared in SETUP and stamped onto every advertisement we send. */
|
|
46
|
+
self: Origin;
|
|
47
|
+
/**
|
|
48
|
+
* The peer's Hop ID, or `undefined` when it declared no RELAY_HOPS.
|
|
49
|
+
*
|
|
50
|
+
* This is what decides whether advertisements carry the parameters at all, in both
|
|
51
|
+
* directions: a peer that declared nothing has not read ours either, so sending it a
|
|
52
|
+
* HOP_PATH would be a protocol violation and expecting one back would reject a legal
|
|
53
|
+
* message. A peer that declared the reserved 0 negotiated the extension but withheld its
|
|
54
|
+
* identity, so the parameters flow and there is simply nothing to exclude.
|
|
55
|
+
*/
|
|
56
|
+
peer?: Origin;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The cluster parameters carried on one advertisement.
|
|
60
|
+
*
|
|
61
|
+
* Present on every PUBLISH_NAMESPACE and NAMESPACE of a session that negotiated the
|
|
62
|
+
* extension, and on none of a session that did not.
|
|
63
|
+
*
|
|
64
|
+
* @internal
|
|
65
|
+
*/
|
|
66
|
+
export interface Advert {
|
|
67
|
+
/** HOP_PATH: the path this advertisement traversed, publisher first, sender last. */
|
|
68
|
+
hops: Origin[];
|
|
69
|
+
/** ROUTE_COST: the marginal cost of subscribing via this advertisement. Absent on the
|
|
70
|
+
* wire means 0, so an endpoint that prices nothing sends nothing. */
|
|
71
|
+
cost: bigint;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Read the peer's Hop ID out of its SETUP, or `undefined` when it did not negotiate.
|
|
75
|
+
*
|
|
76
|
+
* @internal
|
|
77
|
+
*/
|
|
78
|
+
export declare function fromSetup(params: SetupOptions, version: IetfVersion): Origin | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* Declare our own Hop ID, which is also what negotiates the extension.
|
|
81
|
+
*
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
export declare function intoSetup(params: SetupOptions, self: Origin, version: IetfVersion): void;
|
|
85
|
+
/**
|
|
86
|
+
* Whether the session negotiated the extension, which is what decides whether an
|
|
87
|
+
* advertisement carries the parameters in either direction.
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
export declare function negotiated(ids: Hops | undefined): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* The advertisement to send for one of our own broadcasts, or `undefined` on a session
|
|
94
|
+
* that negotiated nothing.
|
|
95
|
+
*
|
|
96
|
+
* The sender's own Hop ID is always the last entry, so a receiver reconstructs the full
|
|
97
|
+
* path without the sender restating it. We originate everything we advertise, so the path
|
|
98
|
+
* is just us and the cost is 0: a subscription costs the peer nothing but the transfer,
|
|
99
|
+
* since we are already producing the content.
|
|
100
|
+
*
|
|
101
|
+
* @internal
|
|
102
|
+
*/
|
|
103
|
+
export declare function advertise(ids: Hops | undefined): Advert | undefined;
|
|
104
|
+
/**
|
|
105
|
+
* Whether this advertisement looped back through `self`.
|
|
106
|
+
*
|
|
107
|
+
* A receiver discards such an advertisement: forwarding it would extend the loop, and
|
|
108
|
+
* subscribing through it would route the receiver back to itself. Hop ID 0 identifies
|
|
109
|
+
* nothing, so a receiver that withheld its own identity detects nothing.
|
|
110
|
+
*
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
export declare function loops(advert: Advert, self: Origin): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Write an advertisement's parameters, ready to encode onto the wire.
|
|
116
|
+
*
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
export declare function intoParams(advert: Advert): Parameters;
|
|
120
|
+
/**
|
|
121
|
+
* Read the parameters a negotiated session puts on every advertisement.
|
|
122
|
+
*
|
|
123
|
+
* The parameter block is mandatory there, so a message that ends before it (the base form)
|
|
124
|
+
* or one whose block does not parse is the peer's violation, same as a block that parses but
|
|
125
|
+
* carries no HOP_PATH.
|
|
126
|
+
*
|
|
127
|
+
* @internal
|
|
128
|
+
*/
|
|
129
|
+
export declare function decodeParams(r: Reader, version: IetfVersion): Promise<Advert>;
|
|
130
|
+
/**
|
|
131
|
+
* Read an advertisement out of a decoded parameter block.
|
|
132
|
+
*
|
|
133
|
+
* Every way this fails is one the draft says to close the session over: a negotiated session
|
|
134
|
+
* that omits HOP_PATH, entries that do not exactly fill the parameter, an empty list, or a
|
|
135
|
+
* non-zero Hop ID appearing twice. So they all surface as one {@link ProtocolViolation},
|
|
136
|
+
* which the session dispatch acts on.
|
|
137
|
+
*
|
|
138
|
+
* @internal
|
|
139
|
+
*/
|
|
140
|
+
export declare function fromParams(params: Parameters): Advert;
|
|
141
|
+
//# sourceMappingURL=cluster.d.ts.map
|