github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/connection_timer.go (about)

     1  package quic
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/metacubex/quic-go/internal/utils"
     7  )
     8  
     9  var deadlineSendImmediately = time.Time{}.Add(42 * time.Millisecond) // any value > time.Time{} and before time.Now() is fine
    10  
    11  type connectionTimer struct {
    12  	timer *utils.Timer
    13  	last  time.Time
    14  }
    15  
    16  func newTimer() *connectionTimer {
    17  	return &connectionTimer{timer: utils.NewTimer()}
    18  }
    19  
    20  func (t *connectionTimer) SetRead() {
    21  	if deadline := t.timer.Deadline(); deadline != deadlineSendImmediately {
    22  		t.last = deadline
    23  	}
    24  	t.timer.SetRead()
    25  }
    26  
    27  func (t *connectionTimer) Chan() <-chan time.Time {
    28  	return t.timer.Chan()
    29  }
    30  
    31  // SetTimer resets the timer.
    32  // It makes sure that the deadline is strictly increasing.
    33  // This prevents busy-looping in cases where the timer fires, but we can't actually send out a packet.
    34  // This doesn't apply to the pacing deadline, which can be set multiple times to deadlineSendImmediately.
    35  func (t *connectionTimer) SetTimer(idleTimeoutOrKeepAlive, ackAlarm, lossTime, pacing time.Time) {
    36  	deadline := idleTimeoutOrKeepAlive
    37  	if !ackAlarm.IsZero() && ackAlarm.Before(deadline) && ackAlarm.After(t.last) {
    38  		deadline = ackAlarm
    39  	}
    40  	if !lossTime.IsZero() && lossTime.Before(deadline) && lossTime.After(t.last) {
    41  		deadline = lossTime
    42  	}
    43  	if !pacing.IsZero() && pacing.Before(deadline) {
    44  		deadline = pacing
    45  	}
    46  	t.timer.Reset(deadline)
    47  }
    48  
    49  func (t *connectionTimer) Stop() {
    50  	t.timer.Stop()
    51  }