From 42c013f2af7962f7c3ecdd400d01874cb48b5036 Mon Sep 17 00:00:00 2001 From: cuiweixie Date: Thu, 11 Jun 2026 20:00:00 +0800 Subject: [PATCH] p2p/nat: return exactly n random STUN servers on every call randomServers drew indices with rand.Intn into a dedup map, bounded by len(serverList)*2 iterations. When n approaches the number of configured servers, repeated random collisions can exhaust the iteration budget before n unique servers are collected, so the function sometimes returns fewer servers than requested even though enough exist. For example, with 2 configured servers and requestLimit==3 (capped to 2), the four allowed draws can collide and yield only a single server. If that server is down, ExternalIP fails without ever trying the other. Replace the sampling loop with rand.Perm, which produces a uniform permutation of all indices in one pass. Slicing the first n entries always yields exactly min(n, len(serverList)) distinct servers, with no probabilistic shortfall. --- p2p/nat/stun.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/p2p/nat/stun.go b/p2p/nat/stun.go index 60c2b920a0..4dca3f61bb 100644 --- a/p2p/nat/stun.go +++ b/p2p/nat/stun.go @@ -91,15 +91,9 @@ func (s *stun) ExternalIP() (net.IP, error) { func (s *stun) randomServers(n int) []string { n = min(n, len(s.serverList)) - m := make(map[int]struct{}, n) list := make([]string, 0, n) - for i := 0; i < len(s.serverList)*2 && len(list) < n; i++ { - index := rand.Intn(len(s.serverList)) - if _, alreadyHit := m[index]; alreadyHit { - continue - } + for _, index := range rand.Perm(len(s.serverList))[:n] { list = append(list, s.serverList[index]) - m[index] = struct{}{} } return list }