Skip to content

Commit

Permalink
fix: wait answer cancelation blocked forever on waiting 487
Browse files Browse the repository at this point in the history
  • Loading branch information
emiago committed Oct 6, 2024
1 parent 1915f34 commit 97b7abd
Showing 1 changed file with 18 additions and 2 deletions.
20 changes: 18 additions & 2 deletions dialog_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"sync"
"time"

"github.com/emiago/sipgo/sip"
"github.com/icholy/digest"
Expand Down Expand Up @@ -174,6 +175,10 @@ type AnswerOptions struct {
Password string
}

var (
WaitAnswerForceCancelErr = errors.New("Context cancel forced")
)

// WaitAnswer waits for success response or returns ErrDialogResponse in case non 2xx
// Canceling context while waiting 2xx will send Cancel request. It will block until 1xx provisional is not received
// If Canceling succesfull context.Canceled error is returned
Expand All @@ -182,7 +187,6 @@ type AnswerOptions struct {
// - any internal in case waiting answer failed for different reasons
func (s *DialogClientSession) WaitAnswer(ctx context.Context, opts AnswerOptions) error {
tx, inviteRequest := s.inviteTx, s.InviteRequest

var r *sip.Response
var err error
for {
Expand All @@ -197,6 +201,11 @@ func (s *DialogClientSession) WaitAnswer(ctx context.Context, opts AnswerOptions
// We will wait until transaction timeous out (TimerB)
defer tx.Terminate()

if err := context.Cause(ctx); err == WaitAnswerForceCancelErr {
// In case caller wants to force cancelation exit.
return ctx.Err()
}

if s.InviteResponse == nil {
select {
case r = <-tx.Responses():
Expand All @@ -219,7 +228,12 @@ func (s *DialogClientSession) WaitAnswer(ctx context.Context, opts AnswerOptions
return fmt.Errorf("cancel failed with non 200. code=%d", res.StatusCode)
}

// Wait for 487 or just timeout per TimerB (tx.Done)
// Wait for 487 or just timeout
// https://datatracker.ietf.org/doc/html/rfc3261#section-9.1
// UAC canceling a request cannot rely on receiving a 487 (Request
// Terminated) response for the original request, as an RFC 2543-
// compliant UAS will not generate such a response. If there is no
// final response for the original request in 64*T1 seconds
loop_487:
for {
select {
Expand All @@ -231,6 +245,8 @@ func (s *DialogClientSession) WaitAnswer(ctx context.Context, opts AnswerOptions
break loop_487
case <-tx.Done():
return tx.Err()
case <-time.After(64 * sip.T1):
break loop_487
}
}

Expand Down

0 comments on commit 97b7abd

Please sign in to comment.