mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 08:40:38 +00:00
support kill dial if sd ep is media timeout (#1001)
* support kill dial if sd ep is media timeout * support kill dial if sd ep is media timeout * support kill dial if sd ep is media timeout * add media timeout reason header to bye message * wip * wip * make configuration for freeswitch media timeout * make configuration for freeswitch media timeout * wip
This commit is contained in:
@@ -137,6 +137,8 @@ const JAMBONES_EAGERLY_PRE_CACHE_AUDIO = parseInt(process.env.JAMBONES_EAGERLY_P
|
|||||||
|
|
||||||
const JAMBONES_USE_FREESWITCH_TIMER_FD = process.env.JAMBONES_USE_FREESWITCH_TIMER_FD;
|
const JAMBONES_USE_FREESWITCH_TIMER_FD = process.env.JAMBONES_USE_FREESWITCH_TIMER_FD;
|
||||||
const JAMBONES_DIAL_SBC_FOR_REGISTERED_USER = process.env.JAMBONES_DIAL_SBC_FOR_REGISTERED_USER || false;
|
const JAMBONES_DIAL_SBC_FOR_REGISTERED_USER = process.env.JAMBONES_DIAL_SBC_FOR_REGISTERED_USER || false;
|
||||||
|
const JAMBONES_MEDIA_TIMEOUT_MS = process.env.JAMBONES_MEDIA_TIMEOUT_MS || 0;
|
||||||
|
const JAMBONES_MEDIA_HOLD_TIMEOUT_MS = process.env.JAMBONES_MEDIA_HOLD_TIMEOUT_MS || 0;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
JAMBONES_MYSQL_HOST,
|
JAMBONES_MYSQL_HOST,
|
||||||
@@ -223,5 +225,7 @@ module.exports = {
|
|||||||
JAMBONZ_DISABLE_DIAL_PAI_HEADER,
|
JAMBONZ_DISABLE_DIAL_PAI_HEADER,
|
||||||
JAMBONES_DISABLE_DIRECT_P2P_CALL,
|
JAMBONES_DISABLE_DIRECT_P2P_CALL,
|
||||||
JAMBONES_USE_FREESWITCH_TIMER_FD,
|
JAMBONES_USE_FREESWITCH_TIMER_FD,
|
||||||
JAMBONES_DIAL_SBC_FOR_REGISTERED_USER
|
JAMBONES_DIAL_SBC_FOR_REGISTERED_USER,
|
||||||
|
JAMBONES_MEDIA_TIMEOUT_MS,
|
||||||
|
JAMBONES_MEDIA_HOLD_TIMEOUT_MS
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ const {
|
|||||||
JAMBONES_INJECT_CONTENT,
|
JAMBONES_INJECT_CONTENT,
|
||||||
JAMBONES_EAGERLY_PRE_CACHE_AUDIO,
|
JAMBONES_EAGERLY_PRE_CACHE_AUDIO,
|
||||||
AWS_REGION,
|
AWS_REGION,
|
||||||
JAMBONES_USE_FREESWITCH_TIMER_FD
|
JAMBONES_USE_FREESWITCH_TIMER_FD,
|
||||||
|
JAMBONES_MEDIA_TIMEOUT_MS,
|
||||||
|
JAMBONES_MEDIA_HOLD_TIMEOUT_MS
|
||||||
} = require('../config');
|
} = require('../config');
|
||||||
const bent = require('bent');
|
const bent = require('bent');
|
||||||
const BackgroundTaskManager = require('../utils/background-task-manager');
|
const BackgroundTaskManager = require('../utils/background-task-manager');
|
||||||
@@ -2796,15 +2798,25 @@ Duration=${duration} `
|
|||||||
|
|
||||||
_configMsEndpoint() {
|
_configMsEndpoint() {
|
||||||
this._enableInbandDtmfIfRequired(this.ep);
|
this._enableInbandDtmfIfRequired(this.ep);
|
||||||
|
this.ep.once('destroy', this._handleMediaTimeout.bind(this));
|
||||||
const opts = {
|
const opts = {
|
||||||
...(this.onHoldMusic && {holdMusic: `shout://${this.onHoldMusic.replace(/^https?:\/\//, '')}`}),
|
...(this.onHoldMusic && {holdMusic: `shout://${this.onHoldMusic.replace(/^https?:\/\//, '')}`}),
|
||||||
...(JAMBONES_USE_FREESWITCH_TIMER_FD && {timer_name: 'timerfd'})
|
...(JAMBONES_USE_FREESWITCH_TIMER_FD && {timer_name: 'timerfd'}),
|
||||||
|
...(JAMBONES_MEDIA_TIMEOUT_MS && {media_timeout: JAMBONES_MEDIA_TIMEOUT_MS}),
|
||||||
|
...(JAMBONES_MEDIA_HOLD_TIMEOUT_MS && {media_hold_timeout: JAMBONES_MEDIA_HOLD_TIMEOUT_MS})
|
||||||
};
|
};
|
||||||
if (Object.keys(opts).length > 0) {
|
if (Object.keys(opts).length > 0) {
|
||||||
this.ep.set(opts);
|
this.ep.set(opts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _handleMediaTimeout(evt) {
|
||||||
|
if (evt.reason === 'MEDIA_TIMEOUT' && !this.callGone) {
|
||||||
|
this.logger.info('CallSession:_handleMediaTimeout: received MEDIA_TIMEOUT, hangup the call');
|
||||||
|
this._jambonzHangup('Media Timeout');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async _enableInbandDtmfIfRequired(ep) {
|
async _enableInbandDtmfIfRequired(ep) {
|
||||||
if (ep.inbandDtmfEnabled) return;
|
if (ep.inbandDtmfEnabled) return;
|
||||||
// only enable inband dtmf detection if voip carrier dtmf_type === tones
|
// only enable inband dtmf detection if voip carrier dtmf_type === tones
|
||||||
|
|||||||
@@ -70,8 +70,12 @@ class InboundCallSession extends CallSession {
|
|||||||
this._hangup('caller');
|
this._hangup('caller');
|
||||||
}
|
}
|
||||||
|
|
||||||
_jambonzHangup() {
|
_jambonzHangup(reason) {
|
||||||
this.dlg?.destroy();
|
this.dlg?.destroy({
|
||||||
|
headers: {
|
||||||
|
...(reason && {'X-Reason': reason})
|
||||||
|
}
|
||||||
|
});
|
||||||
// kill current task or wakeup the call session.
|
// kill current task or wakeup the call session.
|
||||||
this._callReleased();
|
this._callReleased();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -273,7 +273,9 @@ class TaskDial extends Task {
|
|||||||
this._removeDtmfDetection(this.dlg);
|
this._removeDtmfDetection(this.dlg);
|
||||||
await this._killOutdials();
|
await this._killOutdials();
|
||||||
if (this.sd) {
|
if (this.sd) {
|
||||||
this.sd.kill();
|
const byeReasonHeader = this.killReason === KillReason.MediaTimeout ? 'Media Timeout' : undefined;
|
||||||
|
this.sd.kill(byeReasonHeader);
|
||||||
|
this.sd.ep?.removeListener('destroy', this._handleMediaTimeout.bind(this));
|
||||||
this.sd.removeAllListeners();
|
this.sd.removeAllListeners();
|
||||||
this.sd = null;
|
this.sd = null;
|
||||||
}
|
}
|
||||||
@@ -887,6 +889,14 @@ class TaskDial extends Task {
|
|||||||
if (this.canReleaseMedia || this.shouldExitMediaPathEntirely) {
|
if (this.canReleaseMedia || this.shouldExitMediaPathEntirely) {
|
||||||
setTimeout(this._releaseMedia.bind(this, cs, sd, this.shouldExitMediaPathEntirely), 200);
|
setTimeout(this._releaseMedia.bind(this, cs, sd, this.shouldExitMediaPathEntirely), 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.sd.ep.once('destroy', this._handleMediaTimeout.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
_handleMediaTimeout(evt) {
|
||||||
|
if (evt.reason === 'MEDIA_TIMEOUT' && this.sd && this.bridged) {
|
||||||
|
this.kill(this.cs, KillReason.MediaTimeout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_bridgeEarlyMedia(sd) {
|
_bridgeEarlyMedia(sd) {
|
||||||
|
|||||||
@@ -196,7 +196,8 @@
|
|||||||
},
|
},
|
||||||
"KillReason": {
|
"KillReason": {
|
||||||
"Hangup": "hangup",
|
"Hangup": "hangup",
|
||||||
"Replaced": "replaced"
|
"Replaced": "replaced",
|
||||||
|
"MediaTimeout": "media_timeout"
|
||||||
},
|
},
|
||||||
"HookMsgTypes": [
|
"HookMsgTypes": [
|
||||||
"session:new",
|
"session:new",
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ const HttpRequestor = require('./http-requestor');
|
|||||||
const WsRequestor = require('./ws-requestor');
|
const WsRequestor = require('./ws-requestor');
|
||||||
const {makeOpusFirst} = require('./sdp-utils');
|
const {makeOpusFirst} = require('./sdp-utils');
|
||||||
const {
|
const {
|
||||||
JAMBONES_USE_FREESWITCH_TIMER_FD
|
JAMBONES_USE_FREESWITCH_TIMER_FD,
|
||||||
|
JAMBONES_MEDIA_TIMEOUT_MS,
|
||||||
|
JAMBONES_MEDIA_HOLD_TIMEOUT_MS
|
||||||
} = require('../config');
|
} = require('../config');
|
||||||
|
|
||||||
class SingleDialer extends Emitter {
|
class SingleDialer extends Emitter {
|
||||||
@@ -317,14 +319,19 @@ class SingleDialer extends Emitter {
|
|||||||
/**
|
/**
|
||||||
* kill the call in progress or the stable dialog, whichever we have
|
* kill the call in progress or the stable dialog, whichever we have
|
||||||
*/
|
*/
|
||||||
async kill() {
|
async kill(Reason) {
|
||||||
this.killed = true;
|
this.killed = true;
|
||||||
if (this.inviteInProgress) await this.inviteInProgress.cancel();
|
if (this.inviteInProgress) await this.inviteInProgress.cancel();
|
||||||
else if (this.dlg && this.dlg.connected) {
|
else if (this.dlg && this.dlg.connected) {
|
||||||
const duration = moment().diff(this.dlg.connectTime, 'seconds');
|
const duration = moment().diff(this.dlg.connectTime, 'seconds');
|
||||||
this.logger.debug('SingleDialer:kill hanging up called party');
|
this.logger.debug('SingleDialer:kill hanging up called party');
|
||||||
this.emit('callStatusChange', {callStatus: CallStatus.Completed, duration});
|
this.emit('callStatusChange', {callStatus: CallStatus.Completed, duration});
|
||||||
this.dlg.destroy();
|
const headers = {
|
||||||
|
...(Reason && {'X-Reason': Reason})
|
||||||
|
};
|
||||||
|
this.dlg.destroy({
|
||||||
|
headers
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (this.ep) {
|
if (this.ep) {
|
||||||
this.logger.debug(`SingleDialer:kill - deleting endpoint ${this.ep.uuid}`);
|
this.logger.debug(`SingleDialer:kill - deleting endpoint ${this.ep.uuid}`);
|
||||||
@@ -335,7 +342,9 @@ class SingleDialer extends Emitter {
|
|||||||
_configMsEndpoint() {
|
_configMsEndpoint() {
|
||||||
const opts = {
|
const opts = {
|
||||||
...(this.onHoldMusic && {holdMusic: `shout://${this.onHoldMusic.replace(/^https?:\/\//, '')}`}),
|
...(this.onHoldMusic && {holdMusic: `shout://${this.onHoldMusic.replace(/^https?:\/\//, '')}`}),
|
||||||
...(JAMBONES_USE_FREESWITCH_TIMER_FD && {timer_name: 'timerfd'})
|
...(JAMBONES_USE_FREESWITCH_TIMER_FD && {timer_name: 'timerfd'}),
|
||||||
|
...(JAMBONES_MEDIA_TIMEOUT_MS && {media_timeout: JAMBONES_MEDIA_TIMEOUT_MS}),
|
||||||
|
...(JAMBONES_MEDIA_HOLD_TIMEOUT_MS && {media_hold_timeout: JAMBONES_MEDIA_HOLD_TIMEOUT_MS})
|
||||||
};
|
};
|
||||||
if (Object.keys(opts).length > 0) {
|
if (Object.keys(opts).length > 0) {
|
||||||
this.ep.set(opts);
|
this.ep.set(opts);
|
||||||
|
|||||||
Reference in New Issue
Block a user