Files
vppn/peer/on_ping.go
2026-06-14 05:42:44 +02:00

68 lines
1.4 KiB
Go

package peer
import (
"log"
"net/netip"
"time"
"vppn/peer/control"
)
func (a *App) onPing(e PingEvent) {
peer, ok := a.peersByIP[e.srcVPNIP]
if !ok {
// TODO: Log here.
return
}
now := time.Now()
// If we're the server, respond - this is always necessary as it's used to
// know if peers are up or down.
if peer.Role == control.Server {
a.sendPing(peer, e.ping.PingTS)
}
// Compute RTT from server echo.
if peer.Role == control.Client {
peer.RTT = now.Sub(time.Unix(0, e.ping.PingTS))
}
// If we're public, nothing more to do.
if a.isPublic {
return
}
// We can only learn our own endpoint from directly-connected peers — Dst is
// the sender's observation of our WG handshake source.
//
// We make sure we don't set a private address as our public address since we
// may be connected via LAN to some peers.
if peer.State == StateDirect {
if dst := e.ping.Dst; addrIsRoutable(e.ping.Dst) {
if dst.Addr().Is4() {
if dst != a.selfV4 {
log.Printf("Local IPv4 updated: %s -> %s", a.selfV4, dst)
a.selfV4 = dst
}
} else {
if dst != a.selfV6 {
log.Printf("Local IPv6 updated: %s -> %s", a.selfV6, dst)
a.selfV6 = dst
}
}
}
return
}
peer.UpdateEndpoints(e.ping.SrcV4, e.ping.SrcV6)
}
func addrIsRoutable(addrPort netip.AddrPort) bool {
if addrPort.Port() == 0 {
return false
}
addr := addrPort.Addr()
return addr.IsGlobalUnicast() && !addr.IsPrivate()
}