@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.
Files changed (101) hide show
  1. package/README.md +9 -7
  2. package/dist/browser-runtime.js +6972 -6693
  3. package/dist/browser-runtime.js.map +4 -4
  4. package/dist/carp-catalog.d.ts +7 -7
  5. package/dist/carp-catalog.d.ts.map +1 -1
  6. package/dist/carp-catalog.js +65 -230
  7. package/dist/carp-catalog.js.map +3 -3
  8. package/dist/catalog-fec-params.js.map +1 -1
  9. package/dist/catalog-network-source.js.map +1 -1
  10. package/dist/delivery-catalog.js +3 -0
  11. package/dist/delivery-catalog.js.map +2 -2
  12. package/dist/delta-fallback-config.js.map +1 -1
  13. package/dist/fec-manager.d.ts +25 -1
  14. package/dist/fec-manager.d.ts.map +1 -1
  15. package/dist/fec-manager.js +208 -15
  16. package/dist/fec-manager.js.map +2 -2
  17. package/dist/fec-state.js.map +1 -1
  18. package/dist/fec-worker-setup.js.map +1 -1
  19. package/dist/held-layer-admission.d.ts +8 -0
  20. package/dist/held-layer-admission.d.ts.map +1 -1
  21. package/dist/held-layer-admission.js +22 -1
  22. package/dist/held-layer-admission.js.map +2 -2
  23. package/dist/iso-block-locator.js.map +1 -1
  24. package/dist/mfu-reassembler.js.map +1 -1
  25. package/dist/mmtp-container-parser.js.map +1 -1
  26. package/dist/mmtp-container-parser.no-modules.js +146 -332
  27. package/dist/mmtp-container-parser.no-modules.js.map +4 -4
  28. package/dist/mmtp-decode-pipeline.js.map +1 -1
  29. package/dist/mmtp-fec-session.d.ts.map +1 -1
  30. package/dist/mmtp-fec-session.js +61 -15
  31. package/dist/mmtp-fec-session.js.map +3 -3
  32. package/dist/mmtp-router.d.ts +11 -6
  33. package/dist/mmtp-router.d.ts.map +1 -1
  34. package/dist/mmtp-router.js +47 -10
  35. package/dist/mmtp-router.js.map +3 -3
  36. package/dist/multicast-auth-catalog.d.ts +8 -8
  37. package/dist/multicast-auth-catalog.d.ts.map +1 -1
  38. package/dist/multicast-auth-catalog.js +171 -75
  39. package/dist/multicast-auth-catalog.js.map +4 -4
  40. package/dist/multicast-input.d.ts +5 -5
  41. package/dist/multicast-input.d.ts.map +1 -1
  42. package/dist/multicast-input.js +126 -49
  43. package/dist/multicast-input.js.map +3 -3
  44. package/dist/multicast-manager.d.ts +11 -4
  45. package/dist/multicast-manager.d.ts.map +1 -1
  46. package/dist/multicast-manager.js +7914 -7659
  47. package/dist/multicast-manager.js.map +4 -4
  48. package/dist/multicast-transport.d.ts +16 -1
  49. package/dist/multicast-transport.d.ts.map +1 -1
  50. package/dist/multicast-transport.js +120 -5
  51. package/dist/multicast-transport.js.map +4 -4
  52. package/dist/multicast-unwrap.js +2 -2
  53. package/dist/multicast-unwrap.js.map +2 -2
  54. package/dist/no-modules.js +100 -288
  55. package/dist/no-modules.js.map +4 -4
  56. package/dist/repair-fetch.js.map +1 -1
  57. package/dist/signaling.js.map +1 -1
  58. package/dist/timestamp-codec.js.map +1 -1
  59. package/dist/wasm-mfu-reassembler.js.map +1 -1
  60. package/dist/wasm-mmtp-container-parser.js.map +1 -1
  61. package/package.json +5 -5
  62. package/schemas/catalog.schema.json +15 -7
  63. package/src/carp-catalog.ts +14 -13
  64. package/src/fec-manager.ts +89 -14
  65. package/src/held-layer-admission.ts +38 -1
  66. package/src/mmtp-fec-session.ts +20 -12
  67. package/src/mmtp-router.ts +65 -16
  68. package/src/multicast-auth-catalog.ts +43 -36
  69. package/src/multicast-input.ts +28 -8
  70. package/src/multicast-manager.ts +38 -34
  71. package/src/multicast-transport.ts +74 -7
  72. package/test-vectors/bc-provenance-v2.json +614 -175
  73. package/test-vectors/catalog/README.md +24 -8
  74. package/test-vectors/catalog/negative/multicast-auth-asm-missing-sender-address.json +0 -2
  75. package/test-vectors/catalog/negative/{multicast-auth-manifest-port-equals-port.json → multicast-auth-draft01-manifest-port.json} +1 -1
  76. package/test-vectors/catalog/negative/multicast-auth-duplicate-first-epoch.json +0 -1
  77. package/test-vectors/catalog/negative/multicast-auth-duplicate-kid.json +0 -1
  78. package/test-vectors/catalog/negative/multicast-auth-endpoint-auth-without-object-auth.json +0 -1
  79. package/test-vectors/catalog/negative/multicast-auth-endpoint-missing-bandwidth.json +0 -1
  80. package/test-vectors/catalog/negative/multicast-auth-manifest-timer-out-of-range.json +0 -1
  81. package/test-vectors/catalog/negative/multicast-auth-sender-address-on-ssm.json +0 -1
  82. package/test-vectors/catalog/negative/multicast-auth-shared-sg-port.json +73 -0
  83. package/test-vectors/catalog/negative/multicast-auth-version-1.json +0 -1
  84. package/test-vectors/catalog/negative/multicast-auth-version-3.json +0 -1
  85. package/test-vectors/catalog/negative/multicast-auth-version-missing.json +0 -1
  86. package/test-vectors/catalog/negative/multicast-endpoint-address-family-mismatch.json +55 -0
  87. package/test-vectors/catalog/negative/multicast-endpoint-address-host-name.json +55 -0
  88. package/test-vectors/catalog/negative/multicast-endpoint-address-leading-zero.json +55 -0
  89. package/test-vectors/catalog/negative/multicast-endpoint-address-ls32-leading-zero.json +55 -0
  90. package/test-vectors/catalog/negative/multicast-endpoint-address-mapped-family-mismatch.json +55 -0
  91. package/test-vectors/catalog/negative/multicast-endpoint-address-zone-id.json +55 -0
  92. package/test-vectors/catalog/positive/multicast-auth-asm-sender.json +0 -2
  93. 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
  94. 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
  95. package/test-vectors/catalog/positive/multicast-auth-max-auth-delay-string.json +55 -0
  96. package/test-vectors/catalog/positive/multicast-auth-rotation.json +0 -1
  97. package/test-vectors/catalog/positive/multicast-draft01-7-2-6-example.json +0 -1
  98. package/test-vectors/catalog/section-codes.json +8 -3
  99. package/test-vectors/catalog-multicast-auth-v1.json +0 -1
  100. package/test-vectors/catalog-validation.json +3 -3
  101. 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":"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"}
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; the caller notes liveness.
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 true;
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 owner = this.#lockedTo?.() ?? this.#sender;
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) {