Fixed relay selection - deterministic w/ fallback.
This commit is contained in:
@@ -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() {
|
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
|
var best *Peer
|
||||||
for _, p := range a.peersByKey {
|
for _, p := range a.peersByKey {
|
||||||
if !p.CanRelay() {
|
if !p.CanRelay() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if best == nil || p.RTT < best.RTT {
|
if best == nil || p.VPNIP.Less(best.VPNIP) {
|
||||||
best = p
|
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 {
|
if best == nil {
|
||||||
log.Printf("no relay available")
|
log.Printf("no relay available")
|
||||||
|
a.relay = nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,10 @@ func (a *App) onStateTick() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we have a live relay (if we're not public).
|
// Keep the active relay pinned to the lowest-IP live relay (if we're not
|
||||||
if !a.isPublic && (a.relay == nil || !a.relay.Up()) {
|
// public). switchActiveRelay is idempotent and handles failover when the
|
||||||
|
// current relay dies as well as failback when a lower-IP relay recovers.
|
||||||
|
if !a.isPublic {
|
||||||
a.switchActiveRelay()
|
a.switchActiveRelay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user