implement release-media and anchor-media operations

This commit is contained in:
Dave Horton
2021-10-10 12:56:44 -04:00
parent 9f158a8cf7
commit 4627c0fa54
7 changed files with 137 additions and 4801 deletions

View File

@@ -130,7 +130,9 @@ class TaskDial extends Task {
get name() { return TaskName.Dial; }
get canReleaseMedia() { return !this.dtmfHook && !this.listenTask && !this.transcribeTask; }
get canReleaseMedia() {
return !process.env.ANCHOR_MEDIA_ALWAYS && !this.dtmfHook && !this.listenTask && !this.transcribeTask;
}
async exec(cs) {
await super.exec(cs);
@@ -179,9 +181,14 @@ class TaskDial extends Task {
* @param {*} tasks - array of play/say tasks to execute
*/
async whisper(tasks, callSid) {
if (!this.epOther || !this.ep) return this.logger.info('Dial:whisper: no paired endpoint found');
try {
const cs = this.callSession;
if (!this.ep && !this.epOther) {
await this.reAnchorMedia(this.callSession, this.sd);
}
if (!this.epOther || !this.ep) return this.logger.info('Dial:whisper: no paired endpoint found');
this.logger.debug('Dial:whisper unbridging endpoints');
await this.epOther.unbridge();
this.logger.debug('Dial:whisper executing tasks');
@@ -190,7 +197,12 @@ class TaskDial extends Task {
await task.exec(cs, callSid === this.callSid ? this.ep : this.epOther);
}
this.logger.debug('Dial:whisper tasks complete');
if (!cs.callGone && this.epOther) this.epOther.bridge(this.ep);
if (!cs.callGone && this.epOther) {
/* if we can release the media back to the SBC, do so now */
if (this.canReleaseMedia) this._releaseMedia(cs, this.sd);
else this.epOther.bridge(this.ep);
}
} catch (err) {
this.logger.error(err, 'Dial:whisper error');
}
@@ -200,12 +212,20 @@ class TaskDial extends Task {
* mute or unmute one side of the call
*/
async mute(callSid, doMute) {
if (doMute && !this.epOther && !this.ep) {
this.logger.info('Dial:mute re-anchoring media so we can mute');
await this.reAnchorMedia(this.callSession, this.sd);
this.epOther.bridge(this.ep);
}
if (!this.epOther || !this.ep) return this.logger.info('Dial:mute: no paired endpoint found');
try {
const parentCall = callSid !== this.callSid;
const ep = parentCall ? this.epOther : this.ep;
await ep[doMute ? 'mute' : 'unmute']();
this.logger.debug(`Dial:mute ${doMute ? 'muted' : 'unmuted'} ${parentCall ? 'parentCall' : 'childCall'}`);
/* release media once mute is over, if we can */
if (!doMute && this.canReleaseMedia) this._releaseMedia(this.callSession, this.sd);
} catch (err) {
this.logger.error(err, 'Dial:mute error');
}
@@ -325,7 +345,8 @@ class TaskDial extends Task {
sbcAddress,
target: t,
opts,
callInfo: cs.callInfo
callInfo: cs.callInfo,
accountInfo: cs.accountInfo
});
this.dials.set(sd.callSid, sd);
@@ -369,9 +390,13 @@ class TaskDial extends Task {
break;
}
})
.on('accept', () => {
.on('accept', async() => {
this.logger.debug(`Dial:_attemptCalls - we have a winner: ${sd.callSid}`);
this._connectSingleDial(cs, sd);
try {
await this._connectSingleDial(cs, sd);
} catch (err) {
this.logger.info({err}, 'Dial:_attemptCalls - Error calling _connectSingleDial ');
}
})
.on('decline', () => {
this.logger.debug(`Dial:_attemptCalls - declined: ${sd.callSid}`);
@@ -397,7 +422,7 @@ class TaskDial extends Task {
});
}
_connectSingleDial(cs, sd) {
async _connectSingleDial(cs, sd) {
if (!this.bridged && !this.canReleaseMedia) {
this.logger.debug('Dial:_connectSingleDial bridging endpoints');
if (this.epOther) {
@@ -408,7 +433,7 @@ class TaskDial extends Task {
}
// ding! ding! ding! we have a winner
this._selectSingleDial(cs, sd);
await this._selectSingleDial(cs, sd);
this._killOutdials(); // NB: order is important
}
@@ -421,7 +446,7 @@ class TaskDial extends Task {
* - launch any nested tasks
* - and establish a handler to clean up if the called party hangs up
*/
_selectSingleDial(cs, sd) {
async _selectSingleDial(cs, sd) {
debug(`Dial:_selectSingleDial ep for outbound call: ${sd.ep.uuid}`);
this.dials.delete(sd.callSid);
@@ -429,7 +454,7 @@ class TaskDial extends Task {
this.callSid = sd.callSid;
if (this.earlyMedia) {
debug('Dial:_selectSingleDial propagating answer supervision on A leg now that B is connected');
cs.propagateAnswer();
await cs.propagateAnswer();
}
if (this.timeLimit) {
this.timerMaxCallDuration = setTimeout(() => {
@@ -445,7 +470,7 @@ class TaskDial extends Task {
this.logger.debug('Dial:_selectSingleDial called party hungup, ending dial operation');
sessionTracker.remove(this.callSid);
if (this.timerMaxCallDuration) clearTimeout(this.timerMaxCallDuration);
this.ep.unbridge();
this.ep && this.ep.unbridge();
this.kill(cs);
}
});
@@ -483,15 +508,24 @@ class TaskDial extends Task {
assert(cs.ep && sd.ep);
try {
this.logger.info('Dial:_releaseMedia - releasing media from freewitch since we can');
this.logger.info('Dial:_releaseMedia - releasing media from freewitch');
const aLegSdp = cs.ep.remote.sdp;
const bLegSdp = sd.ep.remote.sdp;
await Promise.all[sd.releaseMediaToSBC(aLegSdp), cs.releaseMediaToSBC(bLegSdp)];
this.epOther = null;
this.logger.info('Dial:_releaseMedia - successfully released media from freewitch');
} catch (err) {
this.logger.info({err}, 'Dial:_releaseMedia error');
}
}
async reAnchorMedia(cs, sd) {
if (cs.ep && sd.ep) return;
this.logger.info('Dial:reAnchorMedia - re-anchoring media to freewitch');
await Promise.all([sd.reAnchorMedia(), cs.reAnchorMedia()]);
this.epOther = cs.ep;
}
}
module.exports = TaskDial;