75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
package peer
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"net/netip"
|
|
"syscall"
|
|
"time"
|
|
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
)
|
|
|
|
// devRetry calls fn up to 6 times with exponential backoff, retrying on EBUSY
|
|
// (transient netlink contention during WireGuard handshake/rekey). Fatal on
|
|
// any other error.
|
|
func devRetry(vpnIP netip.Addr, op string, fn func() error) {
|
|
const attempts = 6
|
|
timeout := 10 * time.Millisecond
|
|
for i := range attempts {
|
|
err := fn()
|
|
if err == nil {
|
|
return
|
|
}
|
|
if errors.Is(err, syscall.EBUSY) && i < attempts-1 {
|
|
time.Sleep(timeout)
|
|
timeout *= 2
|
|
continue
|
|
}
|
|
log.Fatalf("%s %v: %v", op, vpnIP, err)
|
|
}
|
|
}
|
|
|
|
func (a *App) devPeers() []wgtypes.Peer {
|
|
peers, err := a.dev.Peers()
|
|
if err != nil {
|
|
log.Fatalf("Failed to get peers %v: %v", a.vpnIP, err)
|
|
}
|
|
return peers
|
|
}
|
|
|
|
func (a *App) devAddPeer(p *Peer) {
|
|
log.Printf("RELAYED: %s - %s ", p.Name, p.VPNIP.String())
|
|
devRetry(p.VPNIP, "AddPeer", func() error { return a.dev.AddPeer(p.PubKey()) })
|
|
p.State = StateRelayed
|
|
}
|
|
|
|
func (a *App) devAddDirect(p *Peer, endpoint netip.AddrPort) {
|
|
log.Printf("DIRECT: %s - %s @ %s", p.Name, p.VPNIP.String(), endpoint.String())
|
|
devRetry(p.VPNIP, "AddDirect", func() error { return a.dev.AddDirect(p.PubKey(), endpoint, p.VPNIP) })
|
|
p.State = StateDirect
|
|
}
|
|
|
|
func (a *App) devSetRelay(p *Peer, endpoint netip.AddrPort) {
|
|
log.Printf("RELAY: %s - %s @ %s", p.Name, p.VPNIP.String(), endpoint.String())
|
|
devRetry(p.VPNIP, "SetRelay", func() error { return a.dev.SetRelay(p.PubKey(), endpoint, a.vpnNet) })
|
|
p.State = StateDirect // Dirrect connection. The app marks peer as relay.
|
|
}
|
|
|
|
func (a *App) devPromote(p *Peer) {
|
|
log.Printf("PROMOTED: %s - %s @ %s", p.Name, p.VPNIP.String(), p.WGEndpoint().String())
|
|
devRetry(p.VPNIP, "Promote", func() error { return a.dev.Promote(p.PubKey(), p.VPNIP) })
|
|
p.State = StateDirect
|
|
}
|
|
|
|
func (a *App) devAddProbe(p *Peer, endpoint netip.AddrPort) {
|
|
log.Printf("PROBE: %s - %s @ %s", p.Name, p.VPNIP.String(), endpoint.String())
|
|
devRetry(p.VPNIP, "AddProbe", func() error { return a.dev.AddProbe(p.PubKey(), endpoint) })
|
|
p.State = StateProbing
|
|
}
|
|
|
|
func (a *App) devRemove(p *Peer) {
|
|
log.Printf("REMOVED: %s - %s", p.Name, p.VPNIP.String())
|
|
devRetry(p.VPNIP, "RemovePeer", func() error { return a.dev.RemovePeer(p.PubKey()) })
|
|
}
|