Skip to content

Commit 736700e

Browse files
authored
ensure request timeout is longer than ringingTimeout (#940)
avoids a footgun where request is canceled before dialing attempt is over
1 parent a9f711e commit 736700e

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

failover.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ const (
4848
// sipDialTimeout is the longer default for calls that dial a phone
4949
// (CreateSIPParticipant with WaitUntilAnswered, TransferSIPParticipant).
5050
sipDialTimeout = 30 * time.Second
51+
// ringingTimeoutMargin keeps a dialing request's deadline above the request's
52+
// ringing timeout, so it doesn't abort before the call can be answered.
53+
ringingTimeoutMargin = 2 * time.Second
5154
)
5255

5356
// perAttemptTimeoutKey carries the caller's original timeout budget once its

sipclient.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,31 @@ package lksdk
1616

1717
import (
1818
"context"
19+
"time"
1920

2021
"github.com/twitchtv/twirp"
22+
"google.golang.org/protobuf/types/known/durationpb"
2123
"google.golang.org/protobuf/types/known/emptypb"
2224

2325
"github.com/livekit/protocol/livekit"
2426
"github.com/livekit/protocol/utils/xtwirp"
2527
"github.com/livekit/server-sdk-go/v2/signalling"
2628
)
2729

30+
// sipDialDeadline returns the default deadline for a phone-dialing call: the
31+
// longer SIP dial timeout, raised to stay at least ringingTimeoutMargin above
32+
// the request's ringing timeout so the request doesn't abort before the call
33+
// can be answered.
34+
func sipDialDeadline(ringingTimeout *durationpb.Duration) time.Duration {
35+
timeout := sipDialTimeout
36+
if ringingTimeout != nil {
37+
if d := ringingTimeout.AsDuration() + ringingTimeoutMargin; d > timeout {
38+
timeout = d
39+
}
40+
}
41+
return timeout
42+
}
43+
2844
//lint:file-ignore SA1019 We still support some deprecated functions for backward compatibility
2945

3046
type SIPClient struct {
@@ -279,7 +295,7 @@ func (s *SIPClient) CreateSIPParticipant(ctx context.Context, in *livekit.Create
279295
// detaches it for failover). Set it before auth so failover sees the budget.
280296
if _, ok := ctx.Deadline(); !ok && in.WaitUntilAnswered {
281297
var cancel func()
282-
ctx, cancel = context.WithTimeout(ctx, sipDialTimeout)
298+
ctx, cancel = context.WithTimeout(ctx, sipDialDeadline(in.GetRingingTimeout()))
283299
defer cancel()
284300
}
285301

@@ -300,7 +316,7 @@ func (s *SIPClient) TransferSIPParticipant(ctx context.Context, in *livekit.Tran
300316
// default deadline (before prepareContext, which detaches it for failover).
301317
if _, ok := ctx.Deadline(); !ok {
302318
var cancel func()
303-
ctx, cancel = context.WithTimeout(ctx, sipDialTimeout)
319+
ctx, cancel = context.WithTimeout(ctx, sipDialDeadline(in.GetRingingTimeout()))
304320
defer cancel()
305321
}
306322

0 commit comments

Comments
 (0)