Commit Graph
29 Commits
Author SHA1 Message Date
Laotree 24959e1ed9 [client] Drop agentConnecting whenever ICE session state clears (#7327)
* [client] Drop agentConnecting whenever ICE session state clears

Closing a WorkerICE raced a blocked dial goroutine: Close released the
agent while connect() was still inside Dial, and the goroutine's own
cleanup skipped its flag reset because w.agent no longer matched. With
agentConnecting stuck on true, evalConnStatus read the peer as
connected, the reconnection guard stopped sending offers and
same-session offers were dropped, so the peer could not recover without
a restart. An aborted recreate in OnNewOffer reaches the same wedged
state without any race.

Route every teardown path through one abandonNegotiation helper so the
agent and flag fields always clear together; Close now also cleans up
residual state left by an aborted recreate.

* [client] Drive the ICE teardown race test through the real dial goroutine

The regression test simulated the stale goroutine by calling closeAgent
directly, so it pinned the symptom rather than the mechanism. Rework it
to start a real negotiation, tear it down mid-flight and let the actual
goroutine run its own cleanup: with no remote responder the dial can
only fail once Close cancels it, so the interleaving stays deterministic
without sleeps or injection points.

Assert the full idle state that abandonNegotiation owns (agent nil,
connecting false, remote session ID empty) instead of only InProgress,
and make the stale-cleanup ownership test verify that the newer session
survives field by field.

* [client] Assert live remote session ID after stale ICE cleanup

The stale-cleanup test compared a snapshot captured before closeAgent
ran, so clearing the field during cleanup would have gone unnoticed.
Read the field under the mutex after the cleanup instead.

* [client] Give the ICE race tests a no-op signal client

The candidate callback fires from a real gather and dereferences the
signaler, so a nil one crashes the test package intermittently when
gather wins the race against Close. Build the worker with a stub
signal.Client instead.

* [client] Read the ICE dial cancel func from an argument in connect

The error paths read w.agentDialerCancel without holding muxAgent while
OnNewOffer rewrites the field for a newer negotiation, a data race the
new teardown test trips under -race. Reading a stale value also let an
old goroutine cancel another session's dial. Capture the cancel func at
goroutine spawn, like the dial context already is.

* [client] Guard the ICE dial success path against stale negotiations

The stale-cleanup guard in closeAgent only protected teardown. Its
success-path counterpart was missing: an older negotiation could complete
agentDial after a newer one replaced w.agent, then clear the newer
session's agentConnecting, record lastSuccess and publish its dead
connection via onICEConnectionIsReady.

Verify ownership under muxAgent twice: right after the dial returns, so a
stale goroutine drops its connection before touching a closed agent, and
again at the state-commit point, atomic with the agentConnecting and
lastSuccess writes, so a replacement arriving in the meantime cannot get
its state clobbered. Both paths close the stale connection and return
without modifying worker state. A regression test holds session A's dial
open until session B is installed, then releases it; the stale connection
must be discarded and B's agent, connecting flag and remote session ID
must survive.

* [client] Fix ICE teardown test leak and document the stale delivery window

A code review of the stale-negotiation guard found a leftover resource
leak in TestWorkerICE_StaleCloseAgentKeepsCurrentSession: session B is
never closed, so its ICE sockets and blocked dial goroutine live as long
as the test process. Register t.Cleanup(w.Close).

The delivery race flagged after the success-path guard is pre-existing
and self-correcting - the newer negotiation overwrites the transient
endpoint - so document it in the existing todo instead of locking the
callback, which would invert lock order against Conn.Close. Adjust the
teardown test comment to match the now-synchronous Close flag clearing.
2026-08-31 17:49:59 +02:00
Viktor Liu 335adfe9c3 [client] Move the PCP implementation to the go-nat fork (#7282) 2026-08-21 14:15:10 +02:00
Viktor Liu 917ad880e3 [client] Rename TURN-specific wg proxy naming to relayed connections (#7231) 2026-08-20 15:07:51 +02:00
Viktor Liu b57f714350 [client] Drop signaling-side ICE candidate filter, drop overlay STUN at mux read-side instead (#6142) 2026-06-15 16:37:03 +02:00
Viktor Liu d33cd4c95b [client] Add NAT-PMP/UPnP support (#5202) 2026-04-08 15:29:32 +08:00
Zoltan Papp baed6e46ec Reset WireGuard endpoint on ICE session change during relay fallback (#5283)
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.
2026-02-16 20:59:29 +01:00
Zoltan Papp d2f9653cea Fix nil pointer panic in ICE agent during sleep/wake cycles (#5261)
Add defensive nil checks in ThreadSafeAgent.Close() to prevent panic
when agent field is nil. This can occur during Windows suspend/resume
when network interfaces are disrupted or the pion/ice library returns
nil without error.

Also capture agent pointer in local variable before goroutine execution
to prevent race conditions.

Fixes service crashes on laptop wake-up.
2026-02-05 12:06:28 +01:00
Viktor Liu ee54827f94 [client] Add IPv6 support to usersace bind (#5147) 2026-01-22 10:20:43 +08:00
Viktor Liu 9cc9462cd5 [client] Use stdnet with a context to avoid DNS deadlocks (#4781) 2025-11-13 20:16:45 +01:00
Zoltan Papp c28275611b Fix agent reference (#4776) 2025-11-11 13:59:32 +01:00
Zoltan Papp 9021bb512b [client] Recreate agent when receive new session id (#4564)
When an ICE agent connection was in progress, new offers were being ignored. This was incorrect logic because the remote agent could be restarted at any time.
In this change, whenever a new session ID is received, the ongoing handshake is closed and a new one is started.
2025-10-08 17:14:24 +02:00
Zoltan Papp bd23ab925e [client] Fix ICE latency handling (#4501)
The GetSelectedCandidatePair() does not carry the latency information.
2025-09-15 15:08:53 +02:00
Zoltan Papp 9e81e782e5 [client] Fix/v4 stun routing (#4430)
Deduplicate STUN package sending.
Originally, because every peer shared the same UDP address, the library could not distinguish which STUN message was associated with which candidate. As a result, the Pion library responded from all candidates for every STUN message.
2025-09-11 10:08:54 +02:00
Zoltan Papp 786ca6fc79 Do not block Offer processing from relay worker (#4435)
- do not miss ICE offers when relay worker busy
- close p2p connection before recreate agent
2025-09-05 11:02:29 +02:00
Zoltan Papp 21368b38d9 [client] Update Pion ICE to the latest version (#4388)
- Update Pion version
- Update protobuf version
2025-09-01 10:42:01 +02:00
Zoltan Papp f425870c8e [client] Avoid duplicated agent close (#4383) 2025-08-20 18:50:51 +02:00
Zoltan Papp 12cad854b2 [client] Fix/ice handshake (#4281)
In this PR, speed up the GRPC message processing, force the recreation of the ICE agent when getting a new, remote offer (do not wait for local STUN timeout).
2025-08-18 20:09:50 +02:00
Zoltan Papp daa8380df9 [client] Feature/lazy connection (#3379)
With the lazy connection feature, the peer will connect to target peers on-demand. The trigger can be any IP traffic.

This feature can be enabled with the NB_ENABLE_EXPERIMENTAL_LAZY_CONN environment variable.

When the engine receives a network map, it binds a free UDP port for every remote peer, and the system configures WireGuard endpoints for these ports. When traffic appears on a UDP socket, the system removes this listener and starts the peer connection procedure immediately.

Key changes
Fix slow netbird status -d command
Move from engine.go file to conn_mgr.go the peer connection related code
Refactor the iface interface usage and moved interface file next to the engine code
Add new command line flag and UI option to enable feature
The peer.Conn struct is reusable after it has been closed.
Change connection states
Connection states
Idle: The peer is not attempting to establish a connection. This typically means it's in a lazy state or the remote peer is expired.

Connecting: The peer is actively trying to establish a connection. This occurs when the peer has entered an active state and is continuously attempting to reach the remote peer.

Connected: A successful peer-to-peer connection has been established and communication is active.
2025-05-21 11:12:28 +02:00
Zoltan Papp ed5647028a [client] Prevent calling the onDisconnected callback in incorrect state (#3582)
Prevent calling the onDisconnected callback if the ICE connection has never been established

If call onDisconnected without onConnected then overwrite the relayed status in the conn priority variable.
2025-03-28 18:08:26 +01:00
Viktor Liu 80ceb80197 [client] Ignore candidates that are part of the the wireguard subnet (#3472) 2025-03-10 13:59:21 +01:00
Zoltan Papp 5953b43ead [client, relay] Fix/wg watch (#3261)
Fix WireGuard watcher related issues

- Fix race handling between TURN and Relayed reconnection
- Move the WgWatcher logic to separate struct
- Handle timeouts in a more defensive way
- Fix initial Relay client reconnection to the home server
2025-02-10 10:32:50 +01:00
Maycon Santos 9f4db0a953 [client] Close ice agent only if not nil (#3210) 2025-01-18 00:18:59 +01:00
Jesse R Codling 3844516aa7 [client] fix: reformat IPv6 ICE addresses when punching (#3050)
Should fix #2327 and #2606 by checking for IPv6 addresses from ICE
2024-12-16 09:58:54 +01:00
Zoltan Papp 2a5cb16494 [relay] Refactor initial Relay connection (#2800)
Can support firewalls with restricted WS rules

allow to run engine without Relay servers
keep up to date Relay address changes
2024-11-22 18:12:34 +01:00
Zoltan Papp b4d7605147 [client] Remove loop after route calculation (#2856)
- ICE do not trigger disconnect callbacks if the stated did not change
- Fix route calculation callback loop
- Move route state updates into protected scope by mutex
- Do not calculate routes in case of peer.Open() and peer.Close()
2024-11-11 10:53:57 +01:00
Zoltan Papp 4e918e55ba [client] Fix controller re-connection (#2758)
Rethink the peer reconnection implementation
2024-10-24 11:43:14 +02:00
Viktor Liu 44e8107383 [client] Limit P2P attempts and restart on specific events (#2657) 2024-10-08 11:21:11 +02:00
Zoltan Papp fd67892cb4 [client] Refactor/iface pkg (#2646)
Refactor the flat code structure
2024-10-02 18:24:22 +02:00
Zoltan Papp 0c039274a4 [relay] Feature/relay integration (#2244)
This update adds new relay integration for NetBird clients. The new relay is based on web sockets and listens on a single port.

- Adds new relay implementation with websocket with single port relaying mechanism
- refactor peer connection logic, allowing upgrade and downgrade from/to P2P connection
- peer connections are faster since it connects first to relay and then upgrades to P2P
- maintains compatibility with old clients by not using the new relay
- updates infrastructure scripts with new relay service
2024-09-08 12:06:14 +02:00