Skip to content

Commit c640c72

Browse files
authored
Merge pull request #123 from lightninglabs/fix-gbn-transport-timeouts
gbn+mailbox: fix transport timeouts, add dynamic pong, harden with rapid tests
2 parents edf0788 + 9f9577b commit c640c72

11 files changed

Lines changed: 1996 additions & 30 deletions

gbn/config.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,28 @@ func WithBoostPercent(boostPercent float32) TimeoutOptions {
7878
}
7979
}
8080

81+
// WithDynamicPongTimeout enables dynamic pong timeout based on observed RTT.
82+
// When enabled, the pong timeout is computed as max(basePongTime,
83+
// pongMultiplier * smoothedRTT), capped at maxPongTime and never allowed to
84+
// exceed the local ping interval. This is useful for relay-based transports
85+
// where the round-trip time through the relay can vary significantly based on
86+
// network conditions.
87+
func WithDynamicPongTimeout(pongMultiplier int,
88+
maxPongTime time.Duration) TimeoutOptions {
89+
90+
return func(manager *TimeoutManager) {
91+
manager.dynamicPongTime = true
92+
93+
if pongMultiplier > 0 {
94+
manager.pongMultiplier = pongMultiplier
95+
}
96+
97+
if maxPongTime > 0 {
98+
manager.maxPongTime = maxPongTime
99+
}
100+
}
101+
}
102+
81103
// config holds the configuration values for an instance of GoBackNConn.
82104
type config struct {
83105
// n is the window size. The sender can send a maximum of n packets

gbn/gbn_conn.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -411,21 +411,22 @@ func (g *GoBackNConn) sendPacketsForever() error {
411411
continue
412412

413413
case <-g.pingTicker.Ticks():
414-
// If we have expected a sync after sending the previous
415-
// ping, both the pingTicker and pongTicker may have
416-
// ticked when waiting to sync. In that case, we can't
417-
// be sure which of the signals we receive over first in
418-
// the above select. We therefore need to check if the
419-
// pong ticker has ticked here to ensure that it get's
420-
// prioritized over the ping ticker.
414+
// The pong timeout is capped at the ping interval, so
415+
// if we're still waiting for a response to the previous
416+
// ping then both tickers may fire at roughly the same
417+
// time. In that case the keepalive timeout must win
418+
// over sending a new ping.
421419
select {
422420
case <-g.pongTicker.Ticks():
423421
return errKeepaliveTimeout
424422
default:
425423
}
426424

427-
// Start the pong timer.
428-
g.pongTicker.Reset()
425+
// Start the pong timer. We use ResetWithInterval
426+
// to pick up any dynamic pong timeout changes
427+
// based on observed RTT.
428+
pongTime := g.timeoutManager.GetPongTime()
429+
g.pongTicker.ResetWithInterval(pongTime)
429430
g.pongTicker.Resume()
430431

431432
// Also reset the ping timer.

0 commit comments

Comments
 (0)