Skip to main content

Paths and escalation

FREEHOP / NETWORK MODELThe path ladder
◈Direct peer
◇Session route
◈Remote peer

direct → gateway → relay → bridged → unreachable

Every pair of peers climbs the same ladder, and stops at the first step that works.

Every pair of peers in a call finds its own media route. Freehop tries the cheapest route first and only moves to the next step after the current attempt exhausts its time budget, so the cost stays with the two people talking whenever possible.

The ladder​

StepPathWhat carries the mediaTypical case
1directNothing in betweenSame LAN, IPv6 on both sides, or addresses discovered with STUN through ordinary home routers
2gatewayOne endpoint's own gatewayBen's carrier NAT cannot reach Dani directly, so he uses the front door of Dani's desktop app
3relayThe gateway of another session memberBen and Kai both sit behind random-port NATs; the session's host node relays for them
4bridgedAnother participant, forwarding the mediaBen and Kai cannot reach each other, but both reach Cleo, who is in the call anyway
unreachableNothingNo route exists inside the session; Freehop says so and keeps retrying slowly

The cost rule behind the ladder: a byte of media only crosses machines that belong to the call. Steps 2 to 4 use machines of the session itself (a participant's gateway, the host node, a participant), never the signalling gate. If you operate the session gateway, its media bandwidth is your cost.

When each step is tried​

Freehop follows the W3C perfect negotiation pattern. Each pair escalates through phases, and each phase has a time budget:

PhaseICE servers in useExpected routeMoves on when
0, endpointApplication-approved STUN, the peer's own gateway, the other peer's gatewaydirect or gatewayNot connected 5 s after the description; one more 5 s if connectivity checks are getting answers
1, sessionPlus up to 2 gateways of connected participants or gateway membersrelay7 s without a connection; one extra 7 s if checks get answers
2, bridgedUnchangedbridgedThe direct or session route later succeeds
no routeUnchangedunreachableNever gives up: ICE restarts after 30 s, 60 s, 120 s, 240 s, then every 300 s

A few rules keep the escalation stable:

  • One side restarts. The peer with the lexicographically greater id is polite. Only the other (impolite) side restarts ICE. The polite side applies the same servers and takes over after 2.5 s if no restart offer arrived. Simultaneous restarts collide: home-lab browser tests observed that a rolled-back restart offer could leave Chromium's senders silent.
  • Both sides gather against the same relays. A description names the extra gateways in use, and the receiver adds those servers before it answers.
  • Nothing deadlocks on a lost envelope. An offer that gets no answer within 8 s is rolled back and sent again. Candidates for an ICE generation that has not arrived yet wait in a buffer of 128.
  • Media is watched. If a connected link's live track sends no packets for two 5-second checks, the link restarts (the polite side asks the impolite side to do it).
  • Networks change. On disconnected a link waits 4 s, then restarts; on failed it restarts at once.

Optional rungs before "no route"​

Applications can opt into two more attempts at exactly the point where a pair would report unreachable. With neither option set, nothing above changes.

  • Port prediction (portPrediction: true). Some strict NATs hand out ports in order. When one side's NAT does and the other keeps one mapping (or also allocates in order), the link restarts once and probes the peer's next ports for up to 10 s, aiming for direct. Random NATs are never predicted.
  • Your own TURN relay (turn). Tried last, for up to 10 s; the path reports relay with via: 'turn'. The media stays encrypted end to end, but it crosses a relay you run or rent, so its bandwidth is yours. It stays the last resort after it connects: the pair checks for a cheaper route after a minute, then less often, and within seconds when a gateway it could use appears. When one works, the pair moves to it and releases the relay. A network that can only reach your gate still needs that relay to be reachable through what the network allows.

Play the timeline​

Step through the phases of one pair, or let it run. Each outcome stops at the phase where it connects.

Escalation timeline

retries: 30 s, 60 s, 120 s, 240 s, then every 5 min
Phase 0: endpoints
  1. Phase 0: endpoints5 s
    ICE servers
    Application-approved STUN, your own gateway and the other side's gateway.
    Route
    Direct (LAN, IPv6, STUN reflexive) or one endpoint’s own gateway.
    Moves on when
    Not connected 5 s after the description, plus one 5 s grace period if connectivity checks get answers.
  2. Phase 1: session gateways7 s
    ICE servers
    Adds up to two gateways of other members: a desktop participant or the host node.
    Route
    Relay through a session gateway, still encrypted end to end.
    Moves on when
    Only the impolite peer restarts ICE; the polite one takes over after 2.5 s. Not connected after 7 s, plus one 7 s grace period if checks get answers.
  3. Phase 2: bridginguntil a route appears
    ICE servers
    Unchanged.
    Route
    A connected participant forwards the media. The lower peer id asks; the other side takes over after 4 s.
    Moves on when
    When the direct or session route later connects, the bridge is released.
  4. Unreachable30 s to 5 min
    ICE servers
    Unchanged.
    Route
    None inside the session. By default Freehop reports it instead of renting a relay; an app can opt into its own.
    Moves on when
    ICE restarts after 30 s, 60 s, 120 s, 240 s, then every 300 s. New members or a network change can open a route.

Phase budgets come from the client's defaults; connection times here are illustrative. The 4-second bridge wait is an initiator fallback, not a deadline that proves a pair unreachable. A phase with no eligible gateway or bridge can be skipped. Working routes are used as soon as they connect.

Worked examples​

Each row below comes from the original home-lab network tests, before the later security fixes, and passed three out of three Chromium runs; the results page also lists the Firefox and WebKit runs. The home-built test environment simulates each network with a Linux kernel NAT profile; physical carrier networks are not yet verified.

People in the callSimulated networksWhat happensResultTest scenario
Two participants like AnaTwo ordinary home routersSTUN-discovered addresses work, because each router keeps the same public port for every destinationdirectdirect-eim
Ivy and a friend on the same kind of networkIPv6 on both sides, IPv4 UDP blockedGlobal IPv6 addresses; the stateful firewalls let the replies in once both sides senddirectipv6-direct
Ben and Kai, aloneTwo random-port (symmetric) NATsNeither NAT keeps a port the other side can predict, and nobody else is in the sessionunreachablehard-pair
Ben, Kai and CleoTwo random-port NATs and a public addressBen and Kai each reach Cleo directly. Cleo forwards their media to each otherBen–Kai bridgedvia Cleohard-pair-bridge
Ben and DaniRandom-port NAT and a desktop app behind a UPnP routerBen connects to Dani's own gateway through the port her router openedgatewayvia Danitwo-peer-desktop-host
Ben, Kai and DaniTwo random-port NATs and a desktop appBoth reach Dani's gateway. Ben and Kai then relay through itBen–Kai relayvia Danihard-pair-gateway
Omar and DaniUDP-blocking office and a desktop appOmar reaches Dani's gateway with TURN over TCPgatewayvia Daniudpblock-gateway
Omar, a colleague in another UDP-blocking office, and DaniTwo UDP-blocking offices and a desktop appBoth use Dani's gateway over TCP, and relay through it to each otherrelayvia Daniudpblock-pair-gateway
Ben and Kai in a hosted sessionTwo random-port NATs, a host node with a public addressThe host node joins without media and relays for themrelayvia host nodehard-pair-host-node
Omar and a colleague in a hosted sessionTwo UDP-blocking offices, a host nodeBoth reach the host node over TCPrelayvia host nodeudpblock-pair-host-node
Gus with Ana and CleoA guest network that only reaches the gate hostAna and Cleo connect directly. Gus can reach nothing but the gateGus unreachable, Ana–Cleo directgate-only

The last row is the honest boundary. A network that can only reach the gate has no media route. A separately configured session gateway must be reachable over a transport the network permits; the gate cannot relay media. See Limits.

Find a path​

Pick a network for Ana and for Ben, and choose who else is in the session. The model shows a possible route under those assumptions, why, and what your own server carries.

Path finder

Illustrative network model, not a test of your connection. Figures below come from Freehop's original home-lab network tests, before the later security fixes.

Ana's network A symmetric NAT that picks a new random port for every destination, as some carrier and campus NATs do.
Ben's network A symmetric NAT that picks a new random port for every destination, as some carrier and campus NATs do.
Also in the session
GATEANASTRICT NATBENSTRICT NATRELAYhost nodeHOST ON / DESKTOP OFF / THIRD PEER OFF
relayvia host node

Relayed by the session's host node.

Both strict NATs pick a new random port for every destination, so neither side can predict where to send. After the 5-second endpoint budget (plus a grace period if checks get answers), Freehop adds the gateways of other session members (up to two at a time) and restarts ICE. The host node's gateway is reachable from both of you, so media relays there. It stays encrypted end to end: the relay only moves ciphertext.

When
Phase 1: session gateways, next 7 s
Your servers
Sealed signalling only. Media bytes: 0.
Home-lab test evidence
hard-pair-host-node 3/3 Chromium, 1/1 Firefox + WebKit passed, gate traffic 62–73 KB per run.

How the path is classified​

When a link connects, Freehop reads the selected ICE candidate pair:

  • no relay candidate on either side: direct;
  • a relay owned by one of the two endpoints: gateway;
  • a relay owned by another member of the session: relay;
  • media arriving through a forwarding participant: bridged;
  • nothing works and no bridge candidate exists: unreachable.

A local peer-reflexive candidate whose relayProtocol is set still rides a relay, and is classified as one. The SDK reports every change as a path event, with via naming the gateway owner or forwarder:

session.on('path', ({ peer, kind, via }) => {
label(peer).textContent = via ? `${kind} via ${nameOf(via)}` : kind;
});

While a pair is bridged or unreachable, it keeps trying the cheaper routes with cheap ICE restarts. When a direct or session route connects later, the bridge is released.

Next​

Gateways and port mapping explains step 2, the participant's own front door.