Skip to content

Commit

Permalink
fix: remove closing dialog server from hangup, do not override existi…
Browse files Browse the repository at this point in the history
…ng contact hdr
  • Loading branch information
emiago committed May 4, 2024
1 parent 8c8ae6b commit 9e65b9c
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 17 deletions.
2 changes: 1 addition & 1 deletion dialog.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

var (
ErrDialogOutsideDialog = errors.New("Call/Transaction outside dialog")
ErrDialogDoesNotExists = errors.New("Call/Transaction Does Not Exist")
ErrDialogDoesNotExists = errors.New("Dialog Does Not Exist")
ErrDialogInviteNoContact = errors.New("No Contact header")
ErrDialogCanceled = errors.New("Dialog canceled")
)
Expand Down
12 changes: 8 additions & 4 deletions dialog_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ func (s *DialogClient) matchDialogRequest(req *sip.Request) (*DialogClientSessio
}

// NewDialogClient provides handle for managing UAC dialog
// Contact hdr must be provided for correct invite
// Contact hdr is default to be provided for correct invite. It is not used if you provided hdr as part of request,
// but contact hdr must be present so this makes sure correct dialog is established.
// In case handling different transports you should have multiple instances per transport
func NewDialogClient(client *Client, contactHDR sip.ContactHeader) *DialogClient {
s := &DialogClient{
Expand All @@ -70,6 +71,7 @@ func (e ErrDialogResponse) Error() string {
}

// Invite sends INVITE request and creates early dialog session.
// This is actually not yet dialog (ID is empty)
// You need to call WaitAnswer after for establishing dialog
// For passing custom Invite request use WriteInvite
func (c *DialogClient) Invite(ctx context.Context, recipient sip.Uri, body []byte, headers ...sip.Header) (*DialogClientSession, error) {
Expand All @@ -87,9 +89,11 @@ func (c *DialogClient) Invite(ctx context.Context, recipient sip.Uri, body []byt
func (c *DialogClient) WriteInvite(ctx context.Context, inviteRequest *sip.Request) (*DialogClientSession, error) {
cli := c.c

inviteRequest.AppendHeader(&c.contactHDR)
if inviteRequest.Contact() == nil {
// Set contact only if not exists
inviteRequest.AppendHeader(&c.contactHDR)
}

// TODO passing client transaction options is now hidden
tx, err := cli.TransactionRequest(ctx, inviteRequest)
if err != nil {
return nil, err
Expand Down Expand Up @@ -407,7 +411,7 @@ func digestTransactionRequest(ctx context.Context, client *Client, req *sip.Requ

// newByeRequestUAC creates bye request from established dialog
// https://datatracker.ietf.org/doc/html/rfc3261#section-15.1.1
// NOTE: it does not copy Via header. This is left to transport or caller to enforce
// NOTE: it does not copy Via header neither increases CSEQ. This is left to dialog transaction request
func newByeRequestUAC(inviteRequest *sip.Request, inviteResponse *sip.Response, body []byte) *sip.Request {
recipient := &inviteRequest.Recipient
cont := inviteResponse.Contact()
Expand Down
8 changes: 4 additions & 4 deletions dialog_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func TestIntegrationDialogBrokenUAC(t *testing.T) {
defer cancel()

uasContact := sip.ContactHeader{
Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5099},
Address: sip.Uri{User: "test", Host: "127.0.0.201", Port: 5099},
}

dialogSrv := NewDialogServer(cli, uasContact)
Expand Down Expand Up @@ -207,7 +207,7 @@ func TestIntegrationDialogBrokenUAC(t *testing.T) {
cli, _ := NewClient(ua)

contactHDR := sip.ContactHeader{
Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088},
Address: sip.Uri{User: "test", Host: "127.0.0.201", Port: 5088},
}
dialogCli := NewDialogClient(cli, contactHDR)

Expand All @@ -227,7 +227,7 @@ func TestIntegrationDialogBrokenUAC(t *testing.T) {
tx.Respond(sip.NewResponseFromRequest(req, sip.StatusInternalServerError, "", nil))
})
// INVITE
t.Log("UAC: INVITE")
t.Log("UAC: INVITE ", uasContact.Address.String())
sess, err := dialogCli.Invite(context.TODO(), uasContact.Address, nil)
require.NoError(t, err)
defer sess.Close()
Expand All @@ -249,7 +249,7 @@ func TestIntegrationDialogBrokenUAC(t *testing.T) {

t.Run("UAS ACK Error", func(t *testing.T) {
// INVITE
t.Log("UAC: INVITE")
t.Log("UAC: INVITE ", uasContact.Address.String())
sess, err := dialogCli.Invite(context.TODO(), uasContact.Address, nil)
require.NoError(t, err)
defer sess.Close()
Expand Down
15 changes: 7 additions & 8 deletions dialog_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (s *DialogServer) matchDialogRequest(req *sip.Request) (*DialogServerSessio
}

// NewDialogServer provides handle for managing UAS dialog
// Contact hdr must be provided for responses
// Contact hdr is default that is provided for responses.
// Client is needed for termination dialog session
// In case handling different transports you should have multiple instances per transport
func NewDialogServer(client *Client, contactHDR sip.ContactHeader) *DialogServer {
Expand Down Expand Up @@ -89,7 +89,7 @@ func (s *DialogServer) ReadInvite(req *sip.Request, tx sip.ServerTransaction) (*
inviteTx: tx,
s: s,
}

s.dialogs.Store(id, dtx)
return dtx, nil
}

Expand Down Expand Up @@ -247,8 +247,11 @@ func (s *DialogServerSession) RespondSDP(sdp []byte) error {
func (s *DialogServerSession) WriteResponse(res *sip.Response) error {
tx := s.inviteTx

// Must add contact header
res.AppendHeader(&s.s.contactHDR)
if res.Contact() == nil {
// Add our default contact header
res.AppendHeader(&s.s.contactHDR)
}

s.Dialog.InviteResponse = res

// Do we have cancel in meantime
Expand Down Expand Up @@ -285,10 +288,7 @@ func (s *DialogServerSession) WriteResponse(res *sip.Response) error {
return fmt.Errorf("ID do not match. Invite request has changed headers?")
}

// We need to make dialog present as ACK can land immediately after
s.s.dialogs.Store(id, s)
s.setState(sip.DialogStateEstablished)

if err := tx.Respond(res); err != nil {
// We could also not delete this as Close will handle cleanup
s.s.dialogs.Delete(id)
Expand Down Expand Up @@ -317,7 +317,6 @@ func (s *DialogServerSession) Bye(ctx context.Context) error {
}

// This is tricky
defer s.Close() // Delete our dialog always
defer s.inviteTx.Terminate() // Terminates INVITE in all cases

// https://datatracker.ietf.org/doc/html/rfc3261#section-15
Expand Down

0 comments on commit 9e65b9c

Please sign in to comment.