Removed peer editing, cleanup

This commit is contained in:
jdl
2026-06-12 14:49:40 +02:00
parent 4d2aa5c8c7
commit 3e7d34a92a
17 changed files with 99 additions and 203 deletions

View File

@@ -24,7 +24,7 @@ type HubPoller struct {
statePath string // where the network state cache is persisted
addCh chan<- m.Peer
removeCh chan<- wgtypes.Key
known map[wgtypes.Key]int64 // pubKey → last seen version
known map[wgtypes.Key]struct{} // pubKeys currently configured
}
func NewHubPoller(
@@ -49,15 +49,15 @@ func NewHubPoller(
statePath: statePath,
addCh: addCh,
removeCh: removeCh,
known: make(map[wgtypes.Key]int64),
known: make(map[wgtypes.Key]struct{}),
}, nil
}
func (hp *HubPoller) Run() {
// Prime from the on-disk cache before reaching the hub, so the peer
// configures WireGuard from its last known state even if the hub is down.
// known starts empty, so this emits every cached peer as an add and seeds
// the version map; the first real poll then emits only deltas.
// known starts empty, so this emits every cached peer as an add; the first
// real poll then emits only deltas (adds for new peers, removes for gone).
if state, err := loadNetworkState(hp.statePath); err == nil {
hp.apply(state)
}
@@ -110,9 +110,10 @@ func (hp *HubPoller) poll() {
}
}
// apply diffs state against the known versions, emitting add events for new or
// changed peers and remove events for peers that disappeared. It returns true
// if anything changed.
// apply diffs state against the set of known peers, emitting an add for each
// newly-seen peer and a remove for each that disappeared. It returns true if
// anything changed. A peer's config is immutable under a stable WG key (the hub
// has no peer-edit path), so a key already in known needs no re-emit.
func (hp *HubPoller) apply(state m.NetworkState) (changed bool) {
seen := make(map[wgtypes.Key]struct{}, len(hp.known))
@@ -132,10 +133,10 @@ func (hp *HubPoller) apply(state m.NetworkState) (changed bool) {
seen[p.WGPubKey] = struct{}{}
if v, ok := hp.known[p.WGPubKey]; ok && v == p.Version {
if _, ok := hp.known[p.WGPubKey]; ok {
continue
}
hp.known[p.WGPubKey] = p.Version
hp.known[p.WGPubKey] = struct{}{}
hp.addCh <- p
changed = true
}

View File

@@ -18,15 +18,14 @@ func testPoller(t *testing.T) (*HubPoller, chan m.Peer, chan wgtypes.Key) {
vpnNet: netip.MustParsePrefix("10.0.0.0/24"),
addCh: addCh,
removeCh: removeCh,
known: make(map[wgtypes.Key]int64),
known: make(map[wgtypes.Key]struct{}),
}
return hp, addCh, removeCh
}
func stateWith(key wgtypes.Key, peerIP byte, version int64) m.NetworkState {
func stateWith(key wgtypes.Key, peerIP byte) m.NetworkState {
return m.NetworkState{Peers: []m.Peer{{
PeerIP: peerIP,
Version: version,
WGPubKey: key,
}}}
}
@@ -35,7 +34,7 @@ func TestApply_EmitsAddsAndReportsChange(t *testing.T) {
hp, addCh, _ := testPoller(t)
key := mustKey(t)
if changed := hp.apply(stateWith(key, 2, 1)); !changed {
if changed := hp.apply(stateWith(key, 2)); !changed {
t.Fatal("expected changed=true on first apply")
}
if len(addCh) != 1 {
@@ -46,41 +45,26 @@ func TestApply_EmitsAddsAndReportsChange(t *testing.T) {
}
}
func TestApply_NoChangeWhenVersionSame(t *testing.T) {
func TestApply_NoChangeWhenKnown(t *testing.T) {
hp, addCh, _ := testPoller(t)
key := mustKey(t)
hp.apply(stateWith(key, 2, 1))
hp.apply(stateWith(key, 2))
<-addCh // drain initial add
if changed := hp.apply(stateWith(key, 2, 1)); changed {
t.Fatal("expected changed=false when version unchanged")
if changed := hp.apply(stateWith(key, 2)); changed {
t.Fatal("expected changed=false when peer already known")
}
if len(addCh) != 0 {
t.Fatalf("expected no re-emit, got %d adds", len(addCh))
}
}
func TestApply_ReEmitsOnVersionBump(t *testing.T) {
hp, addCh, _ := testPoller(t)
key := mustKey(t)
hp.apply(stateWith(key, 2, 1))
<-addCh
if changed := hp.apply(stateWith(key, 2, 2)); !changed {
t.Fatal("expected changed=true on version bump")
}
if len(addCh) != 1 {
t.Fatalf("expected 1 re-emit, got %d", len(addCh))
}
}
func TestApply_RemovesVanishedPeer(t *testing.T) {
hp, addCh, removeCh := testPoller(t)
key := mustKey(t)
hp.apply(stateWith(key, 2, 1))
hp.apply(stateWith(key, 2))
<-addCh
// Empty state: the peer is gone.

View File

@@ -18,7 +18,6 @@ func TestNetworkState_RoundTrip(t *testing.T) {
state := m.NetworkState{Peers: []m.Peer{
{
PeerIP: 1,
Version: 7,
Name: "hub",
Addr4: netip.MustParseAddr("10.11.12.1"),
Port: 51820,
@@ -28,7 +27,6 @@ func TestNetworkState_RoundTrip(t *testing.T) {
},
{
PeerIP: 10,
Version: 3,
Name: "laptop",
Addr4: netip.MustParseAddr("10.11.12.10"),
Port: 51820,

View File

@@ -25,8 +25,8 @@ func (a *App) onAddPeer(p m.Peer) {
Name: p.Name,
IsRelay: p.Relay,
IsPublic: p.IsPublic(),
Endpoint4: p.Endpoint4(),
Endpoint6: p.Endpoint6(),
EndpointV4: p.Endpoint4(),
EndpointV6: p.Endpoint6(),
RTT: time.Duration(math.MaxInt64) * time.Nanosecond,
Role: roleFor(a.isPublic, a.vpnIP, p.IsPublic(), vpnIP),
SignPubKey: p.SignPubKey,

View File

@@ -280,7 +280,7 @@ func TestSwitchActiveRelay(t *testing.T) {
t.Errorf("call[0]: got %v, want AddDirect with ep1", dev.Calls[0])
}
dev.AssertSetRelay(t, 1, dev.Calls[1].PubKey, ep2, a.vpnNet)
if a.relay == nil || a.relay.Endpoint4 != ep2 {
if a.relay == nil || a.relay.EndpointV4 != ep2 {
t.Error("relay should be the backup peer")
}
},

View File

@@ -24,8 +24,8 @@ type Peer struct {
Name string // Human-readable DNS label.
IsRelay bool // Peer is a relay.
IsPublic bool // Peer has a public IP.
Endpoint4 netip.AddrPort // Reported IPv4 endpoint.
Endpoint6 netip.AddrPort // Reported IPv6 endpoint.
EndpointV4 netip.AddrPort // Reported IPv4 endpoint.
EndpointV6 netip.AddrPort // Reported IPv6 endpoint.
RTT time.Duration // Round-trip time.
State PeerState // Current routing state; updated on each devXxx call.
Role control.Role // Client initiates pings; server responds.
@@ -62,14 +62,14 @@ func (p *Peer) CanRelay() bool {
}
func (p *Peer) PreferredEndpoint() netip.AddrPort {
return preferredEndpoint(p.Endpoint4, p.Endpoint6)
return preferredEndpoint(p.EndpointV4, p.EndpointV6)
}
func (p *Peer) UpdateEndpoints(v4, v6 netip.AddrPort) {
if v4.IsValid() {
p.Endpoint4 = v4
p.EndpointV4 = v4
}
if v6.IsValid() {
p.Endpoint6 = v6
p.EndpointV6 = v6
}
}