e-speak

Candidate Gathering Latency and the Mechanics of Trickle ICE

By Nadia Ferrante

Interactive Connectivity Establishment (ICE), standardized in RFC 8445, provides the baseline state machine for NAT traversal in real-time communications. In its original formulation, an ICE agent was expected to complete the gathering of every local, server reflexive, and relayed candidate before generating a Session Description Protocol (SDP) offer or answer. For voice systems operating under strict latency budgets, this blocking approach degrades call setup time.

The extension known as Trickle ICE, specified in RFC 8838, addresses this gathering tax by decoupling the candidate discovery process from the initial signaling exchange. This document details the underlying state transitions, the network overhead imposed by pre-gathering, and the specific failure profiles that emerge when transmitting media over non-converged candidate pairs.

The Vanilla ICE Gathering Model and Setup Delays

The vanilla ICE model assumes a strict phase ordering: candidate gathering, offer/answer exchange, connectivity checks, nomination, and media flow. Gathering all transport addresses before generating the initial SDP message creates a latency floor that no downstream optimization can recover.

"The original Interactive Connectivity Establishment (ICE) specification [RFC5245] required an agent to complete the entire candidate gathering phase before sending the initial offer or answer." — RFC 8838, Section 1.

The Serialized Gathering Bottleneck

When an endpoint initializes an ICE agent without trickling, it must interrogate every available physical and virtual network interface. Host candidates are gathered almost instantaneously via local operating system socket queries (getsockname or Netlink sockets on Linux). However, server reflexive and relayed candidates depend entirely on network I/O with remote infrastructure.

To obtain server reflexive candidates, the client sends Session Traversal Utilities for NAT (STUN) Binding Requests to a configured STUN server, as specified in RFC 5389. This involves: 1. DNS resolution for the STUN server hostnames (typically an A and AAAA query per server). 2. Transmission of the STUN Binding Request UDP datagram. 3. Waiting for the STUN Binding Response containing the XOR-MAPPED-ADDRESS attribute.

Relayed candidates gathered via Traversal Using Relays around NAT (TURN), defined in RFC 8656, are more costly. The client must execute a full Allocate transaction. If authentication is enabled—which is the case in production deployments—the initial Allocate request returns a 401 Unauthorized response with a nonce and realm. The client must then compute a message integrity digest over the credentials and transmit a second Allocate request.

If the STUN or TURN servers are situated 40 ms away (a round-trip time of 80 ms), the TURN allocation alone consumes a minimum of 160 ms of network transit time, assuming zero packet loss and immediate processing. If IPv6 is present alongside IPv4, or if multiple network interfaces exist (such as an active Wi-Fi interface and an active LTE/5G interface), this gathering phase executes concurrently or serially across all interfaces. In environments with slow or timing-out DNS resolvers, gathering frequently blocks for 1200 ms to 3000 ms before an SDP offer can be formatted.

Pacing Timers and Retransmission Delays

STUN retransmissions introduce heavy tail latency when endpoints pre-gather. RFC 5389 specifies an initial Retransmission TimeOut (RTO) of 500 ms for UDP transactions, doubling for each subsequent attempt (binary exponential backoff: 500 ms, 1000 ms, 2000 ms). If a single UDP datagram directed to a STUN server is dropped, the vanilla ICE agent remains blocked in the gathering phase for at least 500 ms while awaiting the timer expiry.

A standard STUN transaction aborts after 7 consecutive unacknowledged requests, spanning a total window of 39.5 s. While most application-level implementations apply an internal cap on gathering time—often between 2000 ms and 5000 ms—the call setup cannot proceed until either that timer fires or all transactions complete. Holding the initial SIP INVITE or WebSockets signaling message until the gathering timeout clears creates an unacceptable user experience, as ring delays directly degrade perceptual call quality.

Mechanics of Incremental Candidate Exchange

Trickle ICE eliminates the gathering gate by permitting the ICE agent to transmit an offer containing only a subset of candidates—frequently just the host candidates, or an empty candidate list containing only a default dummy transport address—and streaming additional candidates over the signaling path as they are discovered.

Incremental State Machine and Candidate Pairing

In a Trickle ICE session, the agent initializes the ICE checklist as soon as the answer arrives, even if only host candidates are available on both sides. The ICE checklist consists of candidate pairs formed by taking the Cartesian product of local and remote candidates:

$$\text{Pair} = (Local, Remote)$$

As subsequent candidates arrive via out-of-band signaling messages, the ICE agent inserts them into the existing checklist dynamically. Every pair is assigned a state: FROZEN, WAITING, IN-PROGRESS, SUCCEEDED, or FAILED. The priority of each pair is computed using the formula defined in RFC 8445:

$$\text{Priority} = 2^{32} \times \min(P_o, P_a) + 2 \times \max(P_o, P_a) + (P_o > P_a ? 1 : 0)$$

where $P_o$ is the priority of the candidate provided by the controlling agent, and $P_a$ is the priority provided by the controlled agent.

` +------------+ +-----------+ +---------------+

+------------+ +-----------+ +---------------+ ^ | | (on retry) v +-----------+ +---------------+ | FAILED | | SUCCEEDED | +-----------+ +---------------+ `

The checklist must be continuously re-sorted by priority as new pairs are injected. To prevent flooding the local uplink with STUN checks, the transmission of checks is paced by the timer Ta, specified in RFC 8445 with a minimum default value of 50 ms (or 20 ms under specific congestion control conditions; I would check the specific stack configuration here, as some browser engines alter Ta dynamically). When a new high-priority candidate pair arrives via trickle signaling, it can preempt the check schedule, entering the WAITING state ahead of lower-priority pairs that were queued earlier.

Pruning and Regular Nomination

Because connectivity checks begin while gathering is active, endpoints typically establish peer-to-peer connectivity using host candidates before TURN allocations complete. If both endpoints reside on the same enterprise subnet or maintain direct public IPv4/IPv6 addresses, the connectivity checks over the host-to-host pair transition to SUCCEEDED within a single RTT.

Under regular nomination, once a check succeeds, the controlling ICE agent sends a subsequent STUN request on that pair with the USE-CANDIDATE attribute asserted. As soon as the response is received, the pair is nominated, and the agent begins transmitting media. TURN allocations that complete later in the background yield candidate pairs that are simply added to the checklist, evaluated, and pruned, without having contributed to call setup delay.

The session signaling signals completion via an end-of-candidates indication per media line (or for the entire session if BUNDLE is used). This explicitly transitions the ICE checklist from the dynamic gathering state to the final evaluation state, terminating any outstanding WAITING checks for candidate combinations that can no longer yield a higher-priority path.

Impairment Behaviors: Loss and Jitter Dynamics

When connectivity checks traverse an impaired IP path, the pacing and state progression of Trickle ICE diverge significantly from non-trickle runs. In network paths characterized by 15% packet loss or jitter swings exceeding 100 ms, STUN checks can experience false timeouts. If an initial STUN check is dropped, the Ta timer schedules the next pair in the checklist while the unacknowledged transaction waits for its RTO. If the signaling channel carries new trickle candidates during this period, high-priority pairs are continually inserted into the queue, multiplying the number of concurrent unacknowledged STUN transactions.

High jitter introduces out-of-order STUN responses, which trigger race conditions in controlling agents that use aggressive nomination. If an older STUN response arrives after a newer, lower-priority candidate check has succeeded, the agent must update its valid list without regressing the selected pair. Furthermore, if the signaling channel itself drops trickle notifications—such as when candidate metadata is multiplexed over an unreliable transport or a congested SIP control plane—the endpoints may reach an uncoordinated state where the controlled agent is checking pairs that the controlling agent has not yet mapped, returning STUN 400 Bad Request or silent drops due to unknown Message-Integrity identifiers.

Once the selected pair is nominated and RTP flows, these impairments alter media quality directly. A 64 kbps G.711 stream or an Opus payload configured for 20 ms frames will suffer immediate burst loss if nomination switches the path from a direct host route to a relayed route mid-session due to late-arriving checks.

Implementation Complexities and Edge Conditions

Trickle ICE is not without trade-offs. The protocol pushes complexity from the endpoints' local network stacks directly into the signaling layer.

Signaling State Synchronization

The primary failure mode in Trickle ICE implementations is the arrival of candidate fragments prior to the arrival and processing of the remote offer or answer. If endpoint A sends an offer, starts gathering, and immediately trickles candidate cand-1 to endpoint B, cand-1 may arrive at endpoint B before endpoint B has unpacked the initial SDP offer.

` Endpoint A Signaling Server Endpoint B | | | |--- Offer (empty candidates) ---->| | |--- Trickle candidate 1 --------->| | | |--- Trickle candidate 1 -->| (DROPPED: No SDP state) | |--- Offer --------------->| `

An ICE agent cannot pair a remote candidate against local candidates if the remote media description does not yet exist. The application layer must maintain a candidate buffer. Candidate messages that arrive before the initial offer/answer exchange settles must be stored in a staging queue and drained into the ICE engine only after setRemoteDescription (or its platform-specific equivalent) returns successfully. If the application layer discards these out-of-sequence candidates instead of buffering them, the checklist will omit valid paths, occasionally leaving the session with zero viable candidate pairs and causing an ICE failure (ICEConnectionStateFailed).

Half-Trickle Support

Heterogeneous environments require handling half-trickle scenarios, where one endpoint supports RFC 8838 and the remote peer does not (e.g., legacy SIP-to-WebRTC gateways). In a half-trickle architecture:

Attempting to emit trickle candidate fragments to an endpoint that did not negotiate trickle support will result in unparsed SIP INFO packets, ignored WebSocket frames, or immediate session termination depending on the strictness of the remote parser.

Candidate Churn and NAT Bindings

Gathering everything up front has one distinct advantage: by the time connectivity checks start, the endpoint knows every IP address it owns. With Trickle ICE, the local topology can change during the gathering phase. On dual-stack mobile endpoints moving from cellular to Wi-Fi, candidates may trickle in for interfaces that lose connectivity 300 ms later.

Each candidate allocation consumes state on middleboxes. A TURN server allocating relay ports binds resources for each client transaction (default lifetime of 600 s in RFC 8656). When an endpoint uses trickle ICE aggressively, it often allocates TURN resources that are never checked because a direct host or server reflexive pair succeeded before the TURN allocate transaction even hit the network. While this minimizes latency to first audio, it increases port allocation churn and processing overhead on TURN relay infrastructure.

The operational baseline remains clear:

Never hold signaling for candidate discovery; emit the offer immediately with local host candidates, trickle reflexive and relay addresses as they resolve, and terminate ICE checklists the instant nomination confirms a viable pair.

FROZEN---->WAITING---->IN-PROGRESS