@blockcast/mmt-container 2.1.0-main.36792a9d6614 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7457,33 +7457,11 @@ var AdaptiveBitrateController = class {
7457
7457
  };
7458
7458
 
7459
7459
  // node_modules/@blockcast/mmt-base/dist/mmtp.js
7460
- var MMTP_HEADER_SIZE2 = 12;
7461
7460
  var MPU_HEADER_SIZE2 = 8;
7462
7461
  var MPU_LENGTH_FIELD_SIZE2 = 2;
7463
7462
  var MPU_HEADER_REMAINDER_SIZE2 = MPU_HEADER_SIZE2 - MPU_LENGTH_FIELD_SIZE2;
7464
7463
  var MMTP_SIGNALING_PACKET_ID2 = 0;
7465
7464
  var MMTP_PACKET_ID_MAX2 = 65535;
7466
- function readMMTPPacketId2(buffer) {
7467
- if (buffer.length < MMTP_HEADER_SIZE2)
7468
- return null;
7469
- const flags = buffer[0];
7470
- if ((flags >> 6 & 3) !== 0)
7471
- return null;
7472
- let offset = MMTP_HEADER_SIZE2;
7473
- if ((flags & 32) !== 0) {
7474
- if (offset + 4 > buffer.length)
7475
- return null;
7476
- offset += 4;
7477
- }
7478
- if ((flags & 2) !== 0) {
7479
- if (offset + 4 > buffer.length)
7480
- return null;
7481
- const length = buffer[offset + 2] << 8 | buffer[offset + 3];
7482
- if (offset + 4 + length > buffer.length)
7483
- return null;
7484
- }
7485
- return buffer[2] << 8 | buffer[3];
7486
- }
7487
7465
 
7488
7466
  // node_modules/@blockcast/mmt-base/dist/net-constants.js
7489
7467
  var DEFAULT_AMT_RELAY_PORT2 = 2268;
@@ -8469,205 +8447,6 @@ var TransportManager = class {
8469
8447
  };
8470
8448
  var transportManager = new TransportManager();
8471
8449
 
8472
- // node_modules/@blockcast/mmt-transport/dist/multicast-receiver-gateway.js
8473
- var REGISTRY = /* @__PURE__ */ Symbol.for("@blockcast/mmt-transport/native-provider-registry/v1");
8474
- var USER_AGENT_VERIFIED = /* @__PURE__ */ Symbol.for("@blockcast/mmt-transport/user-agent-verified/v1");
8475
- var INTEGRITY_SCHEME = "manifest-ed25519-2";
8476
- var MulticastError = class extends Error {
8477
- code;
8478
- constructor(code, message, cause) {
8479
- super(message, cause === void 0 ? void 0 : { cause });
8480
- this.name = "MulticastError";
8481
- this.code = code;
8482
- }
8483
- };
8484
- function datagramsOf(chunk) {
8485
- const list = Array.isArray(chunk) ? chunk : chunk?.datagrams ?? [];
8486
- const out = [];
8487
- for (const d of list) {
8488
- const data = d instanceof Uint8Array || d instanceof ArrayBuffer ? d : d?.data;
8489
- if (data instanceof Uint8Array)
8490
- out.push(data);
8491
- else if (data instanceof ArrayBuffer)
8492
- out.push(new Uint8Array(data));
8493
- }
8494
- return out;
8495
- }
8496
- function reasonOf(value) {
8497
- return typeof value === "object" && value !== null && "reason" in value ? value.reason : value;
8498
- }
8499
- function registry() {
8500
- const g = globalThis;
8501
- if (g[REGISTRY] === void 0) {
8502
- const providers = /* @__PURE__ */ new WeakSet();
8503
- const byScope = /* @__PURE__ */ new WeakMap();
8504
- Object.defineProperty(g, REGISTRY, {
8505
- value: Object.freeze({
8506
- isProvider: (x) => typeof x === "object" && x !== null && providers.has(x),
8507
- providerFor: (scope) => {
8508
- let provider = byScope.get(scope);
8509
- if (provider === void 0) {
8510
- provider = createProvider(scope);
8511
- providers.add(provider);
8512
- byScope.set(scope, provider);
8513
- }
8514
- return provider;
8515
- }
8516
- }),
8517
- writable: false,
8518
- configurable: false,
8519
- enumerable: false
8520
- });
8521
- }
8522
- return g[REGISTRY];
8523
- }
8524
- function resolveMulticastGateway(scope = globalThis) {
8525
- const s = scope;
8526
- if (typeof s.MulticastReceiver === "function")
8527
- return registry().providerFor(scope);
8528
- if (typeof s.multicast?.subscribe === "function")
8529
- return s.multicast;
8530
- return void 0;
8531
- }
8532
- function isUserAgentVerifiedGateway(gateway) {
8533
- return registry().isProvider(gateway);
8534
- }
8535
- function userAgentVerifiedIngress(ingress, gateway) {
8536
- if (isUserAgentVerifiedGateway(gateway))
8537
- return { ...ingress, admittedBy: USER_AGENT_VERIFIED };
8538
- if (!("admittedBy" in ingress))
8539
- return ingress;
8540
- const { admittedBy: _, ...rest } = ingress;
8541
- return rest;
8542
- }
8543
- function unsupported(message, cause) {
8544
- return new MulticastError("capability-unsupported", message, cause);
8545
- }
8546
- function createProvider(scope) {
8547
- const Receiver = scope.MulticastReceiver;
8548
- let gate = null;
8549
- return {
8550
- capabilities: () => Promise.resolve({ consumeModes: ["bytes"] }),
8551
- subscribe: async (config) => {
8552
- const c = config;
8553
- if (c.consume !== "bytes")
8554
- throw unsupported(`consume mode ${String(c.consume)} is not supported`);
8555
- const origin = c.origin ?? "ip-multicast";
8556
- if (origin !== "ip-multicast" && !(origin === "amt" && c.discovery === "driad")) {
8557
- throw unsupported(`origin ${String(origin)} is not supported by MulticastReceiver`);
8558
- }
8559
- if (c.relay !== void 0)
8560
- throw unsupported("MulticastReceiver picks its own AMT relay");
8561
- if (!c.source)
8562
- throw unsupported("MulticastReceiver needs an SSM source");
8563
- if (c.senderAddress !== void 0 && c.senderAddress !== c.source) {
8564
- throw unsupported("MulticastReceiver filters by source only");
8565
- }
8566
- const options = { sourceAddress: c.source, groupAddress: c.group, localPort: c.port };
8567
- if (gate !== null)
8568
- await gate;
8569
- let rx;
8570
- try {
8571
- rx = new Receiver(options);
8572
- } catch (error) {
8573
- throw unsupported("MulticastReceiver refused the request", error);
8574
- }
8575
- const opened = rx.opened;
8576
- if (gate === null)
8577
- gate = opened.then(() => void 0, () => void 0);
8578
- return openSubscription(rx, opened, options, c.packetIds);
8579
- }
8580
- };
8581
- }
8582
- async function openSubscription(rx, openedPromise, options, packetIds) {
8583
- let opened;
8584
- try {
8585
- opened = await openedPromise;
8586
- } catch (error) {
8587
- throw new MulticastError("subscription-failed", "MulticastReceiver did not open", error);
8588
- }
8589
- if (rx.integrityScheme !== INTEGRITY_SCHEME) {
8590
- await rx.close();
8591
- throw unsupported(`integrity scheme ${String(rx.integrityScheme)} is not ${INTEGRITY_SCHEME}`);
8592
- }
8593
- const events = new EventTarget();
8594
- let state = "connected";
8595
- let filter = packetIds?.length ? new Set(packetIds) : null;
8596
- let closing = false;
8597
- const setState = (next) => {
8598
- if (state === next)
8599
- return;
8600
- state = next;
8601
- events.dispatchEvent(new CustomEvent("state", { detail: next }));
8602
- };
8603
- const sourceAddress = options.sourceAddress;
8604
- const subscription = {
8605
- id: `${options.sourceAddress}|${options.groupAddress}|${options.localPort}`,
8606
- get state() {
8607
- return state;
8608
- },
8609
- delivery: "datagram",
8610
- eventTypes: Object.freeze(["bytes", "packets", "state", "error"]),
8611
- setPacketIds(ids) {
8612
- filter = ids.length ? new Set(ids) : null;
8613
- },
8614
- addEventListener: events.addEventListener.bind(events),
8615
- removeEventListener: events.removeEventListener.bind(events),
8616
- async unsubscribe() {
8617
- closing = true;
8618
- await rx.close();
8619
- setState("closed");
8620
- }
8621
- };
8622
- void (async () => {
8623
- const reader = opened.readable.getReader();
8624
- try {
8625
- for (; ; ) {
8626
- const { value, done } = await reader.read();
8627
- if (done)
8628
- break;
8629
- const packets = [];
8630
- for (const data of datagramsOf(value)) {
8631
- if (filter !== null) {
8632
- const id = readMMTPPacketId2(data);
8633
- if (id === null || !filter.has(id))
8634
- continue;
8635
- }
8636
- const copy = data.slice().buffer;
8637
- packets.push(copy);
8638
- events.dispatchEvent(Object.assign(new CustomEvent("bytes", { detail: copy }), { sourceAddress }));
8639
- }
8640
- if (packets.length > 0)
8641
- events.dispatchEvent(new CustomEvent("packets", { detail: packets }));
8642
- }
8643
- } catch {
8644
- }
8645
- })();
8646
- void rx.closed.then((value) => {
8647
- const reason = reasonOf(value);
8648
- if (!closing) {
8649
- if (reason === "consent-withdrawn") {
8650
- events.dispatchEvent(new CustomEvent("error", {
8651
- detail: new MulticastError("origin-not-trusted", "multicast consent withdrawn")
8652
- }));
8653
- } else if (reason === "oversubscribed" || reason === "network") {
8654
- events.dispatchEvent(new CustomEvent("error", {
8655
- detail: new MulticastError("subscription-failed", `MulticastReceiver closed: ${reason}`)
8656
- }));
8657
- }
8658
- }
8659
- setState("closed");
8660
- }, (error) => {
8661
- if (!closing) {
8662
- events.dispatchEvent(new CustomEvent("error", {
8663
- detail: new MulticastError("subscription-failed", "MulticastReceiver failed", error)
8664
- }));
8665
- }
8666
- setState("closed");
8667
- });
8668
- return subscription;
8669
- }
8670
-
8671
8450
  // node_modules/@blockcast/mmt-transport/dist/moqt-priority.js
8672
8451
  var MAX_MOQT_PRIORITY = 255;
8673
8452
  function moqtPriority(value, field) {
@@ -8954,9 +8733,9 @@ function validateTemplatePair(mediaUriTemplate, mediaObjectTemplate, path) {
8954
8733
  }
8955
8734
  function validateMmtpDashTemplate(template, path) {
8956
8735
  const variables = [...template.matchAll(TEMPLATE_VARIABLE)].map((match) => match[1]);
8957
- const unsupported2 = variables.find((variable) => variable !== "Number" && variable !== "RepresentationID");
8958
- if (unsupported2 !== void 0) {
8959
- throw new Error(`${path} contains unsupported MMTP-backed DASH template variable $${unsupported2}$`);
8736
+ const unsupported = variables.find((variable) => variable !== "Number" && variable !== "RepresentationID");
8737
+ if (unsupported !== void 0) {
8738
+ throw new Error(`${path} contains unsupported MMTP-backed DASH template variable $${unsupported}$`);
8960
8739
  }
8961
8740
  if (variables.filter((variable) => variable === "Number").length !== 1) {
8962
8741
  throw new Error(`${path} must contain exactly one $Number$ for MMTP-backed DASH`);
@@ -17319,17 +17098,17 @@ var FECManager = class _FECManager {
17319
17098
 
17320
17099
  // src/mfu-reassembly-policy.ts
17321
17100
  function validateReliableMoqOptionShape(value) {
17322
- const unsupported2 = Object.keys(value).filter(
17101
+ const unsupported = Object.keys(value).filter(
17323
17102
  (key) => key !== "transport" && key !== "startsAtRandomAccessGroup"
17324
17103
  );
17325
- if (unsupported2.length > 0) {
17326
- if (unsupported2.includes("maxRacingGroups")) {
17104
+ if (unsupported.length > 0) {
17105
+ if (unsupported.includes("maxRacingGroups")) {
17327
17106
  throw new Error(
17328
17107
  "[MFU reassembly] maxRacingGroups was removed; reliable MoQ completion is transport-owned"
17329
17108
  );
17330
17109
  }
17331
17110
  throw new Error(
17332
- `[MFU reassembly] unsupported reliable MoQ option(s): ${unsupported2.join(", ")}`
17111
+ `[MFU reassembly] unsupported reliable MoQ option(s): ${unsupported.join(", ")}`
17333
17112
  );
17334
17113
  }
17335
17114
  const startsAtRandomAccessGroup = value["startsAtRandomAccessGroup"];
@@ -17373,12 +17152,12 @@ function assertValidMfuReassemblyPolicy(policy) {
17373
17152
  return;
17374
17153
  }
17375
17154
  if (value["transport"] === "datagram") {
17376
- const unsupported2 = Object.keys(value).filter(
17155
+ const unsupported = Object.keys(value).filter(
17377
17156
  (key) => key !== "transport" && key !== "deadlineMs"
17378
17157
  );
17379
- if (unsupported2.length > 0) {
17158
+ if (unsupported.length > 0) {
17380
17159
  throw new Error(
17381
- `[MFU reassembly] unsupported datagram option(s): ${unsupported2.join(", ")}`
17160
+ `[MFU reassembly] unsupported datagram option(s): ${unsupported.join(", ")}`
17382
17161
  );
17383
17162
  }
17384
17163
  assertValidDatagramDeadline(value["deadlineMs"]);
@@ -23800,11 +23579,10 @@ var MmtpRouter = class {
23800
23579
  if (!entry) return;
23801
23580
  entry.receiver.release();
23802
23581
  entry.protected = false;
23803
- entry.userAgent = false;
23804
23582
  this.#assistBlocks.clear();
23805
23583
  this.#assistFailures.clear();
23806
23584
  }
23807
- /** Packets of a track a protected flow lists, dropped unread: a MoQ copy (duplicate, overflow, or listed by more than one flow) or a multicast source datagram that names no flow, of a track a user-agent-admitted flow lists. */
23585
+ /** MoQ packets of a track a protected flow lists, dropped on its unicast path: duplicate, overflow, or listed by more than one flow. */
23808
23586
  get unadmittedListedDropCount() {
23809
23587
  return this.#unadmittedListedDrops;
23810
23588
  }
@@ -23845,13 +23623,6 @@ var MmtpRouter = class {
23845
23623
  }
23846
23624
  return false;
23847
23625
  }
23848
- /** Whether a protected flow the user agent admitted lists `packetId`. */
23849
- #userAgentGoverns(packetId) {
23850
- for (const entry of this.#provenance.values()) {
23851
- if (entry.protected && entry.userAgent && ingressHasPacketId(entry.ingress, packetId)) return true;
23852
- }
23853
- return false;
23854
- }
23855
23626
  /**
23856
23627
  * A MoQ repair symbol no protected flow lists, owned by a source track one
23857
23628
  * does: its FEC instance is governed (7.2.7 step 2) and takes only admitted
@@ -23942,7 +23713,7 @@ var MmtpRouter = class {
23942
23713
  fec.cancelBlockTimeout(blockStart, ownerPacketId, catalogTrackName);
23943
23714
  fec.countRecovery(ownerPacketId, blockStart, catalogTrackName);
23944
23715
  fec.markBlockCompleted(blockStart, ownerPacketId, catalogTrackName);
23945
- }, true)) {
23716
+ })) {
23946
23717
  this.#unlistedAssistedRecoveries++;
23947
23718
  this.#assistBlocks.delete(key);
23948
23719
  return;
@@ -25098,12 +24869,6 @@ var MmtpRouter = class {
25098
24869
  debugRouter(`[MmtpRouter] Dropping multicast packet pid=${info.packetId}: flow ${ingress.flow} has no receiver`);
25099
24870
  return;
25100
24871
  }
25101
- if (ingress.admittedBy === USER_AGENT_VERIFIED) {
25102
- this.#noteFlowAdmitted(ingress.flow);
25103
- protectedFlow.userAgent = true;
25104
- this.#processMMTP(packet, source, true, ingress, overlapCopy);
25105
- return;
25106
- }
25107
24872
  const { verdict } = protectedFlow.receiver.onDatagram(packet, "multicast");
25108
24873
  if (verdict === "admitted") {
25109
24874
  this.#noteFlowAdmitted(ingress.flow);
@@ -25121,11 +24886,6 @@ var MmtpRouter = class {
25121
24886
  return;
25122
24887
  }
25123
24888
  }
25124
- const flowless = source === "multicast" && !manifestAdmitted && ingress?.flow === void 0;
25125
- if (flowless && !info.isRepair && this.#userAgentGoverns(info.packetId)) {
25126
- this.#unadmittedListedDrops++;
25127
- return;
25128
- }
25129
24889
  if (info.isRepair) {
25130
24890
  const overlay = this.#overlayRepairTarget(info.packetId, catalogTrackNameForPacket(ingress, info.packetId));
25131
24891
  if (overlay !== void 0) {
@@ -25143,7 +24903,7 @@ var MmtpRouter = class {
25143
24903
  );
25144
24904
  if (!repair) return;
25145
24905
  if (ownerPacketId != null && this.#fecManager) {
25146
- if ((flowless && this.#userAgentGoverns(ownerPacketId) || source === "moq" && !manifestAdmitted) && this.#setAsideUnlistedRepair(ownerPacketId, catalogTrackNameForPacket(ingress, ownerPacketId), repair)) return;
24906
+ if (source === "moq" && !manifestAdmitted && this.#setAsideUnlistedRepair(ownerPacketId, catalogTrackNameForPacket(ingress, ownerPacketId), repair)) return;
25147
24907
  this.#repairPidCounts[info.packetId] = (this.#repairPidCounts[info.packetId] || 0) + 1;
25148
24908
  const count = this.#repairPidCounts[info.packetId];
25149
24909
  if (count <= 2 || count % 500 === 0) {
@@ -25722,7 +25482,7 @@ var MmtpRouter = class {
25722
25482
  }
25723
25483
  // ── Private: FEC recovery routing ───────────────────────────────
25724
25484
  /** Route WASM-recovered block through appropriate path based on container kind. */
25725
- #routeRecoveredBlock(blockId, recovered, ownerPacketId, catalogTrackName, complete, assisted = false) {
25485
+ #routeRecoveredBlock(blockId, recovered, ownerPacketId, catalogTrackName, complete) {
25726
25486
  const packetSymbolSize = this.#symbolSizeForPacket(ownerPacketId);
25727
25487
  if (ownerPacketId === void 0) {
25728
25488
  throw new Error("[MmtpRouter] a recovered FEC block needs its owner packetId to read its fec.blockProfile");
@@ -25739,7 +25499,7 @@ var MmtpRouter = class {
25739
25499
  ownerPacketId,
25740
25500
  blockProfile
25741
25501
  });
25742
- return this.#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete, assisted);
25502
+ return this.#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete);
25743
25503
  }
25744
25504
  /**
25745
25505
  * A recovered source packet of a protected flow is admitted on its own
@@ -25751,24 +25511,9 @@ var MmtpRouter = class {
25751
25511
  * recovered packets is refused is unrecovered (7.2.7): its caller leaves it
25752
25512
  * open, so it reaches its FEC deadline and fails by class. Always true
25753
25513
  * outside a protected flow.
25754
- *
25755
- * On a flow the user agent admitted, the live decoder's recoveries are kept
25756
- * without a record: while the flow is protected that decoder takes only
25757
- * symbols the user agent or a record verified (a flow-less multicast
25758
- * datagram of a listed track is dropped or set aside in #processMMTP), so
25759
- * what it recovers is as verified as they are. An `assisted` (scratch-decoder) recovery mixes in
25760
- * unlisted MoQ repair and still needs a record.
25761
- * ponytail: per-flow flag; per-block provenance only if a protected flow
25762
- * ever mixes verified and unverified live inputs.
25763
- * ponytail: a worker frame computed before the protection reset can still
25764
- * arrive after it (frames carry no epoch); its inputs are MoQ copies read
25765
- * and played before protection, so it admits nothing new. Drop pre-reset
25766
- * frames by epoch only if pre-protection input ever matters.
25767
- */
25768
- #routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete, assisted = false) {
25769
- const entry = ownerPacketId == null ? void 0 : this.#provenanceFor(ownerPacketId, catalogTrackName);
25770
- const receiver = entry === void 0 || entry === "ambiguous" ? entry : entry.receiver;
25771
- const userAgent = !assisted && entry !== void 0 && entry !== "ambiguous" && entry.protected === true && entry.userAgent === true;
25514
+ */
25515
+ #routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete) {
25516
+ const receiver = ownerPacketId == null ? void 0 : this.#provenanceFor(ownerPacketId, catalogTrackName);
25772
25517
  let recovered = true;
25773
25518
  if (receiver) {
25774
25519
  const parsed = this.#stream(ownerPacketId, catalogTrackName).duplicates.parsedSymbols;
@@ -25780,8 +25525,6 @@ var MmtpRouter = class {
25780
25525
  let admitted = false;
25781
25526
  if (receiver === "ambiguous") {
25782
25527
  this.#ambiguousRecoveredDrops++;
25783
- } else if (userAgent) {
25784
- admitted = true;
25785
25528
  } else {
25786
25529
  const wire = new Uint8Array(sym.rawSymbol.byteLength + 4);
25787
25530
  wire.set(sym.rawSymbol);
@@ -25809,12 +25552,12 @@ var MmtpRouter = class {
25809
25552
  catalogTrackName === void 0 || !byName ? byName?.values() : byName.has(catalogTrackName) ? [byName.get(catalogTrackName)] : []
25810
25553
  );
25811
25554
  if (flows.size > 1) return "ambiguous";
25812
- for (const bound of flows) return this.#provenance.get(bound) ?? "ambiguous";
25555
+ for (const bound of flows) return this.#provenance.get(bound)?.receiver ?? "ambiguous";
25813
25556
  let match;
25814
- for (const entry of this.#provenance.values()) {
25815
- if (entry.ingress.tracks.some((t) => t.packetId === packetId && (catalogTrackName === void 0 || t.name === catalogTrackName))) {
25557
+ for (const { receiver, ingress } of this.#provenance.values()) {
25558
+ if (ingress.tracks.some((t) => t.packetId === packetId && (catalogTrackName === void 0 || t.name === catalogTrackName))) {
25816
25559
  if (match) return "ambiguous";
25817
- match = entry;
25560
+ match = receiver;
25818
25561
  }
25819
25562
  }
25820
25563
  return match;
@@ -26596,8 +26339,11 @@ function providerErrorOf(error) {
26596
26339
  return Object.freeze(typeof code === "string" ? { name, message, code } : { name, message });
26597
26340
  }
26598
26341
  var MAX_TRACKED_DROPPED_PIDS = 16;
26342
+ function getMulticastGlobals() {
26343
+ return globalThis;
26344
+ }
26599
26345
  function hasMulticastGateway() {
26600
- return typeof resolveMulticastGateway()?.subscribe === "function";
26346
+ return typeof getMulticastGlobals().multicast?.subscribe === "function";
26601
26347
  }
26602
26348
  function senderOf(event) {
26603
26349
  const sourceAddress = event.sourceAddress;
@@ -26689,9 +26435,6 @@ var MulticastTransport = class {
26689
26435
  // listener closure, so an in-place admission change (setContext) applies
26690
26436
  // from the next packet on without rejoining.
26691
26437
  #context = void 0;
26692
- #deliveredContext = void 0;
26693
- /** The live join's gateway, when it is the user agent's MulticastReceiver provider. */
26694
- #userAgentGateway = void 0;
26695
26438
  // The live join's provider-side filter. An in-place widening must reach it,
26696
26439
  // or the provider never delivers the new ID; null without a live join.
26697
26440
  #providerFilter = null;
@@ -26728,7 +26471,7 @@ var MulticastTransport = class {
26728
26471
  this.#dataPlaneLive = false;
26729
26472
  this.#sender = void 0;
26730
26473
  if (this.#disposed) return this.#declined(generation, "disposed");
26731
- const gateway = this.#gateway ?? resolveMulticastGateway();
26474
+ const gateway = this.#gateway ?? getMulticastGlobals().multicast;
26732
26475
  if (typeof gateway?.subscribe !== "function") {
26733
26476
  console.warn("[MulticastTransport] Multicast API not available");
26734
26477
  return this.#declined(generation, "unavailable");
@@ -26744,16 +26487,15 @@ var MulticastTransport = class {
26744
26487
  console.log(
26745
26488
  `[MulticastTransport] window.multicast.subscribe(${config.sourceAddress ?? config.senderAddress ?? "*"}, ${config.groupAddress}, ${config.port})`
26746
26489
  );
26747
- const userAgent = isUserAgentVerifiedGateway(gateway);
26748
26490
  const subscribeConfig = toWindowMulticastSubscribeConfig({
26749
26491
  source: config.sourceAddress,
26750
26492
  senderAddress: config.senderAddress,
26751
26493
  group: config.groupAddress,
26752
26494
  port: config.port,
26753
- mode: userAgent ? "native" : config.mode,
26754
- amtRelay: userAgent ? void 0 : config.amtRelay,
26755
- amtRelayPort: userAgent ? void 0 : config.amtRelayPort,
26756
- amtDiscovery: userAgent ? void 0 : config.amtDiscovery,
26495
+ mode: config.mode,
26496
+ amtRelay: config.amtRelay,
26497
+ amtRelayPort: config.amtRelayPort,
26498
+ amtDiscovery: config.amtDiscovery,
26757
26499
  packetIds: config.packetIds,
26758
26500
  tracks: config.tracks,
26759
26501
  atsc3: config.atsc3
@@ -26799,8 +26541,7 @@ var MulticastTransport = class {
26799
26541
  acknowledgedUpdate: 0,
26800
26542
  inFlight: 0
26801
26543
  };
26802
- this.#userAgentGateway = userAgent ? gateway : void 0;
26803
- this.#setContext(context);
26544
+ this.#context = context;
26804
26545
  if (packetIds) {
26805
26546
  for (const packetId of packetIds) {
26806
26547
  if (!this.#acceptedBytesByPacketId.has(packetId)) {
@@ -26808,7 +26549,7 @@ var MulticastTransport = class {
26808
26549
  }
26809
26550
  }
26810
26551
  }
26811
- this.#resolvedTransport = userAgent ? "user-agent" : subscribeConfig.origin === "amt" ? "amt" : "native";
26552
+ this.#resolvedTransport = subscribeConfig.origin === "amt" ? "amt" : "native";
26812
26553
  const delivery = subscription.delivery ?? "datagram";
26813
26554
  if (delivery !== "datagram" && delivery !== "ordered-relay") {
26814
26555
  throw new Error(
@@ -26889,7 +26630,7 @@ var MulticastTransport = class {
26889
26630
  }
26890
26631
  if (!this.#acceptPacket(packet, sourceAddress)) return false;
26891
26632
  const liveness = !this.#isRecordCandidate(packet);
26892
- this.#onPacket(packet, this.#deliveredContext);
26633
+ this.#onPacket(packet, this.#context);
26893
26634
  return liveness;
26894
26635
  }
26895
26636
  #isRecordCandidate(packet) {
@@ -27100,10 +26841,8 @@ var MulticastTransport = class {
27100
26841
  return this.#subscription !== null;
27101
26842
  }
27102
26843
  /**
27103
- * The live join's context as the caller gave it (the join's `context`, or
27104
- * the last setContext), or undefined without a live join. On a native
27105
- * provider each accepted packet is delivered with a marked copy of it
27106
- * (`userAgentVerifiedIngress`); this getter never carries the mark.
26844
+ * What the live join delivers with every accepted packet (the join's
26845
+ * `context`, or the last setContext), or undefined without a live join.
27107
26846
  */
27108
26847
  get context() {
27109
26848
  return this.#context;
@@ -27127,16 +26866,7 @@ var MulticastTransport = class {
27127
26866
  "[MulticastTransport] setContext needs a live join; join() carries the first context"
27128
26867
  );
27129
26868
  }
27130
- this.#setContext(context);
27131
- }
27132
- /**
27133
- * The join's context, and what the subscription delivers with each packet:
27134
- * marked admitted by the user agent when the gateway is its native
27135
- * MulticastReceiver provider. feedPacket never marks.
27136
- */
27137
- #setContext(context) {
27138
26869
  this.#context = context;
27139
- this.#deliveredContext = this.#userAgentGateway !== void 0 && typeof context === "object" && context !== null ? userAgentVerifiedIngress(context, this.#userAgentGateway) : context;
27140
26870
  }
27141
26871
  /**
27142
26872
  * Replace the live join's packet-ID allow-list in place, without rejoining.
@@ -27268,8 +26998,6 @@ var MulticastTransport = class {
27268
26998
  this.#matchedSource = void 0;
27269
26999
  this.#providerFilter = null;
27270
27000
  this.#context = void 0;
27271
- this.#deliveredContext = void 0;
27272
- this.#userAgentGateway = void 0;
27273
27001
  this.#withdrawnPacketIds.clear();
27274
27002
  }
27275
27003
  /** The ingress filter; an accepted packet is counted here, once. */
@@ -28622,17 +28350,8 @@ var MulticastManager = class {
28622
28350
  * repair roles and owners are registered here; in-band owners stay the
28623
28351
  * caller's. Joining is best effort: a group that fails to join is logged
28624
28352
  * and leaves the media join as it was.
28625
- *
28626
- * `options.gateway` names the gateway a subscribe callback reads through.
28627
- * When it is the browser's own MulticastReceiver provider, the callback's
28628
- * packets are fed as admitted by the user agent
28629
- * (`userAgentVerifiedIngress`); nothing the callback passes can mark them.
28630
- * The mark rests on this statement, not on the data path: every packet the
28631
- * callback delivers must come from a subscription opened on
28632
- * `options.gateway`. A callback that also merges another source (a MoQ or
28633
- * WebSocket repair feed) must not name a native provider here.
28634
- */
28635
- joinRepairEndpoints(endpoints, provider, options) {
28353
+ */
28354
+ joinRepairEndpoints(endpoints, provider) {
28636
28355
  const releases = [];
28637
28356
  let released = false;
28638
28357
  const safely = (each) => {
@@ -28654,19 +28373,17 @@ var MulticastManager = class {
28654
28373
  ...endpoint.flow === void 0 ? {} : { flow: endpoint.flow }
28655
28374
  };
28656
28375
  let sender;
28657
- const feed = (packet, sourceAddress, ingressToFeed) => {
28376
+ const onPacket = (packet, sourceAddress) => {
28658
28377
  if (released) return;
28659
28378
  if (sourceAddress !== void 0 && !sameDatagramSource(sourceAddress, this.#transport.sender ?? (sender ??= sourceAddress))) return;
28660
- this.#router.feedPacket(packet, "multicast", ingressToFeed);
28379
+ this.#router.feedPacket(packet, "multicast", ingress);
28661
28380
  };
28662
28381
  const fail = (error) => console.warn(`[MulticastManager] repair group ${endpoint.group}:${endpoint.port} not joined`, error);
28663
28382
  if (typeof provider === "function") {
28664
- const marked = userAgentVerifiedIngress(ingress, options?.gateway);
28665
- const onPacket = (packet, sourceAddress) => feed(packet, sourceAddress, marked);
28666
28383
  Promise.resolve().then(() => provider(endpoint, onPacket)).then((release2) => released ? safely(release2) : releases.push(release2), fail);
28667
28384
  continue;
28668
28385
  }
28669
- const transport = new MulticastTransport((packet, delivered) => feed(packet, void 0, delivered ?? ingress), {
28386
+ const transport = new MulticastTransport((packet) => onPacket(packet), {
28670
28387
  gateway: provider,
28671
28388
  lockedTo: () => this.#transport.sender
28672
28389
  });
@@ -28682,7 +28399,7 @@ var MulticastManager = class {
28682
28399
  tracks: endpoint.tracks.map(({ name, packetId }) => ({ name, packetId })),
28683
28400
  // A protected repair group's records ride in band on its port (7.2.3).
28684
28401
  ...endpoint.flow === void 0 ? {} : { protected: true }
28685
- }, ingress).then((joined) => {
28402
+ }).then((joined) => {
28686
28403
  if (!joined && !released) fail(transport.lastJoinOutcome);
28687
28404
  });
28688
28405
  }