Skip to content

Commit

Permalink
implement relay discovery in autorelay
Browse files Browse the repository at this point in the history
  • Loading branch information
marten-seemann committed Mar 30, 2022
1 parent 63e5c36 commit b4a94f7
Show file tree
Hide file tree
Showing 8 changed files with 794 additions and 626 deletions.
7 changes: 3 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/libp2p/go-libp2p-core/transport"
"github.com/libp2p/go-libp2p-peerstore/pstoremem"

drouting "github.com/libp2p/go-libp2p/p2p/discovery/routing"
"github.com/libp2p/go-libp2p/p2p/host/autonat"
"github.com/libp2p/go-libp2p/p2p/host/autorelay"
bhost "github.com/libp2p/go-libp2p/p2p/host/basic"
Expand Down Expand Up @@ -270,7 +269,7 @@ func (cfg *Config) NewNode() (host.Host, error) {
}
}

// Note: h.AddrsFactory may be changed by AutoRelay, but non-relay version is
// Note: h.AddrsFactory may be changed by relayFinder, but non-relay version is
// used by AutoNAT below.
var ar *autorelay.AutoRelay
addrF := h.AddrsFactory
Expand All @@ -293,9 +292,9 @@ func (cfg *Config) NewNode() (host.Host, error) {
h.Close()
return nil, fmt.Errorf("cannot enable autorelay; no suitable routing for discovery")
}
opts = append(opts, autorelay.WithDiscoverer(drouting.NewRoutingDiscovery(crouter)))
_ = crouter
}
ar, err = autorelay.NewAutoRelay(h, router, opts...)
ar, err = autorelay.NewAutoRelay(h, nil, opts...)
if err != nil {
return nil, err
}
Expand Down
123 changes: 123 additions & 0 deletions p2p/host/autorelay/autorelay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package autorelay

import (
"context"
"sync"

basic "github.com/libp2p/go-libp2p/p2p/host/basic"

"github.com/libp2p/go-libp2p-core/event"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/network"
"github.com/libp2p/go-libp2p-core/peer"

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

mx sync.Mutex
status network.Reachability

relayFinder *relayFinder

peerChanIn <-chan peer.AddrInfo // capacity 0
peerChanOut chan peer.AddrInfo // capacity 20

host host.Host
addrsF basic.AddrsFactory
}

func NewAutoRelay(bhost *basic.BasicHost, peerChan <-chan peer.AddrInfo, opts ...Option) (*AutoRelay, error) {
r := &AutoRelay{
host: bhost,
addrsF: bhost.AddrsFactory,
status: network.ReachabilityUnknown,
peerChanIn: peerChan,
peerChanOut: make(chan peer.AddrInfo, 20),
}
r.ctx, r.ctxCancel = context.WithCancel(context.Background())
conf := defaultConfig
for _, opt := range opts {
if err := opt(&conf); err != nil {
return nil, err
}
}
r.relayFinder = newRelayFinder(bhost, r.peerChanOut, &conf)
bhost.AddrsFactory = r.hostAddrs

r.refCount.Add(1)
go func() {
defer r.refCount.Done()
r.background()
}()
return r, nil
}

func (r *AutoRelay) background() {
subReachability, err := r.host.EventBus().Subscribe(new(event.EvtLocalReachabilityChanged))
if err != nil {
log.Debug("failed to subscribe to the EvtLocalReachabilityChanged")
return
}
defer subReachability.Close()

for {
select {
case <-r.ctx.Done():
return
case ev, ok := <-subReachability.Out():
if !ok {
return
}
// TODO: push changed addresses
evt := ev.(event.EvtLocalReachabilityChanged)
switch evt.Reachability {
case network.ReachabilityPrivate, network.ReachabilityUnknown:
if err := r.relayFinder.Start(); err != nil {
log.Error("failed to start relay finder")
}
case network.ReachabilityPublic:
r.relayFinder.Stop()
}
r.mx.Lock()
r.status = evt.Reachability
r.mx.Unlock()
case pi := <-r.peerChanIn:
select {
case r.peerChanOut <- pi: // if there's space in the channel, great
default:
// no space left in the channel. Drop the oldest entry.
<-r.peerChanOut
r.peerChanOut <- pi
}
}
}
}

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()
defer r.mx.Unlock()

if r.status != network.ReachabilityPrivate {
return addrs
}
return r.relayFinder.relayAddrs(addrs)
}

func (r *AutoRelay) Close() error {
r.ctxCancel()
err := r.relayFinder.Stop()
r.refCount.Wait()
return err
}
Loading

0 comments on commit b4a94f7

Please sign in to comment.