mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-18 20:07:44 +00:00
Fix/dial refer (#1264)
* Revert "Update dial.js (#1243)"
This reverts commit 259dedcded.
* 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
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,6 +2,9 @@
|
||||
logs
|
||||
*.log
|
||||
|
||||
.claude/
|
||||
CLAUDE.md
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
"KillReason": {
|
||||
"Hangup": "hangup",
|
||||
"Replaced": "replaced",
|
||||
"ReferComplete": "refer-complete",
|
||||
"MediaTimeout": "media_timeout"
|
||||
},
|
||||
"HookMsgTypes": [
|
||||
|
||||
@@ -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');
|
||||
|
||||
117
test/scenarios/uas-dial-refer.xml
Normal file
117
test/scenarios/uas-dial-refer.xml
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE scenario SYSTEM "sipp.dtd">
|
||||
|
||||
<scenario name="UAS that accepts call and sends REFER">
|
||||
<!-- Receive incoming INVITE -->
|
||||
<recv request="INVITE" crlf="true">
|
||||
<action>
|
||||
<ereg regexp=".*" search_in="hdr" header="Subject:" assign_to="1" />
|
||||
<ereg regexp=".*" search_in="hdr" header="From:" assign_to="2" />
|
||||
</action>
|
||||
</recv>
|
||||
|
||||
<!-- Send 180 Ringing -->
|
||||
<send>
|
||||
<![CDATA[
|
||||
SIP/2.0 180 Ringing
|
||||
[last_Via:]
|
||||
[last_From:]
|
||||
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||
[last_Call-ID:]
|
||||
[last_CSeq:]
|
||||
[last_Record-Route:]
|
||||
Subject:[$1]
|
||||
Content-Length: 0
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<!-- Send 200 OK with SDP -->
|
||||
<send>
|
||||
<![CDATA[
|
||||
SIP/2.0 200 OK
|
||||
[last_Via:]
|
||||
[last_From:]
|
||||
[last_To:];tag=[pid]SIPpTag01[call_number]
|
||||
[last_Call-ID:]
|
||||
[last_CSeq:]
|
||||
[last_Record-Route:]
|
||||
Subject:[$1]
|
||||
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
||||
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
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<recv request="ACK" rtd="true" crlf="true">
|
||||
<action>
|
||||
<!-- Check if this is NOT the first call (tag ends with 012 or higher) -->
|
||||
<ereg regexp="tag=1SIPpTag01[2-9]" search_in="hdr" header="To:" assign_to="3" />
|
||||
<log message="Not first call check result: [$3]"/>
|
||||
</action>
|
||||
</recv>
|
||||
|
||||
<!-- Skip REFER if we found a non-first call tag -->
|
||||
<nop next="skip_refer" test="3" value="" compare="not_equal">
|
||||
<action>
|
||||
<log message="Found non-first call tag [$3], skipping REFER"/>
|
||||
</action>
|
||||
</nop>
|
||||
|
||||
<!-- Wait a moment, then send REFER (only on first call) -->
|
||||
<pause milliseconds="1000"/>
|
||||
|
||||
<nop>
|
||||
<action>
|
||||
<log message="Sending REFER for first call"/>
|
||||
</action>
|
||||
</nop>
|
||||
|
||||
<!-- Send REFER (only on first iteration) -->
|
||||
<send retrans="500">
|
||||
<![CDATA[
|
||||
REFER sip:service@[remote_ip]:[remote_port] SIP/2.0
|
||||
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
|
||||
From: <sip:[local_ip]:[local_port]>;tag=[pid]SIPpTag01[call_number]
|
||||
To: [$2]
|
||||
[last_Call-ID:]
|
||||
CSeq: 2 REFER
|
||||
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
||||
Max-Forwards: 70
|
||||
X-Call-Number: [call_number]
|
||||
Refer-To: <sip:+15551234567@example.com>
|
||||
Referred-By: <sip:[local_ip]:[local_port]>
|
||||
Content-Length: 0
|
||||
]]>
|
||||
</send>
|
||||
|
||||
<!-- Expect 202 Accepted (only on first iteration) -->
|
||||
<recv response="202"/>
|
||||
|
||||
<label id="skip_refer"/>
|
||||
|
||||
<!-- Wait for BYE from feature server -->
|
||||
<recv request="BYE"/>
|
||||
|
||||
<!-- Send 200 OK to BYE -->
|
||||
<send>
|
||||
<![CDATA[
|
||||
SIP/2.0 200 OK
|
||||
[last_Via:]
|
||||
[last_From:]
|
||||
[last_To:]
|
||||
[last_Call-ID:]
|
||||
[last_CSeq:]
|
||||
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
|
||||
Content-Length: 0
|
||||
]]>
|
||||
</send>
|
||||
|
||||
</scenario>
|
||||
90
test/sip-refer-handler-tests.js
Normal file
90
test/sip-refer-handler-tests.js
Normal file
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user