diff --git a/lib/tasks/sip_refer.js b/lib/tasks/sip_refer.js
index f4d41f0e..580befea 100644
--- a/lib/tasks/sip_refer.js
+++ b/lib/tasks/sip_refer.js
@@ -47,7 +47,17 @@ class TaskSipRefer extends Task {
/* if we fail, fall through to next verb. If success, we should get BYE from far end */
if (this.referStatus === 202) {
+ this._notifyTimer = setTimeout(() => {
+ this.logger.info('TaskSipRefer:exec - no NOTIFY received in 15 secs, exiting');
+ this.performAction({refer_status: this.referStatus})
+ .catch((err) => this.logger.error(err, 'TaskSipRefer:exec - error performing action'));
+ this.notifyTaskDone();
+ }, 15000);
await this.awaitTaskDone();
+ if (this._notifyTimer) {
+ clearTimeout(this._notifyTimer);
+ this._notifyTimer = null;
+ }
}
else {
await this.performAction({refer_status: this.referStatus});
@@ -71,10 +81,10 @@ class TaskSipRefer extends Task {
const contentType = req.get('Content-Type');
this.logger.debug({body: req.body}, `TaskSipRefer:_handleNotify got ${contentType}`);
- if (contentType === 'message/sipfrag') {
+ if (contentType?.includes('message/sipfrag')) {
const arr = /SIP\/2\.0\s+(\d+)/.exec(req.body);
if (arr) {
- const status = arr[1];
+ const status = typeof arr[1] === 'string' ? parseInt(arr[1], 10) : arr[1];
this.logger.debug(`TaskSipRefer:_handleNotify: call got status ${status}`);
if (this.eventHook) {
const b3 = this.getTracingPropagation();
diff --git a/package.json b/package.json
index fab1f826..fb144714 100644
--- a/package.json
+++ b/package.json
@@ -19,7 +19,7 @@
"bugs": {},
"scripts": {
"start": "node app",
- "test": "NODE_ENV=test JAMBONES_HOSTING=1 HTTP_POOL=1 DRACHTIO_HOST=127.0.0.1 DRACHTIO_PORT=9060 DRACHTIO_SECRET=cymru JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_PORT=3360 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=127.0.0.1 JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=debug ENABLE_METRICS=0 HTTP_PORT=3000 JAMBONES_SBCS=172.38.0.10 JAMBONES_FREESWITCH=127.0.0.1:8022:ClueCon:docker-host JAMBONES_TIME_SERIES_HOST=127.0.0.1 JAMBONES_NETWORK_CIDR=172.38.0.0/16 node test/ ",
+ "test": "NODE_ENV=test JAMBONES_HOSTING=1 HTTP_POOL=1 DRACHTIO_HOST=127.0.0.1 DRACHTIO_PORT=9060 DRACHTIO_SECRET=cymru JAMBONES_MYSQL_HOST=127.0.0.1 JAMBONES_MYSQL_PORT=3360 JAMBONES_MYSQL_USER=jambones_test JAMBONES_MYSQL_PASSWORD=jambones_test JAMBONES_MYSQL_DATABASE=jambones_test JAMBONES_REDIS_HOST=127.0.0.1 JAMBONES_REDIS_PORT=16379 JAMBONES_LOGLEVEL=error ENABLE_METRICS=0 HTTP_PORT=3000 JAMBONES_SBCS=172.38.0.10 JAMBONES_FREESWITCH=127.0.0.1:8022:ClueCon:docker-host JAMBONES_TIME_SERIES_HOST=127.0.0.1 JAMBONES_NETWORK_CIDR=172.38.0.0/16 node test/ ",
"coverage": "./node_modules/.bin/nyc --reporter html --report-dir ./coverage npm run test",
"jslint": "eslint app.js lib"
},
diff --git a/test/index.js b/test/index.js
index 5f0bfdf4..a9321996 100644
--- a/test/index.js
+++ b/test/index.js
@@ -8,5 +8,6 @@ require('./gather-tests');
require('./sip-request-tests');
require('./create-call-test');
require('./play-tests');
+require('./sip-refer-tests');
require('./remove-test-db');
require('./docker_stop');
diff --git a/test/scenarios/uac-refer-no-notify.xml b/test/scenarios/uac-refer-no-notify.xml
new file mode 100644
index 00000000..6f6d4df5
--- /dev/null
+++ b/test/scenarios/uac-refer-no-notify.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+ ;tag=[pid]SIPpTag00[call_number]
+ To:
+ Call-ID: [call_id]
+ CSeq: 1 INVITE
+ Contact: sip:[from]@[local_ip]:[local_port]
+ Max-Forwards: 70
+ X-Account-Sid: bb845d4b-83a9-4cde-a6e9-50f3743bab3f
+ Subject: uac-refer-no-notify.xml
+ Content-Type: application/sdp
+ Content-Length: [len]
+
+ v=0
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+ s=-
+ c=IN IP[media_ip_type] [media_ip]
+ t=0 0
+ m=audio [media_port] RTP/AVP 0
+ a=rtpmap:0 PCMU/8000
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;tag=[pid]SIPpTag00[call_number]
+ To: [service] [peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 1 ACK
+ Max-Forwards: 70
+ Subject: REFER test with no NOT
+ Content-Length: 0
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
diff --git a/test/scenarios/uac-refer-with-notify.xml b/test/scenarios/uac-refer-with-notify.xml
new file mode 100644
index 00000000..93a48b4d
--- /dev/null
+++ b/test/scenarios/uac-refer-with-notify.xml
@@ -0,0 +1,115 @@
+
+
+
+
+
+
+
+ ;tag=[pid]SIPpTag00[call_number]
+ To:
+ Call-ID: [call_id]
+ CSeq: 1 INVITE
+ Contact: sip:[from]@[local_ip]:[local_port]
+ Max-Forwards: 70
+ X-Account-Sid: bb845d4b-83a9-4cde-a6e9-50f3743bab3f
+ Subject: uac-refer-with-notify.xml
+ Content-Type: application/sdp
+ Content-Length: [len]
+
+ v=0
+ o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
+ s=-
+ c=IN IP[media_ip_type] [media_ip]
+ t=0 0
+ m=audio [media_port] RTP/AVP 0
+ a=rtpmap:0 PCMU/8000
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ;tag=[pid]SIPpTag00[call_number]
+ To: [peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 1 ACK
+ Max-Forwards: 70
+ Subject: uac-refer-with-notify.xml
+ Content-Length: 0
+
+ ]]>
+
+
+
+
+
+
+
+
+
+
+ ;tag=[pid]SIPpTag00[call_number]
+ To: [peer_tag_param]
+ Call-ID: [call_id]
+ CSeq: 2 NOTIFY
+ Contact: sip:sipp@[local_ip]:[local_port]
+ Max-Forwards: 70
+ Subject: uac-refer-with-notify.xml
+ Content-Type: message/sipfrag;version=2.0
+ Content-Length: 16
+
+ SIP/2.0 200 OK
+ ]]>
+
+
+
+
diff --git a/test/sip-refer-tests.js b/test/sip-refer-tests.js
new file mode 100644
index 00000000..7b5de67c
--- /dev/null
+++ b/test/sip-refer-tests.js
@@ -0,0 +1,100 @@
+const test = require('tape');
+const { sippUac } = require('./sipp')('test_fs');
+const clearModule = require('clear-module');
+const {provisionCallHook, provisionCustomHook, provisionActionHook} = require('./utils')
+const bent = require('bent');
+const getJSON = bent('json')
+
+const sleepFor = async(ms) => new Promise(resolve => setTimeout(resolve, ms));
+
+process.on('unhandledRejection', (reason, p) => {
+ console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
+});
+
+function connect(connectable) {
+ return new Promise((resolve, reject) => {
+ connectable.on('connect', () => {
+ return resolve();
+ });
+ });
+}
+
+test('\'refer\' tests w/202 and NOTIFY', {timeout: 25000}, async(t) => {
+ clearModule.all();
+ const {srf, disconnect} = require('../app');
+
+ try {
+ await connect(srf);
+
+ // GIVEN
+ const verbs = [
+ {
+ verb: 'say',
+ text: 'silence_stream://100'
+ },
+ {
+ verb: 'sip:refer',
+ referTo: '123456',
+ actionHook: '/actionHook'
+ }
+ ];
+ const noVerbs = [];
+
+ const from = 'refer_with_notify';
+ provisionCallHook(from, verbs);
+ provisionActionHook(from, noVerbs)
+
+ // THEN
+ await sippUac('uac-refer-with-notify.xml', '172.38.0.10', from);
+ t.pass('refer: successfully received 202 Accepted');
+ await sleepFor(1000);
+ const obj = await getJSON(`http:127.0.0.1:3100/lastRequest/${from}_actionHook`);
+ t.ok(obj.body.final_referred_call_status === 200, 'refer: successfully received NOTIFY with 200 OK');
+ //console.log(`obj: ${JSON.stringify(obj)}`);
+ disconnect();
+ } catch (err) {
+ console.log(`error received: ${err}`);
+ disconnect();
+ t.error(err);
+ }
+});
+
+test('\'refer\' tests w/202 but no NOTIFY', {timeout: 25000}, async(t) => {
+ clearModule.all();
+ const {srf, disconnect} = require('../app');
+
+ try {
+ await connect(srf);
+
+ // GIVEN
+ const verbs = [
+ {
+ verb: 'say',
+ text: 'silence_stream://100'
+ },
+ {
+ verb: 'sip:refer',
+ referTo: '123456',
+ actionHook: '/actionHook'
+ }
+ ];
+ const noVerbs = [];
+
+ const from = 'refer_no_notify';
+ provisionCallHook(from, verbs);
+ provisionActionHook(from, noVerbs)
+
+ // THEN
+ await sippUac('uac-refer-no-notify.xml', '172.38.0.10', from);
+ t.pass('refer: successfully received 202 Accepted w/o NOTIFY');
+ await sleepFor(17000);
+ const obj = await getJSON(`http:127.0.0.1:3100/lastRequest/${from}_actionHook`);
+ console.log(`obj: ${JSON.stringify(obj)}`);
+ t.ok(obj.body.refer_status === 202, 'refer: successfully timed out and reported 202');
+ disconnect();
+ } catch (err) {
+ console.log(`error received: ${err}`);
+ disconnect();
+ t.error(err);
+ }
+});
diff --git a/test/sip-tests.js b/test/sip-tests.js
index 00c73cb6..1e60f24b 100644
--- a/test/sip-tests.js
+++ b/test/sip-tests.js
@@ -53,6 +53,13 @@ test('incoming call tests', (t) => {
.then(() => {
return t.pass('handles in-dialog requests');
})
+ .then(() => {
+ return sippUac('uac-refer-no-notify.xml', '172.38.0.30');
+ })
+ .then(() => {
+ return t.pass('handles sip:refer where we get 202 but no NOTIFY');
+ })
+
.then(() => {
srf.disconnect();
t.end();
diff --git a/test/utils.js b/test/utils.js
index 0a0d7626..6ce588a8 100644
--- a/test/utils.js
+++ b/test/utils.js
@@ -24,4 +24,13 @@ const provisionCustomHook = (from, verbs) => {
post(`/customHookMapping`, mapping);
}
-module.exports = { provisionCallHook, provisionCustomHook}
+const provisionActionHook = (from, verbs) => {
+ const mapping = {
+ from,
+ data: JSON.stringify(verbs)
+ };
+ const post = bent('http://127.0.0.1:3100', 'POST', 'string', 200);
+ post(`/actionHook`, mapping);
+}
+
+module.exports = { provisionCallHook, provisionCustomHook, provisionActionHook}