Skip to content

Commit 485002a

Browse files
authored
Make media timeout more robust. (#351)
1 parent 9c21182 commit 485002a

File tree

1 file changed

+43
-7
lines changed

1 file changed

+43
-7
lines changed

pkg/sip/media_port.go

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ func NewMediaPortWith(log logger.Logger, mon *stats.CallMonitor, conn UDPConn, o
125125
mon: mon,
126126
externalIP: opts.IP,
127127
mediaTimeout: mediaTimeout,
128+
timeoutReset: make(chan struct{}, 1),
128129
jitterEnabled: opts.EnableJitterBuffer,
129130
port: newUDPConn(conn),
130131
audioOut: media.NewSwitchWriter(sampleRate),
@@ -148,6 +149,7 @@ type MediaPort struct {
148149
packetCount atomic.Uint64
149150
mediaTimeout <-chan struct{}
150151
timeoutStart atomic.Pointer[time.Time]
152+
timeoutReset chan struct{}
151153
closed core.Fuse
152154
dtmfAudioEnabled bool
153155
jitterEnabled bool
@@ -179,32 +181,66 @@ func (p *MediaPort) EnableTimeout(enabled bool) {
179181
p.timeoutStart.Store(nil)
180182
return
181183
}
184+
select {
185+
case p.timeoutReset <- struct{}{}:
186+
default:
187+
}
182188
now := time.Now()
183189
p.timeoutStart.Store(&now)
190+
p.log.Infow("media timeout enabled",
191+
"packets", p.packetCount.Load(),
192+
)
184193
}
185194

186195
func (p *MediaPort) timeoutLoop(timeoutCallback func()) {
187-
ticker := time.NewTicker(p.opts.MediaTimeout)
196+
tickInterval := p.opts.MediaTimeout
197+
ticker := time.NewTicker(tickInterval)
188198
defer ticker.Stop()
189199

190-
var lastPackets uint64
200+
var (
201+
lastPackets uint64
202+
startPackets uint64
203+
lastTime time.Time
204+
)
191205
for {
192206
select {
193207
case <-p.closed.Watch():
194208
return
209+
case <-p.timeoutReset:
210+
ticker.Reset(tickInterval)
211+
startPackets = p.packetCount.Load()
212+
lastTime = time.Now()
195213
case <-ticker.C:
196214
curPackets := p.packetCount.Load()
197215
if curPackets != lastPackets {
198216
lastPackets = curPackets
199-
continue
217+
lastTime = time.Now()
218+
continue // wait for the next tick
200219
}
201-
start := p.timeoutStart.Load()
202-
if start == nil {
203-
continue // temporary disabled
220+
startPtr := p.timeoutStart.Load()
221+
if startPtr == nil {
222+
continue // timeout disabled
204223
}
205-
if lastPackets == 0 && time.Since(*start) < p.opts.MediaTimeoutInitial {
224+
225+
// First timeout is allowed to be longer. Skip ticks if it's too early.
226+
sinceStart := time.Since(*startPtr)
227+
if lastPackets == startPackets && sinceStart < p.opts.MediaTimeoutInitial {
206228
continue
207229
}
230+
231+
// Ticker is allowed to fire earlier than the full timeout interval. Skip if it's not a full timeout yet.
232+
sinceLast := time.Since(lastTime)
233+
if sinceLast < p.opts.MediaTimeout {
234+
continue
235+
}
236+
p.log.Infow("triggering media timeout",
237+
"packets", lastPackets,
238+
"startPackets", startPackets,
239+
"sinceStart", sinceStart,
240+
"sinceLast", sinceLast,
241+
"initial", p.opts.MediaTimeoutInitial,
242+
"timeout", p.opts.MediaTimeout,
243+
)
208244
timeoutCallback()
209245
return
210246
}

0 commit comments

Comments
 (0)