mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-12 14:24:13 +00:00
304 lines
12 KiB
C
304 lines
12 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "cpr_stdio.h"
|
|
#include <time.h>
|
|
#include "sessionHash.h"
|
|
#include "CCProvider.h"
|
|
#include "call_logger.h"
|
|
|
|
|
|
|
|
void calllogger_init_call_log (cc_call_log_t *log)
|
|
{
|
|
log->localPartyName = strlib_empty();
|
|
log->localPartyNumber = strlib_empty();
|
|
log->remotePartyName[0] = strlib_empty();
|
|
log->remotePartyName[1] = strlib_empty();
|
|
log->remotePartyNumber[0] = strlib_empty();
|
|
log->remotePartyNumber[1] = strlib_empty();
|
|
log->altPartyNumber[0] = strlib_empty();
|
|
log->altPartyNumber[1] = strlib_empty();
|
|
log->startTime = 0;
|
|
log->duration = 0;
|
|
|
|
log->logDisp = CC_LOGD_UNKNWN;
|
|
log->callState = MAX_CALL_STATES;
|
|
}
|
|
|
|
void calllogger_copy_call_log (cc_call_log_t *dest, cc_call_log_t * src)
|
|
{
|
|
dest->localPartyName = strlib_copy(src->localPartyName);
|
|
dest->localPartyNumber = strlib_copy(src->localPartyNumber);
|
|
dest->remotePartyName[0] = strlib_copy(src->remotePartyName[0]);
|
|
dest->remotePartyName[1] = strlib_copy(src->remotePartyName[1]);
|
|
dest->remotePartyNumber[0] = strlib_copy(src->remotePartyNumber[0]);
|
|
dest->remotePartyNumber[1] = strlib_copy(src->remotePartyNumber[1]);
|
|
dest->altPartyNumber[0] = strlib_copy(src->altPartyNumber[0]);
|
|
dest->altPartyNumber[1] = strlib_copy(src->altPartyNumber[1]);
|
|
dest->startTime = src->startTime;
|
|
dest->duration = src->duration;
|
|
|
|
dest->logDisp = src->logDisp;
|
|
dest->callState = src->callState;
|
|
}
|
|
|
|
void calllogger_free_call_log (cc_call_log_t *log)
|
|
{
|
|
strlib_free(log->localPartyName);
|
|
strlib_free(log->localPartyNumber);
|
|
strlib_free(log->remotePartyName[0]);
|
|
strlib_free(log->remotePartyName[1]);
|
|
strlib_free(log->remotePartyNumber[0]);
|
|
strlib_free(log->remotePartyNumber[1]);
|
|
strlib_free(log->altPartyNumber[0]);
|
|
strlib_free(log->altPartyNumber[1]);
|
|
|
|
calllogger_init_call_log(log);
|
|
}
|
|
|
|
void calllogger_print_call_log(cc_call_log_t *log)
|
|
{
|
|
static const char *fname = "calllogger_print_call_log";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
CCLOG_DEBUG("Remote ID %s:%s %s:%s\n LocalID %s:%s \n alt %s:%s\n",
|
|
log->remotePartyName[0], log->remotePartyNumber[0],
|
|
log->remotePartyName[1], log->remotePartyNumber[1],
|
|
log->localPartyName, log->localPartyNumber,
|
|
log->altPartyNumber[0], log->altPartyNumber[1] );
|
|
CCLOG_DEBUG("state %d \n Disp %d\n", log->callState, log->logDisp);
|
|
}
|
|
|
|
/**
|
|
* Call logger update to be called placed call num update
|
|
*/
|
|
void calllogger_setPlacedCallInfo (session_data_t *data)
|
|
{
|
|
static const char *fname = "calllogger_setPlacedCallInfo";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"updating placed number for session %x to %s:%s\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->sess_id,
|
|
data->cld_name, data->cld_number);
|
|
if ( data->call_log.logDisp == CC_LOGD_RCVD ) { return;}
|
|
data->call_log.remotePartyName[0] = strlib_copy(data->plcd_name);
|
|
data->call_log.remotePartyNumber[0] = strlib_copy(data->plcd_number);
|
|
data->call_log.logDisp = CC_LOGD_SENT;
|
|
data->call_log.startTime = time(NULL);
|
|
}
|
|
|
|
/**
|
|
* call logger api to be called for log disp update
|
|
*/
|
|
void calllogger_updateLogDisp (session_data_t *data)
|
|
{
|
|
static const char *fname = "calllogger_updateLogDisp";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"updating log disposition for session %x to %d\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->sess_id, data->log_disp);
|
|
data->call_log.logDisp = data->log_disp;
|
|
}
|
|
|
|
cc_boolean partyInfoPassedTheNumberFilter (cc_string_t partyString)
|
|
{
|
|
static const char *fname = "partyInfoPassedTheNumberFilter";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
// check if partyString is something we should not be logging at this point
|
|
// Uris: CfwdALL 105
|
|
// Conference 152
|
|
if (partyString && strlen(partyString) > 1 &&
|
|
(partyString[1] == 17 ||
|
|
partyString[1] == 91 ||
|
|
partyString[1] == 05 ||
|
|
partyString[1] == 18 ||
|
|
partyString[1] == 16 ||
|
|
partyString[1] == 52 )) {
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Filtering out the partyName=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), partyString);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* partyInfoPassedTheNameFilter
|
|
*
|
|
* @param partyString String
|
|
* @return boolean
|
|
*/
|
|
cc_boolean partyInfoPassedTheNameFilter(cc_string_t partyString) {
|
|
static const char *fname = "partyInfoPassedTheNameFilter";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
// If the name String has Conference, filter it out
|
|
if (partyString && strlen(partyString) > 1 &&
|
|
(partyString[1] == 52 || partyString[1] == 53)) {
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Filtering out the partyName=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), partyString);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static cc_string_t missedCallMask=NULL;
|
|
void calllogger_setMissedCallLoggingConfig(cc_string_t mask) {
|
|
static const char *fname = "calllogger_setMissedCallLoggingConfig";
|
|
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering... mask=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), mask);
|
|
if ( missedCallMask == NULL) {
|
|
missedCallMask = strlib_empty();
|
|
}
|
|
missedCallMask = strlib_update(missedCallMask, mask);
|
|
}
|
|
|
|
cc_boolean isMissedCallLoggingEnabled (unsigned int line)
|
|
{
|
|
static const char *fname = "isMissedCallLoggingEnabled";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering... mask=%s\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), missedCallMask);
|
|
if (missedCallMask == NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
if ((line > 0) && strlen(missedCallMask) > (line-1)) {
|
|
if ( missedCallMask[line-1] == '0' ) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void handlePlacedCall (session_data_t *data)
|
|
{
|
|
static const char *fname = "handlePlacedCall";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n",DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
|
|
//populate calling party if not already populated
|
|
if ( data->call_log.localPartyNumber == strlib_empty() ) {
|
|
data->call_log.localPartyNumber = strlib_update(data->call_log.localPartyNumber, data->clg_number);
|
|
data->call_log.localPartyName = strlib_update(data->call_log.localPartyName, data->clg_name);
|
|
}
|
|
|
|
// first update or update with the same number we update name and number
|
|
if ( data->call_log.remotePartyNumber[0] == strlib_empty() ||
|
|
(data->cld_number[0] != 0 && strncmp(data->call_log.remotePartyNumber[0],
|
|
data->cld_number, strlen(data->cld_number)) == 0 )) {
|
|
if ( partyInfoPassedTheNameFilter(data->cld_name) &&
|
|
partyInfoPassedTheNumberFilter(data->cld_number) )
|
|
data->call_log.remotePartyNumber[0] = strlib_update(data->call_log.remotePartyNumber[0], data->cld_number);
|
|
data->call_log.remotePartyName[0] = strlib_update(data->call_log.remotePartyName[0], data->cld_name);
|
|
}
|
|
|
|
// Start the duration count once the call reaches connected state.
|
|
if ( data->state == CONNECTED &&
|
|
data->call_log.startTime == 0 ) {
|
|
data->call_log.startTime = time(NULL);
|
|
}
|
|
|
|
if (data->state == ONHOOK ) {
|
|
// only set the duration if the call entered the connected state
|
|
if ( data->call_log.startTime != 0 ) {
|
|
data->call_log.duration = (cc_uint32_t) (time(NULL) - data->call_log.startTime);
|
|
} else {
|
|
data->call_log.startTime = time(NULL);
|
|
}
|
|
}
|
|
|
|
data->call_log.callState = data->state;
|
|
}
|
|
|
|
|
|
void handleMissedOrReceviedCall ( session_data_t *data )
|
|
{
|
|
static const char *fname = "handleMissedOrReceviedCall";
|
|
int line = GET_LINE_ID(data->sess_id);
|
|
cc_string_t localName = strlib_empty(), localNumber = strlib_empty();
|
|
cc_string_t remoteName = strlib_empty(), remoteNumber = strlib_empty();
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
|
|
if (data->type == CC_CALL_TYPE_INCOMING || data->type == CC_CALL_TYPE_FORWARDED ) {
|
|
localName = data->cld_name;
|
|
localNumber = data->cld_number;
|
|
remoteName = data->clg_name;
|
|
remoteNumber = data->clg_number;
|
|
} else {
|
|
localName = data->clg_name;
|
|
localNumber = data->clg_number;
|
|
remoteName = data->cld_name;
|
|
remoteNumber = data->cld_number;
|
|
}
|
|
|
|
if ( data->call_log.localPartyNumber == strlib_empty() ) {
|
|
data->call_log.localPartyNumber = strlib_update(data->call_log.localPartyNumber, localNumber);
|
|
data->call_log.localPartyName = strlib_update(data->call_log.localPartyName, localName);
|
|
}
|
|
|
|
// first update or update with the same number we update name and number
|
|
if ( data->call_log.remotePartyNumber[0] == strlib_empty() ||
|
|
(remoteNumber[0] != 0 && strncmp(data->call_log.remotePartyNumber[0],
|
|
remoteNumber, strlen(remoteNumber)) == 0 )) {
|
|
data->call_log.remotePartyNumber[0] = strlib_update(data->call_log.remotePartyNumber[0], remoteNumber);
|
|
data->call_log.altPartyNumber[0] = strlib_update(data->call_log.altPartyNumber[0], data->alt_number);
|
|
if (data->call_log.remotePartyName[0] == strlib_empty() ) {
|
|
data->call_log.remotePartyName[0] = strlib_update(data->call_log.remotePartyName[0], remoteName);
|
|
}
|
|
} else {
|
|
// since number doesn't match this is a new leg
|
|
data->call_log.remotePartyName[1] = strlib_update(data->call_log.remotePartyName[1], remoteName);
|
|
data->call_log.remotePartyNumber[1] = strlib_update(data->call_log.remotePartyNumber[1], remoteNumber);
|
|
data->call_log.altPartyNumber[1] = strlib_update(data->call_log.altPartyNumber[1], data->alt_number);
|
|
}
|
|
|
|
if ( data->state == ONHOOK ) {
|
|
if ( data->call_log.callState == RINGIN ) {
|
|
data->call_log.startTime = time(NULL);
|
|
if (isMissedCallLoggingEnabled(line)) {
|
|
data->call_log.logDisp = CC_LOGD_MISSED;
|
|
} else {
|
|
data->call_log.logDisp = CC_LOGD_DELETE;
|
|
}
|
|
data->call_log.startTime = time(NULL);
|
|
data->call_log.duration = 0; //missed call duration is 0
|
|
} else if ( data->call_log.startTime != 0 ){
|
|
//connected call going onhook update duration
|
|
data->call_log.duration = (cc_uint32_t) (time(NULL) - data->call_log.startTime);
|
|
}
|
|
}
|
|
|
|
if ( data->state == CONNECTED && data->call_log.startTime == 0 ) {
|
|
data->call_log.logDisp = CC_LOGD_RCVD;
|
|
data->call_log.startTime = time(NULL);
|
|
}
|
|
|
|
data->call_log.callState = data->state;
|
|
}
|
|
|
|
|
|
/**
|
|
* Call logger update to be called on attr or callinfo or state events
|
|
*/
|
|
void calllogger_update (session_data_t *data)
|
|
{
|
|
static const char *fname = "calllogger_update";
|
|
|
|
CCLOG_DEBUG(DEB_F_PREFIX"Entering...\n", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
|
if (data->call_log.logDisp == CC_LOGD_DELETE) {
|
|
CCLOG_DEBUG(DEB_F_PREFIX"log disposition set to delete. Ignoring call logging for sess_id=%x\n",
|
|
DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->sess_id);
|
|
}
|
|
|
|
if (data->call_log.logDisp == CC_LOGD_RCVD || data->call_log.logDisp == CC_LOGD_MISSED ||
|
|
data->type == CC_CALL_TYPE_INCOMING || data->type == CC_CALL_TYPE_FORWARDED ) {
|
|
handleMissedOrReceviedCall(data);
|
|
} else if ( data->call_log.logDisp == CC_LOGD_SENT ||
|
|
data->type == CC_CALL_TYPE_OUTGOING ) {
|
|
handlePlacedCall (data);
|
|
}
|
|
|
|
}
|