@blockcast/mmt-container 1.0.1 → 2.0.0-main.609e08d7e29f
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 +9 -7
- package/dist/browser-runtime.js +6972 -6693
- package/dist/browser-runtime.js.map +4 -4
- package/dist/carp-catalog.d.ts +7 -7
- package/dist/carp-catalog.d.ts.map +1 -1
- package/dist/carp-catalog.js +65 -230
- package/dist/carp-catalog.js.map +3 -3
- package/dist/catalog-fec-params.js.map +1 -1
- package/dist/catalog-network-source.js.map +1 -1
- package/dist/delivery-catalog.js +3 -0
- package/dist/delivery-catalog.js.map +2 -2
- package/dist/delta-fallback-config.js.map +1 -1
- package/dist/fec-manager.d.ts +25 -1
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +208 -15
- package/dist/fec-manager.js.map +2 -2
- package/dist/fec-state.js.map +1 -1
- package/dist/fec-worker-setup.js.map +1 -1
- package/dist/held-layer-admission.d.ts +8 -0
- package/dist/held-layer-admission.d.ts.map +1 -1
- package/dist/held-layer-admission.js +22 -1
- package/dist/held-layer-admission.js.map +2 -2
- package/dist/iso-block-locator.js.map +1 -1
- package/dist/mfu-reassembler.js.map +1 -1
- package/dist/mmtp-container-parser.js.map +1 -1
- package/dist/mmtp-container-parser.no-modules.js +146 -332
- package/dist/mmtp-container-parser.no-modules.js.map +4 -4
- package/dist/mmtp-decode-pipeline.js.map +1 -1
- package/dist/mmtp-fec-session.d.ts.map +1 -1
- package/dist/mmtp-fec-session.js +61 -15
- package/dist/mmtp-fec-session.js.map +3 -3
- package/dist/mmtp-router.d.ts +11 -6
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +47 -10
- package/dist/mmtp-router.js.map +3 -3
- package/dist/multicast-auth-catalog.d.ts +8 -8
- package/dist/multicast-auth-catalog.d.ts.map +1 -1
- package/dist/multicast-auth-catalog.js +171 -75
- package/dist/multicast-auth-catalog.js.map +4 -4
- package/dist/multicast-input.d.ts +5 -5
- package/dist/multicast-input.d.ts.map +1 -1
- package/dist/multicast-input.js +126 -49
- package/dist/multicast-input.js.map +3 -3
- package/dist/multicast-manager.d.ts +11 -4
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +7914 -7659
- package/dist/multicast-manager.js.map +4 -4
- package/dist/multicast-transport.d.ts +16 -1
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +120 -5
- package/dist/multicast-transport.js.map +4 -4
- package/dist/multicast-unwrap.js +2 -2
- package/dist/multicast-unwrap.js.map +2 -2
- package/dist/no-modules.js +100 -288
- package/dist/no-modules.js.map +4 -4
- package/dist/repair-fetch.js.map +1 -1
- package/dist/signaling.js.map +1 -1
- package/dist/timestamp-codec.js.map +1 -1
- package/dist/wasm-mfu-reassembler.js.map +1 -1
- package/dist/wasm-mmtp-container-parser.js.map +1 -1
- package/package.json +5 -5
- package/schemas/catalog.schema.json +15 -7
- package/src/carp-catalog.ts +14 -13
- package/src/fec-manager.ts +89 -14
- package/src/held-layer-admission.ts +38 -1
- package/src/mmtp-fec-session.ts +20 -12
- package/src/mmtp-router.ts +65 -16
- package/src/multicast-auth-catalog.ts +43 -36
- package/src/multicast-input.ts +28 -8
- package/src/multicast-manager.ts +38 -34
- package/src/multicast-transport.ts +74 -7
- package/test-vectors/bc-provenance-v2.json +614 -175
- package/test-vectors/catalog/README.md +24 -8
- package/test-vectors/catalog/negative/multicast-auth-asm-missing-sender-address.json +0 -2
- package/test-vectors/catalog/negative/{multicast-auth-manifest-port-equals-port.json → multicast-auth-draft01-manifest-port.json} +1 -1
- package/test-vectors/catalog/negative/multicast-auth-duplicate-first-epoch.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-duplicate-kid.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-endpoint-auth-without-object-auth.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-endpoint-missing-bandwidth.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-manifest-timer-out-of-range.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-sender-address-on-ssm.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-shared-sg-port.json +73 -0
- package/test-vectors/catalog/negative/multicast-auth-version-1.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-version-3.json +0 -1
- package/test-vectors/catalog/negative/multicast-auth-version-missing.json +0 -1
- package/test-vectors/catalog/negative/multicast-endpoint-address-family-mismatch.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-host-name.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-leading-zero.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-ls32-leading-zero.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-mapped-family-mismatch.json +55 -0
- package/test-vectors/catalog/negative/multicast-endpoint-address-zone-id.json +55 -0
- package/test-vectors/catalog/positive/multicast-auth-asm-sender.json +0 -2
- package/test-vectors/catalog/{negative/multicast-auth-max-auth-delay-above-max.json → positive/multicast-auth-max-auth-delay-above-max-clamped.json} +0 -1
- package/test-vectors/catalog/{negative/multicast-auth-max-auth-delay-below-min.json → positive/multicast-auth-max-auth-delay-below-min-clamped.json} +0 -1
- package/test-vectors/catalog/positive/multicast-auth-max-auth-delay-string.json +55 -0
- package/test-vectors/catalog/positive/multicast-auth-rotation.json +0 -1
- package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +0 -1
- package/test-vectors/catalog/section-codes.json +8 -3
- package/test-vectors/catalog-multicast-auth-v1.json +0 -1
- package/test-vectors/catalog-validation.json +3 -3
- package/test-vectors/generate-bc-provenance-v2.mjs +94 -14
|
@@ -27,6 +27,20 @@ export interface MulticastTransportConfig {
|
|
|
27
27
|
plpId?: number;
|
|
28
28
|
serviceId?: number;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* The join is a protected flow (multicast-02 7.2.3): its bc-provenance
|
|
32
|
+
* records ride in band on this `port`, so a datagram whose first four octets
|
|
33
|
+
* are "MHM2" passes ahead of the packet_id read and the allow-list, and is
|
|
34
|
+
* never counted toward a packet_id. On an unprotected join it is an
|
|
35
|
+
* unparseable MMTP packet, as before.
|
|
36
|
+
*
|
|
37
|
+
* A protected join admits only datagrams whose reported sender is the
|
|
38
|
+
* flow's S (`sourceAddress`, or `senderAddress` on ASM), compared as IP
|
|
39
|
+
* addresses, before anything hashes them (multicast-02 7.2.7). A datagram
|
|
40
|
+
* with no reported sender is dropped, and a join that cannot report one
|
|
41
|
+
* (no S, or an ATSC 3.0 tuner) is declined `invalid-request`.
|
|
42
|
+
*/
|
|
43
|
+
protected?: boolean;
|
|
30
44
|
}
|
|
31
45
|
export type ResolvedMulticastTransport = 'native' | 'amt';
|
|
32
46
|
/**
|
|
@@ -123,7 +137,8 @@ export interface MulticastTransportStats {
|
|
|
123
137
|
* one (G, port, packet_id); the first sender whose packet is accepted owns
|
|
124
138
|
* the sub-flow until the next join, and every other sender is dropped here,
|
|
125
139
|
* before any gap, duplicate or FEC ledger sees it. A join or a silence
|
|
126
|
-
* failback releases the lock.
|
|
140
|
+
* failback releases the lock. On a protected join it also counts every
|
|
141
|
+
* datagram whose sender is not the flow's S, or is not reported.
|
|
127
142
|
*/
|
|
128
143
|
packetsDroppedForeignSender: number;
|
|
129
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multicast-transport.d.ts","sourceRoot":"","sources":["../src/multicast-transport.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAIL,KAAK,uBAAuB,EAC5B,KAAK,sBAAsB,EAE5B,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"multicast-transport.d.ts","sourceRoot":"","sources":["../src/multicast-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1263,6 +1263,9 @@ var AMTGatewayManager = class {
|
|
|
1263
1263
|
*/
|
|
1264
1264
|
async subscribe(config) {
|
|
1265
1265
|
const { key } = config;
|
|
1266
|
+
if (config.protected) {
|
|
1267
|
+
throw new Error("AMTGatewayManager refuses a protected join: it reports no per-datagram sender (multicast-02 7.2.7)");
|
|
1268
|
+
}
|
|
1266
1269
|
const keyStr = this.getKeyString(key);
|
|
1267
1270
|
if (this.subscriptions.has(keyStr)) {
|
|
1268
1271
|
console.log(`[AMT] Reusing existing subscription to ${keyStr}`);
|
|
@@ -1437,6 +1440,73 @@ var FEC_BLOCK_PROFILES2 = Object.freeze([
|
|
|
1437
1440
|
"iso-ssbg1-v1"
|
|
1438
1441
|
]);
|
|
1439
1442
|
|
|
1443
|
+
// ../mmt-base/dist/ip-address.js
|
|
1444
|
+
var DEC_OCTET = /^(?:0|[1-9]\d{0,2})$/;
|
|
1445
|
+
var H16 = /^[0-9A-Fa-f]{1,4}$/;
|
|
1446
|
+
function parseIpv4(text2) {
|
|
1447
|
+
const fields = text2.split(".");
|
|
1448
|
+
if (fields.length !== 4)
|
|
1449
|
+
return void 0;
|
|
1450
|
+
const octets = [];
|
|
1451
|
+
for (const field of fields) {
|
|
1452
|
+
if (!DEC_OCTET.test(field))
|
|
1453
|
+
return void 0;
|
|
1454
|
+
const value = Number(field);
|
|
1455
|
+
if (value > 255)
|
|
1456
|
+
return void 0;
|
|
1457
|
+
octets.push(value);
|
|
1458
|
+
}
|
|
1459
|
+
return octets;
|
|
1460
|
+
}
|
|
1461
|
+
function parseIpv6(text2) {
|
|
1462
|
+
const halves = text2.split("::");
|
|
1463
|
+
if (halves.length > 2)
|
|
1464
|
+
return void 0;
|
|
1465
|
+
const groupsOf = (part) => part === "" ? [] : part.split(":");
|
|
1466
|
+
const left = groupsOf(halves[0]);
|
|
1467
|
+
const right = halves.length === 2 ? groupsOf(halves[1]) : [];
|
|
1468
|
+
const words = [];
|
|
1469
|
+
const all = [...left, ...right];
|
|
1470
|
+
const last = halves.length === 2 && right.length === 0 ? -1 : all.length - 1;
|
|
1471
|
+
for (let index = 0; index < all.length; index++) {
|
|
1472
|
+
const group = all[index];
|
|
1473
|
+
if (index === last && group.includes(".")) {
|
|
1474
|
+
const v4 = parseIpv4(group);
|
|
1475
|
+
if (!v4)
|
|
1476
|
+
return void 0;
|
|
1477
|
+
words.push([v4[0] << 8 | v4[1], v4[2] << 8 | v4[3]]);
|
|
1478
|
+
} else if (H16.test(group)) {
|
|
1479
|
+
words.push([Number.parseInt(group, 16)]);
|
|
1480
|
+
} else {
|
|
1481
|
+
return void 0;
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
const leftWords = words.slice(0, left.length).flat();
|
|
1485
|
+
const rightWords = words.slice(left.length).flat();
|
|
1486
|
+
const missing = 8 - leftWords.length - rightWords.length;
|
|
1487
|
+
if (halves.length === 2 ? missing < 1 : missing !== 0)
|
|
1488
|
+
return void 0;
|
|
1489
|
+
const out = new Uint8Array(16);
|
|
1490
|
+
[...leftWords, ...new Array(missing).fill(0), ...rightWords].forEach((word, index) => {
|
|
1491
|
+
out[index * 2] = word >> 8;
|
|
1492
|
+
out[index * 2 + 1] = word & 255;
|
|
1493
|
+
});
|
|
1494
|
+
return out;
|
|
1495
|
+
}
|
|
1496
|
+
function parseIpAddressLiteral2(text2) {
|
|
1497
|
+
if (typeof text2 !== "string")
|
|
1498
|
+
return void 0;
|
|
1499
|
+
if (text2.includes(":"))
|
|
1500
|
+
return parseIpv6(text2);
|
|
1501
|
+
const v4 = parseIpv4(text2);
|
|
1502
|
+
return v4 ? Uint8Array.from(v4) : void 0;
|
|
1503
|
+
}
|
|
1504
|
+
function sameIpAddress(a, b) {
|
|
1505
|
+
const x = parseIpAddressLiteral2(a);
|
|
1506
|
+
const y = parseIpAddressLiteral2(b);
|
|
1507
|
+
return x !== void 0 && y !== void 0 && x.length === y.length && x.every((octet, index) => octet === y[index]);
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1440
1510
|
// ../mmt-base/dist/fec-bindings.js
|
|
1441
1511
|
var RUNTIME_FEC_RECEIVER2 = Object.freeze({
|
|
1442
1512
|
schemes: Object.freeze(["raptorq", "reed-solomon"]),
|
|
@@ -1444,6 +1514,17 @@ var RUNTIME_FEC_RECEIVER2 = Object.freeze({
|
|
|
1444
1514
|
overlays: true
|
|
1445
1515
|
});
|
|
1446
1516
|
|
|
1517
|
+
// ../mmt-manifest-verify/dist/bc-provenance-v2.js
|
|
1518
|
+
var BCPV2_HEADER_LENGTH = 68;
|
|
1519
|
+
var BCPV2_SIGNATURE_LENGTH = 64;
|
|
1520
|
+
var BCPV2_MIN_RECORD_LENGTH = BCPV2_HEADER_LENGTH + 32 + BCPV2_SIGNATURE_LENGTH;
|
|
1521
|
+
var text = new TextEncoder();
|
|
1522
|
+
var MAGIC = Uint8Array.from([77, 72, 77, 50]);
|
|
1523
|
+
function isBcpV2RecordCandidate(datagram) {
|
|
1524
|
+
return datagram.byteLength >= 4 && datagram[0] === MAGIC[0] && datagram[1] === MAGIC[1] && datagram[2] === MAGIC[2] && datagram[3] === MAGIC[3];
|
|
1525
|
+
}
|
|
1526
|
+
var SIGNING_DOMAIN = text.encode("mcast-manifest-v2\0");
|
|
1527
|
+
|
|
1447
1528
|
// src/multicast-transport.ts
|
|
1448
1529
|
var JOIN_SUCCEEDED = Object.freeze({ ok: true });
|
|
1449
1530
|
function providerErrorOf(error) {
|
|
@@ -1545,6 +1626,11 @@ var MulticastTransport = class {
|
|
|
1545
1626
|
// per packet once a count outgrows the small-integer range.
|
|
1546
1627
|
#acceptedBytesByPacketId = /* @__PURE__ */ new Map();
|
|
1547
1628
|
#packetIds = null;
|
|
1629
|
+
#protected = false;
|
|
1630
|
+
// A protected join's S, and the last sender spelling that matched it, so a
|
|
1631
|
+
// matching sender parses once per spelling rather than per datagram.
|
|
1632
|
+
#protectedSource = void 0;
|
|
1633
|
+
#matchedSource = void 0;
|
|
1548
1634
|
// The sender S this join's accepted packets came from, once known; see
|
|
1549
1635
|
// packetsDroppedForeignSender. Cleared by every join and by a silence
|
|
1550
1636
|
// failback, so a replacement publisher is not locked out.
|
|
@@ -1596,6 +1682,11 @@ var MulticastTransport = class {
|
|
|
1596
1682
|
return this.#declined(generation, "unavailable");
|
|
1597
1683
|
}
|
|
1598
1684
|
let failure = "invalid-request";
|
|
1685
|
+
const protectedSource = config.protected === true ? config.sourceAddress ?? config.senderAddress : void 0;
|
|
1686
|
+
if (config.protected === true && (protectedSource === void 0 || config.atsc3)) {
|
|
1687
|
+
console.warn("[MulticastTransport] protected join refused: the path reports no per-datagram sender to check against S");
|
|
1688
|
+
return this.#declined(generation, "invalid-request");
|
|
1689
|
+
}
|
|
1599
1690
|
try {
|
|
1600
1691
|
const packetIds = config.packetIds?.length ? new Set(config.packetIds) : null;
|
|
1601
1692
|
console.log(
|
|
@@ -1631,7 +1722,7 @@ var MulticastTransport = class {
|
|
|
1631
1722
|
this.#subscription = subscription;
|
|
1632
1723
|
const live = () => !this.#disposed && generation === this.#joinGeneration;
|
|
1633
1724
|
const anySource = !config.sourceAddress && !config.senderAddress && !config.atsc3;
|
|
1634
|
-
const packetListener = !anySource && subscriptionDeliversPacketBatches(subscription) ? {
|
|
1725
|
+
const packetListener = !anySource && protectedSource === void 0 && subscriptionDeliversPacketBatches(subscription) ? {
|
|
1635
1726
|
type: "packets",
|
|
1636
1727
|
listener: (event) => {
|
|
1637
1728
|
if (!live()) return;
|
|
@@ -1646,6 +1737,9 @@ var MulticastTransport = class {
|
|
|
1646
1737
|
};
|
|
1647
1738
|
this.#packetListener = packetListener;
|
|
1648
1739
|
this.#packetIds = packetIds;
|
|
1740
|
+
this.#protected = config.protected === true;
|
|
1741
|
+
this.#protectedSource = protectedSource;
|
|
1742
|
+
this.#matchedSource = void 0;
|
|
1649
1743
|
this.#providerFilter = {
|
|
1650
1744
|
acknowledged: packetIds,
|
|
1651
1745
|
sent: 0,
|
|
@@ -1730,7 +1824,8 @@ var MulticastTransport = class {
|
|
|
1730
1824
|
}
|
|
1731
1825
|
/**
|
|
1732
1826
|
* One packet from the subscription: filter, count, and hand it to the
|
|
1733
|
-
* callback. Returns whether it was delivered
|
|
1827
|
+
* callback. Returns whether it was delivered as liveness (a delivered record
|
|
1828
|
+
* candidate is not); the caller notes liveness.
|
|
1734
1829
|
*/
|
|
1735
1830
|
#deliver(detail, sourceAddress) {
|
|
1736
1831
|
const packet = normalizeBytesEventDetail(detail);
|
|
@@ -1739,8 +1834,12 @@ var MulticastTransport = class {
|
|
|
1739
1834
|
return false;
|
|
1740
1835
|
}
|
|
1741
1836
|
if (!this.#acceptPacket(packet, sourceAddress)) return false;
|
|
1837
|
+
const liveness = !this.#isRecordCandidate(packet);
|
|
1742
1838
|
this.#onPacket(packet, this.#context);
|
|
1743
|
-
return
|
|
1839
|
+
return liveness;
|
|
1840
|
+
}
|
|
1841
|
+
#isRecordCandidate(packet) {
|
|
1842
|
+
return this.#protected && isBcpV2RecordCandidate(packet);
|
|
1744
1843
|
}
|
|
1745
1844
|
/**
|
|
1746
1845
|
* One `packets` event. Each packet is delivered as a `bytes` event would
|
|
@@ -1788,8 +1887,9 @@ var MulticastTransport = class {
|
|
|
1788
1887
|
if (this.#disposed) return;
|
|
1789
1888
|
const packet = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
1790
1889
|
if (!this.#acceptPacket(packet, sourceAddress)) return;
|
|
1890
|
+
const liveness = !this.#isRecordCandidate(packet);
|
|
1791
1891
|
this.#onPacket(packet, context);
|
|
1792
|
-
this.#resetWatchdog();
|
|
1892
|
+
if (liveness) this.#resetWatchdog();
|
|
1793
1893
|
}
|
|
1794
1894
|
confirmVideo() {
|
|
1795
1895
|
this.#videoConfirmed = true;
|
|
@@ -2098,17 +2198,32 @@ var MulticastTransport = class {
|
|
|
2098
2198
|
this.#resolvedTransport = void 0;
|
|
2099
2199
|
this.#delivery = void 0;
|
|
2100
2200
|
this.#packetIds = null;
|
|
2201
|
+
this.#protected = false;
|
|
2202
|
+
this.#protectedSource = void 0;
|
|
2203
|
+
this.#matchedSource = void 0;
|
|
2101
2204
|
this.#providerFilter = null;
|
|
2102
2205
|
this.#context = void 0;
|
|
2103
2206
|
this.#withdrawnPacketIds.clear();
|
|
2104
2207
|
}
|
|
2105
2208
|
/** The ingress filter; an accepted packet is counted here, once. */
|
|
2106
2209
|
#acceptPacket(packet, sourceAddress) {
|
|
2107
|
-
const
|
|
2210
|
+
const source = this.#protectedSource;
|
|
2211
|
+
if (source !== void 0 && (sourceAddress === void 0 || sourceAddress !== this.#matchedSource)) {
|
|
2212
|
+
if (sourceAddress === void 0 || !sameIpAddress(sourceAddress, source)) {
|
|
2213
|
+
this.#stats.packetsDroppedForeignSender++;
|
|
2214
|
+
return false;
|
|
2215
|
+
}
|
|
2216
|
+
this.#matchedSource = sourceAddress;
|
|
2217
|
+
}
|
|
2218
|
+
const owner = source === void 0 ? this.#lockedTo?.() ?? this.#sender : void 0;
|
|
2108
2219
|
if (sourceAddress !== void 0 && owner !== void 0 && sourceAddress !== owner) {
|
|
2109
2220
|
this.#stats.packetsDroppedForeignSender++;
|
|
2110
2221
|
return false;
|
|
2111
2222
|
}
|
|
2223
|
+
if (this.#isRecordCandidate(packet)) {
|
|
2224
|
+
this.#countAccepted(packet, null, void 0);
|
|
2225
|
+
return true;
|
|
2226
|
+
}
|
|
2112
2227
|
const packetId = readMMTPPacketId(packet);
|
|
2113
2228
|
if (packetId === null) {
|
|
2114
2229
|
if (!this.#packetIds) {
|