drachtio-srf 4.5.1 → 4.5.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dialog.js +1 -0
- package/lib/sip-parser/message.js +6 -1
- package/lib/srf.js +12 -2
- package/package.json +1 -1
- package/test/docker-compose-testbed.yaml +11 -0
- package/test/scenarios/uas-reinvite-with-auth.xml +213 -0
- package/test/uac.js +26 -0
- package/test/unit-tests/parser.js +10 -0
package/lib/dialog.js
CHANGED
|
@@ -86,7 +86,12 @@ class SipMessage {
|
|
|
86
86
|
|
|
87
87
|
getParsedHeader(hdr) {
|
|
88
88
|
const name = parser.getHeaderName(hdr) ;
|
|
89
|
-
const v = this.headers[name]
|
|
89
|
+
const v = this.headers[name];
|
|
90
|
+
|
|
91
|
+
if (!v) {
|
|
92
|
+
throw new Error('header not available');
|
|
93
|
+
}
|
|
94
|
+
|
|
90
95
|
const fn = parser.getParser(hdr.toLowerCase()) ;
|
|
91
96
|
return fn({s:v, i:0}) ;
|
|
92
97
|
}
|
package/lib/srf.js
CHANGED
|
@@ -25,6 +25,8 @@ DialogState.Cancelled = 'cancelled';
|
|
|
25
25
|
DialogDirection.Initiator = 'initiator';
|
|
26
26
|
DialogDirection.Recipient = 'recipient';
|
|
27
27
|
|
|
28
|
+
const sleepFor = async(ms) => await new Promise((resolve) => setTimeout(resolve, ms));
|
|
29
|
+
|
|
28
30
|
const noncopyableHdrs = ['via', 'from', 'to', 'call-id', 'cseq', 'contact', 'content-length', 'content-type'];
|
|
29
31
|
function copyAllHeaders(msg, obj) {
|
|
30
32
|
if (msg) Object.keys(msg.headers).forEach((h) => {
|
|
@@ -819,7 +821,7 @@ class Srf extends Emitter {
|
|
|
819
821
|
if (!(opts.headers.to || opts.headers.To) && !opts.calledNumber) { opts.calledNumber = req.calledNumber; }
|
|
820
822
|
|
|
821
823
|
opts.localSdp = opts.localSdpB && typeof opts.localSdpB !== 'function' ? opts.localSdpB : req.body ;
|
|
822
|
-
const is3pcc = !opts.localSdp;
|
|
824
|
+
const is3pcc = !opts.localSdp || opts.noAck;
|
|
823
825
|
if (is3pcc) opts.noAck = true;
|
|
824
826
|
|
|
825
827
|
let remoteSdpB, translatedRemoteSdpB ;
|
|
@@ -835,7 +837,15 @@ class Srf extends Emitter {
|
|
|
835
837
|
|
|
836
838
|
if (remoteSdpB && remoteSdpB === sdpB) {
|
|
837
839
|
// called again with same remote SDP, return previous result
|
|
838
|
-
return translatedRemoteSdpB
|
|
840
|
+
if (translatedRemoteSdpB) return translatedRemoteSdpB;
|
|
841
|
+
|
|
842
|
+
/* race condition: we are still producing the translatedSdp from 183 */
|
|
843
|
+
await sleepFor(100);
|
|
844
|
+
if (translatedRemoteSdpB) return translatedRemoteSdpB;
|
|
845
|
+
await sleepFor(500);
|
|
846
|
+
if (translatedRemoteSdpB) return translatedRemoteSdpB;
|
|
847
|
+
await sleepFor(1000);
|
|
848
|
+
return translatedRemoteSdpB;
|
|
839
849
|
}
|
|
840
850
|
|
|
841
851
|
remoteSdpB = sdpB ;
|
package/package.json
CHANGED
|
@@ -161,3 +161,14 @@ services:
|
|
|
161
161
|
networks:
|
|
162
162
|
testbed:
|
|
163
163
|
ipv4_address: 172.29.0.24
|
|
164
|
+
|
|
165
|
+
sipp-uas-reinvite-with-auth:
|
|
166
|
+
image: drachtio/sipp:latest
|
|
167
|
+
command: sipp -sf /tmp/uas-reinvite-with-auth.xml
|
|
168
|
+
container_name: sipp-uas-reinvite-with-auth
|
|
169
|
+
volumes:
|
|
170
|
+
- ./scenarios:/tmp
|
|
171
|
+
tty: true
|
|
172
|
+
networks:
|
|
173
|
+
testbed:
|
|
174
|
+
ipv4_address: 172.29.0.25
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
|
2
|
+
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
|
3
|
+
|
|
4
|
+
<scenario name="Basic UAS responder">
|
|
5
|
+
<recv request="INVITE" crlf="true">
|
|
6
|
+
<action>
|
|
7
|
+
<ereg regexp="<sip:(.*)>" search_in="hdr" header="Contact:" assign_to="3"/>
|
|
8
|
+
<log message="Contact hostport is [$3]"/>
|
|
9
|
+
</action>
|
|
10
|
+
|
|
11
|
+
</recv>
|
|
12
|
+
|
|
13
|
+
<send>
|
|
14
|
+
<![CDATA[
|
|
15
|
+
|
|
16
|
+
SIP/2.0 100 Trying
|
|
17
|
+
[last_Via:]
|
|
18
|
+
[last_From:]
|
|
19
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
20
|
+
[last_Call-ID:]
|
|
21
|
+
[last_CSeq:]
|
|
22
|
+
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
|
23
|
+
Content-Length: 0
|
|
24
|
+
|
|
25
|
+
]]>
|
|
26
|
+
</send>
|
|
27
|
+
|
|
28
|
+
<send retrans="500">
|
|
29
|
+
<![CDATA[
|
|
30
|
+
|
|
31
|
+
SIP/2.0 407 Proxy Authentication Required
|
|
32
|
+
[last_Via:]
|
|
33
|
+
[last_From:]
|
|
34
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
35
|
+
[last_Call-ID:]
|
|
36
|
+
[last_CSeq:]
|
|
37
|
+
Proxy-Authenticate: Digest realm="local", nonce="4cdbb733645816512687270b83d2ae5d11e4d9d8"
|
|
38
|
+
Content-Length: 0
|
|
39
|
+
|
|
40
|
+
]]>
|
|
41
|
+
</send>
|
|
42
|
+
|
|
43
|
+
<recv request="ACK"
|
|
44
|
+
rtd="true"
|
|
45
|
+
crlf="true">
|
|
46
|
+
<action>
|
|
47
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
48
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
49
|
+
</action>
|
|
50
|
+
</recv>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
<recv request="INVITE" crlf="true">
|
|
54
|
+
<action>
|
|
55
|
+
<ereg regexp="<sip:(.*)>" search_in="hdr" header="Contact:" assign_to="3"/>
|
|
56
|
+
<log message="Contact hostport is [$3]"/>
|
|
57
|
+
</action>
|
|
58
|
+
|
|
59
|
+
</recv>
|
|
60
|
+
|
|
61
|
+
<send>
|
|
62
|
+
<![CDATA[
|
|
63
|
+
|
|
64
|
+
SIP/2.0 100 Trying
|
|
65
|
+
[last_Via:]
|
|
66
|
+
[last_From:]
|
|
67
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
68
|
+
[last_Call-ID:]
|
|
69
|
+
[last_CSeq:]
|
|
70
|
+
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
|
71
|
+
Content-Length: 0
|
|
72
|
+
|
|
73
|
+
]]>
|
|
74
|
+
</send>
|
|
75
|
+
|
|
76
|
+
<send retrans="500">
|
|
77
|
+
<![CDATA[
|
|
78
|
+
|
|
79
|
+
SIP/2.0 200 OK
|
|
80
|
+
[last_Via:]
|
|
81
|
+
[last_From:]
|
|
82
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
83
|
+
[last_Call-ID:]
|
|
84
|
+
[last_CSeq:]
|
|
85
|
+
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
|
86
|
+
Content-Type: application/sdp
|
|
87
|
+
Content-Length: [len]
|
|
88
|
+
|
|
89
|
+
v=0
|
|
90
|
+
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
|
|
91
|
+
s=-
|
|
92
|
+
c=IN IP[media_ip_type] [media_ip]
|
|
93
|
+
t=0 0
|
|
94
|
+
m=audio [media_port] RTP/AVP 0
|
|
95
|
+
a=rtpmap:0 PCMU/8000
|
|
96
|
+
|
|
97
|
+
]]>
|
|
98
|
+
</send>
|
|
99
|
+
|
|
100
|
+
<recv request="ACK"
|
|
101
|
+
rtd="true"
|
|
102
|
+
crlf="true">
|
|
103
|
+
<action>
|
|
104
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
105
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
106
|
+
</action>
|
|
107
|
+
</recv>
|
|
108
|
+
|
|
109
|
+
<recv request="INVITE" crlf="true">
|
|
110
|
+
<action>
|
|
111
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
112
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
113
|
+
</action>
|
|
114
|
+
</recv>
|
|
115
|
+
|
|
116
|
+
<send retrans="500">
|
|
117
|
+
<![CDATA[
|
|
118
|
+
|
|
119
|
+
SIP/2.0 407 Proxy Authentication Required
|
|
120
|
+
[last_Via:]
|
|
121
|
+
[last_From:]
|
|
122
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
123
|
+
[last_Call-ID:]
|
|
124
|
+
[last_CSeq:]
|
|
125
|
+
Proxy-Authenticate: Digest realm="local", nonce="4cdbb733645816512687270b83d2ae5d11e4d9d8"
|
|
126
|
+
Content-Length: 0
|
|
127
|
+
|
|
128
|
+
]]>
|
|
129
|
+
</send>
|
|
130
|
+
|
|
131
|
+
<recv request="ACK"
|
|
132
|
+
rtd="true"
|
|
133
|
+
crlf="true">
|
|
134
|
+
<action>
|
|
135
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
136
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
137
|
+
</action>
|
|
138
|
+
</recv>
|
|
139
|
+
|
|
140
|
+
<recv request="INVITE" crlf="true">
|
|
141
|
+
<action>
|
|
142
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
143
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
144
|
+
</action>
|
|
145
|
+
|
|
146
|
+
</recv>
|
|
147
|
+
|
|
148
|
+
<send>
|
|
149
|
+
<![CDATA[
|
|
150
|
+
|
|
151
|
+
SIP/2.0 200 OK
|
|
152
|
+
[last_Via:]
|
|
153
|
+
[last_From:]
|
|
154
|
+
[last_To:];tag=[pid]SIPpTag01[call_number]
|
|
155
|
+
[last_Call-ID:]
|
|
156
|
+
[last_CSeq:]
|
|
157
|
+
[last_Record-Route:]
|
|
158
|
+
Subject:[$1]
|
|
159
|
+
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
|
160
|
+
Content-Type: application/sdp
|
|
161
|
+
Content-Length: [len]
|
|
162
|
+
|
|
163
|
+
v=0
|
|
164
|
+
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
|
|
165
|
+
s=-
|
|
166
|
+
c=IN IP[media_ip_type] [media_ip]
|
|
167
|
+
t=0 0
|
|
168
|
+
m=audio [media_port] RTP/AVP 0
|
|
169
|
+
a=rtpmap:0 PCMU/8000
|
|
170
|
+
|
|
171
|
+
]]>
|
|
172
|
+
</send>
|
|
173
|
+
|
|
174
|
+
<recv request="ACK"
|
|
175
|
+
rtd="true"
|
|
176
|
+
crlf="true">
|
|
177
|
+
<action>
|
|
178
|
+
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="1"/>
|
|
179
|
+
<ereg regexp=".*" search_in="hdr" header="To:" assign_to="2"/>
|
|
180
|
+
</action>
|
|
181
|
+
</recv>
|
|
182
|
+
|
|
183
|
+
<recv request="BYE">
|
|
184
|
+
</recv>
|
|
185
|
+
|
|
186
|
+
<send>
|
|
187
|
+
<![CDATA[
|
|
188
|
+
|
|
189
|
+
SIP/2.0 200 OK
|
|
190
|
+
[last_Via:]
|
|
191
|
+
[last_From:]
|
|
192
|
+
[last_To:]
|
|
193
|
+
[last_Call-ID:]
|
|
194
|
+
[last_CSeq:]
|
|
195
|
+
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
|
196
|
+
Content-Length: 0
|
|
197
|
+
|
|
198
|
+
]]>
|
|
199
|
+
</send>
|
|
200
|
+
|
|
201
|
+
<!-- Keep the call open for a while in case the 200 is lost to be -->
|
|
202
|
+
<!-- able to retransmit it if we receive the BYE again. -->
|
|
203
|
+
<timewait milliseconds="4000"/>
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
<!-- definition of the response time repartition table (unit is ms) -->
|
|
207
|
+
<ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
|
|
208
|
+
|
|
209
|
+
<!-- definition of the call length repartition table (unit is ms) -->
|
|
210
|
+
<CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
|
|
211
|
+
|
|
212
|
+
</scenario>
|
|
213
|
+
|
package/test/uac.js
CHANGED
|
@@ -176,6 +176,32 @@ test('UAC', (t) => {
|
|
|
176
176
|
srf = new Srf();
|
|
177
177
|
return connect(srf);
|
|
178
178
|
})
|
|
179
|
+
.then(() => {
|
|
180
|
+
return srf.createUAC('sip:172.29.0.25', {
|
|
181
|
+
method: 'INVITE',
|
|
182
|
+
headers: {
|
|
183
|
+
To: 'sip:dhorton@sip.drachtio.org',
|
|
184
|
+
From: 'sip:dhorton@sip.drachtio.org'
|
|
185
|
+
},
|
|
186
|
+
auth: {
|
|
187
|
+
username: 'foo',
|
|
188
|
+
password: 'bar'
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
})
|
|
192
|
+
.then((uac) => {
|
|
193
|
+
uacOverlap = uac;
|
|
194
|
+
return uac.modify('hold');
|
|
195
|
+
})
|
|
196
|
+
.then(() => uacOverlap.destroy())
|
|
197
|
+
.then(() => {
|
|
198
|
+
srf.disconnect();
|
|
199
|
+
return t.pass('SipDialog will handle authentication on re-invites');
|
|
200
|
+
})
|
|
201
|
+
.then(() => {
|
|
202
|
+
srf = new Srf();
|
|
203
|
+
return connect(srf);
|
|
204
|
+
})
|
|
179
205
|
.then(() => {
|
|
180
206
|
return srf.createUAC('sip:sipp-uas-auth', {
|
|
181
207
|
method: 'INVITE',
|
|
@@ -40,6 +40,10 @@ describe('Parser', function () {
|
|
|
40
40
|
msg.set('From', '<sip:daveh@localhost>;tag=1234');
|
|
41
41
|
msg.get('from').should.eql('<sip:daveh@localhost>;tag=1234');
|
|
42
42
|
});
|
|
43
|
+
it('should not parse a header when not available', function () {
|
|
44
|
+
var msg = new SipMessage();
|
|
45
|
+
should.throws(msg.getParsedHeader.bind(msg, 'contact'));
|
|
46
|
+
});
|
|
43
47
|
it('should parse multiple headers into an array', function () {
|
|
44
48
|
var msg = new SipMessage(examples('invite'));
|
|
45
49
|
var via = msg.getParsedHeader('via');
|
|
@@ -146,5 +150,11 @@ describe('Parser', function () {
|
|
|
146
150
|
msg.get('From').should.eql('"Dave" <sip:daveh@localhost>;tag=1234');
|
|
147
151
|
msg.callingName.should.eql('Dave');
|
|
148
152
|
});
|
|
153
|
+
it('should parse calling name', function () {
|
|
154
|
+
var msg = new SipMessage();
|
|
155
|
+
msg.set('From', '"Dave" <sip:daveh@localhost>;tag=1234');
|
|
156
|
+
msg.get('From').should.eql('"Dave" <sip:daveh@localhost>;tag=1234');
|
|
157
|
+
msg.callingName.should.eql('Dave');
|
|
158
|
+
});
|
|
149
159
|
});
|
|
150
160
|
|