RFC 8838
Trickle ICE: Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (ICE) Protocol
RFC 8838: Trickle ICE: Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (ICE) Protocol ๐
Okay bestie, this one is from the IETF (the Internet Engineering Task Force), and it's on the Standards Track ๐ It's dated January 2021, and its ISSN is 2070-1721.
The authors are E. Ivov (8x8 / Jitsi), J. Uberti (Google), and P. Saint-Andre (Mozilla). Their whole squad made this, so it's giving collab energy โจ
The header doesn't list anything this RFC obsoletes or updates, so there's no drama with older docs here ๐
Abstract
This document describes "Trickle ICE", an extension to the Interactive Connectivity Establishment (ICE) protocol ๐ฆ It lets ICE agents start connectivity checks while they're still gathering candidates, by swapping candidates bit by bit over time instead of dumping them all at once. Main-character move. This method can considerably speed up setting up a communication session ๐
Status of This Memo
This is an Internet Standards Track document ๐ธ
It's a product of the Internet Engineering Task Force (IETF), so it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841 ๐
For the current status, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8838 ๐
Copyright Notice
Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved. ๐
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as in effect on the date of publication. Please read these carefully, because they spell out your rights and restrictions for this document ๐งพ Any Code Components pulled out of this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions. They're provided without warranty, as described in the Simplified BSD License ๐ซถ
Table of Contents
1. Introduction
2. Terminology
3. Determining Support for Trickle ICE
4. Generating the Initial ICE Description
5. Handling the Initial ICE Description and Generating the Initial
ICE Response
6. Handling the Initial ICE Response
7. Forming Checklists
8. Performing Connectivity Checks
9. Gathering and Conveying Newly Gathered Local Candidates
10. Pairing Newly Gathered Local Candidates
11. Receiving Trickled Candidates
12. Inserting Trickled Candidate Pairs into a Checklist
13. Generating an End-of-Candidates Indication
14. Receiving an End-of-Candidates Indication
15. Subsequent Exchanges and ICE Restarts
16. Half Trickle
17. Preserving Candidate Order While Trickling
18. Requirements for Using Protocols
19. IANA Considerations
20. Security Considerations
21. References
21.1. Normative References
21.2. Informative References
Appendix A. Interaction with Regular ICE
Appendix B. Interaction with ICE-Lite
Acknowledgements
Authors' Addresses
1. Introduction โจ
The Interactive Connectivity Establishment (ICE) protocol [RFC8445] explains how an ICE agent gathers candidates, swaps candidates with a peer ICE agent, and creates candidate pairs. Once the pairs are gathered, the ICE agent runs connectivity checks and eventually nominates and selects the pairs that will send and receive data during the session ๐
Following the procedures in [RFC8445] can make session setup take kinda long ๐ฅฒ That's because candidate gathering often means querying Session Traversal Utilities for NAT (STUN) servers [RFC5389] and allocating relayed candidates on Traversal Using Relay NAT (TURN) servers [RFC5766]. Lots of ICE steps can run in parallel, but the pacing requirements from [RFC8445] still need to be followed โณ
This document defines "Trickle ICE", a supplementary mode of ICE operation. Candidates can be exchanged incrementally as soon as they're available (and at the same time as other candidates are being gathered). Connectivity checks can start as soon as candidate pairs have been created ๐ฆ Since Trickle ICE lets candidate gathering and connectivity checks happen in parallel, it can considerably speed up setting up a communication session. It's so efficient ๐ญ
This document also covers how to discover support for Trickle ICE, how the procedures in [RFC8445] are modified or supplemented when you use Trickle ICE, and how a Trickle ICE agent can interoperate with an ICE agent that complies with [RFC8445] ๐ง
Here's the tea: this document doesn't define any protocol-specific usage of Trickle ICE. Those details live in separate usage documents. Examples are [RFC8840], which defines usage with the Session Initiation Protocol (SIP) [RFC3261] and the Session Description Protocol (SDP) [RFC4566], and [XEP-0176], which defines usage with the Extensible Messaging and Presence Protocol (XMPP) [RFC6120]. Some examples in this document do use SDP and the Offer/Answer model [RFC3264] to explain the core ideas, though ๐
Here's a diagram of a successful Trickle ICE exchange with a using protocol that follows the Offer/Answer model ๐
Alice Bob
| Offer |
|---------------------------------------------->|
| Additional Candidates |
|---------------------------------------------->|
| Answer |
|<----------------------------------------------|
| Additional Candidates |
|<----------------------------------------------|
| Additional Candidates and Connectivity Checks |
|<--------------------------------------------->|
|<========== CONNECTION ESTABLISHED ===========>|
Figure 1: Flow
The main body of this document describes what Trickle ICE agents do, roughly in the order things happen during an ICE session ๐
- Determining support for Trickle ICE
- Generating the initial ICE description
- Handling the initial ICE description and generating the initial ICE response
- Handling the initial ICE response
- Forming checklists, pruning candidates, performing connectivity checks, etc.
- Gathering and conveying candidates after the initial ICE description and response
- Handling inbound trickled candidates
- Generating and handling the end-of-candidates indication
- Handling ICE restarts
Fun fact: there's quite a bit of real operational experience behind the technique, going back to 2005, when the XMPP Jingle extension defined a "dribble mode" as specified in [XEP-0176] ๐ฐ๏ธ This document also picks up feedback from folks who've implemented and deployed the technique over the years ๐ซถ
2. Terminology ๐
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here. Only the capitalized versions count, so read them carefully ๐
This specification uses all the terminology defined for Interactive Connectivity Establishment in [RFC8445]. On top of that, it defines these terms:
Empty Checklist: A checklist that doesn't contain any candidate pairs at the start, because they'll be added one by one as they're trickled. (This doesn't happen with a regular ICE agent, since all candidate pairs are already known when the agent creates the checklist set.) ๐ซ
Full Trickle: The typical way Trickle ICE agents operate. The initial ICE description can include any number of candidates (even zero), and it doesn't need to include a full generation of candidates the way half trickle does ๐ซ
Generation: All of the candidates conveyed within an ICE session, correlated with one particular combination of Username Fragment and Password ๐งฉ
Half Trickle: A Trickle ICE mode where the initiator gathers a full generation of candidates strictly before creating and conveying the initial ICE description. Once that's sent, regular ICE agents, which don't need Trickle ICE support, can process it. It also lets Trickle-ICE-capable responders keep gathering candidates and running connectivity checks without blocking, so you get roughly "half" the perks of Trickle ICE ๐ The half-trickle mechanism is mostly meant for when the responder's support for Trickle ICE can't be confirmed before the initial ICE description is conveyed.
ICE Description: Any attributes related to the ICE session (other than candidates) that are needed to configure an ICE agent. These include but aren't limited to the Username Fragment, the Password, and other attributes ๐ ๏ธ
Trickled Candidates: Candidates that a Trickle ICE agent conveys after it has conveyed or responded to the initial ICE description, but still within the same ICE session. Trickled candidates can be conveyed in parallel with candidate gathering and connectivity checks โก
Trickling: The act of incrementally conveying trickled candidates ๐
3. Determining Support for Trickle ICE โจ
okay so bestie, to fully support Trickle ICE, using protocols SHOULD bring in one of these mechanisms so implementations can figure out whether Trickle ICE is supported ๐:
- Provide a capabilities discovery method so agents can verify Trickle ICE support before starting a session (XMPP's Service Discovery [XEP-0030] is one such mechanism ๐ ).
- Make support for Trickle ICE mandatory so user agents can just assume it's there ๐ซถ.
If a using protocol doesn't have a way to figure out ahead of time whether Trickle ICE is supported, agents can use the half-trickle procedure described in Section 16 ๐.
Before sending the initial ICE description, agents whose using protocols support capabilities discovery can check whether the remote party supports Trickle ICE. If an agent finds out the remote party doesn't support it, it MUST fall back to using regular ICE or abandon the entire session ๐.
Even if a using protocol has no capabilities discovery method, a user agent can show that it supports Trickle ICE inside the ICE description by including an ICE option of 'trickle'. This token MUST be provided either at the session level or, if at the data stream level, for every data stream (an agent MUST NOT specify Trickle ICE support for some data streams but not others). ๐ Note: The encoding of the 'trickle' ICE option, and the message(s) used to carry it to the peer, are protocol specific. For instance, the encoding for SDP [RFC4566] is defined in [RFC8840].
Dedicated discovery semantics and half trickle are needed only before an ICE session starts. Once an ICE session is established and both parties have confirmed Trickle ICE support, either agent can use full trickle for later exchanges (see also Section 15) ๐ฆ.
4. Generating the Initial ICE Description ๐
An ICE agent can start gathering candidates as soon as it gets a hint that communication is coming (like a user-interface cue or an explicit request to start a session) ๐. Unlike regular ICE, Trickle ICE implementations don't have to gather candidates in a blocking way. So unless half trickle is being used, the user experience gets better when the initiating agent generates and sends its initial ICE description as early as possible, which lets the remote party start gathering and trickling candidates sooner ๐.
An initiator MAY include any mix of candidates when it conveys the initial ICE description. That could mean sending every candidate it plans to use (like half trickle does), sending only a publicly reachable IP address (for example, a candidate at a data relay that's known to not be behind a firewall), or sending no candidates at all. With no candidates, the initiator can get the responder's initial candidate list sooner, and the responder can start gathering more quickly โก.
For candidates included in the initial ICE description, calculating priorities and foundations, figuring out redundancy, and everything else works just like regular ICE [RFC8445] ๐.
5. Handling the Initial ICE Description and Generating the Initial ICE Response ๐
When a responder gets the initial ICE description, it first checks whether the ICE description or the initiator indicates Trickle ICE support, as explained in Section 3 ๐. If it doesn't, the responder MUST process the initial ICE description according to regular ICE procedures [RFC8445]. (Or, if no ICE support is detected at all, it follows the relevant processing rules for the using protocol, such as the Offer/Answer processing rules [RFC3264].) But if Trickle ICE support is confirmed, the responder automatically assumes regular ICE support too ๐ซถ.
If the initial ICE description shows Trickle ICE support, the responder works out its role and starts gathering and prioritizing candidates. While it's doing that, it also sends back an initial ICE response, so both the initiator and the responder can form checklists and start connectivity checks ๐โโ๏ธ๐จ.
A responder can respond to the initial ICE description at any point while it's still gathering candidates. The initial ICE response MAY contain any set of candidates, including all of them or none at all. (Sending no candidates is useful because the initial ICE response goes out as fast as possible, so both parties can see the ICE session as actively being negotiated right away ๐.)
As noted in Section 3, in using protocols that use SDP, the initial ICE response can show Trickle ICE support by including a token of trickle in the ice-options attribute ๐ง.
6. Handling the Initial ICE Response ๐
When the initiator processes the initial ICE response, it follows regular ICE procedures to determine its role. After that, it forms checklists (Section 7) and performs connectivity checks (Section 8) โ .
7. Forming Checklists ๐
According to regular ICE procedures [RFC8445], for candidate pairing to be possible and for redundant candidates to get pruned, the candidates need to be provided in the initial ICE description and the initial ICE response. Trickle ICE is different: checklists can be empty until candidates are conveyed or received ๐คฏ. So a Trickle ICE agent handles checklist formation and candidate pairing a little differently from a regular ICE agent. It still forms the checklists, but it only fills a given checklist once it actually has candidate pairs for that checklist. Every checklist starts out in the Running state, even if it's empty (this is consistent with Section 6.1.2.1 of [RFC8445]) ๐ธ.
8. Performing Connectivity Checks โก
As specified in [RFC8445], whenever timer Ta fires, only checklists in the Running state get picked when scheduling connectivity checks for candidate pairs. So a Trickle ICE agent MUST keep each checklist in the Running state for as long as it expects candidate pairs to keep getting added to it ๐. After that, the checklist state is set according to the procedures in [RFC8445].
Whenever timer Ta fires and an empty checklist gets picked, nothing happens for that list. Without waiting for timer Ta to expire again, the agent selects the next checklist in the Running state, in accordance with Section 6.1.4.2 of [RFC8445] ๐.
Section 7.2.5.4 of [RFC8445] requires that agents update checklists and timer states when a connectivity check transaction completes. During that update, regular ICE agents set a checklist to Failed if both of these conditions are satisfied:
- all of the pairs in the checklist are in either the Failed state or the Succeeded state; and
- there is not a pair in the valid list for each component of the data stream.
With Trickle ICE, that situation happens a lot while candidate gathering and trickling are still going on, even though future checks might totally succeed ๐ญ. So Trickle ICE agents add these conditions to the list above:
- all candidate gathering has completed, and the agent is not expecting to discover any new local candidates; and
- the remote agent has conveyed an end-of-candidates indication for that checklist as described in Section 13.
9. Gathering and Conveying Newly Gathered Local Candidates ๐ฆ
After Trickle ICE agents have sent their initial ICE descriptions and initial ICE responses, they'll most likely keep gathering new local candidates as STUN, TURN, and other non-host candidate gathering mechanisms start to pay off ๐. Whenever an agent finds a new candidate, it computes the candidate's priority, type, foundation, and component ID according to regular ICE procedures.
Then the new candidate gets checked for redundancy against the existing list of local candidates. If its transport address and base match an existing candidate's, it's considered redundant and gets ignored ๐๏ธ. This often happens with server-reflexive candidates that match the host addresses they were obtained from (for example, when those host addresses are public IPv4 addresses). Unlike regular ICE, Trickle ICE agents consider the new candidate redundant regardless of its priority.
Next, the agent "trickles" the newly discovered candidate(s) to the remote agent. Delivery is handled by a using protocol such as SIP or XMPP, and Trickle ICE puts no restrictions on how that's done. (For example, some using protocols might choose not to trickle updates for server-reflexive candidates and instead rely on discovering peer-reflexive ones ๐ .)
When candidates are trickled, the using protocol MUST deliver each candidate (and any end-of-candidates indication as described in Section 13) to the receiving Trickle ICE implementation exactly once and in the same order it was conveyed ๐ฏ. If the using protocol does any candidate retransmissions, the ICE implementation shouldn't see them ๐.
Candidate trickling also needs to be tied to a specific ICE session. That way, if there's an ICE restart, any delayed updates from a previous session can be recognized and ignored by the receiving party ๐ซ. For example, using protocols that signal candidates via SDP might include a Username Fragment value in the corresponding a=candidate line, like this:
a=candidate:1 1 UDP 2130706431 2001:db8::1 5000 typ host ufrag 8hhY
Or, as another example, WebRTC implementations might include a Username Fragment in the JavaScript objects that represent candidates ๐งโโ๏ธ.
๐ Note: The using protocol needs to give both parties a way to indicate and agree on the ICE session in force (as identified by the Username Fragment and Password combination), so they have a consistent view of which candidates are supposed to be paired. This is especially important for ICE restarts (see Section 15) ๐.
๐ Note: A using protocol might prefer not to trickle server-reflexive candidates to entities that are known to be publicly accessible, since sending a direct STUN binding request is likely to reach the destination faster than a trickle update traveling through the signaling path ๐๐.
10. Pairing Newly Gathered Local Candidates โจ
okay so bestie, this is where the agent takes the local candidates it just gathered and starts building candidate pairs ๐๐ the ICE spec [RFC8445] already explains how pairing works, but Trickle ICE has a few extra rules on top, so let's go through them ๐ซถ
- A Trickle ICE agent MUST NOT pair a local candidate until it has been trickled to the remote party. no cap, this is a hard rule ๐ โโ๏ธ๐
- Once the agent has conveyed the local candidate to the remote party, it checks whether any remote candidates are already known for this same stream and component. if none are known, the agent just adds the new candidate to its list of local candidates and doesn't pair it yet ๐ธ
- otherwise, if the agent has already learned one or more remote candidates for this stream and component, it tries to pair the new local candidate as described in [RFC8445] ๐ฆ
- if a newly formed pair has a local candidate whose type is server-reflexive, the agent MUST replace that local candidate with its base before completing the relevant redundancy tests ๐ง
- the agent prunes redundant pairs by following the rules in Section 6.1.2.4 of [RFC8445], but it only checks existing pairs whose state is Waiting or Frozen ๐ this is so it doesn't remove pairs with connectivity checks in flight (In-Progress) or pairs that already have a definitive result (Succeeded or Failed) ๐ญ
- if, after the redundancy tests, the checklist already has the maximum number of candidate pairs (100 by default as per [RFC8445]), the agent SHOULD discard any pairs in the Failed state to make room ๐ if there are no Failed pairs, the agent SHOULD discard a pair with a lower priority than the new pair, until the number of pairs equals the maximum. this matches Section 6.1.2.5 of [RFC8445] ๐
11. Receiving Trickled Candidates ๐
at any time during an ICE session, a Trickle ICE agent might get new candidates from the remote agent ๐ฌ it'll try to form a candidate pair from them, and again the ICE spec [RFC8445] is the base, with these provisos:
- the agent checks whether any local candidates are already known for this same stream and component. if not, it just adds the new candidate to its list of remote candidates without pairing it ๐
- otherwise, if the agent has already gathered one or more local candidates for this stream and component, it tries to pair the new remote candidate as described in [RFC8445] ๐ฆ
- if a newly formed pair has a local candidate whose type is server-reflexive, the agent MUST replace that local candidate with its base before doing the redundancy check in the next step ๐ง
- the agent prunes redundant pairs as described below, but only checks existing pairs whose state is Waiting or Frozen ๐ same reasoning as before: pairs with checks In-Progress or a definitive result of Succeeded or Failed stay put ๐
- A. if the agent finds a redundancy between two pairs and one of them contains a newly received remote candidate whose type is peer-reflexive, the agent SHOULD discard the pair containing that candidate, set the priority of the existing pair to the priority of the discarded pair, and re-sort the checklist โจ this helps fix problems with remote peer-reflexive candidates that get a STUN Binding request before the candidate is trickled to the receiving agent ๐ซ (like when the two agents see pair priorities differently, since one might call the same candidate peer-reflexive while the other calls it server-reflexive)
- B. the agent then applies the rules in Section 6.1.2.4 of [RFC8445] ๐
- if, after the redundancy tests, the checklist already has the maximum number of candidate pairs (100 by default as per [RFC8445]), the agent SHOULD discard any Failed pairs to make room ๐ if there are none, it SHOULD discard a lower-priority pair than the new one until the count equals the maximum. this is consistent with Section 6.1.2.5 of [RFC8445] ๐
12. Inserting Trickled Candidate Pairs into a Checklist โจ
Okay so, bestie, this is where a newly formed candidate pair finds its home ๐ก. After a local agent has trickled a candidate and formed a candidate pair from that local candidate (Section 9), or after a remote agent has received a trickled candidate and formed a candidate pair from that remote candidate (Section 11), a Trickle ICE agent adds the new candidate pair to a checklist as this section defines. ๐
To make this easier to picture, the spec gives us a table of all the checklists in an agent ๐. Heads up: at first, foundation f5 has no candidate pairs at all ๐ฅบ.
+=================+====+====+====+====+====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+====+====+====+
| s1 (Audio.RTP) | F | F | F | | |
+-----------------+----+----+----+----+----+
| s2 (Audio.RTCP) | F | F | F | F | |
+-----------------+----+----+----+----+----+
| s3 (Video.RTP) | F | | | | |
+-----------------+----+----+----+----+----+
| s4 (Video.RTCP) | F | | | | |
+-----------------+----+----+----+----+----+
Table 1: Example of Checklist State
Each row is a component for a given data stream. So s1 and s2 could be the RTP and RTP Control Protocol (RTCP) components for audio, and each row is basically its own checklist in the checklist set ๐. Each column is one foundation, and each cell is one candidate pair. In this section's tables, "F" means "frozen", "W" means "waiting", and "S" means "succeeded", and "^^" marks the candidate pairs that were just added ๐ฆ.
When an agent starts ICE processing, following Section 6.1.2.6 of [RFC8445], it unfreezes, for each foundation, the pair with the lowest component ID. If the component IDs are equal, it goes with the highest priority instead. That's the topmost pair in every column ๐. Here's the starting vibe:
+=================+====+====+====+====+====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+====+====+====+
| s1 (Audio.RTP) | W | W | W | | |
+-----------------+----+----+----+----+----+
| s2 (Audio.RTCP) | F | F | F | W | |
+-----------------+----+----+----+----+----+
| s3 (Video.RTP) | F | | | | |
+-----------------+----+----+----+----+----+
| s4 (Video.RTCP) | F | | | | |
+-----------------+----+----+----+----+----+
Table 2: Initial Checklist State
Then, as the checks go on (see Section 7.2.5.4 of [RFC8445]), every pair that hits the Succeeded state ("S") makes the agent unfreeze all pairs for all data streams that share its foundation ๐. So if the pair in column 1, row 1 succeeds, the agent unfreezes the pairs in column 1, rows 2, 3, and 4. Iconic. ๐
+=================+====+====+====+====+====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+====+====+====+
| s1 (Audio.RTP) | S | W | W | | |
+-----------------+----+----+----+----+----+
| s2 (Audio.RTCP) | W | F | F | W | |
+-----------------+----+----+----+----+----+
| s3 (Video.RTP) | W | | | | |
+-----------------+----+----+----+----+----+
| s4 (Video.RTCP) | W | | | | |
+-----------------+----+----+----+----+----+
Table 3: Checklist State with Succeeded
Candidate Pair
Trickle ICE keeps all of these rules for "static" checklist sets too ๐ง. So if a Trickle ICE agent started its checks with every pair already present, the way the pair states change would look exactly like a regular ICE agent. No difference at all, ngl ๐ .
The big difference with Trickle ICE is that checklist sets can keep changing, since candidates can show up after checks have already started ๐ญ. When that happens, the agent sets the state of the new pair using the rules below. โจ
Rule 1: If the newly formed pair has the lowest component ID and, if the component IDs are equal, the highest priority of any candidate pair for this foundation (so basically, if it's the topmost pair in its column), set the state to Waiting. For example, this happens if the newly formed pair lands in column 5, row 1. This rule matches Section 6.1.2.6 of [RFC8445]. ๐ฅ
+=================+====+====+====+====+=====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+====+====+=====+
| s1 (Audio.RTP) | S | W | W | | ^W^ |
+-----------------+----+----+----+----+-----+
| s2 (Audio.RTCP) | W | F | F | W | |
+-----------------+----+----+----+----+-----+
| s3 (Video.RTP) | W | | | | |
+-----------------+----+----+----+----+-----+
| s4 (Video.RTCP) | W | | | | |
+-----------------+----+----+----+----+-----+
Table 4: Checklist State with Newly
Formed Pair, Rule 1
Rule 2: If there's at least one pair in the Succeeded state for this foundation, set the state to Waiting. For example, this happens if the pair in column 5, row 1 succeeded and the newly formed pair lands in column 5, row 2. This rule matches Section 7.2.5.3.3 of [RFC8445]. ๐ซถ
+=================+====+====+====+====+=====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+====+====+=====+
| s1 (Audio.RTP) | S | W | W | | S |
+-----------------+----+----+----+----+-----+
| s2 (Audio.RTCP) | W | F | F | W | ^W^ |
+-----------------+----+----+----+----+-----+
| s3 (Video.RTP) | W | | | | |
+-----------------+----+----+----+----+-----+
| s4 (Video.RTCP) | W | | | | |
+-----------------+----+----+----+----+-----+
Table 5: Checklist State with Newly
Formed Pair, Rule 2
Rule 3: In every other case, set the state to Frozen. For example, this happens if the newly formed pair lands in column 3, row 3. ๐ง
+=================+====+====+=====+====+====+
| | f1 | f2 | f3 | f4 | f5 |
+=================+====+====+=====+====+====+
| s1 (Audio.RTP) | S | W | W | | S |
+-----------------+----+----+-----+----+----+
| s2 (Audio.RTCP) | W | F | F | W | W |
+-----------------+----+----+-----+----+----+
| s3 (Video.RTP) | W | | ^F^ | | |
+-----------------+----+----+-----+----+----+
| s4 (Video.RTCP) | W | | | | |
+-----------------+----+----+-----+----+----+
Table 6: Checklist State with Newly
Formed Pair, Rule 3
13. Generating an End-of-Candidates Indication ๐
Once candidate gathering finishes or times out for an ICE session tied to a specific data stream, the agent generates an "end-of-candidates" indication for that session and sends it to the remote agent over the signaling channel ๐จ. The exact form depends on the using protocol, but the indication MUST specify the generation (the Username Fragment and Password combination) ๐. That's how an agent matches the end-of-candidates indication to the right ICE session. Here's how it can be sent:
- As part of an initiation request. This is usually how it goes with the initial ICE description for half trickle ๐ธ
- Along with the last candidate an agent sends for a stream ๐
- As a standalone notification. For example, after STUN Binding requests or TURN Allocate requests to a server time out and the agent is no longer actively gathering candidates ๐ด
Sending the end-of-candidates indication on time really matters ๐ฐ๏ธ. It avoids confusion and speeds up the end of ICE processing. Specifically:
- A controlled Trickle ICE agent SHOULD convey an end-of-candidates indication after it has finished gathering for a data stream, unless ICE processing ends before the agent gets the chance to finish gathering. ๐ฆ
- A controlling agent MAY conclude ICE processing before it has conveyed end-of-candidates indications for all streams. However, it is RECOMMENDED for a controlling agent to convey end-of-candidates indications whenever possible. That keeps things consistent and keeps middleboxes and controlled agents up to date on how ICE processing is going ๐
When an agent conveys an end-of-candidates indication while trickling (instead of in the initial ICE description or a response to it), the using protocol is responsible for defining how the indication gets tied to one or more specific data streams ๐งฉ.
An agent MAY also choose to generate an end-of-candidates indication before candidate gathering has actually finished, if it decides gathering has been going on for longer than an acceptable amount of time โณ. Just remember, an agent MUST NOT convey any more candidates after it has conveyed an end-of-candidates indication. No take-backsies ๐ โโ๏ธ.
When an agent performs half trickle, it SHOULD convey an end-of-candidates indication together with its initial ICE description, unless it's planning to possibly trickle more candidates (for example, in case the remote party turns out to support Trickle ICE) ๐ค.
After an agent conveys the end-of-candidates indication, it updates the state of the matching checklist as Section 8 explains ๐. From that point on, an agent MUST NOT trickle any new candidates within this ICE session. So if you want to add new candidates to the negotiation, the only way is an ICE restart (see Section 15) ๐.
This spec doesn't override the regular ICE rules for ending ICE processing ๐. So even when end-of-candidates indications have been conveyed, an agent still has to go through pair nomination. Also, if pairs have been nominated for components and data streams, ICE processing MAY still conclude even if end-of-candidates indications haven't come in for every stream. Either way, an agent MUST NOT trickle any new candidates within an ICE session after nomination of a candidate pair, as Section 8.1.1 of [RFC8445] describes ๐โจ.
14. Receiving an End-of-Candidates Indication ๐
okay bestie, so getting an end-of-candidates indication lets an agent update its checklist states ๐. If valid pairs don't exist for every component in every data stream, the agent can figure out that ICE processing has failed ๐ญ. It also helps things move faster when a candidate pair has already been validated but uses a lower-preference transport like TURN โก. In that situation, an implementation MAY wait and see if higher-priority candidates show up ๐. The end-of-candidates indication basically says "don't wait, nothing better is coming" ๐ซถ.
When an agent gets an end-of-candidates indication for a specific data stream, it updates the state of the relevant checklist as per Section 8 ๐ . This can mean some checklists get marked as Failed ๐. If the checklist is still in the Running state after the update, the agent notes that it got an end-of-candidates indication and takes that into account in future checklist updates ๐ง .
After an agent has received an end-of-candidates indication, it MUST ignore any newly received candidates for that data stream or data session ๐ซ. No late arrivals, periodt โจ.
15. Subsequent Exchanges and ICE Restarts ๐
Before conveying an end-of-candidates indication, either agent MAY send more candidate info at any time the using protocol allows ๐ฌ. When that happens, the agents use the semantics from [RFC8445] (like checking the Username Fragment and Password combo) to figure out whether the new candidate info needs an ICE restart ๐ต๏ธโโ๏ธ.
If an ICE restart does happen, the agents can assume Trickle ICE is still supported, as long as support was figured out earlier ๐ฆ. So they can keep doing Trickle ICE behavior, the same way they would in an initial exchange of ICE descriptions where support was determined through a capabilities discovery method ๐.
16. Half Trickle ๐
Okay, half trickle is giving "compromise" energy and I'm here for it ๐ฅน. The initiator sends the initial ICE description with a usable but not necessarily full generation of candidates ๐. This makes sure a regular ICE responder can still process the description ๐งธ. It's mostly for situations where Trickle ICE support can't be confirmed before the initial ICE description is sent ๐คทโโ๏ธ.
The initial ICE description says "hey, I support Trickle ICE!" so the responder can reply with less than a full generation of candidates and trickle the rest later ๐. The initial ICE description for half trickle can include an end-of-candidates indication, but it's not mandatory ๐. Why? Because if trickle support is confirmed, the initiator can just trickle more candidates before sending an end-of-candidates indication โจ.
Half trickle is useful when an agent has no way to check ahead of time whether the remote party supports Trickle ICE ๐. Since the initial ICE description has a full generation of candidates, a regular ICE agent can handle it no problem ๐ช. Meanwhile, a Trickle ICE agent can still use the optimization defined in this specification ๐. Negotiation doesn't fail for the regular agent, and the Trickle ICE agent still gets roughly half the Trickle ICE benefits ๐ธ.
Half trickle is only needed during an initial exchange of ICE descriptions ๐. Once both parties have received an ICE description from their peer, they can each reliably determine Trickle ICE support and use it for all later exchanges (see Section 15) ๐.
Sometimes half trickle can bring more than half the UX improvement ๐คฉ. This happens when an agent starts gathering candidates based on UI cues that the user is about to start an interaction, like keypad activity or the phone going off hook ๐. That means some or all of the candidate gathering could be finished before the agent actually has to send the candidate info ๐โโ๏ธ. Since the responder can trickle candidates, both agents can start connectivity checks and finish ICE processing earlier than with regular ICE, and potentially as early as with full trickle ๐.
But anticipation isn't always possible ๐ฎโ๐จ. For example, a multipurpose user agent, or a WebRTC web page where calling is a non-central feature (like calling a support line when the main features break), might not be able to tell call intentions apart from other user activity ๐ต. In those cases, full trickle is most likely to give the ideal user experience ๐. Even so, half trickle is still an upgrade over regular ICE, because responders get a better experience too ๐ซถ.
17. Preserving Candidate Order While Trickling ๐ข
Here's the tea โ. A key thing about regular ICE is that connectivity checks for a specific foundation and component are attempted at the same time by both agents ๐ค. This way, any firewalls or NATs in front of the agents whitelist both endpoints and let everything through except the first ("suicide") packets ๐งฑ. It also matters for unfreezing candidates at the right time โฐ. It's not crucial, but keeping this behavior in Trickle ICE will likely improve ICE performance ๐.
To make that happen, when trickling candidates, agents SHOULD respect the order of components as shown by their component IDs ๐ข. In other words, candidates for a given component SHOULD NOT be sent before candidates for a component with a lower ID number within the same foundation ๐ โโ๏ธ. Also, candidates SHOULD be paired, using the procedures in Section 12, in the same order they're sent ๐งฉ.
Here's an example SDP description with two components (RTP and RTCP) and two foundations (host and server-reflexive) ๐:
v=0
o=jdoe 2890844526 2890842807 IN IP4 10.0.1.1
s=
c=IN IP4 10.0.1.1
t=0 0
a=ice-pwd:asd88fgpdd777uzjYhagZg
a=ice-ufrag:8hhY
m=audio 5000 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=candidate:1 1 UDP 2130706431 10.0.1.1 5000 typ host
a=candidate:1 2 UDP 2130706431 10.0.1.1 5001 typ host
a=candidate:2 1 UDP 1694498815 192.0.2.3 5000 typ srflx
raddr 10.0.1.1 rport 8998
a=candidate:2 2 UDP 1694498815 192.0.2.3 5001 typ srflx
raddr 10.0.1.1 rport 8998
For this candidate info, the RTCP host candidate would not be sent before the RTP host candidate ๐ โโ๏ธ. Similarly, the RTP server-reflexive candidate would be sent together with or before the RTCP server-reflexive candidate ๐ .
18. Requirements for Using Protocols ๐
To fully enable Trickle ICE, this specification defines the following requirements for using protocols ๐.
- A using protocol SHOULD provide a way for parties to advertise and discover support for Trickle ICE before an ICE session begins (see Section 3) ๐ฃ.
- A using protocol MUST provide methods for incrementally conveying (i.e., "trickling") additional candidates after conveying the initial ICE description (see Section 9) ๐.
- A using protocol MUST deliver each trickled candidate or end-of-candidates indication exactly once and in the same order it was conveyed (see Section 9) ๐ฏ.
- A using protocol MUST provide a mechanism for both parties to indicate and agree on the ICE session in force (see Section 9) ๐ค.
- A using protocol MUST provide a way for parties to communicate the end-of-candidates indication, which MUST specify the particular ICE session to which the indication applies (see Section 13) ๐.
19. IANA Considerations ๐๏ธ
IANA has registered the following ICE option in the "ICE Options" subregistry of the "Interactive Connectivity Establishment (ICE) registry", following the procedures defined in [RFC6336] โจ.
ICE Option: trickle
Contact: IESG <iesg@ietf.org>
Change controller: IESG
Description: An ICE option of 'trickle' indicates support for incremental communication of ICE candidates ๐ฌ.
Reference: RFC 8838 ๐
20. Security Considerations ๐
Okay, this part is serious, so listen up ๐จ. This specification inherits most of its semantics from [RFC8445], which means all the security considerations described there apply to Trickle ICE ๐ก๏ธ. No skipping them, bestie ๐ค.
If the privacy implications of revealing host addresses on an endpoint device are a concern (see, for example, the discussion in [RFC8828] and in Section 19 of [RFC8445]), agents can generate ICE descriptions that contain no candidates ๐. Then they only trickle candidates that don't reveal host addresses (e.g., relayed candidates) ๐ถ๏ธ. Privacy protected, iconic behavior ๐.
21. References ๐
21.1. Normative References ๐
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997, <https://www.rfc-editor.org/info/rfc2119>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8445] Keranen, A., Holmberg, C., and J. Rosenberg, "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal", RFC 8445, DOI 10.17487/RFC8445, July 2018, <https://www.rfc-editor.org/info/rfc8445>.
21.2. Informative References โจ
Okay bestie, here's the "if you want the backstory" reading list ๐๐ซถ Every one of these is cited somewhere earlier, and the authors put them here so you can go deeper.
- [RFC1918] Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., and E. Lear, "Address Allocation for Private Internets", BCP 5, RFC 1918, DOI 10.17487/RFC1918, February 1996,
https://www.rfc-editor.org/info/rfc1918. ๐ - [RFC3261] Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A., Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP: Session Initiation Protocol", RFC 3261, DOI 10.17487/RFC3261, June 2002,
https://www.rfc-editor.org/info/rfc3261. ๐ - [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, DOI 10.17487/RFC3264, June 2002,
https://www.rfc-editor.org/info/rfc3264. ๐ค - [RFC4566] Handley, M., Jacobson, V., and C. Perkins, "SDP: Session Description Protocol", RFC 4566, DOI 10.17487/RFC4566, July 2006,
https://www.rfc-editor.org/info/rfc4566. ๐ - [RFC4787] Audet, F., Ed. and C. Jennings, "Network Address Translation (NAT) Behavioral Requirements for Unicast UDP", BCP 127, RFC 4787, DOI 10.17487/RFC4787, January 2007,
https://www.rfc-editor.org/info/rfc4787. ๐งฑ - [RFC5389] Rosenberg, J., Mahy, R., Matthews, P., and D. Wing, "Session Traversal Utilities for NAT (STUN)", RFC 5389, DOI 10.17487/RFC5389, October 2008,
https://www.rfc-editor.org/info/rfc5389. ๐ต๏ธโโ๏ธ - [RFC5766] Mahy, R., Matthews, P., and J. Rosenberg, "Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)", RFC 5766, DOI 10.17487/RFC5766, April 2010,
https://www.rfc-editor.org/info/rfc5766. ๐ - [RFC6120] Saint-Andre, P., "Extensible Messaging and Presence Protocol (XMPP): Core", RFC 6120, DOI 10.17487/RFC6120, March 2011,
https://www.rfc-editor.org/info/rfc6120. ๐ฌ - [RFC6336] Westerlund, M. and C. Perkins, "IANA Registry for Interactive Connectivity Establishment (ICE) Options", RFC 6336, DOI 10.17487/RFC6336, July 2011,
https://www.rfc-editor.org/info/rfc6336. ๐๏ธ - [RFC8828] Uberti, J. and G. Shieh, "WebRTC IP Address Handling Requirements", RFC 8828, DOI 10.17487/RFC8828, January 2021,
https://www.rfc-editor.org/info/rfc8828. ๐ - [RFC8840] Ivov, E., Stach, T., Marocco, E., and C. Holmberg, "A Session Initiation Protocol (SIP) Usage for Incremental Provisioning of Candidates for the Interactive Connectivity Establishment (Trickle ICE)", RFC 8840, DOI 10.17487/RFC8840, January 2021,
https://www.rfc-editor.org/info/rfc8840. ๐ผ - [XEP-0030] Hildebrand, J., Millard, P., Eatmon, R., and P. Saint-Andre, "XEP-0030: Service Discovery", XMPP Standards Foundation, XEP-0030, June 2008. ๐
- [XEP-0176] Beda, J., Ludwig, S., Saint-Andre, P., Hildebrand, J., Egan, S., and R. McQueen, "XEP-0176: Jingle ICE-UDP Transport Method", XMPP Standards Foundation, XEP-0176, June 2009. ๐
Appendix A. Interaction with Regular ICE ๐ท
Okay so ICE was designed to be super flexible and adapt to as many network setups as possible ๐ง But even with all that flexibility, ICE as specified in [RFC8445] does not support Trickle ICE by itself. This appendix is about how trickling candidates interacts with regular ICE, and honestly it's a whole plot twist ๐ญ
[RFC8445] describes the conditions you need to update checklists and timer states while an ICE agent is in the Running state. Those conditions get checked when a transaction completes, and one of them says:
| if there is not a valid pair in the valid list for each component
| of the data stream associated with the checklist, the state of the
| checklist is set to Failed.
This can be a real problem and cause ICE processing to fail too early in a bunch of situations. Here's one case that's giving drama ๐
- Alice and Bob are both in different networks behind Network Address Translation (NAT). Alice and Bob have different addresses themselves, but both networks use the same private internet block (for example, the "20-bit block" 172.16/12 specified in [RFC1918]).
- Alice sends Bob the candidate
172.16.0.1, which just so happens to be an existing host on Bob's network. Oops ๐ - Bob makes a candidate pair from his host candidate and
172.16.0.1, puts that one pair into a checklist, and starts checks. - Those checks reach the host at
172.16.0.1on Bob's network, which replies with an ICMP "port unreachable" error. Per [RFC8445], Bob marks the transaction as Failed. Rude ๐
At this point, the checklist only has a Failed pair, and the valid list is empty. That makes the data stream fail and maybe all of ICE processing too, even though Trickle ICE agents can send over candidates later that would actually work. So close, yet so cursed ๐ญ
There's a similar race condition if the initial ICE description from Alice only has candidates that Bob can tell are unreachable from any of his gathered candidates. For example, this happens if Bob's candidates are all IPv4 addresses and the very first candidate he gets from Alice is an IPv6 one. Mismatch era ๐ฅ
Another potential problem shows up when a non-Trickle ICE implementation starts an interaction with a Trickle ICE implementation. Here's that one:
- Alice's client has a non-Trickle ICE implementation.
- Bob's client supports Trickle ICE.
- Alice and Bob are behind NATs with address-dependent filtering [RFC4787].
- Bob has two STUN servers, but one of them is unreachable right now.
Once Bob's agent gets Alice's initial ICE description, it would immediately start connectivity checks. It would also start gathering candidates, and that would take forever because of the unreachable STUN server. By the time Bob's answer is ready and sent to Alice, Bob's connectivity checks might have already failed. Alice can't start her connectivity checks and punch holes in her NAT until she gets Bob's answer, so her NAT would be filtering Bob's checks as coming from an unknown endpoint. Not the vibe ๐ซ
Appendix B. Interaction with ICE-Lite ๐ฆ
The behavior of ICE-lite agents that can do Trickle ICE doesn't require any special rules beyond the ones already defined in this specification and [RFC8445]. So this section is just here for information, no pressure โจ
An ICE-lite agent would generate candidate information as per [RFC8445] and would say it supports Trickle ICE. Since that candidate information includes a full generation of candidates, it would also come with an end-of-candidates indication ๐
When doing full trickle, a full ICE implementation could send the initial ICE description, or the response to one, with no candidates at all. After it gets a response that identifies the remote agent as an ICE-lite implementation, the initiator can choose not to trickle any more candidates. The same goes when the ICE-lite agent starts the interaction and the full ICE agent is the responder. In these cases, the connectivity checks are enough for the ICE-lite implementation to discover all the potentially useful candidates as peer-reflexive candidates. Main character energy, no extra signaling needed ๐ Here's an example of one ICE session using SDP syntax:
ICE-Lite Bob
Agent
| Offer (a=ice-lite a=ice-options:trickle) |
|---------------------------------------------->|
| |no cand
| Answer (a=ice-options:trickle) |trickling
|<----------------------------------------------|
| Connectivity Checks |
|<--------------------------------------------->|
peer rflx| |
cand disco| |
|<========== CONNECTION ESTABLISHED ===========>|
Figure 2: Example
Not only does this approach cut down on signaling traffic, it also removes the need to discover STUN Bindings or make TURN allocations. That can seriously lighten ICE processing, and I'm obsessed ๐ซถ๐
Acknowledgements ๐
The authors would like to thank Bernard Aboba, Flemming Andreasen, Rajmohan Banavi, Taylor Brandstetter, Philipp Hancke, Christer Holmberg, Ari Kerรคnen, Paul Kyzivat, Jonathan Lennox, Enrico Marocco, Pal Martinsen, Nils Ohlmeier, Thomas Stach, Peter Thatcher, Martin Thomson, Brandon Williams, and Dale Worley for their reviews and suggestions that made this document better. Sarah Banks, Roni Even, and David Mandelberg completed the OPSDIR, GenART, and security reviews, respectively. Thanks also to Ari Kerรคnen and Peter Thatcher in their role as chairs, and Ben Campbell in his role as responsible Area Director. Everyone involved is literally iconic ๐โจ
Authors' Addresses ๐
Emil Ivov
8x8, Inc. / Jitsi
675 Creekside Way
Campbell, CA 95008
United States of America
Phone: +1 512 420 6968
Email: emcho@jitsi.org
Justin Uberti
Google
747 6th Street S
Kirkland, WA 98033
United States of America
Phone: +1 857 288 8888
Email: justin@uberti.name
Peter Saint-Andre
Mozilla
P.O. Box 787
Parker, CO 80134
United States of America
Phone: +1 720 256 6756
Email: stpeter@mozilla.com
URI: https://www.mozilla.com/
๐ฆ where this page comes from
- ietf: rfc8838 2021-01
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms