diff --git a/config/config.go b/config/config.go index c503509465..58a34cb1ee 100644 --- a/config/config.go +++ b/config/config.go @@ -66,6 +66,8 @@ type Config struct { DisablePing bool Routing RoutingC + + EnableAutoRelay bool } // NewNode constructs a new libp2p Host from the Config. @@ -166,34 +168,51 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { return nil, err } + // Configure routing and autorelay + var router routing.PeerRouting if cfg.Routing != nil { - router, err := cfg.Routing(h) + router, err = cfg.Routing(h) if err != nil { h.Close() return nil, err } + } + + if cfg.EnableAutoRelay { + if !cfg.Relay { + h.Close() + return nil, fmt.Errorf("cannot enable autorelay; relay is not enabled") + } + + if router == nil { + h.Close() + return nil, fmt.Errorf("cannot enable autorelay; no routing for discovery") + } crouter, ok := router.(routing.ContentRouting) - if ok { - if cfg.Relay { - discovery := discovery.NewRoutingDiscovery(crouter) - - hop := false - for _, opt := range cfg.RelayOpts { - if opt == circuit.OptHop { - hop = true - break - } - } - - if hop { - h = relay.NewRelayHost(swrm.Context(), h.(*bhost.BasicHost), discovery) - } else { - h = relay.NewAutoRelayHost(swrm.Context(), h.(*bhost.BasicHost), discovery) - } + if !ok { + h.Close() + return nil, fmt.Errorf("cannot enable autorelay; no suitable routing for discovery") + } + + discovery := discovery.NewRoutingDiscovery(crouter) + + hop := false + for _, opt := range cfg.RelayOpts { + if opt == circuit.OptHop { + hop = true + break } } + if hop { + h = relay.NewRelayHost(swrm.Context(), h.(*bhost.BasicHost), discovery) + } else { + h = relay.NewAutoRelayHost(swrm.Context(), h.(*bhost.BasicHost), discovery) + } + } + + if router != nil { h = routed.Wrap(h, router) } diff --git a/options.go b/options.go index 0015c80818..125ec8d601 100644 --- a/options.go +++ b/options.go @@ -220,6 +220,15 @@ func DisableRelay() Option { } } +// EnableAutoRelay configures libp2p to enable autorelay advertising; requires relay to +// be enabled and the Routing option to provide an instance of ContentRouting. +func EnableAutoRelay() Option { + return func(cfg *Config) error { + cfg.EnableAutoRelay = true + return nil + } +} + // FilterAddresses configures libp2p to never dial nor accept connections from // the given addresses. func FilterAddresses(addrs ...*net.IPNet) Option { diff --git a/p2p/host/relay/autorelay_test.go b/p2p/host/relay/autorelay_test.go index ce50ea8c09..82a0f8ac6f 100644 --- a/p2p/host/relay/autorelay_test.go +++ b/p2p/host/relay/autorelay_test.go @@ -142,11 +142,11 @@ func TestAutoRelay(t *testing.T) { } h1 := makeAutoNATServicePrivate(ctx, t) - _, err := libp2p.New(ctx, libp2p.EnableRelay(circuit.OptHop), libp2p.Routing(makeRouting)) + _, err := libp2p.New(ctx, libp2p.EnableRelay(circuit.OptHop), libp2p.EnableAutoRelay(), libp2p.Routing(makeRouting)) if err != nil { t.Fatal(err) } - h3, err := libp2p.New(ctx, libp2p.EnableRelay(), libp2p.Routing(makeRouting)) + h3, err := libp2p.New(ctx, libp2p.EnableRelay(), libp2p.EnableAutoRelay(), libp2p.Routing(makeRouting)) if err != nil { t.Fatal(err) }