p2p/discover: add iterList

This commit is contained in:
Felix Lange 2026-04-27 16:20:53 +02:00
parent 8def19181a
commit cbeee83116
2 changed files with 19 additions and 13 deletions

View file

@ -17,9 +17,11 @@
package discover package discover
import ( import (
"container/list"
"crypto/ecdsa" "crypto/ecdsa"
crand "crypto/rand" crand "crypto/rand"
"encoding/binary" "encoding/binary"
"iter"
"math/rand" "math/rand"
"net" "net"
"net/netip" "net/netip"
@ -143,3 +145,16 @@ func (r *reseedingRandom) Shuffle(n int, swap func(i, j int)) {
defer r.mu.Unlock() defer r.mu.Unlock()
r.cur.Shuffle(n, swap) r.cur.Shuffle(n, swap)
} }
// iterList iterates over the elements of the given list.
func iterList[T any](l *list.List) iter.Seq2[T, *list.Element] {
return func(yield func(T, *list.Element) bool) {
for el := l.Front(); el != nil; {
next := el.Next()
if !yield(el.Value.(T), el) {
return
}
el = next
}
}
}

View file

@ -446,10 +446,8 @@ func (t *UDPv4) loop() {
} }
// Start the timer so it fires when the next pending reply has expired. // Start the timer so it fires when the next pending reply has expired.
now := time.Now() now := time.Now()
for el := plist.Front(); el != nil; { for p, el := range iterList[*replyMatcher](plist) {
next := el.Next() if dist := p.deadline.Sub(now); dist < 2*respTimeout {
nextTimeout = el.Value.(*replyMatcher)
if dist := nextTimeout.deadline.Sub(now); dist < 2*respTimeout {
timeout.Reset(dist) timeout.Reset(dist)
return return
} }
@ -458,7 +456,6 @@ func (t *UDPv4) loop() {
// backwards after the deadline was assigned. // backwards after the deadline was assigned.
nextTimeout.errc <- errClockWarp nextTimeout.errc <- errClockWarp
plist.Remove(el) plist.Remove(el)
el = next
} }
nextTimeout = nil nextTimeout = nil
timeout.Stop() timeout.Stop()
@ -480,9 +477,7 @@ func (t *UDPv4) loop() {
case r := <-t.gotreply: case r := <-t.gotreply:
var matched bool // whether any replyMatcher considered the reply acceptable. var matched bool // whether any replyMatcher considered the reply acceptable.
for el := plist.Front(); el != nil; { for p, el := range iterList[*replyMatcher](plist) {
next := el.Next()
p := el.Value.(*replyMatcher)
if p.from == r.from && p.ptype == r.data.Kind() && p.ip == r.ip { if p.from == r.from && p.ptype == r.data.Kind() && p.ip == r.ip {
ok, requestDone := p.callback(r.data) ok, requestDone := p.callback(r.data)
matched = matched || ok matched = matched || ok
@ -495,7 +490,6 @@ func (t *UDPv4) loop() {
// Reset the continuous timeout counter (time drift detection) // Reset the continuous timeout counter (time drift detection)
contTimeouts = 0 contTimeouts = 0
} }
el = next
} }
r.matched <- matched r.matched <- matched
@ -503,15 +497,12 @@ func (t *UDPv4) loop() {
nextTimeout = nil nextTimeout = nil
// Notify and remove callbacks whose deadline is in the past. // Notify and remove callbacks whose deadline is in the past.
for el := plist.Front(); el != nil; { for p, el := range iterList[*replyMatcher](plist) {
next := el.Next()
p := el.Value.(*replyMatcher)
if now.After(p.deadline) || now.Equal(p.deadline) { if now.After(p.deadline) || now.Equal(p.deadline) {
p.errc <- errTimeout p.errc <- errTimeout
plist.Remove(el) plist.Remove(el)
contTimeouts++ contTimeouts++
} }
el = next
} }
// If we've accumulated too many timeouts, do an NTP time sync check // If we've accumulated too many timeouts, do an NTP time sync check
if contTimeouts > ntpFailureThreshold { if contTimeouts > ntpFailureThreshold {