package peer import ( "log" "net/netip" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "vppn/peer/control" ) func (a *App) onAddPeer(p HubPeer) { a.onRemovePeer(p.PubKey) peer := &Peer{ wgPeer: wgtypes.Peer{PublicKey: p.PubKey}, VPNIP: p.VPNIP, IsRelay: p.IsRelay, IsPublic: p.IsPublic, Endpoint4: p.EndpointV4, Endpoint6: p.EndpointV6, Role: roleFor(a.isPublic, a.vpnIP, p), } endpoint := peer.PreferredEndpoint() if peer.IsPublic && !endpoint.IsValid() { // The peer is misconfigured. // TODO: Log here. return } a.peersByKey[p.PubKey] = peer a.peersByIP[peer.VPNIP] = peer if !peer.IsPublic { a.devAddPeer(peer) return } a.devAddDirect(peer, endpoint) } func (a *App) onRemovePeer(key wgtypes.Key) { peer, exists := a.peersByKey[key] if !exists { return } a.devRemove(peer) delete(a.peersByKey, key) delete(a.peersByIP, peer.VPNIP) if peer == a.relay { a.relay = nil a.switchActiveRelay() } } // switchActiveRelay promotes the lowest-latency relay peer to active. func (a *App) switchActiveRelay() { if a.relay != nil { a.devAddDirect(a.relay, a.relay.WGEndpoint()) a.relay = nil } var best *Peer for _, p := range a.peersByKey { if !p.CanRelay() { continue } if best == nil || betterRelay(p, best) { best = p } } if best == nil { log.Printf("no relay available") return } a.devSetRelay(best, best.WGEndpoint()) a.relay = best } // TODO: Why not < ?? // betterRelay reports whether a is a better relay candidate than b. // Prefers lower RTT; treats zero RTT (no measurement yet) as worst case. func betterRelay(a, b *Peer) bool { if a.RTT == 0 { return false } if b.RTT == 0 { return true } return a.RTT < b.RTT } func preferredEndpoint(v4, v6 netip.AddrPort) netip.AddrPort { if v4.IsValid() { return v4 } return v6 } func roleFor(selfIsPublic bool, selfIP netip.Addr, p HubPeer) control.Role { if !selfIsPublic && p.IsPublic { return control.Client } if selfIsPublic && !p.IsPublic { return control.Server } return control.RoleFor(selfIP, p.VPNIP) }