mirror of
https://github.com/luxfi/node.git
synced 2026-07-27 03:39:39 +00:00
78 lines
1.9 KiB
Go
78 lines
1.9 KiB
Go
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package network
|
|
|
|
import (
|
|
"math/rand"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/luxfi/net/endpoints"
|
|
)
|
|
|
|
func init() {
|
|
rand.Seed(time.Now().UnixNano())
|
|
}
|
|
|
|
// trackedIP tracks an endpoint that we are trying to connect to.
|
|
// The endpoint can be either an IP address or a hostname.
|
|
type trackedIP struct {
|
|
delayLock sync.RWMutex
|
|
delay time.Duration
|
|
|
|
endpoint endpoints.Endpoint
|
|
|
|
stopTrackingOnce sync.Once
|
|
onStopTracking chan struct{}
|
|
}
|
|
|
|
func newTrackedIP(endpoint endpoints.Endpoint) *trackedIP {
|
|
return &trackedIP{
|
|
endpoint: endpoint,
|
|
onStopTracking: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (ip *trackedIP) trackNewEndpoint(newEndpoint endpoints.Endpoint) *trackedIP {
|
|
ip.stopTracking()
|
|
return &trackedIP{
|
|
delay: ip.getDelay(),
|
|
endpoint: newEndpoint,
|
|
onStopTracking: make(chan struct{}),
|
|
}
|
|
}
|
|
|
|
func (ip *trackedIP) getDelay() time.Duration {
|
|
ip.delayLock.RLock()
|
|
delay := ip.delay
|
|
ip.delayLock.RUnlock()
|
|
return delay
|
|
}
|
|
|
|
func (ip *trackedIP) increaseDelay(initialDelay, maxDelay time.Duration) {
|
|
ip.delayLock.Lock()
|
|
defer ip.delayLock.Unlock()
|
|
|
|
// If the timeout was previously 0, ensure that there is a reasonable delay.
|
|
if ip.delay <= 0 {
|
|
ip.delay = initialDelay
|
|
}
|
|
|
|
// Randomization is only performed here to distribute reconnection
|
|
// attempts to a node that previously shut down. This doesn't
|
|
// require cryptographically secure random number generation.
|
|
// set the timeout to [1, 2) * timeout
|
|
ip.delay = time.Duration(float64(ip.delay) * (1 + rand.Float64())) // #nosec G404
|
|
if ip.delay > maxDelay {
|
|
// set the timeout to [.75, 1) * maxDelay
|
|
ip.delay = time.Duration(float64(maxDelay) * (3 + rand.Float64()) / 4) // #nosec G404
|
|
}
|
|
}
|
|
|
|
func (ip *trackedIP) stopTracking() {
|
|
ip.stopTrackingOnce.Do(func() {
|
|
close(ip.onStopTracking)
|
|
})
|
|
}
|