Repository navigation
feat(webrtc): true ICE-Lite listener for WebRTC-Direct (#1512) - #1532
Conversation
The spec requires the publicly-reachable server to act as an ICE-Lite agent: respond to the controlling dialer's STUN checks, never initiate its own, and stay in the controlled role (RFC 8445 §2.1, §6.1.1). go-libp2p (pion SetLite(true)) and rust-libp2p (webrtc-rs set_lite) flip a native flag; aioice has no local lite mode (only remote_is_lite), so its controlled agent still sends connectivity checks. make_connection_ice_lite() makes the muxed listener connection genuinely Lite: - check_start (aioice's sole sender of connectivity-check requests) is replaced with a respond-only version that marks the pair valid and completes ICE on the dialer's USE-CANDIDATE nomination -- no check ever goes on the wire. - switch_role is pinned so the agent stays controlled even if a peer sends an ICE-CONTROLLED attribute (a Lite agent never switches; otherwise the respond-only agent could not self-nominate and ICE would fail). Binding responses and consent-freshness liveness are unchanged. Verified against go-libp2p v0.49 (go->py and py->py, v1+v2) -- all complete with zero outbound connectivity checks from the listener. Closes libp2p#1512
|
Note on CI: both red checks are unrelated flakes, not from this PR (which only touches
A re-run should clear both. |
Make ice_lite a flag on the mux connection factory so the listener cannot forget the override, assert controlled role, document harness vs spec path, and pin aioice 0.10.x for the private-API surface Lite relies on. Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
Review (with follow-ups applied)
Earlier AI/maintainer review of this PR rated it Ready for the core ICE-Lite change (make_connection_ice_lite, respond-only check_start, pinned switch_role, tests + 1512.feature.rst). Full write-up: local downloads/AI-PR-REVIEWS/1532/AI-PR-REVIEW-1532-0.md.
Completions landed on this branch (f95e378d)
Addressed the optional in-repo nits from that review:
ice_lite=onUdpMux.add_ice_connection— listener usesice_lite=Trueso Lite cannot be forgotten on a second call site.assert not conn.ice_controllinginmake_connection_ice_lite, plus harness docstring noting Lite is STUN/spec-path only (not the experimental/sdppath).- Explicit
aioice>=0.10.0,<0.11in thewebrtcextra so the private-API surface Lite relies on stays pinned.
Out of scope for this PR (as discussed): consent config flag, and upstreaming Lite into aioice. Tracking for a native aioice Lite mode: aiortc/aioice#114.
Merge plan
Approve. Waiting for CI/CD checks to go green, then squash-merge.
|
@acul71 PR ready for merge, no conflicts, and all ci checks passed successfully |
|
Gentle nudge on this one: @acul71 approved it on 2026-09-14, CI is green (38/38) and GitHub reports it mergeable with no conflicts, but it has been sitting open since. Nothing is blocking it that I can see. @acul71 @sumanjeet0012 — could one of you merge it, or tell me what it still needs? @seetadev flagging it too since it predates the 0.8.0 release and would be good to have in the next one. Happy to rebase onto current |
Closes #1512. The last open blocker on the #1437 WebRTC-Direct track.
The spec requirement
The libp2p WebRTC-Direct spec: "Given that B is publicly reachable, B acts as an [ICE Lite] agent." A Lite agent responds to the controlling dialer's STUN checks, never initiates its own, and stays in the controlled role (RFC 8445 §2.1, §6.1.1). go-libp2p (
pion SetLite(true)) and rust-libp2p (webrtc-rs set_lite) get this from a native flag in their ICE stack. aioice has no local lite mode (onlyremote_is_lite), so its controlled agent still sent connectivity checks — leaving the py listener non-Lite (it interoperated only because the dialer does all the work).The change
make_connection_ice_lite()makes the muxed listener connection genuinely Lite:check_start— aioice's sole sender of connectivity-check requests — is replaced with a respond-only version that marks the pair valid and completes ICE on the dialer'sUSE-CANDIDATEnomination. No check ever goes on the wire; binding responses still flow.switch_roleis pinned so the agent stays controlled even if a peer sends anICE-CONTROLLEDattribute (a Lite agent never switches — otherwise the respond-only agent could not self-nominate and ICE would fail).Consent-freshness liveness is unchanged, matching pion's Lite.
Verification
ICE-CONTROLLEDattribute.tests/core/transport/webrtc246 passed; ruff / format / mypy clean.The change was adversarially reviewed across five dimensions (override correctness, spec/interop, regression, lifecycle, test fragility); the two confirmed findings — the role-switch edge and a consent-timing test flake — are fixed in this PR.
Notes: touches aioice 0.10.x internals (the same private-API surface
attach_muxed_connection/add_ice_connectionalready rely on), guarded with asserts that fail loudly on an aioice bump.