forked from emiago/diago
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dialog_client_session.go
111 lines (89 loc) · 2.58 KB
/
dialog_client_session.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// SPDX-License-Identifier: MPL-2.0
// SPDX-FileCopyrightText: Copyright (c) 2024, Emir Aganovic
package diago
import (
"context"
"sync/atomic"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
)
// DialogClientSession represents outbound channel
type DialogClientSession struct {
*sipgo.DialogClientSession
DialogMedia
// lastInvite is actual last invite sent by remote REINVITE
// We do not use sipgo as this needs mutex but also keeping original invite
lastInvite *sip.Request
closed atomic.Uint32
}
func (d *DialogClientSession) Close() {
if !d.closed.CompareAndSwap(0, 1) {
return
}
d.DialogMedia.Close()
d.DialogClientSession.Close()
}
func (d *DialogClientSession) Id() string {
return d.ID
}
func (d *DialogClientSession) Hangup(ctx context.Context) error {
return d.Bye(ctx)
}
func (d *DialogClientSession) FromUser() string {
return d.InviteRequest.From().Address.User
}
func (d *DialogClientSession) ToUser() string {
return d.InviteRequest.To().Address.User
}
func (d *DialogClientSession) DialogSIP() *sipgo.Dialog {
return &d.Dialog
}
func (d *DialogClientSession) RemoteContact() *sip.ContactHeader {
d.mu.Lock()
defer d.mu.Unlock()
return d.remoteContactUnsafe()
}
func (d *DialogClientSession) remoteContactUnsafe() *sip.ContactHeader {
if d.lastInvite != nil {
// Invite update can change contact
return d.lastInvite.Contact()
}
return d.InviteResponse.Contact()
}
// ReInvite sends new invite based on current media session
func (d *DialogClientSession) ReInvite(ctx context.Context) error {
d.mu.Lock()
sdp := d.mediaSession.LocalSDP()
contact := d.remoteContactUnsafe()
d.mu.Unlock()
req := sip.NewRequest(sip.INVITE, contact.Address)
req.AppendHeader(d.InviteRequest.Contact())
req.SetBody(sdp)
res, err := d.Do(ctx, req)
if err != nil {
return err
}
if !res.IsSuccess() {
return sipgo.ErrDialogResponse{
Res: res,
}
}
return nil
}
func (d *DialogClientSession) handleReInvite(req *sip.Request, tx sip.ServerTransaction) {
if err := d.ReadRequest(req, tx); err != nil {
tx.Respond(sip.NewResponseFromRequest(req, sip.StatusBadRequest, err.Error(), nil))
return
}
d.mu.Lock()
defer d.mu.Unlock()
d.lastInvite = req
if err := d.sdpReInviteUnsafe(req.Body()); err != nil {
tx.Respond(sip.NewResponseFromRequest(req, sip.StatusRequestTerminated, err.Error(), nil))
return
}
tx.Respond(sip.NewResponseFromRequest(req, sip.StatusOK, "OK", nil))
}
func (d *DialogClientSession) readSIPInfoDTMF(req *sip.Request, tx sip.ServerTransaction) {
tx.Respond(sip.NewResponseFromRequest(req, sip.StatusNotAcceptable, "Not Acceptable", nil))
}