fix(webrtc): wire the WebRTC-Direct inbound path; spec Noise roles; real loopback test - #1447
Open
yashksaini-coder wants to merge 4 commits into
Open
Conversation
tox commands_pre installed no extras, so aiortc was absent in CI and every test under tests/core/transport/webrtc was skipped on GitHub. aiortc 1.15 is pure Python and its native deps (av, pylibsrtp) ship manylinux/win wheels, so no system packages are needed. Refs libp2p#1437
…oles The listener's inbound completion was a stub: after ICE it logged and returned, so no inbound connection ever reached the handler. dial() was broken too - get_remote_fingerprint read attributes aiortc does not have. - listener: own a trio nursery (system task, like TCP), hop asyncio->trio without blocking the loop, run Noise XX as *initiator* (spec: server initiates, dialer responds), then hand the authenticated connection to the handler; bound in-flight unauthenticated inbounds. - transport.dial(): Noise responder; verify authenticated peer ID against /p2p/ after the handshake. - noise: role-ordered prologue (dialer fingerprint, then server); PatternXX.handshake_outbound(remote_peer=None) skips only the ID equality check; DataChannelReadWriter.read(n) honours n (the Noise packet reader asks for the 2-byte prefix alone). - helpers: get_remote_fingerprint reads pc.sctp.transport._ssl peer cert; noise send waits for data channel 0 to open. - tests: transport-level dial->listen->stream echo loopback, wrong /p2p/ rejection, e2e Noise role test, buffered read test, fingerprint test. Refs libp2p#1437
- Frame Noise handshake bytes as uvarint-prefixed webrtc.pb.Message stream frames on channel 0 (spec 'Multiplexing'; what go/js do) instead of raw bytes - required for interop; py<->py was symmetric so tests did not notice. - Listener: guard the handler call - the nursery lives in a trio system task, so an escaping exception aborted the whole trio run. - dial(): bound the Noise phase (responder's first step is a read) with handshake_timeout; close the PC on every failure path, not just the two explicit mismatches; do not pass config.ice_servers (previously no STUN servers were used; the default Google STUN added ~5s to offline dials). - Tests: framing round-trip/chunking/FIN/malformed, handler-exception regression. Refs libp2p#1437
yashksaini-coder
force-pushed
the
fix/webrtc-direct-inbound-wiring
branch
from
August 19, 2026 17:56
104ae51 to
fb35ba6
Compare
Contributor
Author
|
@seetadev @acul71 Rebased on latest main; CI fully green (incl. Windows). This PR makes WebRTC-Direct actually connect end-to-end: the inbound path was a stub and |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
First code step for #1437. Makes WebRTC-Direct actually connect end to end (it did not):
_complete_inboundlogged and returned; handler never called). Now: listener-owned trio nursery (system task, like TCP), non-blocking asyncio→trio hop, Noise XX as initiator (spec: server initiates, dialer responds), authenticatedWebRTCConnectionhanded to the handler. In-flight unauthenticated inbounds bounded bymax_in_flight_connections.dial()was broken:get_remote_fingerprintreadpc._dtlsTransport._remote_certificate, which aiortc doesn't have. Now reads the DTLS peer cert frompc.sctp.transport._ssl. Dialer is the Noise responder and verifies the authenticated ID against/p2p/.dialer_fp ‖ server_fp, per spec) instead of local/remote.PatternXX.handshake_outbound(remote_peer: ID | None)— skips only the equality check whenNone(server doesn't know the dialer's ID); signature verification unchanged. Existing callers unaffected.DataChannelReadWriter.read(n)now honoursn— the Noise packet reader asks for the 2-byte length prefix alone; returning a whole channel message broke framing.sendwaits for data channel 0 to open (initiator sends right after DTLS, before SCTP opens the channel →InvalidStateError).Tests
test_dial_listen_open_stream_echo: dial → ICE/DTLS → Noise → handler → stream echo, both sides see the other's peer ID. Plus wrong-/p2p/rejection, e2e Noise role test, buffered-read test, fingerprint test,remote_peer=Nonepattern test.tests/core/transport/webrtc+tests/core/security/noise: 319 passed locally; loopback run 5× no flake. mypy/pyrefly clean.Stacked on #1446 (CI needs aiortc installed for these to run); will rebase once that merges.
Refs #1437