feat(webrtc): support webrtc-direct v2#3520
Conversation
Chrome is removing the SDP munging that v1 browser-to-server dials rely on (the WebRTC-NoSdpMangleUfrag field trial), so the listener now also speaks the v2 flow, which carries the client's ICE password in the server ufrag instead of munging. Implements libp2p/specs#715. - listener: parse both halves of the STUN USERNAME, dispatch on the ufrag prefix (v1, v2, or reject an unknown version), recover the v2 client password, and set pion's ICE credentials to match. - udpmux: surface the server and client ufrag separately and key the mux on the server (local) ufrag, which is what pion looks up. - validation: reject STUN USERNAME fragments outside the RFC 8839 ice-char set or length bounds before they reach SDP. - dialer: add opt-in WithDialerVersion(2) that emits the v2 wire format for go-to-go and testing; v1 stays the default. - tests: parsing/validation units plus end-to-end v1 and v2 dials against a single listener.
|
Is this tested via the interop tester? |
|
@sukunrt Not via the interop tester yet. It dials I did verify v2 manually end to end against real Chrome (munging off) and js-libp2p both ways: #3499 (comment) (see specific commits listed there) So iiuc once JS ships dialling v2 (libp2p/js-libp2p#3480) we'll have browser-to-go v2 running as part of CI interop in libp2p/test-plans. |
|
Can you add an integration test here? I think you just need to enable the V2Dialer option. |
Can we enable go v2 dialer to go server meanwhile and add the js dialer when it's merged? |
The transport integration tests only exercised the default (v1) dial flow. Add an explicit v2 case so the no-munging path has coverage against the shared listener, which accepts both versions and selects one from the ufrag prefix. Both variants run the full battery (ping, streams, resets, deadlines, rcmgr); the WebRTC name gates move from exact match to substring so v1 and v2 are gated identically.
|
Thanks for pointer @sukunrt, added in 53e9c5a. The transport integration tests now run a It's go dialer to go server, so self-consistency rather than cross-implementation interop. iiuc the JS dialer side lands in libp2p/test-plans once libp2p/js-libp2p#3480 merges, so this PR can be merged without blocking? |
The udpmux now owns parsing and validation of the STUN USERNAME, so a malformed or unsupported request is dropped before the mux allocates a connection or queues a candidate for the listener. - udpmux: credentialsFromSTUNMessage validates both ICE ufrags, selects the WebRTC Direct version, and recovers the client password before getOrCreateConn. The ice-char validators and the v1/v2 ufrag prefixes live in ufrag.go, so the listener no longer re-validates. - udpmux: rename Candidate.Ufrag to LocalUfrag, add RemotePwd, and name the local ufrag consistently across the maps and helpers. - udpmux: drop the empty-ufrag guard in RemoveConnByUfrag, now unreachable since empty ufrags fail validation upstream. - transport: New defaults dialerVersion to 1 so dial never handles the confusing 0 value; the dialer reads udpmux.UfragPrefixV1/V2.
Problem
/webrtc-directlets a browser dial a public libp2p server with no signalling and no CA-signed cert. That path works by "munging" the local SDP so the server can predict the browser's ICE credentials, and Chrome is taking that ability away (theWebRTC-NoSdpMangleUfragfield trial). Once it reaches stable, browsers can no longer open/webrtc-directconnections to a go-libp2p server, which is the whole reason the transport exists.I documented it in libp2p/specs#672 (comment)
Fix
v2 spec avoids "munging" and is proposed at:
This PR implements it while maintaining backward-compatibility with v1 clients too
Details
USERNAMEwith no signalling;WithDialerVersion("v2")lets a go node dial v2; v1 stays the default for now. can be flipped in future PR, but also does not matter, GO will not do the dials, JS will (feat: webrtc-direct-v2 js-libp2p#3480), so this is just for formal parity and testingTesting
This keeps browser-to-server connectivity alive once Chrome flips the trial; verified end to end against a real Chrome (v2, munging off) and js-libp2p both ways.
Details: #3499 (comment)
References