@blockcast/mmt-container 0.5.0-main.9c437a834da9 → 0.5.0-main.dd44e35d4e29
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/dist/browser-runtime.js +145 -83
- package/dist/browser-runtime.js.map +2 -2
- package/dist/fec-manager.d.ts +14 -1
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +72 -18
- package/dist/fec-manager.js.map +2 -2
- package/dist/mmtp-router.d.ts +8 -2
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +70 -52
- package/dist/mmtp-router.js.map +2 -2
- package/dist/multicast-manager.d.ts +2 -2
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +145 -83
- package/dist/multicast-manager.js.map +2 -2
- package/package.json +5 -5
- package/src/fec-manager.ts +86 -22
- package/src/mmtp-router.ts +85 -55
- package/src/multicast-manager.ts +7 -15
package/dist/browser-runtime.js
CHANGED
|
@@ -13502,6 +13502,9 @@ var FECManager = class _FECManager {
|
|
|
13502
13502
|
// Receiver-local first-accepted-symbol time per block, bounded like
|
|
13503
13503
|
// #blockPathCounts (see blockAnchorAtMs).
|
|
13504
13504
|
this.#blockAnchorsMs = /* @__PURE__ */ new Map();
|
|
13505
|
+
// The receipt time of the packet being fed, when it is not now: a datagram
|
|
13506
|
+
// held on a miss and admitted later (withReceiptTime).
|
|
13507
|
+
this.#receiptAtMs = void 0;
|
|
13505
13508
|
// Exact catalog identity observed on accepted symbols for each FEC block.
|
|
13506
13509
|
// Conflicting identities collapse to null so recovery fails closed.
|
|
13507
13510
|
this.#blockCatalogTrackNames = /* @__PURE__ */ new Map();
|
|
@@ -13549,6 +13552,9 @@ var FECManager = class _FECManager {
|
|
|
13549
13552
|
// Worker recovery emits all K source symbols. Track recovery once per block
|
|
13550
13553
|
// while routing only ESI slots that were absent from the direct source path.
|
|
13551
13554
|
this.#workerRecoveredBlocks = /* @__PURE__ */ new Set();
|
|
13555
|
+
// Worker-recovered blocks a recovered packet of which admission refused,
|
|
13556
|
+
// until the decode's final symbol (7.2.7: the block is unrecovered).
|
|
13557
|
+
this.#refusedRecoveries = /* @__PURE__ */ new Set();
|
|
13552
13558
|
// How the multicast leg delivers symbols (see MulticastSymbolDelivery). The
|
|
13553
13559
|
// provider declares it per transport join; absence keeps datagram semantics.
|
|
13554
13560
|
this.#multicastSymbolDelivery = "datagram";
|
|
@@ -13687,6 +13693,11 @@ var FECManager = class _FECManager {
|
|
|
13687
13693
|
/** A stream's SBN went backwards (or jumped implausibly): the source restarted. */
|
|
13688
13694
|
this.onSourceDiscontinuity = null;
|
|
13689
13695
|
// Worker-path callbacks — async recovery and stats from FecWorkerClient.
|
|
13696
|
+
/**
|
|
13697
|
+
* A recovered source symbol. Return false when admission refused the
|
|
13698
|
+
* packet it carries (bc-provenance v2, draft-ramadan-moq-multicast-01
|
|
13699
|
+
* 7.2.7): the block is then unrecovered and stays open to its FEC deadline.
|
|
13700
|
+
*/
|
|
13690
13701
|
this.onBlockRecovered = null;
|
|
13691
13702
|
this.onFecStatsUpdate = null;
|
|
13692
13703
|
}
|
|
@@ -13739,6 +13750,7 @@ var FECManager = class _FECManager {
|
|
|
13739
13750
|
#seenSymbols;
|
|
13740
13751
|
#blockPathCounts;
|
|
13741
13752
|
#blockAnchorsMs;
|
|
13753
|
+
#receiptAtMs;
|
|
13742
13754
|
#blockCatalogTrackNames;
|
|
13743
13755
|
#startupAlignedPackets;
|
|
13744
13756
|
#startupPartialBlocks;
|
|
@@ -13751,6 +13763,7 @@ var FECManager = class _FECManager {
|
|
|
13751
13763
|
#repairDeadlines;
|
|
13752
13764
|
#repairDeadlineAtMs;
|
|
13753
13765
|
#workerRecoveredBlocks;
|
|
13766
|
+
#refusedRecoveries;
|
|
13754
13767
|
#multicastSymbolDelivery;
|
|
13755
13768
|
#orderedFrontiers;
|
|
13756
13769
|
#orderedPendingBlocks;
|
|
@@ -13890,6 +13903,7 @@ var FECManager = class _FECManager {
|
|
|
13890
13903
|
this.#completedBlocks.delete(record.key);
|
|
13891
13904
|
this.#cleanlyCompletedBlocks.delete(record.key);
|
|
13892
13905
|
this.#workerRecoveredBlocks.delete(record.key);
|
|
13906
|
+
this.#refusedRecoveries.delete(record.key);
|
|
13893
13907
|
this.#failedBlocks.delete(record.key);
|
|
13894
13908
|
this.#resolvedBlockClasses.delete(record.key);
|
|
13895
13909
|
this.#repairedBlocks.delete(record.key);
|
|
@@ -14228,7 +14242,7 @@ var FECManager = class _FECManager {
|
|
|
14228
14242
|
* remainder, so repeated source progress costs no timer operation.
|
|
14229
14243
|
*/
|
|
14230
14244
|
#armRepairDeadline(key, sbn, packetId, catalogTrackName, delayMs) {
|
|
14231
|
-
const deadlineMs =
|
|
14245
|
+
const deadlineMs = this.#notEarlierUnderReceipt(this.#receiptNow() + delayMs, this.#repairDeadlineAtMs.get(key));
|
|
14232
14246
|
this.#repairDeadlineAtMs.set(key, deadlineMs);
|
|
14233
14247
|
const armed = this.#repairDeadlines.get(key);
|
|
14234
14248
|
if (armed?.handle != null) {
|
|
@@ -14248,7 +14262,7 @@ var FECManager = class _FECManager {
|
|
|
14248
14262
|
timer.handle = null;
|
|
14249
14263
|
this.#requestRepair(sbn, packetId, catalogTrackName);
|
|
14250
14264
|
};
|
|
14251
|
-
timer.handle = setTimeout(onFire,
|
|
14265
|
+
timer.handle = setTimeout(onFire, Math.max(0, deadlineMs - performance.now()));
|
|
14252
14266
|
this.#repairDeadlines.set(key, timer);
|
|
14253
14267
|
}
|
|
14254
14268
|
#requestRepair(sbn, packetId, catalogTrackName, settledByOrder = false) {
|
|
@@ -14652,7 +14666,10 @@ var FECManager = class _FECManager {
|
|
|
14652
14666
|
}
|
|
14653
14667
|
#armBlockTimeout(sbn, packetId, catalogTrackName, delayMs) {
|
|
14654
14668
|
const key = this.#blockKey(sbn, packetId, catalogTrackName);
|
|
14655
|
-
const waitAtMs =
|
|
14669
|
+
const waitAtMs = this.#notEarlierUnderReceipt(
|
|
14670
|
+
this.#receiptNow() + Math.max(1, Math.ceil(delayMs)),
|
|
14671
|
+
this.#blockWaitDeadlinesMs.get(key)
|
|
14672
|
+
);
|
|
14656
14673
|
const holdAtMs = this.#repairHoldUntilMs.get(key);
|
|
14657
14674
|
this.#blockWaitDeadlinesMs.set(key, holdAtMs === void 0 ? waitAtMs : Math.min(waitAtMs, holdAtMs));
|
|
14658
14675
|
this.#applyBlockDeadline(key, sbn, packetId, catalogTrackName);
|
|
@@ -15041,6 +15058,7 @@ var FECManager = class _FECManager {
|
|
|
15041
15058
|
resetSet(this.#cleanlyCompletedBlocks);
|
|
15042
15059
|
resetSet(this.#repairRequestedBlocks);
|
|
15043
15060
|
resetSet(this.#workerRecoveredBlocks);
|
|
15061
|
+
resetSet(this.#refusedRecoveries);
|
|
15044
15062
|
resetSet(this.#startupAlignedPackets);
|
|
15045
15063
|
resetSet(this.#startupPartialBlocks);
|
|
15046
15064
|
resetSet(this.#startupRepairReadyPackets);
|
|
@@ -15167,6 +15185,7 @@ var FECManager = class _FECManager {
|
|
|
15167
15185
|
dropSet(this.#cleanlyCompletedBlocks);
|
|
15168
15186
|
dropSet(this.#repairRequestedBlocks);
|
|
15169
15187
|
dropSet(this.#workerRecoveredBlocks);
|
|
15188
|
+
dropSet(this.#refusedRecoveries);
|
|
15170
15189
|
dropSet(this.#startupAlignedPackets);
|
|
15171
15190
|
dropSet(this.#startupPartialBlocks);
|
|
15172
15191
|
dropSet(this.#startupRepairReadyPackets);
|
|
@@ -15280,7 +15299,9 @@ var FECManager = class _FECManager {
|
|
|
15280
15299
|
moqSymbols: 0,
|
|
15281
15300
|
complete: false
|
|
15282
15301
|
};
|
|
15283
|
-
|
|
15302
|
+
const receivedAtMs = this.#receiptNow();
|
|
15303
|
+
const anchorMs = this.#blockAnchorsMs.get(blockKey);
|
|
15304
|
+
if (anchorMs === void 0 || receivedAtMs < anchorMs) this.#blockAnchorsMs.set(blockKey, receivedAtMs);
|
|
15284
15305
|
if (source === "multicast") counts.multicastSymbols++;
|
|
15285
15306
|
else counts.moqSymbols++;
|
|
15286
15307
|
this.#blockPathCounts.set(blockKey, counts);
|
|
@@ -15953,7 +15974,25 @@ var FECManager = class _FECManager {
|
|
|
15953
15974
|
const blockKey = this.#blockKey(meta.sbn, packetId, recoveredCatalogTrackName);
|
|
15954
15975
|
const cleanlyCompleted = this.#cleanlyCompletedBlocks.has(blockKey);
|
|
15955
15976
|
if (!cleanlyCompleted) {
|
|
15956
|
-
|
|
15977
|
+
const symbolKey = `${blockKey}:${esi}`;
|
|
15978
|
+
if (!this.#seenSymbols.has(symbolKey)) {
|
|
15979
|
+
this.#seenSymbols.add(symbolKey);
|
|
15980
|
+
const admitted = this.onBlockRecovered?.(
|
|
15981
|
+
meta.sbn,
|
|
15982
|
+
packetId,
|
|
15983
|
+
data,
|
|
15984
|
+
meta,
|
|
15985
|
+
recoveredCatalogTrackName
|
|
15986
|
+
);
|
|
15987
|
+
if (admitted === false) {
|
|
15988
|
+
this.#refusedRecoveries.add(blockKey);
|
|
15989
|
+
if (this.#refusedRecoveries.size > 1e3) dropOldest(this.#refusedRecoveries, 500);
|
|
15990
|
+
}
|
|
15991
|
+
}
|
|
15992
|
+
}
|
|
15993
|
+
const refused = esi >= meta.ssbLength - 1 && this.#refusedRecoveries.delete(blockKey);
|
|
15994
|
+
if (esi >= meta.ssbLength - 1 && !refused && !this.#completedBlocks.has(blockKey)) {
|
|
15995
|
+
if (!cleanlyCompleted && !this.#workerRecoveredBlocks.has(blockKey)) {
|
|
15957
15996
|
this.#traceLifecycle(
|
|
15958
15997
|
"recovered",
|
|
15959
15998
|
meta.sbn,
|
|
@@ -15968,19 +16007,6 @@ var FECManager = class _FECManager {
|
|
|
15968
16007
|
}
|
|
15969
16008
|
this.#noteBlockRepaired(blockKey, meta.sbn, packetId, recoveredCatalogTrackName);
|
|
15970
16009
|
}
|
|
15971
|
-
const symbolKey = `${blockKey}:${esi}`;
|
|
15972
|
-
if (!this.#seenSymbols.has(symbolKey)) {
|
|
15973
|
-
this.#seenSymbols.add(symbolKey);
|
|
15974
|
-
this.onBlockRecovered?.(
|
|
15975
|
-
meta.sbn,
|
|
15976
|
-
packetId,
|
|
15977
|
-
data,
|
|
15978
|
-
meta,
|
|
15979
|
-
recoveredCatalogTrackName
|
|
15980
|
-
);
|
|
15981
|
-
}
|
|
15982
|
-
}
|
|
15983
|
-
if (esi >= meta.ssbLength - 1 && !this.#completedBlocks.has(blockKey)) {
|
|
15984
16010
|
this.cancelBlockTimeout(meta.sbn, packetId, recoveredCatalogTrackName);
|
|
15985
16011
|
if (recoveredCatalogTrackName === void 0) {
|
|
15986
16012
|
this.onBlockComplete?.(meta.sbn, packetId);
|
|
@@ -16550,6 +16576,33 @@ var FECManager = class _FECManager {
|
|
|
16550
16576
|
}
|
|
16551
16577
|
queueMicrotask(() => this.#syncDecoderBlockOwners.delete(key));
|
|
16552
16578
|
}
|
|
16579
|
+
/**
|
|
16580
|
+
* Run `fn` with `receivedAtMs` (performance.now() clock) as the receipt
|
|
16581
|
+
* time of what it feeds. Within a consumer the bc-provenance profile
|
|
16582
|
+
* governs, a datagram held on a miss and admitted later keeps its receipt
|
|
16583
|
+
* time (fec-01 9): it anchors its block's ts and arms the block's
|
|
16584
|
+
* deadlines from then, never later than they are already armed.
|
|
16585
|
+
*/
|
|
16586
|
+
withReceiptTime(receivedAtMs, fn) {
|
|
16587
|
+
const outer = this.#receiptAtMs;
|
|
16588
|
+
this.#receiptAtMs = receivedAtMs;
|
|
16589
|
+
try {
|
|
16590
|
+
fn();
|
|
16591
|
+
} finally {
|
|
16592
|
+
this.#receiptAtMs = outer;
|
|
16593
|
+
}
|
|
16594
|
+
}
|
|
16595
|
+
#receiptNow() {
|
|
16596
|
+
return this.#receiptAtMs ?? performance.now();
|
|
16597
|
+
}
|
|
16598
|
+
/**
|
|
16599
|
+
* A held packet admitted late arms from its (earlier) receipt time; that
|
|
16600
|
+
* never pulls in a deadline later activity already armed. Outside a
|
|
16601
|
+
* receipt scope a re-arm replaces the deadline, as a narrower bound may.
|
|
16602
|
+
*/
|
|
16603
|
+
#notEarlierUnderReceipt(deadlineMs, armedMs) {
|
|
16604
|
+
return this.#receiptAtMs === void 0 || armedMs === void 0 ? deadlineMs : Math.max(deadlineMs, armedMs);
|
|
16605
|
+
}
|
|
16553
16606
|
/** Refresh deadlines after accepted block activity. */
|
|
16554
16607
|
noteBlockActivity(sbn, packetId, catalogTrackName, sourceProgress = false) {
|
|
16555
16608
|
if (!this.#trackConfigs.has(packetId)) return;
|
|
@@ -16728,6 +16781,7 @@ var FECManager = class _FECManager {
|
|
|
16728
16781
|
this.#cleanlyCompletedBlocks.clear();
|
|
16729
16782
|
this.#repairRequestedBlocks.clear();
|
|
16730
16783
|
this.#workerRecoveredBlocks.clear();
|
|
16784
|
+
this.#refusedRecoveries.clear();
|
|
16731
16785
|
this.#syncDecoderBlockOwners.clear();
|
|
16732
16786
|
this.#startupAlignedPackets.clear();
|
|
16733
16787
|
this.#startupPartialBlocks.clear();
|
|
@@ -19434,6 +19488,8 @@ var MmtpRouter = class {
|
|
|
19434
19488
|
#unicastRepair = false;
|
|
19435
19489
|
/** How to route a held unicast (MoQ) datagram once a record admits it. */
|
|
19436
19490
|
#heldReplay = /* @__PURE__ */ new WeakMap();
|
|
19491
|
+
/** When a held datagram was received: admitted later, it keeps that receipt time (fec-01 9). */
|
|
19492
|
+
#heldAt = /* @__PURE__ */ new WeakMap();
|
|
19437
19493
|
/** The flow whose receiver admitted a stream's source datagrams, by packetId then catalog track name: recovered packets answer to it. */
|
|
19438
19494
|
#provenanceStreamFlow = /* @__PURE__ */ new Map();
|
|
19439
19495
|
#unregisteredFlowDrops = 0;
|
|
@@ -20219,6 +20275,7 @@ var MmtpRouter = class {
|
|
|
20219
20275
|
if (verdict === "admitted") return "admitted";
|
|
20220
20276
|
if (verdict === "held") {
|
|
20221
20277
|
this.#heldReplay.set(packet, replay);
|
|
20278
|
+
this.#heldAt.set(packet, performance.now());
|
|
20222
20279
|
return "held";
|
|
20223
20280
|
}
|
|
20224
20281
|
this.#unadmittedListedDrops++;
|
|
@@ -20237,9 +20294,14 @@ var MmtpRouter = class {
|
|
|
20237
20294
|
this.#noteFlowAdmitted(flow);
|
|
20238
20295
|
this.#withDeferredFecPokes(() => {
|
|
20239
20296
|
for (const datagram of result.admitted) {
|
|
20240
|
-
const
|
|
20241
|
-
|
|
20242
|
-
|
|
20297
|
+
const route = () => {
|
|
20298
|
+
const replay = this.#heldReplay.get(datagram);
|
|
20299
|
+
if (replay) replay();
|
|
20300
|
+
else this.#processMMTP(datagram, "multicast", true, this.#heldIngress.get(datagram) ?? entry.ingress, false, true);
|
|
20301
|
+
};
|
|
20302
|
+
const heldAt = this.#heldAt.get(datagram);
|
|
20303
|
+
if (heldAt !== void 0 && this.#fecManager?.withReceiptTime) this.#fecManager.withReceiptTime(heldAt, route);
|
|
20304
|
+
else route();
|
|
20243
20305
|
}
|
|
20244
20306
|
});
|
|
20245
20307
|
}
|
|
@@ -20490,10 +20552,11 @@ var MmtpRouter = class {
|
|
|
20490
20552
|
catalogTrackName
|
|
20491
20553
|
);
|
|
20492
20554
|
if (recovered && !alreadyCompleted) {
|
|
20493
|
-
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
|
|
20555
|
+
this.#routeRecoveredBlock(blockStart, recovered, ownerPacketId, catalogTrackName, () => {
|
|
20556
|
+
fec.cancelBlockTimeout(blockStart, ownerPacketId, catalogTrackName);
|
|
20557
|
+
fec.countRecovery(ownerPacketId, blockStart, catalogTrackName);
|
|
20558
|
+
fec.markBlockCompleted(blockStart, ownerPacketId, catalogTrackName);
|
|
20559
|
+
});
|
|
20497
20560
|
}
|
|
20498
20561
|
}
|
|
20499
20562
|
/**
|
|
@@ -20534,10 +20597,11 @@ var MmtpRouter = class {
|
|
|
20534
20597
|
const alreadyCompleted = fec.isBlockCompleted(blockStart, ownerPacketId, catalogTrackName);
|
|
20535
20598
|
const recovered = fec.feedSourceSymbol(ownerPacketId, ssId, payload.symbolData, catalogTrackName);
|
|
20536
20599
|
if (!recovered || alreadyCompleted) continue;
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20600
|
+
this.#routeRecoveredBlock(blockStart, recovered, ownerPacketId, catalogTrackName, () => {
|
|
20601
|
+
fec.cancelBlockTimeout(blockStart, ownerPacketId, catalogTrackName);
|
|
20602
|
+
fec.countRecovery(ownerPacketId, blockStart, catalogTrackName);
|
|
20603
|
+
fec.markBlockCompleted(blockStart, ownerPacketId, catalogTrackName);
|
|
20604
|
+
});
|
|
20541
20605
|
}
|
|
20542
20606
|
}
|
|
20543
20607
|
#resolveRepairOwnerPacketId(packetId, ingress) {
|
|
@@ -20560,14 +20624,18 @@ var MmtpRouter = class {
|
|
|
20560
20624
|
* Sync WASM decoders return the block's K' = SSB_length fixed-width
|
|
20561
20625
|
* ssbg_mode1 source symbols concatenated. */
|
|
20562
20626
|
routeRecoveredBlock(blockId, data, packetId, catalogTrackName) {
|
|
20563
|
-
|
|
20627
|
+
let recovered = false;
|
|
20628
|
+
this.#withDeferredFecPokes(() => {
|
|
20629
|
+
recovered = this.#routeRecoveredBlock(blockId, data, packetId, catalogTrackName);
|
|
20630
|
+
});
|
|
20631
|
+
return recovered;
|
|
20564
20632
|
}
|
|
20565
20633
|
/** Route a single recovered source symbol through the parser + dedup pipeline.
|
|
20566
20634
|
* Worker-backed decoders emit one padded source symbol per frame event. */
|
|
20567
20635
|
routeRecoveredSymbol(blockId, data, packetId, esi = 0, catalogTrackName) {
|
|
20568
20636
|
const blockProfile = this.#blockProfileFor(packetId);
|
|
20569
20637
|
const result = processFecSymbol(data, { ownerPacketId: packetId, index: esi, blockProfile });
|
|
20570
|
-
this.#routeVerifiedFecSymbols(blockId, result, packetId, catalogTrackName);
|
|
20638
|
+
return this.#routeVerifiedFecSymbols(blockId, result, packetId, catalogTrackName);
|
|
20571
20639
|
}
|
|
20572
20640
|
// ── Keyframe timer cancellation ─────────────────────────────────
|
|
20573
20641
|
/** Cancel the active keyframe loss timer.
|
|
@@ -21239,7 +21307,10 @@ var MmtpRouter = class {
|
|
|
21239
21307
|
if (verdict === "admitted") {
|
|
21240
21308
|
this.#noteFlowAdmitted(ingress.flow);
|
|
21241
21309
|
this.#processMMTP(packet, source, true, ingress, overlapCopy);
|
|
21242
|
-
} else if (verdict === "held")
|
|
21310
|
+
} else if (verdict === "held") {
|
|
21311
|
+
this.#heldIngress.set(packet, ingress);
|
|
21312
|
+
this.#heldAt.set(packet, performance.now());
|
|
21313
|
+
}
|
|
21243
21314
|
return;
|
|
21244
21315
|
}
|
|
21245
21316
|
if (source === "moq" && !manifestAdmitted) {
|
|
@@ -21422,36 +21493,22 @@ var MmtpRouter = class {
|
|
|
21422
21493
|
sourceFec.symbolData,
|
|
21423
21494
|
catalogTrackName
|
|
21424
21495
|
);
|
|
21425
|
-
if (recovered) {
|
|
21426
|
-
|
|
21496
|
+
if (recovered && !alreadyCompleted) {
|
|
21497
|
+
const fec = this.#fecManager;
|
|
21498
|
+
const sbn = sourceFec.sbn;
|
|
21499
|
+
const packetId = info.packetId;
|
|
21500
|
+
const tracked = this.#classifyPacketId(packetId) !== null;
|
|
21501
|
+
this.#routeRecoveredBlock(sbn, recovered, packetId, catalogTrackName, () => {
|
|
21427
21502
|
if (catalogTrackName === void 0) {
|
|
21428
|
-
|
|
21503
|
+
if (tracked) fec.cancelBlockTimeout(sbn, packetId);
|
|
21504
|
+
fec.countRecovery(packetId, sbn, catalogTrackName);
|
|
21505
|
+
fec.markBlockCompleted(sbn, packetId);
|
|
21429
21506
|
} else {
|
|
21430
|
-
|
|
21431
|
-
|
|
21432
|
-
|
|
21433
|
-
catalogTrackName
|
|
21434
|
-
);
|
|
21507
|
+
if (tracked) fec.cancelBlockTimeout(sbn, packetId, catalogTrackName);
|
|
21508
|
+
fec.countRecovery(packetId, sbn, catalogTrackName);
|
|
21509
|
+
fec.markBlockCompleted(sbn, packetId, catalogTrackName);
|
|
21435
21510
|
}
|
|
21436
|
-
}
|
|
21437
|
-
if (!alreadyCompleted) {
|
|
21438
|
-
this.#fecManager.countRecovery(info.packetId, sourceFec.sbn, catalogTrackName);
|
|
21439
|
-
if (catalogTrackName === void 0) {
|
|
21440
|
-
this.#fecManager.markBlockCompleted(sourceFec.sbn, info.packetId);
|
|
21441
|
-
} else {
|
|
21442
|
-
this.#fecManager.markBlockCompleted(
|
|
21443
|
-
sourceFec.sbn,
|
|
21444
|
-
info.packetId,
|
|
21445
|
-
catalogTrackName
|
|
21446
|
-
);
|
|
21447
|
-
}
|
|
21448
|
-
this.#routeRecoveredBlock(
|
|
21449
|
-
sourceFec.sbn,
|
|
21450
|
-
recovered,
|
|
21451
|
-
info.packetId,
|
|
21452
|
-
catalogTrackName
|
|
21453
|
-
);
|
|
21454
|
-
}
|
|
21511
|
+
});
|
|
21455
21512
|
}
|
|
21456
21513
|
}
|
|
21457
21514
|
}
|
|
@@ -21827,7 +21884,7 @@ var MmtpRouter = class {
|
|
|
21827
21884
|
}
|
|
21828
21885
|
// ── Private: FEC recovery routing ───────────────────────────────
|
|
21829
21886
|
/** Route WASM-recovered block through appropriate path based on container kind. */
|
|
21830
|
-
#routeRecoveredBlock(blockId, recovered, ownerPacketId, catalogTrackName) {
|
|
21887
|
+
#routeRecoveredBlock(blockId, recovered, ownerPacketId, catalogTrackName, complete) {
|
|
21831
21888
|
const packetSymbolSize = this.#symbolSizeForPacket(ownerPacketId);
|
|
21832
21889
|
if (ownerPacketId === void 0) {
|
|
21833
21890
|
throw new Error("[MmtpRouter] a recovered FEC block needs its owner packetId to read its fec.blockProfile");
|
|
@@ -21844,31 +21901,46 @@ var MmtpRouter = class {
|
|
|
21844
21901
|
ownerPacketId,
|
|
21845
21902
|
blockProfile
|
|
21846
21903
|
});
|
|
21847
|
-
this.#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName);
|
|
21904
|
+
return this.#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete);
|
|
21848
21905
|
}
|
|
21849
21906
|
/**
|
|
21850
21907
|
* A recovered source packet of a protected flow is admitted on its own
|
|
21851
21908
|
* digest: its bytes with the SS_ID it was sent with (SS_Start + ESI)
|
|
21852
21909
|
* appended are the datagram the record listed (7.2.7). One that no record
|
|
21853
21910
|
* lists is dropped; holding it would let it out later as a multicast arrival.
|
|
21911
|
+
* Returns whether the decode recovered the block: every packet it yields
|
|
21912
|
+
* that this router has not parsed already is admitted. A block one of whose
|
|
21913
|
+
* recovered packets is refused is unrecovered (7.2.7): its caller leaves it
|
|
21914
|
+
* open, so it reaches its FEC deadline and fails by class. Always true
|
|
21915
|
+
* outside a protected flow.
|
|
21854
21916
|
*/
|
|
21855
|
-
#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName) {
|
|
21917
|
+
#routeVerifiedFecSymbols(blockId, result, ownerPacketId, catalogTrackName, complete) {
|
|
21856
21918
|
const receiver = ownerPacketId == null ? void 0 : this.#provenanceFor(ownerPacketId, catalogTrackName);
|
|
21857
|
-
|
|
21858
|
-
|
|
21859
|
-
|
|
21860
|
-
} else if (receiver) {
|
|
21919
|
+
let recovered = true;
|
|
21920
|
+
if (receiver) {
|
|
21921
|
+
const parsed = this.#stream(ownerPacketId, catalogTrackName).duplicates.parsedSymbols;
|
|
21861
21922
|
result = {
|
|
21862
21923
|
...result,
|
|
21863
21924
|
symbols: result.symbols.filter((sym) => {
|
|
21864
|
-
const
|
|
21865
|
-
|
|
21866
|
-
|
|
21867
|
-
|
|
21925
|
+
const ssId = this.#fecAnchorForRecovered(blockId, sym.index);
|
|
21926
|
+
if (parsed.has(ssId)) return false;
|
|
21927
|
+
let admitted = false;
|
|
21928
|
+
if (receiver === "ambiguous") {
|
|
21929
|
+
this.#ambiguousRecoveredDrops++;
|
|
21930
|
+
} else {
|
|
21931
|
+
const wire = new Uint8Array(sym.rawSymbol.byteLength + 4);
|
|
21932
|
+
wire.set(sym.rawSymbol);
|
|
21933
|
+
new DataView(wire.buffer).setUint32(sym.rawSymbol.byteLength, ssId);
|
|
21934
|
+
admitted = receiver.admitRecovered(wire);
|
|
21935
|
+
}
|
|
21936
|
+
if (!admitted) recovered = false;
|
|
21937
|
+
return admitted;
|
|
21868
21938
|
})
|
|
21869
21939
|
};
|
|
21870
21940
|
}
|
|
21941
|
+
if (recovered) complete?.();
|
|
21871
21942
|
this.#routeProcessedFecSymbols(blockId, result, ownerPacketId, catalogTrackName);
|
|
21943
|
+
return recovered;
|
|
21872
21944
|
}
|
|
21873
21945
|
/**
|
|
21874
21946
|
* The receiver a recovered packet of `packetId` answers to: the flow that
|
|
@@ -26928,17 +27000,7 @@ var MulticastManager = class {
|
|
|
26928
27000
|
this.#fec.onBlockRecovered = (sbn, packetId, data, meta, recoveredTrackName) => {
|
|
26929
27001
|
const recovered = new Uint8Array(data);
|
|
26930
27002
|
const catalogTrackName = recoveredTrackName ?? this.#fec.catalogTrackNameForBlock(sbn, packetId);
|
|
26931
|
-
|
|
26932
|
-
this.#router.routeRecoveredSymbol(sbn, recovered, packetId, meta.esi);
|
|
26933
|
-
} else {
|
|
26934
|
-
this.#router.routeRecoveredSymbol(
|
|
26935
|
-
sbn,
|
|
26936
|
-
recovered,
|
|
26937
|
-
packetId,
|
|
26938
|
-
meta.esi,
|
|
26939
|
-
catalogTrackName
|
|
26940
|
-
);
|
|
26941
|
-
}
|
|
27003
|
+
return catalogTrackName === void 0 ? this.#router.routeRecoveredSymbol(sbn, recovered, packetId, meta.esi) : this.#router.routeRecoveredSymbol(sbn, recovered, packetId, meta.esi, catalogTrackName);
|
|
26942
27004
|
};
|
|
26943
27005
|
this.#fec.onRepairResolved = (sbn, packetId, _outcome, catalogTrackName) => {
|
|
26944
27006
|
this.clearRepairForBlock(sbn, packetId, catalogTrackName);
|
|
@@ -27916,11 +27978,11 @@ var MulticastManager = class {
|
|
|
27916
27978
|
}
|
|
27917
27979
|
/** Route a Worker-recovered FEC block through the MMTP parser + dedup pipeline. */
|
|
27918
27980
|
routeRecoveredBlock(blockId, data, packetId, catalogTrackName) {
|
|
27919
|
-
this.#router.routeRecoveredBlock(blockId, data, packetId, catalogTrackName);
|
|
27981
|
+
return this.#router.routeRecoveredBlock(blockId, data, packetId, catalogTrackName);
|
|
27920
27982
|
}
|
|
27921
27983
|
/** Route one Worker-recovered source symbol through the MMTP parser + dedup pipeline. */
|
|
27922
27984
|
routeRecoveredSymbol(blockId, data, packetId, esi = 0, catalogTrackName) {
|
|
27923
|
-
this.#router.routeRecoveredSymbol(blockId, data, packetId, esi, catalogTrackName);
|
|
27985
|
+
return this.#router.routeRecoveredSymbol(blockId, data, packetId, esi, catalogTrackName);
|
|
27924
27986
|
}
|
|
27925
27987
|
// ---------------------------------------------------------------------------
|
|
27926
27988
|
// Phase 14: multi-track catalog ingest (D-04, D-06, D-07, D-17, D-26, D-28)
|