package autorelayimport ()// AutoRelay will call this function when it needs new candidates because it is// not connected to the desired number of relays or we get disconnected from one// of the relays. Implementations must send *at most* numPeers, and close the// channel when they don't intend to provide any more peers. AutoRelay will not// call the callback again until the channel is closed. Implementations should// send new peers, but may send peers they sent before. AutoRelay implements a// per-peer backoff (see WithBackoff). See WithMinInterval for setting the// minimum interval between calls to the callback. The context.Context passed// may be canceled when AutoRelay feels satisfied, it will be canceled when the// node is shutting down. If the context is canceled you MUST close the output// channel at some point.typePeerSourcefunc(ctx context.Context, num int) <-chanpeer.AddrInfotype config struct { clock ClockWithInstantTimer peerSource PeerSource// minimum interval used to call the peerSource callback minInterval time.Duration// see WithMinCandidates minCandidates int// see WithMaxCandidates maxCandidates int// Delay until we obtain reservations with relays, if we have less than minCandidates candidates. // See WithBootDelay. bootDelay time.Duration// backoff is the time we wait after failing to obtain a reservation with a candidate backoff time.Duration// Number of relays we strive to obtain a reservation with. desiredRelays int// see WithMaxCandidateAge maxCandidateAge time.Duration setMinCandidates bool// see WithMetricsTracer metricsTracer MetricsTracer}var defaultConfig = config{clock: RealClock{},minCandidates: 4,maxCandidates: 20,bootDelay: 3 * time.Minute,backoff: time.Hour,desiredRelays: 2,maxCandidateAge: 30 * time.Minute,minInterval: 30 * time.Second,}var ( errAlreadyHavePeerSource = errors.New("can only use a single WithPeerSource or WithStaticRelays"))typeOptionfunc(*config) errorfunc ( []peer.AddrInfo) Option {returnfunc( *config) error {if .peerSource != nil {returnerrAlreadyHavePeerSource }WithPeerSource(func( context.Context, int) <-chanpeer.AddrInfo {iflen() < { = len() } := make(chanpeer.AddrInfo, )deferclose()for := 0; < ; ++ { <- [] }return })()WithMinCandidates(len())()WithMaxCandidates(len())()WithNumRelays(len())()returnnil }}// WithPeerSource defines a callback for AutoRelay to query for more relay candidates.func ( PeerSource) Option {returnfunc( *config) error {if .peerSource != nil {returnerrAlreadyHavePeerSource } .peerSource = returnnil }}// WithNumRelays sets the number of relays we strive to obtain reservations with.func ( int) Option {returnfunc( *config) error { .desiredRelays = returnnil }}// WithMaxCandidates sets the number of relay candidates that we buffer.func ( int) Option {returnfunc( *config) error { .maxCandidates = if .minCandidates > { .minCandidates = }returnnil }}// WithMinCandidates sets the minimum number of relay candidates we collect before to get a reservation// with any of them (unless we've been running for longer than the boot delay).// This is to make sure that we don't just randomly connect to the first candidate that we discover.func ( int) Option {returnfunc( *config) error {if > .maxCandidates { = .maxCandidates } .minCandidates = .setMinCandidates = truereturnnil }}// WithBootDelay set the boot delay for finding relays.// We won't attempt any reservation if we've have less than a minimum number of candidates.// This prevents us to connect to the "first best" relay, and allows us to carefully select the relay.// However, in case we haven't found enough relays after the boot delay, we use what we have.func ( time.Duration) Option {returnfunc( *config) error { .bootDelay = returnnil }}// WithBackoff sets the time we wait after failing to obtain a reservation with a candidate.func ( time.Duration) Option {returnfunc( *config) error { .backoff = returnnil }}// WithMaxCandidateAge sets the maximum age of a candidate.// When we are connected to the desired number of relays, we don't ask the peer source for new candidates.// This can lead to AutoRelay's candidate list becoming outdated, and means we won't be able// to quickly establish a new relay connection if our existing connection breaks, if all the candidates// have become stale.func ( time.Duration) Option {returnfunc( *config) error { .maxCandidateAge = returnnil }}// InstantTimer is a timer that triggers at some instant rather than some durationtypeInstantTimerinterface {Reset(d time.Time) boolStop() boolCh() <-chantime.Time}// ClockWithInstantTimer is a clock that can create timers that trigger at some// instant rather than some durationtypeClockWithInstantTimerinterface {Now() time.TimeSince(t time.Time) time.DurationInstantTimer(when time.Time) InstantTimer}typeRealTimerstruct{ t *time.Timer }var _ InstantTimer = (*RealTimer)(nil)func ( RealTimer) () <-chantime.Time {return .t.C}func ( RealTimer) ( time.Time) bool {return .t.Reset(time.Until())}func ( RealTimer) () bool {return .t.Stop()}typeRealClockstruct{}var _ ClockWithInstantTimer = RealClock{}func (RealClock) () time.Time {returntime.Now()}func (RealClock) ( time.Time) time.Duration {returntime.Since()}func (RealClock) ( time.Time) InstantTimer { := time.NewTimer(time.Until())return &RealTimer{}}func ( ClockWithInstantTimer) Option {returnfunc( *config) error { .clock = returnnil }}// WithMinInterval sets the minimum interval after which peerSource callback will be called for more// candidates even if AutoRelay needs new candidates.func ( time.Duration) Option {returnfunc( *config) error { .minInterval = returnnil }}// WithMetricsTracer configures autorelay to use mt to track metricsfunc ( MetricsTracer) Option {returnfunc( *config) error { .metricsTracer = returnnil }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.