fix(nat): use the full bounded NAT window (#371)
This commit is contained in:
1 parent
b2f6d33630
commit
1ed7ffc84b
3 files changed
+37
-29
No files matched your search
@@ -35,10 +35,11 @@ state, or media path.
|
||||
candidates and cannot enter the arithmetic sequence. If three or more
|
||||
distinct survey candidates for one media section and public address form an
|
||||
arithmetic port sequence, the adapter appends at most eight bounded
|
||||
candidates around the sequence's high endpoint. Every ordinary candidate
|
||||
keeps normal Trickle ICE timing; no ordinary candidate is delayed, rejected,
|
||||
or replaced. A Browser that does not expose candidate source URLs keeps
|
||||
ordinary ICE but does not mix independent observations into prediction.
|
||||
candidates outward from both sequence endpoints: four above the high endpoint
|
||||
and four below the low endpoint. Every ordinary candidate keeps normal
|
||||
Trickle ICE timing; no ordinary candidate is delayed, rejected, or replaced.
|
||||
A Browser that does not expose candidate source URLs keeps ordinary ICE but
|
||||
does not mix independent observations into prediction.
|
||||
4. Candidate observations remain in memory for that connection only. No NAT
|
||||
label, raw address, port, score, hard candidate skip, periodic probe, or
|
||||
route-controller branch is introduced. Sanitized diagnostics record only
|
||||
|
||||
@@ -244,23 +244,21 @@ function stableStep(observations: readonly SrflxObservation[]): number | null {
|
||||
return step;
|
||||
}
|
||||
|
||||
function predictedFrom(
|
||||
anchor: SrflxObservation,
|
||||
function predictedAround(
|
||||
low: SrflxObservation,
|
||||
high: SrflxObservation,
|
||||
step: number,
|
||||
occupiedPorts: ReadonlySet<number>,
|
||||
): SignalCandidate[] {
|
||||
const predicted: SignalCandidate[] = [];
|
||||
const seenPorts = new Set(occupiedPorts);
|
||||
for (const direction of [1, -1] as const) {
|
||||
for (const [anchor, direction] of [
|
||||
[high, 1],
|
||||
[low, -1],
|
||||
] as const) {
|
||||
for (let index = 1; index <= NAT_PREDICTION_STEPS; index += 1) {
|
||||
const port = anchor.port + direction * step * index;
|
||||
if (port < MIN_PREDICTABLE_PORT || port > MAX_PREDICTABLE_PORT) {
|
||||
continue;
|
||||
}
|
||||
if (seenPorts.has(port)) {
|
||||
continue;
|
||||
}
|
||||
seenPorts.add(port);
|
||||
const fields = [...anchor.fields];
|
||||
fields[0] = `candidate:s${direction > 0 ? "p" : "m"}${index}`;
|
||||
fields[5] = String(port);
|
||||
@@ -298,14 +296,11 @@ export function predictSrflxCandidates(
|
||||
if (step === null) {
|
||||
continue;
|
||||
}
|
||||
const anchor = distinct.reduce((latest, observation) =>
|
||||
observation.port > latest.port ? observation : latest,
|
||||
const ordered = [...distinct].sort((left, right) => left.port - right.port);
|
||||
return predictedAround(ordered[0]!, ordered.at(-1)!, step).slice(
|
||||
0,
|
||||
MAX_NAT_PREDICTION_CANDIDATES,
|
||||
);
|
||||
return predictedFrom(
|
||||
anchor,
|
||||
step,
|
||||
new Set(distinct.map((observation) => observation.port)),
|
||||
).slice(0, MAX_NAT_PREDICTION_CANDIDATES);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -118,12 +118,17 @@ describe("NAT prediction ICE adapter", () => {
|
||||
candidate(40_006),
|
||||
]);
|
||||
|
||||
expect(predictions.length).toBeLessThanOrEqual(
|
||||
MAX_NAT_PREDICTION_CANDIDATES,
|
||||
);
|
||||
expect(predictions.map(portOf)).toEqual(
|
||||
expect.arrayContaining([40_009, 39_997]),
|
||||
);
|
||||
expect(predictions).toHaveLength(MAX_NAT_PREDICTION_CANDIDATES);
|
||||
expect(predictions.map(portOf)).toEqual([
|
||||
40_009,
|
||||
40_012,
|
||||
40_015,
|
||||
40_018,
|
||||
39_997,
|
||||
39_994,
|
||||
39_991,
|
||||
39_988,
|
||||
]);
|
||||
expect(predictions.every((value) => value?.sdpMid === "0")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -134,9 +139,16 @@ describe("NAT prediction ICE adapter", () => {
|
||||
candidate(40_000),
|
||||
]);
|
||||
|
||||
expect(predictions.map(portOf)).toEqual(
|
||||
expect.arrayContaining([40_009, 39_997]),
|
||||
);
|
||||
expect(predictions.map(portOf)).toEqual([
|
||||
40_009,
|
||||
40_012,
|
||||
40_015,
|
||||
40_018,
|
||||
39_997,
|
||||
39_994,
|
||||
39_991,
|
||||
39_988,
|
||||
]);
|
||||
});
|
||||
|
||||
it("does not predict an unstable or incomplete mapping shape", () => {
|
||||
|
||||
Reference in new issue
Block a user