[client] Drop stale WG timeouts via the watcher context instead of a generation counter

Tag each WG timeout event with the watcher's context and discard it at
dispatch time when that context is cancelled. This replaces the earlier
generation counter and the mailbox-level epoch filter: cancelling the
watcher is now the single act that both stops it and retires its pending
timeouts, so the two can no longer diverge, and the staleness check moves
to dispatch time so a cancel performed by an earlier event in the same
drained batch already suppresses a superseded watcher's timeout.
This commit is contained in:
Zoltán Papp
2026-08-05 16:14:11 +02:00
parent 47df3c3ef0
commit 28d3a478b8
3 changed files with 47 additions and 24 deletions
+13 -1
View File
@@ -1,6 +1,7 @@
package peer
import (
"context"
"time"
"github.com/pion/ice/v4"
@@ -15,6 +16,15 @@ import (
// never mutate Conn state directly.
type event any
// staleableEvent is implemented by events tied to the lifetime of a transport
// component (WG watcher, ICE agent, relay connection). Each such component runs
// under its own context, cancelled when the component is superseded; an event
// carrying a cancelled context is dropped at dispatch time. A cancel performed
// by an earlier event in the same drained batch already suppresses it.
type staleableEvent interface {
isStale() bool
}
// evClose asks the event loop to tear down the connection. done is closed
// once the teardown finished.
type evClose struct {
@@ -55,9 +65,11 @@ type evRelayDown struct{}
type evRelayDialDone struct{}
type evWGTimeout struct {
gen uint64
ctx context.Context
}
func (e evWGTimeout) isStale() bool { return e.ctx.Err() != nil }
// evWGHandshake reports the first WireGuard handshake of the current watcher run.
type evWGHandshake struct {
when time.Time