diff --git a/lib/tasks/make_task.js b/lib/tasks/make_task.js index 0803d4fd..7b6eb89f 100644 --- a/lib/tasks/make_task.js +++ b/lib/tasks/make_task.js @@ -17,8 +17,10 @@ function makeTask(logger, obj, parent) { case TaskName.SipDecline: const TaskSipDecline = require('./sip_decline'); return new TaskSipDecline(logger, data, parent); + case TaskName.SipRefer: + const TaskSipRefer = require('./sip_refer'); + return new TaskSipRefer(logger, data, parent); case TaskName.Conference: - logger.debug({data}, 'Conference verb'); const TaskConference = require('./conference'); return new TaskConference(logger, data, parent); case TaskName.Dial: diff --git a/lib/tasks/sip_refer.js b/lib/tasks/sip_refer.js index 046f132b..cbf5bb95 100644 --- a/lib/tasks/sip_refer.js +++ b/lib/tasks/sip_refer.js @@ -1,5 +1,6 @@ const Task = require('./task'); const {TaskName, TaskPreconditions} = require('../utils/constants'); +const {parseUri} = require('drachtio-srf'); /** * sends a sip REFER to transfer the existing call @@ -12,6 +13,7 @@ class TaskSipRefer extends Task { this.referTo = this.data.referTo; this.referredBy = this.data.referredBy; this.headers = this.data.headers || {}; + this.eventHook = this.data.eventHook; } get name() { return TaskName.SipRefer; } @@ -19,10 +21,10 @@ class TaskSipRefer extends Task { async exec(cs) { super.exec(cs); const {dlg} = cs; - const {referTo, referredBy} = this._normalizeReferHeaders(dlg); + const {referTo, referredBy} = this._normalizeReferHeaders(cs, dlg); try { - this.notifyHandler = this._handleNotify.bind(this, dlg); + this.notifyHandler = this._handleNotify.bind(this, cs, dlg); dlg.on('notify', this.notifyHandler); const response = await dlg.request({ method: 'REFER', @@ -34,9 +36,13 @@ class TaskSipRefer extends Task { }); this.referStatus = response.status; this.logger.info(`TaskSipRefer:exec - received ${this.referStatus} to REFER`); - await this.performAction({status: this.referStatus}); - //if (response.status === 202) this.awaitTaskDone(); + /* if we fail, fall through to next verb. If success, we should get BYE from far end */ + if (this.referStatus === 202) { + this.logger.info('waiting for eventual BYE'); + await this.awaitTaskDone(); + } + else await this.performAction({refer_status: this.referStatus}); } catch (err) { this.logger.info({err}, 'TaskSipRefer:exec - error sending REFER'); } @@ -45,30 +51,51 @@ class TaskSipRefer extends Task { async kill(cs) { super.kill(cs); const {dlg} = cs; - dlg.removeEventListener('notify', this.notifyHandler); + dlg.off('notify', this.notifyHandler); } - async _handleNotify(dlg, req, res) { + async _handleNotify(cs, dlg, req, res) { + res.send(200); + const contentType = req.get('Content-Type'); this.logger.info({body: req.body}, `TaskSipRefer:_handleNotify got ${contentType}`); - res.send(200); + + if (contentType === 'message/sipfrag') { + const arr = /SIP\/2\.0\s+(\d+)/.exec(req.body); + if (arr) { + const status = arr[1]; + this.logger.info(`call got status ${status}`); + if (this.eventHook) { + await cs.requestor.request(this.eventHook, {event: 'transfer-status', call_status: status}); + } + if (status >= 200) { + await this.performAction({refer_status: 202, final_referred_call_status: status}); + this.notifyTaskDone(); + } + } + } } - _normalizeReferHeaders(dlg) { + _normalizeReferHeaders(cs, dlg) { let {referTo, referredBy} = this; + /* get IP address of the SBC to use as hostname if needed */ + const {host} = parseUri(dlg.remote.uri); + if (!referTo.startsWith('<') && !referTo.startsWith('sip') && !referTo.startsWith('"')) { /* they may have only provided a phone number/user */ - referTo = `sip:${referTo}@localhost`; + referTo = `sip:${referTo}@${host}`; } if (!referredBy) { /* default */ - referredBy = dlg.local.uri; + referredBy = cs.req?.callingNumber || dlg.local.uri; + this.logger.info({referredBy}, 'setting referredby'); } - else if (!referredBy.startsWith('<') && !referredBy.startsWith('sip') && !referredBy.startsWith('"')) { + if (!referredBy.startsWith('<') && !referredBy.startsWith('sip') && !referredBy.startsWith('"')) { /* they may have only provided a phone number/user */ - referredBy = `sip:${referredBy}@localhost`; + referredBy = `sip:${referredBy}@${host}`; } + return {referTo, referredBy}; } }