Fixed relay selection - deterministic w/ fallback.

This commit is contained in:
jdl
2026-06-18 06:41:55 +02:00
parent 8aafcab57f
commit da2115584c
2 changed files with 25 additions and 11 deletions

View File

@@ -67,27 +67,39 @@ func (a *App) onRemovePeer(key wgtypes.Key) {
}
}
// switchActiveRelay promotes the lowest-latency relay peer to active.
// switchActiveRelay selects the live relay with the lowest VPN IP as active.
//
// Choosing deterministically by IP (rather than by lowest RTT) makes every
// non-public peer converge on the same relay, so two non-public peers always
// share a relay and can reach each other. Failover walks up to the next-lowest
// live relay; failback returns to a lower-IP relay once it recovers. The call
// is idempotent: if the best relay is already active it does nothing, so it's
// safe to run every state tick.
func (a *App) switchActiveRelay() {
if a.relay != nil {
// If we have a relay, it's public, so should go back to being a direct
// peer - this will convert it's /24 to a /32.
a.devAddDirect(a.relay, a.relay.PreferredEndpoint())
a.relay = nil
}
var best *Peer
for _, p := range a.peersByKey {
if !p.CanRelay() {
continue
}
if best == nil || p.RTT < best.RTT {
if best == nil || p.VPNIP.Less(best.VPNIP) {
best = p
}
}
if best == a.relay {
return // Already on the best relay (or none available and none before).
}
if a.relay != nil {
// The old relay is public, so it goes back to being a direct peer -
// this converts its /24 back to a /32.
a.devAddDirect(a.relay, a.relay.PreferredEndpoint())
}
if best == nil {
log.Printf("no relay available")
a.relay = nil
return
}