Files
vppn/peer/remote.go
2026-06-15 19:45:07 +02:00

86 lines
2.1 KiB
Go

package peer
import (
"net/netip"
"time"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"vppn/peer/control"
)
type PeerState string
const (
StateRelayed = PeerState("RELAY ")
StateProbing = PeerState("PROBE ")
StateDirect = PeerState("DIRECT")
)
type Peer struct {
wgPeer wgtypes.Peer
VPNIP netip.Addr // VPN IP address.
Name string // Human-readable DNS label.
IsRelay bool // Peer is a relay.
IsPublic bool // Peer has a public IP.
EndpointV4 netip.AddrPort // Reported IPv4 endpoint.
EndpointV6 netip.AddrPort // Reported IPv6 endpoint.
EndpointLAN netip.AddrPort // Discovered via multicast.
EndpointWG netip.AddrPort // Current wireguard endpoint.
RTT time.Duration // Round-trip time.
LastPing time.Time // Last time we had a ping.
ProbeStart time.Time // When we started probing.
ProbeEndpoint netip.AddrPort
State PeerState // Current routing state; updated on each devXxx call.
Role control.Role // Role in relation to the local application.
SignPubKey [32]byte // nacl/sign public key for verifying multicast beacons.
}
// PubKey is the wireguard public key.
func (p *Peer) PubKey() wgtypes.Key {
return p.wgPeer.PublicKey
}
func (p *Peer) WGEndpoint() netip.AddrPort {
ep := p.wgPeer.Endpoint
if ep == nil {
return netip.AddrPort{}
}
addr, ok := netip.AddrFromSlice(ep.IP)
if !ok {
return netip.AddrPort{}
}
return netip.AddrPortFrom(addr.Unmap(), uint16(ep.Port))
}
func (p *Peer) LastHandshakeTime() time.Time {
return p.wgPeer.LastHandshakeTime
}
func (p *Peer) Up() bool {
return time.Since(p.LastPing) < 3*PingInterval
}
func (p *Peer) CanRelay() bool {
return p.IsRelay && p.Up()
}
func (p *Peer) PreferredEndpoint() netip.AddrPort {
if p.EndpointLAN.IsValid() {
return p.EndpointLAN
} else if p.EndpointV4.IsValid() {
return p.EndpointV4
} else {
return p.EndpointV6
}
}
func (p *Peer) UpdateEndpoints(v4, v6 netip.AddrPort) {
if v4.IsValid() {
p.EndpointV4 = v4
}
if v6.IsValid() {
p.EndpointV6 = v6
}
}