Skip to content

Commit 5432489

Browse files
committed
feat: dialog support setting contact header based on client connection #211
1 parent 3632e69 commit 5432489

File tree

4 files changed

+47
-30
lines changed

4 files changed

+47
-30
lines changed

client.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,16 @@ func (c *Client) TransactionRequest(ctx context.Context, req *sip.Request, optio
147147

148148
if len(options) == 0 {
149149
clientRequestBuildReq(c, req)
150-
return c.requestTransaction(ctx, req)
150+
} else {
151+
for _, o := range options {
152+
if err := o(c, req); err != nil {
153+
return nil, err
154+
}
155+
}
151156
}
152157

153-
for _, o := range options {
154-
if err := o(c, req); err != nil {
155-
return nil, err
156-
}
158+
if c.TxRequester != nil {
159+
return c.TxRequester.Request(ctx, req)
157160
}
158161

159162
// Do some request validation, but only place as warning
@@ -164,17 +167,20 @@ func (c *Client) TransactionRequest(ctx context.Context, req *sip.Request, optio
164167
c.log.Warn("Missing Content-Length for reliable transport")
165168
}
166169

167-
return c.requestTransaction(ctx, req)
170+
return c.tx.Request(ctx, req)
168171
}
169172

170-
func (c *Client) requestTransaction(ctx context.Context, req *sip.Request) (sip.ClientTransaction, error) {
171-
if c.TxRequester != nil {
172-
return c.TxRequester.Request(ctx, req)
173+
func (c *Client) newTransaction(ctx context.Context, req *sip.Request, onConnection func(conn sip.Connection) error, options ...ClientRequestOption) (sip.ClientTransaction, error) {
174+
if len(options) == 0 {
175+
clientRequestBuildReq(c, req)
176+
} else {
177+
for _, o := range options {
178+
if err := o(c, req); err != nil {
179+
return nil, err
180+
}
181+
}
173182
}
174-
return c.tx.Request(ctx, req)
175-
}
176183

177-
func (c *Client) newTransaction(ctx context.Context, req *sip.Request, onConnection func(conn sip.Connection) error) (sip.ClientTransaction, error) {
178184
if c.TxRequester != nil {
179185
return c.TxRequester.Request(ctx, req)
180186
}

dialog_client.go

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,12 @@ func (s *DialogClientSession) Do(ctx context.Context, req *sip.Request) (*sip.Re
8585
}
8686
}
8787

88-
// TransactionRequest is doing client DIALOG request based on RFC
88+
// TransactionRequest is doing subsequent client DIALOG request based on RFC after initial session (INVITE) setup
8989
// https://www.rfc-editor.org/rfc/rfc3261#section-12.2.1
9090
// This ensures that you have proper request done within dialog. You should avoid setting any Dialog header (cseq, from, to, callid)
9191
func (s *DialogClientSession) TransactionRequest(ctx context.Context, req *sip.Request) (sip.ClientTransaction, error) {
9292
s.buildReq(req)
9393

94-
// Overrides contact header with local connection addr
95-
if cont := req.Contact(); cont.Address.Host == "" {
96-
tx, err := s.UA.Client.newTransaction(ctx, req, func(conn sip.Connection) error {
97-
var err error
98-
cont.Address.Host, cont.Address.Port, err = sip.ParseAddr(conn.LocalAddr().String())
99-
return err
100-
})
101-
return tx, err
102-
}
103-
10494
// Passing option to avoid CSEQ apply
10595
return s.UA.Client.TransactionRequest(ctx, req, s.requestValidate)
10696
}

dialog_integration_test.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,10 @@ func TestIntegrationDialog(t *testing.T) {
125125
defer ua.Close()
126126

127127
srv, _ := NewServer(ua)
128-
cli, _ := NewClient(ua)
128+
cli, _ := NewClient(ua, WithClientConnectionAddr("127.0.0.200:0"))
129129

130-
contactHDR := sip.ContactHeader{
131-
Address: sip.Uri{User: "test", Host: "127.0.0.200", Port: 5088},
132-
}
130+
// Use for now empheral contact based on client connection
131+
contactHDR := sip.ContactHeader{}
133132
dialogCli := NewDialogClientCache(cli, contactHDR)
134133

135134
// Setup server side
@@ -141,8 +140,7 @@ func TestIntegrationDialog(t *testing.T) {
141140
t.Log("UAC server: ", r.StartLine())
142141
})
143142

144-
startTestServer(ctx, srv, contactHDR.Address.HostPort())
145-
t.Run("UAS hangup", func(t *testing.T) {
143+
t.Run("UAShangup", func(t *testing.T) {
146144
// INVITE
147145
t.Log("UAC: INVITE")
148146
sess, err := dialogCli.Invite(context.TODO(), uasContact.Address, nil)

dialog_ua.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,30 @@ func (d *DialogClientSession) Invite(ctx context.Context, options ...ClientReque
123123
inviteReq := d.InviteRequest
124124

125125
var err error
126-
d.inviteTx, err = cli.TransactionRequest(ctx, inviteReq, options...)
126+
d.inviteTx, err = func() (sip.ClientTransaction, error) {
127+
// Try overriding contact header with via or local connection host port
128+
if cont := inviteReq.Contact(); cont.Address.Port == 0 {
129+
return cli.newTransaction(ctx, inviteReq, func(conn sip.Connection) error {
130+
// Using via instead connection to avoid double parsing
131+
// host, port, err = sip.ParseAddr(conn.LocalAddr().String())
132+
via := inviteReq.Via()
133+
if cont.Address.Host == "" {
134+
cont.Address.Host = via.Host
135+
cont.Address.Port = via.Port
136+
return nil
137+
}
138+
139+
// In case host is FQDN we will not override
140+
if via.Host == cont.Address.Host {
141+
cont.Address.Port = via.Port
142+
}
143+
return nil
144+
}, options...)
145+
}
146+
147+
return cli.TransactionRequest(ctx, inviteReq, options...)
148+
}()
149+
127150
if err == nil {
128151
d.lastCSeqNo.Store(inviteReq.CSeq().SeqNo)
129152
}

0 commit comments

Comments
 (0)