From 3e7d34a92a5fbab9eb3e15f833b4fc4cbd419b6f Mon Sep 17 00:00:00 2001 From: jdl Date: Fri, 12 Jun 2026 14:49:40 +0200 Subject: [PATCH] Removed peer editing, cleanup --- hub/api/api.go | 102 ++++++++++++++----------- hub/api/db/generated.go | 17 ++--- hub/api/db/tables.defs | 11 ++- hub/api/migrations/2024-11-30-init.sql | 1 - hub/handler.go | 4 - hub/handlers.go | 51 +------------ hub/routes.go | 2 - hub/templates/network/peer-delete.html | 2 +- hub/templates/network/peer-edit.html | 38 --------- hub/templates/network/peer-view.html | 1 - m/models.go | 4 - peer/hub_poller.go | 19 ++--- peer/hub_poller_test.go | 32 ++------ peer/network_state_test.go | 2 - peer/on_hub.go | 4 +- peer/on_hub_test.go | 2 +- peer/remote.go | 10 +-- 17 files changed, 99 insertions(+), 203 deletions(-) delete mode 100644 hub/templates/network/peer-edit.html diff --git a/hub/api/api.go b/hub/api/api.go index a0fa94e..19838b8 100644 --- a/hub/api/api.go +++ b/hub/api/api.go @@ -40,7 +40,13 @@ func New(dbPath string) (*API, error) { sessions: make(map[string]*Session), } - return a, a.ensurePassword() + if err := a.ensurePassword(); err != nil { + return nil, err + } + + go a.sweepSessions() + + return a, nil } func (a *API) ensurePassword() error { @@ -80,58 +86,72 @@ func (a *API) Session_Delete(sessionID string) error { return nil } -// Session_Get returns a snapshot copy of the session for sessionID (creating a -// fresh one if absent/expired). Returning a value rather than the stored -// pointer prevents callers from racing on the shared struct; mutations go -// through Session_SignIn / Session_Delete under the lock. +const ( + sessionTTLSecs = 86400 * 21 // sessions expire 21 days after last use + sessionSweepEvery = time.Hour // cadence of expired-session eviction +) + +// Session_Get returns a snapshot copy of the signed-in session for sessionID, +// or the zero Session if the cookie is missing/unknown/expired. It never +// creates a session, so anonymous requests cost no memory — a session is minted +// only by Session_SignIn. Returning a value (not the stored pointer) keeps +// callers from racing on the shared struct. func (a *API) Session_Get(sessionID string) (Session, error) { a.sessionsMu.Lock() defer a.sessionsMu.Unlock() - if sessionID != "" { - s, ok := a.sessions[sessionID] - if ok { - if timeSince(s.LastSeenAt) <= 86400*21 { - if timeSince(s.LastSeenAt) > 86400*7 { - s.LastSeenAt = time.Now().Unix() - } - return *s, nil - } - delete(a.sessions, sessionID) - } + s, ok := a.sessions[sessionID] + + if sessionID == "" || !ok { + return Session{}, nil } - return *a.session_Create(), nil + if timeSince(s.LastSeenAt) > sessionTTLSecs { + delete(a.sessions, sessionID) + return Session{}, nil + } + + s.LastSeenAt = time.Now().Unix() + return *s, nil } -// caller must hold sessionsMu -func (a *API) session_Create() *Session { +// Session_SignIn verifies pwd and, on success, mints a fresh signed-in session, +// returning it so the caller can set the cookie. A new ID per sign-in rotates +// the session at the privilege boundary (session-fixation resistance). +func (a *API) Session_SignIn(pwd string) (Session, error) { + conf, err := a.Config_Get() + if err != nil { + return Session{}, err + } + if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil { + return Session{}, ErrNotAuthorized + } + + a.sessionsMu.Lock() + defer a.sessionsMu.Unlock() s := &Session{ SessionID: idgen.NewToken(), + SignedIn: true, CreatedAt: time.Now().Unix(), LastSeenAt: time.Now().Unix(), } a.sessions[s.SessionID] = s - return s + return *s, nil } -func (a *API) Session_SignIn(sessionID, pwd string) error { - conf, err := a.Config_Get() - if err != nil { - return err +// sweepSessions periodically evicts sessions past their TTL. Without it, a +// signed-in session whose ID is never presented again would linger forever +// (Session_Get only evicts on a lookup of that same ID). +func (a *API) sweepSessions() { + for range time.Tick(sessionSweepEvery) { + a.sessionsMu.Lock() + for id, s := range a.sessions { + if timeSince(s.LastSeenAt) > sessionTTLSecs { + delete(a.sessions, id) + } + } + a.sessionsMu.Unlock() } - if err := bcrypt.CompareHashAndPassword(conf.Password, []byte(pwd)); err != nil { - return ErrNotAuthorized - } - a.sessionsMu.Lock() - defer a.sessionsMu.Unlock() - s, ok := a.sessions[sessionID] - if !ok { - // Session expired or was evicted between fetch and sign-in. - return ErrNotAuthorized - } - s.SignedIn = true - return nil } func (a *API) Network_Create(n *Network) error { @@ -153,7 +173,6 @@ func (a *API) Network_List() ([]*Network, error) { } func (a *API) Peer_CreateNew(p *Peer) error { - p.Version = idgen.NextID(0) p.WGPubKey = []byte{} p.SignPubKey = []byte{} p.APIKey = idgen.NewToken() @@ -175,21 +194,12 @@ func (a *API) Peer_Init(peer *Peer, args m.PeerInitArgs) error { return errors.New("peer already initialized") } - peer.Version = idgen.NextID(0) peer.WGPubKey = args.WGPubKey peer.SignPubKey = args.SignPubKey return db.Peer_UpdateFull(a.db, peer) } -func (a *API) Peer_Update(p *Peer) error { - a.lock.Lock() - defer a.lock.Unlock() - - p.Version = idgen.NextID(0) - return db.Peer_Update(a.db, p) -} - func (a *API) Peer_Delete(networkID int64, peerIP byte) error { return db.Peer_Delete(a.db, networkID, peerIP) } diff --git a/hub/api/db/generated.go b/hub/api/db/generated.go index e0ac098..22ca0f8 100644 --- a/hub/api/db/generated.go +++ b/hub/api/db/generated.go @@ -341,7 +341,6 @@ func Network_List( type Peer struct { NetworkID int64 PeerIP byte - Version int64 APIKey string Name string Addr4 []byte @@ -352,7 +351,7 @@ type Peer struct { SignPubKey []byte } -const Peer_SelectQuery = "SELECT NetworkID,PeerIP,Version,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey FROM peers" +const Peer_SelectQuery = "SELECT NetworkID,PeerIP,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey FROM peers" func Peer_Insert( tx TX, @@ -363,7 +362,7 @@ func Peer_Insert( return err } - _, err = tx.Exec("INSERT INTO peers(NetworkID,PeerIP,Version,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey) VALUES(?,?,?,?,?,?,?,?,?,?,?)", row.NetworkID, row.PeerIP, row.Version, row.APIKey, row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.WGPubKey, row.SignPubKey) + _, err = tx.Exec("INSERT INTO peers(NetworkID,PeerIP,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey) VALUES(?,?,?,?,?,?,?,?,?,?)", row.NetworkID, row.PeerIP, row.APIKey, row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.WGPubKey, row.SignPubKey) return err } @@ -376,7 +375,7 @@ func Peer_Update( return err } - result, err := tx.Exec("UPDATE peers SET Version=?,Name=?,Addr4=?,Addr6=?,Port=?,Relay=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.NetworkID, row.PeerIP) + result, err := tx.Exec("UPDATE peers SET Name=?,Addr4=?,Addr6=?,Port=?,Relay=? WHERE NetworkID=? AND PeerIP=?", row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.NetworkID, row.PeerIP) if err != nil { return err } @@ -404,7 +403,7 @@ func Peer_UpdateFull( return err } - result, err := tx.Exec("UPDATE peers SET Version=?,APIKey=?,Name=?,Addr4=?,Addr6=?,Port=?,Relay=?,WGPubKey=?,SignPubKey=? WHERE NetworkID=? AND PeerIP=?", row.Version, row.APIKey, row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.WGPubKey, row.SignPubKey, row.NetworkID, row.PeerIP) + result, err := tx.Exec("UPDATE peers SET APIKey=?,Name=?,Addr4=?,Addr6=?,Port=?,Relay=?,WGPubKey=?,SignPubKey=? WHERE NetworkID=? AND PeerIP=?", row.APIKey, row.Name, row.Addr4, row.Addr6, row.Port, row.Relay, row.WGPubKey, row.SignPubKey, row.NetworkID, row.PeerIP) if err != nil { return err } @@ -456,8 +455,8 @@ func Peer_Get( err error, ) { row = &Peer{} - r := tx.QueryRow("SELECT NetworkID,PeerIP,Version,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP) - if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey); err != nil { + r := tx.QueryRow("SELECT NetworkID,PeerIP,APIKey,Name,Addr4,Addr6,Port,Relay,WGPubKey,SignPubKey FROM peers WHERE NetworkID=? AND PeerIP=?", NetworkID, PeerIP) + if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey); err != nil { row = nil } return @@ -473,7 +472,7 @@ func Peer_GetWhere( ) { row = &Peer{} r := tx.QueryRow(query, args...) - if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey); err != nil { + if err = r.Scan(&row.NetworkID, &row.PeerIP, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey); err != nil { row = nil } return @@ -495,7 +494,7 @@ func Peer_Iterate( defer rows.Close() for rows.Next() { row := &Peer{} - err := rows.Scan(&row.NetworkID, &row.PeerIP, &row.Version, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey) + err := rows.Scan(&row.NetworkID, &row.PeerIP, &row.APIKey, &row.Name, &row.Addr4, &row.Addr6, &row.Port, &row.Relay, &row.WGPubKey, &row.SignPubKey) if !yield(row, err) { return } diff --git a/hub/api/db/tables.defs b/hub/api/db/tables.defs index e3ca04f..39665fa 100644 --- a/hub/api/db/tables.defs +++ b/hub/api/db/tables.defs @@ -12,13 +12,12 @@ TABLE networks OF Network ( TABLE peers OF Peer ( NetworkID int64 PK, PeerIP byte PK, - Version int64, APIKey string NoUpdate, - Name string, - Addr4 []byte, - Addr6 []byte, - Port uint16, - Relay bool, + Name string NoUpdate, + Addr4 []byte NoUpdate, + Addr6 []byte NoUpdate, + Port uint16 NoUpdate, + Relay bool NoUpdate, WGPubKey []byte NoUpdate, SignPubKey []byte NoUpdate ); diff --git a/hub/api/migrations/2024-11-30-init.sql b/hub/api/migrations/2024-11-30-init.sql index b443841..bce964b 100644 --- a/hub/api/migrations/2024-11-30-init.sql +++ b/hub/api/migrations/2024-11-30-init.sql @@ -12,7 +12,6 @@ CREATE TABLE networks ( CREATE TABLE peers ( NetworkID INTEGER NOT NULL, PeerIP INTEGER NOT NULL, -- Final byte of IP. - Version INTEGER NOT NULL, -- Changes when updated. APIKey TEXT NOT NULL UNIQUE, -- Peer's secret API key. Name TEXT NOT NULL, -- For humans. Addr4 BLOB NOT NULL, diff --git a/hub/handler.go b/hub/handler.go index 1581a73..7dedf05 100644 --- a/hub/handler.go +++ b/hub/handler.go @@ -20,10 +20,6 @@ func (app *App) handlePub(pattern string, fn handlerFunc) { return } - if s.SessionID != sessionID { - app.setCookie(w, SESSION_ID_COOKIE_NAME, s.SessionID) - } - if r.Method == http.MethodPost { r.ParseMultipartForm(64 * 1024) } else { diff --git a/hub/handlers.go b/hub/handlers.go index 5d30ba0..7f90f80 100644 --- a/hub/handlers.go +++ b/hub/handlers.go @@ -34,9 +34,11 @@ func (a *App) _signinSubmit(s *api.Session, w http.ResponseWriter, r *http.Reque return err } - if err := a.api.Session_SignIn(s.SessionID, pwd); err != nil { + sess, err := a.api.Session_SignIn(pwd) + if err != nil { return err } + a.setCookie(w, SESSION_ID_COOKIE_NAME, sess.SessionID) return a.redirect(w, r, "/") } @@ -185,52 +187,6 @@ func (a *App) _adminPeerView(s *api.Session, w http.ResponseWriter, r *http.Requ }{s, net, peer}) } -func (a *App) _adminPeerEdit(s *api.Session, w http.ResponseWriter, r *http.Request) error { - net, peer, err := a.formGetPeer(r.Form) - if err != nil { - return err - } - - return a.render("/network/peer-edit.html", w, struct { - Session *api.Session - Network *api.Network - Peer *api.Peer - }{s, net, peer}) -} - -func (a *App) _adminPeerEditSubmit(s *api.Session, w http.ResponseWriter, r *http.Request) error { - _, peer, err := a.formGetPeer(r.Form) - if err != nil { - return err - } - - var addr4Str, addr6Str string - - err = webutil.NewFormScanner(r.Form). - Scan("Name", &peer.Name). - Scan("Addr4", &addr4Str). - Scan("Addr6", &addr6Str). - Scan("Port", &peer.Port). - Scan("Relay", &peer.Relay). - Error() - if err != nil { - return err - } - - if peer.Addr4, err = stringToIP(addr4Str); err != nil { - return err - } - if peer.Addr6, err = stringToIP(addr6Str); err != nil { - return err - } - - if err = a.api.Peer_Update(peer); err != nil { - return err - } - - return a.redirect(w, r, "/admin/peer/view/?NetworkID=%d&PeerIP=%d", peer.NetworkID, peer.PeerIP) -} - func (a *App) _adminPeerDelete(s *api.Session, w http.ResponseWriter, r *http.Request) error { n, peer, err := a.formGetPeer(r.Form) if err != nil { @@ -378,7 +334,6 @@ func (a *App) peersList(networkID int64) (peers []m.Peer, err error) { copy(signKey[:], p.SignPubKey) peers = append(peers, m.Peer{ PeerIP: p.PeerIP, - Version: p.Version, Name: p.Name, Addr4: addrFromBytes(p.Addr4), Addr6: addrFromBytes(p.Addr6), diff --git a/hub/routes.go b/hub/routes.go index bb2d555..3ba5fe3 100644 --- a/hub/routes.go +++ b/hub/routes.go @@ -22,8 +22,6 @@ func (a *App) registerRoutes() { a.handleSignedIn("GET /admin/peer/create/", a._adminPeerCreate) a.handleSignedIn("POST /admin/peer/create/", a._adminPeerCreateSubmit) a.handleSignedIn("GET /admin/peer/view/", a._adminPeerView) - a.handleSignedIn("GET /admin/peer/edit/", a._adminPeerEdit) - a.handleSignedIn("POST /admin/peer/edit/", a._adminPeerEditSubmit) a.handleSignedIn("GET /admin/peer/delete/", a._adminPeerDelete) a.handleSignedIn("POST /admin/peer/delete/", a._adminPeerDeleteSubmit) diff --git a/hub/templates/network/peer-delete.html b/hub/templates/network/peer-delete.html index afb5aca..0161999 100644 --- a/hub/templates/network/peer-delete.html +++ b/hub/templates/network/peer-delete.html @@ -4,7 +4,7 @@ {{with .Peer -}}
- +

Cancel diff --git a/hub/templates/network/peer-edit.html b/hub/templates/network/peer-edit.html deleted file mode 100644 index 4fd89a8..0000000 --- a/hub/templates/network/peer-edit.html +++ /dev/null @@ -1,38 +0,0 @@ -{{define "body" -}} -

Edit Peer

- -{{with .Peer -}} - -

-
- -

-

-
- -

-

-
- -

-

-
- -

-

-
- -

-

- -

-

- - Cancel -

-
-{{- end}} -{{- end}} diff --git a/hub/templates/network/peer-view.html b/hub/templates/network/peer-view.html index 3d41b02..11bf105 100644 --- a/hub/templates/network/peer-view.html +++ b/hub/templates/network/peer-view.html @@ -1,7 +1,6 @@ {{define "body" -}}

{{.Peer.Name}}

- Edit / Delete

diff --git a/m/models.go b/m/models.go index b751ef8..386401c 100644 --- a/m/models.go +++ b/m/models.go @@ -28,7 +28,6 @@ type PeerInitResp struct { // non-public peer (it is the peer's own bind/beacon port). type Peer struct { PeerIP byte - Version int64 Name string Addr4 netip.Addr // zero if none Addr6 netip.Addr // zero if none @@ -74,7 +73,6 @@ func (p Peer) PreferredEndpoint() netip.AddrPort { // encoding/json would emit them as arrays of numbers). type peerJSON struct { PeerIP byte - Version int64 Name string Addr4 netip.Addr Addr6 netip.Addr @@ -87,7 +85,6 @@ type peerJSON struct { func (p Peer) MarshalJSON() ([]byte, error) { return json.Marshal(peerJSON{ PeerIP: p.PeerIP, - Version: p.Version, Name: p.Name, Addr4: p.Addr4, Addr6: p.Addr6, @@ -120,7 +117,6 @@ func (p *Peer) UnmarshalJSON(data []byte) error { } *p = Peer{ PeerIP: j.PeerIP, - Version: j.Version, Name: j.Name, Addr4: j.Addr4, Addr6: j.Addr6, diff --git a/peer/hub_poller.go b/peer/hub_poller.go index a41f888..2138e86 100644 --- a/peer/hub_poller.go +++ b/peer/hub_poller.go @@ -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 } diff --git a/peer/hub_poller_test.go b/peer/hub_poller_test.go index 4131a23..87efba3 100644 --- a/peer/hub_poller_test.go +++ b/peer/hub_poller_test.go @@ -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. diff --git a/peer/network_state_test.go b/peer/network_state_test.go index 85d9c0e..be1fd23 100644 --- a/peer/network_state_test.go +++ b/peer/network_state_test.go @@ -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, diff --git a/peer/on_hub.go b/peer/on_hub.go index 2dc6558..677263f 100644 --- a/peer/on_hub.go +++ b/peer/on_hub.go @@ -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, diff --git a/peer/on_hub_test.go b/peer/on_hub_test.go index 5114563..230aa93 100644 --- a/peer/on_hub_test.go +++ b/peer/on_hub_test.go @@ -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") } }, diff --git a/peer/remote.go b/peer/remote.go index 6ef7bbe..d3b889a 100644 --- a/peer/remote.go +++ b/peer/remote.go @@ -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 } }