package peer import ( "log" "math" "net/netip" "time" "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, RTT: time.Duration(math.MaxInt64) * time.Nanosecond, Role: roleFor(a.isPublic, a.vpnIP, p), SignPubKey: p.SignPubKey, } 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 { // 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 { best = p } } if best == nil { log.Printf("no relay available") return } a.devSetRelay(best, best.PreferredEndpoint()) a.relay = best } 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) }