Registers three separate receivers on the same home relay, each passing
its own onDisconnected method value, then drops the relay connection and
expects every receiver to be notified exactly once.
This FAILS on main:
manager_test.go:558: not every listener was notified,
got: map[peer-a:1]
addListener deduplicates with reflect.ValueOf(callback).Pointer(). For a
method value that pointer is the address of the compiler-generated
wrapper, not an identity bound to the receiver, so all three registrations
compare equal and only the first survives. Every peer on the home relay
shares the same connectionURL key, so in production only one peer is ever
notified when the relay drops.
The test is committed red on purpose to document the defect.
* [relay] evict foreign client cache on disconnect
When a foreign relay's TCP connection drops, the manager's
onServerDisconnected handler only triggered reconnect logic for the
home server; the disconnected foreign entry stayed in the relayClients
cache. Subsequent OpenConn calls reused the closed client until the
60-second cleanup tick evicted it, breaking peer connectivity through
that relay for up to a minute.
Evict the foreign entry from the cache on disconnect so the next
OpenConn dials a fresh client.
Also:
- Make the reconnect backoff cap configurable via WithMaxBackoffInterval
ManagerOption; the previous hard-coded 60s constant forced
TestAutoReconnect to sleep ~61s. Test now polls Ready() and finishes
in ~2s.
- Add NB_HOME_RELAY_SERVERS env var that overrides the relay URL list
received from management, so a peer can be pinned to a specific home
relay (used by the netbird-conn-lab Edge 4 reproducer).
* [client] treat empty NB_HOME_RELAY_SERVERS as unset
Returning (urls=[], ok=true) when the env var contained only separators or
whitespace caused callers to wipe the mgmt-provided relay list, leaving the
peer with no relays. Treat a parsed-empty result the same as an unset env.