mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-20 16:50:39 +00:00
snake case REST payloads, support for LCC with child_call_hook, handle 302 on outdial
This commit is contained in:
43
lib/session/adulting-call-session.js
Normal file
43
lib/session/adulting-call-session.js
Normal file
@@ -0,0 +1,43 @@
|
||||
const CallSession = require('./call-session');
|
||||
|
||||
/**
|
||||
* @classdesc Subclass of CallSession. Represents a CallSession
|
||||
* that was initially a child call leg; i.e. established via a Dial verb.
|
||||
* Now it is all grown up and filling out its own CallSession. Yoo-hoo!
|
||||
* @extends CallSession
|
||||
|
||||
*/
|
||||
class AdultingCallSession extends CallSession {
|
||||
constructor({logger, application, singleDialer, tasks, callInfo}) {
|
||||
super({
|
||||
logger,
|
||||
application,
|
||||
srf: singleDialer.dlg.srf,
|
||||
tasks,
|
||||
callInfo
|
||||
});
|
||||
this.sd = singleDialer;
|
||||
|
||||
this.sd.dlg.on('destroy', () => {
|
||||
this.logger.info('AdultingCallSession: called party hung up');
|
||||
this._callReleased();
|
||||
});
|
||||
this.sd.emit('adulting');
|
||||
}
|
||||
|
||||
get dlg() {
|
||||
return this.sd.dlg;
|
||||
}
|
||||
|
||||
get ep() {
|
||||
return this.sd.ep;
|
||||
}
|
||||
|
||||
get callSid() {
|
||||
return this.callInfo.callSid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
module.exports = AdultingCallSession;
|
||||
@@ -45,7 +45,7 @@ class CallSession extends Emitter {
|
||||
this.serviceUrl = srf.locals.serviceUrl;
|
||||
}
|
||||
|
||||
if (!this.isConfirmCallSession && !this.isSmsCallSession) {
|
||||
if (!this.isConfirmCallSession && !this.isSmsCallSession && !this.isAdultingCallSession) {
|
||||
sessionTracker.add(this.callSid, this);
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,12 @@ class CallSession extends Emitter {
|
||||
return this.application.transferredCall === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if this session is a ConfirmCallSession
|
||||
*/
|
||||
get isAdultingCallSession() {
|
||||
return this.constructor.name === 'AdultingCallSession';
|
||||
}
|
||||
/**
|
||||
* returns true if this session is a ConfirmCallSession
|
||||
*/
|
||||
@@ -296,10 +302,47 @@ class CallSession extends Emitter {
|
||||
* @param {object} [opts.call_hook] - new call_status_hook
|
||||
*/
|
||||
async _lccCallHook(opts) {
|
||||
const tasks = await this.requestor.request(opts.call_hook, this.callInfo);
|
||||
if (tasks && tasks.length > 0) {
|
||||
this.logger.info({tasks: listTaskNames(tasks)}, 'CallSession:updateCall new task list');
|
||||
this.replaceApplication(normalizeJambones(this.logger, tasks).map((tdata) => makeTask(this.logger, tdata)));
|
||||
const webhooks = [];
|
||||
let sd;
|
||||
if (opts.call_hook) webhooks.push(this.requestor.request(opts.call_hook, this.callInfo));
|
||||
if (opts.child_call_hook) {
|
||||
/* child call hook only allowed from a connected Dial state */
|
||||
const task = this.currentTask;
|
||||
sd = task.sd;
|
||||
if (task && TaskName.Dial === task.name && sd) {
|
||||
webhooks.push(this.requestor.request(opts.child_call_hook, sd.callInfo));
|
||||
}
|
||||
}
|
||||
const [tasks1, tasks2] = await Promise.all(webhooks);
|
||||
let tasks, childTasks;
|
||||
if (opts.call_hook) {
|
||||
tasks = tasks1;
|
||||
if (opts.child_call_hook) childTasks = tasks2;
|
||||
}
|
||||
else childTasks = tasks1;
|
||||
|
||||
if (childTasks) {
|
||||
const {parentLogger} = this.srf.locals;
|
||||
const childLogger = parentLogger.child({callId: this.callId, callSid: sd.callSid});
|
||||
const t = normalizeJambones(childLogger, childTasks).map((tdata) => makeTask(childLogger, tdata));
|
||||
childLogger.info({tasks: listTaskNames(t)}, 'CallSession:updateCall new task list for child call');
|
||||
const cs = await sd.doAdulting({
|
||||
logger: childLogger,
|
||||
application: this.application,
|
||||
tasks: t
|
||||
});
|
||||
|
||||
/* need to update the callSid of the child with its own (new) AdultingCallSession */
|
||||
sessionTracker.add(cs.callSid, cs);
|
||||
}
|
||||
if (tasks) {
|
||||
const t = normalizeJambones(this.logger, tasks).map((tdata) => makeTask(this.logger, tdata));
|
||||
this.logger.info({tasks: listTaskNames(t)}, 'CallSession:updateCall new task list');
|
||||
this.replaceApplication(t);
|
||||
}
|
||||
else {
|
||||
/* we started a new app on the child leg, but nothing given for parent so hang him up */
|
||||
this.currentTask.kill();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +447,7 @@ class CallSession extends Emitter {
|
||||
if (opts.call_status) {
|
||||
return this._lccCallStatus(opts);
|
||||
}
|
||||
if (opts.call_hook) {
|
||||
if (opts.call_hook || opts.child_call_hook) {
|
||||
return await this._lccCallHook(opts);
|
||||
}
|
||||
if (opts.listen_status) {
|
||||
@@ -489,9 +532,16 @@ class CallSession extends Emitter {
|
||||
const ep = await this.ms.createEndpoint({remoteSdp: this.req.body});
|
||||
ep.cs = this;
|
||||
this.ep = ep;
|
||||
await ep.set('hangup_after_bridge', false);
|
||||
ep.set({
|
||||
hangup_after_bridge: false,
|
||||
park_after_bridge: true
|
||||
}).catch((err) => this.logger.error({err}, 'Error setting park_after_bridge'));
|
||||
|
||||
this.logger.debug('allocated endpoint');
|
||||
this.logger.debug(`allocated endpoint ${this.ep.uuid}`);
|
||||
|
||||
this.ep.on('destroy', () => {
|
||||
this.logger.info(`endpoint was destroyed!! ${this.ep.uuid}`);
|
||||
});
|
||||
|
||||
if (this.direction === CallDirection.Inbound) {
|
||||
if (task.earlyMedia && !this.req.finalResponseSent) {
|
||||
|
||||
Reference in New Issue
Block a user