diff --git a/p2p/net/swarm/swarm_dial.go b/p2p/net/swarm/swarm_dial.go index 446ece4504..7456b7f42d 100644 --- a/p2p/net/swarm/swarm_dial.go +++ b/p2p/net/swarm/swarm_dial.go @@ -22,9 +22,17 @@ import ( ) // The maximum number of address resolution steps we'll perform for a single -// peer (for all addresses). +// peer (for all addresses). In other words, the maximum number of times we'll +// call `.Resolve` for all of a peer's addresses const maxAddressResolution = 32 +// The maximum number of addresses we'll return when resolving all of a peer's +// address +const maximumResolvedAddresses = 100 + +// The maximum queue size of addresses left to resolve. +const maximumToResolveAddresses = 100 + // Diagram of dial sync: // // many callers of Dial() synched w. dials many addrs results to callers @@ -337,7 +345,7 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia // * Otherwise, resolve it and add the results to the "to resolve" list. toResolve := append([]ma.Multiaddr{}, pi.Addrs...) resolved := make([]ma.Multiaddr, 0, len(pi.Addrs)) - for len(toResolve) > 0 { + for len(toResolve) > 0 && len(resolved) < maximumResolvedAddresses { // pop the last addr off. addr := toResolve[len(toResolve)-1] toResolve = toResolve[:len(toResolve)-1] @@ -372,6 +380,9 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia } var added bool for _, a := range resolvedAddrs { + if len(toResolve) >= maximumToResolveAddresses { + break + } if !addr.Equal(a) { toResolve = append(toResolve, a) added = true @@ -382,6 +393,11 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia } } + if len(toResolve) >= maximumToResolveAddresses { + // No point in resolving any more addresses, we don't have space. + continue + } + // otherwise, resolve it reqaddr := addr.Encapsulate(p2paddr) resaddrs, err := s.maResolver.Resolve(ctx, reqaddr) @@ -391,6 +407,9 @@ func (s *Swarm) resolveAddrs(ctx context.Context, pi peer.AddrInfo) ([]ma.Multia // add the results to the toResolve list. for _, res := range resaddrs { + if len(toResolve) >= maximumToResolveAddresses { + break + } pi, err := peer.AddrInfoFromP2pAddr(res) if err != nil { log.Infof("error parsing %s: %s", res, err) diff --git a/p2p/net/swarm/swarm_dial_test.go b/p2p/net/swarm/swarm_dial_test.go index f4c33170a9..09989b6ee9 100644 --- a/p2p/net/swarm/swarm_dial_test.go +++ b/p2p/net/swarm/swarm_dial_test.go @@ -398,3 +398,18 @@ func TestBlackHoledAddrBlocked(t *testing.T) { } require.ErrorIs(t, err, ErrDialRefusedBlackHole) } + +func TestSkipDialingManyDNS(t *testing.T) { + resolver, err := madns.NewResolver() + if err != nil { + t.Fatal(err) + } + s := newTestSwarmWithResolver(t, resolver) + defer s.Close() + id := test.RandPeerIDFatal(t) + addr := ma.StringCast("/dns/example.com/udp/1234/p2p-circuit/dns/example.com/p2p-circuit/dns/example.com") + + resolved, err := s.resolveAddrs(context.Background(), peer.AddrInfo{ID: id, Addrs: []ma.Multiaddr{addr}}) + require.NoError(t, err) + require.Less(t, len(resolved), maximumResolvedAddresses) +}