@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.
Files changed (310) hide show
  1. package/README.md +1 -0
  2. package/announced.d.ts +111 -21
  3. package/announced.d.ts.map +1 -1
  4. package/announced.js +213 -40
  5. package/announced.js.map +1 -1
  6. package/broadcast.d.ts +80 -25
  7. package/broadcast.d.ts.map +1 -1
  8. package/broadcast.js +270 -49
  9. package/broadcast.js.map +1 -1
  10. package/connection/accept.d.ts +6 -0
  11. package/connection/accept.d.ts.map +1 -1
  12. package/connection/accept.js +42 -13
  13. package/connection/accept.js.map +1 -1
  14. package/connection/browser.d.ts +5 -0
  15. package/connection/browser.d.ts.map +1 -0
  16. package/connection/browser.js +31 -0
  17. package/connection/browser.js.map +1 -0
  18. package/connection/connect.d.ts +43 -1
  19. package/connection/connect.d.ts.map +1 -1
  20. package/connection/connect.js +118 -123
  21. package/connection/connect.js.map +1 -1
  22. package/connection/established.d.ts +43 -16
  23. package/connection/established.d.ts.map +1 -1
  24. package/connection/established.js.map +1 -1
  25. package/connection/handshake.d.ts +12 -1
  26. package/connection/handshake.d.ts.map +1 -1
  27. package/connection/handshake.js +30 -14
  28. package/connection/handshake.js.map +1 -1
  29. package/connection/index.d.ts +8 -0
  30. package/connection/index.d.ts.map +1 -1
  31. package/connection/index.js +6 -0
  32. package/connection/index.js.map +1 -1
  33. package/connection/reload.d.ts +66 -9
  34. package/connection/reload.d.ts.map +1 -1
  35. package/connection/reload.js +192 -66
  36. package/connection/reload.js.map +1 -1
  37. package/connection/stats.d.ts +92 -0
  38. package/connection/stats.d.ts.map +1 -0
  39. package/connection/stats.js +35 -0
  40. package/connection/stats.js.map +1 -0
  41. package/connection/transport.d.ts +10 -0
  42. package/connection/transport.d.ts.map +1 -0
  43. package/connection/transport.js +12 -0
  44. package/connection/transport.js.map +1 -0
  45. package/consume.d.ts +44 -0
  46. package/consume.d.ts.map +1 -0
  47. package/consume.js +60 -0
  48. package/consume.js.map +1 -0
  49. package/datagram.d.ts +23 -0
  50. package/datagram.d.ts.map +1 -0
  51. package/datagram.js +3 -0
  52. package/datagram.js.map +1 -0
  53. package/error.d.ts +76 -0
  54. package/error.d.ts.map +1 -0
  55. package/error.js +107 -0
  56. package/error.js.map +1 -0
  57. package/group.d.ts +143 -38
  58. package/group.d.ts.map +1 -1
  59. package/group.js +270 -68
  60. package/group.js.map +1 -1
  61. package/ietf/adapter.d.ts +2 -2
  62. package/ietf/adapter.d.ts.map +1 -1
  63. package/ietf/adapter.js +20 -10
  64. package/ietf/adapter.js.map +1 -1
  65. package/ietf/aliases.d.ts +73 -5
  66. package/ietf/aliases.d.ts.map +1 -1
  67. package/ietf/aliases.js +121 -14
  68. package/ietf/aliases.js.map +1 -1
  69. package/ietf/cluster.d.ts +141 -0
  70. package/ietf/cluster.d.ts.map +1 -0
  71. package/ietf/cluster.js +204 -0
  72. package/ietf/cluster.js.map +1 -0
  73. package/ietf/connection.d.ts +39 -6
  74. package/ietf/connection.d.ts.map +1 -1
  75. package/ietf/connection.js +73 -12
  76. package/ietf/connection.js.map +1 -1
  77. package/ietf/fetch.d.ts +17 -0
  78. package/ietf/fetch.d.ts.map +1 -1
  79. package/ietf/fetch.js +21 -0
  80. package/ietf/fetch.js.map +1 -1
  81. package/ietf/filter.d.ts +87 -0
  82. package/ietf/filter.d.ts.map +1 -0
  83. package/ietf/filter.js +292 -0
  84. package/ietf/filter.js.map +1 -0
  85. package/ietf/index.d.ts +2 -0
  86. package/ietf/index.d.ts.map +1 -1
  87. package/ietf/index.js +3 -0
  88. package/ietf/index.js.map +1 -1
  89. package/ietf/namespace.d.ts +6 -0
  90. package/ietf/namespace.d.ts.map +1 -1
  91. package/ietf/namespace.js +27 -2
  92. package/ietf/namespace.js.map +1 -1
  93. package/ietf/object.d.ts +54 -6
  94. package/ietf/object.d.ts.map +1 -1
  95. package/ietf/object.js +178 -25
  96. package/ietf/object.js.map +1 -1
  97. package/ietf/parameters.d.ts +35 -10
  98. package/ietf/parameters.d.ts.map +1 -1
  99. package/ietf/parameters.js +236 -45
  100. package/ietf/parameters.js.map +1 -1
  101. package/ietf/priority.d.ts +5 -0
  102. package/ietf/priority.d.ts.map +1 -0
  103. package/ietf/priority.js +10 -0
  104. package/ietf/priority.js.map +1 -0
  105. package/ietf/properties.d.ts +13 -2
  106. package/ietf/properties.d.ts.map +1 -1
  107. package/ietf/properties.js +65 -8
  108. package/ietf/properties.js.map +1 -1
  109. package/ietf/publish.d.ts.map +1 -1
  110. package/ietf/publish.js +13 -3
  111. package/ietf/publish.js.map +1 -1
  112. package/ietf/publish_namespace.d.ts +16 -2
  113. package/ietf/publish_namespace.d.ts.map +1 -1
  114. package/ietf/publish_namespace.js +25 -6
  115. package/ietf/publish_namespace.js.map +1 -1
  116. package/ietf/publisher.d.ts +40 -7
  117. package/ietf/publisher.d.ts.map +1 -1
  118. package/ietf/publisher.js +751 -134
  119. package/ietf/publisher.js.map +1 -1
  120. package/ietf/request.js +1 -1
  121. package/ietf/request.js.map +1 -1
  122. package/ietf/solicit.d.ts +41 -0
  123. package/ietf/solicit.d.ts.map +1 -0
  124. package/ietf/solicit.js +47 -0
  125. package/ietf/solicit.js.map +1 -0
  126. package/ietf/subscribe.d.ts +41 -2
  127. package/ietf/subscribe.d.ts.map +1 -1
  128. package/ietf/subscribe.js +103 -22
  129. package/ietf/subscribe.js.map +1 -1
  130. package/ietf/subscribe_namespace.d.ts +21 -7
  131. package/ietf/subscribe_namespace.d.ts.map +1 -1
  132. package/ietf/subscribe_namespace.js +31 -14
  133. package/ietf/subscribe_namespace.js.map +1 -1
  134. package/ietf/subscriber.d.ts +20 -7
  135. package/ietf/subscriber.d.ts.map +1 -1
  136. package/ietf/subscriber.js +512 -142
  137. package/ietf/subscriber.js.map +1 -1
  138. package/ietf/version.d.ts +7 -1
  139. package/ietf/version.d.ts.map +1 -1
  140. package/ietf/version.js +7 -0
  141. package/ietf/version.js.map +1 -1
  142. package/index.d.ts +10 -5
  143. package/index.d.ts.map +1 -1
  144. package/index.js +10 -5
  145. package/index.js.map +1 -1
  146. package/internal.d.ts +29 -0
  147. package/internal.d.ts.map +1 -0
  148. package/internal.js +8 -0
  149. package/internal.js.map +1 -0
  150. package/lite/announce.d.ts +62 -15
  151. package/lite/announce.d.ts.map +1 -1
  152. package/lite/announce.js +230 -94
  153. package/lite/announce.js.map +1 -1
  154. package/lite/connection.d.ts +69 -20
  155. package/lite/connection.d.ts.map +1 -1
  156. package/lite/connection.js +128 -81
  157. package/lite/connection.js.map +1 -1
  158. package/lite/datagram.d.ts +23 -0
  159. package/lite/datagram.d.ts.map +1 -0
  160. package/lite/datagram.js +57 -0
  161. package/lite/datagram.js.map +1 -0
  162. package/lite/datagram_stream.d.ts +8 -0
  163. package/lite/datagram_stream.d.ts.map +1 -0
  164. package/lite/datagram_stream.js +44 -0
  165. package/lite/datagram_stream.js.map +1 -0
  166. package/lite/fetch.d.ts.map +1 -1
  167. package/lite/fetch.js +2 -2
  168. package/lite/fetch.js.map +1 -1
  169. package/lite/index.d.ts +3 -0
  170. package/lite/index.d.ts.map +1 -1
  171. package/lite/index.js +3 -0
  172. package/lite/index.js.map +1 -1
  173. package/lite/priority.d.ts +67 -0
  174. package/lite/priority.d.ts.map +1 -0
  175. package/lite/priority.js +114 -0
  176. package/lite/priority.js.map +1 -0
  177. package/lite/probe.d.ts +18 -2
  178. package/lite/probe.d.ts.map +1 -1
  179. package/lite/probe.js +24 -22
  180. package/lite/probe.js.map +1 -1
  181. package/lite/publisher.d.ts +14 -7
  182. package/lite/publisher.d.ts.map +1 -1
  183. package/lite/publisher.js +406 -84
  184. package/lite/publisher.js.map +1 -1
  185. package/lite/setup.d.ts +83 -6
  186. package/lite/setup.d.ts.map +1 -1
  187. package/lite/setup.js +203 -31
  188. package/lite/setup.js.map +1 -1
  189. package/lite/stream.d.ts +12 -3
  190. package/lite/stream.d.ts.map +1 -1
  191. package/lite/stream.js +7 -4
  192. package/lite/stream.js.map +1 -1
  193. package/lite/subscribe.d.ts +37 -23
  194. package/lite/subscribe.d.ts.map +1 -1
  195. package/lite/subscribe.js +70 -55
  196. package/lite/subscribe.js.map +1 -1
  197. package/lite/subscriber.d.ts +29 -23
  198. package/lite/subscriber.d.ts.map +1 -1
  199. package/lite/subscriber.js +689 -112
  200. package/lite/subscriber.js.map +1 -1
  201. package/lite/track.d.ts +25 -13
  202. package/lite/track.d.ts.map +1 -1
  203. package/lite/track.js +60 -35
  204. package/lite/track.js.map +1 -1
  205. package/lite/version.d.ts +39 -4
  206. package/lite/version.d.ts.map +1 -1
  207. package/lite/version.js +139 -17
  208. package/lite/version.js.map +1 -1
  209. package/mock.d.ts +53 -3
  210. package/mock.d.ts.map +1 -1
  211. package/mock.js +110 -21
  212. package/mock.js.map +1 -1
  213. package/{lite/origin.d.ts → origin.d.ts} +25 -1
  214. package/origin.d.ts.map +1 -0
  215. package/{lite/origin.js → origin.js} +25 -1
  216. package/origin.js.map +1 -0
  217. package/package.json +6 -4
  218. package/path.d.ts +67 -0
  219. package/path.d.ts.map +1 -1
  220. package/path.js +128 -0
  221. package/path.js.map +1 -1
  222. package/stream.d.ts +94 -4
  223. package/stream.d.ts.map +1 -1
  224. package/stream.js +128 -17
  225. package/stream.js.map +1 -1
  226. package/time.d.ts +109 -86
  227. package/time.d.ts.map +1 -1
  228. package/time.js +80 -30
  229. package/time.js.map +1 -1
  230. package/track.d.ts +298 -47
  231. package/track.d.ts.map +1 -1
  232. package/track.js +721 -109
  233. package/track.js.map +1 -1
  234. package/util/timeout.d.ts +5 -0
  235. package/util/timeout.d.ts.map +1 -0
  236. package/util/timeout.js +18 -0
  237. package/util/timeout.js.map +1 -0
  238. package/util/utf8.d.ts +3 -0
  239. package/util/utf8.d.ts.map +1 -0
  240. package/util/utf8.js +7 -0
  241. package/util/utf8.js.map +1 -0
  242. package/varint.d.ts +14 -3
  243. package/varint.d.ts.map +1 -1
  244. package/varint.js +23 -12
  245. package/varint.js.map +1 -1
  246. package/zod.d.ts +5 -5
  247. package/zod.d.ts.map +1 -1
  248. package/zod.js.map +1 -1
  249. package/bandwidth.d.ts +0 -11
  250. package/bandwidth.d.ts.map +0 -1
  251. package/bandwidth.js +0 -7
  252. package/bandwidth.js.map +0 -1
  253. package/connection/cert.test.d.ts +0 -2
  254. package/connection/cert.test.d.ts.map +0 -1
  255. package/connection/cert.test.js +0 -26
  256. package/connection/cert.test.js.map +0 -1
  257. package/connection/reload.test.d.ts +0 -2
  258. package/connection/reload.test.d.ts.map +0 -1
  259. package/connection/reload.test.js +0 -39
  260. package/connection/reload.test.js.map +0 -1
  261. package/group.test.d.ts +0 -2
  262. package/group.test.d.ts.map +0 -1
  263. package/group.test.js +0 -66
  264. package/group.test.js.map +0 -1
  265. package/ietf/aliases.test.d.ts +0 -2
  266. package/ietf/aliases.test.d.ts.map +0 -1
  267. package/ietf/aliases.test.js +0 -30
  268. package/ietf/aliases.test.js.map +0 -1
  269. package/ietf/ietf.test.d.ts +0 -2
  270. package/ietf/ietf.test.d.ts.map +0 -1
  271. package/ietf/ietf.test.js +0 -873
  272. package/ietf/ietf.test.js.map +0 -1
  273. package/integration.test.d.ts +0 -2
  274. package/integration.test.d.ts.map +0 -1
  275. package/integration.test.js +0 -90
  276. package/integration.test.js.map +0 -1
  277. package/lite/origin.d.ts.map +0 -1
  278. package/lite/origin.js.map +0 -1
  279. package/lite/subscriber.test.d.ts +0 -2
  280. package/lite/subscriber.test.d.ts.map +0 -1
  281. package/lite/subscriber.test.js +0 -30
  282. package/lite/subscriber.test.js.map +0 -1
  283. package/lite/track.test.d.ts +0 -2
  284. package/lite/track.test.d.ts.map +0 -1
  285. package/lite/track.test.js +0 -53
  286. package/lite/track.test.js.map +0 -1
  287. package/path.test.d.ts +0 -2
  288. package/path.test.d.ts.map +0 -1
  289. package/path.test.js +0 -169
  290. package/path.test.js.map +0 -1
  291. package/stream.test.d.ts +0 -2
  292. package/stream.test.d.ts.map +0 -1
  293. package/stream.test.js +0 -210
  294. package/stream.test.js.map +0 -1
  295. package/track.test.d.ts +0 -2
  296. package/track.test.d.ts.map +0 -1
  297. package/track.test.js +0 -56
  298. package/track.test.js.map +0 -1
  299. package/util/error.d.ts +0 -3
  300. package/util/error.d.ts.map +0 -1
  301. package/util/error.js +0 -9
  302. package/util/error.js.map +0 -1
  303. package/util/index.d.ts +0 -2
  304. package/util/index.d.ts.map +0 -1
  305. package/util/index.js +0 -3
  306. package/util/index.js.map +0 -1
  307. package/varint.test.d.ts +0 -2
  308. package/varint.test.d.ts.map +0 -1
  309. package/varint.test.js +0 -106
  310. package/varint.test.js.map +0 -1
@@ -1,21 +1,23 @@
1
1
  /* @ts-self-types="./connection.d.ts" */
2
2
  import { Signal } from "@norskvideo/moq-signals";
3
- import { createBandwidth } from "../bandwidth.js";
3
+ import * as announce from "../announced.js";
4
+ import { transportStats } from "../connection/stats.js";
5
+ import { transportOf } from "../connection/transport.js";
6
+ import { randomOrigin } from "../origin.js";
4
7
  import * as Path from "../path.js";
5
8
  import { Readers, Stream, Writer } from "../stream.js";
6
- import { AnnounceInterest } from "./announce.js";
9
+ import { AnnounceRequest } from "./announce.js";
10
+ import { Fetch } from "./fetch.js";
7
11
  import { Goaway } from "./goaway.js";
8
12
  import { Group } from "./group.js";
9
- import { randomOrigin } from "./origin.js";
10
13
  import { Publisher } from "./publisher.js";
11
14
  import { SessionInfo } from "./session.js";
12
- import { Setup } from "./setup.js";
13
- import { DataId, StreamId } from "./stream.js";
15
+ import { ProbeLevel, Setup } from "./setup.js";
16
+ import { DataType, StreamId } from "./stream.js";
14
17
  import { Subscribe } from "./subscribe.js";
15
18
  import { Subscriber } from "./subscriber.js";
16
- import { Track } from "./track.js";
17
- import { hasSetupStream, Version, versionName } from "./version.js";
18
- const SEND_BW_POLL_INTERVAL = 100; // ms
19
+ import { Track as TrackMessage } from "./track.js";
20
+ import { hasDatagrams, hasProbeRtt, hasSetupStream, versionName } from "./version.js";
19
21
  /**
20
22
  * Represents a connection to a MoQ server.
21
23
  *
@@ -26,6 +28,10 @@ export class Connection {
26
28
  url;
27
29
  // The version of the connection as a human-readable string.
28
30
  version;
31
+ // The wire transport this session runs over.
32
+ transport;
33
+ /** Whether the relay supports broadcast discovery; see {@link Established.discovery}. */
34
+ discovery;
29
35
  // The version used for encoding/decoding.
30
36
  #version;
31
37
  // The established WebTransport session.
@@ -36,44 +42,49 @@ export class Connection {
36
42
  #publisher;
37
43
  // Module for distributing tracks.
38
44
  #subscriber;
39
- /** Estimated send bitrate from the congestion controller. */
40
- sendBandwidth;
41
- /** Estimated receive bitrate from PROBE (moq-lite-03+ only). */
42
- recvBandwidth;
43
- /** RTT in milliseconds from PROBE (moq-lite-04+ only). */
44
- rtt;
45
+ /** The peer's PROBE estimates; see {@link Established.probe}. */
46
+ probe;
45
47
  /** Random per-connection origin id. Shared by Publisher (for outbound hop
46
48
  * chains) and Subscriber (available for optional self-filtering on announces). */
47
49
  origin;
50
+ // The peer's SETUP, recorded once its Setup stream is read (lite-05+). Streams whose
51
+ // encoding depends on a negotiated capability (e.g. PROBE) wait on this. undefined
52
+ // until the peer's SETUP arrives; stays undefined forever on older drafts.
53
+ #peerSetup = new Signal(undefined);
54
+ // Mirrors the role out of #peerSetup, so the public surface exposes the peer's declared
55
+ // direction without handing out the whole SETUP (whose probe level gates our own streams).
56
+ #peerRole = new Signal(undefined);
57
+ // Written by the Subscriber as PROBE messages arrive.
58
+ #probe = new Signal({});
59
+ /**
60
+ * The {@link Role} the peer advertised in its SETUP, for a server deciding whether the
61
+ * peer's authorization grants the direction it intends to use.
62
+ *
63
+ * `undefined` until the peer's SETUP arrives, and forever on pre-lite-05 versions, which
64
+ * carry no in-band role. {@link Role.Both} is the absence of the parameter, so it is what
65
+ * a peer reports when it declines to declare a direction, sends a value we don't
66
+ * recognize, or is a server (which never sends one).
67
+ */
68
+ get peerRole() {
69
+ return this.#peerRole;
70
+ }
48
71
  /**
49
72
  * Creates a new Connection instance.
50
- * @param url - The URL of the connection
51
- * @param quic - The WebTransport session
52
- * @param session - The session stream
53
73
  *
54
74
  * @internal
55
75
  */
56
- constructor(url, quic, version, session) {
76
+ constructor({ url, quic, version, session, discovery = true }) {
57
77
  this.url = url;
58
78
  this.#quic = quic;
59
79
  this.#session = session;
60
80
  this.version = versionName(version);
61
81
  this.#version = version;
62
- // Send bandwidth is version-agnostic: depends on browser/QUIC support.
63
- const hasGetStats = typeof quic.getStats === "function";
64
- if (hasGetStats) {
65
- this.sendBandwidth = createBandwidth();
66
- }
67
- // Recv bandwidth requires PROBE support (Lite03+).
68
- if (version !== Version.DRAFT_01 && version !== Version.DRAFT_02) {
69
- this.recvBandwidth = createBandwidth();
70
- }
71
- // RTT can be populated by PROBE (Lite04+) or getStats() (when supported).
72
- // TODO prefer getStats() when both are available.
73
- this.rtt = new Signal(undefined);
82
+ this.transport = transportOf(quic);
83
+ this.discovery = discovery;
84
+ this.probe = this.#probe;
74
85
  this.origin = randomOrigin();
75
86
  this.#publisher = new Publisher(this.#quic, this.#version, this.origin);
76
- this.#subscriber = new Subscriber(this.#quic, this.#version, this.origin, this.recvBandwidth, this.rtt);
87
+ this.#subscriber = new Subscriber(this.#quic, this.#version, this.origin, this.#probe, this.#peerSetup);
77
88
  void this.#run();
78
89
  }
79
90
  /**
@@ -92,15 +103,14 @@ export class Connection {
92
103
  }
93
104
  async #run() {
94
105
  const tasks = [this.#runSession(), this.#runBidis(), this.#runUnis()];
95
- // moq-lite-05+: each endpoint opens a Setup stream and sends a single SETUP message.
96
106
  if (hasSetupStream(this.#version)) {
97
- tasks.push(this.#runSetup());
98
- }
99
- if (this.sendBandwidth) {
100
- tasks.push(this.#runSendBandwidth(this.sendBandwidth));
107
+ tasks.push(this.#sendSetup());
101
108
  }
102
- if (this.recvBandwidth) {
103
- tasks.push(this.#subscriber.runProbe());
109
+ tasks.push(this.#subscriber.runProbe());
110
+ // Route incoming QUIC datagrams into their subscriptions (lite-05+; runDatagrams
111
+ // no-ops on a transport that doesn't carry them).
112
+ if (hasDatagrams(this.#version)) {
113
+ tasks.push(this.#subscriber.runDatagrams());
104
114
  }
105
115
  try {
106
116
  await Promise.all(tasks);
@@ -112,14 +122,23 @@ export class Connection {
112
122
  this.close();
113
123
  }
114
124
  }
115
- publish(path, broadcast) {
116
- this.#publisher.publish(path, broadcast);
125
+ publish(path, producer) {
126
+ this.#publisher.publish(path, producer);
117
127
  }
118
128
  announced(prefix = Path.empty()) {
119
129
  return this.#subscriber.announced(prefix);
120
130
  }
121
- consume(broadcast) {
122
- return this.#subscriber.consume(broadcast);
131
+ consume(path) {
132
+ return this.#subscriber.consume(path);
133
+ }
134
+ /**
135
+ * Watches a broadcast, live only while it is announced.
136
+ *
137
+ * @param path - The path of the broadcast to watch
138
+ * @returns A reactive handle to the broadcast
139
+ */
140
+ announcedBroadcast(path) {
141
+ return new announce.Broadcast({ connection: this, path });
123
142
  }
124
143
  async #runSession() {
125
144
  if (!this.#session) {
@@ -136,6 +155,26 @@ export class Connection {
136
155
  console.debug("session stream closed");
137
156
  }
138
157
  }
158
+ // Open the unidirectional Setup Stream, send our single SETUP, and FIN (lite-05+).
159
+ // The browser uses WebTransport, which carries the request URI, so we advertise no
160
+ // path and leave routing to the URL. The probe level reflects what this transport
161
+ // can actually measure; we never pad, so we never advertise Increase.
162
+ // Role stays Both: publish/consume are called after this point, so there is nothing
163
+ // to narrow yet. The origin declares our session identity so the peer can filter
164
+ // reflected announcements (lite-06 removed ANNOUNCE_REQUEST's exclude_hop for it).
165
+ async #sendSetup() {
166
+ const writer = await Writer.open(this.#quic);
167
+ try {
168
+ await writer.u53(DataType.Setup);
169
+ const probe = await probeLevel(this.#quic, this.#version);
170
+ await new Setup({ probe, origin: this.origin }).encode(writer, this.#version);
171
+ writer.close();
172
+ }
173
+ catch (err) {
174
+ writer.reset(err);
175
+ throw err;
176
+ }
177
+ }
139
178
  async #runBidis() {
140
179
  for (;;) {
141
180
  const stream = await Stream.accept(this.#quic);
@@ -156,15 +195,19 @@ export class Connection {
156
195
  throw new Error("duplicate session stream");
157
196
  }
158
197
  else if (typ === StreamId.Announce) {
159
- const msg = await AnnounceInterest.decode(stream.reader, this.#version);
198
+ const msg = await AnnounceRequest.decode(stream.reader, this.#version);
160
199
  await this.#publisher.runAnnounce(msg, stream);
161
200
  }
162
201
  else if (typ === StreamId.Subscribe) {
163
202
  const msg = await Subscribe.decode(stream.reader, this.#version);
164
203
  await this.#publisher.runSubscribe(msg, stream);
165
204
  }
205
+ else if (typ === StreamId.Fetch) {
206
+ const msg = await Fetch.decode(stream.reader, this.#version);
207
+ await this.#publisher.runFetch(msg, stream);
208
+ }
166
209
  else if (typ === StreamId.Track) {
167
- const msg = await Track.decode(stream.reader, this.#version);
210
+ const msg = await TrackMessage.decode(stream.reader, this.#version);
168
211
  await this.#publisher.runTrackInfo(msg, stream);
169
212
  }
170
213
  else if (typ === StreamId.Probe) {
@@ -194,54 +237,58 @@ export class Connection {
194
237
  }
195
238
  }
196
239
  async #runUni(stream) {
197
- const typ = await stream.u8();
198
- if (typ === DataId.Group) {
240
+ const typ = await stream.u53();
241
+ if (typ === DataType.Group) {
199
242
  const msg = await Group.decode(stream);
200
243
  await this.#subscriber.runGroup(msg, stream);
201
244
  }
202
- else if (typ === DataId.Setup) {
203
- // moq-lite-05+: read the peer's SETUP and discard it (the path, if any,
204
- // is handled at accept time by the server's transport binding).
205
- await Setup.decode(stream, this.#version);
245
+ else if (typ === DataType.Setup) {
246
+ // The peer sends exactly one SETUP, then FINs. Record it so capability-gated
247
+ // streams (e.g. PROBE) can react, then drain to the FIN.
248
+ const setup = await Setup.decode(stream, this.#version);
249
+ this.#peerSetup.set(setup);
250
+ this.#peerRole.set(setup.role);
206
251
  }
207
252
  else {
208
253
  throw new Error(`unknown stream type: ${typ.toString()}`);
209
254
  }
210
255
  }
211
- // moq-lite-05+: open a unidirectional Setup stream, send a single SETUP, and FIN.
212
- // The browser conveys its path via the WebTransport URL, so the SETUP is empty.
213
- async #runSetup() {
214
- const writer = await Writer.open(this.#quic);
215
- try {
216
- await writer.u8(DataId.Setup);
217
- await new Setup().encode(writer, this.#version);
218
- writer.close();
219
- }
220
- catch (err) {
221
- writer.reset(err);
222
- }
223
- }
224
- async #runSendBandwidth(bandwidth) {
225
- const quic = this.#quic;
226
- return new Promise((resolve) => {
227
- const id = setInterval(async () => {
228
- try {
229
- const stats = await quic.getStats();
230
- bandwidth.set(stats.estimatedSendRate ?? undefined);
231
- }
232
- catch {
233
- clearInterval(id);
234
- resolve();
235
- }
236
- }, SEND_BW_POLL_INTERVAL);
237
- void this.closed.then(() => {
238
- clearInterval(id);
239
- resolve();
240
- });
241
- });
256
+ /** Snapshot the transport's counters; see {@link Established.stats}. */
257
+ async stats() {
258
+ return transportStats(this.#quic);
242
259
  }
243
260
  get closed() {
244
261
  return this.#quic.closed.then(() => undefined);
245
262
  }
246
263
  }
264
+ /**
265
+ * The probe level to advertise in SETUP, from what the transport can measure.
266
+ *
267
+ * `Report` claims we can measure and periodically report, so it is only truthful
268
+ * when a metric this version can carry actually exists. The qmux/WebSocket fallback
269
+ * implements no `getStats()` at all, and even a transport that has one may report
270
+ * neither figure. Advertising `Report` and then holding the subscriber's PROBE
271
+ * stream open with nothing to send is the state this avoids; the subscriber's own
272
+ * gate then skips a stream it could not use.
273
+ *
274
+ * Mirrors `ProbeLevel::detect` in `moq-net`, including its limitation: a metric
275
+ * that only appears after SETUP reads as unsupported here.
276
+ *
277
+ * @internal
278
+ */
279
+ export async function probeLevel(quic, version) {
280
+ const getStats = quic.getStats;
281
+ if (typeof getStats !== "function")
282
+ return ProbeLevel.None;
283
+ // A transport that can't answer tells us nothing, which is itself an answer.
284
+ let stats;
285
+ try {
286
+ stats = await getStats.call(quic);
287
+ }
288
+ catch {
289
+ return ProbeLevel.None;
290
+ }
291
+ const rtt = hasProbeRtt(version) ? stats.smoothedRtt : undefined;
292
+ return stats.estimatedSendRate != null || rtt != null ? ProbeLevel.Report : ProbeLevel.None;
293
+ }
247
294
  //# sourceMappingURL=connection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/lite/connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { Signal } from \"@moq/signals\";\nimport type { Announced } from \"../announced.ts\";\nimport { type Bandwidth, createBandwidth } from \"../bandwidth.ts\";\nimport type { Broadcast } from \"../broadcast.ts\";\nimport type { Established } from \"../connection/established.ts\";\nimport * as Path from \"../path.ts\";\nimport { type Reader, Readers, Stream, Writer } from \"../stream.ts\";\nimport type * as Time from \"../time.ts\";\nimport { AnnounceInterest } from \"./announce.ts\";\nimport { Goaway } from \"./goaway.ts\";\nimport { Group } from \"./group.ts\";\nimport { type Origin, randomOrigin } from \"./origin.ts\";\nimport { Publisher } from \"./publisher.ts\";\nimport { SessionInfo } from \"./session.ts\";\nimport { Setup } from \"./setup.ts\";\nimport { DataId, StreamId } from \"./stream.ts\";\nimport { Subscribe } from \"./subscribe.ts\";\nimport { Subscriber } from \"./subscriber.ts\";\nimport { Track } from \"./track.ts\";\nimport { hasSetupStream, Version, versionName } from \"./version.ts\";\n\nconst SEND_BW_POLL_INTERVAL = 100; // ms\n\n/**\n * Represents a connection to a MoQ server.\n *\n * @public\n */\nexport class Connection implements Established {\n\t// The URL of the connection.\n\treadonly url: URL;\n\n\t// The version of the connection as a human-readable string.\n\treadonly version: string;\n\n\t// The version used for encoding/decoding.\n\t#version: Version;\n\n\t// The established WebTransport session.\n\t#quic: WebTransport;\n\n\t// Use to receive/send session messages.\n\t#session?: Stream;\n\n\t// Module for contributing tracks.\n\t#publisher: Publisher;\n\n\t// Module for distributing tracks.\n\t#subscriber: Subscriber;\n\n\t/** Estimated send bitrate from the congestion controller. */\n\treadonly sendBandwidth?: Bandwidth;\n\n\t/** Estimated receive bitrate from PROBE (moq-lite-03+ only). */\n\treadonly recvBandwidth?: Bandwidth;\n\n\t/** RTT in milliseconds from PROBE (moq-lite-04+ only). */\n\treadonly rtt?: Signal<Time.Milli | undefined>;\n\n\t/** Random per-connection origin id. Shared by Publisher (for outbound hop\n\t * chains) and Subscriber (available for optional self-filtering on announces). */\n\treadonly origin: Origin;\n\n\t/**\n\t * Creates a new Connection instance.\n\t * @param url - The URL of the connection\n\t * @param quic - The WebTransport session\n\t * @param session - The session stream\n\t *\n\t * @internal\n\t */\n\tconstructor(url: URL, quic: WebTransport, version: Version, session?: Stream) {\n\t\tthis.url = url;\n\t\tthis.#quic = quic;\n\t\tthis.#session = session;\n\t\tthis.version = versionName(version);\n\t\tthis.#version = version;\n\n\t\t// Send bandwidth is version-agnostic: depends on browser/QUIC support.\n\t\tconst hasGetStats = typeof (quic as unknown as { getStats?: unknown }).getStats === \"function\";\n\t\tif (hasGetStats) {\n\t\t\tthis.sendBandwidth = createBandwidth();\n\t\t}\n\n\t\t// Recv bandwidth requires PROBE support (Lite03+).\n\t\tif (version !== Version.DRAFT_01 && version !== Version.DRAFT_02) {\n\t\t\tthis.recvBandwidth = createBandwidth();\n\t\t}\n\n\t\t// RTT can be populated by PROBE (Lite04+) or getStats() (when supported).\n\t\t// TODO prefer getStats() when both are available.\n\t\tthis.rtt = new Signal<Time.Milli | undefined>(undefined);\n\n\t\tthis.origin = randomOrigin();\n\t\tthis.#publisher = new Publisher(this.#quic, this.#version, this.origin);\n\t\tthis.#subscriber = new Subscriber(this.#quic, this.#version, this.origin, this.recvBandwidth, this.rtt);\n\n\t\tvoid this.#run();\n\t}\n\n\t/**\n\t * Closes the connection.\n\t */\n\tclose() {\n\t\tthis.#publisher.close();\n\t\tthis.#subscriber.close();\n\n\t\ttry {\n\t\t\t// TODO: For whatever reason, this try/catch doesn't seem to work..?\n\t\t\tthis.#quic.close();\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tasync #run(): Promise<void> {\n\t\tconst tasks: Promise<void>[] = [this.#runSession(), this.#runBidis(), this.#runUnis()];\n\n\t\t// moq-lite-05+: each endpoint opens a Setup stream and sends a single SETUP message.\n\t\tif (hasSetupStream(this.#version)) {\n\t\t\ttasks.push(this.#runSetup());\n\t\t}\n\n\t\tif (this.sendBandwidth) {\n\t\t\ttasks.push(this.#runSendBandwidth(this.sendBandwidth));\n\t\t}\n\n\t\tif (this.recvBandwidth) {\n\t\t\ttasks.push(this.#subscriber.runProbe());\n\t\t}\n\n\t\ttry {\n\t\t\tawait Promise.all(tasks);\n\t\t} catch (err) {\n\t\t\tconsole.error(\"fatal error running connection\", err);\n\t\t} finally {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\tpublish(path: Path.Valid, broadcast: Broadcast) {\n\t\tthis.#publisher.publish(path, broadcast);\n\t}\n\n\tannounced(prefix = Path.empty()): Announced {\n\t\treturn this.#subscriber.announced(prefix);\n\t}\n\n\tconsume(broadcast: Path.Valid): Broadcast {\n\t\treturn this.#subscriber.consume(broadcast);\n\t}\n\n\tasync #runSession() {\n\t\tif (!this.#session) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst msg = await SessionInfo.decodeMaybe(this.#session.reader, this.#version);\n\t\t\t\tif (!msg) break;\n\t\t\t}\n\t\t} finally {\n\t\t\tconsole.debug(\"session stream closed\");\n\t\t}\n\t}\n\n\tasync #runBidis() {\n\t\tfor (;;) {\n\t\t\tconst stream = await Stream.accept(this.#quic);\n\t\t\tif (!stream) break;\n\n\t\t\tthis.#runBidi(stream)\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tstream.writer.reset(err);\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tstream.writer.close();\n\t\t\t\t});\n\t\t}\n\t}\n\n\tasync #runBidi(stream: Stream) {\n\t\tconst typ = await stream.reader.u53();\n\n\t\tif (typ === StreamId.Session) {\n\t\t\tthrow new Error(\"duplicate session stream\");\n\t\t} else if (typ === StreamId.Announce) {\n\t\t\tconst msg = await AnnounceInterest.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runAnnounce(msg, stream);\n\t\t} else if (typ === StreamId.Subscribe) {\n\t\t\tconst msg = await Subscribe.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runSubscribe(msg, stream);\n\t\t} else if (typ === StreamId.Track) {\n\t\t\tconst msg = await Track.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runTrackInfo(msg, stream);\n\t\t} else if (typ === StreamId.Probe) {\n\t\t\tawait this.#publisher.runProbe(stream);\n\t\t} else if (typ === StreamId.Goaway) {\n\t\t\tconst msg = await Goaway.decode(stream.reader, this.#version);\n\t\t\tconsole.info(\"received goaway:\", msg.uri);\n\t\t} else {\n\t\t\tthrow new Error(`unknown stream type: ${typ.toString()}`);\n\t\t}\n\t}\n\n\tasync #runUnis() {\n\t\tconst readers = new Readers(this.#quic);\n\n\t\tfor (;;) {\n\t\t\tconst stream = await readers.next();\n\t\t\tif (!stream) break;\n\n\t\t\tthis.#runUni(stream)\n\t\t\t\t.then(() => {\n\t\t\t\t\tstream.stop(new Error(\"cancel\"));\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tstream.stop(err);\n\t\t\t\t});\n\t\t}\n\t}\n\n\tasync #runUni(stream: Reader) {\n\t\tconst typ = await stream.u8();\n\t\tif (typ === DataId.Group) {\n\t\t\tconst msg = await Group.decode(stream);\n\t\t\tawait this.#subscriber.runGroup(msg, stream);\n\t\t} else if (typ === DataId.Setup) {\n\t\t\t// moq-lite-05+: read the peer's SETUP and discard it (the path, if any,\n\t\t\t// is handled at accept time by the server's transport binding).\n\t\t\tawait Setup.decode(stream, this.#version);\n\t\t} else {\n\t\t\tthrow new Error(`unknown stream type: ${typ.toString()}`);\n\t\t}\n\t}\n\n\t// moq-lite-05+: open a unidirectional Setup stream, send a single SETUP, and FIN.\n\t// The browser conveys its path via the WebTransport URL, so the SETUP is empty.\n\tasync #runSetup(): Promise<void> {\n\t\tconst writer = await Writer.open(this.#quic);\n\t\ttry {\n\t\t\tawait writer.u8(DataId.Setup);\n\t\t\tawait new Setup().encode(writer, this.#version);\n\t\t\twriter.close();\n\t\t} catch (err: unknown) {\n\t\t\twriter.reset(err);\n\t\t}\n\t}\n\n\tasync #runSendBandwidth(bandwidth: Bandwidth): Promise<void> {\n\t\tconst quic = this.#quic as unknown as {\n\t\t\tgetStats: () => Promise<{ estimatedSendRate: number | null }>;\n\t\t};\n\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tconst id = setInterval(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = await quic.getStats();\n\t\t\t\t\tbandwidth.set(stats.estimatedSendRate ?? undefined);\n\t\t\t\t} catch {\n\t\t\t\t\tclearInterval(id);\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t}, SEND_BW_POLL_INTERVAL);\n\n\t\t\tvoid this.closed.then(() => {\n\t\t\t\tclearInterval(id);\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tget closed(): Promise<void> {\n\t\treturn this.#quic.closed.then(() => undefined);\n\t}\n}\n"]}
1
+ {"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/lite/connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Getter, Signal } from \"@moq/signals\";\nimport * as announce from \"../announced.ts\";\nimport type * as broadcast from \"../broadcast.ts\";\nimport type { Established } from \"../connection/established.ts\";\nimport { type Probe, type Stats, transportStats } from \"../connection/stats.ts\";\nimport { type Transport, transportOf } from \"../connection/transport.ts\";\nimport { type Origin, randomOrigin } from \"../origin.ts\";\nimport * as Path from \"../path.ts\";\nimport { type Reader, Readers, Stream, Writer } from \"../stream.ts\";\nimport { AnnounceRequest } from \"./announce.ts\";\nimport { Fetch } from \"./fetch.ts\";\nimport { Goaway } from \"./goaway.ts\";\nimport { Group } from \"./group.ts\";\nimport { Publisher } from \"./publisher.ts\";\nimport { SessionInfo } from \"./session.ts\";\nimport { ProbeLevel, type Role, Setup } from \"./setup.ts\";\nimport { DataType, StreamId } from \"./stream.ts\";\nimport { Subscribe } from \"./subscribe.ts\";\nimport { Subscriber } from \"./subscriber.ts\";\nimport { Track as TrackMessage } from \"./track.ts\";\nimport { hasDatagrams, hasProbeRtt, hasSetupStream, type Version, versionName } from \"./version.ts\";\n\n/**\n * Constructor options for {@link Connection}.\n *\n * @internal\n */\nexport interface ConnectionProps {\n\t/** The URL of the connection. */\n\turl: URL;\n\t/** The established WebTransport session. */\n\tquic: WebTransport;\n\t/** The negotiated wire version. */\n\tversion: Version;\n\t/** The session stream, absent on drafts that have none. */\n\tsession?: Stream;\n\t/** Whether the relay supports broadcast discovery. Defaults to true. */\n\tdiscovery?: boolean;\n}\n\n/**\n * Represents a connection to a MoQ server.\n *\n * @public\n */\nexport class Connection implements Established {\n\t// The URL of the connection.\n\treadonly url: URL;\n\n\t// The version of the connection as a human-readable string.\n\treadonly version: string;\n\n\t// The wire transport this session runs over.\n\treadonly transport: Transport;\n\n\t/** Whether the relay supports broadcast discovery; see {@link Established.discovery}. */\n\treadonly discovery: boolean;\n\n\t// The version used for encoding/decoding.\n\t#version: Version;\n\n\t// The established WebTransport session.\n\t#quic: WebTransport;\n\n\t// Use to receive/send session messages.\n\t#session?: Stream;\n\n\t// Module for contributing tracks.\n\t#publisher: Publisher;\n\n\t// Module for distributing tracks.\n\t#subscriber: Subscriber;\n\n\t/** The peer's PROBE estimates; see {@link Established.probe}. */\n\treadonly probe: Getter<Probe>;\n\n\t/** Random per-connection origin id. Shared by Publisher (for outbound hop\n\t * chains) and Subscriber (available for optional self-filtering on announces). */\n\treadonly origin: Origin;\n\n\t// The peer's SETUP, recorded once its Setup stream is read (lite-05+). Streams whose\n\t// encoding depends on a negotiated capability (e.g. PROBE) wait on this. undefined\n\t// until the peer's SETUP arrives; stays undefined forever on older drafts.\n\t#peerSetup = new Signal<Setup | undefined>(undefined);\n\n\t// Mirrors the role out of #peerSetup, so the public surface exposes the peer's declared\n\t// direction without handing out the whole SETUP (whose probe level gates our own streams).\n\t#peerRole = new Signal<Role | undefined>(undefined);\n\n\t// Written by the Subscriber as PROBE messages arrive.\n\t#probe = new Signal<Probe>({});\n\n\t/**\n\t * The {@link Role} the peer advertised in its SETUP, for a server deciding whether the\n\t * peer's authorization grants the direction it intends to use.\n\t *\n\t * `undefined` until the peer's SETUP arrives, and forever on pre-lite-05 versions, which\n\t * carry no in-band role. {@link Role.Both} is the absence of the parameter, so it is what\n\t * a peer reports when it declines to declare a direction, sends a value we don't\n\t * recognize, or is a server (which never sends one).\n\t */\n\tget peerRole(): Getter<Role | undefined> {\n\t\treturn this.#peerRole;\n\t}\n\n\t/**\n\t * Creates a new Connection instance.\n\t *\n\t * @internal\n\t */\n\tconstructor({ url, quic, version, session, discovery = true }: ConnectionProps) {\n\t\tthis.url = url;\n\t\tthis.#quic = quic;\n\t\tthis.#session = session;\n\t\tthis.version = versionName(version);\n\t\tthis.#version = version;\n\t\tthis.transport = transportOf(quic);\n\t\tthis.discovery = discovery;\n\n\t\tthis.probe = this.#probe;\n\n\t\tthis.origin = randomOrigin();\n\t\tthis.#publisher = new Publisher(this.#quic, this.#version, this.origin);\n\t\tthis.#subscriber = new Subscriber(this.#quic, this.#version, this.origin, this.#probe, this.#peerSetup);\n\n\t\tvoid this.#run();\n\t}\n\n\t/**\n\t * Closes the connection.\n\t */\n\tclose() {\n\t\tthis.#publisher.close();\n\t\tthis.#subscriber.close();\n\n\t\ttry {\n\t\t\t// TODO: For whatever reason, this try/catch doesn't seem to work..?\n\t\t\tthis.#quic.close();\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tasync #run(): Promise<void> {\n\t\tconst tasks: Promise<void>[] = [this.#runSession(), this.#runBidis(), this.#runUnis()];\n\n\t\tif (hasSetupStream(this.#version)) {\n\t\t\ttasks.push(this.#sendSetup());\n\t\t}\n\n\t\ttasks.push(this.#subscriber.runProbe());\n\n\t\t// Route incoming QUIC datagrams into their subscriptions (lite-05+; runDatagrams\n\t\t// no-ops on a transport that doesn't carry them).\n\t\tif (hasDatagrams(this.#version)) {\n\t\t\ttasks.push(this.#subscriber.runDatagrams());\n\t\t}\n\n\t\ttry {\n\t\t\tawait Promise.all(tasks);\n\t\t} catch (err) {\n\t\t\tconsole.error(\"fatal error running connection\", err);\n\t\t} finally {\n\t\t\tthis.close();\n\t\t}\n\t}\n\n\tpublish(path: Path.Valid, producer: broadcast.Producer) {\n\t\tthis.#publisher.publish(path, producer);\n\t}\n\n\tannounced(prefix = Path.empty()): announce.Consumer {\n\t\treturn this.#subscriber.announced(prefix);\n\t}\n\n\tconsume(path: Path.Valid): broadcast.Consumer {\n\t\treturn this.#subscriber.consume(path);\n\t}\n\n\t/**\n\t * Watches a broadcast, live only while it is announced.\n\t *\n\t * @param path - The path of the broadcast to watch\n\t * @returns A reactive handle to the broadcast\n\t */\n\tannouncedBroadcast(path: Path.Valid): announce.Broadcast {\n\t\treturn new announce.Broadcast({ connection: this, path });\n\t}\n\n\tasync #runSession() {\n\t\tif (!this.#session) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tfor (;;) {\n\t\t\t\tconst msg = await SessionInfo.decodeMaybe(this.#session.reader, this.#version);\n\t\t\t\tif (!msg) break;\n\t\t\t}\n\t\t} finally {\n\t\t\tconsole.debug(\"session stream closed\");\n\t\t}\n\t}\n\n\t// Open the unidirectional Setup Stream, send our single SETUP, and FIN (lite-05+).\n\t// The browser uses WebTransport, which carries the request URI, so we advertise no\n\t// path and leave routing to the URL. The probe level reflects what this transport\n\t// can actually measure; we never pad, so we never advertise Increase.\n\t// Role stays Both: publish/consume are called after this point, so there is nothing\n\t// to narrow yet. The origin declares our session identity so the peer can filter\n\t// reflected announcements (lite-06 removed ANNOUNCE_REQUEST's exclude_hop for it).\n\tasync #sendSetup(): Promise<void> {\n\t\tconst writer = await Writer.open(this.#quic);\n\t\ttry {\n\t\t\tawait writer.u53(DataType.Setup);\n\t\t\tconst probe = await probeLevel(this.#quic, this.#version);\n\t\t\tawait new Setup({ probe, origin: this.origin }).encode(writer, this.#version);\n\t\t\twriter.close();\n\t\t} catch (err: unknown) {\n\t\t\twriter.reset(err);\n\t\t\tthrow err;\n\t\t}\n\t}\n\n\tasync #runBidis() {\n\t\tfor (;;) {\n\t\t\tconst stream = await Stream.accept(this.#quic);\n\t\t\tif (!stream) break;\n\n\t\t\tthis.#runBidi(stream)\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tstream.writer.reset(err);\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tstream.writer.close();\n\t\t\t\t});\n\t\t}\n\t}\n\n\tasync #runBidi(stream: Stream) {\n\t\tconst typ = await stream.reader.u53();\n\n\t\tif (typ === StreamId.Session) {\n\t\t\tthrow new Error(\"duplicate session stream\");\n\t\t} else if (typ === StreamId.Announce) {\n\t\t\tconst msg = await AnnounceRequest.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runAnnounce(msg, stream);\n\t\t} else if (typ === StreamId.Subscribe) {\n\t\t\tconst msg = await Subscribe.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runSubscribe(msg, stream);\n\t\t} else if (typ === StreamId.Fetch) {\n\t\t\tconst msg = await Fetch.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runFetch(msg, stream);\n\t\t} else if (typ === StreamId.Track) {\n\t\t\tconst msg = await TrackMessage.decode(stream.reader, this.#version);\n\t\t\tawait this.#publisher.runTrackInfo(msg, stream);\n\t\t} else if (typ === StreamId.Probe) {\n\t\t\tawait this.#publisher.runProbe(stream);\n\t\t} else if (typ === StreamId.Goaway) {\n\t\t\tconst msg = await Goaway.decode(stream.reader, this.#version);\n\t\t\tconsole.info(\"received goaway:\", msg.uri);\n\t\t} else {\n\t\t\tthrow new Error(`unknown stream type: ${typ.toString()}`);\n\t\t}\n\t}\n\n\tasync #runUnis() {\n\t\tconst readers = new Readers(this.#quic);\n\n\t\tfor (;;) {\n\t\t\tconst stream = await readers.next();\n\t\t\tif (!stream) break;\n\n\t\t\tthis.#runUni(stream)\n\t\t\t\t.then(() => {\n\t\t\t\t\tstream.stop(new Error(\"cancel\"));\n\t\t\t\t})\n\t\t\t\t.catch((err: unknown) => {\n\t\t\t\t\tstream.stop(err);\n\t\t\t\t});\n\t\t}\n\t}\n\n\tasync #runUni(stream: Reader) {\n\t\tconst typ = await stream.u53();\n\t\tif (typ === DataType.Group) {\n\t\t\tconst msg = await Group.decode(stream);\n\t\t\tawait this.#subscriber.runGroup(msg, stream);\n\t\t} else if (typ === DataType.Setup) {\n\t\t\t// The peer sends exactly one SETUP, then FINs. Record it so capability-gated\n\t\t\t// streams (e.g. PROBE) can react, then drain to the FIN.\n\t\t\tconst setup = await Setup.decode(stream, this.#version);\n\t\t\tthis.#peerSetup.set(setup);\n\t\t\tthis.#peerRole.set(setup.role);\n\t\t} else {\n\t\t\tthrow new Error(`unknown stream type: ${typ.toString()}`);\n\t\t}\n\t}\n\n\t/** Snapshot the transport's counters; see {@link Established.stats}. */\n\tasync stats(): Promise<Stats> {\n\t\treturn transportStats(this.#quic);\n\t}\n\n\tget closed(): Promise<void> {\n\t\treturn this.#quic.closed.then(() => undefined);\n\t}\n}\n\n/**\n * The probe level to advertise in SETUP, from what the transport can measure.\n *\n * `Report` claims we can measure and periodically report, so it is only truthful\n * when a metric this version can carry actually exists. The qmux/WebSocket fallback\n * implements no `getStats()` at all, and even a transport that has one may report\n * neither figure. Advertising `Report` and then holding the subscriber's PROBE\n * stream open with nothing to send is the state this avoids; the subscriber's own\n * gate then skips a stream it could not use.\n *\n * Mirrors `ProbeLevel::detect` in `moq-net`, including its limitation: a metric\n * that only appears after SETUP reads as unsupported here.\n *\n * @internal\n */\nexport async function probeLevel(quic: WebTransport, version: Version): Promise<ProbeLevel> {\n\tconst getStats = (\n\t\tquic as unknown as {\n\t\t\tgetStats?: () => Promise<{ estimatedSendRate: number | null; smoothedRtt?: number | null }>;\n\t\t}\n\t).getStats;\n\tif (typeof getStats !== \"function\") return ProbeLevel.None;\n\n\t// A transport that can't answer tells us nothing, which is itself an answer.\n\tlet stats: { estimatedSendRate: number | null; smoothedRtt?: number | null };\n\ttry {\n\t\tstats = await getStats.call(quic);\n\t} catch {\n\t\treturn ProbeLevel.None;\n\t}\n\n\tconst rtt = hasProbeRtt(version) ? stats.smoothedRtt : undefined;\n\treturn stats.estimatedSendRate != null || rtt != null ? ProbeLevel.Report : ProbeLevel.None;\n}\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A QUIC datagram body: `subscribe (i) | sequence (i) | timestamp (i) | payload (b)`.
3
+ *
4
+ * The payload runs to the datagram boundary, so unlike a size-prefixed lite message there is no
5
+ * inner length prefix. Mirrors the Rust `lite::Datagram`; the model counterpart is
6
+ * {@link Datagram} in `../datagram.ts`.
7
+ */
8
+ export declare class Datagram {
9
+ /** Subscribe ID this datagram is delivered on. */
10
+ subscribe: bigint;
11
+ /** Group sequence number (shared with the track's group namespace). */
12
+ sequence: number;
13
+ /** Absolute presentation timestamp, in the track's negotiated timescale. */
14
+ timestamp: number;
15
+ /** The frame payload, delimited by the datagram boundary. */
16
+ payload: Uint8Array;
17
+ constructor(subscribe: bigint, sequence: number, timestamp: number, payload: Uint8Array);
18
+ /** Encode the body to a single `Uint8Array` (no length prefix; the datagram boundary delimits it). */
19
+ encode(): Uint8Array;
20
+ /** Decode a datagram body from the raw bytes of one QUIC datagram. */
21
+ static decode(data: Uint8Array): Promise<Datagram>;
22
+ }
23
+ //# sourceMappingURL=datagram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datagram.d.ts","sourceRoot":"","sources":["../../src/lite/datagram.ts"],"names":[],"mappings":"AAQA;;;;;;GAMG;AACH,qBAAa,QAAQ;IACpB,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,CAAC;IAClB,6DAA6D;IAC7D,OAAO,EAAE,UAAU,CAAC;IAEpB,YAAY,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAKtF;IAED,sGAAsG;IACtG,MAAM,IAAI,UAAU,CAiBnB;IAED,sEAAsE;IACtE,OAAa,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,CAOvD;CACD"}
@@ -0,0 +1,57 @@
1
+ /* @ts-self-types="./datagram.d.ts" */
2
+ /**
3
+ * Wire-level QUIC datagram body for moq-lite-05 (§6.4).
4
+ *
5
+ * @module
6
+ */
7
+ import { Reader } from "../stream.js";
8
+ import * as Varint from "../varint.js";
9
+ /**
10
+ * A QUIC datagram body: `subscribe (i) | sequence (i) | timestamp (i) | payload (b)`.
11
+ *
12
+ * The payload runs to the datagram boundary, so unlike a size-prefixed lite message there is no
13
+ * inner length prefix. Mirrors the Rust `lite::Datagram`; the model counterpart is
14
+ * {@link Datagram} in `../datagram.ts`.
15
+ */
16
+ export class Datagram {
17
+ /** Subscribe ID this datagram is delivered on. */
18
+ subscribe;
19
+ /** Group sequence number (shared with the track's group namespace). */
20
+ sequence;
21
+ /** Absolute presentation timestamp, in the track's negotiated timescale. */
22
+ timestamp;
23
+ /** The frame payload, delimited by the datagram boundary. */
24
+ payload;
25
+ constructor(subscribe, sequence, timestamp, payload) {
26
+ this.subscribe = subscribe;
27
+ this.sequence = sequence;
28
+ this.timestamp = timestamp;
29
+ this.payload = payload;
30
+ }
31
+ /** Encode the body to a single `Uint8Array` (no length prefix; the datagram boundary delimits it). */
32
+ encode() {
33
+ const subscribe = Varint.encodeTo(new ArrayBuffer(8), this.subscribe);
34
+ const sequence = Varint.encodeTo(new ArrayBuffer(8), this.sequence);
35
+ const timestamp = Varint.encodeTo(new ArrayBuffer(8), this.timestamp);
36
+ const out = new Uint8Array(subscribe.byteLength + sequence.byteLength + timestamp.byteLength + this.payload.byteLength);
37
+ let offset = 0;
38
+ out.set(subscribe, offset);
39
+ offset += subscribe.byteLength;
40
+ out.set(sequence, offset);
41
+ offset += sequence.byteLength;
42
+ out.set(timestamp, offset);
43
+ offset += timestamp.byteLength;
44
+ out.set(this.payload, offset);
45
+ return out;
46
+ }
47
+ /** Decode a datagram body from the raw bytes of one QUIC datagram. */
48
+ static async decode(data) {
49
+ const r = new Reader(undefined, data);
50
+ const subscribe = await r.u62();
51
+ const sequence = await r.u53();
52
+ const timestamp = await r.u53();
53
+ const payload = await r.readAll();
54
+ return new Datagram(subscribe, sequence, timestamp, payload);
55
+ }
56
+ }
57
+ //# sourceMappingURL=datagram.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datagram.js","sourceRoot":"","sources":["../../src/lite/datagram.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,OAAO,QAAQ;IACpB,kDAAkD;IAClD,SAAS,CAAS;IAClB,uEAAuE;IACvE,QAAQ,CAAS;IACjB,4EAA4E;IAC5E,SAAS,CAAS;IAClB,6DAA6D;IAC7D,OAAO,CAAa;IAEpB,YAAY,SAAiB,EAAE,QAAgB,EAAE,SAAiB,EAAE,OAAmB;QACtF,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACxB,CAAC;IAED,sGAAsG;IACtG,MAAM;QACL,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACtE,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpE,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QAEtE,MAAM,GAAG,GAAG,IAAI,UAAU,CACzB,SAAS,CAAC,UAAU,GAAG,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAC3F,CAAC;QACF,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC;QAC/B,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1B,MAAM,IAAI,QAAQ,CAAC,UAAU,CAAC;QAC9B,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAC3B,MAAM,IAAI,SAAS,CAAC,UAAU,CAAC;QAC/B,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC9B,OAAO,GAAG,CAAC;IACZ,CAAC;IAED,sEAAsE;IACtE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAgB;QACnC,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,IAAI,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;CACD","sourcesContent":["/**\n * Wire-level QUIC datagram body for moq-lite-05 (§6.4).\n *\n * @module\n */\nimport { Reader } from \"../stream.ts\";\nimport * as Varint from \"../varint.ts\";\n\n/**\n * A QUIC datagram body: `subscribe (i) | sequence (i) | timestamp (i) | payload (b)`.\n *\n * The payload runs to the datagram boundary, so unlike a size-prefixed lite message there is no\n * inner length prefix. Mirrors the Rust `lite::Datagram`; the model counterpart is\n * {@link Datagram} in `../datagram.ts`.\n */\nexport class Datagram {\n\t/** Subscribe ID this datagram is delivered on. */\n\tsubscribe: bigint;\n\t/** Group sequence number (shared with the track's group namespace). */\n\tsequence: number;\n\t/** Absolute presentation timestamp, in the track's negotiated timescale. */\n\ttimestamp: number;\n\t/** The frame payload, delimited by the datagram boundary. */\n\tpayload: Uint8Array;\n\n\tconstructor(subscribe: bigint, sequence: number, timestamp: number, payload: Uint8Array) {\n\t\tthis.subscribe = subscribe;\n\t\tthis.sequence = sequence;\n\t\tthis.timestamp = timestamp;\n\t\tthis.payload = payload;\n\t}\n\n\t/** Encode the body to a single `Uint8Array` (no length prefix; the datagram boundary delimits it). */\n\tencode(): Uint8Array {\n\t\tconst subscribe = Varint.encodeTo(new ArrayBuffer(8), this.subscribe);\n\t\tconst sequence = Varint.encodeTo(new ArrayBuffer(8), this.sequence);\n\t\tconst timestamp = Varint.encodeTo(new ArrayBuffer(8), this.timestamp);\n\n\t\tconst out = new Uint8Array(\n\t\t\tsubscribe.byteLength + sequence.byteLength + timestamp.byteLength + this.payload.byteLength,\n\t\t);\n\t\tlet offset = 0;\n\t\tout.set(subscribe, offset);\n\t\toffset += subscribe.byteLength;\n\t\tout.set(sequence, offset);\n\t\toffset += sequence.byteLength;\n\t\tout.set(timestamp, offset);\n\t\toffset += timestamp.byteLength;\n\t\tout.set(this.payload, offset);\n\t\treturn out;\n\t}\n\n\t/** Decode a datagram body from the raw bytes of one QUIC datagram. */\n\tstatic async decode(data: Uint8Array): Promise<Datagram> {\n\t\tconst r = new Reader(undefined, data);\n\t\tconst subscribe = await r.u62();\n\t\tconst sequence = await r.u53();\n\t\tconst timestamp = await r.u53();\n\t\tconst payload = await r.readAll();\n\t\treturn new Datagram(subscribe, sequence, timestamp, payload);\n\t}\n}\n"]}
@@ -0,0 +1,8 @@
1
+ /** Compatibility helpers for browser WebTransport datagram stream shape changes. */
2
+ /** The max outgoing datagram payload size, or 0 when this transport cannot send datagrams. */
3
+ export declare function maxDatagramSize(quic: WebTransport): number;
4
+ /** Get a datagram reader, or undefined when this browser/transport does not expose one. */
5
+ export declare function datagramReader(quic: WebTransport): ReadableStreamDefaultReader<Uint8Array> | undefined;
6
+ /** Get a datagram writer, or undefined when this browser/transport does not expose one. */
7
+ export declare function datagramWriter(quic: WebTransport): WritableStreamDefaultWriter<Uint8Array> | undefined;
8
+ //# sourceMappingURL=datagram_stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datagram_stream.d.ts","sourceRoot":"","sources":["../../src/lite/datagram_stream.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAcpF,8FAA8F;AAC9F,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAG1D;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,2BAA2B,CAAC,UAAU,CAAC,GAAG,SAAS,CAatG;AAED,2FAA2F;AAC3F,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,GAAG,2BAA2B,CAAC,UAAU,CAAC,GAAG,SAAS,CAgBtG"}
@@ -0,0 +1,44 @@
1
+ /* @ts-self-types="./datagram_stream.d.ts" */
2
+ /** Compatibility helpers for browser WebTransport datagram stream shape changes. */
3
+ function datagrams(quic) {
4
+ return quic.datagrams;
5
+ }
6
+ /** The max outgoing datagram payload size, or 0 when this transport cannot send datagrams. */
7
+ export function maxDatagramSize(quic) {
8
+ const size = datagrams(quic)?.maxDatagramSize;
9
+ return typeof size === "number" && size > 0 ? size : 0;
10
+ }
11
+ /** Get a datagram reader, or undefined when this browser/transport does not expose one. */
12
+ export function datagramReader(quic) {
13
+ const readable = datagrams(quic)?.readable;
14
+ if (!readable) {
15
+ console.warn("datagram receive disabled: WebTransport datagrams.readable is unavailable");
16
+ return undefined;
17
+ }
18
+ try {
19
+ return readable.getReader();
20
+ }
21
+ catch (err) {
22
+ console.warn("datagram receive disabled: failed to open WebTransport datagram reader", err);
23
+ return undefined;
24
+ }
25
+ }
26
+ /** Get a datagram writer, or undefined when this browser/transport does not expose one. */
27
+ export function datagramWriter(quic) {
28
+ const stream = datagrams(quic);
29
+ if (!stream || maxDatagramSize(quic) === 0)
30
+ return undefined;
31
+ try {
32
+ const writable = typeof stream.createWritable === "function" ? stream.createWritable() : stream.writable;
33
+ if (!writable) {
34
+ console.warn("datagram send disabled: WebTransport datagram writable stream is unavailable");
35
+ return undefined;
36
+ }
37
+ return writable.getWriter();
38
+ }
39
+ catch (err) {
40
+ console.warn("datagram send disabled: failed to open WebTransport datagram writer", err);
41
+ return undefined;
42
+ }
43
+ }
44
+ //# sourceMappingURL=datagram_stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datagram_stream.js","sourceRoot":"","sources":["../../src/lite/datagram_stream.ts"],"names":[],"mappings":"AAAA,oFAAoF;AAUpF,SAAS,SAAS,CAAC,IAAkB;IACpC,OAAQ,IAAkD,CAAC,SAAS,CAAC;AACtE,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,IAAkB;IACjD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;IAC9C,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,IAAkB;IAChD,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAC1F,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,wEAAwE,EAAE,GAAG,CAAC,CAAC;QAC5F,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,cAAc,CAAC,IAAkB;IAChD,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE7D,IAAI,CAAC;QACJ,MAAM,QAAQ,GAAG,OAAO,MAAM,CAAC,cAAc,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;QACzG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAC;YAC7F,OAAO,SAAS,CAAC;QAClB,CAAC;QAED,OAAO,QAAQ,CAAC,SAAS,EAAE,CAAC;IAC7B,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,qEAAqE,EAAE,GAAG,CAAC,CAAC;QACzF,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC","sourcesContent":["/** Compatibility helpers for browser WebTransport datagram stream shape changes. */\n\n/** The current standards-track datagram send stream, plus Chrome's legacy writable property. */\ninterface DatagramDuplex {\n\treadonly readable?: ReadableStream<Uint8Array>;\n\treadonly writable?: WritableStream<Uint8Array>;\n\treadonly maxDatagramSize?: number;\n\tcreateWritable?: () => WritableStream<Uint8Array>;\n}\n\nfunction datagrams(quic: WebTransport): DatagramDuplex | undefined {\n\treturn (quic as unknown as { datagrams?: DatagramDuplex }).datagrams;\n}\n\n/** The max outgoing datagram payload size, or 0 when this transport cannot send datagrams. */\nexport function maxDatagramSize(quic: WebTransport): number {\n\tconst size = datagrams(quic)?.maxDatagramSize;\n\treturn typeof size === \"number\" && size > 0 ? size : 0;\n}\n\n/** Get a datagram reader, or undefined when this browser/transport does not expose one. */\nexport function datagramReader(quic: WebTransport): ReadableStreamDefaultReader<Uint8Array> | undefined {\n\tconst readable = datagrams(quic)?.readable;\n\tif (!readable) {\n\t\tconsole.warn(\"datagram receive disabled: WebTransport datagrams.readable is unavailable\");\n\t\treturn undefined;\n\t}\n\n\ttry {\n\t\treturn readable.getReader();\n\t} catch (err: unknown) {\n\t\tconsole.warn(\"datagram receive disabled: failed to open WebTransport datagram reader\", err);\n\t\treturn undefined;\n\t}\n}\n\n/** Get a datagram writer, or undefined when this browser/transport does not expose one. */\nexport function datagramWriter(quic: WebTransport): WritableStreamDefaultWriter<Uint8Array> | undefined {\n\tconst stream = datagrams(quic);\n\tif (!stream || maxDatagramSize(quic) === 0) return undefined;\n\n\ttry {\n\t\tconst writable = typeof stream.createWritable === \"function\" ? stream.createWritable() : stream.writable;\n\t\tif (!writable) {\n\t\t\tconsole.warn(\"datagram send disabled: WebTransport datagram writable stream is unavailable\");\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn writable.getWriter();\n\t} catch (err: unknown) {\n\t\tconsole.warn(\"datagram send disabled: failed to open WebTransport datagram writer\", err);\n\t\treturn undefined;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/lite/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAYvC,qBAAa,KAAK;;IACjB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,YAAY,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAKhF;IAiBK,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvD;IAED,OAAa,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAG/D;CACD"}
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/lite/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAYvC,qBAAa,KAAK;;IACjB,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IAEd,YAAY,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAKhF;IAkBK,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGvD;IAED,OAAa,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAG/D;CACD"}
package/lite/fetch.js CHANGED
@@ -37,11 +37,11 @@ export class Fetch {
37
37
  }
38
38
  async encode(w, version) {
39
39
  guardFetch(version);
40
- return Message.encode(w, this.#encode.bind(this));
40
+ return Message.encode(w, (w) => this.#encode(w));
41
41
  }
42
42
  static async decode(r, version) {
43
43
  guardFetch(version);
44
- return Message.decode(r, Fetch.#decode);
44
+ return Message.decode(r, (r) => Fetch.#decode(r));
45
45
  }
46
46
  }
47
47
  //# sourceMappingURL=fetch.js.map
package/lite/fetch.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/lite/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAEnC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,SAAS,UAAU,CAAC,OAAgB;IACnC,QAAQ,OAAO,EAAE,CAAC;QACjB,KAAK,OAAO,CAAC,QAAQ,CAAC;QACtB,KAAK,OAAO,CAAC,QAAQ;YACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACzD;YACC,MAAM;IACR,CAAC;AACF,CAAC;AAED,MAAM,OAAO,KAAK;IACjB,SAAS,CAAa;IACtB,KAAK,CAAS;IACd,QAAQ,CAAS;IACjB,KAAK,CAAS;IAEd,YAAY,SAAqB,EAAE,KAAa,EAAE,QAAgB,EAAE,KAAa;QAChF,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,CAAS;QACtB,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAS;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAC5B,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,OAAgB;QACvC,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,OAAgB;QAC9C,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;CACD","sourcesContent":["import * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport { Version } from \"./version.ts\";\n\nfunction guardFetch(version: Version) {\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\tthrow new Error(\"fetch not supported for this version\");\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nexport class Fetch {\n\tbroadcast: Path.Valid;\n\ttrack: string;\n\tpriority: number;\n\tgroup: number;\n\n\tconstructor(broadcast: Path.Valid, track: string, priority: number, group: number) {\n\t\tthis.broadcast = broadcast;\n\t\tthis.track = track;\n\t\tthis.priority = priority;\n\t\tthis.group = group;\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.string(Path.encode(this.broadcast));\n\t\tawait w.string(this.track);\n\t\tawait w.u8(this.priority);\n\t\tawait w.u53(this.group);\n\t}\n\n\tstatic async #decode(r: Reader): Promise<Fetch> {\n\t\tconst broadcast = Path.decode(await r.string());\n\t\tconst track = await r.string();\n\t\tconst priority = await r.u8();\n\t\tconst group = await r.u53();\n\t\treturn new Fetch(broadcast, track, priority, group);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tguardFetch(version);\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<Fetch> {\n\t\tguardFetch(version);\n\t\treturn Message.decode(r, Fetch.#decode);\n\t}\n}\n"]}
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../src/lite/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AAEnC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,SAAS,UAAU,CAAC,OAAgB;IACnC,QAAQ,OAAO,EAAE,CAAC;QACjB,KAAK,OAAO,CAAC,QAAQ,CAAC;QACtB,KAAK,OAAO,CAAC,QAAQ;YACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACzD;YACC,MAAM;IACR,CAAC;AACF,CAAC;AAED,MAAM,OAAO,KAAK;IACjB,SAAS,CAAa;IACtB,KAAK,CAAS;IACd,QAAQ,CAAS;IACjB,KAAK,CAAS;IAEd,YAAY,SAAqB,EAAE,KAAa,EAAE,QAAgB,EAAE,KAAa;QAChF,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,CAAS;QACtB,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1B,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAS;QAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC;QAE5B,OAAO,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,OAAgB;QACvC,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAS,EAAE,OAAgB;QAC9C,UAAU,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,CAAC;CACD","sourcesContent":["import * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport { Version } from \"./version.ts\";\n\nfunction guardFetch(version: Version) {\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\tthrow new Error(\"fetch not supported for this version\");\n\t\tdefault:\n\t\t\tbreak;\n\t}\n}\n\nexport class Fetch {\n\tbroadcast: Path.Valid;\n\ttrack: string;\n\tpriority: number;\n\tgroup: number;\n\n\tconstructor(broadcast: Path.Valid, track: string, priority: number, group: number) {\n\t\tthis.broadcast = broadcast;\n\t\tthis.track = track;\n\t\tthis.priority = priority;\n\t\tthis.group = group;\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.string(Path.encode(this.broadcast));\n\t\tawait w.string(this.track);\n\t\tawait w.u8(this.priority);\n\t\tawait w.u53(this.group);\n\t}\n\n\tstatic async #decode(r: Reader): Promise<Fetch> {\n\t\tconst broadcast = Path.decode(await r.string());\n\t\tconst track = await r.string();\n\t\tconst priority = await r.u8();\n\t\tconst group = await r.u53();\n\n\t\treturn new Fetch(broadcast, track, priority, group);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tguardFetch(version);\n\t\treturn Message.encode(w, (w) => this.#encode(w));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<Fetch> {\n\t\tguardFetch(version);\n\t\treturn Message.decode(r, (r) => Fetch.#decode(r));\n\t}\n}\n"]}
package/lite/index.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  export * from "./announce";
2
2
  export * from "./connection";
3
+ export * from "./datagram";
3
4
  export * from "./fetch";
4
5
  export * from "./goaway";
5
6
  export * from "./group";
6
7
  export * from "./probe";
7
8
  export * from "./session";
9
+ export * from "./setup";
8
10
  export * from "./stream";
9
11
  export * from "./subscribe";
12
+ export * from "./track";
10
13
  export * from "./version";
11
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lite/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lite/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC"}