mirror of
https://github.com/fosrl/olm.git
synced 2026-10-29 15:09:09 +01:00
Rapid test the local endpoints as well
This commit is contained in:
+34
-6
@@ -196,7 +196,7 @@ func (pm *PeerManager) AddPeer(siteConfig SiteConfig) error {
|
|||||||
|
|
||||||
// Perform rapid initial holepunch test (outside of lock to avoid blocking)
|
// Perform rapid initial holepunch test (outside of lock to avoid blocking)
|
||||||
// This quickly determines if holepunch is viable and triggers relay if not
|
// This quickly determines if holepunch is viable and triggers relay if not
|
||||||
go pm.performRapidInitialTest(siteConfig.SiteId, siteConfig.Endpoint)
|
go pm.performRapidInitialTest(siteConfig.SiteId, siteConfig.Endpoint, siteConfig.LocalEndpoints)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -868,15 +868,43 @@ endpoint=%s:%d`, util.FixKey(peer.PublicKey), formattedEndpoint, relayPort)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// performRapidInitialTest performs a rapid holepunch test for a newly added peer.
|
// performRapidInitialTest performs a rapid holepunch test for a newly added peer.
|
||||||
// If the test fails, it immediately requests relay to minimize connection delay.
|
// It races a test of the public endpoint against a test of the local candidate endpoints
|
||||||
// This runs in a goroutine to avoid blocking AddPeer.
|
// (if any) and waits for both to finish before acting, so we never request relay only to
|
||||||
func (pm *PeerManager) performRapidInitialTest(siteId int, endpoint string) {
|
// have it immediately superseded by a local connection (or vice versa). Local wins if it's
|
||||||
|
// viable at all; otherwise relay is requested only if the public endpoint isn't viable.
|
||||||
|
// This runs in a goroutine to avoid blocking AddPeer - the peer already starts out pointed
|
||||||
|
// at the public endpoint (set synchronously in AddPeer), so this just settles the peer onto
|
||||||
|
// its steady-state connection within ~1-2 seconds.
|
||||||
|
func (pm *PeerManager) performRapidInitialTest(siteId int, endpoint string, localEndpoints []string) {
|
||||||
if pm.peerMonitor == nil {
|
if pm.peerMonitor == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform rapid test - this takes ~1-2 seconds max
|
var wg sync.WaitGroup
|
||||||
holepunchViable := pm.peerMonitor.RapidTestPeer(siteId, endpoint)
|
var localWinner string
|
||||||
|
var holepunchViable bool
|
||||||
|
|
||||||
|
if len(localEndpoints) > 0 {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
localWinner = pm.peerMonitor.RapidTestLocalEndpoints(siteId, localEndpoints)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
holepunchViable = pm.peerMonitor.RapidTestPeer(siteId, endpoint)
|
||||||
|
}()
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if localWinner != "" {
|
||||||
|
logger.Info("Rapid test: local connection viable for site %d, switching to %s", siteId, localWinner)
|
||||||
|
pm.LocalPeer(siteId, localWinner)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if !holepunchViable {
|
if !holepunchViable {
|
||||||
// Holepunch failed rapid test, request relay immediately
|
// Holepunch failed rapid test, request relay immediately
|
||||||
|
|||||||
@@ -370,6 +370,49 @@ func (pm *PeerMonitor) RapidTestPeer(siteID int, endpoint string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RapidTestLocalEndpoints performs a rapid connectivity test of local candidate endpoints
|
||||||
|
// for a newly added peer, so local viability is known within the same ~1-2 second window as
|
||||||
|
// RapidTestPeer's public-endpoint test (rather than waiting for the next backoff-loop tick,
|
||||||
|
// which could be tens of seconds away). Candidates are tried in order (best-to-worst) and
|
||||||
|
// the first reachable one wins. Returns the winning endpoint, or "" if none are reachable.
|
||||||
|
func (pm *PeerMonitor) RapidTestLocalEndpoints(siteID int, endpoints []string) string {
|
||||||
|
if pm.holepunchTester == nil || len(endpoints) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
pm.mutex.Lock()
|
||||||
|
timeout := pm.rapidTestTimeout
|
||||||
|
pm.mutex.Unlock()
|
||||||
|
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
result := pm.holepunchTester.TestEndpoint(endpoint, timeout)
|
||||||
|
if !result.Success {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Rapid test: local endpoint %s for site %d SUCCEEDED (RTT: %v)", endpoint, siteID, result.RTT)
|
||||||
|
|
||||||
|
pm.mutex.Lock()
|
||||||
|
// Peer may have been removed while we were testing.
|
||||||
|
stillTracked := false
|
||||||
|
if _, tracked := pm.localEndpoints[siteID]; tracked {
|
||||||
|
stillTracked = true
|
||||||
|
pm.localActiveEndpoint[siteID] = endpoint
|
||||||
|
pm.localFailures[siteID] = 0
|
||||||
|
}
|
||||||
|
pm.mutex.Unlock()
|
||||||
|
|
||||||
|
if stillTracked {
|
||||||
|
pm.sendLocal(siteID, endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
return endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Rapid test: no local endpoint reachable for site %d", siteID)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// UpdatePeerEndpoint updates the monitor endpoint for a peer
|
// UpdatePeerEndpoint updates the monitor endpoint for a peer
|
||||||
func (pm *PeerMonitor) UpdatePeerEndpoint(siteID int, monitorPeer string) {
|
func (pm *PeerMonitor) UpdatePeerEndpoint(siteID int, monitorPeer string) {
|
||||||
pm.mutex.Lock()
|
pm.mutex.Lock()
|
||||||
|
|||||||
Reference in New Issue
Block a user