drachtio-srf 4.5.0 → 4.5.13
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 +104 -89
- package/lib/srf.js +17 -3
- 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/lib/dialog.js
CHANGED
|
@@ -198,21 +198,24 @@ class Dialog extends Emitter {
|
|
|
198
198
|
|
|
199
199
|
const __x = (callback) => {
|
|
200
200
|
if (this.dialogType === 'INVITE') {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
201
|
+
try {
|
|
202
|
+
this.agent.request({
|
|
203
|
+
method: 'BYE',
|
|
204
|
+
headers: opts.headers || {},
|
|
205
|
+
stackDialogId: this.id,
|
|
206
|
+
auth: opts.auth || this.auth,
|
|
207
|
+
_socket: this.socket
|
|
208
|
+
}, (err, bye) => {
|
|
209
|
+
if (err || !bye) {
|
|
210
|
+
return removeDialog(err, bye, callback);
|
|
211
|
+
}
|
|
212
|
+
bye.on('response', () => {
|
|
213
|
+
removeDialog(err, bye, callback);
|
|
214
|
+
});
|
|
214
215
|
});
|
|
215
|
-
})
|
|
216
|
+
} catch (err) {
|
|
217
|
+
removeDialog(err, null, callback);
|
|
218
|
+
}
|
|
216
219
|
if (this._emitter) {
|
|
217
220
|
Object.assign(this._state, {state: 'terminated'});
|
|
218
221
|
this._emitter.emit('stateChange', this._state);
|
|
@@ -223,14 +226,18 @@ class Dialog extends Emitter {
|
|
|
223
226
|
opts.headers = opts.headers || {} ;
|
|
224
227
|
opts.headers['subscription-state'] = 'terminated';
|
|
225
228
|
opts.headers['event'] = this.subscribeEvent ;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
229
|
+
try {
|
|
230
|
+
this.agent.request({
|
|
231
|
+
method: 'NOTIFY',
|
|
232
|
+
headers: opts.headers || {},
|
|
233
|
+
stackDialogId: this.id,
|
|
234
|
+
_socket: this.socket
|
|
235
|
+
}, (err, notify) => {
|
|
236
|
+
removeDialog(err, notify, callback);
|
|
237
|
+
}) ;
|
|
238
|
+
} catch (err) {
|
|
239
|
+
removeDialog(err, null, callback);
|
|
240
|
+
}
|
|
234
241
|
}
|
|
235
242
|
};
|
|
236
243
|
|
|
@@ -318,43 +325,48 @@ class Dialog extends Emitter {
|
|
|
318
325
|
if (opts.headers && !opts.headers['Contact']) {
|
|
319
326
|
opts.headers['Contact'] = this.local.contact;
|
|
320
327
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
else {
|
|
346
|
-
debug(`opts: ${JSON.stringify(opts)}`);
|
|
347
|
-
debug('SipDialog#modify: go 200 OK to 3pcc INVITE with no sdp; ack is application responsibility');
|
|
348
|
-
return callback(null, res.body, (sdp) => {
|
|
349
|
-
ack({body: sdp});
|
|
328
|
+
try {
|
|
329
|
+
this.agent.request({
|
|
330
|
+
method: 'INVITE',
|
|
331
|
+
stackDialogId: this.id,
|
|
332
|
+
body: this.local.sdp,
|
|
333
|
+
_socket: this.socket,
|
|
334
|
+
auth: opts.auth || this.auth,
|
|
335
|
+
headers:
|
|
336
|
+
opts.headers ? opts.headers : {'Contact': this.local.contact}
|
|
337
|
+
}, (err, req) => {
|
|
338
|
+
if (err) {
|
|
339
|
+
this._reinvitesInProgress.count--;
|
|
340
|
+
const admitOne = this._reinvitesInProgress.admitOne.shift();
|
|
341
|
+
if (admitOne) setImmediate(admitOne);
|
|
342
|
+
return callback(err);
|
|
343
|
+
}
|
|
344
|
+
req.on('response', (res, ack) => {
|
|
345
|
+
debug(`Dialog#modifySession: received response to reINVITE with status ${res.status}`) ;
|
|
346
|
+
if (res.status >= 200) {
|
|
347
|
+
if (200 === res.status) {
|
|
348
|
+
this.remote.sdp = res.body ;
|
|
349
|
+
if (this.local.sdp || opts.noAck !== true) {
|
|
350
|
+
ack() ;
|
|
350
351
|
onReInviteComplete(this);
|
|
351
|
-
|
|
352
|
+
return callback(null, res.body);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
debug(`opts: ${JSON.stringify(opts)}`);
|
|
356
|
+
debug('SipDialog#modify: go 200 OK to 3pcc INVITE with no sdp; ack is application responsibility');
|
|
357
|
+
return callback(null, res.body, (sdp) => {
|
|
358
|
+
ack({body: sdp});
|
|
359
|
+
onReInviteComplete(this);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
352
362
|
}
|
|
363
|
+
callback(new SipError(res.status, res.reason)) ;
|
|
353
364
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
365
|
+
}) ;
|
|
366
|
+
});
|
|
367
|
+
} catch (err) {
|
|
368
|
+
callback(err);
|
|
369
|
+
}
|
|
358
370
|
});
|
|
359
371
|
};
|
|
360
372
|
|
|
@@ -398,45 +410,48 @@ class Dialog extends Emitter {
|
|
|
398
410
|
const __x = (callback) => {
|
|
399
411
|
const method = opts.method.toUpperCase() ;
|
|
400
412
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
req.on('response', (res, ack) => {
|
|
414
|
-
if ('BYE' === method) {
|
|
415
|
-
this.srf.removeDialog(this) ;
|
|
413
|
+
try {
|
|
414
|
+
this.agent.request({
|
|
415
|
+
method: method,
|
|
416
|
+
stackDialogId: this.id,
|
|
417
|
+
headers: opts.headers || {},
|
|
418
|
+
auth: opts.auth || this.auth,
|
|
419
|
+
_socket: this.socket,
|
|
420
|
+
body: opts.body
|
|
421
|
+
}, (err, req) => {
|
|
422
|
+
if (err) {
|
|
423
|
+
return callback(err) ;
|
|
416
424
|
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
425
|
+
|
|
426
|
+
req.on('response', (res, ack) => {
|
|
427
|
+
if ('BYE' === method) {
|
|
428
|
+
this.srf.removeDialog(this) ;
|
|
429
|
+
}
|
|
430
|
+
if ('INVITE' === method && res.status >= 200) {
|
|
431
|
+
if (res.status > 200 || opts.body || opts.noAck !== true) ack() ;
|
|
432
|
+
else {
|
|
433
|
+
return callback(null, res, ack) ;
|
|
434
|
+
}
|
|
422
435
|
}
|
|
423
|
-
}
|
|
424
436
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
437
|
+
if (this.dialogType === 'SUBSCRIBE' && 'NOTIFY' === method &&
|
|
438
|
+
/terminated/.test(req.get('Subscription-State'))) {
|
|
439
|
+
debug('received response to a NOTIFY we sent terminating final subscription; dialog is ended') ;
|
|
428
440
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
441
|
+
const from = req.getParsedHeader('From');
|
|
442
|
+
if (this.removeSubscription(from.uri, req.get('Event')) === 0) {
|
|
443
|
+
this.connected = false ;
|
|
444
|
+
this.srf.removeDialog(this) ;
|
|
445
|
+
this.emit('destroy', req) ;
|
|
446
|
+
this.removeAllListeners();
|
|
447
|
+
}
|
|
435
448
|
}
|
|
436
|
-
|
|
437
|
-
|
|
449
|
+
callback(null, res) ;
|
|
450
|
+
}) ;
|
|
438
451
|
}) ;
|
|
439
|
-
})
|
|
452
|
+
} catch (err) {
|
|
453
|
+
callback(err);
|
|
454
|
+
}
|
|
440
455
|
} ;
|
|
441
456
|
|
|
442
457
|
if (callback) {
|
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) => {
|
|
@@ -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 ;
|
|
@@ -872,7 +882,11 @@ class Srf extends Emitter {
|
|
|
872
882
|
|
|
873
883
|
/* get headers from response on uac (B) leg and ready them for inclusion on our response on uas (A) leg */
|
|
874
884
|
function copyUACHeadersToUAS(uacRes) {
|
|
875
|
-
const headers = {}
|
|
885
|
+
const headers = {};
|
|
886
|
+
if (!uacRes) {
|
|
887
|
+
return headers;
|
|
888
|
+
}
|
|
889
|
+
|
|
876
890
|
if (proxyResponseHeaders[0] === 'all') {
|
|
877
891
|
copyAllHeaders(uacRes, headers);
|
|
878
892
|
possiblyRemoveHeaders(proxyResponseHeaders.slice(1), headers);
|
|
@@ -908,7 +922,7 @@ class Srf extends Emitter {
|
|
|
908
922
|
try {
|
|
909
923
|
const sdpA = await generateSdpA(provisionalRes);
|
|
910
924
|
opts.body = sdpA ;
|
|
911
|
-
return res.send(provisionalRes.status, provisionalRes.reason, opts)
|
|
925
|
+
return res.send(provisionalRes.status, provisionalRes.reason, opts);
|
|
912
926
|
} catch (err) {
|
|
913
927
|
debug(`Srf#createB2BUA: failed in call to produceSdpForALeg: ${err.message}`);
|
|
914
928
|
res.send(500) ;
|
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',
|