mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-22 01:27:55 +00:00
implement release-media and anchor-media operations
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user