[client] Reset WireGuard endpoint on ICE session change during relay fallback#5283
[client] Reset WireGuard endpoint on ICE session change during relay fallback#5283
Conversation
When an ICE connection disconnects and falls back to relay, reset the WireGuard endpoint and handshake watcher if the remote peer's ICE session has changed. This ensures the controller re-establishes a fresh WireGuard handshake rather than waiting on a stale endpoint from the previous session.
📝 WalkthroughWalkthroughThese changes introduce session-aware reset mechanisms for ICE peer connections. When an ICE session changes during disconnection, the system propagates this state through worker_ice, conn, endpoint, and wg_watcher modules to reset the endpoint address and restart handshake timing. Changes
Sequence DiagramsequenceDiagram
participant WorkerICE
participant Conn
participant EndpointUpdater
participant WgInterface
participant WGWatcher
WorkerICE->>WorkerICE: Detect session change via new offer
WorkerICE->>WorkerICE: Set remoteSessionChanged = true
WorkerICE->>WorkerICE: closeAgent() called
WorkerICE->>Conn: onICEStateDisconnected(sessionChanged=true)
Conn->>Conn: resetEndpoint() invoked
Conn->>EndpointUpdater: RemoveEndpointAddress()
EndpointUpdater->>WgInterface: RemoveEndpointAddress(RemoteKey)
WgInterface-->>EndpointUpdater: Confirm removal
Conn->>WGWatcher: Reset()
WGWatcher->>WGWatcher: Signal resetCh
WGWatcher->>WGWatcher: Restart handshake timeout logic
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly Related PRs
Suggested Reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| defer w.muxAgent.Unlock() | ||
|
|
||
| sessionChanged := w.remoteSessionChanged | ||
| w.remoteSessionChanged = false |
There was a problem hiding this comment.
Both old and new agents consume this flag. Intentional?
There was a problem hiding this comment.
1. Agent A is alive and ICE connection is established with a WireGuard endpoint configured.
2. New offer arrives (OnNewOffer):
- Remote peer has a new session ID (different from current), meaning it wants to reconnect.
- remoteSessionChanged = true is set, this is the signal that the WG endpoint needs to be reset.
- Agent A is closed directly and replaced by a new Agent B.
- w.agent now points to Agent B.
3. Deprecated Agent A's callback fires (onConnectionStateChange → closeAgent):
- Agent A transitions to disconnected/failed/closed.
- closeAgent is called with Agent A.
- but we must to reset the WireGuard, consume the flag
The problem is we have a race between the Agent A close callback and the Agent B on connected callback. If the Agent B connected faster then disconnect the old one then we have an inconsistent state. This is why we do all the time this double check but it is not enough.
|



When an ICE connection disconnects and falls back to relay, reset the WireGuard endpoint and handshake watcher if the remote peer's ICE session has changed. This ensures the controller re-establishes a fresh WireGuard handshake rather than waiting on a stale endpoint from the previous session.
Describe your changes
Issue ticket number and link
Stack
Checklist
Documentation
Select exactly one:
Docs PR URL (required if "docs added" is checked)
Paste the PR link from https://github.com/netbirdio/docs here:
https://github.com/netbirdio/docs/pull/__
Summary by CodeRabbit