// SPDX-FileCopyrightText: 2023 The Pion community // SPDX-License-Identifier: MIT package sctp import ( "math" "sync" "time" ) const ( ackInterval time.Duration = 200 * time.Millisecond ) // ackTimerObserver is the inteface to an ack timer observer. type ackTimerObserver interface { onAckTimeout() } type ackTimerState uint8 const ( ackTimerStopped ackTimerState = iota ackTimerStarted ackTimerClosed ) // ackTimer provides the retnransmission timer conforms with RFC 4960 Sec 6.3.1 type ackTimer struct { timer *time.Timer observer ackTimerObserver mutex sync.Mutex state ackTimerState pending uint8 } // newAckTimer creates a new acknowledgement timer used to enable delayed ack. func newAckTimer(observer ackTimerObserver) *ackTimer { t := &ackTimer{observer: observer} t.timer = time.AfterFunc(math.MaxInt64, t.timeout) t.timer.Stop() return t } func (t *ackTimer) timeout() { t.mutex.Lock() if t.pending--; t.pending == 0 && t.state == ackTimerStarted { t.state = ackTimerStopped defer t.observer.onAckTimeout() } t.mutex.Unlock() } // start starts the timer. func (t *ackTimer) start() bool { t.mutex.Lock() defer t.mutex.Unlock() // this timer is already closed or already running if t.state != ackTimerStopped { return false } t.state = ackTimerStarted t.pending++ t.timer.Reset(ackInterval) return true } // stops the timer. this is similar to stop() but subsequent start() call // will fail (the timer is no longer usable) func (t *ackTimer) stop() { t.mutex.Lock() defer t.mutex.Unlock() if t.state == ackTimerStarted { if t.timer.Stop() { t.pending-- } t.state = ackTimerStopped } } // closes the timer. this is similar to stop() but subsequent start() call // will fail (the timer is no longer usable) func (t *ackTimer) close() { t.mutex.Lock() defer t.mutex.Unlock() if t.state == ackTimerStarted && t.timer.Stop() { t.pending-- } t.state = ackTimerClosed } // isRunning tests if the timer is running. // Debug purpose only func (t *ackTimer) isRunning() bool { t.mutex.Lock() defer t.mutex.Unlock() return t.state == ackTimerStarted }