From 1bac632a35f8d926a7f52758d0da0be961786dff Mon Sep 17 00:00:00 2001 From: Dave Horton Date: Mon, 21 Feb 2022 18:17:43 -0500 Subject: [PATCH] initial working version with ws api --- lib/session/call-session.js | 87 ++++++++++++++++++++++++++++++------- lib/utils/ws-requestor.js | 11 ++--- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/lib/session/call-session.js b/lib/session/call-session.js index 64588de7..15e7342d 100644 --- a/lib/session/call-session.js +++ b/lib/session/call-session.js @@ -62,6 +62,8 @@ class CallSession extends Emitter { } this._pool = srf.locals.dbHelpers.pool; + + this.requestor.on('command', this._onCommand.bind(this)); } /** @@ -404,31 +406,43 @@ class CallSession extends Emitter { */ async _lccCallHook(opts) { const webhooks = []; - let sd; - if (opts.call_hook) { - webhooks.push(this.requestor.request('session:redirect', opts.call_hook, this.callInfo.toJSON())); - } - 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('session:redirect', opts.child_call_hook, sd.callInfo.toJSON())); + let sd, tasks, childTasks; + + if (opts.call_hook || opts.child_call_hook) { + if (opts.call_hook) { + webhooks.push(this.requestor.request('session:redirect', opts.call_hook, this.callInfo.toJSON())); } + 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('session:redirect', opts.child_call_hook, sd.callInfo.toJSON())); + } + } + 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; } - const [tasks1, tasks2] = await Promise.all(webhooks); - let tasks, childTasks; - if (opts.call_hook) { - tasks = tasks1; - if (opts.child_call_hook) childTasks = tasks2; + else if (opts.parent_call || opts.child_call) { + const {parent_call, child_call} = opts; + assert.ok(!parent_call || Array.isArray(parent_call), 'CallSession:_lccCallHook - parent_call must be an array'); + assert.ok(!child_call || Array.isArray(child_call), 'CallSession:_lccCallHook - child_call must be an array'); + tasks = parent_call; + childTasks = child_call; } - 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:_lccCallHook new task list for child call'); + + // TODO: if using websockets api, we need a new websocket for the adulting session.. const cs = await sd.doAdulting({ logger: childLogger, application: this.application, @@ -606,6 +620,47 @@ class CallSession extends Emitter { this.taskIdx = 0; } + _onCommand({msgid, command, call_sid, data}) { + this.logger.info({msgid, command, call_sid, data}, 'CallSession:_onCommand - received command'); + switch (command) { + case 'redirect': + if (Array.isArray(data)) { + const t = normalizeJambones(this.logger, data).map((tdata) => makeTask(this.logger, tdata)); + this.logger.info({tasks: listTaskNames(t)}, 'CallSession:_onCommand new task list'); + this.replaceApplication(t); + } + else this._lccCallHook(data); + break; + + case 'call:status': + this._lccCallStatus(data); + break; + + case 'mute:status': + this._lccMuteStatus(data); + break; + + case 'conf:mute-status': + this._lccConfMuteStatus(data); + break; + + case 'conf:hold-status': + this._lccConfHoldStatus(data); + break; + + case 'listen:status': + this._lccListenStatus(data); + break; + + case 'whisper': + this._lccWhisper(data); + break; + + default: + this.logger.info(`CallSession:_onCommand - invalid command ${command}`); + } + } + _evaluatePreconditions(task) { switch (task.preconditions) { case TaskPreconditions.None: diff --git a/lib/utils/ws-requestor.js b/lib/utils/ws-requestor.js index e8acf64a..b6883fcb 100644 --- a/lib/utils/ws-requestor.js +++ b/lib/utils/ws-requestor.js @@ -196,7 +196,7 @@ class WsRequestor extends BaseRequestor { /* messages must be JSON format */ try { - const {type, msgid, command, call_sid, data} = JSON.parse(content); + const {type, msgid, command, data} = JSON.parse(content); assert.ok(type, 'type property not supplied'); switch (type) { @@ -207,9 +207,8 @@ class WsRequestor extends BaseRequestor { case 'command': assert.ok(command, 'command property not supplied'); - assert.ok(call_sid, 'call_sid property not supplied'); assert.ok(data, 'data property not supplied'); - this._recvCommand(msgid, command, call_sid, data); + this._recvCommand(msgid, command, data); break; default: @@ -232,8 +231,10 @@ class WsRequestor extends BaseRequestor { success && success(data); } - _recvCommand(msgid, command, call_sid, data) { - // TODO: execute command + _recvCommand(msgid, command, data) { + // TODO: validate command + this.logger.info({msgid, command, data}, 'received command'); + this.emit('command', {msgid, command, data}); } }