diff --git a/peer/device.go b/peer/device.go index 30dd63c..0ebc5e1 100644 --- a/peer/device.go +++ b/peer/device.go @@ -38,21 +38,27 @@ func (a *App) devPeers() []wgtypes.Peer { return peers } -func (a *App) devAddPeer(p *Peer) { +func (a *App) devAddRelayed(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 + p.EndpointV4 = netip.AddrPort{} + p.EndpointV6 = netip.AddrPort{} + p.EndpointLAN = netip.AddrPort{} } 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 // Direct connection. The app marks peer as relay. } @@ -64,13 +70,18 @@ func (a *App) devPromote(p *Peer) { log.Printf("DIRECT: %s - %s (waiting for handshake)", p.Name, p.VPNIP.String()) } devRetry(p.VPNIP, "Promote", func() error { return a.dev.Promote(p.PubKey(), p.VPNIP) }) + p.State = StateDirect + p.LastPing = time.Now() // Assume the peer is up after being promoted. } 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 + p.ProbeStart = time.Now() + p.ProbeEndpoint = endpoint } func (a *App) devRemove(p *Peer) { diff --git a/peer/on_hub.go b/peer/on_hub.go index ece81cf..8198755 100644 --- a/peer/on_hub.go +++ b/peer/on_hub.go @@ -43,7 +43,7 @@ func (a *App) onAddPeer(p m.Peer) { // endpoint from the incoming handshake automatically. a.devPromote(peer) } else { - a.devAddPeer(peer) + a.devAddRelayed(peer) } return } diff --git a/peer/on_statetick.go b/peer/on_statetick.go index 6681f08..a35f19c 100644 --- a/peer/on_statetick.go +++ b/peer/on_statetick.go @@ -2,7 +2,6 @@ package peer import ( "log" - "net/netip" "time" "vppn/peer/wginterface" @@ -31,7 +30,6 @@ func (a *App) onStateTick() { case StateRelayed: // If we have an ep to probe, add it. if ep := p.PreferredEndpoint(); ep.IsValid() { - p.ProbeStart = time.Now() a.devAddProbe(p, ep) } @@ -40,15 +38,12 @@ func (a *App) onStateTick() { // Promote probing peers to direct once alive (direct path confirmed // working). a.devPromote(p) - } else if ep := p.PreferredEndpoint(); ep.IsValid() && ep != p.WGEndpoint() { - // Update the probe address if it's changed. + } 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. - p.EndpointV4 = netip.AddrPort{} - p.EndpointV6 = netip.AddrPort{} - p.EndpointLAN = netip.AddrPort{} - a.devAddPeer(p) + a.devAddRelayed(p) } case StateDirect: @@ -58,10 +53,7 @@ func (a *App) onStateTick() { // Stale non-public direct peer: demote to relayed and wait for new IP // information. - p.EndpointV4 = netip.AddrPort{} - p.EndpointV6 = netip.AddrPort{} - p.EndpointLAN = netip.AddrPort{} - a.devAddPeer(p) + a.devAddRelayed(p) } } diff --git a/peer/remote.go b/peer/remote.go index ab6387d..22ccb5f 100644 --- a/peer/remote.go +++ b/peer/remote.go @@ -18,21 +18,22 @@ const ( ) 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. - 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. + 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.