derp: simplify DERP map handling

This commit is contained in:
Kristoffer Dalby
2026-06-16 07:04:42 +00:00
parent c3cfbf1cc0
commit 19d5d9deeb
2 changed files with 15 additions and 38 deletions
+9 -22
View File
@@ -85,16 +85,12 @@ func mergeDERPMaps(derpMaps []*tailcfg.DERPMap) *tailcfg.DERPMap {
for _, derpMap := range derpMaps { for _, derpMap := range derpMaps {
// Clone each region: copying the pointer would let a later in-place // Clone each region: copying the pointer would let a later in-place
// shuffle (shuffleRegionNoClone) alias regions shared with the source // shuffle alias regions shared with the source map or a previously
// map or a previously served map, racing concurrent readers. // served map, racing concurrent readers.
for id, region := range derpMap.Regions { for id, region := range derpMap.Regions {
result.Regions[id] = region.Clone() if cloned := region.Clone(); cloned != nil {
} result.Regions[id] = cloned
} }
for id, region := range result.Regions {
if region == nil {
delete(result.Regions, id)
} }
} }
@@ -152,14 +148,13 @@ func shuffleDERPMap(dm *tailcfg.DERPMap) {
continue continue
} }
dm.Regions[id] = shuffleRegionNoClone(region) derpRandom().Shuffle(len(region.Nodes), reflect.Swapper(region.Nodes))
} }
} }
var crc64Table = crc64.MakeTable(crc64.ISO) var crc64Table = crc64.MakeTable(crc64.ISO)
var ( var (
derpRandomOnce sync.Once
derpRandomInst *rand.Rand derpRandomInst *rand.Rand
derpRandomMu sync.Mutex derpRandomMu sync.Mutex
) )
@@ -168,12 +163,10 @@ func derpRandom() *rand.Rand {
derpRandomMu.Lock() derpRandomMu.Lock()
defer derpRandomMu.Unlock() defer derpRandomMu.Unlock()
derpRandomOnce.Do(func() { if derpRandomInst == nil {
seed := cmp.Or(viper.GetString("dns.base_domain"), time.Now().String()) seed := cmp.Or(viper.GetString("dns.base_domain"), time.Now().String())
rnd := rand.New(rand.NewSource(0)) //nolint:gosec // weak random is fine for DERP scrambling derpRandomInst = rand.New(rand.NewSource(int64(crc64.Checksum([]byte(seed), crc64Table)))) //nolint:gosec // weak random is fine for DERP scrambling
rnd.Seed(int64(crc64.Checksum([]byte(seed), crc64Table))) //nolint:gosec // safe conversion }
derpRandomInst = rnd
})
return derpRandomInst return derpRandomInst
} }
@@ -182,11 +175,5 @@ func resetDerpRandomForTesting() {
derpRandomMu.Lock() derpRandomMu.Lock()
defer derpRandomMu.Unlock() defer derpRandomMu.Unlock()
derpRandomOnce = sync.Once{}
derpRandomInst = nil derpRandomInst = nil
} }
func shuffleRegionNoClone(r *tailcfg.DERPRegion) *tailcfg.DERPRegion {
derpRandom().Shuffle(len(r.Nodes), reflect.Swapper(r.Nodes))
return r
}
+6 -16
View File
@@ -76,20 +76,15 @@ func (d *DERPServer) GenerateRegion() (tailcfg.DERPRegion, error) {
return tailcfg.DERPRegion{}, err return tailcfg.DERPRegion{}, err
} }
var (
host string
port int
portStr string
)
// Extract hostname and port from URL // Extract hostname and port from URL
host, portStr, err = net.SplitHostPort(serverURL.Host) host, portStr, err := net.SplitHostPort(serverURL.Host)
var port int
if err != nil { if err != nil {
host = serverURL.Host
if serverURL.Scheme == "https" { if serverURL.Scheme == "https" {
host = serverURL.Host
port = 443 port = 443
} else { } else {
host = serverURL.Host
port = 80 port = 80
} }
} else { } else {
@@ -371,15 +366,10 @@ func (d *DERPServer) ServeSTUN() {
} }
func serverSTUNListener(ctx context.Context, packetConn *net.UDPConn) { func serverSTUNListener(ctx context.Context, packetConn *net.UDPConn) {
var ( var buf [64 << 10]byte
buf [64 << 10]byte
bytesRead int
udpAddr *net.UDPAddr
err error
)
for { for {
bytesRead, udpAddr, err = packetConn.ReadFromUDP(buf[:]) bytesRead, udpAddr, err := packetConn.ReadFromUDP(buf[:])
if err != nil { if err != nil {
if ctx.Err() != nil { if ctx.Err() != nil {
return return