cmux-next iOS: WireGuard by default, WebRTC media session for browser video
Draft
AZ
17d ago+4258+4258+0123456789012345678901234567890123456789-133-133-012345678901234567890123456789
Summary
cmux-next iOS: WireGuard becomes the default link, and browser video rides a WebRTC media session beside it.
- Default transport. New installs dial WireGuard. A saved choice stays. Settings → Transport lists "WireGuard (recommended)" and "WebRTC only". "WebRTC only" behaves as before.
- Media session. When the link is WireGuard, the phone opens a WebRTC peer connection to the same Mac's cnx-hostd. It carries only the browser video track. It uses the same TeamHub signaling (
webrtc-offerwith a newmediaFor) and the same Cloudflare TURN credentials. It is negotiated with a newwebrtc-medialane inwg-init/wg-resp. - Routes and fallback. The Mac's media lane has two routes: the media session's track (preferred) and RTP in the tunnel (the floor). Video changes route only at a keyframe. A dead session (ICE failed/closed) or a silent one (500 ms without TWCC feedback) falls back to the tunnel, then to the
browserchannel as before. Video moves back when the session is up again. The phone gates sources by keyframe and capture time, so a late frame from the old route never reaches the decoder. - Lifecycle. The session opens lazily: on a shown browser tab, or on a warm-up when the workspace has browser tabs. It closes 30 s after no tab is visible, or when the app goes to the background. It never delays the link or the terminal.
- Mac. hostd answers a media offer only for a live WireGuard link of the same phone device and owner that passed pairing. There is no new trust path.
- Input. Input stays on the WireGuard input lane (see
verify/hybrid-link.md"Input path"). - Labels.
- Phone: "Connected · WireGuard direct · video WebRTC (TURN) · 14 ms".
- Mac:
phone_mediaevent; the iPhone card shows "Video over WebRTC (TURN)".
The contract is in PROTOCOL.md under "Media session". Design, tests, review and live measurements are in cnx-ios/verify/hybrid-link.md.
Tests
- Rust (rbx):
cargo test --workspacegreen; clippy-D warningsand fmt clean. New:cnx-link/tests/hybrid.rs(4 tests: switch, fallback and return, silent stall, Block UDP, older peers);media::routes(7);- the gate tests in
media; cnx-ffibrowser_video_rides_the_media_session_beside_wireguard;- hostd
media_sessionrefusal test.
- The floor-stall fix has a red commit, then a green one.
- Swift on mini-cmux11s: CnxKit, 411 tests in 109 suites, including the new
TransportDefaultTestsandLinkStatusMediaTests. CmuxNextCnxHostTestspassed as a fleet step.
Review
A fresh correctness-first subagent found 2 must-fix and 2 should-fix issues. All are fixed. The table is in verify/hybrid-link.md.
Live check (real link, mini-cmuxs-mac-mini-3, fleet Mac cnx-e2e-ce1d3585 + Demo simulator)
- Hybrid vs WireGuard-only. Every frame rode the requested carrier. Glass-to-glass p50 was 40 and 83 ms for hybrid and 56 and 51 ms for WireGuard-only, at 24 to 35 fps. The mini's load was 500 to 900, so the comparison is noisy, and on a direct path the two carriers are within noise.
- Killed media session. Video moved to tunnel RTP in 0.23 s and back to WebRTC 1.0 s later. Each switch happened at a keyframe.
- Silent black hole. The stall was detected in 595 ms and video fell back. It returned within 0.4 s after the black hole was removed. The longest frame gap was 650 ms, and the tab never went black.
- Block UDP. The link ran over TURN over TLS. The media session failed and retried with backoff, and video stayed on tunnel RTP.
- Phone label. Settings → Devices shows "Connected · WireGuard direct · video WebRTC (direct) · 0 ms". The picker shows "WireGuard (recommended)" and "WebRTC only".
- Not checked live. The Mac's iPhone card was not looked at in the GUI because that would need focus. It is unit-tested.
Changelog
none (cmux-next iOS, unreleased)
🤖 Generated with Claude Code