@norskvideo/moq-net 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/announced.d.ts +111 -21
- package/announced.d.ts.map +1 -1
- package/announced.js +213 -40
- package/announced.js.map +1 -1
- package/broadcast.d.ts +80 -25
- package/broadcast.d.ts.map +1 -1
- package/broadcast.js +270 -49
- package/broadcast.js.map +1 -1
- package/connection/accept.d.ts +6 -0
- package/connection/accept.d.ts.map +1 -1
- package/connection/accept.js +42 -13
- package/connection/accept.js.map +1 -1
- package/connection/browser.d.ts +5 -0
- package/connection/browser.d.ts.map +1 -0
- package/connection/browser.js +31 -0
- package/connection/browser.js.map +1 -0
- package/connection/connect.d.ts +43 -1
- package/connection/connect.d.ts.map +1 -1
- package/connection/connect.js +118 -123
- package/connection/connect.js.map +1 -1
- package/connection/established.d.ts +43 -16
- package/connection/established.d.ts.map +1 -1
- package/connection/established.js.map +1 -1
- package/connection/handshake.d.ts +12 -1
- package/connection/handshake.d.ts.map +1 -1
- package/connection/handshake.js +30 -14
- package/connection/handshake.js.map +1 -1
- package/connection/index.d.ts +8 -0
- package/connection/index.d.ts.map +1 -1
- package/connection/index.js +6 -0
- package/connection/index.js.map +1 -1
- package/connection/reload.d.ts +66 -9
- package/connection/reload.d.ts.map +1 -1
- package/connection/reload.js +192 -66
- package/connection/reload.js.map +1 -1
- package/connection/stats.d.ts +92 -0
- package/connection/stats.d.ts.map +1 -0
- package/connection/stats.js +35 -0
- package/connection/stats.js.map +1 -0
- package/connection/transport.d.ts +10 -0
- package/connection/transport.d.ts.map +1 -0
- package/connection/transport.js +12 -0
- package/connection/transport.js.map +1 -0
- package/consume.d.ts +44 -0
- package/consume.d.ts.map +1 -0
- package/consume.js +60 -0
- package/consume.js.map +1 -0
- package/datagram.d.ts +23 -0
- package/datagram.d.ts.map +1 -0
- package/datagram.js +3 -0
- package/datagram.js.map +1 -0
- package/error.d.ts +76 -0
- package/error.d.ts.map +1 -0
- package/error.js +107 -0
- package/error.js.map +1 -0
- package/group.d.ts +143 -38
- package/group.d.ts.map +1 -1
- package/group.js +270 -68
- package/group.js.map +1 -1
- package/ietf/adapter.d.ts +2 -2
- package/ietf/adapter.d.ts.map +1 -1
- package/ietf/adapter.js +20 -10
- package/ietf/adapter.js.map +1 -1
- package/ietf/aliases.d.ts +73 -5
- package/ietf/aliases.d.ts.map +1 -1
- package/ietf/aliases.js +121 -14
- package/ietf/aliases.js.map +1 -1
- package/ietf/cluster.d.ts +141 -0
- package/ietf/cluster.d.ts.map +1 -0
- package/ietf/cluster.js +204 -0
- package/ietf/cluster.js.map +1 -0
- package/ietf/connection.d.ts +39 -6
- package/ietf/connection.d.ts.map +1 -1
- package/ietf/connection.js +73 -12
- package/ietf/connection.js.map +1 -1
- package/ietf/fetch.d.ts +17 -0
- package/ietf/fetch.d.ts.map +1 -1
- package/ietf/fetch.js +21 -0
- package/ietf/fetch.js.map +1 -1
- package/ietf/filter.d.ts +87 -0
- package/ietf/filter.d.ts.map +1 -0
- package/ietf/filter.js +292 -0
- package/ietf/filter.js.map +1 -0
- package/ietf/index.d.ts +2 -0
- package/ietf/index.d.ts.map +1 -1
- package/ietf/index.js +3 -0
- package/ietf/index.js.map +1 -1
- package/ietf/namespace.d.ts +6 -0
- package/ietf/namespace.d.ts.map +1 -1
- package/ietf/namespace.js +27 -2
- package/ietf/namespace.js.map +1 -1
- package/ietf/object.d.ts +54 -6
- package/ietf/object.d.ts.map +1 -1
- package/ietf/object.js +178 -25
- package/ietf/object.js.map +1 -1
- package/ietf/parameters.d.ts +35 -10
- package/ietf/parameters.d.ts.map +1 -1
- package/ietf/parameters.js +236 -45
- package/ietf/parameters.js.map +1 -1
- package/ietf/priority.d.ts +5 -0
- package/ietf/priority.d.ts.map +1 -0
- package/ietf/priority.js +10 -0
- package/ietf/priority.js.map +1 -0
- package/ietf/properties.d.ts +13 -2
- package/ietf/properties.d.ts.map +1 -1
- package/ietf/properties.js +65 -8
- package/ietf/properties.js.map +1 -1
- package/ietf/publish.d.ts.map +1 -1
- package/ietf/publish.js +13 -3
- package/ietf/publish.js.map +1 -1
- package/ietf/publish_namespace.d.ts +16 -2
- package/ietf/publish_namespace.d.ts.map +1 -1
- package/ietf/publish_namespace.js +25 -6
- package/ietf/publish_namespace.js.map +1 -1
- package/ietf/publisher.d.ts +40 -7
- package/ietf/publisher.d.ts.map +1 -1
- package/ietf/publisher.js +751 -134
- package/ietf/publisher.js.map +1 -1
- package/ietf/request.js +1 -1
- package/ietf/request.js.map +1 -1
- package/ietf/solicit.d.ts +41 -0
- package/ietf/solicit.d.ts.map +1 -0
- package/ietf/solicit.js +47 -0
- package/ietf/solicit.js.map +1 -0
- package/ietf/subscribe.d.ts +41 -2
- package/ietf/subscribe.d.ts.map +1 -1
- package/ietf/subscribe.js +103 -22
- package/ietf/subscribe.js.map +1 -1
- package/ietf/subscribe_namespace.d.ts +21 -7
- package/ietf/subscribe_namespace.d.ts.map +1 -1
- package/ietf/subscribe_namespace.js +31 -14
- package/ietf/subscribe_namespace.js.map +1 -1
- package/ietf/subscriber.d.ts +20 -7
- package/ietf/subscriber.d.ts.map +1 -1
- package/ietf/subscriber.js +512 -142
- package/ietf/subscriber.js.map +1 -1
- package/ietf/version.d.ts +7 -1
- package/ietf/version.d.ts.map +1 -1
- package/ietf/version.js +7 -0
- package/ietf/version.js.map +1 -1
- package/index.d.ts +10 -5
- package/index.d.ts.map +1 -1
- package/index.js +10 -5
- package/index.js.map +1 -1
- package/internal.d.ts +29 -0
- package/internal.d.ts.map +1 -0
- package/internal.js +8 -0
- package/internal.js.map +1 -0
- package/lite/announce.d.ts +62 -15
- package/lite/announce.d.ts.map +1 -1
- package/lite/announce.js +230 -94
- package/lite/announce.js.map +1 -1
- package/lite/connection.d.ts +69 -20
- package/lite/connection.d.ts.map +1 -1
- package/lite/connection.js +128 -81
- package/lite/connection.js.map +1 -1
- package/lite/datagram.d.ts +23 -0
- package/lite/datagram.d.ts.map +1 -0
- package/lite/datagram.js +57 -0
- package/lite/datagram.js.map +1 -0
- package/lite/datagram_stream.d.ts +8 -0
- package/lite/datagram_stream.d.ts.map +1 -0
- package/lite/datagram_stream.js +44 -0
- package/lite/datagram_stream.js.map +1 -0
- package/lite/fetch.d.ts.map +1 -1
- package/lite/fetch.js +2 -2
- package/lite/fetch.js.map +1 -1
- package/lite/index.d.ts +3 -0
- package/lite/index.d.ts.map +1 -1
- package/lite/index.js +3 -0
- package/lite/index.js.map +1 -1
- package/lite/priority.d.ts +67 -0
- package/lite/priority.d.ts.map +1 -0
- package/lite/priority.js +114 -0
- package/lite/priority.js.map +1 -0
- package/lite/probe.d.ts +18 -2
- package/lite/probe.d.ts.map +1 -1
- package/lite/probe.js +24 -22
- package/lite/probe.js.map +1 -1
- package/lite/publisher.d.ts +14 -7
- package/lite/publisher.d.ts.map +1 -1
- package/lite/publisher.js +406 -84
- package/lite/publisher.js.map +1 -1
- package/lite/setup.d.ts +83 -6
- package/lite/setup.d.ts.map +1 -1
- package/lite/setup.js +203 -31
- package/lite/setup.js.map +1 -1
- package/lite/stream.d.ts +12 -3
- package/lite/stream.d.ts.map +1 -1
- package/lite/stream.js +7 -4
- package/lite/stream.js.map +1 -1
- package/lite/subscribe.d.ts +37 -23
- package/lite/subscribe.d.ts.map +1 -1
- package/lite/subscribe.js +70 -55
- package/lite/subscribe.js.map +1 -1
- package/lite/subscriber.d.ts +29 -23
- package/lite/subscriber.d.ts.map +1 -1
- package/lite/subscriber.js +689 -112
- package/lite/subscriber.js.map +1 -1
- package/lite/track.d.ts +25 -13
- package/lite/track.d.ts.map +1 -1
- package/lite/track.js +60 -35
- package/lite/track.js.map +1 -1
- package/lite/version.d.ts +39 -4
- package/lite/version.d.ts.map +1 -1
- package/lite/version.js +139 -17
- package/lite/version.js.map +1 -1
- package/mock.d.ts +53 -3
- package/mock.d.ts.map +1 -1
- package/mock.js +110 -21
- package/mock.js.map +1 -1
- package/{lite/origin.d.ts → origin.d.ts} +25 -1
- package/origin.d.ts.map +1 -0
- package/{lite/origin.js → origin.js} +25 -1
- package/origin.js.map +1 -0
- package/package.json +6 -4
- package/path.d.ts +67 -0
- package/path.d.ts.map +1 -1
- package/path.js +128 -0
- package/path.js.map +1 -1
- package/stream.d.ts +94 -4
- package/stream.d.ts.map +1 -1
- package/stream.js +128 -17
- package/stream.js.map +1 -1
- package/time.d.ts +109 -86
- package/time.d.ts.map +1 -1
- package/time.js +80 -30
- package/time.js.map +1 -1
- package/track.d.ts +298 -47
- package/track.d.ts.map +1 -1
- package/track.js +721 -109
- package/track.js.map +1 -1
- package/util/timeout.d.ts +5 -0
- package/util/timeout.d.ts.map +1 -0
- package/util/timeout.js +18 -0
- package/util/timeout.js.map +1 -0
- package/util/utf8.d.ts +3 -0
- package/util/utf8.d.ts.map +1 -0
- package/util/utf8.js +7 -0
- package/util/utf8.js.map +1 -0
- package/varint.d.ts +14 -3
- package/varint.d.ts.map +1 -1
- package/varint.js +23 -12
- package/varint.js.map +1 -1
- package/zod.d.ts +5 -5
- package/zod.d.ts.map +1 -1
- package/zod.js.map +1 -1
- package/bandwidth.d.ts +0 -11
- package/bandwidth.d.ts.map +0 -1
- package/bandwidth.js +0 -7
- package/bandwidth.js.map +0 -1
- package/connection/cert.test.d.ts +0 -2
- package/connection/cert.test.d.ts.map +0 -1
- package/connection/cert.test.js +0 -26
- package/connection/cert.test.js.map +0 -1
- package/connection/reload.test.d.ts +0 -2
- package/connection/reload.test.d.ts.map +0 -1
- package/connection/reload.test.js +0 -39
- package/connection/reload.test.js.map +0 -1
- package/group.test.d.ts +0 -2
- package/group.test.d.ts.map +0 -1
- package/group.test.js +0 -66
- package/group.test.js.map +0 -1
- package/ietf/aliases.test.d.ts +0 -2
- package/ietf/aliases.test.d.ts.map +0 -1
- package/ietf/aliases.test.js +0 -30
- package/ietf/aliases.test.js.map +0 -1
- package/ietf/ietf.test.d.ts +0 -2
- package/ietf/ietf.test.d.ts.map +0 -1
- package/ietf/ietf.test.js +0 -873
- package/ietf/ietf.test.js.map +0 -1
- package/integration.test.d.ts +0 -2
- package/integration.test.d.ts.map +0 -1
- package/integration.test.js +0 -90
- package/integration.test.js.map +0 -1
- package/lite/origin.d.ts.map +0 -1
- package/lite/origin.js.map +0 -1
- package/lite/subscriber.test.d.ts +0 -2
- package/lite/subscriber.test.d.ts.map +0 -1
- package/lite/subscriber.test.js +0 -30
- package/lite/subscriber.test.js.map +0 -1
- package/lite/track.test.d.ts +0 -2
- package/lite/track.test.d.ts.map +0 -1
- package/lite/track.test.js +0 -53
- package/lite/track.test.js.map +0 -1
- package/path.test.d.ts +0 -2
- package/path.test.d.ts.map +0 -1
- package/path.test.js +0 -169
- package/path.test.js.map +0 -1
- package/stream.test.d.ts +0 -2
- package/stream.test.d.ts.map +0 -1
- package/stream.test.js +0 -210
- package/stream.test.js.map +0 -1
- package/track.test.d.ts +0 -2
- package/track.test.d.ts.map +0 -1
- package/track.test.js +0 -56
- package/track.test.js.map +0 -1
- package/util/error.d.ts +0 -3
- package/util/error.d.ts.map +0 -1
- package/util/error.js +0 -9
- package/util/error.js.map +0 -1
- package/util/index.d.ts +0 -2
- package/util/index.d.ts.map +0 -1
- package/util/index.js +0 -3
- package/util/index.js.map +0 -1
- package/varint.test.d.ts +0 -2
- package/varint.test.d.ts.map +0 -1
- package/varint.test.js +0 -106
- package/varint.test.js.map +0 -1
package/lite/version.js
CHANGED
|
@@ -4,10 +4,138 @@ export const Version = {
|
|
|
4
4
|
DRAFT_02: 0xff0dad02,
|
|
5
5
|
DRAFT_03: 0xff0dad03,
|
|
6
6
|
DRAFT_04: 0xff0dad04,
|
|
7
|
-
|
|
8
|
-
///
|
|
9
|
-
|
|
7
|
+
DRAFT_05: 0xff0dad05,
|
|
8
|
+
/// Work-in-progress lite-06, advertised as the preferred WebTransport subprotocol.
|
|
9
|
+
/// Adds announce ids: each active ANNOUNCE_BROADCAST implicitly assigns the next
|
|
10
|
+
/// ordinal, and ended/restart reference that id instead of repeating the path.
|
|
11
|
+
DRAFT_06: 0xff0dad06,
|
|
10
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Whether the PROBE message carries the RTT field.
|
|
15
|
+
*
|
|
16
|
+
* Added in lite-04. Lite-03 carries the bitrate alone, so a report with only an RTT to
|
|
17
|
+
* give says nothing there and must not be sent.
|
|
18
|
+
*/
|
|
19
|
+
export function hasProbeRtt(version) {
|
|
20
|
+
// Explicitly list older versions so future versions default to carrying RTT.
|
|
21
|
+
switch (version) {
|
|
22
|
+
case Version.DRAFT_01:
|
|
23
|
+
case Version.DRAFT_02:
|
|
24
|
+
case Version.DRAFT_03:
|
|
25
|
+
return false;
|
|
26
|
+
default:
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/// Whether the session opens a unidirectional Setup Stream carrying a single SETUP message
|
|
31
|
+
/// (capabilities + optional Path). Added in lite-05; older drafts have no Setup Stream.
|
|
32
|
+
export function hasSetupStream(version) {
|
|
33
|
+
// Explicitly list older versions so future versions default to having the stream.
|
|
34
|
+
switch (version) {
|
|
35
|
+
case Version.DRAFT_01:
|
|
36
|
+
case Version.DRAFT_02:
|
|
37
|
+
case Version.DRAFT_03:
|
|
38
|
+
case Version.DRAFT_04:
|
|
39
|
+
return false;
|
|
40
|
+
default:
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/// Whether the session may deliver groups over unreliable QUIC datagrams (lite-05 §6.4).
|
|
45
|
+
/// A datagram carries one single-frame group's `subscribe | sequence | timestamp | payload` and is
|
|
46
|
+
/// routed over the existing subscription. Added in lite-05; older versions never send/accept them.
|
|
47
|
+
export function hasDatagrams(version) {
|
|
48
|
+
// Explicitly list older versions so future versions default to having datagrams.
|
|
49
|
+
switch (version) {
|
|
50
|
+
case Version.DRAFT_01:
|
|
51
|
+
case Version.DRAFT_02:
|
|
52
|
+
case Version.DRAFT_03:
|
|
53
|
+
case Version.DRAFT_04:
|
|
54
|
+
return false;
|
|
55
|
+
default:
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Whether announce streams begin with ANNOUNCE_OK and omit the sender's origin from each hop chain. */
|
|
60
|
+
export function hasAnnounceOk(version) {
|
|
61
|
+
// Explicitly list older versions so future versions keep the lite-05+ announce behavior.
|
|
62
|
+
switch (version) {
|
|
63
|
+
case Version.DRAFT_01:
|
|
64
|
+
case Version.DRAFT_02:
|
|
65
|
+
case Version.DRAFT_03:
|
|
66
|
+
case Version.DRAFT_04:
|
|
67
|
+
return false;
|
|
68
|
+
default:
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/** Whether the version can replace an advertisement in place rather than retracting and
|
|
73
|
+
* re-announcing it. Added in lite-05 as a duplicate ANNOUNCE; lite-06 gave it a message of
|
|
74
|
+
* its own (ANNOUNCE_UPDATE) and made the duplicate a violation. */
|
|
75
|
+
export function restartSupported(version) {
|
|
76
|
+
// Explicitly list older versions so future versions default to supported.
|
|
77
|
+
switch (version) {
|
|
78
|
+
case Version.DRAFT_01:
|
|
79
|
+
case Version.DRAFT_02:
|
|
80
|
+
case Version.DRAFT_03:
|
|
81
|
+
case Version.DRAFT_04:
|
|
82
|
+
return false;
|
|
83
|
+
default:
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Whether announcements carry implicit announce ids: each `active` assigns the next
|
|
88
|
+
* per-stream ordinal, and `ended`/`restart` reference that id instead of repeating the
|
|
89
|
+
* path. Added in lite-06. */
|
|
90
|
+
export function hasAnnounceId(version) {
|
|
91
|
+
// Explicitly list older versions so future versions keep the lite-06+ announce behavior.
|
|
92
|
+
switch (version) {
|
|
93
|
+
case Version.DRAFT_01:
|
|
94
|
+
case Version.DRAFT_02:
|
|
95
|
+
case Version.DRAFT_03:
|
|
96
|
+
case Version.DRAFT_04:
|
|
97
|
+
case Version.DRAFT_05:
|
|
98
|
+
return false;
|
|
99
|
+
default:
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Whether ANNOUNCE_REQUEST carries the Exclude Hop field: the subscriber's own
|
|
104
|
+
* origin id, which the publisher uses to skip announces whose hop chain already
|
|
105
|
+
* passed through the subscriber. Present in lite-04 and lite-05 only.
|
|
106
|
+
*
|
|
107
|
+
* The receiver's own reflected-announce check drops those announces anyway (and
|
|
108
|
+
* catches loops of any length, not just the two-hop case), so lite-06 drops the
|
|
109
|
+
* field and keeps the check.
|
|
110
|
+
*
|
|
111
|
+
* Unlike the gates above, this lists the versions that *have* the field: it was
|
|
112
|
+
* removed rather than added, so future versions default to not carrying it. */
|
|
113
|
+
export function hasExcludeHop(version) {
|
|
114
|
+
switch (version) {
|
|
115
|
+
case Version.DRAFT_04:
|
|
116
|
+
case Version.DRAFT_05:
|
|
117
|
+
return true;
|
|
118
|
+
default:
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/** Whether announcements carry a route cost varint alongside the hop chain: the
|
|
123
|
+
* marginal cost of pulling the broadcast via this route, accumulated per link.
|
|
124
|
+
* Added in lite-06. Older versions carry nothing, so a received route stays at
|
|
125
|
+
* zero and routing falls back to the hop-count tie-break. */
|
|
126
|
+
export function hasRouteCost(version) {
|
|
127
|
+
// Explicitly list older versions so future versions keep the lite-06+ behavior.
|
|
128
|
+
switch (version) {
|
|
129
|
+
case Version.DRAFT_01:
|
|
130
|
+
case Version.DRAFT_02:
|
|
131
|
+
case Version.DRAFT_03:
|
|
132
|
+
case Version.DRAFT_04:
|
|
133
|
+
case Version.DRAFT_05:
|
|
134
|
+
return false;
|
|
135
|
+
default:
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
11
139
|
/// The WebTransport subprotocol identifier for moq-lite.
|
|
12
140
|
/// Version negotiation still happens via SETUP when this is used.
|
|
13
141
|
export const ALPN = "moql";
|
|
@@ -15,27 +143,21 @@ export const ALPN = "moql";
|
|
|
15
143
|
export const ALPN_03 = "moq-lite-03";
|
|
16
144
|
/// The ALPN string for Draft04, which uses ALPN-based version negotiation.
|
|
17
145
|
export const ALPN_04 = "moq-lite-04";
|
|
18
|
-
/// The ALPN string for
|
|
19
|
-
|
|
20
|
-
|
|
146
|
+
/// The ALPN string for Draft05, which uses ALPN-based version negotiation.
|
|
147
|
+
export const ALPN_05 = "moq-lite-05";
|
|
148
|
+
/// The ALPN string for the work-in-progress Draft06. It is NOT in the default
|
|
149
|
+
/// WebTransport `protocols` list, so lite-06 is never advertised or negotiated by
|
|
150
|
+
/// default; a peer only reaches it when both sides explicitly offer this ALPN.
|
|
151
|
+
export const ALPN_06_WIP = "moq-lite-06-wip";
|
|
21
152
|
const VERSION_NAMES = {
|
|
22
153
|
[Version.DRAFT_01]: "moq-lite-01",
|
|
23
154
|
[Version.DRAFT_02]: "moq-lite-02",
|
|
24
155
|
[Version.DRAFT_03]: "moq-lite-03",
|
|
25
156
|
[Version.DRAFT_04]: "moq-lite-04",
|
|
26
|
-
[Version.
|
|
157
|
+
[Version.DRAFT_05]: "moq-lite-05",
|
|
158
|
+
[Version.DRAFT_06]: "moq-lite-06-wip",
|
|
27
159
|
};
|
|
28
160
|
export function versionName(v) {
|
|
29
161
|
return VERSION_NAMES[v] ?? `unknown(0x${v.toString(16)})`;
|
|
30
162
|
}
|
|
31
|
-
/// Whether this version uses a unidirectional Setup stream (moq-lite-05+).
|
|
32
|
-
export function hasSetupStream(v) {
|
|
33
|
-
return v === Version.DRAFT_05_WIP;
|
|
34
|
-
}
|
|
35
|
-
/// Whether this version uses the moq-lite-05 framing bundle: the Track stream
|
|
36
|
-
/// (TRACK/TRACK_INFO), a SUBSCRIBE_OK trimmed to the resolved start group plus a
|
|
37
|
-
/// distinct SUBSCRIBE_END, and a per-frame timestamp delta.
|
|
38
|
-
export function hasTrackStream(v) {
|
|
39
|
-
return v === Version.DRAFT_05_WIP;
|
|
40
|
-
}
|
|
41
163
|
//# sourceMappingURL=version.js.map
|
package/lite/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/lite/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG;IACtB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/lite/version.ts"],"names":[],"mappings":"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","sourcesContent":["export const Version = {\n\tDRAFT_01: 0xff0dad01,\n\tDRAFT_02: 0xff0dad02,\n\tDRAFT_03: 0xff0dad03,\n\tDRAFT_04: 0xff0dad04,\n\tDRAFT_05: 0xff0dad05,\n\t/// Work-in-progress lite-06, advertised as the preferred WebTransport subprotocol.\n\t/// Adds announce ids: each active ANNOUNCE_BROADCAST implicitly assigns the next\n\t/// ordinal, and ended/restart reference that id instead of repeating the path.\n\tDRAFT_06: 0xff0dad06,\n} as const;\n\nexport type Version = (typeof Version)[keyof typeof Version];\n\n/**\n * Whether the PROBE message carries the RTT field.\n *\n * Added in lite-04. Lite-03 carries the bitrate alone, so a report with only an RTT to\n * give says nothing there and must not be sent.\n */\nexport function hasProbeRtt(version: Version): boolean {\n\t// Explicitly list older versions so future versions default to carrying RTT.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/// Whether the session opens a unidirectional Setup Stream carrying a single SETUP message\n/// (capabilities + optional Path). Added in lite-05; older drafts have no Setup Stream.\nexport function hasSetupStream(version: Version): boolean {\n\t// Explicitly list older versions so future versions default to having the stream.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/// Whether the session may deliver groups over unreliable QUIC datagrams (lite-05 §6.4).\n/// A datagram carries one single-frame group's `subscribe | sequence | timestamp | payload` and is\n/// routed over the existing subscription. Added in lite-05; older versions never send/accept them.\nexport function hasDatagrams(version: Version): boolean {\n\t// Explicitly list older versions so future versions default to having datagrams.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/** Whether announce streams begin with ANNOUNCE_OK and omit the sender's origin from each hop chain. */\nexport function hasAnnounceOk(version: Version): boolean {\n\t// Explicitly list older versions so future versions keep the lite-05+ announce behavior.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/** Whether the version can replace an advertisement in place rather than retracting and\n * re-announcing it. Added in lite-05 as a duplicate ANNOUNCE; lite-06 gave it a message of\n * its own (ANNOUNCE_UPDATE) and made the duplicate a violation. */\nexport function restartSupported(version: Version): boolean {\n\t// Explicitly list older versions so future versions default to supported.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/** Whether announcements carry implicit announce ids: each `active` assigns the next\n * per-stream ordinal, and `ended`/`restart` reference that id instead of repeating the\n * path. Added in lite-06. */\nexport function hasAnnounceId(version: Version): boolean {\n\t// Explicitly list older versions so future versions keep the lite-06+ announce behavior.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\tcase Version.DRAFT_05:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/** Whether ANNOUNCE_REQUEST carries the Exclude Hop field: the subscriber's own\n * origin id, which the publisher uses to skip announces whose hop chain already\n * passed through the subscriber. Present in lite-04 and lite-05 only.\n *\n * The receiver's own reflected-announce check drops those announces anyway (and\n * catches loops of any length, not just the two-hop case), so lite-06 drops the\n * field and keeps the check.\n *\n * Unlike the gates above, this lists the versions that *have* the field: it was\n * removed rather than added, so future versions default to not carrying it. */\nexport function hasExcludeHop(version: Version): boolean {\n\tswitch (version) {\n\t\tcase Version.DRAFT_04:\n\t\tcase Version.DRAFT_05:\n\t\t\treturn true;\n\t\tdefault:\n\t\t\treturn false;\n\t}\n}\n\n/** Whether announcements carry a route cost varint alongside the hop chain: the\n * marginal cost of pulling the broadcast via this route, accumulated per link.\n * Added in lite-06. Older versions carry nothing, so a received route stays at\n * zero and routing falls back to the hop-count tie-break. */\nexport function hasRouteCost(version: Version): boolean {\n\t// Explicitly list older versions so future versions keep the lite-06+ behavior.\n\tswitch (version) {\n\t\tcase Version.DRAFT_01:\n\t\tcase Version.DRAFT_02:\n\t\tcase Version.DRAFT_03:\n\t\tcase Version.DRAFT_04:\n\t\tcase Version.DRAFT_05:\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n\n/// The WebTransport subprotocol identifier for moq-lite.\n/// Version negotiation still happens via SETUP when this is used.\nexport const ALPN = \"moql\";\n\n/// The ALPN string for Draft03, which uses ALPN-based version negotiation.\nexport const ALPN_03 = \"moq-lite-03\";\n\n/// The ALPN string for Draft04, which uses ALPN-based version negotiation.\nexport const ALPN_04 = \"moq-lite-04\";\n\n/// The ALPN string for Draft05, which uses ALPN-based version negotiation.\nexport const ALPN_05 = \"moq-lite-05\";\n\n/// The ALPN string for the work-in-progress Draft06. It is NOT in the default\n/// WebTransport `protocols` list, so lite-06 is never advertised or negotiated by\n/// default; a peer only reaches it when both sides explicitly offer this ALPN.\nexport const ALPN_06_WIP = \"moq-lite-06-wip\";\n\nconst VERSION_NAMES: Record<number, string> = {\n\t[Version.DRAFT_01]: \"moq-lite-01\",\n\t[Version.DRAFT_02]: \"moq-lite-02\",\n\t[Version.DRAFT_03]: \"moq-lite-03\",\n\t[Version.DRAFT_04]: \"moq-lite-04\",\n\t[Version.DRAFT_05]: \"moq-lite-05\",\n\t[Version.DRAFT_06]: \"moq-lite-06-wip\",\n};\n\nexport function versionName(v: Version): string {\n\treturn VERSION_NAMES[v] ?? `unknown(0x${v.toString(16)})`;\n}\n"]}
|
package/mock.d.ts
CHANGED
|
@@ -3,14 +3,64 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Creates paired client/server transports connected via TransformStreams.
|
|
5
5
|
*/
|
|
6
|
+
import type { TransportStats } from "./connection/stats";
|
|
7
|
+
import type { SendStream } from "./stream";
|
|
8
|
+
/** A fake {@link WebTransport} backed by TransformStreams, paired with a peer. */
|
|
9
|
+
export declare class MockTransport implements WebTransport {
|
|
10
|
+
#private;
|
|
11
|
+
readonly protocol: string;
|
|
12
|
+
readonly ready: Promise<undefined>;
|
|
13
|
+
readonly closed: Promise<WebTransportCloseInfo>;
|
|
14
|
+
readonly incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalStream>;
|
|
15
|
+
readonly incomingUnidirectionalStreams: ReadableStream<ReadableStream<Uint8Array>>;
|
|
16
|
+
readonly datagrams: WebTransportDatagramDuplexStream;
|
|
17
|
+
readonly congestionControl: WebTransportCongestionControl;
|
|
18
|
+
readonly reliability: string;
|
|
19
|
+
/**
|
|
20
|
+
* Every outgoing stream this transport opened, in call order, split by stream kind. Each
|
|
21
|
+
* carries a live {@link SendStream.sendOrder} (set when it opened, and by any later
|
|
22
|
+
* re-rank), so a test can assert how the wire layer prioritized it. The mock always
|
|
23
|
+
* delivers in creation order, so nothing else observes it.
|
|
24
|
+
*/
|
|
25
|
+
readonly sendStreams: {
|
|
26
|
+
uni: SendStream[];
|
|
27
|
+
bidi: SendStream[];
|
|
28
|
+
};
|
|
29
|
+
constructor(protocol: string, datagramsEnabled?: boolean, datagramWritable?: DatagramWritableApi, datagramReadable?: boolean);
|
|
30
|
+
setPeer(peer: MockTransport): void;
|
|
31
|
+
createBidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WebTransportBidirectionalStream>;
|
|
32
|
+
createUnidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WritableStream<Uint8Array>>;
|
|
33
|
+
close(_closeInfo?: WebTransportCloseInfo): void;
|
|
34
|
+
/** The snapshot {@link getStats} resolves with (default empty). */
|
|
35
|
+
stats: TransportStats;
|
|
36
|
+
getStats(): Promise<TransportStats>;
|
|
37
|
+
}
|
|
38
|
+
type DatagramWritableApi = "writable" | "createWritable" | "none";
|
|
39
|
+
/** Options for {@link createMockTransportPair}. */
|
|
40
|
+
export interface MockTransportOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Whether the paired transports carry QUIC datagrams (default true). Set false to
|
|
43
|
+
* simulate a transport that reports `maxDatagramSize` 0 (e.g. a qmux/WebSocket
|
|
44
|
+
* session), so the wire layer must fall back to not sending datagrams.
|
|
45
|
+
*/
|
|
46
|
+
datagrams?: boolean;
|
|
47
|
+
/** Which outgoing datagram API shape the mock exposes. */
|
|
48
|
+
datagramWritable?: DatagramWritableApi;
|
|
49
|
+
/** Whether the incoming datagram readable stream is exposed. */
|
|
50
|
+
datagramReadable?: boolean;
|
|
51
|
+
/** The snapshot `getStats()` resolves with on both transports (default empty). */
|
|
52
|
+
stats?: TransportStats;
|
|
53
|
+
}
|
|
6
54
|
/**
|
|
7
55
|
* Creates a pair of connected MockTransport instances.
|
|
8
56
|
*
|
|
9
57
|
* @param protocol - The WebTransport protocol identifier (e.g. "moqt-17", "moql", "")
|
|
58
|
+
* @param options - Optional behavior toggles for datagram availability
|
|
10
59
|
* @returns An object containing `client` and `server` transports
|
|
11
60
|
*/
|
|
12
|
-
export declare function createMockTransportPair(protocol?: string): {
|
|
13
|
-
client:
|
|
14
|
-
server:
|
|
61
|
+
export declare function createMockTransportPair(protocol?: string, options?: MockTransportOptions): {
|
|
62
|
+
client: MockTransport;
|
|
63
|
+
server: MockTransport;
|
|
15
64
|
};
|
|
65
|
+
export {};
|
|
16
66
|
//# sourceMappingURL=mock.d.ts.map
|
package/mock.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAqB9C,kFAAkF;AAClF,qBAAa,aAAc,YAAW,YAAY;;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAEhD,QAAQ,CAAC,4BAA4B,EAAE,cAAc,CAAC,+BAA+B,CAAC,CAAC;IACvF,QAAQ,CAAC,6BAA6B,EAAE,cAAc,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC;IAEnF,QAAQ,CAAC,SAAS,EAAE,gCAAgC,CAAC;IACrD,QAAQ,CAAC,iBAAiB,EAAE,6BAA6B,CAAC;IAC1D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE;QAAE,GAAG,EAAE,UAAU,EAAE,CAAC;QAAC,IAAI,EAAE,UAAU,EAAE,CAAA;KAAE,CAAyB;IAYxF,YACC,QAAQ,EAAE,MAAM,EAChB,gBAAgB,UAAO,EACvB,gBAAgB,GAAE,mBAAgC,EAClD,gBAAgB,UAAO,EAoFvB;IAED,OAAO,CAAC,IAAI,EAAE,aAAa,QAE1B;IAEK,yBAAyB,CAAC,OAAO,CAAC,EAAE,6BAA6B,GAAG,OAAO,CAAC,+BAA+B,CAAC,CA2BjH;IAEK,0BAA0B,CAAC,OAAO,CAAC,EAAE,6BAA6B,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAiB7G;IAeD,KAAK,CAAC,UAAU,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAwC9C;IAED,mEAAmE;IACnE,KAAK,EAAE,cAAc,CAAM;IAErB,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC,CAExC;CACD;AAED,KAAK,mBAAmB,GAAG,UAAU,GAAG,gBAAgB,GAAG,MAAM,CAAC;AAElE,mDAAmD;AACnD,MAAM,WAAW,oBAAoB;IACpC;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,mBAAmB,CAAC;IAEvC,gEAAgE;IAChE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,kFAAkF;IAClF,KAAK,CAAC,EAAE,cAAc,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACtC,QAAQ,SAAK,EACb,OAAO,CAAC,EAAE,oBAAoB,GAC5B;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAYlD"}
|
package/mock.js
CHANGED
|
@@ -17,7 +17,8 @@ function newStream() {
|
|
|
17
17
|
},
|
|
18
18
|
}, WRITABLE_STRATEGY, READABLE_STRATEGY);
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
/** A fake {@link WebTransport} backed by TransformStreams, paired with a peer. */
|
|
21
|
+
export class MockTransport {
|
|
21
22
|
protocol;
|
|
22
23
|
ready;
|
|
23
24
|
closed;
|
|
@@ -26,12 +27,22 @@ class MockTransport {
|
|
|
26
27
|
datagrams;
|
|
27
28
|
congestionControl;
|
|
28
29
|
reliability;
|
|
30
|
+
/**
|
|
31
|
+
* Every outgoing stream this transport opened, in call order, split by stream kind. Each
|
|
32
|
+
* carries a live {@link SendStream.sendOrder} (set when it opened, and by any later
|
|
33
|
+
* re-rank), so a test can assert how the wire layer prioritized it. The mock always
|
|
34
|
+
* delivers in creation order, so nothing else observes it.
|
|
35
|
+
*/
|
|
36
|
+
sendStreams = { uni: [], bidi: [] };
|
|
29
37
|
#closeResolve;
|
|
30
38
|
#bidiController;
|
|
31
39
|
#uniController;
|
|
40
|
+
// Incoming-datagram controller (only set when datagrams are enabled); the peer's
|
|
41
|
+
// writable enqueues into it.
|
|
42
|
+
#datagramController;
|
|
32
43
|
// Reference to the peer so we can enqueue streams to them
|
|
33
44
|
#peer;
|
|
34
|
-
constructor(protocol) {
|
|
45
|
+
constructor(protocol, datagramsEnabled = true, datagramWritable = "writable", datagramReadable = true) {
|
|
35
46
|
this.protocol = protocol;
|
|
36
47
|
this.ready = Promise.resolve(undefined);
|
|
37
48
|
this.closed = new Promise((resolve) => {
|
|
@@ -49,21 +60,68 @@ class MockTransport {
|
|
|
49
60
|
});
|
|
50
61
|
this.congestionControl = "default";
|
|
51
62
|
this.reliability = "supports-unreliable";
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
if (datagramsEnabled) {
|
|
64
|
+
// A real datagram duplex: writes enqueue into the peer's incoming readable,
|
|
65
|
+
// so a peer pair actually exchanges datagrams (unlike a real qmux Session,
|
|
66
|
+
// whose datagram streams are inert stubs).
|
|
67
|
+
const readable = datagramReadable
|
|
68
|
+
? new ReadableStream({
|
|
69
|
+
start: (controller) => {
|
|
70
|
+
this.#datagramController = controller;
|
|
71
|
+
},
|
|
72
|
+
})
|
|
73
|
+
: undefined;
|
|
74
|
+
const writable = new WritableStream({
|
|
75
|
+
write: (chunk) => {
|
|
76
|
+
const peer = this.#peer;
|
|
77
|
+
if (!peer)
|
|
78
|
+
return;
|
|
79
|
+
const controller = peer.#datagramController;
|
|
80
|
+
if (!controller)
|
|
81
|
+
return;
|
|
82
|
+
try {
|
|
83
|
+
// Copy so the caller's scratch buffer reuse can't corrupt queued data.
|
|
84
|
+
controller.enqueue(new Uint8Array(chunk));
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// Peer closed; drop (datagrams are best-effort).
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
const datagrams = {
|
|
92
|
+
readable,
|
|
93
|
+
incomingHighWaterMark: 0,
|
|
94
|
+
outgoingHighWaterMark: 0,
|
|
95
|
+
incomingMaxAge: null,
|
|
96
|
+
outgoingMaxAge: null,
|
|
97
|
+
maxDatagramSize: 1200,
|
|
98
|
+
};
|
|
99
|
+
if (datagramWritable === "writable") {
|
|
100
|
+
datagrams.writable = writable;
|
|
101
|
+
}
|
|
102
|
+
else if (datagramWritable === "createWritable") {
|
|
103
|
+
datagrams.createWritable = () => writable;
|
|
104
|
+
}
|
|
105
|
+
this.datagrams = datagrams;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
// Simulate a transport that doesn't carry datagrams (maxDatagramSize 0): the
|
|
109
|
+
// wire layer must fall back to not sending, with no group fallback.
|
|
110
|
+
this.datagrams = {
|
|
111
|
+
readable: new ReadableStream(),
|
|
112
|
+
writable: new WritableStream(),
|
|
113
|
+
incomingHighWaterMark: 0,
|
|
114
|
+
outgoingHighWaterMark: 0,
|
|
115
|
+
incomingMaxAge: null,
|
|
116
|
+
outgoingMaxAge: null,
|
|
117
|
+
maxDatagramSize: 0,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
62
120
|
}
|
|
63
121
|
setPeer(peer) {
|
|
64
122
|
this.#peer = peer;
|
|
65
123
|
}
|
|
66
|
-
async createBidirectionalStream(
|
|
124
|
+
async createBidirectionalStream(options) {
|
|
67
125
|
const peer = this.#peer;
|
|
68
126
|
if (!peer)
|
|
69
127
|
throw new Error("no peer");
|
|
@@ -73,7 +131,7 @@ class MockTransport {
|
|
|
73
131
|
// Local side: writes to c2s, reads from s2c
|
|
74
132
|
const local = {
|
|
75
133
|
readable: s2c.readable,
|
|
76
|
-
writable: c2s.writable,
|
|
134
|
+
writable: this.#sendStream(c2s.writable, this.sendStreams.bidi, options),
|
|
77
135
|
};
|
|
78
136
|
// Peer side: writes to s2c, reads from c2s
|
|
79
137
|
const remote = {
|
|
@@ -88,18 +146,29 @@ class MockTransport {
|
|
|
88
146
|
}
|
|
89
147
|
return local;
|
|
90
148
|
}
|
|
91
|
-
async createUnidirectionalStream(
|
|
149
|
+
async createUnidirectionalStream(options) {
|
|
92
150
|
const peer = this.#peer;
|
|
93
151
|
if (!peer)
|
|
94
152
|
throw new Error("no peer");
|
|
95
153
|
const c2s = newStream();
|
|
154
|
+
// Record before handing the peer its end, so a peer that waits for the stream to arrive
|
|
155
|
+
// always finds it here.
|
|
156
|
+
const stream = this.#sendStream(c2s.writable, this.sendStreams.uni, options);
|
|
96
157
|
try {
|
|
97
158
|
peer.#uniController.enqueue(c2s.readable);
|
|
98
159
|
}
|
|
99
160
|
catch {
|
|
100
161
|
// Peer closed
|
|
101
162
|
}
|
|
102
|
-
return
|
|
163
|
+
return stream;
|
|
164
|
+
}
|
|
165
|
+
// Give a writable the send order it opened with and record it, so a test sees both that
|
|
166
|
+
// order and any later re-rank (which assigns the same property, as on a real send stream).
|
|
167
|
+
#sendStream(writable, log, options) {
|
|
168
|
+
const stream = writable;
|
|
169
|
+
stream.sendOrder = options?.sendOrder;
|
|
170
|
+
log.push(stream);
|
|
171
|
+
return stream;
|
|
103
172
|
}
|
|
104
173
|
close(_closeInfo) {
|
|
105
174
|
const info = _closeInfo ?? { closeCode: 0, reason: "" };
|
|
@@ -116,6 +185,12 @@ class MockTransport {
|
|
|
116
185
|
catch {
|
|
117
186
|
// Already closed
|
|
118
187
|
}
|
|
188
|
+
try {
|
|
189
|
+
this.#datagramController?.close();
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
// Already closed
|
|
193
|
+
}
|
|
119
194
|
// Also close peer's incoming streams
|
|
120
195
|
if (this.#peer) {
|
|
121
196
|
try {
|
|
@@ -130,23 +205,37 @@ class MockTransport {
|
|
|
130
205
|
catch {
|
|
131
206
|
// Already closed
|
|
132
207
|
}
|
|
208
|
+
try {
|
|
209
|
+
this.#peer.#datagramController?.close();
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
// Already closed
|
|
213
|
+
}
|
|
133
214
|
this.#peer.#closeResolve(info);
|
|
134
215
|
}
|
|
135
216
|
}
|
|
136
|
-
|
|
217
|
+
/** The snapshot {@link getStats} resolves with (default empty). */
|
|
218
|
+
stats = {};
|
|
137
219
|
async getStats() {
|
|
138
|
-
return
|
|
220
|
+
return this.stats;
|
|
139
221
|
}
|
|
140
222
|
}
|
|
141
223
|
/**
|
|
142
224
|
* Creates a pair of connected MockTransport instances.
|
|
143
225
|
*
|
|
144
226
|
* @param protocol - The WebTransport protocol identifier (e.g. "moqt-17", "moql", "")
|
|
227
|
+
* @param options - Optional behavior toggles for datagram availability
|
|
145
228
|
* @returns An object containing `client` and `server` transports
|
|
146
229
|
*/
|
|
147
|
-
export function createMockTransportPair(protocol = "") {
|
|
148
|
-
const
|
|
149
|
-
const
|
|
230
|
+
export function createMockTransportPair(protocol = "", options) {
|
|
231
|
+
const datagrams = options?.datagrams ?? true;
|
|
232
|
+
const client = new MockTransport(protocol, datagrams, options?.datagramWritable, options?.datagramReadable);
|
|
233
|
+
const server = new MockTransport(protocol, datagrams, options?.datagramWritable, options?.datagramReadable);
|
|
234
|
+
if (options?.stats) {
|
|
235
|
+
// Copy per side so a test advancing one transport's counters doesn't move the other's.
|
|
236
|
+
client.stats = { ...options.stats };
|
|
237
|
+
server.stats = { ...options.stats };
|
|
238
|
+
}
|
|
150
239
|
client.setPeer(server);
|
|
151
240
|
server.setPeer(client);
|
|
152
241
|
return { client, server };
|
package/mock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mock WebTransport implementation for in-process testing.\n *\n * Creates paired client/server transports connected via TransformStreams.\n */\n\n// High watermark to prevent writes from blocking on backpressure.\n// Real WebTransport has kernel buffers; we simulate this with a large queue.\nconst WRITABLE_STRATEGY: QueuingStrategy<Uint8Array> = { highWaterMark: 256 };\nconst READABLE_STRATEGY: QueuingStrategy<Uint8Array> = { highWaterMark: 256 };\n\nfunction newStream(): TransformStream<Uint8Array, Uint8Array> {\n\treturn new TransformStream(\n\t\t{\n\t\t\t// Copy each chunk to simulate real WebTransport's kernel-boundary copy.\n\t\t\t// Without this, Writer's scratch buffer reuse corrupts queued data.\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tcontroller.enqueue(new Uint8Array(chunk));\n\t\t\t},\n\t\t},\n\t\tWRITABLE_STRATEGY,\n\t\tREADABLE_STRATEGY,\n\t);\n}\n\nclass MockTransport implements WebTransport {\n\treadonly protocol: string;\n\treadonly ready: Promise<undefined>;\n\treadonly closed: Promise<WebTransportCloseInfo>;\n\n\treadonly incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalStream>;\n\treadonly incomingUnidirectionalStreams: ReadableStream<ReadableStream<Uint8Array>>;\n\n\treadonly datagrams: WebTransportDatagramDuplexStream;\n\treadonly congestionControl: WebTransportCongestionControl;\n\treadonly reliability: string;\n\n\t#closeResolve!: (info: WebTransportCloseInfo) => void;\n\t#bidiController!: ReadableStreamDefaultController<WebTransportBidirectionalStream>;\n\t#uniController!: ReadableStreamDefaultController<ReadableStream<Uint8Array>>;\n\n\t// Reference to the peer so we can enqueue streams to them\n\t#peer?: MockTransport;\n\n\tconstructor(protocol: string) {\n\t\tthis.protocol = protocol;\n\t\tthis.ready = Promise.resolve(undefined);\n\t\tthis.closed = new Promise((resolve) => {\n\t\t\tthis.#closeResolve = resolve;\n\t\t});\n\n\t\tthis.incomingBidirectionalStreams = new ReadableStream({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis.#bidiController = controller;\n\t\t\t},\n\t\t});\n\n\t\tthis.incomingUnidirectionalStreams = new ReadableStream({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis.#uniController = controller;\n\t\t\t},\n\t\t});\n\n\t\tthis.congestionControl = \"default\";\n\t\tthis.reliability = \"supports-unreliable\";\n\n\t\t// Stub datagrams\n\t\tthis.datagrams = {\n\t\t\treadable: new ReadableStream(),\n\t\t\twritable: new WritableStream(),\n\t\t\tincomingHighWaterMark: 0,\n\t\t\toutgoingHighWaterMark: 0,\n\t\t\tincomingMaxAge: null,\n\t\t\toutgoingMaxAge: null,\n\t\t\tmaxDatagramSize: 0,\n\t\t};\n\t}\n\n\tsetPeer(peer: MockTransport) {\n\t\tthis.#peer = peer;\n\t}\n\n\tasync createBidirectionalStream(\n\t\t_options?: WebTransportSendStreamOptions,\n\t): Promise<WebTransportBidirectionalStream> {\n\t\tconst peer = this.#peer;\n\t\tif (!peer) throw new Error(\"no peer\");\n\n\t\t// Create two TransformStreams for the two directions\n\t\tconst c2s = newStream();\n\t\tconst s2c = newStream();\n\n\t\t// Local side: writes to c2s, reads from s2c\n\t\tconst local = {\n\t\t\treadable: s2c.readable,\n\t\t\twritable: c2s.writable,\n\t\t} as WebTransportBidirectionalStream;\n\n\t\t// Peer side: writes to s2c, reads from c2s\n\t\tconst remote = {\n\t\t\treadable: c2s.readable,\n\t\t\twritable: s2c.writable,\n\t\t} as WebTransportBidirectionalStream;\n\n\t\ttry {\n\t\t\tpeer.#bidiController.enqueue(remote);\n\t\t} catch {\n\t\t\t// Peer closed\n\t\t}\n\n\t\treturn local;\n\t}\n\n\tasync createUnidirectionalStream(_options?: WebTransportSendStreamOptions): Promise<WritableStream<Uint8Array>> {\n\t\tconst peer = this.#peer;\n\t\tif (!peer) throw new Error(\"no peer\");\n\n\t\tconst c2s = newStream();\n\n\t\ttry {\n\t\t\tpeer.#uniController.enqueue(c2s.readable);\n\t\t} catch {\n\t\t\t// Peer closed\n\t\t}\n\n\t\treturn c2s.writable;\n\t}\n\n\tclose(_closeInfo?: WebTransportCloseInfo): void {\n\t\tconst info = _closeInfo ?? { closeCode: 0, reason: \"\" };\n\t\tthis.#closeResolve(info);\n\n\t\ttry {\n\t\t\tthis.#bidiController.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\t\ttry {\n\t\t\tthis.#uniController.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\n\t\t// Also close peer's incoming streams\n\t\tif (this.#peer) {\n\t\t\ttry {\n\t\t\t\tthis.#peer.#bidiController.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.#peer.#uniController.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t\tthis.#peer.#closeResolve(info);\n\t\t}\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: WebTransportStats type not available in all TS libs\n\tasync getStats(): Promise<any> {\n\t\treturn {};\n\t}\n}\n\n/**\n * Creates a pair of connected MockTransport instances.\n *\n * @param protocol - The WebTransport protocol identifier (e.g. \"moqt-17\", \"moql\", \"\")\n * @returns An object containing `client` and `server` transports\n */\nexport function createMockTransportPair(protocol = \"\"): { client: WebTransport; server: WebTransport } {\n\tconst client = new MockTransport(protocol);\n\tconst server = new MockTransport(protocol);\n\tclient.setPeer(server);\n\tserver.setPeer(client);\n\treturn { client, server };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mock WebTransport implementation for in-process testing.\n *\n * Creates paired client/server transports connected via TransformStreams.\n */\n\nimport type { TransportStats } from \"./connection/stats.ts\";\nimport type { SendStream } from \"./stream.ts\";\n\n// High watermark to prevent writes from blocking on backpressure.\n// Real WebTransport has kernel buffers; we simulate this with a large queue.\nconst WRITABLE_STRATEGY: QueuingStrategy<Uint8Array> = { highWaterMark: 256 };\nconst READABLE_STRATEGY: QueuingStrategy<Uint8Array> = { highWaterMark: 256 };\n\nfunction newStream(): TransformStream<Uint8Array, Uint8Array> {\n\treturn new TransformStream(\n\t\t{\n\t\t\t// Copy each chunk to simulate real WebTransport's kernel-boundary copy.\n\t\t\t// Without this, Writer's scratch buffer reuse corrupts queued data.\n\t\t\ttransform(chunk, controller) {\n\t\t\t\tcontroller.enqueue(new Uint8Array(chunk));\n\t\t\t},\n\t\t},\n\t\tWRITABLE_STRATEGY,\n\t\tREADABLE_STRATEGY,\n\t);\n}\n\n/** A fake {@link WebTransport} backed by TransformStreams, paired with a peer. */\nexport class MockTransport implements WebTransport {\n\treadonly protocol: string;\n\treadonly ready: Promise<undefined>;\n\treadonly closed: Promise<WebTransportCloseInfo>;\n\n\treadonly incomingBidirectionalStreams: ReadableStream<WebTransportBidirectionalStream>;\n\treadonly incomingUnidirectionalStreams: ReadableStream<ReadableStream<Uint8Array>>;\n\n\treadonly datagrams: WebTransportDatagramDuplexStream;\n\treadonly congestionControl: WebTransportCongestionControl;\n\treadonly reliability: string;\n\n\t/**\n\t * Every outgoing stream this transport opened, in call order, split by stream kind. Each\n\t * carries a live {@link SendStream.sendOrder} (set when it opened, and by any later\n\t * re-rank), so a test can assert how the wire layer prioritized it. The mock always\n\t * delivers in creation order, so nothing else observes it.\n\t */\n\treadonly sendStreams: { uni: SendStream[]; bidi: SendStream[] } = { uni: [], bidi: [] };\n\n\t#closeResolve!: (info: WebTransportCloseInfo) => void;\n\t#bidiController!: ReadableStreamDefaultController<WebTransportBidirectionalStream>;\n\t#uniController!: ReadableStreamDefaultController<ReadableStream<Uint8Array>>;\n\t// Incoming-datagram controller (only set when datagrams are enabled); the peer's\n\t// writable enqueues into it.\n\t#datagramController?: ReadableStreamDefaultController<Uint8Array>;\n\n\t// Reference to the peer so we can enqueue streams to them\n\t#peer?: MockTransport;\n\n\tconstructor(\n\t\tprotocol: string,\n\t\tdatagramsEnabled = true,\n\t\tdatagramWritable: DatagramWritableApi = \"writable\",\n\t\tdatagramReadable = true,\n\t) {\n\t\tthis.protocol = protocol;\n\t\tthis.ready = Promise.resolve(undefined);\n\t\tthis.closed = new Promise((resolve) => {\n\t\t\tthis.#closeResolve = resolve;\n\t\t});\n\n\t\tthis.incomingBidirectionalStreams = new ReadableStream({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis.#bidiController = controller;\n\t\t\t},\n\t\t});\n\n\t\tthis.incomingUnidirectionalStreams = new ReadableStream({\n\t\t\tstart: (controller) => {\n\t\t\t\tthis.#uniController = controller;\n\t\t\t},\n\t\t});\n\n\t\tthis.congestionControl = \"default\";\n\t\tthis.reliability = \"supports-unreliable\";\n\n\t\tif (datagramsEnabled) {\n\t\t\t// A real datagram duplex: writes enqueue into the peer's incoming readable,\n\t\t\t// so a peer pair actually exchanges datagrams (unlike a real qmux Session,\n\t\t\t// whose datagram streams are inert stubs).\n\t\t\tconst readable = datagramReadable\n\t\t\t\t? new ReadableStream<Uint8Array>({\n\t\t\t\t\t\tstart: (controller) => {\n\t\t\t\t\t\t\tthis.#datagramController = controller;\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t: undefined;\n\t\t\tconst writable = new WritableStream<Uint8Array>({\n\t\t\t\twrite: (chunk) => {\n\t\t\t\t\tconst peer = this.#peer;\n\t\t\t\t\tif (!peer) return;\n\t\t\t\t\tconst controller = peer.#datagramController;\n\t\t\t\t\tif (!controller) return;\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Copy so the caller's scratch buffer reuse can't corrupt queued data.\n\t\t\t\t\t\tcontroller.enqueue(new Uint8Array(chunk));\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Peer closed; drop (datagrams are best-effort).\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst datagrams: {\n\t\t\t\treadable?: ReadableStream<Uint8Array>;\n\t\t\t\twritable?: WritableStream<Uint8Array>;\n\t\t\t\tmaxDatagramSize: number;\n\t\t\t\tincomingHighWaterMark: number;\n\t\t\t\toutgoingHighWaterMark: number;\n\t\t\t\tincomingMaxAge: null;\n\t\t\t\toutgoingMaxAge: null;\n\t\t\t\tcreateWritable?: () => WritableStream<Uint8Array>;\n\t\t\t} = {\n\t\t\t\treadable,\n\t\t\t\tincomingHighWaterMark: 0,\n\t\t\t\toutgoingHighWaterMark: 0,\n\t\t\t\tincomingMaxAge: null,\n\t\t\t\toutgoingMaxAge: null,\n\t\t\t\tmaxDatagramSize: 1200,\n\t\t\t};\n\t\t\tif (datagramWritable === \"writable\") {\n\t\t\t\tdatagrams.writable = writable;\n\t\t\t} else if (datagramWritable === \"createWritable\") {\n\t\t\t\tdatagrams.createWritable = () => writable;\n\t\t\t}\n\t\t\tthis.datagrams = datagrams as WebTransportDatagramDuplexStream;\n\t\t} else {\n\t\t\t// Simulate a transport that doesn't carry datagrams (maxDatagramSize 0): the\n\t\t\t// wire layer must fall back to not sending, with no group fallback.\n\t\t\tthis.datagrams = {\n\t\t\t\treadable: new ReadableStream(),\n\t\t\t\twritable: new WritableStream(),\n\t\t\t\tincomingHighWaterMark: 0,\n\t\t\t\toutgoingHighWaterMark: 0,\n\t\t\t\tincomingMaxAge: null,\n\t\t\t\toutgoingMaxAge: null,\n\t\t\t\tmaxDatagramSize: 0,\n\t\t\t};\n\t\t}\n\t}\n\n\tsetPeer(peer: MockTransport) {\n\t\tthis.#peer = peer;\n\t}\n\n\tasync createBidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WebTransportBidirectionalStream> {\n\t\tconst peer = this.#peer;\n\t\tif (!peer) throw new Error(\"no peer\");\n\n\t\t// Create two TransformStreams for the two directions\n\t\tconst c2s = newStream();\n\t\tconst s2c = newStream();\n\n\t\t// Local side: writes to c2s, reads from s2c\n\t\tconst local = {\n\t\t\treadable: s2c.readable,\n\t\t\twritable: this.#sendStream(c2s.writable, this.sendStreams.bidi, options),\n\t\t} as WebTransportBidirectionalStream;\n\n\t\t// Peer side: writes to s2c, reads from c2s\n\t\tconst remote = {\n\t\t\treadable: c2s.readable,\n\t\t\twritable: s2c.writable,\n\t\t} as WebTransportBidirectionalStream;\n\n\t\ttry {\n\t\t\tpeer.#bidiController.enqueue(remote);\n\t\t} catch {\n\t\t\t// Peer closed\n\t\t}\n\n\t\treturn local;\n\t}\n\n\tasync createUnidirectionalStream(options?: WebTransportSendStreamOptions): Promise<WritableStream<Uint8Array>> {\n\t\tconst peer = this.#peer;\n\t\tif (!peer) throw new Error(\"no peer\");\n\n\t\tconst c2s = newStream();\n\n\t\t// Record before handing the peer its end, so a peer that waits for the stream to arrive\n\t\t// always finds it here.\n\t\tconst stream = this.#sendStream(c2s.writable, this.sendStreams.uni, options);\n\n\t\ttry {\n\t\t\tpeer.#uniController.enqueue(c2s.readable);\n\t\t} catch {\n\t\t\t// Peer closed\n\t\t}\n\n\t\treturn stream;\n\t}\n\n\t// Give a writable the send order it opened with and record it, so a test sees both that\n\t// order and any later re-rank (which assigns the same property, as on a real send stream).\n\t#sendStream(\n\t\twritable: WritableStream<Uint8Array>,\n\t\tlog: SendStream[],\n\t\toptions?: WebTransportSendStreamOptions,\n\t): SendStream {\n\t\tconst stream = writable as SendStream;\n\t\tstream.sendOrder = options?.sendOrder;\n\t\tlog.push(stream);\n\t\treturn stream;\n\t}\n\n\tclose(_closeInfo?: WebTransportCloseInfo): void {\n\t\tconst info = _closeInfo ?? { closeCode: 0, reason: \"\" };\n\t\tthis.#closeResolve(info);\n\n\t\ttry {\n\t\t\tthis.#bidiController.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\t\ttry {\n\t\t\tthis.#uniController.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\n\t\ttry {\n\t\t\tthis.#datagramController?.close();\n\t\t} catch {\n\t\t\t// Already closed\n\t\t}\n\n\t\t// Also close peer's incoming streams\n\t\tif (this.#peer) {\n\t\t\ttry {\n\t\t\t\tthis.#peer.#bidiController.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.#peer.#uniController.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tthis.#peer.#datagramController?.close();\n\t\t\t} catch {\n\t\t\t\t// Already closed\n\t\t\t}\n\t\t\tthis.#peer.#closeResolve(info);\n\t\t}\n\t}\n\n\t/** The snapshot {@link getStats} resolves with (default empty). */\n\tstats: TransportStats = {};\n\n\tasync getStats(): Promise<TransportStats> {\n\t\treturn this.stats;\n\t}\n}\n\ntype DatagramWritableApi = \"writable\" | \"createWritable\" | \"none\";\n\n/** Options for {@link createMockTransportPair}. */\nexport interface MockTransportOptions {\n\t/**\n\t * Whether the paired transports carry QUIC datagrams (default true). Set false to\n\t * simulate a transport that reports `maxDatagramSize` 0 (e.g. a qmux/WebSocket\n\t * session), so the wire layer must fall back to not sending datagrams.\n\t */\n\tdatagrams?: boolean;\n\n\t/** Which outgoing datagram API shape the mock exposes. */\n\tdatagramWritable?: DatagramWritableApi;\n\n\t/** Whether the incoming datagram readable stream is exposed. */\n\tdatagramReadable?: boolean;\n\n\t/** The snapshot `getStats()` resolves with on both transports (default empty). */\n\tstats?: TransportStats;\n}\n\n/**\n * Creates a pair of connected MockTransport instances.\n *\n * @param protocol - The WebTransport protocol identifier (e.g. \"moqt-17\", \"moql\", \"\")\n * @param options - Optional behavior toggles for datagram availability\n * @returns An object containing `client` and `server` transports\n */\nexport function createMockTransportPair(\n\tprotocol = \"\",\n\toptions?: MockTransportOptions,\n): { client: MockTransport; server: MockTransport } {\n\tconst datagrams = options?.datagrams ?? true;\n\tconst client = new MockTransport(protocol, datagrams, options?.datagramWritable, options?.datagramReadable);\n\tconst server = new MockTransport(protocol, datagrams, options?.datagramWritable, options?.datagramReadable);\n\tif (options?.stats) {\n\t\t// Copy per side so a test advancing one transport's counters doesn't move the other's.\n\t\tclient.stats = { ...options.stats };\n\t\tserver.stats = { ...options.stats };\n\t}\n\tclient.setPeer(server);\n\tserver.setPeer(client);\n\treturn { client, server };\n}\n"]}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Endpoint identity within a hop chain, shared by both wire protocols.
|
|
3
|
+
*
|
|
4
|
+
* moq-lite carries these natively on every announcement; moq-transport carries them
|
|
5
|
+
* via the MoQ Cluster extension (see `ietf/cluster.ts`). Mirrors `Origin` in
|
|
6
|
+
* `rs/moq-net`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import * as z from "@zod/mini";
|
|
2
11
|
/**
|
|
3
12
|
* A relay origin id, encoded as a 62-bit varint on the wire.
|
|
4
13
|
*
|
|
@@ -9,6 +18,21 @@ import * as z from "zod/mini";
|
|
|
9
18
|
*/
|
|
10
19
|
export declare const OriginSchema: z.core.$ZodBranded<z.ZodMiniBigInt<bigint>, "Origin", "out">;
|
|
11
20
|
export type Origin = z.infer<typeof OriginSchema>;
|
|
21
|
+
/**
|
|
22
|
+
* The reserved id 0, meaning "no identity".
|
|
23
|
+
*
|
|
24
|
+
* It stands in for an endpoint that never declared one, and any number of endpoints can
|
|
25
|
+
* be 0, so it identifies nothing: it is never a loop, never a publisher two chains have
|
|
26
|
+
* in common, and never excluded from an advertisement.
|
|
27
|
+
*/
|
|
28
|
+
export declare const UNKNOWN_ORIGIN: Origin;
|
|
29
|
+
/**
|
|
30
|
+
* Maximum length of a hop chain. Must match `MAX_HOPS` in Rust's `model/origin.rs`.
|
|
31
|
+
*
|
|
32
|
+
* Broadcasts with longer chains are rejected, which bounds loop detection and rejects
|
|
33
|
+
* pathological announcements across clusters with unbounded forwarding.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MAX_HOPS = 32;
|
|
12
36
|
/**
|
|
13
37
|
* Generate a fresh origin with a random non-zero id.
|
|
14
38
|
*
|
package/origin.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin.d.ts","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAE/B;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,8DAGR,CAAC;AAElB,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,EAAE,MAA+B,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,KAAK,CAAC;AAE3B;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAOrC"}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
/* @ts-self-types="./origin.d.ts" */
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Endpoint identity within a hop chain, shared by both wire protocols.
|
|
4
|
+
*
|
|
5
|
+
* moq-lite carries these natively on every announcement; moq-transport carries them
|
|
6
|
+
* via the MoQ Cluster extension (see `ietf/cluster.ts`). Mirrors `Origin` in
|
|
7
|
+
* `rs/moq-net`.
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import * as z from "@zod/mini";
|
|
3
12
|
/**
|
|
4
13
|
* A relay origin id, encoded as a 62-bit varint on the wire.
|
|
5
14
|
*
|
|
@@ -12,6 +21,21 @@ export const OriginSchema = z
|
|
|
12
21
|
.bigint()
|
|
13
22
|
.check(z.refine((value) => value >= 0n && value < 1n << 62n, "Origin must be a non-negative 62-bit integer"))
|
|
14
23
|
.brand("Origin");
|
|
24
|
+
/**
|
|
25
|
+
* The reserved id 0, meaning "no identity".
|
|
26
|
+
*
|
|
27
|
+
* It stands in for an endpoint that never declared one, and any number of endpoints can
|
|
28
|
+
* be 0, so it identifies nothing: it is never a loop, never a publisher two chains have
|
|
29
|
+
* in common, and never excluded from an advertisement.
|
|
30
|
+
*/
|
|
31
|
+
export const UNKNOWN_ORIGIN = OriginSchema.parse(0n);
|
|
32
|
+
/**
|
|
33
|
+
* Maximum length of a hop chain. Must match `MAX_HOPS` in Rust's `model/origin.rs`.
|
|
34
|
+
*
|
|
35
|
+
* Broadcasts with longer chains are rejected, which bounds loop detection and rejects
|
|
36
|
+
* pathological announcements across clusters with unbounded forwarding.
|
|
37
|
+
*/
|
|
38
|
+
export const MAX_HOPS = 32;
|
|
15
39
|
/**
|
|
16
40
|
* Generate a fresh origin with a random non-zero id.
|
|
17
41
|
*
|
package/origin.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"origin.js","sourceRoot":"","sources":["../src/origin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,CAAC,MAAM,WAAW,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC;KAC3B,MAAM,EAAE;KACR,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI,GAAG,EAAE,8CAA8C,CAAC,CAAC;KAC5G,KAAK,CAAC,QAAQ,CAAC,CAAC;AAIlB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAW,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,CAAC;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY;IAC3B,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,mBAAmB;IACnB,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,iBAAoB,CAAC;IAC1C,yDAAyD;IACzD,OAAO,YAAY,CAAC,KAAK,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAClD,CAAC","sourcesContent":["/**\n * Endpoint identity within a hop chain, shared by both wire protocols.\n *\n * moq-lite carries these natively on every announcement; moq-transport carries them\n * via the MoQ Cluster extension (see `ietf/cluster.ts`). Mirrors `Origin` in\n * `rs/moq-net`.\n *\n * @module\n */\nimport * as z from \"@zod/mini\";\n\n/**\n * A relay origin id, encoded as a 62-bit varint on the wire.\n *\n * The {@link OriginSchema} validates any incoming value and brands it so the\n * type system enforces \"only validated origins flow into hop lists.\" Internal\n * code that synthesizes an id (e.g. {@link randomOrigin}) uses\n * `OriginSchema.parse(...)` to produce a branded value from the raw bigint.\n */\nexport const OriginSchema = z\n\t.bigint()\n\t.check(z.refine((value) => value >= 0n && value < 1n << 62n, \"Origin must be a non-negative 62-bit integer\"))\n\t.brand(\"Origin\");\n\nexport type Origin = z.infer<typeof OriginSchema>;\n\n/**\n * The reserved id 0, meaning \"no identity\".\n *\n * It stands in for an endpoint that never declared one, and any number of endpoints can\n * be 0, so it identifies nothing: it is never a loop, never a publisher two chains have\n * in common, and never excluded from an advertisement.\n */\nexport const UNKNOWN_ORIGIN: Origin = OriginSchema.parse(0n);\n\n/**\n * Maximum length of a hop chain. Must match `MAX_HOPS` in Rust's `model/origin.rs`.\n *\n * Broadcasts with longer chains are rejected, which bounds loop detection and rejects\n * pathological announcements across clusters with unbounded forwarding.\n */\nexport const MAX_HOPS = 32;\n\n/**\n * Generate a fresh origin with a random non-zero id.\n *\n * `crypto.getRandomValues` is overkill for best-effort loop detection, but\n * used for slightly better distribution than `Math.random` at negligible cost.\n *\n * TEMPORARY: the wire format allows 62 bits, but older `@moq/lite` JS clients\n * decode `AnnounceInterest.exclude_hop` as a u53 (number) and throw on anything\n * > 2^53-1. To keep those clients alive against fresh peers, we cap the random\n * id at 53 bits. Restore to 62 bits once the u62 fix has propagated to deployed\n * bundles. Mirrors `Origin::random` in rs/moq-net.\n */\nexport function randomOrigin(): Origin {\n\tconst buf = new BigUint64Array(1);\n\tcrypto.getRandomValues(buf);\n\t// Mask to 53 bits.\n\tconst raw = buf[0] & 0x1f_ffff_ffff_ffffn;\n\t// Guard against the (astronomically unlikely) zero draw.\n\treturn OriginSchema.parse(raw === 0n ? 1n : raw);\n}\n"]}
|