mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-11-16 05:05:17 +00:00
130 lines
2.8 KiB
Go
130 lines
2.8 KiB
Go
package autorelay
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
|
|
"github.com/libp2p/go-libp2p/core/event"
|
|
"github.com/libp2p/go-libp2p/core/host"
|
|
"github.com/libp2p/go-libp2p/core/network"
|
|
basic "github.com/libp2p/go-libp2p/p2p/host/basic"
|
|
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
|
|
|
|
logging "github.com/ipfs/go-log/v2"
|
|
ma "github.com/multiformats/go-multiaddr"
|
|
)
|
|
|
|
var log = logging.Logger("autorelay")
|
|
|
|
type AutoRelay struct {
|
|
refCount sync.WaitGroup
|
|
ctx context.Context
|
|
ctxCancel context.CancelFunc
|
|
|
|
conf *config
|
|
|
|
mx sync.Mutex
|
|
status network.Reachability
|
|
|
|
relayFinder *relayFinder
|
|
|
|
host host.Host
|
|
addrsF basic.AddrsFactory
|
|
|
|
metricsTracer MetricsTracer
|
|
}
|
|
|
|
func NewAutoRelay(bhost *basic.BasicHost, opts ...Option) (*AutoRelay, error) {
|
|
r := &AutoRelay{
|
|
host: bhost,
|
|
addrsF: bhost.AddrsFactory,
|
|
status: network.ReachabilityUnknown,
|
|
}
|
|
conf := defaultConfig
|
|
for _, opt := range opts {
|
|
if err := opt(&conf); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
r.ctx, r.ctxCancel = context.WithCancel(context.Background())
|
|
r.conf = &conf
|
|
r.relayFinder = newRelayFinder(bhost, conf.peerSource, &conf)
|
|
r.metricsTracer = &wrappedMetricsTracer{conf.metricsTracer}
|
|
bhost.AddrsFactory = r.hostAddrs
|
|
|
|
return r, nil
|
|
}
|
|
|
|
func (r *AutoRelay) Start() {
|
|
r.refCount.Add(1)
|
|
go func() {
|
|
r.background()
|
|
r.refCount.Done()
|
|
}()
|
|
}
|
|
|
|
func (r *AutoRelay) background() {
|
|
subReachability, err := r.host.EventBus().Subscribe(new(event.EvtLocalReachabilityChanged), eventbus.Name("autorelay (background)"))
|
|
if err != nil {
|
|
log.Debug("failed to subscribe to the EvtLocalReachabilityChanged")
|
|
return
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case <-r.ctx.Done():
|
|
subReachability.Close()
|
|
return
|
|
case ev, ok := <-subReachability.Out():
|
|
if !ok {
|
|
subReachability.Close()
|
|
return
|
|
}
|
|
// TODO: push changed addresses
|
|
evt := ev.(event.EvtLocalReachabilityChanged)
|
|
switch evt.Reachability {
|
|
case network.ReachabilityPrivate, network.ReachabilityUnknown:
|
|
err := r.relayFinder.Start()
|
|
if errors.Is(err, errAlreadyRunning) {
|
|
log.Debug("tried to start already running relay finder")
|
|
} else if err != nil {
|
|
log.Errorw("failed to start relay finder", "error", err)
|
|
} else {
|
|
r.metricsTracer.RelayFinderStatus(true)
|
|
}
|
|
case network.ReachabilityPublic:
|
|
r.relayFinder.Stop()
|
|
r.metricsTracer.RelayFinderStatus(false)
|
|
}
|
|
r.mx.Lock()
|
|
r.status = evt.Reachability
|
|
r.mx.Unlock()
|
|
}
|
|
}
|
|
}
|
|
|
|
func (r *AutoRelay) hostAddrs(addrs []ma.Multiaddr) []ma.Multiaddr {
|
|
return r.relayAddrs(r.addrsF(addrs))
|
|
}
|
|
|
|
func (r *AutoRelay) relayAddrs(addrs []ma.Multiaddr) []ma.Multiaddr {
|
|
r.mx.Lock()
|
|
|
|
if r.status != network.ReachabilityPrivate {
|
|
r.mx.Unlock()
|
|
return addrs
|
|
}
|
|
|
|
a := r.relayFinder.relayAddrs(addrs)
|
|
r.mx.Unlock()
|
|
return a
|
|
}
|
|
|
|
func (r *AutoRelay) Close() error {
|
|
r.ctxCancel()
|
|
err := r.relayFinder.Stop()
|
|
r.refCount.Wait()
|
|
return err
|
|
}
|