WIP
This commit is contained in:
@@ -19,6 +19,7 @@ const (
|
|||||||
ControlPort = 4561
|
ControlPort = 4561
|
||||||
PingInterval = 8 * time.Second
|
PingInterval = 8 * time.Second
|
||||||
TimeoutInterval = 30 * time.Second
|
TimeoutInterval = 30 * time.Second
|
||||||
|
probeTimeout = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// HubPeer is a peer entry as reported by the hub poller.
|
// HubPeer is a peer entry as reported by the hub poller.
|
||||||
|
|||||||
@@ -47,6 +47,13 @@ func (a *App) devAddDirect(p *Peer, endpoint netip.AddrPort) {
|
|||||||
p.State = StateDirect
|
p.State = StateDirect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) devAddRelayed(p *Peer, relayVPNIP netip.Addr) {
|
||||||
|
port := ForwarderBasePort + uint16(p.VPNIP.As4()[3])
|
||||||
|
endpoint := netip.AddrPortFrom(relayVPNIP, port)
|
||||||
|
devRetry(p.VPNIP, "AddRelayed", func() error { return a.dev.AddDirect(p.PubKey(), endpoint, p.VPNIP) })
|
||||||
|
p.State = StateRelayed
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) devSetRelay(p *Peer, endpoint netip.AddrPort) {
|
func (a *App) devSetRelay(p *Peer, endpoint netip.AddrPort) {
|
||||||
devRetry(p.VPNIP, "SetRelay", func() error { return a.dev.SetRelay(p.PubKey(), endpoint, a.vpnNet) })
|
devRetry(p.VPNIP, "SetRelay", func() error { return a.dev.SetRelay(p.PubKey(), endpoint, a.vpnNet) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,11 @@ func (a *App) onAddPeer(p HubPeer) {
|
|||||||
a.peersByIP[peer.VPNIP] = peer
|
a.peersByIP[peer.VPNIP] = peer
|
||||||
|
|
||||||
if !peer.IsPublic {
|
if !peer.IsPublic {
|
||||||
a.devAddPeer(peer)
|
if a.relay != nil {
|
||||||
|
a.devAddRelayed(peer, a.relay.VPNIP)
|
||||||
|
} else {
|
||||||
|
a.devAddPeer(peer)
|
||||||
|
}
|
||||||
if a.forwarder != nil && endpoint.IsValid() {
|
if a.forwarder != nil && endpoint.IsValid() {
|
||||||
a.forwarder.SetEndpoint(peer.VPNIP.As4()[3], endpoint)
|
a.forwarder.SetEndpoint(peer.VPNIP.As4()[3], endpoint)
|
||||||
}
|
}
|
||||||
@@ -86,11 +90,21 @@ func (a *App) switchActiveRelay() {
|
|||||||
}
|
}
|
||||||
if best == nil {
|
if best == nil {
|
||||||
log.Printf("no relay available")
|
log.Printf("no relay available")
|
||||||
return
|
} else {
|
||||||
|
a.devSetRelay(best, best.PreferredEndpoint())
|
||||||
|
a.relay = best
|
||||||
}
|
}
|
||||||
|
|
||||||
a.devSetRelay(best, best.PreferredEndpoint())
|
for _, p := range a.peersByKey {
|
||||||
a.relay = best
|
if p.State != StateRelayed {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if best != nil {
|
||||||
|
a.devAddRelayed(p, best.VPNIP)
|
||||||
|
} else {
|
||||||
|
a.devAddPeer(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func preferredEndpoint(v4, v6 netip.AddrPort) netip.AddrPort {
|
func preferredEndpoint(v4, v6 netip.AddrPort) netip.AddrPort {
|
||||||
|
|||||||
@@ -54,5 +54,7 @@ func (a *App) addProbe(peer *Peer, v4, v6 netip.AddrPort) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
peer.UpdateEndpoints(v4, v6)
|
peer.UpdateEndpoints(v4, v6)
|
||||||
a.devAddProbe(peer, endpoint)
|
a.devAddDirect(peer, endpoint)
|
||||||
|
peer.State = StateProbing
|
||||||
|
peer.probeDeadline = time.Now().Add(probeTimeout)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"vppn/peer/control"
|
"vppn/peer/control"
|
||||||
"vppn/peer/wginterface"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) onTick() {
|
func (a *App) onTick() {
|
||||||
@@ -29,16 +28,27 @@ func (a *App) onTick() {
|
|||||||
|
|
||||||
switch p.State {
|
switch p.State {
|
||||||
case StateProbing:
|
case StateProbing:
|
||||||
// Promote probing peers to direct once alive (direct path confirmed
|
if p.Up() {
|
||||||
// working).
|
// Direct handshake succeeded; WG entry already correct.
|
||||||
if time.Since(p.LastHandshakeTime()) < wginterface.SessionTimeout {
|
p.State = StateDirect
|
||||||
a.devAddDirect(p, p.WGEndpoint())
|
} else if time.Now().After(p.probeDeadline) {
|
||||||
|
// Probe timed out — revert to relay.
|
||||||
|
if a.relay != nil {
|
||||||
|
a.devAddRelayed(p, a.relay.VPNIP)
|
||||||
|
} else {
|
||||||
|
a.devAddPeer(p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case StateDirect:
|
case StateDirect:
|
||||||
// Demote stale non-public direct peers back to probing.
|
// Demotion skips StateProbing — only probe when there is positive
|
||||||
|
// evidence of a direct path (ping or multicast beacon).
|
||||||
if !p.IsPublic && !p.Up() {
|
if !p.IsPublic && !p.Up() {
|
||||||
a.devAddProbe(p, p.WGEndpoint())
|
if a.relay != nil {
|
||||||
|
a.devAddRelayed(p, a.relay.VPNIP)
|
||||||
|
} else {
|
||||||
|
a.devAddPeer(p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user