connection_timer.go 1.4 KB

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