diff --git a/lib/proxy_logic_13/proxy_logic_13.js b/lib/proxy_logic_13/proxy_logic_13.js index b08ea47..ba29b72 100644 --- a/lib/proxy_logic_13/proxy_logic_13.js +++ b/lib/proxy_logic_13/proxy_logic_13.js @@ -773,6 +773,43 @@ var parkedChannels = {}; * @private */ var recordingConv = {}; +var recordingConvChannels = {}; + +function getRecordingConvKey(extension, convid) { + return extension + '|' + convid; +} + +function getRecordingConvStatus(extension, convid) { + return recordingConv[getRecordingConvKey(extension, convid)] || recordingConv[convid]; +} + +function isRecordingConversation(extension, convid) { + return getRecordingConvStatus(extension, convid) !== undefined; +} + +function stopRecordConversationForExtension(extension, convid, cb) { + try { + var recordingKey = getRecordingConvKey(extension, convid); + var chid = recordingConvChannels[recordingKey] || getExtenIdChannelConversation(extension, convid); + if (!chid) { + logger.warn(IDLOG, 'no channel to stop record of conversation ' + convid + ' of exten ' + extension); + cb(); + return; + } + + logger.info(IDLOG, 'execute the stop record of the channel ' + chid + ' of exten ' + extension); + astProxy.doCmd({ + command: 'stopRecordCall', + channel: chid + }, function (err) { + cb(err); + stopRecordCallCb(err, convid, extension); + }); + } catch (err) { + logger.error(IDLOG, err.stack); + cb(err); + } +} /** * These are the key names used into the asterisk structure @@ -4168,12 +4205,13 @@ function addConversationToExten(exten, resp, chid, spyConnected) { conv.setThroughTrunk(isConvThroughTrunk(conv)); // if the conversation is recording, sets its recording status - if (recordingConv[convid] !== undefined) { + var recordingStatus = getRecordingConvStatus(exten, convid); + if (recordingStatus !== undefined) { logger.info(IDLOG, 'set recording status to conversation ' + convid); - if (recordingConv[convid] === RECORDING_STATUS.TRUE) { + if (recordingStatus === RECORDING_STATUS.TRUE) { conv.setRecording(true); - } else if (recordingConv[convid] === RECORDING_STATUS.MUTE) { + } else if (recordingStatus === RECORDING_STATUS.MUTE) { conv.setRecordingMute(); } } @@ -4340,12 +4378,13 @@ function addConversationToTrunk(trunk, resp, chid) { } // if the conversation is recording, sets its recording status - if (recordingConv[convid] !== undefined) { + var recordingStatus = recordingConv[convid]; + if (recordingStatus !== undefined) { logger.info(IDLOG, 'set recording status to conversation ' + convid); - if (recordingConv[convid] === RECORDING_STATUS.TRUE) { + if (recordingStatus === RECORDING_STATUS.TRUE) { conv.setRecording(true); - } else if (recordingConv[convid] === RECORDING_STATUS.MUTE) { + } else if (recordingStatus === RECORDING_STATUS.MUTE) { conv.setRecordingMute(); } } @@ -7314,13 +7353,19 @@ function evtHangupConversation(data) { throw new Error('wrong parameters: ' + JSON.stringify(arguments)); } - // check the presence of recording status to be removed - var convid; - for (convid in recordingConv) { - if (convid.indexOf(data.channel) !== -1) { - delete recordingConv[convid]; + Object.keys(recordingConv).forEach(function(recordingKey) { + var keyPrefix = data.channelExten + '|'; + if (recordingKey.indexOf(keyPrefix) === 0) { + var recordedConvid = recordingKey.substring(keyPrefix.length); + stopRecordConversationForExtension(data.channelExten, recordedConvid, function(err) { + if (err) { + logger.error(IDLOG, 'stopping record on hangup of exten ' + data.channelExten + ' failed: ' + err.toString()); + } + }); + } else if (recordingKey.indexOf(data.channel) !== -1) { + delete recordingConv[recordingKey]; } - } + }); // check the extension existence if (extensions[data.channelExten]) { @@ -8166,16 +8211,30 @@ function blindTransferConversation(extension, convid, to, cb) { var chToTransfer = utilChannel13.extractExtensionFromChannel(channel) === extension ? channel : bridgedChannel; if (chToTransfer !== undefined) { - logger.info(IDLOG, 'blind transfer channel ' + chToTransfer + ' of exten ' + extension + ' to ' + to); - astProxy.doCmd({ - command: 'blindTransfer', - chToTransfer: chToTransfer, - context: blindTransferContext, - to: to - }, function (err) { - cb(err); - blindTransferConvCb(err); - }); + var executeBlindTransfer = function() { + logger.info(IDLOG, 'blind transfer channel ' + chToTransfer + ' of exten ' + extension + ' to ' + to); + astProxy.doCmd({ + command: 'blindTransfer', + chToTransfer: chToTransfer, + context: blindTransferContext, + to: to + }, function (err) { + cb(err); + blindTransferConvCb(err); + }); + }; + + if (isRecordingConversation(extension, convid)) { + stopRecordConversationBeforeTransfer(extension, convid, function(err) { + if (err) { + logger.warn(IDLOG, 'continue blind transfer after recording stop failure: ' + err.toString()); + } + executeBlindTransfer(); + }); + return; + } + + executeBlindTransfer(); } else { msg = 'blind transfer: no channel to transfer ' + chToTransfer; logger.error(IDLOG, msg); @@ -8233,17 +8292,20 @@ function attendedTransferConversation(extension, convid, to, cb) { var chToTransfer = utilChannel13.extractExtensionFromChannel(channel) === extension ? channel : bridgedChannel; if (chToTransfer !== undefined) { + var executeAttendedTransfer = function() { + // attended transfer the channel + logger.info(IDLOG, 'attended transfer of the channel ' + chToTransfer + ' of exten ' + extension + ' to ' + to); + astProxy.doCmd({ + command: 'attendedTransfer', + chToTransfer: chToTransfer, + to: to + }, function (err) { + cb(err); + attendedTransferConvCb(err); + }); + }; - // attended transfer the channel - logger.info(IDLOG, 'attended transfer of the channel ' + chToTransfer + ' of exten ' + extension + ' to ' + to); - astProxy.doCmd({ - command: 'attendedTransfer', - chToTransfer: chToTransfer, - to: to - }, function (err) { - cb(err); - attendedTransferConvCb(err); - }); + executeAttendedTransfer(); } else { msg = 'attended transfer: no channel to transfer ' + chToTransfer; @@ -8993,29 +9055,13 @@ function stopRecordConversation(extension, convid, cb) { // check the endpoint existence if (extensions[extension]) { - // get the channel to stop record - var chid = getExtenIdSourceChannelConversation(extension, convid); - - if (recordingConv[convid] === undefined) { + if (!isRecordingConversation(extension, convid)) { str = 'the conversation ' + convid + ' is not recording'; logger.info(IDLOG, str); cb(str); - } else if (chid) { - // start the recording - logger.info(IDLOG, 'execute the stop record of the channel ' + chid + ' of exten ' + extension); - astProxy.doCmd({ - command: 'stopRecordCall', - channel: chid - }, function (err) { - cb(err); - stopRecordCallCb(err, convid); - }); - } else { - str = 'no channel to stop record of conversation ' + convid + ' of exten ' + extension; - logger.warn(IDLOG, str); - cb(str); + stopRecordConversationForExtension(extension, convid, cb); } } else { @@ -9030,6 +9076,37 @@ function stopRecordConversation(extension, convid, cb) { } } +function stopRecordConversationBeforeTransfer(extension, convid, cb) { + try { + if (!isRecordingConversation(extension, convid)) { + cb(); + return; + } + + var chid = getExtenIdChannelConversation(extension, convid); + if (!chid) { + logger.warn(IDLOG, 'no channel to stop record before transfer of conversation ' + convid + ' of exten ' + extension); + cb(); + return; + } + + logger.info(IDLOG, 'stop recording before transfer of conversation ' + convid + ' of exten ' + extension); + astProxy.doCmd({ + command: 'stopRecordCall', + channel: chid + }, function (err) { + if (err) { + logger.error(IDLOG, 'stop recording before transfer of conversation ' + convid + ' failed: ' + err.toString()); + } + stopRecordCallCb(err, convid, extension); + cb(err); + }); + } catch (err) { + logger.error(IDLOG, err.stack); + cb(err); + } +} + /** * Start the spy of the conversation with speaking. * @@ -9156,16 +9233,14 @@ function muteRecordConversation(extension, convid, cb) { if (extensions[extension]) { // get the channel to record - var ch = getExtenSourceChannelConversation(extension, convid); + var chid = getExtenIdChannelConversation(extension, convid); // check if the conversation is already recording - if (recordingConv[convid] === undefined) { + if (!isRecordingConversation(extension, convid)) { logger.info(IDLOG, 'the conversation ' + convid + ' is not recording, so it can not be mute'); cb(); - } else if (ch) { - - var chid = ch.getChannel(); // the channel identifier + } else if (chid) { // start the recording logger.info(IDLOG, 'mute the recording of convid "' + convid + '" of extension "' + extension + '" with channel ' + chid); @@ -9182,7 +9257,7 @@ function muteRecordConversation(extension, convid, cb) { logger.info(IDLOG, 'mute the recording of convid "' + convid + '" of extension "' + extension + '" with channel ' + chid + ' has been successfully'); // set the recording status mute of all conversations with specified convid - setRecordStatusMuteConversations(convid); + setRecordStatusMuteConversations(convid, extension); cb(); } catch (e) { @@ -9229,16 +9304,14 @@ function unmuteRecordConversation(extension, convid, cb) { if (extensions[extension]) { // get the channel to record - var ch = getExtenSourceChannelConversation(extension, convid); + var chid = getExtenIdChannelConversation(extension, convid); // check if the conversation is already recording - if (recordingConv[convid] === undefined) { + if (!isRecordingConversation(extension, convid)) { logger.info(IDLOG, 'the conversation ' + convid + ' is not recording, so it can not be unmute'); cb(); - } else if (ch) { - - var chid = ch.getChannel(); // the channel identifier + } else if (chid) { // start the recording logger.info(IDLOG, 'unmute the recording of convid "' + convid + '" of extension "' + extension + '" with channel ' + chid); @@ -9253,9 +9326,9 @@ function unmuteRecordConversation(extension, convid, cb) { return; } logger.info(IDLOG, 'unmuting the recording of convid "' + convid + '" of extension "' + extension + '" with channel ' + chid + ' has been successfully'); - recordingConv[convid] = RECORDING_STATUS.TRUE; + recordingConv[getRecordingConvKey(extension, convid)] = RECORDING_STATUS.TRUE; // set the recording status of all conversations with specified convid - setRecordStatusConversations(convid, true); + setRecordStatusConversations(convid, true, extension); cb(); } catch (e) { @@ -9302,20 +9375,18 @@ function startRecordConversation(extension, convid, cb) { if (extensions[extension]) { // get the channel to record - var ch = getExtenSourceChannelConversation(extension, convid); + var chid = getExtenIdChannelConversation(extension, convid); // get the name of the audio file var now = new Date(); var filename = getRecordFilename(extension, convid, now); var filepath = getRecordFilepath(extension, convid, now); // check if the conversation is already recording - if (recordingConv[convid] !== undefined) { + if (isRecordingConversation(extension, convid)) { logger.info(IDLOG, 'the conversation ' + convid + ' is already recording'); cb(); - } else if (ch) { - - var chid = ch.getChannel(); // the channel identifier + } else if (chid) { logger.info(IDLOG, 'set asterisk variables to record the convid "' + convid + '" of extension "' + extension + '"'); // set some asterisk variables to fill the "recordingfile" field of the @@ -9369,6 +9440,29 @@ function startRecordConversation(extension, convid, cb) { }); }, + function (callback) { + + logger.info(IDLOG, 'set "CDR(recordingfile)" asterisk variable with filename "' + filename + '"'); + astProxy.doCmd({ + command: 'setVariable', + name: 'CDR(recordingfile)', + value: filename, + channel: chid + }, function (err) { + try { + if (err) { + callback(err); + } else { + callback(); + } + + } catch (e) { + logger.error(IDLOG, e.stack); + callback(e); + } + }); + }, + function (callback) { logger.info(IDLOG, 'set "MASTER_CHANNEL(CDR(recordingfile))" asterisk variable with filename "' + filename + '"'); @@ -9439,8 +9533,9 @@ function startRecordConversation(extension, convid, cb) { } logger.info(IDLOG, 'record the convid "' + convid + '" of extension "' + extension + '" has been successfully started in ' + filepath); + recordingConvChannels[getRecordingConvKey(extension, convid)] = chid; // set the recording status of the conversation - startRecordCallCb(convid); + startRecordCallCb(convid, extension); cb(); } catch (e) { @@ -9477,7 +9572,7 @@ function startRecordConversation(extension, convid, cb) { * @param {string} convid The conversation identifier * @private */ -function stopRecordCallCb(err, convid) { +function stopRecordCallCb(err, convid, extension) { try { if (err) { logger.error(IDLOG, 'stop record convid ' + convid + ' failed: ' + err.toString()); @@ -9486,9 +9581,14 @@ function stopRecordCallCb(err, convid) { logger.info(IDLOG, 'stop record convid ' + convid + ' started succesfully'); // remove the recording status of the conversation - delete recordingConv[convid]; + if (extension) { + delete recordingConv[getRecordingConvKey(extension, convid)]; + delete recordingConvChannels[getRecordingConvKey(extension, convid)]; + } else { + delete recordingConv[convid]; + } // reset the recording status of all conversations with specified convid - setRecordStatusConversations(convid, false); + setRecordStatusConversations(convid, false, extension); } } catch (error) { logger.error(IDLOG, error.stack); @@ -9502,12 +9602,16 @@ function stopRecordCallCb(err, convid) { * @param {string} convid The conversation identifier * @private */ -function startRecordCallCb(convid) { +function startRecordCallCb(convid, extension) { try { // set the recording status of the conversation to memory - recordingConv[convid] = RECORDING_STATUS.TRUE; + if (extension) { + recordingConv[getRecordingConvKey(extension, convid)] = RECORDING_STATUS.TRUE; + } else { + recordingConv[convid] = RECORDING_STATUS.TRUE; + } // set the recording status of all conversations with specified convid - setRecordStatusConversations(convid, true); + setRecordStatusConversations(convid, true, extension); } catch (error) { logger.error(IDLOG, error.stack); @@ -9522,7 +9626,7 @@ function startRecordCallCb(convid) { * @param {boolean} value The value to be set * @private */ -function setRecordStatusConversations(convid, value) { +function setRecordStatusConversations(convid, value, extension) { try { // check parameters if (typeof convid !== 'string' || typeof value !== 'boolean') { @@ -9541,7 +9645,7 @@ function setRecordStatusConversations(convid, value) { for (cid in convs) { // if the current conversation identifier is the // same of that specified, set its recording status - if (cid === convid) { + if (cid === convid && (!extension || exten === extension)) { convs[convid].setRecording(value); logger.info(IDLOG, 'set recording status ' + value + ' to conversation ' + convid); @@ -9587,7 +9691,7 @@ function setRecordStatusConversations(convid, value) { * @param {string} convid The conversation identifier * @private */ -function setRecordStatusMuteConversations(convid) { +function setRecordStatusMuteConversations(convid, extension) { try { // check parameter if (typeof convid !== 'string') { @@ -9606,8 +9710,12 @@ function setRecordStatusMuteConversations(convid) { for (cid in convs) { // if the current conversation identifier is the // same of that specified, set its recording status to mute - if (cid === convid) { - recordingConv[convid] = RECORDING_STATUS.MUTE; + if (cid === convid && (!extension || exten === extension)) { + if (extension) { + recordingConv[getRecordingConvKey(extension, convid)] = RECORDING_STATUS.MUTE; + } else { + recordingConv[convid] = RECORDING_STATUS.MUTE; + } convs[convid].setRecordingMute(); logger.info(IDLOG, 'set recording status "mute" to conversation ' + convid); @@ -9619,6 +9727,10 @@ function setRecordStatusMuteConversations(convid) { } } + if (extension) { + return; + } + var trunk; for (trunk in trunks) { // cycle in all trunks @@ -10424,4 +10536,4 @@ exports.getC2CMode = getC2CMode; exports.isC2CModeCloud = isC2CModeCloud; exports.getNullCallPeriod = getNullCallPeriod; exports.getStaticDataQueues = getStaticDataQueues; -exports.getPausedQueues = getPausedQueues; \ No newline at end of file +exports.getPausedQueues = getPausedQueues;