ClearChat

Under the hood · 10 min read

How WebRTC opens a call between two browsers

Signalling, ICE candidates, STUN, the DTLS handshake and SRTP — the four steps every browser call goes through, explained without the spec language.

WebRTC is the technology that lets two browsers exchange audio, video and data directly. It ships in every current browser, needs no plugin, and is what ClearChat is built on.

It is also famously confusing, because it solves four separate problems at once and the documentation tends to describe all four simultaneously. Here they are one at a time.

The problem it's solving

Two browsers want to send each other video. Neither has a public address anyone can dial. Both sit behind a home router doing network address translation, so from the outside they share one address with every other device in the house. Neither knows what video formats the other supports. And neither has any way to send the other a message.

That last one is the catch: WebRTC cannot start itself. Something outside it has to carry the first message.

Step 1 — Signalling: you carry the first message

One side generates an offer: a block of text in SDP format listing the media it wants to send, the codecs it speaks, and a fingerprint of the certificate it will use for encryption. The other side replies with an answer in the same format.

WebRTC does not specify how those two blobs get from one browser to the other. That is left entirely to you. A WebSocket to a small server is typical. So is a QR code, a chat message, or — as ClearChat originally did — copying a code and pasting it into WhatsApp.

This is why every “serverless” claim deserves a second look. Signalling always happens. It just doesn't have to be big, and it doesn't have to see your media.

Step 2 — ICE: finding a route that works

Now both sides know what the other wants. They still don't know how to reach each other.

ICE (Interactive Connectivity Establishment) solves this by brute force: each side gathers every address it might be reachable on, sends the list over, and then both sides try every combination until something works.

The addresses, called candidates, come in kinds:

Candidates are usually sent as they're discovered rather than all at once — trickle ICE — so connection setup can start before gathering finishes.

Step 3 — DTLS: agreeing on keys

Once a route is found, the two sides perform a DTLS handshake — essentially TLS over UDP — and derive the keys used to encrypt media.

The important detail is how each side knows it is talking to the right party. Remember the fingerprint in the SDP from step 1? After the handshake, each side checks that the certificate the other actually presented matches the fingerprint that arrived through signalling. If they differ, the connection is dropped.

That check is what ties encryption to identity — and it is why the signalling channel matters so much more than it first appears. Whoever controls signalling can substitute a fingerprint. That threat, and what can be done about it, is the subject of is your call really end-to-end encrypted.

Step 4 — SRTP and data channels: the actual call

With keys agreed, media flows as SRTP — encrypted RTP. This is not optional. WebRTC has no unencrypted mode; a browser will not send plain RTP at all.

Alongside media, WebRTC offers data channels, which carry arbitrary bytes over SCTP with the same encryption. Text chat, file transfer and small control messages all ride here. ClearChat uses one data channel for your messages and a second for coordination between the two browsers.

Changing things mid-call

Swapping your camera for a screen share does not require redoing any of the above. The sender object exposes replaceTrack(), which swaps the media source underneath an established connection with no new offer and no interruption.

This matters more than it sounds. In a design like ClearChat's, where the signalling socket closes once the call is up, replaceTrack() is the only way to change what you're sending — there is no longer a channel to negotiate over. It's why screen sharing can be added to a live call at all.

Watching it happen

Open chrome://webrtc-internals in a Chromium browser (or about:webrtc in Firefox) before starting a call. You'll see the offer and answer in full, every candidate as it's gathered, which pair won, and live statistics for packets, bitrate and round-trip time.

It is the fastest way to turn “it doesn't work” into a specific answer about which of the four steps failed.

← All guides · Start a call