@blockcast/mmt-base 0.4.0 → 0.4.1-main.2e0aa69d293d
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 +3 -2
- package/dist/catalog-fec-source.d.ts +16 -3
- package/dist/catalog-fec-source.d.ts.map +1 -1
- package/dist/catalog-fec-source.js +24 -5
- package/dist/catalog-fec-source.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mmtp.d.ts +28 -11
- package/dist/mmtp.d.ts.map +1 -1
- package/dist/mmtp.js +28 -18
- package/dist/mmtp.js.map +1 -1
- package/dist/multicast-catalog.d.ts +75 -0
- package/dist/multicast-catalog.d.ts.map +1 -0
- package/dist/multicast-catalog.js +318 -0
- package/dist/multicast-catalog.js.map +1 -0
- package/dist/signalling.d.ts +35 -21
- package/dist/signalling.d.ts.map +1 -1
- package/dist/signalling.js +68 -54
- package/dist/signalling.js.map +1 -1
- package/package.json +1 -1
- package/src/catalog-fec-source.ts +24 -5
- package/src/index.ts +1 -0
- package/src/mmtp.ts +60 -26
- package/src/multicast-catalog.ts +350 -0
- package/src/signalling.ts +73 -59
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The draft-ramadan-moq-multicast-01 endpoint and `auth` rules, written once
|
|
3
|
+
* for both sides of the catalog: `validateCmsfMmtpCatalog` in
|
|
4
|
+
* `@blockcast/mmt-container` throws the first issue, and the receivers in
|
|
5
|
+
* `@blockcast/mmt-transport` ignore every endpoint an issue names (all of
|
|
6
|
+
* them when the issue is catalog-level). It lives here because mmt-base is
|
|
7
|
+
* the only package both depend on.
|
|
8
|
+
*
|
|
9
|
+
* Draft: Blockcast/moqcast-draft@fd962fd73d21ed281b60219c11ea61cc9e4e91c4
|
|
10
|
+
* (PR #2 head; normative text equal to 3162ef93), sections 4.1 and 7.2.6.
|
|
11
|
+
*/
|
|
12
|
+
/** Canonical unpadded base64url of exactly 32 octets. */
|
|
13
|
+
export const ED25519_PUBLIC_KEY_BASE64URL = /^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$/;
|
|
14
|
+
const UINT32_MAX = 0xffff_ffff;
|
|
15
|
+
const AUTH_MEMBERS = new Set(["scheme", "version", "sig", "keys", "minEpoch"]);
|
|
16
|
+
const KEY_MEMBERS = new Set(["kid", "publicKey", "firstEpoch"]);
|
|
17
|
+
const ENDPOINT_AUTH_MEMBERS = new Set([
|
|
18
|
+
"manifestPort",
|
|
19
|
+
"streamId",
|
|
20
|
+
"senderAddress",
|
|
21
|
+
"maxAuthDelayMs",
|
|
22
|
+
"manifestTimerMs",
|
|
23
|
+
"manifestTrack",
|
|
24
|
+
]);
|
|
25
|
+
function isObject(value) {
|
|
26
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
function isNonEmptyString(value) {
|
|
29
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
30
|
+
}
|
|
31
|
+
function isIntegerIn(value, min, max) {
|
|
32
|
+
return Number.isSafeInteger(value) && value >= min && value <= max;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Join mode and `S` of one endpoint, or `undefined` when its fields disagree
|
|
36
|
+
* and a receiver must ignore it (4.1). `sourceAddress` alone selects the mode;
|
|
37
|
+
* `protocol` may only restate it, so "amt" and "atsc3" (draft -00) are
|
|
38
|
+
* inconsistent here: a bearer is a `networkSource`, never a protocol.
|
|
39
|
+
*/
|
|
40
|
+
export function multicastEndpointSource(endpoint) {
|
|
41
|
+
if (!isObject(endpoint))
|
|
42
|
+
return undefined;
|
|
43
|
+
const sourceAddress = endpoint["sourceAddress"];
|
|
44
|
+
if (sourceAddress !== undefined && !isNonEmptyString(sourceAddress))
|
|
45
|
+
return undefined;
|
|
46
|
+
const mode = sourceAddress === undefined ? "asm" : "ssm";
|
|
47
|
+
const protocol = endpoint["protocol"];
|
|
48
|
+
if (protocol !== undefined && protocol !== mode)
|
|
49
|
+
return undefined;
|
|
50
|
+
const auth = endpoint["auth"];
|
|
51
|
+
const senderAddress = isObject(auth) ? auth["senderAddress"] : undefined;
|
|
52
|
+
if (mode === "ssm")
|
|
53
|
+
return senderAddress === undefined ? { mode, source: sourceAddress } : undefined;
|
|
54
|
+
if (auth === undefined)
|
|
55
|
+
return { mode };
|
|
56
|
+
return isNonEmptyString(senderAddress) ? { mode, source: senderAddress } : undefined;
|
|
57
|
+
}
|
|
58
|
+
function authIssues(auth) {
|
|
59
|
+
const base = "$.multicast.auth";
|
|
60
|
+
const issue = (path, message) => [
|
|
61
|
+
{ code: "multicast_auth", path: `${base}${path}`, message },
|
|
62
|
+
];
|
|
63
|
+
if (!isObject(auth))
|
|
64
|
+
return issue("", "auth must be an object");
|
|
65
|
+
const unknown = Object.keys(auth).filter(key => !AUTH_MEMBERS.has(key));
|
|
66
|
+
if (unknown.length > 0) {
|
|
67
|
+
return issue("", `auth has unknown member(s) ${unknown.join(", ")}; draft -01 7.2.6 defines scheme, version, sig, keys and minEpoch`);
|
|
68
|
+
}
|
|
69
|
+
if (auth["scheme"] !== "bc-provenance")
|
|
70
|
+
return issue(".scheme", 'scheme must be "bc-provenance"');
|
|
71
|
+
if (auth["version"] !== 2)
|
|
72
|
+
return issue(".version", "version must be 2 (bc-provenance version 2, draft -01 7.2)");
|
|
73
|
+
if (auth["sig"] !== "ed25519")
|
|
74
|
+
return issue(".sig", 'sig must be "ed25519"');
|
|
75
|
+
const keys = auth["keys"];
|
|
76
|
+
if (!Array.isArray(keys) || keys.length < 1 || keys.length > 4) {
|
|
77
|
+
return issue(".keys", "keys must be an array of one to four {kid, publicKey, firstEpoch} objects");
|
|
78
|
+
}
|
|
79
|
+
const kids = new Set();
|
|
80
|
+
const firstEpochs = new Set();
|
|
81
|
+
for (let index = 0; index < keys.length; index++) {
|
|
82
|
+
const key = keys[index];
|
|
83
|
+
const at = `.keys[${index}]`;
|
|
84
|
+
if (!isObject(key) || Object.keys(key).some(member => !KEY_MEMBERS.has(member))) {
|
|
85
|
+
return issue(at, "a key is exactly {kid, publicKey, firstEpoch}");
|
|
86
|
+
}
|
|
87
|
+
if (!isIntegerIn(key["kid"], 0, UINT32_MAX))
|
|
88
|
+
return issue(`${at}.kid`, "kid must be an unsigned 32-bit integer");
|
|
89
|
+
if (typeof key["publicKey"] !== "string" || !ED25519_PUBLIC_KEY_BASE64URL.test(key["publicKey"])) {
|
|
90
|
+
return issue(`${at}.publicKey`, "publicKey must be a 32-octet Ed25519 key in canonical unpadded base64url");
|
|
91
|
+
}
|
|
92
|
+
if (!isIntegerIn(key["firstEpoch"], 0, UINT32_MAX)) {
|
|
93
|
+
return issue(`${at}.firstEpoch`, "firstEpoch must be an unsigned 32-bit integer");
|
|
94
|
+
}
|
|
95
|
+
// A repeated kid or firstEpoch leaves no key set (7.2.6): fail the whole
|
|
96
|
+
// block, never fall back to unauthenticated reception.
|
|
97
|
+
if (kids.has(key["kid"]))
|
|
98
|
+
return issue(`${at}.kid`, `kid ${key["kid"]} is repeated; the catalog holds no key set`);
|
|
99
|
+
if (firstEpochs.has(key["firstEpoch"])) {
|
|
100
|
+
return issue(`${at}.firstEpoch`, `firstEpoch ${key["firstEpoch"]} is repeated; the catalog holds no key set`);
|
|
101
|
+
}
|
|
102
|
+
kids.add(key["kid"]);
|
|
103
|
+
firstEpochs.add(key["firstEpoch"]);
|
|
104
|
+
}
|
|
105
|
+
if (!isIntegerIn(auth["minEpoch"], 0, UINT32_MAX)) {
|
|
106
|
+
return issue(".minEpoch", "minEpoch must be an unsigned 32-bit integer");
|
|
107
|
+
}
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
function endpointAuthIssue(endpoint, mode, at) {
|
|
111
|
+
const auth = endpoint["auth"];
|
|
112
|
+
if (!isObject(auth))
|
|
113
|
+
return { path: `${at}.auth`, message: "auth must be an object" };
|
|
114
|
+
const unknown = Object.keys(auth).filter(key => !ENDPOINT_AUTH_MEMBERS.has(key));
|
|
115
|
+
if (unknown.length > 0)
|
|
116
|
+
return { path: `${at}.auth`, message: `auth has unknown member(s) ${unknown.join(", ")}` };
|
|
117
|
+
if (!isIntegerIn(auth["manifestPort"], 1, 65535)) {
|
|
118
|
+
return { path: `${at}.auth.manifestPort`, message: "manifestPort must be an integer from 1 to 65535" };
|
|
119
|
+
}
|
|
120
|
+
if (!isIntegerIn(auth["streamId"], 0, UINT32_MAX)) {
|
|
121
|
+
return { path: `${at}.auth.streamId`, message: "streamId must be an unsigned 32-bit integer" };
|
|
122
|
+
}
|
|
123
|
+
if (mode === "ssm" && auth["senderAddress"] !== undefined) {
|
|
124
|
+
return { path: `${at}.auth.senderAddress`, message: "senderAddress must not appear on an SSM endpoint; S is sourceAddress" };
|
|
125
|
+
}
|
|
126
|
+
if (mode === "asm" && !isNonEmptyString(auth["senderAddress"])) {
|
|
127
|
+
return { path: `${at}.auth.senderAddress`, message: "a protected ASM endpoint requires senderAddress" };
|
|
128
|
+
}
|
|
129
|
+
if (auth["maxAuthDelayMs"] !== undefined && !isIntegerIn(auth["maxAuthDelayMs"], 50, 1000)) {
|
|
130
|
+
return { path: `${at}.auth.maxAuthDelayMs`, message: "maxAuthDelayMs must be an integer from 50 to 1000" };
|
|
131
|
+
}
|
|
132
|
+
if (auth["manifestTimerMs"] !== undefined && !isIntegerIn(auth["manifestTimerMs"], 1, Number.MAX_SAFE_INTEGER)) {
|
|
133
|
+
return { path: `${at}.auth.manifestTimerMs`, message: "manifestTimerMs must be an integer of at least 1" };
|
|
134
|
+
}
|
|
135
|
+
if (auth["manifestTrack"] !== undefined && !isNonEmptyString(auth["manifestTrack"])) {
|
|
136
|
+
return { path: `${at}.auth.manifestTrack`, message: "manifestTrack must be a non-empty string" };
|
|
137
|
+
}
|
|
138
|
+
if (!isIntegerIn(endpoint["bandwidth"], 1, Number.MAX_SAFE_INTEGER)) {
|
|
139
|
+
return { path: `${at}.bandwidth`, message: "a protected endpoint requires bandwidth, which bounds the receiver's hold queues" };
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Where a catalog object carries the namespace of the catalog track it was
|
|
145
|
+
* read from. A symbol, so it is never wire data and survives object spread;
|
|
146
|
+
* `Symbol.for`, so two bundled copies of this module agree on it.
|
|
147
|
+
*/
|
|
148
|
+
export const CATALOG_NAMESPACE = Symbol.for("@blockcast/mmt-base/catalogNamespace");
|
|
149
|
+
/**
|
|
150
|
+
* `catalog` tagged with the namespace of its catalog track. Every receiver
|
|
151
|
+
* rule that takes the catalog (`multicastCatalogIssues`,
|
|
152
|
+
* `admittedMulticastEndpoints` and the transport selectors built on them)
|
|
153
|
+
* then judges the foreign-namespace rule against it, independent of track
|
|
154
|
+
* order. Tag once, where the catalog track is read.
|
|
155
|
+
*/
|
|
156
|
+
export function withCatalogNamespace(catalog, namespace) {
|
|
157
|
+
return { ...catalog, [CATALOG_NAMESPACE]: namespace };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Every draft -01 4.1 / 7.2.6 violation in `catalog.multicast`, in document
|
|
161
|
+
* order. Packet-id, group-address and track-existence rules are not here; the
|
|
162
|
+
* container validator and the receivers already check those.
|
|
163
|
+
*
|
|
164
|
+
* `catalogNamespace` is the namespace of the catalog track, from `options` or else the
|
|
165
|
+
* catalog's `withCatalogNamespace` tag. Without it the
|
|
166
|
+
* foreign-namespace rule can only compare listed tracks with each other: the
|
|
167
|
+
* first listed track's namespace becomes the reference, so which side of a
|
|
168
|
+
* disagreement is dropped depends on order. It still fails closed; pass
|
|
169
|
+
* `catalogNamespace` wherever the catalog track is known.
|
|
170
|
+
*/
|
|
171
|
+
export function multicastCatalogIssues(catalog, options = {}) {
|
|
172
|
+
if (!isObject(catalog))
|
|
173
|
+
return [];
|
|
174
|
+
const issues = [];
|
|
175
|
+
if ("multicast.auth" in catalog) {
|
|
176
|
+
// Fail closed: a draft -00 publisher meant the flow to be protected, and
|
|
177
|
+
// the key it names verifies nothing in bc-provenance version 2.
|
|
178
|
+
issues.push({
|
|
179
|
+
code: "multicast_auth",
|
|
180
|
+
path: '$["multicast.auth"]',
|
|
181
|
+
message: 'the root "multicast.auth" key is retired; declare auth as multicast.auth (draft -01 7.2.6)',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
const multicast = catalog["multicast"];
|
|
185
|
+
if (!isObject(multicast))
|
|
186
|
+
return issues;
|
|
187
|
+
const protectedCatalog = multicast["auth"] !== undefined;
|
|
188
|
+
if (protectedCatalog)
|
|
189
|
+
issues.push(...authIssues(multicast["auth"]));
|
|
190
|
+
const endpoints = multicast["endpoints"];
|
|
191
|
+
if (!Array.isArray(endpoints))
|
|
192
|
+
return issues;
|
|
193
|
+
const tracks = Array.isArray(catalog["tracks"]) ? catalog["tracks"] : [];
|
|
194
|
+
const namespaceOf = new Map();
|
|
195
|
+
for (const track of tracks) {
|
|
196
|
+
if (isObject(track) && typeof track["name"] === "string")
|
|
197
|
+
namespaceOf.set(track["name"], track["namespace"]);
|
|
198
|
+
}
|
|
199
|
+
const tagged = catalog[CATALOG_NAMESPACE];
|
|
200
|
+
let referenceNamespace = options.catalogNamespace ?? (typeof tagged === "string" ? tagged : undefined);
|
|
201
|
+
const sources = [];
|
|
202
|
+
for (let index = 0; index < endpoints.length; index++) {
|
|
203
|
+
const endpoint = endpoints[index];
|
|
204
|
+
const at = `$.multicast.endpoints[${index}]`;
|
|
205
|
+
const fail = (code, path, message) => {
|
|
206
|
+
issues.push({ code, path, message, endpointIndex: index });
|
|
207
|
+
};
|
|
208
|
+
sources.push(undefined);
|
|
209
|
+
if (!isObject(endpoint)) {
|
|
210
|
+
fail("multicast_endpoint", at, "endpoint must be an object");
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const protocol = endpoint["protocol"];
|
|
214
|
+
if (protocol !== undefined && protocol !== "ssm" && protocol !== "asm") {
|
|
215
|
+
fail("multicast_endpoint", `${at}.protocol`, `protocol must be "ssm" or "asm"; a bearer such as ${JSON.stringify(protocol)} is a networkSource entry (draft -01 4.2)`);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
const hasAuth = endpoint["auth"] !== undefined;
|
|
219
|
+
if (protectedCatalog !== hasAuth) {
|
|
220
|
+
fail("multicast_endpoint_auth", `${at}.auth`, protectedCatalog
|
|
221
|
+
? "every endpoint requires auth when multicast carries auth; a receiver ignores this endpoint"
|
|
222
|
+
: "auth names no key without multicast.auth; a receiver ignores this endpoint");
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
const sourceAddress = endpoint["sourceAddress"];
|
|
226
|
+
if (sourceAddress !== undefined && !isNonEmptyString(sourceAddress)) {
|
|
227
|
+
fail("multicast_endpoint", `${at}.sourceAddress`, "sourceAddress must be a non-empty string");
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
const mode = sourceAddress === undefined ? "asm" : "ssm";
|
|
231
|
+
if (protocol !== undefined && protocol !== mode) {
|
|
232
|
+
fail("multicast_endpoint", `${at}.protocol`, `protocol ${JSON.stringify(protocol)} disagrees with sourceAddress, which selects ${mode}`);
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
// The (S, G, port) rule below compares ports with ===, so only an
|
|
236
|
+
// integer may reach it: "5001" and 5001 would otherwise both pass.
|
|
237
|
+
if (!isIntegerIn(endpoint["port"], 1, 65535)) {
|
|
238
|
+
fail("multicast_endpoint", `${at}.port`, "port must be an integer from 1 to 65535");
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
if (hasAuth) {
|
|
242
|
+
const authIssue = endpointAuthIssue(endpoint, mode, at);
|
|
243
|
+
if (authIssue) {
|
|
244
|
+
fail("multicast_endpoint_auth", authIssue.path, authIssue.message);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
sources[index] = multicastEndpointSource(endpoint);
|
|
249
|
+
const refs = Array.isArray(endpoint["tracks"]) ? endpoint["tracks"] : [];
|
|
250
|
+
for (let refIndex = 0; refIndex < refs.length; refIndex++) {
|
|
251
|
+
const ref = refs[refIndex];
|
|
252
|
+
const name = isObject(ref) ? ref["name"] : ref;
|
|
253
|
+
if (typeof name !== "string")
|
|
254
|
+
continue;
|
|
255
|
+
const namespace = namespaceOf.get(name);
|
|
256
|
+
if (typeof namespace !== "string")
|
|
257
|
+
continue;
|
|
258
|
+
referenceNamespace ??= namespace;
|
|
259
|
+
if (namespace !== referenceNamespace) {
|
|
260
|
+
fail("multicast_track", `${at}.tracks[${refIndex}].name`, `track ${JSON.stringify(name)} declares namespace ${JSON.stringify(namespace)}, not the catalog track's ${JSON.stringify(referenceNamespace)}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// One endpoint object per (S, G, port), and a manifestPort that is no port
|
|
265
|
+
// and no other manifestPort of its (S, G) (4.1, 7.2.6). The rule binds the
|
|
266
|
+
// endpoint whose manifestPort clashes; two equal tuples or two equal
|
|
267
|
+
// manifestPorts break it on both sides, so both are named.
|
|
268
|
+
const tupleOf = (index) => {
|
|
269
|
+
const endpoint = endpoints[index];
|
|
270
|
+
const auth = endpoint["auth"];
|
|
271
|
+
return {
|
|
272
|
+
sg: JSON.stringify([sources[index].source ?? null, endpoint["groupAddress"]]),
|
|
273
|
+
port: endpoint["port"],
|
|
274
|
+
manifestPort: isObject(auth) ? auth["manifestPort"] : undefined,
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
for (let index = 0; index < endpoints.length; index++) {
|
|
278
|
+
if (!sources[index])
|
|
279
|
+
continue;
|
|
280
|
+
const own = tupleOf(index);
|
|
281
|
+
const at = `$.multicast.endpoints[${index}]`;
|
|
282
|
+
if (own.manifestPort !== undefined && own.manifestPort === own.port) {
|
|
283
|
+
issues.push({ code: "multicast_endpoint_auth", path: `${at}.auth.manifestPort`, message: "manifestPort must differ from the endpoint's own port", endpointIndex: index });
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
for (let other = 0; other < endpoints.length; other++) {
|
|
287
|
+
if (other === index || !sources[other])
|
|
288
|
+
continue;
|
|
289
|
+
const peer = tupleOf(other);
|
|
290
|
+
if (peer.sg !== own.sg)
|
|
291
|
+
continue;
|
|
292
|
+
if (peer.port === own.port) {
|
|
293
|
+
issues.push({ code: "multicast_endpoint", path: `${at}.port`, message: `(S, G, port) is shared with endpoint ${other}; one endpoint object per multicast tuple`, endpointIndex: index });
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
if (own.manifestPort !== undefined && (own.manifestPort === peer.port || own.manifestPort === peer.manifestPort)) {
|
|
297
|
+
issues.push({ code: "multicast_endpoint_auth", path: `${at}.auth.manifestPort`, message: `manifestPort is a port or manifestPort of endpoint ${other} on the same (S, G)`, endpointIndex: index });
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return issues;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Indices of the endpoints a receiver may use: none when a catalog-level
|
|
306
|
+
* issue leaves it no key set (7.2.6), otherwise every endpoint no issue
|
|
307
|
+
* names. Other receiver checks (group address, packet ids) still apply.
|
|
308
|
+
*/
|
|
309
|
+
export function admittedMulticastEndpoints(catalog, options = {}) {
|
|
310
|
+
const multicast = isObject(catalog) ? catalog["multicast"] : undefined;
|
|
311
|
+
const endpoints = isObject(multicast) && Array.isArray(multicast["endpoints"]) ? multicast["endpoints"] : [];
|
|
312
|
+
const issues = multicastCatalogIssues(catalog, options);
|
|
313
|
+
if (issues.some(issue => issue.endpointIndex === undefined))
|
|
314
|
+
return new Set();
|
|
315
|
+
const ignored = new Set(issues.map(issue => issue.endpointIndex));
|
|
316
|
+
return new Set(endpoints.map((_, index) => index).filter(index => !ignored.has(index)));
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=multicast-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multicast-catalog.js","sourceRoot":"","sources":["../src/multicast-catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/signalling.d.ts
CHANGED
|
@@ -126,44 +126,58 @@ export declare function parseAlFecMessageBody(message: Uint8Array): AlFecMessage
|
|
|
126
126
|
*/
|
|
127
127
|
export declare function parseAlFecMessage(mmtpPacket: Uint8Array): AlFecMessage | null;
|
|
128
128
|
/**
|
|
129
|
-
* Decoder geometry of one FEC flow
|
|
130
|
-
*
|
|
131
|
-
*
|
|
129
|
+
* Decoder geometry of one FEC flow's AL-FEC message entry under
|
|
130
|
+
* draft-ramadan-moq-mmt-01 Section 8.3 ("iso-ssbg1-v1"): one Asset, coding
|
|
131
|
+
* byte 0x14, fec_code_id_for_repair_flow 3 (RaptorQ) or 1 (Reed-Solomon),
|
|
132
|
+
* and no OTI (draft-ramadan-moq-mmt-01 Section 7.2). K, T and P come from
|
|
133
|
+
* the entry's own fields; a private field, if present, is ignored.
|
|
132
134
|
*/
|
|
133
135
|
export interface AlFecRaptorQFlowConfig {
|
|
136
|
+
/** The flow's one Asset packet_id (number_of_assets is 1). */
|
|
134
137
|
sourcePacketIds: number[];
|
|
135
138
|
repairFlowId: number;
|
|
139
|
+
/** `FEC_CODE_RAPTORQ` (3) or `FEC_CODE_REED_SOLOMON` (1). */
|
|
140
|
+
fecCodeId: number;
|
|
136
141
|
/** Always `SSBG_MODE_1` (`iso-ssbg1-v1`). */
|
|
137
142
|
ssbgMode: number;
|
|
138
|
-
/**
|
|
143
|
+
/** Always 0: the profile's coding byte is exactly 0x14. */
|
|
139
144
|
fecPayloadIdMode: 0 | 1;
|
|
145
|
+
/** T, from length_of_repair_symbol. */
|
|
140
146
|
repairSymbolSize: number;
|
|
147
|
+
/** K, from maximum_k_for_repair_flow. */
|
|
141
148
|
maximumK: number;
|
|
149
|
+
/** P, from maximum_p_for_repair_flow: the RSB_length total over every published layer. */
|
|
142
150
|
maximumP: number;
|
|
143
|
-
interleaveDepth: number;
|
|
144
|
-
oti: Uint8Array;
|
|
145
151
|
protectionWindowTime: number;
|
|
146
152
|
protectionWindowSize: number;
|
|
147
153
|
}
|
|
148
154
|
/**
|
|
149
|
-
* Validate one parsed FEC flow against
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
155
|
+
* Validate one parsed FEC flow against draft-ramadan-moq-mmt-01 Sections 8.3
|
|
156
|
+
* and 12.2 and return its decoder geometry, or null when the entry is
|
|
157
|
+
* outside them. Fail closed on everything else:
|
|
158
|
+
*
|
|
159
|
+
* - coding byte other than 0x14 (one-stage, ssbg_mode1, ffsrpts_flag 0,
|
|
160
|
+
* fec_payload_id_mode 0). 0x15 is fec_payload_id_mode 1 under Amd 1:2025,
|
|
161
|
+
* which "iso-ssbg1-v1" does not describe (moq-fec-01 Section 7.3);
|
|
162
|
+
* - number_of_assets other than 1;
|
|
163
|
+
* - fec_code_id_for_repair_flow other than 3 or 1, the retired Blockcast
|
|
164
|
+
* code 2 included (ISO/IEC 23008-10 Table 1);
|
|
165
|
+
* - T < 14, K = 0, P = 0, K + P - 1 > 2^24 - 1;
|
|
166
|
+
* - RaptorQ: T not a multiple of 8, or K > 56403;
|
|
167
|
+
* - Reed-Solomon: K + P > 255;
|
|
168
|
+
* - repair_flow_id 0 (the signalling flow) or the flow's own packet_id.
|
|
153
169
|
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
* Amd 1:2025): one-stage, ssbg_mode1, ffsrpts_flag 0, fec_payload_id_mode 0.
|
|
157
|
-
* 0x15 is accepted too: its low bit is fec_payload_id_mode 1 under Amd
|
|
158
|
-
* 1:2025 but reserved "1" in the unamended 2023 Table C.3, so a 2023 sender
|
|
159
|
-
* of the same profile emits it. No later field depends on the bit, and each
|
|
160
|
-
* source packet's FEC_type says whether it carries a Source FEC Payload ID,
|
|
161
|
-
* so the bit is reported, not interpreted (BLO-35597 N1). Any other coding
|
|
162
|
-
* byte is refused here, though `parseAlFecMessageBody` still reports it:
|
|
163
|
-
* ssbg_mode0 (0x10/0x11, the retired `k-padded-v1` wire) carries no length
|
|
164
|
-
* field; ffsrpts_flag=1 changes the source/repair packet trailer layout.
|
|
170
|
+
* Checks that span entries (another entry's packet_id, a duplicate
|
|
171
|
+
* repair_flow_id or Asset) are `alFecMessageFlowConfigs`'.
|
|
165
172
|
*/
|
|
166
173
|
export declare function alFecRaptorQFlowConfig(flow: AlFecFlow): AlFecRaptorQFlowConfig | null;
|
|
174
|
+
/**
|
|
175
|
+
* `alFecRaptorQFlowConfig` for every entry of a message, index for index,
|
|
176
|
+
* plus the draft-ramadan-moq-mmt-01 Section 12.2 checks that span entries: an
|
|
177
|
+
* entry whose repair_flow_id is another entry's Asset packet_id, and every
|
|
178
|
+
* entry of two that name one repair_flow_id or list one Asset, is null.
|
|
179
|
+
*/
|
|
180
|
+
export declare function alFecMessageFlowConfigs(message: AlFecMessageBody): (AlFecRaptorQFlowConfig | null)[];
|
|
167
181
|
/** location_type values (Table 96) a receiver may meet in an asset location. */
|
|
168
182
|
export type MmtGeneralLocation = {
|
|
169
183
|
locationType: 0x00;
|
package/dist/signalling.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signalling.d.ts","sourceRoot":"","sources":["../src/signalling.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"signalling.d.ts","sourceRoot":"","sources":["../src/signalling.ts"],"names":[],"mappings":"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"}
|
package/dist/signalling.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* receiver that refuses a reserved value cannot accept a conformant revision
|
|
21
21
|
* of the syntax that assigns it.
|
|
22
22
|
*/
|
|
23
|
-
import { ALFEC_MESSAGE_ID, FEC_CODE_RAPTORQ, PACKET_TYPE_SIGNALING, parseMMTPHeader, } from './mmtp.js';
|
|
23
|
+
import { ALFEC_MESSAGE_ID, FEC_CODE_RAPTORQ, FEC_CODE_REED_SOLOMON, MMTP_SIGNALING_PACKET_ID, PACKET_TYPE_SIGNALING, parseMMTPHeader, } from './mmtp.js';
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
25
25
|
// Wire reader
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
@@ -330,83 +330,97 @@ export function parseAlFecMessage(mmtpPacket) {
|
|
|
330
330
|
return null;
|
|
331
331
|
return { ...alFec[0].message, payloadForm: packet.payloadForm };
|
|
332
332
|
}
|
|
333
|
-
const RAPTORQ_PRIVATE_FIELD_LENGTH = 13;
|
|
334
333
|
const RAPTORQ_MAX_SOURCE_SYMBOLS = 56_403;
|
|
335
334
|
const REPAIR_SYMBOL_ID_MAX = 0x00ff_ffff;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const transferLength = (oti[0] * 0x1_0000_0000) +
|
|
340
|
-
(((oti[1] << 24) | (oti[2] << 16) | (oti[3] << 8) | oti[4]) >>> 0);
|
|
341
|
-
const symbolSize = (oti[6] << 8) | oti[7];
|
|
342
|
-
const sourceBlocks = oti[8];
|
|
343
|
-
const subBlocks = (oti[9] << 8) | oti[10];
|
|
344
|
-
const alignment = oti[11];
|
|
345
|
-
if (!Number.isSafeInteger(transferLength) || transferLength <= 0 ||
|
|
346
|
-
symbolSize !== repairSymbolSize || symbolSize === 0 || symbolSize % 8 !== 0 ||
|
|
347
|
-
sourceBlocks !== 1 || subBlocks !== 1 || alignment !== 8 ||
|
|
348
|
-
transferLength % symbolSize !== 0) {
|
|
349
|
-
return null;
|
|
350
|
-
}
|
|
351
|
-
const k = transferLength / symbolSize;
|
|
352
|
-
return Number.isInteger(k) && k >= 1 && k <= RAPTORQ_MAX_SOURCE_SYMBOLS ? k : null;
|
|
353
|
-
}
|
|
335
|
+
/** The 12-octet MMTP header plus the 2-octet length of the T - 2 construction (moq-fec-01 Section 7.3). */
|
|
336
|
+
const MIN_REPAIR_SYMBOL_SIZE = 14;
|
|
337
|
+
const REED_SOLOMON_MAX_BLOCK = 255;
|
|
354
338
|
/**
|
|
355
|
-
* Validate one parsed FEC flow against
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
339
|
+
* Validate one parsed FEC flow against draft-ramadan-moq-mmt-01 Sections 8.3
|
|
340
|
+
* and 12.2 and return its decoder geometry, or null when the entry is
|
|
341
|
+
* outside them. Fail closed on everything else:
|
|
342
|
+
*
|
|
343
|
+
* - coding byte other than 0x14 (one-stage, ssbg_mode1, ffsrpts_flag 0,
|
|
344
|
+
* fec_payload_id_mode 0). 0x15 is fec_payload_id_mode 1 under Amd 1:2025,
|
|
345
|
+
* which "iso-ssbg1-v1" does not describe (moq-fec-01 Section 7.3);
|
|
346
|
+
* - number_of_assets other than 1;
|
|
347
|
+
* - fec_code_id_for_repair_flow other than 3 or 1, the retired Blockcast
|
|
348
|
+
* code 2 included (ISO/IEC 23008-10 Table 1);
|
|
349
|
+
* - T < 14, K = 0, P = 0, K + P - 1 > 2^24 - 1;
|
|
350
|
+
* - RaptorQ: T not a multiple of 8, or K > 56403;
|
|
351
|
+
* - Reed-Solomon: K + P > 255;
|
|
352
|
+
* - repair_flow_id 0 (the signalling flow) or the flow's own packet_id.
|
|
359
353
|
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
* Amd 1:2025): one-stage, ssbg_mode1, ffsrpts_flag 0, fec_payload_id_mode 0.
|
|
363
|
-
* 0x15 is accepted too: its low bit is fec_payload_id_mode 1 under Amd
|
|
364
|
-
* 1:2025 but reserved "1" in the unamended 2023 Table C.3, so a 2023 sender
|
|
365
|
-
* of the same profile emits it. No later field depends on the bit, and each
|
|
366
|
-
* source packet's FEC_type says whether it carries a Source FEC Payload ID,
|
|
367
|
-
* so the bit is reported, not interpreted (BLO-35597 N1). Any other coding
|
|
368
|
-
* byte is refused here, though `parseAlFecMessageBody` still reports it:
|
|
369
|
-
* ssbg_mode0 (0x10/0x11, the retired `k-padded-v1` wire) carries no length
|
|
370
|
-
* field; ffsrpts_flag=1 changes the source/repair packet trailer layout.
|
|
354
|
+
* Checks that span entries (another entry's packet_id, a duplicate
|
|
355
|
+
* repair_flow_id or Asset) are `alFecMessageFlowConfigs`'.
|
|
371
356
|
*/
|
|
372
357
|
export function alFecRaptorQFlowConfig(flow) {
|
|
373
358
|
if (flow.fecCodingStructure !== FEC_CODING_STRUCTURE_ONE_STAGE || flow.repairFlows.length !== 1)
|
|
374
359
|
return null;
|
|
375
|
-
if (flow.ssbgMode !== SSBG_MODE_1)
|
|
360
|
+
if (flow.ssbgMode !== SSBG_MODE_1 || flow.ffsrptsFlag !== 0 || flow.fecPayloadIdMode !== 0)
|
|
376
361
|
return null;
|
|
377
|
-
if (flow.
|
|
362
|
+
if (flow.packetIds.length !== 1)
|
|
378
363
|
return null;
|
|
379
364
|
const repair = flow.repairFlows[0];
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
if (!privateField || privateField.privateFlag !== 1 ||
|
|
384
|
-
privateField.data.length !== RAPTORQ_PRIVATE_FIELD_LENGTH) {
|
|
365
|
+
const { fecCodeId, maximumK: k, maximumP: p } = repair;
|
|
366
|
+
const t = flow.repairSymbolSize;
|
|
367
|
+
if (t < MIN_REPAIR_SYMBOL_SIZE || k < 1 || p < 1 || k + p - 1 > REPAIR_SYMBOL_ID_MAX)
|
|
385
368
|
return null;
|
|
369
|
+
if (fecCodeId === FEC_CODE_RAPTORQ) {
|
|
370
|
+
if (t % 8 !== 0 || k > RAPTORQ_MAX_SOURCE_SYMBOLS)
|
|
371
|
+
return null;
|
|
386
372
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
if (repair.maximumK !== otiK || repair.maximumP === 0 ||
|
|
393
|
-
repair.maximumK + repair.maximumP - 1 > REPAIR_SYMBOL_ID_MAX) {
|
|
373
|
+
else if (fecCodeId === FEC_CODE_REED_SOLOMON) {
|
|
374
|
+
if (k + p > REED_SOLOMON_MAX_BLOCK)
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
394
378
|
return null;
|
|
395
379
|
}
|
|
380
|
+
if (repair.repairFlowId === MMTP_SIGNALING_PACKET_ID || repair.repairFlowId === flow.packetIds[0])
|
|
381
|
+
return null;
|
|
396
382
|
return {
|
|
397
383
|
sourcePacketIds: [...flow.packetIds],
|
|
398
384
|
repairFlowId: repair.repairFlowId,
|
|
385
|
+
fecCodeId,
|
|
399
386
|
ssbgMode: flow.ssbgMode,
|
|
400
387
|
fecPayloadIdMode: flow.fecPayloadIdMode,
|
|
401
|
-
repairSymbolSize:
|
|
402
|
-
maximumK:
|
|
403
|
-
maximumP:
|
|
404
|
-
interleaveDepth,
|
|
405
|
-
oti,
|
|
388
|
+
repairSymbolSize: t,
|
|
389
|
+
maximumK: k,
|
|
390
|
+
maximumP: p,
|
|
406
391
|
protectionWindowTime: repair.protectionWindowTime,
|
|
407
392
|
protectionWindowSize: repair.protectionWindowSize,
|
|
408
393
|
};
|
|
409
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* `alFecRaptorQFlowConfig` for every entry of a message, index for index,
|
|
397
|
+
* plus the draft-ramadan-moq-mmt-01 Section 12.2 checks that span entries: an
|
|
398
|
+
* entry whose repair_flow_id is another entry's Asset packet_id, and every
|
|
399
|
+
* entry of two that name one repair_flow_id or list one Asset, is null.
|
|
400
|
+
*/
|
|
401
|
+
export function alFecMessageFlowConfigs(message) {
|
|
402
|
+
const assetCount = new Map();
|
|
403
|
+
const repairCount = new Map();
|
|
404
|
+
const bump = (map, key) => map.set(key, (map.get(key) ?? 0) + 1);
|
|
405
|
+
for (const flow of message.flows) {
|
|
406
|
+
for (const id of flow.packetIds)
|
|
407
|
+
bump(assetCount, id);
|
|
408
|
+
for (const repair of flow.repairFlows)
|
|
409
|
+
bump(repairCount, repair.repairFlowId);
|
|
410
|
+
}
|
|
411
|
+
return message.flows.map(flow => {
|
|
412
|
+
const config = alFecRaptorQFlowConfig(flow);
|
|
413
|
+
if (!config)
|
|
414
|
+
return null;
|
|
415
|
+
const [asset] = config.sourcePacketIds;
|
|
416
|
+
if (assetCount.get(asset) !== 1 || repairCount.get(config.repairFlowId) !== 1)
|
|
417
|
+
return null;
|
|
418
|
+
// Its own packet_id is already refused, so any count here is another entry's.
|
|
419
|
+
if (assetCount.has(config.repairFlowId))
|
|
420
|
+
return null;
|
|
421
|
+
return config;
|
|
422
|
+
});
|
|
423
|
+
}
|
|
410
424
|
/**
|
|
411
425
|
* MMT_general_location_info() for an Asset location. "Only the value of
|
|
412
426
|
* location_type between 0x00 and 0x06 shall be used for an Asset location"
|