Follow RFC 8445 to skip connectivity checks in lite mode#909
Follow RFC 8445 to skip connectivity checks in lite mode#909
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #909 +/- ##
==========================================
+ Coverage 88.48% 88.59% +0.10%
==========================================
Files 45 45
Lines 5811 5811
==========================================
+ Hits 5142 5148 +6
+ Misses 460 455 -5
+ Partials 209 208 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
3ea45e4 to
4c3a539
Compare
4c3a539 to
d43393c
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates ICE Lite behavior to align with RFC 8445 by ensuring lite agents (STUN-server-only) do not generate connectivity checks, while still correctly handling nomination when acting as the controlled agent.
Changes:
- Suppress triggered checks (
PingCandidate) for lite controlled agents on inbound Binding Requests. - Allow lite controlled agents to accept USE-CANDIDATE nomination without requiring a prior triggered check.
- Add unit/integration tests covering lite-mode check suppression and full-to-lite interoperability.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| selection.go | Adjust controlled selector to skip triggered checks in lite mode and handle nomination for lite controlled agents. |
| selection_test.go | Add tests validating lite behavior (no triggered checks) and a full-to-lite integration scenario. |
Comments suppressed due to low confidence (1)
selection.go:446
- In the lite-agent nomination path, the pair can be selected even when it hasn’t reached
CandidatePairStateSucceeded, but the code doesn’t updatepair.statetoSucceeded. This can leave the selected (nominated) pair stuck inWaiting/InProgress, which is internally inconsistent (e.g.,Conn.WriteToPairrejects non-Succeededpairs) and makes stats/reporting misleading. Consider marking the pair asCandidatePairStateSucceeded(and/or otherwise adding it to the valid list semantics) when a lite controlled agent accepts nomination.
if pair.state == CandidatePairStateSucceeded || s.agent.lite {
// For full agents: pair reached Succeeded via a triggered check (RFC 8445 §7.3.1.5).
// For lite agents: RFC 8445 §7.3.2 — the lite agent directly constructs the pair,
// places it in the valid list, and sets the nominated flag; no triggered check needed.
selectedPair := s.agent.getSelectedPair()
if s.shouldSwitchSelectedPair(pair, selectedPair, nominationValue) {
s.log.Tracef("Accepting nomination for pair %s", pair)
s.agent.setSelectedPair(pair)
} else {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| t.Run("NominationStillAccepted", func(t *testing.T) { | ||
| // A lite agent must still accept USE-CANDIDATE and set the selected pair | ||
| // (RFC 8445 §7.3.2), even though it never sends its own checks. | ||
| agent, local, remote, pair := setupAgent(t) | ||
| pair.state = CandidatePairStateSucceeded | ||
|
|
||
| ls, ok := agent.getSelector().(*liteSelector) | ||
| require.True(t, ok) | ||
|
|
||
| assert.Nil(t, agent.getSelectedPair(), "no pair selected yet") | ||
|
|
||
| msg, err := stun.Build(stun.BindingRequest, | ||
| stun.TransactionID, | ||
| stun.NewUsername(agent.localUfrag+":"+agent.remoteUfrag), | ||
| UseCandidate(), | ||
| stun.NewShortTermIntegrity(agent.localPwd), | ||
| stun.Fingerprint, | ||
| ) | ||
| require.NoError(t, err) | ||
|
|
||
| ls.HandleBindingRequest(msg, local, remote) | ||
|
|
||
| assert.Equal(t, pair, agent.getSelectedPair(), | ||
| "lite controlled agent must accept nomination and set selected pair") | ||
| // Still no triggered check emitted |
There was a problem hiding this comment.
NominationStillAccepted sets pair.state = CandidatePairStateSucceeded before calling HandleBindingRequest, so it doesn’t actually verify the new RFC 8445 §7.3.2 behavior described in the PR (accepting USE-CANDIDATE and selecting the pair even when the pair has not reached Succeeded via a triggered check). To cover the intended behavior, keep the pair in Waiting/InProgress and assert that the lite controlled agent still selects it on receiving a USE-CANDIDATE request (while still not emitting any triggered checks).
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (1)
selection.go:445
- In the lite-agent nomination path,
setSelectedPair(pair)can be executed whilepair.stateis stillCandidatePairStateWaiting(since the lite controlled agent never sends checks that would transition it toSucceeded). This leaves the selected/nominated pair reported aswaitinginGetCandidatePairsStats()/GetCandidatePairsInfo(), and also causesConn.WriteToPair()to fail withErrCandidatePairNotSucceededeven though the pair is actively selected and working. Consider explicitly transitioning the pair toCandidatePairStateSucceededwhen a lite agent accepts a nomination (RFC 8445 §7.3.2 “places it in the valid list”).
if pair.state == CandidatePairStateSucceeded || s.agent.lite {
// For full agents: pair reached Succeeded via a triggered check (RFC 8445 §7.3.1.5).
// For lite agents: RFC 8445 §7.3.2 — the lite agent directly constructs the pair,
// places it in the valid list, and sets the nominated flag; no triggered check needed.
selectedPair := s.agent.getSelectedPair()
if s.shouldSwitchSelectedPair(pair, selectedPair, nominationValue) {
s.log.Tracef("Accepting nomination for pair %s", pair)
s.agent.setSelectedPair(pair)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
JoTurk
left a comment
There was a problem hiding this comment.
looks good, thank you.
I'll try to look at the rest of the code again, before we merge or tag this to make sure we don't introduce bugs.
Description
Lite ICE agents are STUN-server-only — they must not generate connectivity checks (RFC 8445 §7). This change fixes two gaps in the current lite mode implementation for the full + lite agent scenario:
Tests added for both behaviours.
Reference issue
Fixes #96
See also #907