Skip to main content

07 — WebRTC Connection Flow

The complete lifecycle from "Join Room" click to audio flowing through the SFU, including every negotiation stage. Target budget: < 2 s p50, < 5 s p95 from click to first audio (direct UDP path).

Sequence Diagram

Stage-by-Stage Detail

1. Authentication. Client holds a 15-min access JWT (from login or silent refresh). No network round-trip if cached — auth is usually a zero-cost stage at join time.

2. Room authorization. POST /rooms/{id}/join is the single bootstrap call. Room Service checks ban list, capacity, room status; resolves the caller's role (moderator/speaker/listener); pins the room's media_region on first join; mints the media token (short-lived JWT the SFU validates — role mapped to canPublish/canSubscribe grants) and fetches ICE servers from TURN Management server-side. One round-trip delivers everything: signaling ticket, media token, ICE config, current roster. Rationale: fewer client round-trips, and clients never talk to TURN Management directly except for mid-call credential refresh.

3. WebSocket connection. Client opens WSS to the regional signaling endpoint with the one-time ticket. On success it has an authenticated, sequence-numbered channel with resume semantics (05).

4–5. SDP offer/answer. Client creates its RTCPeerConnection with the ICE server list, adds the local Opus audio track (if speaker), and sends the offer. The SFU is the remote peer: it validates the media token, creates the participant/transport, and answers. Listeners produce a recv-only offer. Renegotiation (new subscriptions as speakers join) reuses the same exchange server-initiated.

6. ICE gathering (parallel with 4–5, trickled). The client discovers candidates: host (local iface), server-reflexive via STUN Binding to the Coturn fleet, and relay via TURN Allocate using the HMAC credential. Candidates are trickled as found — we never wait for gathering to complete.

7. TURN credential retrieval. Already in hand from stage 2 (no extra round-trip on the join path). Mid-call, if credentials near expiry before an ICE restart, the client calls POST /ice/credentials directly.

8. ICE negotiation. Both agents run STUN connectivity checks across candidate pairs, priority-ordered so direct UDP wins when possible: host ↔ host > srflx > relay. Controlling side nominates the first working pair. TURN relay engages only when NAT/firewall blocks everything else (~8–15 % of sessions in practice; we provision TURN for ~20 %). If UDP is blocked entirely, TURN over TCP/TLS:5349 is the last resort.

9. DTLS handshake. Over the nominated pair, client and SFU perform DTLS. Each side verifies the peer certificate's fingerprint against the a=fingerprint from the signaled SDP — this binds the encrypted transport to the authenticated signaling exchange (no MITM without breaking signaling auth).

10. SRTP establishment. DTLS-SRTP key export: both sides derive SRTP/SRTCP session keys from the DTLS master secret. All media from here is SRTP-encrypted with per-packet auth tags; RTCP is SRTCP.

11. Media forwarding. Speaker clients publish Opus (48 kHz, inband FEC on, DTX on; target 32–64 kbps). The SFU forwards each producer's packets to that room's subscribers — no decode/re-encode (that's the SFU-vs-MCU point), just selective forwarding with per-subscriber congestion control (transport-cc; audio may drop FEC layers under pressure). media_ready flows back through signaling for UX ("you are live") and analytics (join-latency metric).

12. Active speaker updates. The SFU measures audio levels (RFC 6464 header extensions + energy), computes the dominant-speaker set, and pushes updates through Signaling (active_speakers, throttled) and to Kafka (sampled) for analytics.

Failure Points & Client Behavior

Stage failsClient behavior
2 (join 4xx)surface reason (full/banned/closed); no retry loop
3 (WS)retry with backoff ≤ 3, then re-join (new ticket)
8 (ICE all pairs fail)ICE restart with fresh credentials; if repeated, force relay-only (iceTransportPolicy: relay) as diagnostic fallback
9–10 (DTLS)treat as fatal transport error → full ICE restart
Mid-call network change (Wi-Fi→LTE)ICE restart (ufrag/pwd refresh) over existing signaling; media resumes without rejoin
WS drops but media aliveresume within 90 s window; media unaffected
SFU node diessignaling ice_restart to new node (room re-hosted); target < 3 s audio gap — see 09