@norskvideo/moq-net 0.1.8 → 0.2.0

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 (286) hide show
  1. package/README.md +2 -2
  2. package/announce.d.ts +7 -0
  3. package/announce.d.ts.map +1 -0
  4. package/announce.js +8 -0
  5. package/announce.js.map +1 -0
  6. package/announced.d.ts +49 -91
  7. package/announced.d.ts.map +1 -1
  8. package/announced.js +21 -156
  9. package/announced.js.map +1 -1
  10. package/bandwidth.d.ts +163 -0
  11. package/bandwidth.d.ts.map +1 -0
  12. package/bandwidth.js +304 -0
  13. package/bandwidth.js.map +1 -0
  14. package/bandwidth_api.d.ts +7 -0
  15. package/bandwidth_api.d.ts.map +1 -0
  16. package/bandwidth_api.js +8 -0
  17. package/bandwidth_api.js.map +1 -0
  18. package/broadcast.d.ts +44 -35
  19. package/broadcast.d.ts.map +1 -1
  20. package/broadcast.js +104 -60
  21. package/broadcast.js.map +1 -1
  22. package/connection/accept.d.ts +16 -1
  23. package/connection/accept.d.ts.map +1 -1
  24. package/connection/accept.js +52 -28
  25. package/connection/accept.js.map +1 -1
  26. package/connection/browser.d.ts.map +1 -1
  27. package/connection/browser.js +9 -7
  28. package/connection/browser.js.map +1 -1
  29. package/connection/connect.d.ts +30 -6
  30. package/connection/connect.d.ts.map +1 -1
  31. package/connection/connect.js +110 -54
  32. package/connection/connect.js.map +1 -1
  33. package/connection/established.d.ts +17 -21
  34. package/connection/established.d.ts.map +1 -1
  35. package/connection/established.js.map +1 -1
  36. package/connection/forward.d.ts +2 -0
  37. package/connection/forward.d.ts.map +1 -0
  38. package/connection/forward.js +173 -0
  39. package/connection/forward.js.map +1 -0
  40. package/connection/handshake.d.ts +1 -0
  41. package/connection/handshake.d.ts.map +1 -1
  42. package/connection/handshake.js +5 -2
  43. package/connection/handshake.js.map +1 -1
  44. package/connection/index.d.ts +5 -5
  45. package/connection/index.d.ts.map +1 -1
  46. package/connection/index.js +4 -5
  47. package/connection/index.js.map +1 -1
  48. package/connection/pool.d.ts +186 -0
  49. package/connection/pool.d.ts.map +1 -0
  50. package/connection/pool.js +361 -0
  51. package/connection/pool.js.map +1 -0
  52. package/connection/reload.d.ts +14 -93
  53. package/connection/reload.d.ts.map +1 -1
  54. package/connection/reload.js +217 -81
  55. package/connection/reload.js.map +1 -1
  56. package/connection/stats.d.ts +3 -26
  57. package/connection/stats.d.ts.map +1 -1
  58. package/connection/stats.js.map +1 -1
  59. package/connection/transport.d.ts +0 -7
  60. package/connection/transport.d.ts.map +1 -1
  61. package/consume.d.ts +1 -43
  62. package/consume.d.ts.map +1 -1
  63. package/consume.js +1 -1
  64. package/consume.js.map +1 -1
  65. package/error.d.ts +180 -29
  66. package/error.d.ts.map +1 -1
  67. package/error.js +331 -16
  68. package/error.js.map +1 -1
  69. package/errors.d.ts +7 -0
  70. package/errors.d.ts.map +1 -0
  71. package/errors.js +8 -0
  72. package/errors.js.map +1 -0
  73. package/group.d.ts +9 -43
  74. package/group.d.ts.map +1 -1
  75. package/group.js +284 -69
  76. package/group.js.map +1 -1
  77. package/hop.d.ts +115 -0
  78. package/hop.d.ts.map +1 -0
  79. package/hop.js +119 -0
  80. package/hop.js.map +1 -0
  81. package/ietf/adapter.d.ts +5 -1
  82. package/ietf/adapter.d.ts.map +1 -1
  83. package/ietf/adapter.js +105 -60
  84. package/ietf/adapter.js.map +1 -1
  85. package/ietf/aliases.d.ts +1 -78
  86. package/ietf/aliases.d.ts.map +1 -1
  87. package/ietf/cluster.d.ts +9 -123
  88. package/ietf/cluster.d.ts.map +1 -1
  89. package/ietf/cluster.js +84 -44
  90. package/ietf/cluster.js.map +1 -1
  91. package/ietf/connection.d.ts +6 -72
  92. package/ietf/connection.d.ts.map +1 -1
  93. package/ietf/connection.js +62 -56
  94. package/ietf/connection.js.map +1 -1
  95. package/ietf/error.d.ts +11 -0
  96. package/ietf/error.d.ts.map +1 -0
  97. package/ietf/error.js +193 -0
  98. package/ietf/error.js.map +1 -0
  99. package/ietf/fetch.d.ts +7 -20
  100. package/ietf/fetch.d.ts.map +1 -1
  101. package/ietf/fetch.js +52 -22
  102. package/ietf/fetch.js.map +1 -1
  103. package/ietf/filter.d.ts +2 -0
  104. package/ietf/filter.d.ts.map +1 -1
  105. package/ietf/filter.js +10 -1
  106. package/ietf/filter.js.map +1 -1
  107. package/ietf/goaway.d.ts.map +1 -1
  108. package/ietf/goaway.js +22 -5
  109. package/ietf/goaway.js.map +1 -1
  110. package/ietf/hidden.d.ts +2 -0
  111. package/ietf/hidden.d.ts.map +1 -0
  112. package/ietf/hidden.js +30 -0
  113. package/ietf/hidden.js.map +1 -0
  114. package/ietf/index.d.ts +2 -0
  115. package/ietf/index.d.ts.map +1 -1
  116. package/ietf/index.js +2 -0
  117. package/ietf/index.js.map +1 -1
  118. package/ietf/object.d.ts +15 -8
  119. package/ietf/object.d.ts.map +1 -1
  120. package/ietf/object.js +51 -36
  121. package/ietf/object.js.map +1 -1
  122. package/ietf/parameters.d.ts +14 -2
  123. package/ietf/parameters.d.ts.map +1 -1
  124. package/ietf/parameters.js +97 -29
  125. package/ietf/parameters.js.map +1 -1
  126. package/ietf/properties.d.ts +1 -0
  127. package/ietf/properties.d.ts.map +1 -1
  128. package/ietf/properties.js +14 -0
  129. package/ietf/properties.js.map +1 -1
  130. package/ietf/publish.d.ts +19 -2
  131. package/ietf/publish.d.ts.map +1 -1
  132. package/ietf/publish.js +40 -6
  133. package/ietf/publish.js.map +1 -1
  134. package/ietf/publish_namespace.d.ts +25 -0
  135. package/ietf/publish_namespace.d.ts.map +1 -1
  136. package/ietf/publish_namespace.js +63 -0
  137. package/ietf/publish_namespace.js.map +1 -1
  138. package/ietf/publisher.d.ts +1 -82
  139. package/ietf/publisher.d.ts.map +1 -1
  140. package/ietf/publisher.js +483 -235
  141. package/ietf/publisher.js.map +1 -1
  142. package/ietf/solicit.d.ts +1 -40
  143. package/ietf/solicit.d.ts.map +1 -1
  144. package/ietf/subscribe.d.ts +8 -6
  145. package/ietf/subscribe.d.ts.map +1 -1
  146. package/ietf/subscribe.js +33 -27
  147. package/ietf/subscribe.js.map +1 -1
  148. package/ietf/subscribe_namespace.d.ts +8 -2
  149. package/ietf/subscribe_namespace.d.ts.map +1 -1
  150. package/ietf/subscribe_namespace.js +18 -8
  151. package/ietf/subscribe_namespace.js.map +1 -1
  152. package/ietf/subscriber.d.ts +1 -65
  153. package/ietf/subscriber.d.ts.map +1 -1
  154. package/ietf/subscriber.js +337 -123
  155. package/ietf/subscriber.js.map +1 -1
  156. package/ietf/token.d.ts +2 -0
  157. package/ietf/token.d.ts.map +1 -0
  158. package/ietf/token.js +99 -0
  159. package/ietf/token.js.map +1 -0
  160. package/ietf/track.d.ts +4 -0
  161. package/ietf/track.d.ts.map +1 -1
  162. package/ietf/track.js +6 -20
  163. package/ietf/track.js.map +1 -1
  164. package/ietf/version.d.ts +12 -1
  165. package/ietf/version.d.ts.map +1 -1
  166. package/ietf/version.js +13 -0
  167. package/ietf/version.js.map +1 -1
  168. package/index.d.ts +12 -7
  169. package/index.d.ts.map +1 -1
  170. package/index.js +10 -5
  171. package/index.js.map +1 -1
  172. package/internal.d.ts +115 -1
  173. package/internal.d.ts.map +1 -1
  174. package/internal.js +108 -0
  175. package/internal.js.map +1 -1
  176. package/lite/announce.d.ts +60 -10
  177. package/lite/announce.d.ts.map +1 -1
  178. package/lite/announce.js +176 -31
  179. package/lite/announce.js.map +1 -1
  180. package/lite/connection.d.ts +9 -59
  181. package/lite/connection.d.ts.map +1 -1
  182. package/lite/connection.js +34 -35
  183. package/lite/connection.js.map +1 -1
  184. package/lite/datagram.d.ts +3 -2
  185. package/lite/datagram.d.ts.map +1 -1
  186. package/lite/datagram.js +7 -8
  187. package/lite/datagram.js.map +1 -1
  188. package/lite/fetch.d.ts +15 -1
  189. package/lite/fetch.d.ts.map +1 -1
  190. package/lite/fetch.js +39 -7
  191. package/lite/fetch.js.map +1 -1
  192. package/lite/goaway.d.ts.map +1 -1
  193. package/lite/goaway.js +7 -1
  194. package/lite/goaway.js.map +1 -1
  195. package/lite/group.d.ts +30 -12
  196. package/lite/group.d.ts.map +1 -1
  197. package/lite/group.js +68 -26
  198. package/lite/group.js.map +1 -1
  199. package/lite/message.d.ts +2 -2
  200. package/lite/message.d.ts.map +1 -1
  201. package/lite/message.js +14 -5
  202. package/lite/message.js.map +1 -1
  203. package/lite/priority.d.ts +1 -61
  204. package/lite/priority.d.ts.map +1 -1
  205. package/lite/priority.js +4 -5
  206. package/lite/priority.js.map +1 -1
  207. package/lite/publisher.d.ts +1 -69
  208. package/lite/publisher.d.ts.map +1 -1
  209. package/lite/publisher.js +630 -262
  210. package/lite/publisher.js.map +1 -1
  211. package/lite/setup.d.ts +8 -8
  212. package/lite/setup.d.ts.map +1 -1
  213. package/lite/setup.js +33 -30
  214. package/lite/setup.js.map +1 -1
  215. package/lite/subscribe.d.ts +71 -17
  216. package/lite/subscribe.d.ts.map +1 -1
  217. package/lite/subscribe.js +205 -53
  218. package/lite/subscribe.js.map +1 -1
  219. package/lite/subscriber.d.ts +15 -56
  220. package/lite/subscriber.d.ts.map +1 -1
  221. package/lite/subscriber.js +451 -247
  222. package/lite/subscriber.js.map +1 -1
  223. package/lite/track.d.ts +4 -10
  224. package/lite/track.d.ts.map +1 -1
  225. package/lite/track.js +34 -29
  226. package/lite/track.js.map +1 -1
  227. package/lite/version.d.ts +42 -6
  228. package/lite/version.d.ts.map +1 -1
  229. package/lite/version.js +126 -10
  230. package/lite/version.js.map +1 -1
  231. package/origin.d.ts +256 -29
  232. package/origin.d.ts.map +1 -1
  233. package/origin.js +1427 -37
  234. package/origin.js.map +1 -1
  235. package/package.json +8 -3
  236. package/path.d.ts +25 -7
  237. package/path.d.ts.map +1 -1
  238. package/path.js +5 -3
  239. package/path.js.map +1 -1
  240. package/stream.d.ts +73 -14
  241. package/stream.d.ts.map +1 -1
  242. package/stream.js +372 -141
  243. package/stream.js.map +1 -1
  244. package/tail.d.ts +18 -0
  245. package/tail.d.ts.map +1 -0
  246. package/tail.js +167 -0
  247. package/tail.js.map +1 -0
  248. package/time.d.ts +15 -2
  249. package/time.d.ts.map +1 -1
  250. package/time.js +28 -9
  251. package/time.js.map +1 -1
  252. package/track.d.ts +211 -83
  253. package/track.d.ts.map +1 -1
  254. package/track.js +816 -205
  255. package/track.js.map +1 -1
  256. package/util/abort.d.ts +2 -0
  257. package/util/abort.d.ts.map +1 -0
  258. package/util/abort.js +20 -0
  259. package/util/abort.js.map +1 -0
  260. package/util/log.d.ts +5 -0
  261. package/util/log.d.ts.map +1 -0
  262. package/util/log.js +17 -0
  263. package/util/log.js.map +1 -0
  264. package/util/u64.d.ts +39 -0
  265. package/util/u64.d.ts.map +1 -0
  266. package/util/u64.js +83 -0
  267. package/util/u64.js.map +1 -0
  268. package/util/varint.d.ts +29 -0
  269. package/util/varint.d.ts.map +1 -0
  270. package/util/varint.js +198 -0
  271. package/util/varint.js.map +1 -0
  272. package/varint.d.ts +10 -6
  273. package/varint.d.ts.map +1 -1
  274. package/varint.js +40 -237
  275. package/varint.js.map +1 -1
  276. package/wire.d.ts +80 -0
  277. package/wire.d.ts.map +1 -0
  278. package/wire.js +32 -0
  279. package/wire.js.map +1 -0
  280. package/zod.d.ts +1 -1
  281. package/zod.d.ts.map +1 -1
  282. package/zod.js.map +1 -1
  283. package/mock.d.ts +0 -66
  284. package/mock.d.ts.map +0 -1
  285. package/mock.js +0 -243
  286. package/mock.js.map +0 -1
package/lite/announce.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /* @ts-self-types="./announce.d.ts" */
2
- import { MAX_HOPS, OriginSchema, UNKNOWN_ORIGIN } from "../origin.js";
2
+ import { ProtocolViolation } from "../error.js";
3
+ import { HopSchema, MAX_HOPS, UNKNOWN_HOP } from "../hop.js";
3
4
  import * as Path from "../path.js";
4
5
  import * as Message from "./message.js";
5
- import { hasAnnounceId, hasAnnounceOk, hasExcludeHop, hasRouteCost, Version } from "./version.js";
6
+ import { hasAnnounceCompression, hasAnnounceId, hasAnnounceOk, hasExcludeHop, hasHidden, hasRouteCost, Version, } from "./version.js";
6
7
  // Pre-lite-06 inner status values, carried inside the single ANNOUNCE_BROADCAST body.
7
8
  const STATUS_ENDED = 0;
8
9
  const STATUS_ACTIVE = 1;
@@ -13,9 +14,25 @@ const STATUS_RESTART = 2;
13
14
  const ANNOUNCE_START = 0;
14
15
  const ANNOUNCE_END = 1;
15
16
  const ANNOUNCE_RESTART = 2;
17
+ // Both wire rules on a hop chain, applied to what we send and to what we receive: a
18
+ // chain that revisits a hop looped, so neither forwarding it nor subscribing through it
19
+ // is safe, and a receiver must end the session over one. `UNKNOWN_HOP` identifies
20
+ // nothing, so any number of hops may be unknown.
21
+ //
22
+ // `ProtocolViolation` so a receipt takes the session down rather than the one stream,
23
+ // matching what `ietf/cluster.ts` throws for the identical rule.
16
24
  function checkHops(hops) {
17
25
  if (hops.length > MAX_HOPS) {
18
- throw new Error(`hop count ${hops.length} exceeds maximum ${MAX_HOPS}`);
26
+ throw new ProtocolViolation(`hop count ${hops.length} exceeds maximum ${MAX_HOPS}`);
27
+ }
28
+ // MAX_HOPS is 32, so the quadratic scan is cheaper than allocating a set.
29
+ for (let i = 0; i < hops.length; i++) {
30
+ const hop = hops[i];
31
+ if (hop === UNKNOWN_HOP)
32
+ continue;
33
+ if (hops.indexOf(hop, i + 1) !== -1) {
34
+ throw new ProtocolViolation(`hop ${hop} appears twice in the chain`);
35
+ }
19
36
  }
20
37
  }
21
38
  async function encodeHops(w, version, hops) {
@@ -28,7 +45,7 @@ async function encodeHops(w, version, hops) {
28
45
  await w.u53(hops.length);
29
46
  break;
30
47
  default:
31
- // Lite04+: hop count + individual Origin varints.
48
+ // Lite04+: hop count + individual Hop varints.
32
49
  await w.u53(hops.length);
33
50
  for (const origin of hops) {
34
51
  await w.u62(origin);
@@ -47,39 +64,90 @@ async function decodeHops(r, version) {
47
64
  throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);
48
65
  // Lite03 carries only a hop count, not individual ids, so every entry is
49
66
  // the reserved "no identity" id.
50
- return new Array(count).fill(UNKNOWN_ORIGIN);
67
+ return new Array(count).fill(UNKNOWN_HOP);
51
68
  }
52
69
  default: {
53
- // Lite04+: hop count + individual Origin varints.
70
+ // Lite04+: hop count + individual Hop varints.
54
71
  const count = await r.u53();
55
72
  if (count > MAX_HOPS)
56
73
  throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);
57
74
  const hops = [];
58
75
  for (let i = 0; i < count; i++) {
59
- hops.push(OriginSchema.parse(await r.u62()));
76
+ hops.push(HopSchema.parse(await r.u62()));
60
77
  }
78
+ checkHops(hops);
61
79
  return hops;
62
80
  }
63
81
  }
64
82
  }
65
- // The route cost rides lite-06+ announcements as a single varint; older
66
- // versions carry nothing and decode as zero.
83
+ // Lite-07 carries a base around a path and a hop list. A distance of 0 names
84
+ // nothing, and a keep without a base is a violation. Other versions have no room for
85
+ // a base at all.
86
+ function checkBase(version, base) {
87
+ if (base && !hasAnnounceCompression(version)) {
88
+ throw new Error("announce compression not supported for this version");
89
+ }
90
+ }
91
+ function toBase(distance, keep) {
92
+ if (distance !== 0n)
93
+ return { distance, keep };
94
+ if (keep !== 0)
95
+ throw new ProtocolViolation("announce keep without a base");
96
+ return undefined;
97
+ }
98
+ async function encodePath(w, version, suffix, base) {
99
+ checkBase(version, base);
100
+ if (hasAnnounceCompression(version)) {
101
+ await w.u62(base?.distance ?? 0n);
102
+ await w.u53(base?.keep ?? 0);
103
+ }
104
+ await w.string(Path.encode(suffix));
105
+ }
106
+ async function decodePath(r, version) {
107
+ if (!hasAnnounceCompression(version))
108
+ return { suffix: Path.decode(await r.string()) };
109
+ const pathBase = toBase(await r.u62(), await r.u53());
110
+ const suffix = Path.decode(await r.string());
111
+ return pathBase ? { suffix, pathBase } : { suffix };
112
+ }
113
+ async function encodeHopsBlock(w, version, hops, base) {
114
+ checkBase(version, base);
115
+ if (!hasAnnounceCompression(version))
116
+ return encodeHops(w, version, hops);
117
+ await w.u62(base?.distance ?? 0n);
118
+ await encodeHops(w, version, hops);
119
+ await w.u53(base?.keep ?? 0);
120
+ }
121
+ async function decodeHopsBlock(r, version) {
122
+ if (!hasAnnounceCompression(version))
123
+ return { hops: await decodeHops(r, version) };
124
+ const distance = await r.u62();
125
+ const hops = await decodeHops(r, version);
126
+ const hopBase = toBase(distance, await r.u53());
127
+ return hopBase ? { hops, hopBase } : { hops };
128
+ }
129
+ // The route cost rides lite-06+ announcements as two varints, warm then cold; older
130
+ // versions carry neither. Costs saturate at 2^62-1 on every version, even where lite-07's
131
+ // varints could carry more, so a cost always forwards to a peer on an older version.
132
+ const MAX_COST = 2n ** 62n - 1n;
133
+ const saturate = (v) => (v > MAX_COST ? MAX_COST : v);
67
134
  async function encodeRouteCost(w, version, cost) {
68
135
  if (!hasRouteCost(version))
69
136
  return;
70
- await w.u62(cost ?? 0n);
137
+ await w.u62(saturate(cost?.warm ?? 0n));
138
+ await w.u62(saturate(cost?.cold ?? 0n));
71
139
  }
72
140
  async function decodeRouteCost(r, version) {
73
141
  if (!hasRouteCost(version))
74
- return 0n;
75
- return await r.u62();
142
+ return undefined;
143
+ return { warm: saturate(await r.u62()), cold: saturate(await r.u62()) };
76
144
  }
77
145
  // lite-06 message body (no discriminator; the type is carried outside the length prefix).
78
146
  async function encodeAnnounce06Body(w, msg, version) {
79
147
  switch (msg.status) {
80
148
  case "active":
81
- await w.string(Path.encode(msg.suffix));
82
- await encodeHops(w, version, msg.hops);
149
+ await encodePath(w, version, msg.suffix, msg.pathBase);
150
+ await encodeHopsBlock(w, version, msg.hops, msg.hopBase);
83
151
  await encodeRouteCost(w, version, msg.cost);
84
152
  break;
85
153
  case "endedId":
@@ -87,12 +155,14 @@ async function encodeAnnounce06Body(w, msg, version) {
87
155
  break;
88
156
  case "restart":
89
157
  await w.u62(msg.id);
90
- await encodeHops(w, version, msg.hops);
158
+ await encodeHopsBlock(w, version, msg.hops, msg.hopBase);
91
159
  await encodeRouteCost(w, version, msg.cost);
92
160
  break;
93
161
  case "ended":
94
162
  // The pre-lite-06 path-form retraction has no place on lite-06.
95
163
  throw new Error("ended-by-path not supported for this version");
164
+ case "skipped":
165
+ throw new Error("decode-only announce type cannot be encoded");
96
166
  }
97
167
  }
98
168
  // lite-06 outer message type for a given announcement.
@@ -106,30 +176,36 @@ function announce06Type(msg) {
106
176
  return ANNOUNCE_RESTART;
107
177
  case "ended":
108
178
  throw new Error("ended-by-path not supported for this version");
179
+ case "skipped":
180
+ throw new Error("decode-only announce type cannot be encoded");
109
181
  }
110
182
  }
111
183
  async function decodeAnnounce06Body(r, typ, version) {
112
184
  switch (typ) {
113
185
  case ANNOUNCE_START: {
114
- const suffix = Path.decode(await r.string());
115
- const hops = await decodeHops(r, version);
116
- return { status: "active", suffix, hops, cost: await decodeRouteCost(r, version) };
186
+ const path = await decodePath(r, version);
187
+ const hops = await decodeHopsBlock(r, version);
188
+ return { status: "active", ...path, ...hops, cost: await decodeRouteCost(r, version) };
117
189
  }
118
190
  case ANNOUNCE_END:
119
191
  return { status: "endedId", id: await r.u62() };
120
192
  case ANNOUNCE_RESTART: {
121
193
  const id = await r.u62();
122
- const hops = await decodeHops(r, version);
123
- return { status: "restart", id, hops, cost: await decodeRouteCost(r, version) };
194
+ const hops = await decodeHopsBlock(r, version);
195
+ return { status: "restart", id, ...hops, cost: await decodeRouteCost(r, version) };
124
196
  }
125
197
  default:
126
- throw new Error(`unknown announce message type: ${typ}`);
198
+ // Skip the length-prefixed body so an earlier Lite06 build negotiating
199
+ // the same ALPN does not kill the announce stream.
200
+ await r.readAll();
201
+ return { status: "skipped" };
127
202
  }
128
203
  }
129
204
  // Pre-lite-06 single ANNOUNCE_BROADCAST body: an inner status byte, then path + hops.
130
205
  async function encodeLegacyBody(w, msg, version) {
131
206
  switch (msg.status) {
132
207
  case "active":
208
+ checkBase(version, msg.pathBase ?? msg.hopBase);
133
209
  await w.u8(STATUS_ACTIVE);
134
210
  await w.string(Path.encode(msg.suffix));
135
211
  await encodeHops(w, version, msg.hops);
@@ -141,6 +217,7 @@ async function encodeLegacyBody(w, msg, version) {
141
217
  break;
142
218
  case "endedId":
143
219
  case "restart":
220
+ case "skipped":
144
221
  // The id-referencing forms only exist on lite-06+.
145
222
  throw new Error("announce ids not supported for this version");
146
223
  }
@@ -184,33 +261,101 @@ export async function decodeAnnounceBroadcastMaybe(r, version) {
184
261
  }
185
262
  return Message.decodeMaybe(r, (r) => decodeLegacyBody(r, version));
186
263
  }
264
+ /**
265
+ * The live announcements on one lite-06+ announce stream, by Announce ID: what
266
+ * ANNOUNCE_END and ANNOUNCE_UPDATE reference, and what a lite-07 base copies from.
267
+ * Every violation throws {@link ProtocolViolation}.
268
+ */
269
+ export class AnnounceHistory {
270
+ #next = 0n;
271
+ #live = new Map();
272
+ #base(base) {
273
+ const live = this.#live.get(this.#next - base.distance);
274
+ if (!live)
275
+ throw new ProtocolViolation(`announce base ${base.distance} is not live`);
276
+ return live;
277
+ }
278
+ #hops(hops, base) {
279
+ if (!base)
280
+ return hops;
281
+ const tail = this.#base(base).hops;
282
+ if (base.keep > tail.length)
283
+ throw new ProtocolViolation(`announce keeps ${base.keep} of ${tail.length} hops`);
284
+ const resolved = [...hops, ...tail.slice(tail.length - base.keep)];
285
+ checkHops(resolved);
286
+ return resolved;
287
+ }
288
+ /** An ANNOUNCE_START: resolve it and assign it the next id. */
289
+ start(msg) {
290
+ let suffix = msg.suffix;
291
+ if (msg.pathBase) {
292
+ const head = Path.parts(this.#base(msg.pathBase).suffix);
293
+ const keep = msg.pathBase.keep;
294
+ if (keep > head.length)
295
+ throw new ProtocolViolation(`announce keeps ${keep} of ${head.length} segments`);
296
+ suffix = Path.join(Path.from(...head.slice(0, keep)), suffix);
297
+ if (Path.parts(suffix).length > Path.MAX_PARTS) {
298
+ throw new ProtocolViolation(`path exceeds ${Path.MAX_PARTS} parts`);
299
+ }
300
+ }
301
+ const hops = this.#hops(msg.hops, msg.hopBase);
302
+ this.#live.set(this.#next++, { suffix, hops });
303
+ return { suffix, hops };
304
+ }
305
+ /** An ANNOUNCE_UPDATE: resolve its chain before replacing the old one, which it may be based on. */
306
+ update(msg) {
307
+ const hops = this.#hops(msg.hops, msg.hopBase);
308
+ const live = this.#live.get(msg.id);
309
+ if (!live)
310
+ throw new ProtocolViolation(`unknown announce id: ${msg.id}`);
311
+ this.#live.set(msg.id, { suffix: live.suffix, hops });
312
+ return { suffix: live.suffix, hops };
313
+ }
314
+ /** An ANNOUNCE_END: retire the id, returning its suffix. */
315
+ end(id) {
316
+ const live = this.#live.get(id);
317
+ if (!live)
318
+ throw new ProtocolViolation(`unknown announce id: ${id}`);
319
+ this.#live.delete(id);
320
+ return live.suffix;
321
+ }
322
+ }
187
323
  /**
188
324
  * ANNOUNCE_REQUEST: sent by the subscriber to request ANNOUNCE_BROADCAST messages
189
325
  * for a path prefix. Renamed from `AnnounceInterest` in lite-05.
190
326
  */
191
327
  export class AnnounceRequest {
192
328
  prefix;
193
- /** Lite04/05 only: the 62-bit Origin id of the peer asking for announces, which the
329
+ /** Lite04/05 only: the 62-bit Hop id of the peer asking for announces, which the
194
330
  * publisher uses to skip announces that already passed through it. Zero means "no
195
331
  * exclusion". Not on the wire elsewhere, so a value set here is ignored when encoding
196
332
  * for another version and decodes as zero.
197
333
  *
198
334
  * Must be a bigint: peer origins are up to 62 bits and overflow u53. */
199
335
  excludeHop;
200
- constructor(prefix, excludeHop = 0n) {
336
+ /** Lite07+: also announce routes with a `.`-prefixed segment below the prefix. Not on
337
+ * the wire earlier, so a value set here is ignored when encoding for an older version
338
+ * and decodes as false. */
339
+ hidden;
340
+ constructor(prefix, excludeHop = 0n, hidden = false) {
201
341
  this.prefix = prefix;
202
342
  this.excludeHop = excludeHop;
343
+ this.hidden = hidden;
203
344
  }
204
345
  async #encode(w, version) {
205
346
  await w.string(Path.encode(this.prefix));
206
347
  if (hasExcludeHop(version)) {
207
348
  await w.u62(this.excludeHop);
208
349
  }
350
+ if (hasHidden(version)) {
351
+ await w.bool(this.hidden);
352
+ }
209
353
  }
210
354
  static async #decode(r, version) {
211
355
  const prefix = Path.decode(await r.string());
212
356
  const excludeHop = hasExcludeHop(version) ? await r.u62() : 0n;
213
- return new AnnounceRequest(prefix, excludeHop);
357
+ const hidden = hasHidden(version) ? await r.bool() : false;
358
+ return new AnnounceRequest(prefix, excludeHop, hidden);
214
359
  }
215
360
  async encode(w, version) {
216
361
  return Message.encode(w, (w) => this.#encode(w, version));
@@ -262,15 +407,15 @@ export class AnnounceInit {
262
407
  /// Sent by the publisher as the first message on an announce stream, before any
263
408
  /// individual Announce messages. Lite05+ only; the successor to AnnounceInit.
264
409
  ///
265
- /// `origin` is the responder's origin id, which the subscriber stamps onto each
410
+ /// `origin` is the responder's Hop ID, which the subscriber stamps onto each
266
411
  /// announce's hop chain (the publisher no longer stamps itself), or the reserved
267
- /// {@link UNKNOWN_ORIGIN} when the responder has no identity to give. `active` is
412
+ /// {@link UNKNOWN_HOP} when the responder has no identity to give. `active` is
268
413
  /// the number of initial Announce messages that follow immediately.
269
414
  export class AnnounceOk {
270
- origin;
415
+ hop;
271
416
  active;
272
- constructor(origin, active) {
273
- this.origin = origin;
417
+ constructor(hop, active) {
418
+ this.hop = hop;
274
419
  this.active = active;
275
420
  }
276
421
  static #guard(version) {
@@ -279,14 +424,14 @@ export class AnnounceOk {
279
424
  }
280
425
  }
281
426
  async #encode(w) {
282
- await w.u62(this.origin);
427
+ await w.u62(this.hop);
283
428
  await w.u53(this.active);
284
429
  }
285
430
  static async #decode(r) {
286
431
  // The draft reserves 0 for "unknown": the responder was never assigned an id, or
287
432
  // withholds it to obscure its routing. It names nobody, so callers must not stamp
288
433
  // it onto a hop chain, but it is a legal message and not grounds to drop the stream.
289
- const origin = OriginSchema.parse(await r.u62());
434
+ const origin = HopSchema.parse(await r.u62());
290
435
  const active = await r.u53();
291
436
  return new AnnounceOk(origin, active);
292
437
  }
@@ -1 +1 @@
1
- {"version":3,"file":"announce.js","sourceRoot":"","sources":["../../src/lite/announce.ts"],"names":[],"mappings":"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","sourcesContent":["import { MAX_HOPS, type Origin, OriginSchema, UNKNOWN_ORIGIN } from \"../origin.ts\";\nimport * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport { hasAnnounceId, hasAnnounceOk, hasExcludeHop, hasRouteCost, Version } from \"./version.ts\";\n\n// Pre-lite-06 inner status values, carried inside the single ANNOUNCE_BROADCAST body.\nconst STATUS_ENDED = 0;\nconst STATUS_ACTIVE = 1;\nconst STATUS_RESTART = 2;\n\n// lite-06 announce message types: an outer discriminator carried before the length\n// prefix, so each announcement is an independently-typed, length-delimited message\n// (mirroring SUBSCRIBE_START/END/DROP on the subscribe stream).\nconst ANNOUNCE_START = 0;\nconst ANNOUNCE_END = 1;\nconst ANNOUNCE_RESTART = 2;\n\n/**\n * An announcement on the Announce Stream, advertising or retracting a broadcast.\n *\n * On lite-06+ these are three independently-typed messages (`ANNOUNCE_START`,\n * `ANNOUNCE_END`, `ANNOUNCE_RESTART`), each framed as `Type | Length | Body` like the\n * subscribe stream's responses. Each `active` (ANNOUNCE_START) implicitly assigns the\n * next announce id (a per-stream ordinal starting at 0); `endedId`/`restart` reference\n * that id instead of repeating the path. Older versions send a single ANNOUNCE_BROADCAST\n * message that retracts by path (`ended`).\n */\nexport type AnnounceBroadcast =\n\t/** A broadcast is now available, carrying the path suffix, the hop chain, and\n\t * (lite-06+) the route cost. An absent cost encodes as zero. */\n\t| { status: \"active\"; suffix: Path.Valid; hops: Origin[]; cost?: bigint }\n\t/** Pre-lite-06: a broadcast is no longer available, retracted by path. */\n\t| { status: \"ended\"; suffix: Path.Valid }\n\t/** Lite06+: a broadcast is no longer available, retracted by announce id.\n\t * The id is retired; referencing it again is a protocol violation. */\n\t| { status: \"endedId\"; id: bigint }\n\t/** Lite06+: atomically replace the announcement with this id (e.g. a new hop\n\t * chain after a relay failover, or a route whose cost moved). The id stays live. */\n\t| { status: \"restart\"; id: bigint; hops: Origin[]; cost?: bigint };\n\nfunction checkHops(hops: Origin[]) {\n\tif (hops.length > MAX_HOPS) {\n\t\tthrow new Error(`hop count ${hops.length} exceeds maximum ${MAX_HOPS}`);\n\t}\n}\n\nasync function encodeHops(w: Writer, version: Version, hops: Origin[]) {\n\tcheckHops(hops);\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\tbreak;\n\t\tcase Version.DRAFT_03:\n\t\t\tawait w.u53(hops.length);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// Lite04+: hop count + individual Origin varints.\n\t\t\tawait w.u53(hops.length);\n\t\t\tfor (const origin of hops) {\n\t\t\t\tawait w.u62(origin);\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\nasync function decodeHops(r: Reader, version: Version): Promise<Origin[]> {\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\treturn [];\n\t\tcase Version.DRAFT_03: {\n\t\t\tconst count = await r.u53();\n\t\t\tif (count > MAX_HOPS) throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);\n\t\t\t// Lite03 carries only a hop count, not individual ids, so every entry is\n\t\t\t// the reserved \"no identity\" id.\n\t\t\treturn new Array<Origin>(count).fill(UNKNOWN_ORIGIN);\n\t\t}\n\t\tdefault: {\n\t\t\t// Lite04+: hop count + individual Origin varints.\n\t\t\tconst count = await r.u53();\n\t\t\tif (count > MAX_HOPS) throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);\n\t\t\tconst hops: Origin[] = [];\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\thops.push(OriginSchema.parse(await r.u62()));\n\t\t\t}\n\t\t\treturn hops;\n\t\t}\n\t}\n}\n\n// The route cost rides lite-06+ announcements as a single varint; older\n// versions carry nothing and decode as zero.\nasync function encodeRouteCost(w: Writer, version: Version, cost: bigint | undefined) {\n\tif (!hasRouteCost(version)) return;\n\tawait w.u62(cost ?? 0n);\n}\n\nasync function decodeRouteCost(r: Reader, version: Version): Promise<bigint> {\n\tif (!hasRouteCost(version)) return 0n;\n\treturn await r.u62();\n}\n\n// lite-06 message body (no discriminator; the type is carried outside the length prefix).\nasync function encodeAnnounce06Body(w: Writer, msg: AnnounceBroadcast, version: Version) {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\tawait w.string(Path.encode(msg.suffix));\n\t\t\tawait encodeHops(w, version, msg.hops);\n\t\t\tawait encodeRouteCost(w, version, msg.cost);\n\t\t\tbreak;\n\t\tcase \"endedId\":\n\t\t\tawait w.u62(msg.id);\n\t\t\tbreak;\n\t\tcase \"restart\":\n\t\t\tawait w.u62(msg.id);\n\t\t\tawait encodeHops(w, version, msg.hops);\n\t\t\tawait encodeRouteCost(w, version, msg.cost);\n\t\t\tbreak;\n\t\tcase \"ended\":\n\t\t\t// The pre-lite-06 path-form retraction has no place on lite-06.\n\t\t\tthrow new Error(\"ended-by-path not supported for this version\");\n\t}\n}\n\n// lite-06 outer message type for a given announcement.\nfunction announce06Type(msg: AnnounceBroadcast): number {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\treturn ANNOUNCE_START;\n\t\tcase \"endedId\":\n\t\t\treturn ANNOUNCE_END;\n\t\tcase \"restart\":\n\t\t\treturn ANNOUNCE_RESTART;\n\t\tcase \"ended\":\n\t\t\tthrow new Error(\"ended-by-path not supported for this version\");\n\t}\n}\n\nasync function decodeAnnounce06Body(r: Reader, typ: number, version: Version): Promise<AnnounceBroadcast> {\n\tswitch (typ) {\n\t\tcase ANNOUNCE_START: {\n\t\t\tconst suffix = Path.decode(await r.string());\n\t\t\tconst hops = await decodeHops(r, version);\n\t\t\treturn { status: \"active\", suffix, hops, cost: await decodeRouteCost(r, version) };\n\t\t}\n\t\tcase ANNOUNCE_END:\n\t\t\treturn { status: \"endedId\", id: await r.u62() };\n\t\tcase ANNOUNCE_RESTART: {\n\t\t\tconst id = await r.u62();\n\t\t\tconst hops = await decodeHops(r, version);\n\t\t\treturn { status: \"restart\", id, hops, cost: await decodeRouteCost(r, version) };\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(`unknown announce message type: ${typ}`);\n\t}\n}\n\n// Pre-lite-06 single ANNOUNCE_BROADCAST body: an inner status byte, then path + hops.\nasync function encodeLegacyBody(w: Writer, msg: AnnounceBroadcast, version: Version) {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\tawait w.u8(STATUS_ACTIVE);\n\t\t\tawait w.string(Path.encode(msg.suffix));\n\t\t\tawait encodeHops(w, version, msg.hops);\n\t\t\tbreak;\n\t\tcase \"ended\":\n\t\t\tawait w.u8(STATUS_ENDED);\n\t\t\tawait w.string(Path.encode(msg.suffix));\n\t\t\tawait encodeHops(w, version, []);\n\t\t\tbreak;\n\t\tcase \"endedId\":\n\t\tcase \"restart\":\n\t\t\t// The id-referencing forms only exist on lite-06+.\n\t\t\tthrow new Error(\"announce ids not supported for this version\");\n\t}\n}\n\nasync function decodeLegacyBody(r: Reader, version: Version): Promise<AnnounceBroadcast> {\n\tconst status = await r.u8();\n\t// On lite-05 a restart travels as a duplicate `active`, but the explicit restart\n\t// status is accepted on decode and treated the same. Older versions never defined it.\n\tconst active = status === STATUS_ACTIVE || (status === STATUS_RESTART && hasAnnounceOk(version));\n\tif (status !== STATUS_ENDED && !active) {\n\t\tthrow new Error(\"invalid announce status\");\n\t}\n\tconst suffix = Path.decode(await r.string());\n\tconst hops = await decodeHops(r, version);\n\treturn active ? { status: \"active\", suffix, hops } : { status: \"ended\", suffix };\n}\n\n/** Encode one announcement, including its type discriminator (lite-06+) and length prefix. */\nexport async function encodeAnnounceBroadcast(w: Writer, msg: AnnounceBroadcast, version: Version): Promise<void> {\n\tif (hasAnnounceId(version)) {\n\t\t// lite-06+: outer type discriminator, then a size-prefixed body (like the subscribe stream).\n\t\tawait w.u53(announce06Type(msg));\n\t\treturn Message.encode(w, (w) => encodeAnnounce06Body(w, msg, version));\n\t}\n\treturn Message.encode(w, (w) => encodeLegacyBody(w, msg, version));\n}\n\n/** Decode one announcement, including its type discriminator (lite-06+) and length prefix. */\nexport async function decodeAnnounceBroadcast(r: Reader, version: Version): Promise<AnnounceBroadcast> {\n\tif (hasAnnounceId(version)) {\n\t\tconst typ = await r.u53();\n\t\treturn Message.decode(r, (r) => decodeAnnounce06Body(r, typ, version));\n\t}\n\treturn Message.decode(r, (r) => decodeLegacyBody(r, version));\n}\n\n/** Like {@link decodeAnnounceBroadcast} but resolves `undefined` on a clean FIN. */\nexport async function decodeAnnounceBroadcastMaybe(\n\tr: Reader,\n\tversion: Version,\n): Promise<AnnounceBroadcast | undefined> {\n\tif (hasAnnounceId(version)) {\n\t\tif (await r.done()) return undefined;\n\t\tconst typ = await r.u53();\n\t\treturn Message.decode(r, (r) => decodeAnnounce06Body(r, typ, version));\n\t}\n\treturn Message.decodeMaybe(r, (r) => decodeLegacyBody(r, version));\n}\n\n/**\n * ANNOUNCE_REQUEST: sent by the subscriber to request ANNOUNCE_BROADCAST messages\n * for a path prefix. Renamed from `AnnounceInterest` in lite-05.\n */\nexport class AnnounceRequest {\n\tprefix: Path.Valid;\n\t/** Lite04/05 only: the 62-bit Origin id of the peer asking for announces, which the\n\t * publisher uses to skip announces that already passed through it. Zero means \"no\n\t * exclusion\". Not on the wire elsewhere, so a value set here is ignored when encoding\n\t * for another version and decodes as zero.\n\t *\n\t * Must be a bigint: peer origins are up to 62 bits and overflow u53. */\n\texcludeHop: bigint;\n\n\tconstructor(prefix: Path.Valid, excludeHop: bigint = 0n) {\n\t\tthis.prefix = prefix;\n\t\tthis.excludeHop = excludeHop;\n\t}\n\n\tasync #encode(w: Writer, version: Version) {\n\t\tawait w.string(Path.encode(this.prefix));\n\t\tif (hasExcludeHop(version)) {\n\t\t\tawait w.u62(this.excludeHop);\n\t\t}\n\t}\n\n\tstatic async #decode(r: Reader, version: Version): Promise<AnnounceRequest> {\n\t\tconst prefix = Path.decode(await r.string());\n\t\tconst excludeHop = hasExcludeHop(version) ? await r.u62() : 0n;\n\t\treturn new AnnounceRequest(prefix, excludeHop);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\treturn Message.encode(w, (w) => this.#encode(w, version));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceRequest> {\n\t\treturn Message.decode(r, (r) => AnnounceRequest.#decode(r, version));\n\t}\n}\n\n/// Sent after setup to communicate the initially announced paths.\n///\n/// Used by Draft01/Draft02 only. Draft03+ uses individual Announce messages instead.\nexport class AnnounceInit {\n\tsuffixes: Path.Valid[];\n\n\tconstructor(paths: Path.Valid[]) {\n\t\tthis.suffixes = paths;\n\t}\n\n\tstatic #guard(version: Version) {\n\t\tswitch (version) {\n\t\t\tcase Version.DRAFT_01:\n\t\t\tcase Version.DRAFT_02:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"announce init not supported for this version\");\n\t\t}\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.u53(this.suffixes.length);\n\t\tfor (const path of this.suffixes) {\n\t\t\tawait w.string(Path.encode(path));\n\t\t}\n\t}\n\n\tstatic async #decode(r: Reader): Promise<AnnounceInit> {\n\t\tconst count = await r.u53();\n\t\tconst suffixes: Path.Valid[] = [];\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tsuffixes.push(Path.decode(await r.string()));\n\t\t}\n\t\treturn new AnnounceInit(suffixes);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tAnnounceInit.#guard(version);\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceInit> {\n\t\tAnnounceInit.#guard(version);\n\t\treturn Message.decode(r, AnnounceInit.#decode);\n\t}\n}\n\n/// Sent by the publisher as the first message on an announce stream, before any\n/// individual Announce messages. Lite05+ only; the successor to AnnounceInit.\n///\n/// `origin` is the responder's origin id, which the subscriber stamps onto each\n/// announce's hop chain (the publisher no longer stamps itself), or the reserved\n/// {@link UNKNOWN_ORIGIN} when the responder has no identity to give. `active` is\n/// the number of initial Announce messages that follow immediately.\nexport class AnnounceOk {\n\torigin: Origin;\n\tactive: number;\n\n\tconstructor(origin: Origin, active: number) {\n\t\tthis.origin = origin;\n\t\tthis.active = active;\n\t}\n\n\tstatic #guard(version: Version) {\n\t\tif (!hasAnnounceOk(version)) {\n\t\t\tthrow new Error(\"announce ok not supported for this version\");\n\t\t}\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.u62(this.origin);\n\t\tawait w.u53(this.active);\n\t}\n\n\tstatic async #decode(r: Reader): Promise<AnnounceOk> {\n\t\t// The draft reserves 0 for \"unknown\": the responder was never assigned an id, or\n\t\t// withholds it to obscure its routing. It names nobody, so callers must not stamp\n\t\t// it onto a hop chain, but it is a legal message and not grounds to drop the stream.\n\t\tconst origin = OriginSchema.parse(await r.u62());\n\t\tconst active = await r.u53();\n\t\treturn new AnnounceOk(origin, active);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tAnnounceOk.#guard(version);\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceOk> {\n\t\tAnnounceOk.#guard(version);\n\t\treturn Message.decode(r, AnnounceOk.#decode);\n\t}\n}\n"]}
1
+ {"version":3,"file":"announce.js","sourceRoot":"","sources":["../../src/lite/announce.ts"],"names":[],"mappings":"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","sourcesContent":["import { ProtocolViolation } from \"../error.ts\";\nimport { type Cost, type Hop, HopSchema, MAX_HOPS, UNKNOWN_HOP } from \"../hop.ts\";\nimport * as Path from \"../path.ts\";\nimport type { Reader, Writer } from \"../stream.ts\";\nimport * as Message from \"./message.ts\";\nimport {\n\thasAnnounceCompression,\n\thasAnnounceId,\n\thasAnnounceOk,\n\thasExcludeHop,\n\thasHidden,\n\thasRouteCost,\n\tVersion,\n} from \"./version.ts\";\n\n// Pre-lite-06 inner status values, carried inside the single ANNOUNCE_BROADCAST body.\nconst STATUS_ENDED = 0;\nconst STATUS_ACTIVE = 1;\nconst STATUS_RESTART = 2;\n\n// lite-06 announce message types: an outer discriminator carried before the length\n// prefix, so each announcement is an independently-typed, length-delimited message\n// (mirroring SUBSCRIBE_START/END/DROP on the subscribe stream).\nconst ANNOUNCE_START = 0;\nconst ANNOUNCE_END = 1;\nconst ANNOUNCE_RESTART = 2;\n\nexport type { Cost };\n\n/**\n * Lite-07: copy `keep` path segments (from the head) or hops (from the tail) of the\n * live announcement `distance` back from the stream's next Announce ID, where 1 is the\n * latest ANNOUNCE_START. Resolved by {@link AnnounceHistory}.\n */\nexport type Base = { distance: bigint; keep: number };\n\n/**\n * An announcement on the Announce Stream, advertising or retracting a broadcast.\n *\n * On lite-06+ these are three independently-typed messages (`ANNOUNCE_START`,\n * `ANNOUNCE_END`, `ANNOUNCE_RESTART`), each framed as `Type | Length | Body` like the\n * subscribe stream's responses. Each `active` (ANNOUNCE_START) implicitly assigns the\n * next announce id (a per-stream ordinal starting at 0); `endedId`/`restart` reference\n * that id instead of repeating the path. Older versions send a single ANNOUNCE_BROADCAST\n * message that retracts by path (`ended`).\n */\nexport type AnnounceBroadcast =\n\t/** A broadcast is now available, carrying the path suffix, the hop chain, and\n\t * (lite-06+) the route cost. An absent cost encodes as zero; it decodes as\n\t * `undefined` on a wire with no room for one. On lite-07, `suffix` follows the\n\t * segments `pathBase` copies and `hops` precede the ones `hopBase` copies. */\n\t| { status: \"active\"; suffix: Path.Valid; hops: Hop[]; cost?: Cost; pathBase?: Base; hopBase?: Base }\n\t/** Pre-lite-06: a broadcast is no longer available, retracted by path. */\n\t| { status: \"ended\"; suffix: Path.Valid }\n\t/** Lite06+: a broadcast is no longer available, retracted by announce id.\n\t * The id is retired; referencing it again is a protocol violation. */\n\t| { status: \"endedId\"; id: bigint }\n\t/** Lite06+: atomically replace the announcement with this id (e.g. a new hop\n\t * chain after a relay failover, or a route whose cost moved). The id stays live. */\n\t| { status: \"restart\"; id: bigint; hops: Hop[]; cost?: Cost; hopBase?: Base }\n\t/** An unknown lite-06+ announce type, skipped by length. Does not assign an id. */\n\t| { status: \"skipped\" };\n\n// Both wire rules on a hop chain, applied to what we send and to what we receive: a\n// chain that revisits a hop looped, so neither forwarding it nor subscribing through it\n// is safe, and a receiver must end the session over one. `UNKNOWN_HOP` identifies\n// nothing, so any number of hops may be unknown.\n//\n// `ProtocolViolation` so a receipt takes the session down rather than the one stream,\n// matching what `ietf/cluster.ts` throws for the identical rule.\nfunction checkHops(hops: Hop[]) {\n\tif (hops.length > MAX_HOPS) {\n\t\tthrow new ProtocolViolation(`hop count ${hops.length} exceeds maximum ${MAX_HOPS}`);\n\t}\n\n\t// MAX_HOPS is 32, so the quadratic scan is cheaper than allocating a set.\n\tfor (let i = 0; i < hops.length; i++) {\n\t\tconst hop = hops[i];\n\t\tif (hop === UNKNOWN_HOP) continue;\n\t\tif (hops.indexOf(hop, i + 1) !== -1) {\n\t\t\tthrow new ProtocolViolation(`hop ${hop} appears twice in the chain`);\n\t\t}\n\t}\n}\n\nasync function encodeHops(w: Writer, version: Version, hops: Hop[]) {\n\tcheckHops(hops);\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\tbreak;\n\t\tcase Version.DRAFT_03:\n\t\t\tawait w.u53(hops.length);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\t// Lite04+: hop count + individual Hop varints.\n\t\t\tawait w.u53(hops.length);\n\t\t\tfor (const origin of hops) {\n\t\t\t\tawait w.u62(origin);\n\t\t\t}\n\t\t\tbreak;\n\t}\n}\n\nasync function decodeHops(r: Reader, version: Version): Promise<Hop[]> {\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\t\treturn [];\n\t\tcase Version.DRAFT_03: {\n\t\t\tconst count = await r.u53();\n\t\t\tif (count > MAX_HOPS) throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);\n\t\t\t// Lite03 carries only a hop count, not individual ids, so every entry is\n\t\t\t// the reserved \"no identity\" id.\n\t\t\treturn new Array<Hop>(count).fill(UNKNOWN_HOP);\n\t\t}\n\t\tdefault: {\n\t\t\t// Lite04+: hop count + individual Hop varints.\n\t\t\tconst count = await r.u53();\n\t\t\tif (count > MAX_HOPS) throw new Error(`hop count ${count} exceeds maximum ${MAX_HOPS}`);\n\t\t\tconst hops: Hop[] = [];\n\t\t\tfor (let i = 0; i < count; i++) {\n\t\t\t\thops.push(HopSchema.parse(await r.u62()));\n\t\t\t}\n\t\t\tcheckHops(hops);\n\t\t\treturn hops;\n\t\t}\n\t}\n}\n\n// Lite-07 carries a base around a path and a hop list. A distance of 0 names\n// nothing, and a keep without a base is a violation. Other versions have no room for\n// a base at all.\nfunction checkBase(version: Version, base: Base | undefined) {\n\tif (base && !hasAnnounceCompression(version)) {\n\t\tthrow new Error(\"announce compression not supported for this version\");\n\t}\n}\n\nfunction toBase(distance: bigint, keep: number): Base | undefined {\n\tif (distance !== 0n) return { distance, keep };\n\tif (keep !== 0) throw new ProtocolViolation(\"announce keep without a base\");\n\treturn undefined;\n}\n\nasync function encodePath(w: Writer, version: Version, suffix: Path.Valid, base: Base | undefined) {\n\tcheckBase(version, base);\n\tif (hasAnnounceCompression(version)) {\n\t\tawait w.u62(base?.distance ?? 0n);\n\t\tawait w.u53(base?.keep ?? 0);\n\t}\n\tawait w.string(Path.encode(suffix));\n}\n\nasync function decodePath(r: Reader, version: Version): Promise<{ suffix: Path.Valid; pathBase?: Base }> {\n\tif (!hasAnnounceCompression(version)) return { suffix: Path.decode(await r.string()) };\n\tconst pathBase = toBase(await r.u62(), await r.u53());\n\tconst suffix = Path.decode(await r.string());\n\treturn pathBase ? { suffix, pathBase } : { suffix };\n}\n\nasync function encodeHopsBlock(w: Writer, version: Version, hops: Hop[], base: Base | undefined) {\n\tcheckBase(version, base);\n\tif (!hasAnnounceCompression(version)) return encodeHops(w, version, hops);\n\tawait w.u62(base?.distance ?? 0n);\n\tawait encodeHops(w, version, hops);\n\tawait w.u53(base?.keep ?? 0);\n}\n\nasync function decodeHopsBlock(r: Reader, version: Version): Promise<{ hops: Hop[]; hopBase?: Base }> {\n\tif (!hasAnnounceCompression(version)) return { hops: await decodeHops(r, version) };\n\tconst distance = await r.u62();\n\tconst hops = await decodeHops(r, version);\n\tconst hopBase = toBase(distance, await r.u53());\n\treturn hopBase ? { hops, hopBase } : { hops };\n}\n\n// The route cost rides lite-06+ announcements as two varints, warm then cold; older\n// versions carry neither. Costs saturate at 2^62-1 on every version, even where lite-07's\n// varints could carry more, so a cost always forwards to a peer on an older version.\nconst MAX_COST = 2n ** 62n - 1n;\nconst saturate = (v: bigint) => (v > MAX_COST ? MAX_COST : v);\n\nasync function encodeRouteCost(w: Writer, version: Version, cost: Cost | undefined) {\n\tif (!hasRouteCost(version)) return;\n\tawait w.u62(saturate(cost?.warm ?? 0n));\n\tawait w.u62(saturate(cost?.cold ?? 0n));\n}\n\nasync function decodeRouteCost(r: Reader, version: Version): Promise<Cost | undefined> {\n\tif (!hasRouteCost(version)) return undefined;\n\treturn { warm: saturate(await r.u62()), cold: saturate(await r.u62()) };\n}\n\n// lite-06 message body (no discriminator; the type is carried outside the length prefix).\nasync function encodeAnnounce06Body(w: Writer, msg: AnnounceBroadcast, version: Version) {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\tawait encodePath(w, version, msg.suffix, msg.pathBase);\n\t\t\tawait encodeHopsBlock(w, version, msg.hops, msg.hopBase);\n\t\t\tawait encodeRouteCost(w, version, msg.cost);\n\t\t\tbreak;\n\t\tcase \"endedId\":\n\t\t\tawait w.u62(msg.id);\n\t\t\tbreak;\n\t\tcase \"restart\":\n\t\t\tawait w.u62(msg.id);\n\t\t\tawait encodeHopsBlock(w, version, msg.hops, msg.hopBase);\n\t\t\tawait encodeRouteCost(w, version, msg.cost);\n\t\t\tbreak;\n\t\tcase \"ended\":\n\t\t\t// The pre-lite-06 path-form retraction has no place on lite-06.\n\t\t\tthrow new Error(\"ended-by-path not supported for this version\");\n\t\tcase \"skipped\":\n\t\t\tthrow new Error(\"decode-only announce type cannot be encoded\");\n\t}\n}\n\n// lite-06 outer message type for a given announcement.\nfunction announce06Type(msg: AnnounceBroadcast): number {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\treturn ANNOUNCE_START;\n\t\tcase \"endedId\":\n\t\t\treturn ANNOUNCE_END;\n\t\tcase \"restart\":\n\t\t\treturn ANNOUNCE_RESTART;\n\t\tcase \"ended\":\n\t\t\tthrow new Error(\"ended-by-path not supported for this version\");\n\t\tcase \"skipped\":\n\t\t\tthrow new Error(\"decode-only announce type cannot be encoded\");\n\t}\n}\n\nasync function decodeAnnounce06Body(r: Reader, typ: number, version: Version): Promise<AnnounceBroadcast> {\n\tswitch (typ) {\n\t\tcase ANNOUNCE_START: {\n\t\t\tconst path = await decodePath(r, version);\n\t\t\tconst hops = await decodeHopsBlock(r, version);\n\t\t\treturn { status: \"active\", ...path, ...hops, cost: await decodeRouteCost(r, version) };\n\t\t}\n\t\tcase ANNOUNCE_END:\n\t\t\treturn { status: \"endedId\", id: await r.u62() };\n\t\tcase ANNOUNCE_RESTART: {\n\t\t\tconst id = await r.u62();\n\t\t\tconst hops = await decodeHopsBlock(r, version);\n\t\t\treturn { status: \"restart\", id, ...hops, cost: await decodeRouteCost(r, version) };\n\t\t}\n\t\tdefault:\n\t\t\t// Skip the length-prefixed body so an earlier Lite06 build negotiating\n\t\t\t// the same ALPN does not kill the announce stream.\n\t\t\tawait r.readAll();\n\t\t\treturn { status: \"skipped\" };\n\t}\n}\n\n// Pre-lite-06 single ANNOUNCE_BROADCAST body: an inner status byte, then path + hops.\nasync function encodeLegacyBody(w: Writer, msg: AnnounceBroadcast, version: Version) {\n\tswitch (msg.status) {\n\t\tcase \"active\":\n\t\t\tcheckBase(version, msg.pathBase ?? msg.hopBase);\n\t\t\tawait w.u8(STATUS_ACTIVE);\n\t\t\tawait w.string(Path.encode(msg.suffix));\n\t\t\tawait encodeHops(w, version, msg.hops);\n\t\t\tbreak;\n\t\tcase \"ended\":\n\t\t\tawait w.u8(STATUS_ENDED);\n\t\t\tawait w.string(Path.encode(msg.suffix));\n\t\t\tawait encodeHops(w, version, []);\n\t\t\tbreak;\n\t\tcase \"endedId\":\n\t\tcase \"restart\":\n\t\tcase \"skipped\":\n\t\t\t// The id-referencing forms only exist on lite-06+.\n\t\t\tthrow new Error(\"announce ids not supported for this version\");\n\t}\n}\n\nasync function decodeLegacyBody(r: Reader, version: Version): Promise<AnnounceBroadcast> {\n\tconst status = await r.u8();\n\t// On lite-05 a restart travels as a duplicate `active`, but the explicit restart\n\t// status is accepted on decode and treated the same. Older versions never defined it.\n\tconst active = status === STATUS_ACTIVE || (status === STATUS_RESTART && hasAnnounceOk(version));\n\tif (status !== STATUS_ENDED && !active) {\n\t\tthrow new Error(\"invalid announce status\");\n\t}\n\tconst suffix = Path.decode(await r.string());\n\tconst hops = await decodeHops(r, version);\n\treturn active ? { status: \"active\", suffix, hops } : { status: \"ended\", suffix };\n}\n\n/** Encode one announcement, including its type discriminator (lite-06+) and length prefix. */\nexport async function encodeAnnounceBroadcast(w: Writer, msg: AnnounceBroadcast, version: Version): Promise<void> {\n\tif (hasAnnounceId(version)) {\n\t\t// lite-06+: outer type discriminator, then a size-prefixed body (like the subscribe stream).\n\t\tawait w.u53(announce06Type(msg));\n\t\treturn Message.encode(w, (w) => encodeAnnounce06Body(w, msg, version));\n\t}\n\treturn Message.encode(w, (w) => encodeLegacyBody(w, msg, version));\n}\n\n/** Decode one announcement, including its type discriminator (lite-06+) and length prefix. */\nexport async function decodeAnnounceBroadcast(r: Reader, version: Version): Promise<AnnounceBroadcast> {\n\tif (hasAnnounceId(version)) {\n\t\tconst typ = await r.u53();\n\t\treturn Message.decode(r, (r) => decodeAnnounce06Body(r, typ, version));\n\t}\n\treturn Message.decode(r, (r) => decodeLegacyBody(r, version));\n}\n\n/** Like {@link decodeAnnounceBroadcast} but resolves `undefined` on a clean FIN. */\nexport async function decodeAnnounceBroadcastMaybe(\n\tr: Reader,\n\tversion: Version,\n): Promise<AnnounceBroadcast | undefined> {\n\tif (hasAnnounceId(version)) {\n\t\tif (await r.done()) return undefined;\n\t\tconst typ = await r.u53();\n\t\treturn Message.decode(r, (r) => decodeAnnounce06Body(r, typ, version));\n\t}\n\treturn Message.decodeMaybe(r, (r) => decodeLegacyBody(r, version));\n}\n\ntype Advertised = { suffix: Path.Valid; hops: Hop[] };\n\n/**\n * The live announcements on one lite-06+ announce stream, by Announce ID: what\n * ANNOUNCE_END and ANNOUNCE_UPDATE reference, and what a lite-07 base copies from.\n * Every violation throws {@link ProtocolViolation}.\n */\nexport class AnnounceHistory {\n\t#next = 0n;\n\t#live = new Map<bigint, Advertised>();\n\n\t#base(base: Base): Advertised {\n\t\tconst live = this.#live.get(this.#next - base.distance);\n\t\tif (!live) throw new ProtocolViolation(`announce base ${base.distance} is not live`);\n\t\treturn live;\n\t}\n\n\t#hops(hops: Hop[], base: Base | undefined): Hop[] {\n\t\tif (!base) return hops;\n\t\tconst tail = this.#base(base).hops;\n\t\tif (base.keep > tail.length) throw new ProtocolViolation(`announce keeps ${base.keep} of ${tail.length} hops`);\n\t\tconst resolved = [...hops, ...tail.slice(tail.length - base.keep)];\n\t\tcheckHops(resolved);\n\t\treturn resolved;\n\t}\n\n\t/** An ANNOUNCE_START: resolve it and assign it the next id. */\n\tstart(msg: { suffix: Path.Valid; hops: Hop[]; pathBase?: Base; hopBase?: Base }): Advertised {\n\t\tlet suffix = msg.suffix;\n\t\tif (msg.pathBase) {\n\t\t\tconst head = Path.parts(this.#base(msg.pathBase).suffix);\n\t\t\tconst keep = msg.pathBase.keep;\n\t\t\tif (keep > head.length) throw new ProtocolViolation(`announce keeps ${keep} of ${head.length} segments`);\n\t\t\tsuffix = Path.join(Path.from(...head.slice(0, keep)), suffix);\n\t\t\tif (Path.parts(suffix).length > Path.MAX_PARTS) {\n\t\t\t\tthrow new ProtocolViolation(`path exceeds ${Path.MAX_PARTS} parts`);\n\t\t\t}\n\t\t}\n\t\tconst hops = this.#hops(msg.hops, msg.hopBase);\n\t\tthis.#live.set(this.#next++, { suffix, hops });\n\t\treturn { suffix, hops };\n\t}\n\n\t/** An ANNOUNCE_UPDATE: resolve its chain before replacing the old one, which it may be based on. */\n\tupdate(msg: { id: bigint; hops: Hop[]; hopBase?: Base }): Advertised {\n\t\tconst hops = this.#hops(msg.hops, msg.hopBase);\n\t\tconst live = this.#live.get(msg.id);\n\t\tif (!live) throw new ProtocolViolation(`unknown announce id: ${msg.id}`);\n\t\tthis.#live.set(msg.id, { suffix: live.suffix, hops });\n\t\treturn { suffix: live.suffix, hops };\n\t}\n\n\t/** An ANNOUNCE_END: retire the id, returning its suffix. */\n\tend(id: bigint): Path.Valid {\n\t\tconst live = this.#live.get(id);\n\t\tif (!live) throw new ProtocolViolation(`unknown announce id: ${id}`);\n\t\tthis.#live.delete(id);\n\t\treturn live.suffix;\n\t}\n}\n\n/**\n * ANNOUNCE_REQUEST: sent by the subscriber to request ANNOUNCE_BROADCAST messages\n * for a path prefix. Renamed from `AnnounceInterest` in lite-05.\n */\nexport class AnnounceRequest {\n\tprefix: Path.Valid;\n\t/** Lite04/05 only: the 62-bit Hop id of the peer asking for announces, which the\n\t * publisher uses to skip announces that already passed through it. Zero means \"no\n\t * exclusion\". Not on the wire elsewhere, so a value set here is ignored when encoding\n\t * for another version and decodes as zero.\n\t *\n\t * Must be a bigint: peer origins are up to 62 bits and overflow u53. */\n\texcludeHop: bigint;\n\t/** Lite07+: also announce routes with a `.`-prefixed segment below the prefix. Not on\n\t * the wire earlier, so a value set here is ignored when encoding for an older version\n\t * and decodes as false. */\n\thidden: boolean;\n\n\tconstructor(prefix: Path.Valid, excludeHop: bigint = 0n, hidden = false) {\n\t\tthis.prefix = prefix;\n\t\tthis.excludeHop = excludeHop;\n\t\tthis.hidden = hidden;\n\t}\n\n\tasync #encode(w: Writer, version: Version) {\n\t\tawait w.string(Path.encode(this.prefix));\n\t\tif (hasExcludeHop(version)) {\n\t\t\tawait w.u62(this.excludeHop);\n\t\t}\n\t\tif (hasHidden(version)) {\n\t\t\tawait w.bool(this.hidden);\n\t\t}\n\t}\n\n\tstatic async #decode(r: Reader, version: Version): Promise<AnnounceRequest> {\n\t\tconst prefix = Path.decode(await r.string());\n\t\tconst excludeHop = hasExcludeHop(version) ? await r.u62() : 0n;\n\t\tconst hidden = hasHidden(version) ? await r.bool() : false;\n\t\treturn new AnnounceRequest(prefix, excludeHop, hidden);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\treturn Message.encode(w, (w) => this.#encode(w, version));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceRequest> {\n\t\treturn Message.decode(r, (r) => AnnounceRequest.#decode(r, version));\n\t}\n}\n\n/// Sent after setup to communicate the initially announced paths.\n///\n/// Used by Draft01/Draft02 only. Draft03+ uses individual Announce messages instead.\nexport class AnnounceInit {\n\tsuffixes: Path.Valid[];\n\n\tconstructor(paths: Path.Valid[]) {\n\t\tthis.suffixes = paths;\n\t}\n\n\tstatic #guard(version: Version) {\n\t\tswitch (version) {\n\t\t\tcase Version.DRAFT_01:\n\t\t\tcase Version.DRAFT_02:\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new Error(\"announce init not supported for this version\");\n\t\t}\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.u53(this.suffixes.length);\n\t\tfor (const path of this.suffixes) {\n\t\t\tawait w.string(Path.encode(path));\n\t\t}\n\t}\n\n\tstatic async #decode(r: Reader): Promise<AnnounceInit> {\n\t\tconst count = await r.u53();\n\t\tconst suffixes: Path.Valid[] = [];\n\t\tfor (let i = 0; i < count; i++) {\n\t\t\tsuffixes.push(Path.decode(await r.string()));\n\t\t}\n\t\treturn new AnnounceInit(suffixes);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tAnnounceInit.#guard(version);\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceInit> {\n\t\tAnnounceInit.#guard(version);\n\t\treturn Message.decode(r, AnnounceInit.#decode);\n\t}\n}\n\n/// Sent by the publisher as the first message on an announce stream, before any\n/// individual Announce messages. Lite05+ only; the successor to AnnounceInit.\n///\n/// `origin` is the responder's Hop ID, which the subscriber stamps onto each\n/// announce's hop chain (the publisher no longer stamps itself), or the reserved\n/// {@link UNKNOWN_HOP} when the responder has no identity to give. `active` is\n/// the number of initial Announce messages that follow immediately.\nexport class AnnounceOk {\n\thop: Hop;\n\tactive: number;\n\n\tconstructor(hop: Hop, active: number) {\n\t\tthis.hop = hop;\n\t\tthis.active = active;\n\t}\n\n\tstatic #guard(version: Version) {\n\t\tif (!hasAnnounceOk(version)) {\n\t\t\tthrow new Error(\"announce ok not supported for this version\");\n\t\t}\n\t}\n\n\tasync #encode(w: Writer) {\n\t\tawait w.u62(this.hop);\n\t\tawait w.u53(this.active);\n\t}\n\n\tstatic async #decode(r: Reader): Promise<AnnounceOk> {\n\t\t// The draft reserves 0 for \"unknown\": the responder was never assigned an id, or\n\t\t// withholds it to obscure its routing. It names nobody, so callers must not stamp\n\t\t// it onto a hop chain, but it is a legal message and not grounds to drop the stream.\n\t\tconst origin = HopSchema.parse(await r.u62());\n\t\tconst active = await r.u53();\n\t\treturn new AnnounceOk(origin, active);\n\t}\n\n\tasync encode(w: Writer, version: Version): Promise<void> {\n\t\tAnnounceOk.#guard(version);\n\t\treturn Message.encode(w, this.#encode.bind(this));\n\t}\n\n\tstatic async decode(r: Reader, version: Version): Promise<AnnounceOk> {\n\t\tAnnounceOk.#guard(version);\n\t\treturn Message.decode(r, AnnounceOk.#decode);\n\t}\n}\n"]}
@@ -1,31 +1,11 @@
1
1
  import { type Getter } from "@norskvideo/moq-signals";
2
- import * as announce from "../announced";
3
- import type * as broadcast from "../broadcast";
2
+ import type * as announce from "../announced";
4
3
  import type { Established } from "../connection/established";
5
4
  import { type Probe, type Stats } from "../connection/stats";
6
5
  import { type Transport } from "../connection/transport";
7
- import { type Origin } from "../origin";
8
- import * as Path from "../path";
9
- import { Stream } from "../stream";
10
- import { ProbeLevel, type Role } from "./setup";
11
- import { type Version } from "./version";
12
- /**
13
- * Constructor options for {@link Connection}.
14
- *
15
- * @internal
16
- */
17
- export interface ConnectionProps {
18
- /** The URL of the connection. */
19
- url: URL;
20
- /** The established WebTransport session. */
21
- quic: WebTransport;
22
- /** The negotiated wire version. */
23
- version: Version;
24
- /** The session stream, absent on drafts that have none. */
25
- session?: Stream;
26
- /** Whether the relay supports broadcast discovery. Defaults to true. */
27
- discovery?: boolean;
28
- }
6
+ import { type Hop } from "../hop";
7
+ import type * as Path from "../path";
8
+ import { type Role } from "./setup";
29
9
  /**
30
10
  * Represents a connection to a MoQ server.
31
11
  *
@@ -40,9 +20,9 @@ export declare class Connection implements Established {
40
20
  readonly discovery: boolean;
41
21
  /** The peer's PROBE estimates; see {@link Established.probe}. */
42
22
  readonly probe: Getter<Probe>;
43
- /** Random per-connection origin id. Shared by Publisher (for outbound hop
23
+ /** Random per-connection Hop ID. Shared by Publisher (for outbound hop
44
24
  * chains) and Subscriber (available for optional self-filtering on announces). */
45
- readonly origin: Origin;
25
+ readonly hop: Hop;
46
26
  /**
47
27
  * The {@link Role} the peer advertised in its SETUP, for a server deciding whether the
48
28
  * peer's authorization grants the direction it intends to use.
@@ -53,44 +33,14 @@ export declare class Connection implements Established {
53
33
  * recognize, or is a server (which never sends one).
54
34
  */
55
35
  get peerRole(): Getter<Role | undefined>;
56
- /**
57
- * Creates a new Connection instance.
58
- *
59
- * @internal
60
- */
61
- constructor({ url, quic, version, session, discovery }: ConnectionProps);
62
36
  /**
63
37
  * Closes the connection.
64
38
  */
65
39
  close(): void;
66
- publish(path: Path.Valid, producer: broadcast.Producer): void;
67
- announced(prefix?: Path.Valid): announce.Consumer;
68
- consume(path: Path.Valid): broadcast.Consumer;
69
- /**
70
- * Watches a broadcast, live only while it is announced.
71
- *
72
- * @param path - The path of the broadcast to watch
73
- * @returns A reactive handle to the broadcast
74
- */
75
- announcedBroadcast(path: Path.Valid): announce.Broadcast;
40
+ announced(scope?: Path.Pattern, options?: announce.Options): announce.Consumer;
76
41
  /** Snapshot the transport's counters; see {@link Established.stats}. */
77
42
  stats(): Promise<Stats>;
78
- get closed(): Promise<void>;
43
+ /** Resolves when the session closes, decoding the peer's close code; see {@link Established.closed}. */
44
+ get closed(): Promise<Error | null>;
79
45
  }
80
- /**
81
- * The probe level to advertise in SETUP, from what the transport can measure.
82
- *
83
- * `Report` claims we can measure and periodically report, so it is only truthful
84
- * when a metric this version can carry actually exists. The qmux/WebSocket fallback
85
- * implements no `getStats()` at all, and even a transport that has one may report
86
- * neither figure. Advertising `Report` and then holding the subscriber's PROBE
87
- * stream open with nothing to send is the state this avoids; the subscriber's own
88
- * gate then skips a stream it could not use.
89
- *
90
- * Mirrors `ProbeLevel::detect` in `moq-net`, including its limitation: a metric
91
- * that only appears after SETUP reads as unsupported here.
92
- *
93
- * @internal
94
- */
95
- export declare function probeLevel(quic: WebTransport, version: Version): Promise<ProbeLevel>;
96
46
  //# sourceMappingURL=connection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/lite/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAU,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAkB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,4BAA4B,CAAC;AACzE,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,IAAI,MAAM,YAAY,CAAC;AACnC,OAAO,EAAwB,MAAM,EAAU,MAAM,cAAc,CAAC;AAOpE,OAAO,EAAE,UAAU,EAAE,KAAK,IAAI,EAAS,MAAM,YAAY,CAAC;AAK1D,OAAO,EAA6C,KAAK,OAAO,EAAe,MAAM,cAAc,CAAC;AAEpG;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,iCAAiC;IACjC,GAAG,EAAE,GAAG,CAAC;IACT,4CAA4C;IAC5C,IAAI,EAAE,YAAY,CAAC;IACnB,mCAAmC;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;GAIG;AACH,qBAAa,UAAW,YAAW,WAAW;;IAE7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAGlB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAGzB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAiB5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9B;sFACkF;IAClF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAcxB;;;;;;;;OAQG;IACH,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC,CAEvC;IAED;;;;OAIG;IACH,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,SAAgB,EAAE,EAAE,eAAe,EAgB7E;IAED;;OAEG;IACH,KAAK,SAUJ;IA0BD,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,QAErD;IAED,SAAS,CAAC,MAAM,aAAe,GAAG,QAAQ,CAAC,QAAQ,CAElD;IAED,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,QAAQ,CAE5C;IAED;;;;;OAKG;IACH,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,SAAS,CAEvD;IAgHD,wEAAwE;IAClE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,CAE5B;IAED,IAAI,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1B;CACD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAkB1F"}
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/lite/connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAU,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,KAAK,QAAQ,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,KAAK,EAAkB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,KAAK,SAAS,EAAe,MAAM,4BAA4B,CAAC;AAEzE,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,KAAK,IAAI,MAAM,YAAY,CAAC;AASxC,OAAO,EAAc,KAAK,IAAI,EAAS,MAAM,YAAY,CAAC;AA2B1D;;;;GAIG;AACH,qBAAa,UAAW,YAAW,WAAW;;IAE7C,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAGlB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAGzB,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAE9B,yFAAyF;IACzF,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAiB5B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAE9B;sFACkF;IAClF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAclB;;;;;;;;OAQG;IACH,IAAI,QAAQ,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,CAAC,CAEvC;IA+BD;;OAEG;IACH,KAAK,SAUJ;IAgCD,SAAS,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAE7E;IAiHD,wEAAwE;IAClE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,CAE5B;IAED,wGAAwG;IACxG,IAAI,MAAM,IAAI,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAElC;CACD"}