Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions p2p/host/basic/addrs_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ func (a *addrsManager) applyAddrsFactory(addrs []ma.Multiaddr) []ma.Multiaddr {
addrs = append(addrs[:0], af...)
// Add certhashes for the addresses provided by the user via address factory.
addrs = a.addCertHashes(ma.Unique(addrs))
slices.SortFunc(addrs, func(a, b ma.Multiaddr) int { return a.Compare(b) })
slices.SortFunc(addrs, ma.Multiaddr.Compare)
return addrs
}

Expand Down Expand Up @@ -514,6 +514,12 @@ func (a *addrsManager) ConfirmedAddrs() (reachable []ma.Multiaddr, unreachable [

func (a *addrsManager) getConfirmedAddrs(localAddrs []ma.Multiaddr) (reachableAddrs, unreachableAddrs, unknownAddrs []ma.Multiaddr) {
reachableAddrs, unreachableAddrs, unknownAddrs = a.addrsReachabilityTracker.ConfirmedAddrs()
// Don't rely on tracker's ordering. removeNotInSource here and removeInSource in
// getDialableAddrs require sorted input; unsorted input silently drops
// confirmed addrs.
slices.SortFunc(reachableAddrs, ma.Multiaddr.Compare)
slices.SortFunc(unreachableAddrs, ma.Multiaddr.Compare)
slices.SortFunc(unknownAddrs, ma.Multiaddr.Compare)
return removeNotInSource(reachableAddrs, localAddrs), removeNotInSource(unreachableAddrs, localAddrs), removeNotInSource(unknownAddrs, localAddrs)
}

Expand Down Expand Up @@ -551,7 +557,7 @@ func (a *addrsManager) getLocalAddrs() []ma.Multiaddr {
// using identify.
finalAddrs = a.addCertHashes(finalAddrs)
finalAddrs = ma.Unique(finalAddrs)
slices.SortFunc(finalAddrs, func(a, b ma.Multiaddr) int { return a.Compare(b) })
slices.SortFunc(finalAddrs, ma.Multiaddr.Compare)
return finalAddrs
}

Expand Down Expand Up @@ -691,8 +697,8 @@ func areAddrsDifferent(prev, current []ma.Multiaddr) bool {
if len(prev) != len(current) {
return true
}
slices.SortFunc(prev, func(a, b ma.Multiaddr) int { return a.Compare(b) })
slices.SortFunc(current, func(a, b ma.Multiaddr) int { return a.Compare(b) })
slices.SortFunc(prev, ma.Multiaddr.Compare)
slices.SortFunc(current, ma.Multiaddr.Compare)
for i := range prev {
if !prev[i].Equal(current[i]) {
return true
Expand Down
47 changes: 47 additions & 0 deletions p2p/host/basic/addrs_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,53 @@ func TestAddrsManagerReachabilityEvent(t *testing.T) {
}
}

func TestAddrsManagerConfirmedAddrsIncludesSecondaryTransports(t *testing.T) {
// A node listening on every transport kubo enables by default, on two UDP
// sockets: one reachable, one not. Each UDP bucket interleaves under
// Multiaddr.Compare (webrtc-direct sorts before its quic-v1 primary), and
// getConfirmedAddrs and Addrs merge the buckets with helpers that
// silently drop entries on unsorted input: removeNotInSource must keep
// all confirmed addrs in both the reachable and unreachable buckets, and
// removeInSource must remove every confirmed-unreachable addr from Addrs.
tcp := ma.StringCast("/ip4/1.2.3.4/tcp/4001")
wsSNI := ma.StringCast("/ip4/1.2.3.4/tcp/4001/tls/sni/*.example.net/ws")
quicPub := ma.StringCast("/ip4/1.2.3.4/udp/4002/quic-v1")
webrtcPub := ma.StringCast("/ip4/1.2.3.4/udp/4002/webrtc-direct")
wtPub := ma.StringCast("/ip4/1.2.3.4/udp/4002/quic-v1/webtransport")
quicPriv := ma.StringCast("/ip4/1.2.3.4/udp/4001/quic-v1")
webrtcPriv := ma.StringCast("/ip4/1.2.3.4/udp/4001/webrtc-direct")
wtPriv := ma.StringCast("/ip4/1.2.3.4/udp/4001/quic-v1/webtransport")
reachableAddrs := []ma.Multiaddr{tcp, wsSNI, quicPub, webrtcPub, wtPub}
unreachableAddrs := []ma.Multiaddr{quicPriv, webrtcPriv, wtPriv}
listenAddrs := append(slices.Clone(reachableAddrs), unreachableAddrs...)

// The UDP socket on port 4001 is unreachable, everything else is reachable.
am := newAddrsManagerTestCase(t, addrsManagerArgs{
ListenAddrs: func() []ma.Multiaddr { return listenAddrs },
AutoNATClient: mockAutoNATClient{
F: func(_ context.Context, reqs []autonatv2.Request) (autonatv2.Result, error) {
rch := network.ReachabilityPublic
if port, err := reqs[0].Addr.ValueForProtocol(ma.P_UDP); err == nil && port == "4001" {
rch = network.ReachabilityPrivate
}
return autonatv2.Result{Addr: reqs[0].Addr, Idx: 0, Reachability: rch}, nil
},
},
})
defer am.Close()

require.Eventually(t, func() bool {
reachable, unreachable, _ := am.ConfirmedAddrs()
return len(reachable) == len(reachableAddrs) && len(unreachable) == len(unreachableAddrs)
}, 5*time.Second, 50*time.Millisecond, "expected all listen addrs to be confirmed")

reachable, unreachable, unknown := am.ConfirmedAddrs()
matest.AssertMultiaddrsMatch(t, reachableAddrs, reachable)
matest.AssertMultiaddrsMatch(t, unreachableAddrs, unreachable)
require.Empty(t, unknown)
matest.AssertMultiaddrsMatch(t, reachableAddrs, am.Addrs())
}

func TestAddrsManagerPeerstoreUpdated(t *testing.T) {
quic1 := ma.StringCast("/ip4/1.2.3.4/udp/1234/quic-v1")
quic2 := ma.StringCast("/ip4/1.2.3.5/udp/1/quic-v1")
Expand Down
2 changes: 1 addition & 1 deletion p2p/host/basic/addrs_reachability_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func (m *probeManager) UpdateAddrs(addrs []ma.Multiaddr) {
m.mx.Lock()
defer m.mx.Unlock()

slices.SortFunc(addrs, func(a, b ma.Multiaddr) int { return a.Compare(b) })
slices.SortFunc(addrs, ma.Multiaddr.Compare)
statuses := make(map[string]*addrStatus, len(addrs))
for _, addr := range addrs {
k := string(addr.Bytes())
Expand Down
Loading