ack_timer.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
  2. // SPDX-License-Identifier: MIT
  3. package sctp
  4. import (
  5. "sync"
  6. "time"
  7. )
  8. const (
  9. ackInterval time.Duration = 200 * time.Millisecond
  10. )
  11. // ackTimerObserver is the inteface to an ack timer observer.
  12. type ackTimerObserver interface {
  13. onAckTimeout()
  14. }
  15. // ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1
  16. type ackTimer struct {
  17. observer ackTimerObserver
  18. interval time.Duration
  19. stopFunc stopAckTimerLoop
  20. closed bool
  21. mutex sync.RWMutex
  22. }
  23. type stopAckTimerLoop func()
  24. // newAckTimer creates a new acknowledgement timer used to enable delayed ack.
  25. func newAckTimer(observer ackTimerObserver) *ackTimer {
  26. return &ackTimer{
  27. observer: observer,
  28. interval: ackInterval,
  29. }
  30. }
  31. // start starts the timer.
  32. func (t *ackTimer) start() bool {
  33. t.mutex.Lock()
  34. defer t.mutex.Unlock()
  35. // this timer is already closed
  36. if t.closed {
  37. return false
  38. }
  39. // this is a noop if the timer is already running
  40. if t.stopFunc != nil {
  41. return false
  42. }
  43. cancelCh := make(chan struct{})
  44. go func() {
  45. timer := time.NewTimer(t.interval)
  46. select {
  47. case <-timer.C:
  48. t.stop()
  49. t.observer.onAckTimeout()
  50. case <-cancelCh:
  51. timer.Stop()
  52. }
  53. }()
  54. t.stopFunc = func() {
  55. close(cancelCh)
  56. }
  57. return true
  58. }
  59. // stops the timer. this is similar to stop() but subsequent start() call
  60. // will fail (the timer is no longer usable)
  61. func (t *ackTimer) stop() {
  62. t.mutex.Lock()
  63. defer t.mutex.Unlock()
  64. if t.stopFunc != nil {
  65. t.stopFunc()
  66. t.stopFunc = nil
  67. }
  68. }
  69. // closes the timer. this is similar to stop() but subsequent start() call
  70. // will fail (the timer is no longer usable)
  71. func (t *ackTimer) close() {
  72. t.mutex.Lock()
  73. defer t.mutex.Unlock()
  74. if t.stopFunc != nil {
  75. t.stopFunc()
  76. t.stopFunc = nil
  77. }
  78. t.closed = true
  79. }
  80. // isRunning tests if the timer is running.
  81. // Debug purpose only
  82. func (t *ackTimer) isRunning() bool {
  83. t.mutex.RLock()
  84. defer t.mutex.RUnlock()
  85. return (t.stopFunc != nil)
  86. }