From c2c5918483796d477a05c03bfcc09c81dc88b30c Mon Sep 17 00:00:00 2001 From: Will Scott Date: Fri, 26 Feb 2021 23:21:36 -0800 Subject: [PATCH] fix autonat race fix #7947 move `BasicHost.AutoNat` to a private field (it has no public method and shouldn't be accessed afaik. Instead add a setter for config that sets it while holding the address mutex to prevent reads of the field at the same time. --- config/config.go | 4 +++- p2p/host/basic/basic_host.go | 16 +++++++++++++--- p2p/host/basic/basic_host_test.go | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/config/config.go b/config/config.go index 0871e584f4..f2377ac682 100644 --- a/config/config.go +++ b/config/config.go @@ -335,10 +335,12 @@ func (cfg *Config) NewNode(ctx context.Context) (host.Host, error) { autonatOpts = append(autonatOpts, autonat.WithReachability(*cfg.AutoNATConfig.ForceReachability)) } - if h.AutoNat, err = autonat.New(ctx, h, autonatOpts...); err != nil { + autonat, err := autonat.New(ctx, h, autonatOpts...) + if err != nil { h.Close() return nil, fmt.Errorf("cannot enable autorelay; autonat failed to start: %v", err) } + h.SetAutoNat(autonat) // start the host background tasks h.Start() diff --git a/p2p/host/basic/basic_host.go b/p2p/host/basic/basic_host.go index de5b7dfe43..1e5fa9ed0c 100644 --- a/p2p/host/basic/basic_host.go +++ b/p2p/host/basic/basic_host.go @@ -112,7 +112,7 @@ type BasicHost struct { signKey crypto.PrivKey caBook peerstore.CertifiedAddrBook - AutoNat autonat.AutoNAT + autoNat autonat.AutoNAT } var _ host.Host = (*BasicHost)(nil) @@ -811,6 +811,7 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr { h.addrMu.RLock() filteredIfaceAddrs := h.filteredInterfaceAddrs allIfaceAddrs := h.allInterfaceAddrs + autonat := h.autoNat h.addrMu.RUnlock() // Iterate over all _unresolved_ listen addresses, resolving our primary @@ -831,8 +832,8 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr { // but not have an external network card, // so net.InterfaceAddrs() not has the public ip // The host can indeed be dialed !!! - if h.AutoNat != nil { - publicAddr, _ := h.AutoNat.PublicAddr() + if autonat != nil { + publicAddr, _ := autonat.PublicAddr() if publicAddr != nil { finalAddrs = append(finalAddrs, publicAddr) } @@ -992,6 +993,15 @@ func (h *BasicHost) AllAddrs() []ma.Multiaddr { return dedupAddrs(finalAddrs) } +// SetAutoNat sets the autonat service for the host. +func (h *BasicHost) SetAutoNat(a autonat.AutoNAT) { + h.addrMu.Lock() + defer h.addrMu.Unlock() + if h.autoNat == nil { + h.autoNat = a + } +} + // Close shuts down the Host's services (network, etc). func (h *BasicHost) Close() error { h.closeSync.Do(func() { diff --git a/p2p/host/basic/basic_host_test.go b/p2p/host/basic/basic_host_test.go index 3585b01b65..950e93fcf5 100644 --- a/p2p/host/basic/basic_host_test.go +++ b/p2p/host/basic/basic_host_test.go @@ -203,7 +203,7 @@ func TestHostAddrsFactory(t *testing.T) { } var err error - h.AutoNat, err = autonat.New(ctx, h, autonat.WithReachability(network.ReachabilityPublic)) + h.autoNat, err = autonat.New(ctx, h, autonat.WithReachability(network.ReachabilityPublic)) if err != nil { t.Fatalf("should be able to attach autonat: %v", err) }