Files
vppn/peer/on_statetick.go

71 lines
1.8 KiB
Go

package peer
import (
"log"
"time"
"vppn/peer/wginterface"
)
func (a *App) onStateTick() {
wgPeers := a.devPeers()
for _, wgPeer := range wgPeers {
p, ok := a.peersByKey[wgPeer.PublicKey]
if !ok {
log.Printf("Wireguard peer not known. Removing: %v", wgPeer.PublicKey)
a.devRemove(&Peer{wgPeer: wgPeer})
continue
}
p.wgPeer = wgPeer
// Log endpoint changes.
if ep := p.WGEndpoint(); ep != p.EndpointWG {
log.Printf("Client %s %s endpoint: %s -> %s", p.Name, p.VPNIP, p.EndpointWG, ep)
p.EndpointWG = ep
}
switch p.State {
case StateRelayed:
if p.DirectAlive() {
// We may already have a valid direct endpoint due to wireguard
// roaming.
a.devPromote(p)
} else if ep := p.PreferredEndpoint(); ep.IsValid() {
// If we have an ep to probe, add it.
a.devAddProbe(p, ep)
}
case StateProbing:
if time.Since(p.LastHandshakeTime()) < 2*wginterface.ProbeKeepalive {
// Promote probing peers to direct once alive (direct path confirmed
// working).
a.devPromote(p)
} else if ep := p.PreferredEndpoint(); ep.IsValid() && ep != p.ProbeEndpoint {
// Re-start probing if we see a new endpoint.
a.devAddProbe(p, ep)
} else if time.Since(p.ProbeStart) > 8*wginterface.ProbeKeepalive {
// Give up probing if we haven't been able to handshake.
a.devAddRelayed(p)
}
case StateDirect:
if p.IsPublic || a.isPublic || p.Up() {
break
}
// Stale non-public direct peer: demote to relayed and wait for new IP
// information.
a.devAddRelayed(p)
}
}
// Keep the active relay pinned to the lowest-IP live relay (if we're not
// 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()
}
}