forked from emiago/sipgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdialog_ua.go
93 lines (81 loc) · 2.28 KB
/
dialog_ua.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package sipgo
import (
"context"
"fmt"
"sync/atomic"
"github.com/emiago/sipgo/sip"
uuid "github.com/satori/go.uuid"
)
// DialogUA defines UserAgent that will be used in controling your dialog.
type DialogUA struct {
Client *Client
ContactHDR sip.ContactHeader
}
func (c *DialogUA) ReadInvite(inviteReq *sip.Request, tx sip.ServerTransaction) (*DialogServerSession, error) {
cont := inviteReq.Contact()
if cont == nil {
return nil, ErrDialogInviteNoContact
}
// Prebuild already to tag for response as it must be same for all responds
// NewResponseFromRequest will skip this for all 100
uuid, err := uuid.NewV4()
if err != nil {
return nil, fmt.Errorf("generating dialog to tag failed: %w", err)
}
inviteReq.To().Params["tag"] = uuid.String()
id, err := sip.UASReadRequestDialogID(inviteReq)
if err != nil {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
dtx := &DialogServerSession{
Dialog: Dialog{
ID: id, // this id has already prebuilt tag
InviteRequest: inviteReq,
lastCSeqNo: inviteReq.CSeq().SeqNo,
state: atomic.Int32{},
stateCh: make(chan sip.DialogState, 3),
ctx: ctx,
cancel: cancel,
},
inviteTx: tx,
ua: c,
}
return dtx, nil
}
func (ua *DialogUA) Invite(ctx context.Context, recipient sip.Uri, body []byte, headers ...sip.Header) (*DialogClientSession, error) {
req := sip.NewRequest(sip.INVITE, recipient)
if body != nil {
req.SetBody(body)
}
for _, h := range headers {
req.AppendHeader(h)
}
return ua.WriteInvite(ctx, req)
}
func (c *DialogUA) WriteInvite(ctx context.Context, inviteRequest *sip.Request) (*DialogClientSession, error) {
cli := c.Client
if inviteRequest.Contact() == nil {
// Set contact only if not exists
inviteRequest.AppendHeader(&c.ContactHDR)
}
tx, err := cli.TransactionRequest(ctx, inviteRequest)
if err != nil {
return nil, err
}
ctx, cancel := context.WithCancel(context.Background())
dtx := &DialogClientSession{
Dialog: Dialog{
InviteRequest: inviteRequest,
lastCSeqNo: inviteRequest.CSeq().SeqNo,
state: atomic.Int32{},
stateCh: make(chan sip.DialogState, 3),
ctx: ctx,
cancel: cancel,
},
// dc: c,
ua: c,
inviteTx: tx,
}
return dtx, nil
}