Skip to content

Commit 762a43e

Browse files
committed
autorelay: send addresses on eventbus; dont wrap address factory
1 parent 8423de3 commit 762a43e

File tree

8 files changed

+223
-126
lines changed

8 files changed

+223
-126
lines changed

config/config.go

+8-26
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,8 @@ func (cfg *Config) newBasicHost(swrm *swarm.Swarm, eventBus event.Bus) (*bhost.B
439439
DisableIdentifyAddressDiscovery: cfg.DisableIdentifyAddressDiscovery,
440440
EnableAutoNATv2: cfg.EnableAutoNATv2,
441441
AutoNATv2Dialer: autonatv2Dialer,
442+
EnableAutoRelay: cfg.EnableAutoRelay,
443+
AutoRelayOpts: cfg.AutoRelayOpts,
442444
})
443445
if err != nil {
444446
return nil, err
@@ -518,28 +520,6 @@ func (cfg *Config) NewNode() (host.Host, error) {
518520
)
519521
}
520522

521-
// enable autorelay
522-
fxopts = append(fxopts,
523-
fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) error {
524-
if cfg.EnableAutoRelay {
525-
if !cfg.DisableMetrics {
526-
mt := autorelay.WithMetricsTracer(
527-
autorelay.NewMetricsTracer(autorelay.WithRegisterer(cfg.PrometheusRegisterer)))
528-
mtOpts := []autorelay.Option{mt}
529-
cfg.AutoRelayOpts = append(mtOpts, cfg.AutoRelayOpts...)
530-
}
531-
532-
ar, err := autorelay.NewAutoRelay(h, cfg.AutoRelayOpts...)
533-
if err != nil {
534-
return err
535-
}
536-
lifecycle.Append(fx.StartStopHook(ar.Start, ar.Close))
537-
return nil
538-
}
539-
return nil
540-
}),
541-
)
542-
543523
var bh *bhost.BasicHost
544524
fxopts = append(fxopts, fx.Invoke(func(bho *bhost.BasicHost) { bh = bho }))
545525
fxopts = append(fxopts, fx.Invoke(func(h *bhost.BasicHost, lifecycle fx.Lifecycle) {
@@ -554,12 +534,10 @@ func (cfg *Config) NewNode() (host.Host, error) {
554534
fxopts = append(fxopts, cfg.UserFxOptions...)
555535

556536
app := fx.New(fxopts...)
557-
if err := app.Start(context.Background()); err != nil {
558-
return nil, err
537+
if app.Err() != nil {
538+
return nil, fmt.Errorf("failed to create host: %w", app.Err())
559539
}
560-
561540
if err := cfg.addAutoNAT(bh); err != nil {
562-
app.Stop(context.Background())
563541
if cfg.Routing != nil {
564542
rh.Close()
565543
} else {
@@ -568,6 +546,10 @@ func (cfg *Config) NewNode() (host.Host, error) {
568546
return nil, err
569547
}
570548

549+
if err := app.Start(context.Background()); err != nil {
550+
return nil, err
551+
}
552+
571553
if cfg.Routing != nil {
572554
return &closableRoutedHost{App: app, RoutedHost: rh}, nil
573555
}

core/event/addrs.go

+5
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,8 @@ type EvtLocalAddressesUpdated struct {
8181
// wrapped in a record.Envelope and signed by the Host's private key.
8282
SignedPeerRecord *record.Envelope
8383
}
84+
85+
// EvtAutoRelayAddrsUpdated is sent by the autorelay when the node's relay addresses are updated
86+
type EvtAutoRelayAddrs struct {
87+
RelayAddrs []ma.Multiaddr
88+
}

p2p/host/autorelay/addrsplosion.go

+4-11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import (
99

1010
// This function cleans up a relay's address set to remove private addresses and curtail
1111
// addrsplosion.
12+
// TODO: Remove this, we don't need this. The current method tries to select the
13+
// best address for the relay. Instead we should rely on the addresses provided by the
14+
// relay in response to the reservation request.
1215
func cleanupAddressSet(addrs []ma.Multiaddr) []ma.Multiaddr {
1316
var public, private []ma.Multiaddr
1417

@@ -17,7 +20,7 @@ func cleanupAddressSet(addrs []ma.Multiaddr) []ma.Multiaddr {
1720
continue
1821
}
1922

20-
if manet.IsPublicAddr(a) || isDNSAddr(a) {
23+
if manet.IsPublicAddr(a) {
2124
public = append(public, a)
2225
continue
2326
}
@@ -51,16 +54,6 @@ func isRelayAddr(a ma.Multiaddr) bool {
5154
return isRelay
5255
}
5356

54-
func isDNSAddr(a ma.Multiaddr) bool {
55-
if first, _ := ma.SplitFirst(a); first != nil {
56-
switch first.Protocol().Code {
57-
case ma.P_DNS, ma.P_DNS4, ma.P_DNS6, ma.P_DNSADDR:
58-
return true
59-
}
60-
}
61-
return false
62-
}
63-
6457
// we have addrsplosion if for some protocol we advertise multiple ports on
6558
// the same base address.
6659
func hasAddrsplosion(addrs []ma.Multiaddr) bool {

p2p/host/autorelay/autorelay.go

+13-24
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ package autorelay
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"sync"
78

89
"github.com/libp2p/go-libp2p/core/event"
910
"github.com/libp2p/go-libp2p/core/host"
1011
"github.com/libp2p/go-libp2p/core/network"
11-
basic "github.com/libp2p/go-libp2p/p2p/host/basic"
1212
"github.com/libp2p/go-libp2p/p2p/host/eventbus"
13+
ma "github.com/multiformats/go-multiaddr"
1314

1415
logging "github.com/ipfs/go-log/v2"
15-
ma "github.com/multiformats/go-multiaddr"
1616
)
1717

1818
var log = logging.Logger("autorelay")
@@ -22,8 +22,6 @@ type AutoRelay struct {
2222
ctx context.Context
2323
ctxCancel context.CancelFunc
2424

25-
conf *config
26-
2725
mx sync.Mutex
2826
status network.Reachability
2927

@@ -34,9 +32,9 @@ type AutoRelay struct {
3432
metricsTracer MetricsTracer
3533
}
3634

37-
func NewAutoRelay(bhost *basic.BasicHost, opts ...Option) (*AutoRelay, error) {
35+
func NewAutoRelay(host host.Host, opts ...Option) (*AutoRelay, error) {
3836
r := &AutoRelay{
39-
host: bhost,
37+
host: host,
4038
status: network.ReachabilityUnknown,
4139
}
4240
conf := defaultConfig
@@ -46,29 +44,20 @@ func NewAutoRelay(bhost *basic.BasicHost, opts ...Option) (*AutoRelay, error) {
4644
}
4745
}
4846
r.ctx, r.ctxCancel = context.WithCancel(context.Background())
49-
r.conf = &conf
50-
r.relayFinder = newRelayFinder(bhost, conf.peerSource, &conf)
51-
r.metricsTracer = &wrappedMetricsTracer{conf.metricsTracer}
52-
53-
// Update the host address factory to use autorelay addresses if we're private
54-
//
55-
// TODO: Don't update host address factory. Instead send our relay addresses on the eventbus.
56-
// The host can decide how to handle those.
57-
addrF := bhost.AddrsFactory
58-
bhost.AddrsFactory = func(addrs []ma.Multiaddr) []ma.Multiaddr {
59-
addrs = addrF(addrs)
60-
r.mx.Lock()
61-
defer r.mx.Unlock()
62-
63-
if r.status != network.ReachabilityPrivate {
64-
return addrs
65-
}
66-
return r.relayFinder.relayAddrs(addrs)
47+
rf, err := newRelayFinder(host, &conf)
48+
if err != nil {
49+
return nil, fmt.Errorf("failed to create autorelay: %w", err)
6750
}
51+
r.relayFinder = rf
52+
r.metricsTracer = &wrappedMetricsTracer{conf.metricsTracer}
6853

6954
return r, nil
7055
}
7156

57+
func (r *AutoRelay) RelayAddrs() []ma.Multiaddr {
58+
return r.relayFinder.RelayAddrs()
59+
}
60+
7261
func (r *AutoRelay) Start() {
7362
r.refCount.Add(1)
7463
go func() {

p2p/host/autorelay/autorelay_test.go

+69-1
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package autorelay_test
33
import (
44
"context"
55
"fmt"
6+
"slices"
67
"strings"
78
"sync/atomic"
89
"testing"
910
"time"
1011

1112
"github.com/libp2p/go-libp2p"
13+
"github.com/libp2p/go-libp2p/core/event"
1214
"github.com/libp2p/go-libp2p/core/host"
1315
"github.com/libp2p/go-libp2p/core/network"
1416
"github.com/libp2p/go-libp2p/core/peer"
@@ -96,7 +98,10 @@ func newRelay(t *testing.T) host.Host {
9698
saddr := addr.String()
9799
if strings.HasPrefix(saddr, "/ip4/127.0.0.1/") {
98100
addrNoIP := strings.TrimPrefix(saddr, "/ip4/127.0.0.1")
99-
addrs[i] = ma.StringCast("/dns4/localhost" + addrNoIP)
101+
// .internal is classified as a public address as users
102+
// are free to map this dns to a public ip address for
103+
// use within a LAN
104+
addrs[i] = ma.StringCast("/dns/libp2p.internal" + addrNoIP)
100105
}
101106
}
102107
return addrs
@@ -517,3 +522,66 @@ func TestNoBusyLoop0MinInterval(t *testing.T) {
517522
val := atomic.LoadUint64(&calledTimes)
518523
require.Less(t, val, uint64(2))
519524
}
525+
func TestAutoRelayAddrsEvent(t *testing.T) {
526+
cl := newMockClock()
527+
r1, r2 := newRelay(t), newRelay(t)
528+
t.Cleanup(func() {
529+
r1.Close()
530+
r2.Close()
531+
})
532+
533+
relayFromP2PAddr := func(a ma.Multiaddr) peer.ID {
534+
r, c := ma.SplitLast(a)
535+
if c.Protocol().Code != ma.P_CIRCUIT {
536+
return ""
537+
}
538+
if id, err := peer.IDFromP2PAddr(r); err == nil {
539+
return id
540+
}
541+
return ""
542+
}
543+
544+
checkPeersExist := func(addrs []ma.Multiaddr, peers ...peer.ID) bool {
545+
for _, p := range peers {
546+
if !slices.ContainsFunc(addrs, func(a ma.Multiaddr) bool { return relayFromP2PAddr(a) == p }) {
547+
return false
548+
}
549+
}
550+
return true
551+
}
552+
peerChan := make(chan peer.AddrInfo, 3)
553+
h := newPrivateNode(t,
554+
func(context.Context, int) <-chan peer.AddrInfo {
555+
return peerChan
556+
},
557+
autorelay.WithClock(cl),
558+
autorelay.WithMinCandidates(1),
559+
autorelay.WithMaxCandidates(10),
560+
autorelay.WithNumRelays(3),
561+
autorelay.WithBootDelay(1*time.Second),
562+
autorelay.WithMinInterval(time.Hour),
563+
)
564+
defer h.Close()
565+
566+
sub, err := h.EventBus().Subscribe(new(event.EvtAutoRelayAddrs))
567+
require.NoError(t, err)
568+
569+
peerChan <- peer.AddrInfo{ID: r1.ID(), Addrs: r1.Addrs()}
570+
cl.AdvanceBy(time.Second)
571+
572+
require.Eventually(t, func() bool {
573+
e := <-sub.Out()
574+
if !checkPeersExist(e.(event.EvtAutoRelayAddrs).RelayAddrs, r1.ID()) {
575+
return false
576+
}
577+
if checkPeersExist(e.(event.EvtAutoRelayAddrs).RelayAddrs, r2.ID()) {
578+
return false
579+
}
580+
return true
581+
}, 5*time.Second, 50*time.Millisecond)
582+
peerChan <- peer.AddrInfo{ID: r2.ID(), Addrs: r2.Addrs()}
583+
require.Eventually(t, func() bool {
584+
e := <-sub.Out()
585+
return checkPeersExist(e.(event.EvtAutoRelayAddrs).RelayAddrs, r1.ID(), r2.ID())
586+
}, 5*time.Second, 50*time.Millisecond)
587+
}

p2p/host/autorelay/relay.go

-19
This file was deleted.

0 commit comments

Comments
 (0)