Reflect local status in the api

This commit is contained in:
Owen
2026-07-17 13:58:20 -04:00
parent a2f0f64c2f
commit e1214e21cd
4 changed files with 56 additions and 8 deletions

View File

@@ -51,6 +51,7 @@ type PeerStatus struct {
LastSeen time.Time `json:"lastSeen"`
Endpoint string `json:"endpoint,omitempty"`
IsRelay bool `json:"isRelay"`
IsLocal bool `json:"isLocal"` // true when connected via a local network endpoint, bypassing both the public endpoint and relay
PeerIP string `json:"peerAddress,omitempty"`
HolepunchConnected bool `json:"holepunchConnected"`
}
@@ -229,7 +230,7 @@ func (s *API) Stop() error {
return nil
}
func (s *API) AddPeerStatus(siteID int, siteName string, connected bool, rtt time.Duration, endpoint string, isRelay bool) {
func (s *API) AddPeerStatus(siteID int, siteName string, connected bool, rtt time.Duration, endpoint string, isRelay bool, isLocal bool) {
s.statusMu.Lock()
defer s.statusMu.Unlock()
@@ -247,10 +248,11 @@ func (s *API) AddPeerStatus(siteID int, siteName string, connected bool, rtt tim
status.LastSeen = time.Now()
status.Endpoint = endpoint
status.IsRelay = isRelay
status.IsLocal = isLocal
}
// UpdatePeerStatus updates the status of a peer including endpoint and relay info
func (s *API) UpdatePeerStatus(siteID int, connected bool, rtt time.Duration, endpoint string, isRelay bool) {
// UpdatePeerStatus updates the status of a peer including endpoint, relay, and local info
func (s *API) UpdatePeerStatus(siteID int, connected bool, rtt time.Duration, endpoint string, isRelay bool, isLocal bool) {
s.statusMu.Lock()
defer s.statusMu.Unlock()
@@ -267,6 +269,7 @@ func (s *API) UpdatePeerStatus(siteID int, connected bool, rtt time.Duration, en
status.LastSeen = time.Now()
status.Endpoint = endpoint
status.IsRelay = isRelay
status.IsLocal = isLocal
}
func (s *API) RemovePeerStatus(siteID int) { // remove the peer from the status map
@@ -363,6 +366,31 @@ func (s *API) UpdatePeerRelayStatus(siteID int, endpoint string, isRelay bool) {
status.Endpoint = endpoint
status.IsRelay = isRelay
if isRelay {
// Relay and local are mutually exclusive; local always wins when viable.
status.IsLocal = false
}
}
// UpdatePeerLocalStatus updates only the local-connection status of a peer. A peer using a
// local connection is never simultaneously relayed.
func (s *API) UpdatePeerLocalStatus(siteID int, endpoint string, isLocal bool) {
s.statusMu.Lock()
defer s.statusMu.Unlock()
status, exists := s.peerStatuses[siteID]
if !exists {
status = &PeerStatus{
SiteID: siteID,
}
s.peerStatuses[siteID] = status
}
status.Endpoint = endpoint
status.IsLocal = isLocal
if isLocal {
status.IsRelay = false
}
}
// UpdatePeerHolepunchStatus updates the holepunch connection status of a peer

View File

@@ -192,7 +192,7 @@ func (o *Olm) handleConnect(msg websocket.WSMessage) {
siteEndpoint = site.Endpoint
}
o.apiServer.AddPeerStatus(site.SiteId, site.Name, false, 0, siteEndpoint, false)
o.apiServer.AddPeerStatus(site.SiteId, site.Name, false, 0, siteEndpoint, false, false)
}
// we still call this to add the aliases for jit lookup but we just do that then pass inside. need to skip the above so we dont add to the api

View File

@@ -192,7 +192,7 @@ func (pm *PeerManager) AddPeer(siteConfig SiteConfig) error {
pm.peers[siteConfig.SiteId] = siteConfig
pm.APIServer.AddPeerStatus(siteConfig.SiteId, siteConfig.Name, false, 0, siteConfig.Endpoint, false)
pm.APIServer.AddPeerStatus(siteConfig.SiteId, siteConfig.Name, false, 0, siteConfig.Endpoint, false, false)
// Perform rapid initial holepunch test (outside of lock to avoid blocking)
// This quickly determines if holepunch is viable and triggers relay if not
@@ -1031,6 +1031,10 @@ endpoint=%s`, util.FixKey(peer.PublicKey), localEndpoint)
return
}
if pm.APIServer != nil {
pm.APIServer.UpdatePeerLocalStatus(siteId, localEndpoint, true)
}
logger.Info("Switched peer %d to local connection at %s", siteId, localEndpoint)
}
@@ -1060,6 +1064,11 @@ func (pm *PeerManager) UnLocalPeer(siteId int) {
if err := pm.UnRelayPeer(siteId, resolved); err != nil {
logger.Error("Failed to fall back peer %d from local connection: %v", siteId, err)
return
}
if pm.APIServer != nil {
pm.APIServer.UpdatePeerLocalStatus(siteId, resolved, false)
}
}

View File

@@ -502,9 +502,18 @@ func (pm *PeerMonitor) handleConnectionStatusChange(siteID int, status Connectio
pm.wgConnectionRTT[siteID] = status.RTT
}
isRelayed := pm.relayedPeers[siteID]
localEndpoint := pm.localActiveEndpoint[siteID]
endpoint := pm.holepunchEndpoints[siteID]
pm.mutex.Unlock()
isLocal := localEndpoint != ""
if isLocal {
// Report the active local endpoint rather than the public one; local and relay
// are mutually exclusive.
endpoint = localEndpoint
isRelayed = false
}
// Log status changes
if !exists || previousStatus != status.Connected {
if status.Connected {
@@ -516,7 +525,7 @@ func (pm *PeerMonitor) handleConnectionStatusChange(siteID int, status Connectio
// Update API with connection status
if pm.apiServer != nil {
pm.apiServer.UpdatePeerStatus(siteID, status.Connected, status.RTT, endpoint, isRelayed)
pm.apiServer.UpdatePeerStatus(siteID, status.Connected, status.RTT, endpoint, isRelayed, isLocal)
}
// Notify route optimizer of status change
@@ -1002,8 +1011,10 @@ func (pm *PeerMonitor) checkHolepunchEndpoints() bool {
wgConnected := pm.wgConnectionStatus[siteID]
pm.mutex.Unlock()
// Update API - use holepunch endpoint and relay status
pm.apiServer.UpdatePeerStatus(siteID, wgConnected, result.RTT, endpoint, isRelayed)
// Update API - use holepunch endpoint and relay status. Sites with an active
// local endpoint are filtered out of this loop above, so isLocal is always
// false here.
pm.apiServer.UpdatePeerStatus(siteID, wgConnected, result.RTT, endpoint, isRelayed, false)
}
// Handle relay logic based on holepunch status