Skip to content

Commit 43ec894

Browse files
committed
Update ack_timer to RFC 9260
1 parent a69c6a2 commit 43ec894

File tree

1 file changed

+36
-12
lines changed

1 file changed

+36
-12
lines changed

ack_timer.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import (
1010
)
1111

1212
const (
13+
// Default SACK delay per RFC 9260 (protocol parameter 'SACK.Delay').
1314
ackInterval time.Duration = 200 * time.Millisecond
15+
// Implementations MUST NOT allow SACK.Delay > 500ms (RFC 9260).
16+
ackMaxDelay time.Duration = 500 * time.Millisecond
1417
)
1518

16-
// ackTimerObserver is the inteface to an ack timer observer.
19+
// ackTimerObserver is the interface to an ack timer observer.
1720
type ackTimerObserver interface {
1821
onAckTimeout()
1922
}
@@ -26,18 +29,27 @@ const (
2629
ackTimerClosed
2730
)
2831

29-
// ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1.
32+
// ackTimer provides the SACK.Delay according to RFC 9260 section 6.2.
3033
type ackTimer struct {
3134
timer *time.Timer
3235
observer ackTimerObserver
33-
mutex sync.Mutex
34-
state ackTimerState
35-
pending uint8
36+
37+
mutex sync.Mutex
38+
state ackTimerState
39+
pending uint8
40+
41+
// Configurable SACK delay clamped to (0, ackMaxDelay].
42+
interval time.Duration
3643
}
3744

3845
// newAckTimer creates a new acknowledgement timer used to enable delayed ack.
46+
// Default delay is 200ms (SACK.Delay). The maximum allowed by spec is 500ms.
3947
func newAckTimer(observer ackTimerObserver) *ackTimer {
40-
t := &ackTimer{observer: observer}
48+
t := &ackTimer{
49+
observer: observer,
50+
interval: ackInterval,
51+
}
52+
4153
t.timer = time.AfterFunc(math.MaxInt64, t.timeout)
4254
t.timer.Stop()
4355

@@ -53,7 +65,7 @@ func (t *ackTimer) timeout() {
5365
t.mutex.Unlock()
5466
}
5567

56-
// start starts the timer.
68+
// start starts the timer if not already running. Returns true if it started.
5769
func (t *ackTimer) start() bool {
5870
t.mutex.Lock()
5971
defer t.mutex.Unlock()
@@ -65,20 +77,30 @@ func (t *ackTimer) start() bool {
6577

6678
t.state = ackTimerStarted
6779
t.pending++
68-
t.timer.Reset(ackInterval)
80+
81+
// Clamp interval (0, ackMaxDelay].
82+
delay := t.interval
83+
if delay <= 0 {
84+
delay = ackInterval
85+
} else if delay > ackMaxDelay {
86+
delay = ackMaxDelay
87+
}
88+
89+
t.timer.Reset(delay)
6990

7091
return true
7192
}
7293

73-
// stops the timer. this is similar to stop() but subsequent start() call
74-
// will fail (the timer is no longer usable).
94+
// stop stops the timer if running and keeps it reusable.
7595
func (t *ackTimer) stop() {
7696
t.mutex.Lock()
7797
defer t.mutex.Unlock()
7898

7999
if t.state == ackTimerStarted {
80100
if t.timer.Stop() {
81-
t.pending--
101+
if t.pending > 0 {
102+
t.pending--
103+
}
82104
}
83105
t.state = ackTimerStopped
84106
}
@@ -91,7 +113,9 @@ func (t *ackTimer) close() {
91113
defer t.mutex.Unlock()
92114

93115
if t.state == ackTimerStarted && t.timer.Stop() {
94-
t.pending--
116+
if t.pending > 0 {
117+
t.pending--
118+
}
95119
}
96120
t.state = ackTimerClosed
97121
}

0 commit comments

Comments
 (0)