fix(nat): apply NAT experiment room-wide (#367)

This commit is contained in:
AAA authored and GitHub committed 2026-09-01 15:09:20 +08:00
1 parent 76a6eb7f85
commit 32c3f95c58
22 files changed
+329 -137

No files matched your search

@@ -12,19 +12,20 @@ receives a small set of adjacent server-reflexive candidates. The result is
network- and generation-specific; it is not a reliable NAT type or participant
capability.
The current WebRTC signaling contract already carries ICE candidates. A safe
experiment therefore needs no new message shape, route state, or media path.
The existing route-policy and ICE candidate owners are sufficient. Making the
experiment room-wide requires one strict protocol revision for the added policy
field, but no new message type, route-controller state, or media path.
## Decision
1. Host Advanced settings exposes `NAT traversal experiment`, disabled by
default and locked while sharing. The choice is local to that page and is
read when each new connection is created; it is not persisted or broadcast
as a room policy.
2. When enabled, Host-originated direct `HostPeer` connections add ports 3479
and 3480 for the same STUN authority already supplied by the server. The
server-provided STUN entries remain unchanged. SFU, ViewerPeer, and Viewer
relay connections keep the stock ICE configuration.
default and locked while sharing. It is part of the current share's room
policy and is broadcast to every authenticated Viewer; it is not persisted
beyond that share generation.
2. When enabled, every Browser P2P connection adds ports 3479 and 3480 for the
same STUN authority already supplied by the server. This covers Host direct,
Viewer upstream, and Viewer relay connections. SFU PeerConnections remain
unchanged.
3. For one ICE gathering generation, the adapter observes only UDP `srflx`
candidates. If three or more distinct candidates for one media section and
public address form an arithmetic port sequence, it appends at most eight
@@ -51,8 +52,8 @@ Negative:
- the Browser may still reject synthetic candidates or the NAT may not have a
matching mapping; and
- the current implementation covers Host-originated direct edges only. It does
not claim to improve Viewer relay edges or two endpoint-dependent NATs.
- two endpoint-dependent NATs remain sensitive to candidate scheduling and
intervening mappings, so room-wide coverage is not a success guarantee.
The controlled lab result (14/15 sequential-to-restricted runs with a bounded
prediction set) is mechanism evidence, not a production success guarantee.
+6 -8
View File
@@ -31,15 +31,13 @@ share generation:
failure; and
- native-edge topology convergence is enabled by default. The Host may disable
it before sharing; when disabled, quality evidence stays diagnostic and
availability routing is unchanged.
availability routing is unchanged;
- the default-off NAT traversal experiment augments direct ICE candidates on
every Browser P2P edge in that share. It is not a participant capability,
route score, or SFU preference. [ADR-0009](../adr/0009-connection-local-nat-prediction-experiment.md)
owns its bounded behavior and evidence boundary.
Host Advanced settings also contain an independent, default-off NAT traversal
experiment. It only augments Host-originated direct ICE candidates for the
current share generation; it is not a route policy, participant capability, or
SFU preference. [ADR-0009](../adr/0009-connection-local-nat-prediction-experiment.md)
owns its bounded behavior and evidence boundary.
These are route-policy gates, not new routing algorithms. Changing either
These are route-policy gates, not new routing algorithms. Changing any
policy requires stopping the current share and starting another generation.
## Endpoint And Server Capacity
+6 -6
View File
@@ -30,11 +30,11 @@ implementation and routine UI detail.
lease. Production enables optional SQLite stable room authority; live
participants, routes, and media remain process-only.
- Media is automatic and distributed. Ordinary peers are STUN-only and prefer
direct/peer UDP. Host may opt into a bounded, connection-local NAT candidate
experiment; the default path remains stock ICE. The only application
fallback is one bounded LiveKit SFU/UDP publication; Screener configures no
TURN or TCP media route. A pre-share peer-only policy can exclude that SFU
suffix for one share generation.
direct/peer UDP. Host may opt the current share into a bounded, room-wide,
connection-local NAT candidate experiment; the default path remains stock
ICE. The only application fallback is one bounded LiveKit SFU/UDP
publication; Screener configures no TURN or TCP media route. A pre-share
peer-only policy can exclude that SFU suffix for one share generation.
- Every endpoint shares one steady outbound-copy cap, default `2` and limited to
`1..3`. One room controller owns one committed graph, one reconcile loop, and
one serial child operation. First decoded frame commits availability work;
@@ -57,7 +57,7 @@ implementation and routine UI detail.
## Current Snapshot
Canonical source uses the strict `screener-v17` Browser/server contract with
Canonical source uses the strict `screener-v18` Browser/server contract with
committed media readiness, bounded candidate-relative progress and one-shot
Host-root convergence. It retains optional SQLite room authority and the
H.264/VP8 sender gate. [Status](./status.md) owns the compact current execution
+5 -4
View File
@@ -58,14 +58,15 @@ supports an opt-in mechanism, not a default or a participant-wide classifier.
The flagship STUN configuration remains unchanged. The self-hosted endpoint is
still the ordinary discovery service; ports 3479 and 3480 are optional
STUN-only listeners for an explicitly enabled Host experiment.
STUN-only listeners for an explicitly enabled room experiment.
The accepted experiment is deliberately connection-local and additive. It
derives the two auxiliary ports from the existing STUN authority, waits for a
clear three-point arithmetic `srflx` shape in one ICE generation, and appends a
small two-sided candidate window. All ordinary candidates remain available;
there is no NAT label, hard candidate skip, route-controller input, or SFU
preference. The UI switch is default off and locks while sharing. Its exact
preference. The Host switch is default off, locks while sharing, and applies to
Host, Viewer upstream, and Viewer relay P2P connections. Its exact
scope is recorded in [ADR-0009](../adr/0009-connection-local-nat-prediction-experiment.md).
The Browser-only alternatives do not yet have an accepted implementation:
@@ -102,8 +103,8 @@ fact. They cannot safely remove a Peer candidate or save its five-second window.
Port prediction remains an experiment rather than a default path. The
controlled namespace matrix supports the bounded mechanism, but field
prevalence, direction, and resource impact are not established. The experiment
therefore stays opt-in, Host-only, and additive until target-network evidence
justifies a wider decision.
therefore stays opt-in and additive until target-network evidence justifies
enabling it by default.
## Rejected Product Inference
+5 -5
View File
@@ -7,7 +7,7 @@ This is the current execution index. Git history owns completed timelines;
## Production
- `https://share.bonfire.icu` runs the strict `screener-v17` Browser/server
- `https://share.bonfire.icu` runs the strict `screener-v18` Browser/server
contract. Exact revision, release, artifact, manifest, and asset identity are
retained by the immutable release descriptor, runtime `REVISION`, and
deployment record rather than copied into this source snapshot.
@@ -49,7 +49,7 @@ This is the current execution index. Git history owns completed timelines;
## Current Source
- Canonical source uses the strict `screener-v17` Browser/server contract.
- Canonical source uses the strict `screener-v18` Browser/server contract.
Optional SQLite stable authority, non-expiring local preferred code, atomic
room replacement and the Host codec selector remain implemented; production
selects stable storage. Graceful restart, crash, timeout and network loss use
@@ -75,9 +75,9 @@ This is the current execution index. Git history owns completed timelines;
sender windows retain the bounded Peer operation; failed exact candidates stay
consumed until the sender or candidate opportunity changes. The pre-share gate
defaults on and locks while sharing.
- Host Advanced settings include a default-off, Host-originated NAT traversal
experiment. It adds only bounded, connection-local predicted ICE candidates;
ordinary candidates and the existing SFU fallback remain unchanged.
- Host Advanced settings include a default-off, per-share NAT traversal
experiment. Every Browser P2P role uses the same bounded, connection-local
candidate adapter; ordinary candidates and SFU fallback remain unchanged.
- Every direct, Browser-relay, and Host SFU video sender owns one clone of its
source track; the original remains presentation and source authority only.
Replacement, rollback, unpublish, physical LiveKit sender recreation, and
+2 -3
View File
@@ -81,14 +81,13 @@ until their stated boundary is met.
`MediaStream` output contract. Reopen only for a registered custom receiver
acting as an ordinary Viewer after a named Browser and physical receiver
pass the [platform-output gate](./research/platform-output.md).
14. **NAT inference and predictive candidates.** The default-off Host-only
14. **NAT inference and predictive candidates.** The default-off room-wide,
connection-local experiment is accepted under
[ADR-0009](./adr/0009-connection-local-nat-prediction-experiment.md). Keep
multi-STUN observations and injected candidates additive and diagnostic;
do not make them a participant-wide NAT label, hard candidate skip, route
score, or SFU preference. Validate target-network success, candidate
direction, and bounded resource impact before enabling it by default or
extending it to Viewer relay edges.
direction, and bounded resource impact before enabling it by default.
15. **Unresolved route-state ownership claims.** Reopen lower-revision
reauthentication, active SFU failure during an unrelated prepare, and
multi-child relay-evidence ownership only from an exact current-wire