drachtio-srf 5.0.2 → 5.0.4

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.
@@ -120,6 +120,8 @@ module.exports = class DigestClient {
120
120
  if (transport) proxy += `;transport=${transport}`;
121
121
  Object.assign(options, {proxy});
122
122
  }
123
+
124
+ options._socket = this.res.socket;
123
125
  this.agent.request(options, callback) ;
124
126
  }) ;
125
127
  }
package/lib/srf.js CHANGED
@@ -298,6 +298,9 @@ class Srf extends Emitter {
298
298
 
299
299
  const __x = async(callback) => {
300
300
  try {
301
+ if (!req.has('Contact')) {
302
+ __fail(new Error('createUAS: Request is missing Contact header'), callback);
303
+ }
301
304
  const sdp = await generateSdp();
302
305
  debug({sdp}, `createUAS - generateSdp returned ${sdp}`);
303
306
  __send(sdp, callback);
@@ -549,9 +552,14 @@ class Srf extends Emitter {
549
552
  return callback(null, {
550
553
  sdp: res.body,
551
554
  ack: (localSdp) => {
552
- return new Promise((resolve) => {
555
+ return new Promise((resolve, reject) => {
553
556
  ack({body: localSdp}) ;
554
557
 
558
+ if (!res.has('Contact')) {
559
+ debug('createUAC: no Contact header in response, returning 480');
560
+ return reject(new Error('createUAC: no Contact header in response'));
561
+ }
562
+
555
563
  const dialog = new Dialog(this, 'uac', {req: req, res: res, auth: opts.auth}) ;
556
564
  dialog.local.sdp = localSdp ;
557
565
  this.addDialog(dialog) ;
@@ -574,6 +582,17 @@ class Srf extends Emitter {
574
582
 
575
583
  if ((200 === res.status && method === 'INVITE') ||
576
584
  ((202 === res.status || 200 === res.status) && method === 'SUBSCRIBE')) {
585
+ if (!res.has('Contact')) {
586
+ debug('createUAC: no Contact header in response, returning 500');
587
+ // When UAC receive a 200 OK without Contact header, it is too late for UAC
588
+ // to send CANCEL as it is already in the dialog.
589
+ // UAC does not have contact header to send indialog request such as ACK or BYE.
590
+ // The best way to handle this is to return 500 to the application.
591
+ // Then leave the drachtio server to release the INVITE transaction as failed.
592
+ const error = new SipError(500, 'No Contact header in response') ;
593
+ error.res = res ;
594
+ return callback(error);
595
+ }
577
596
  const dialog = new Dialog(this, 'uac', {req: req, res: res, auth: opts.auth}) ;
578
597
  if (req._dialogState) {
579
598
  dialog.stateEmitter = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drachtio-srf",
3
- "version": "5.0.2",
3
+ "version": "5.0.4",
4
4
  "description": "drachtio signaling resource framework",
5
5
  "main": "lib/srf.js",
6
6
  "types": "lib/@types/index.d.ts",
package/test/b2b.js CHANGED
@@ -19,6 +19,34 @@ test('B2B', (t) => {
19
19
  });
20
20
 
21
21
  Promise.resolve()
22
+ // B2BUA with PRACK
23
+ .then(() => {
24
+ debug('starting sipp');
25
+ return b2b.expectSuccess('sip:sipp-uas-prack', {
26
+ proxyResponseHeaders: [
27
+ 'all'
28
+ ],
29
+ responseHeaders: {
30
+ 'Contact': 'sip:foo@localhost'
31
+ }
32
+ });
33
+ })
34
+ .then(() => {
35
+ debug('start sipp...');
36
+ return sippUac('uac-prack.xml');
37
+ })
38
+ .then(() => {
39
+ return t.pass('b2b handles PRACK for both UAS and UAC');
40
+ })
41
+ .then(() => {
42
+ b2b.disconnect();
43
+ return new Promise((resolve, reject) => {
44
+ setTimeout(() => {
45
+ b2b = new B2b();
46
+ resolve();
47
+ }, 100);
48
+ });
49
+ })
22
50
  // INVITE with no SDP
23
51
  .then(() => {
24
52
  debug('starting sipp');
@@ -186,6 +214,50 @@ test('B2B', (t) => {
186
214
  });
187
215
  })
188
216
 
217
+ // reject no contact headers in sip request
218
+ .then(() => {
219
+ debug('starting sipp');
220
+ return b2b.expectFailure('sip:sipp-uas-404', 404, 400);
221
+ })
222
+ .then(() => {
223
+ debug('start sipp...');
224
+ return sippUac('uac-expect-400-no-contact-header.xml');
225
+ })
226
+ .then(() => {
227
+ return t.pass('reject if no contact headers in request');
228
+ })
229
+ .then(() => {
230
+ b2b.disconnect();
231
+ return new Promise((resolve, reject) => {
232
+ setTimeout(() => {
233
+ b2b = new B2b();
234
+ resolve();
235
+ }, 100);
236
+ });
237
+ })
238
+
239
+ // reject no contact headers in sip response
240
+ .then(() => {
241
+ debug('starting sipp');
242
+ return b2b.expectFailure('sipp-uas-200-ok-no-contact-cancel', 500, 480);
243
+ })
244
+ .then(() => {
245
+ debug('start sipp...');
246
+ return sippUac('uac-expect-480.xml');
247
+ })
248
+ .then(() => {
249
+ return t.pass('reject if no contact headers in response');
250
+ })
251
+ .then(() => {
252
+ b2b.disconnect();
253
+ return new Promise((resolve, reject) => {
254
+ setTimeout(() => {
255
+ b2b = new B2b();
256
+ resolve();
257
+ }, 100);
258
+ });
259
+ })
260
+
189
261
  // pass headers on response
190
262
  .then(() => {
191
263
  debug('starting sipp');
@@ -194,3 +194,14 @@ services:
194
194
  networks:
195
195
  testbed:
196
196
  ipv4_address: 172.29.0.27
197
+
198
+ sipp-uas-200-ok-no-contact-cancel:
199
+ image: drachtio/sipp:latest
200
+ command: sipp -sf /tmp/uas-200-ok-no-contact-cancel.xml
201
+ container_name: sipp-uas-200-ok-no-contact-cancel
202
+ volumes:
203
+ - ./scenarios:/tmp
204
+ tty: true
205
+ networks:
206
+ testbed:
207
+ ipv4_address: 172.29.0.28
@@ -0,0 +1,81 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?>
2
+ <!DOCTYPE scenario SYSTEM "sipp.dtd">
3
+
4
+ <!-- This program is free software; you can redistribute it and/or -->
5
+ <!-- modify it under the terms of the GNU General Public License as -->
6
+ <!-- published by the Free Software Foundation; either version 2 of the -->
7
+ <!-- License, or (at your option) any later version. -->
8
+ <!-- -->
9
+ <!-- This program is distributed in the hope that it will be useful, -->
10
+ <!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
11
+ <!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
12
+ <!-- GNU General Public License for more details. -->
13
+ <!-- -->
14
+ <!-- You should have received a copy of the GNU General Public License -->
15
+ <!-- along with this program; if not, write to the -->
16
+ <!-- Free Software Foundation, Inc., -->
17
+ <!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
18
+ <!-- -->
19
+ <!-- Sipp default 'uac' scenario. -->
20
+ <!-- -->
21
+
22
+ <scenario name="Basic Sipstone UAC">
23
+ <!-- In client mode (sipp placing calls), the Call-ID MUST be -->
24
+ <!-- generated by sipp. To do so, use [call_id] keyword. -->
25
+ <send retrans="500">
26
+ <![CDATA[
27
+
28
+ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
29
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
30
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
31
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>
32
+ Call-ID: [call_id]
33
+ CSeq: 1 INVITE
34
+ Max-Forwards: 70
35
+ Subject: Performance Test
36
+ Content-Type: application/sdp
37
+ Content-Length: [len]
38
+
39
+ v=0
40
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
41
+ s=-
42
+ c=IN IP[media_ip_type] [media_ip]
43
+ t=0 0
44
+ m=audio [media_port] RTP/AVP 0
45
+ a=rtpmap:0 PCMU/8000
46
+
47
+ ]]>
48
+ </send>
49
+
50
+ <recv response="100"
51
+ optional="true">
52
+ </recv>
53
+
54
+ <recv response="400" rtd="true"/>
55
+
56
+ <!-- Packet lost can be simulated in any send/recv message by -->
57
+ <!-- by adding the 'lost = "10"'. Value can be [1-100] percent. -->
58
+ <send>
59
+ <![CDATA[
60
+
61
+ ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
62
+ [last_Via]
63
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
64
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
65
+ Call-ID: [call_id]
66
+ CSeq: 1 ACK
67
+ Max-Forwards: 70
68
+ Subject: Performance Test
69
+ Content-Length: 0
70
+
71
+ ]]>
72
+ </send>
73
+
74
+ <!-- definition of the response time repartition table (unit is ms) -->
75
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
76
+
77
+ <!-- definition of the call length repartition table (unit is ms) -->
78
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
79
+
80
+ </scenario>
81
+
@@ -0,0 +1,128 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?>
2
+ <!DOCTYPE scenario SYSTEM "sipp.dtd">
3
+
4
+ <scenario name="UAC with PRACK Support">
5
+ <!-- Send INVITE with 100rel support -->
6
+ <send retrans="500">
7
+ <![CDATA[
8
+
9
+ INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
10
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
11
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
12
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>
13
+ Call-ID: [call_id]
14
+ CSeq: 1 INVITE
15
+ Contact: sip:sipp@[local_ip]:[local_port]
16
+ Supported: 100rel
17
+ Max-Forwards: 70
18
+ Subject: Performance Test
19
+ Content-Type: application/sdp
20
+ Content-Length: [len]
21
+
22
+ v=0
23
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
24
+ s=-
25
+ c=IN IP[media_ip_type] [media_ip]
26
+ t=0 0
27
+ m=audio [media_port] RTP/AVP 0
28
+ a=rtpmap:0 PCMU/8000
29
+
30
+ ]]>
31
+ </send>
32
+
33
+ <recv response="100" optional="true">
34
+ </recv>
35
+
36
+ <!-- Receive 180 Ringing with reliability required -->
37
+ <!-- Save RSeq and CSeq values for PRACK -->
38
+ <recv response="180" rrs="true">
39
+ <action>
40
+ <ereg regexp="([0-9]+)"
41
+ search_in="hdr"
42
+ header="RSeq:"
43
+ check_it="true"
44
+ assign_to="1"/>
45
+ <ereg regexp="([0-9]+) INVITE"
46
+ search_in="hdr"
47
+ header="CSeq:"
48
+ check_it="true"
49
+ assign_to="2"/>
50
+ </action>
51
+ </recv>
52
+
53
+ <!-- Send PRACK for the 180 response -->
54
+ <send>
55
+ <![CDATA[
56
+
57
+ PRACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
58
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
59
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
60
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
61
+ Call-ID: [call_id]
62
+ CSeq: 2 PRACK
63
+ RAck: [$1] [$2] INVITE
64
+ Contact: sip:sipp@[local_ip]:[local_port]
65
+ Max-Forwards: 70
66
+ Content-Length: 0
67
+
68
+ ]]>
69
+ </send>
70
+
71
+ <!-- Receive 200 OK for PRACK -->
72
+ <recv response="200">
73
+ </recv>
74
+
75
+ <!-- Receive 200 OK for INVITE -->
76
+ <recv response="200" rtd="true">
77
+ </recv>
78
+
79
+ <!-- Send ACK for 200 OK INVITE -->
80
+ <send>
81
+ <![CDATA[
82
+
83
+ ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
84
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
85
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
86
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
87
+ Call-ID: [call_id]
88
+ CSeq: 1 ACK
89
+ Contact: sip:sipp@[local_ip]:[local_port]
90
+ Max-Forwards: 70
91
+ Subject: Performance Test
92
+ Content-Length: 0
93
+
94
+ ]]>
95
+ </send>
96
+
97
+ <!-- Pause in conversation -->
98
+ <pause milliseconds="1000"/>
99
+
100
+ <!-- Send BYE -->
101
+ <send retrans="500">
102
+ <![CDATA[
103
+
104
+ BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
105
+ Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
106
+ From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[pid]SIPpTag00[call_number]
107
+ To: [service] <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
108
+ Call-ID: [call_id]
109
+ CSeq: 3 BYE
110
+ Contact: sip:sipp@[local_ip]:[local_port]
111
+ Max-Forwards: 70
112
+ Subject: Performance Test
113
+ Content-Length: 0
114
+
115
+ ]]>
116
+ </send>
117
+
118
+ <!-- Receive 200 OK for BYE -->
119
+ <recv response="200" crlf="true">
120
+ </recv>
121
+
122
+ <!-- definition of the response time repartition table (unit is ms) -->
123
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
124
+
125
+ <!-- definition of the call length repartition table (unit is ms) -->
126
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
127
+
128
+ </scenario>
@@ -0,0 +1,111 @@
1
+ <?xml version="1.0" encoding="ISO-8859-1" ?>
2
+ <!DOCTYPE scenario SYSTEM "sipp.dtd">
3
+
4
+ <!-- This program is free software; you can redistribute it and/or -->
5
+ <!-- modify it under the terms of the GNU General Public License as -->
6
+ <!-- published by the Free Software Foundation; either version 2 of the -->
7
+ <!-- License, or (at your option) any later version. -->
8
+ <!-- -->
9
+ <!-- This program is distributed in the hope that it will be useful, -->
10
+ <!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
11
+ <!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
12
+ <!-- GNU General Public License for more details. -->
13
+ <!-- -->
14
+ <!-- You should have received a copy of the GNU General Public License -->
15
+ <!-- along with this program; if not, write to the -->
16
+ <!-- Free Software Foundation, Inc., -->
17
+ <!-- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -->
18
+ <!-- -->
19
+ <!-- Sipp default 'uas' scenario. -->
20
+ <!-- -->
21
+
22
+ <scenario name="Basic UAS responder">
23
+ <!-- By adding rrs="true" (Record Route Sets), the route sets -->
24
+ <!-- are saved and used for following messages sent. Useful to test -->
25
+ <!-- against stateful SIP proxies/B2BUAs. -->
26
+ <recv request="INVITE" crlf="true">
27
+ <action>
28
+ <ereg regexp=".*" search_in="hdr" header="Via" check_it="false" assign_to="1"/>
29
+ <ereg regexp=".*" search_in="hdr" header="CSeq" check_it="false" assign_to="2"/>
30
+ </action>
31
+ </recv>
32
+
33
+ <!-- The '[last_*]' keyword is replaced automatically by the -->
34
+ <!-- specified header if it was present in the last message received -->
35
+ <!-- (except if it was a retransmission). If the header was not -->
36
+ <!-- present or if no message has been received, the '[last_*]' -->
37
+ <!-- keyword is discarded, and all bytes until the end of the line -->
38
+ <!-- are also discarded. -->
39
+ <!-- -->
40
+ <!-- If the specified header was present several times in the -->
41
+ <!-- message, all occurrences are concatenated (CRLF separated) -->
42
+ <!-- to be used in place of the '[last_*]' keyword. -->
43
+
44
+ <send>
45
+ <![CDATA[
46
+
47
+ SIP/2.0 200 OK
48
+ [last_Via:]
49
+ [last_From:]
50
+ [last_To:]
51
+ [last_Call-ID:]
52
+ [last_CSeq:]
53
+ Content-Type: application/sdp
54
+ Content-Length: [len]
55
+
56
+ v=0
57
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
58
+ s=-
59
+ c=IN IP[media_ip_type] [media_ip]
60
+ t=0 0
61
+ m=audio [media_port] RTP/AVP 0
62
+ a=rtpmap:0 PCMU/8000
63
+
64
+ ]]>
65
+ </send>
66
+
67
+ <recv request="CANCEL">
68
+ </recv>
69
+
70
+ <send>
71
+ <![CDATA[
72
+
73
+ SIP/2.0 200 OK
74
+ [last_Via:]
75
+ [last_From:]
76
+ [last_To:]
77
+ [last_Call-ID:]
78
+ [last_CSeq:]
79
+ Content-Length: 0
80
+
81
+ ]]>
82
+ </send>
83
+
84
+
85
+ <send retrans="500">
86
+ <![CDATA[
87
+
88
+ SIP/2.0 487 Request Terminated
89
+ Via [$1]
90
+ [last_From:]
91
+ [last_To:];tag=[pid]SIPpTag01[call_number]
92
+ [last_Call-ID:]
93
+ CSeq [$2]
94
+ Content-Length: 0
95
+
96
+ ]]>
97
+ </send>
98
+
99
+ <recv request="ACK"
100
+ rtd="true"
101
+ crlf="true">
102
+ </recv>
103
+
104
+ <!-- definition of the response time repartition table (unit is ms) -->
105
+ <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
106
+
107
+ <!-- definition of the call length repartition table (unit is ms) -->
108
+ <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
109
+
110
+ </scenario>
111
+