From 740c2b89b4f5c3a96a1507ea0df942e329ad8590 Mon Sep 17 00:00:00 2001 From: Dave Horton Date: Tue, 12 Oct 2021 12:22:52 -0400 Subject: [PATCH] Dial: dtmf detection now based on SIP INFO events from sbcs and rtpengine --- lib/tasks/dial.js | 71 ++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/lib/tasks/dial.js b/lib/tasks/dial.js index 8ab8b49c..b040a7e0 100644 --- a/lib/tasks/dial.js +++ b/lib/tasks/dial.js @@ -131,7 +131,7 @@ class TaskDial extends Task { get name() { return TaskName.Dial; } get canReleaseMedia() { - return !process.env.ANCHOR_MEDIA_ALWAYS && !this.dtmfHook && !this.listenTask && !this.transcribeTask; + return !process.env.ANCHOR_MEDIA_ALWAYS && !this.listenTask && !this.transcribeTask; } async exec(cs) { @@ -146,13 +146,12 @@ class TaskDial extends Task { this.epOther.play(this.dialMusic).catch((err) => {}); } } - if (this.epOther) this._installDtmfDetection(cs, this.epOther, this.parentDtmfCollector); await this._attemptCalls(cs); await this.awaitTaskDone(); this.logger.debug({callSid: this.cs.callSid}, 'Dial:exec task is done, sending actionHook if any'); await this.performAction(this.results, this.killReason !== KillReason.Replaced); - this._removeDtmfDetection(cs, this.epOther); - this._removeDtmfDetection(cs, this.ep); + this._removeDtmfDetection(cs.dlg); + this._removeDtmfDetection(this.dlg); } catch (err) { this.logger.error({err}, 'TaskDial:exec terminating with error'); this.kill(cs); @@ -162,8 +161,8 @@ class TaskDial extends Task { async kill(cs, reason) { super.kill(cs); this.killReason = reason || KillReason.Hangup; - this._removeDtmfDetection(this.cs, this.epOther); - this._removeDtmfDetection(this.cs, this.ep); + this._removeDtmfDetection(cs.dlg); + this._removeDtmfDetection(this.dlg); this._killOutdials(); if (this.sd) { this.sd.kill(); @@ -236,35 +235,39 @@ class TaskDial extends Task { this.dials.clear(); } - _installDtmfDetection(cs, ep, dtmfDetector) { - if (ep && this.dtmfHook && !ep.dtmfDetector) { - ep.dtmfDetector = dtmfDetector; - ep.on('dtmf', this._onDtmf.bind(this, cs, ep)); - } + _installDtmfDetection(cs, dlg) { + dlg.on('info', this._onInfo.bind(this, cs, dlg)); } - _removeDtmfDetection(cs, ep) { - if (ep) { - delete ep.dtmfDetector; - ep.removeAllListeners('dtmf'); - } + _removeDtmfDetection(dlg) { + dlg && dlg.removeAllListeners('info'); } - _onDtmf(cs, ep, evt) { - if (ep.dtmfDetector) { - const match = ep.dtmfDetector.keyPress(evt.dtmf); - if (match) { - this.logger.debug({callSid: this.cs.callSid}, `Dial:_onDtmf triggered dtmf match: ${match}`); - const requestor = ep.dtmfDetector === this.parentDtmfCollector ? - cs.requestor : - (this.sd ? this.sd.requestor : null); - if (!requestor) { - this.logger.info(`Dial:_onDtmf got digits on B leg after adulting: ${evt.dtmf}`); - } - else { - requestor.request(this.dtmfHook, {dtmf: match, ...cs.callInfo.toJSON()}) - .catch((err) => this.logger.info(err, 'Dial:_onDtmf - error')); - } - } + _onInfo(cs, dlg, req, res) { + res.send(200); + if (req.get('Content-Type') !== 'application/dtmf-relay') return; + + const dtmfDetector = dlg === cs.dlg ? this.parentDtmfCollector : this.childDtmfCollector; + if (!dtmfDetector) return; + let requestor, callSid, callInfo; + if (dtmfDetector === this.parentDtmfCollector) { + requestor = cs.requestor; + callSid = cs.callSid; + callInfo = cs.callInfo; + } + else { + requestor = this.sd?.requestor; + callSid = this.sd?.callSid; + callInfo = this.sd?.callInfo; + } + if (!requestor) return; + const arr = /Signal=([0-9#*])/.exec(req.body); + if (!arr) return; + const key = arr[1]; + const match = dtmfDetector.keyPress(key); + if (match) { + this.logger.info({callSid}, `Dial:_onInfo triggered dtmf match: ${match}`); + requestor.request(this.dtmfHook, {dtmf: match, ...callInfo.toJSON()}) + .catch((err) => this.logger.info(err, 'Dial:_onDtmf - error')); } } @@ -274,7 +277,6 @@ class TaskDial extends Task { debug(`Dial:__initializeInbound allocated ep for incoming call: ${ep.uuid}`); /* send outbound legs back to the same SBC (to support static IP feature) */ - //if (!this.proxy) this.proxy = `${cs.req.source_address}:${cs.req.source_port};transport=tcp`; if (!this.proxy) this.proxy = `${cs.req.source_address}:${cs.req.source_port}`; if (this.dialMusic) { @@ -478,7 +480,8 @@ class TaskDial extends Task { dialCallSid: sd.callSid, }); - if (this.childDtmfCollector) this._installDtmfDetection(cs, this.ep, this.childDtmfCollector); + if (this.parentDtmfCollector) this._installDtmfDetection(cs, cs.dlg); + if (this.childDtmfCollector) this._installDtmfDetection(cs, this.dlg); if (this.transcribeTask) this.transcribeTask.exec(cs, this.ep); if (this.listenTask) this.listenTask.exec(cs, this.ep);