From 7691af30de97ced16d6bd3a3320e6a4402d376a4 Mon Sep 17 00:00:00 2001 From: Dave Horton Date: Sat, 28 Jun 2025 15:01:09 -0400 Subject: [PATCH] Fix/dial refer (#1264) * Revert "Update dial.js (#1243)" This reverts commit 259dedcded60a24fbaf86d491f52bf26ee9f11a9. * add to .gitignore * when we receive a REFER on the parent leg, after adulting the child the dial task in the parent session should end --- .gitignore | 3 + lib/tasks/dial.js | 6 +- lib/utils/constants.json | 1 + test/index.js | 1 + test/scenarios/uas-dial-refer.xml | 117 ++++++++++++++++++++++++++++++ test/sip-refer-handler-tests.js | 90 +++++++++++++++++++++++ test/webhook/app.js | 18 +++++ 7 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 test/scenarios/uas-dial-refer.xml create mode 100644 test/sip-refer-handler-tests.js diff --git a/.gitignore b/.gitignore index bbb7837e..82c6d7a3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,9 @@ logs *.log +.claude/ +CLAUDE.md + # Runtime data pids *.pid diff --git a/lib/tasks/dial.js b/lib/tasks/dial.js index f6a8676a..103b41cd 100644 --- a/lib/tasks/dial.js +++ b/lib/tasks/dial.js @@ -422,12 +422,14 @@ class TaskDial extends Task { } //caller and callee legs are briged together, accept refer with 202 will release callee leg endpoint //that makes freeswitch release endpoint for caller leg. - //if the remaning leg is not a child (the child has now adulted) then hangup the A leg. if (this.ep) this.ep.unbridge(); res.send(202); this.logger.info('DialTask:handleRefer - sent 202 Accepted'); + + /* if we got the REFER on the parent leg, end the dial task after completing the refer */ if (!isChild) { - this.cs._jambonzHangup('refer-completed'); + this.logger.info('DialTask:handleRefer - killing dial task after processing REFER on parent leg'); + cs.currentTask?.kill(cs, KillReason.ReferComplete); } } catch (err) { this.logger.info({err}, 'DialTask:handleRefer - error processing incoming REFER'); diff --git a/lib/utils/constants.json b/lib/utils/constants.json index 5ca7e97b..5a38b016 100644 --- a/lib/utils/constants.json +++ b/lib/utils/constants.json @@ -243,6 +243,7 @@ "KillReason": { "Hangup": "hangup", "Replaced": "replaced", + "ReferComplete": "refer-complete", "MediaTimeout": "media_timeout" }, "HookMsgTypes": [ diff --git a/test/index.js b/test/index.js index 14746b95..3228a410 100644 --- a/test/index.js +++ b/test/index.js @@ -16,6 +16,7 @@ require('./sip-request-tests'); require('./create-call-test'); require('./play-tests'); require('./sip-refer-tests'); +require('./sip-refer-handler-tests'); require('./listen-tests'); require('./config-test'); require('./queue-test'); diff --git a/test/scenarios/uas-dial-refer.xml b/test/scenarios/uas-dial-refer.xml new file mode 100644 index 00000000..73ca3367 --- /dev/null +++ b/test/scenarios/uas-dial-refer.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + 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]SIPpTag01[call_number] + To: [$2] + [last_Call-ID:] + CSeq: 2 REFER + Contact: + Max-Forwards: 70 + X-Call-Number: [call_number] + Refer-To: + Referred-By: + Content-Length: 0 + ]]> + + + + + + \ No newline at end of file diff --git a/test/sip-refer-handler-tests.js b/test/sip-refer-handler-tests.js new file mode 100644 index 00000000..4525b03c --- /dev/null +++ b/test/sip-refer-handler-tests.js @@ -0,0 +1,90 @@ +const test = require('tape'); +const { sippUac } = require('./sipp')('test_fs'); +const bent = require('bent'); +const getJSON = bent('json') +const clearModule = require('clear-module'); +const {provisionCallHook} = require('./utils'); +const { sleepFor } = require('../lib/utils/helpers'); + +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('when parent leg recvs REFER it should end the dial after adulting child leg', async(t) => { + clearModule.all(); + const {srf, disconnect} = require('../app'); + try { + await connect(srf); + // wait for fs connected to drachtio server. + await sleepFor(1000); + + // GIVEN + const from = "dial_refer_handler"; + let verbs = [ + { + "verb": "dial", + "callerId": from, + "actionHook": "/actionHook", + "referHook": "/referHook", + "anchorMedia": true, + "target": [ + { + "type": "phone", + "number": "15083084809" + } + ] + } + ]; + + await provisionCallHook(from, verbs); + + // THEN + //const p = sippUac('uas-dial.xml', '172.38.0.10', undefined, undefined, 2); + const p = sippUac('uas-dial-refer.xml', '172.38.0.10', undefined, undefined, 2); + await sleepFor(1000); + + let account_sid = '622f62e4-303a-49f2-bbe0-eb1e1714e37a'; + + let post = bent('http://127.0.0.1:3000/', 'POST', 'json', 201); + post('v1/createCall', { + 'account_sid':account_sid, + "call_hook": { + "url": "http://127.0.0.1:3100/", + "method": "POST", + }, + "from": from, + "to": { + "type": "phone", + "number": "15583084808" + }}); + + await p; + + // Verify that the referHook was called + const obj = await getJSON(`http://127.0.0.1:3100/lastRequest/${from}_referHook`); + t.ok(obj.body.from === from, + 'dial-refer-handler: referHook was called with correct from'); + t.ok(obj.body.refer_details && obj.body.refer_details.sip_refer_to, + 'dial-refer-handler: refer_details included in referHook'); + t.ok(obj.body.refer_details.refer_to_user === '+15551234567', + 'dial-refer-handler: refer_to_user correctly parsed'); + t.ok(obj.body.refer_details.referring_call_sid, + 'dial-refer-handler: referring_call_sid included'); + t.ok(obj.body.refer_details.referred_call_sid, + 'dial-refer-handler: referred_call_sid included'); + + disconnect(); + } catch (err) { + console.log(`error received: ${err}`); + disconnect(); + t.error(err); + } +}); \ No newline at end of file diff --git a/test/webhook/app.js b/test/webhook/app.js index fba7c233..c8872264 100644 --- a/test/webhook/app.js +++ b/test/webhook/app.js @@ -99,6 +99,24 @@ app.post('/actionHook', (req, res) => { return res.sendStatus(200); }); +/* + * referHook + */ +app.post('/referHook', (req, res) => { + console.log({payload: req.body}, 'POST /referHook'); + let key = req.body.from + "_referHook" + addRequestToMap(key, req, hook_mapping); + return res.json([{"verb": "pause", "length": 2}]); +}); + +/* + * adultingHook + */ +app.post('/adulting', (req, res) => { + console.log({payload: req.body}, 'POST /adulting'); + return res.sendStatus(200); +}); + /* * customHook * For the hook to return