2006-07-24 15:19:05 +00:00
/*
* FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application Call Detail Recorder module
* Copyright 2006 , Author : Yossi Neiman of Cartis Solutions , Inc . < freeswitch AT cartissolutions . com >
*
* Version : MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
* http : //www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , either express or implied . See the License
* for the specific language governing rights and limitations under the
* License .
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft - Switch Application Call Detail Recorder module
*
* The Initial Developer of the Original Code is
* Yossi Neiman < freeswitch AT cartissolutions . com >
* Portions created by the Initial Developer are Copyright ( C )
* the Initial Developer . All Rights Reserved .
*
* Contributor ( s ) :
*
* Yossi Neiman < freeswitch AT cartissolutions . com >
*
* Description : This C + + source file describes the BaseCDR class that all other CDR classes inherit from .
* It handles the bulk of the processing of data from the switch_channel_t objects .
*
* basecdr . cpp
*
*/
# include "basecdr.h"
# include <iostream>
# include <string>
# include <cstring>
# include <switch.h>
BaseCDR : : BaseCDR ( )
{
callstartdate = 0 ;
callanswerdate = 0 ;
callenddate = 0 ;
strncpy ( clid , " Unknown " , 7 ) ;
strncpy ( src , " -1 " , 2 ) ;
strncpy ( dst , " -1 " , 2 ) ;
strncpy ( srcchannel , " -1 " , 2 ) ;
strncpy ( dstchannel , " -1 " , 2 ) ;
strncpy ( lastapp , " -1 " , 2 ) ;
billusec = 0 ;
disposition = 0 ;
amaflags = 0 ;
errorstate = 0 ;
}
BaseCDR : : BaseCDR ( switch_mod_cdr_newchannel_t * newchannel )
{
if ( newchannel ! = 0 )
{
2006-07-27 17:05:27 +00:00
errorstate = 0 ;
2006-07-24 15:19:05 +00:00
memset ( clid , 0 , 80 ) ;
memset ( dialplan , 0 , 80 ) ;
memset ( myuuid , 0 , 37 ) ;
memset ( destuuid , 0 , 37 ) ;
memset ( dialplan , 0 , 80 ) ;
memset ( & hangupcause , 0 , sizeof ( hangupcause ) ) ;
hangupcause_text = 0 ;
memset ( src , 0 , 80 ) ;
memset ( dst , 0 , 80 ) ;
memset ( srcchannel , 0 , 80 ) ;
memset ( dstchannel , 0 , 80 ) ;
memset ( network_addr , 0 , 40 ) ;
memset ( ani , 0 , 80 ) ;
memset ( ani2 , 0 , 80 ) ;
memset ( lastapp , 0 , 80 ) ;
memset ( lastdata , 0 , 255 ) ;
coresession = newchannel - > session ;
callstartdate = newchannel - > timetable - > created ;
callanswerdate = newchannel - > timetable - > answered ;
callenddate = newchannel - > timetable - > hungup ;
if ( newchannel - > callerprofile - > caller_id_name ! = 0 )
{
strncpy ( clid , newchannel - > callerprofile - > caller_id_name , strlen ( newchannel - > callerprofile - > caller_id_name ) ) ;
2006-07-27 17:05:27 +00:00
strncat ( clid , " < " , 2 ) ;
2006-07-24 15:19:05 +00:00
if ( newchannel - > callerprofile - > caller_id_number ! = 0 )
strncat ( clid , newchannel - > callerprofile - > caller_id_number , strlen ( clid ) + strlen ( newchannel - > callerprofile - > caller_id_number ) ) ;
2006-07-27 17:05:27 +00:00
strncat ( clid , " > " , 1 ) ;
2006-07-24 15:19:05 +00:00
}
// Get the ANI information if it's set
if ( newchannel - > callerprofile - > ani ! = 0 )
strncpy ( ani , newchannel - > callerprofile - > ani , strlen ( newchannel - > callerprofile - > ani ) ) ;
if ( newchannel - > callerprofile - > ani2 ! = 0 )
strncpy ( ani2 , newchannel - > callerprofile - > ani2 , strlen ( newchannel - > callerprofile - > ani2 ) ) ;
if ( newchannel - > callerprofile - > dialplan ! = 0 )
strncpy ( dialplan , newchannel - > callerprofile - > dialplan , strlen ( newchannel - > callerprofile - > dialplan ) ) ;
if ( newchannel - > callerprofile - > network_addr ! = 0 )
strncpy ( network_addr , newchannel - > callerprofile - > network_addr , strlen ( newchannel - > callerprofile - > network_addr ) ) ;
2006-07-27 17:05:27 +00:00
2006-07-24 15:19:05 +00:00
originated = newchannel - > originate ;
if ( newchannel - > originateprofile - > uuid ! = 0 )
strncpy ( destuuid , newchannel - > originateprofile - > uuid , strlen ( newchannel - > originateprofile - > uuid ) ) ;
// We still need to check if this is originated or not
if ( originated = = 0 )
{
if ( newchannel - > callerprofile - > destination_number ! = 0 )
strncpy ( src , newchannel - > callerprofile - > destination_number , strlen ( newchannel - > callerprofile - > destination_number ) ) ;
if ( newchannel - > callerprofile - > caller_id_number ! = 0 )
strncpy ( dst , newchannel - > callerprofile - > caller_id_number , strlen ( newchannel - > callerprofile - > caller_id_number ) ) ;
if ( newchannel - > originateprofile - > chan_name ! = 0 )
strncpy ( dstchannel , newchannel - > originateprofile - > chan_name , strlen ( newchannel - > originateprofile - > chan_name ) ) ;
}
else
{
if ( newchannel - > callerprofile - > caller_id_number ! = 0 )
strncpy ( src , newchannel - > callerprofile - > caller_id_number , strlen ( newchannel - > callerprofile - > caller_id_number ) ) ;
if ( newchannel - > callerprofile - > destination_number ! = 0 )
strncpy ( dst , newchannel - > callerprofile - > destination_number , strlen ( newchannel - > callerprofile - > destination_number ) ) ;
if ( newchannel - > originateprofile - > chan_name ! = 0 )
strncpy ( dstchannel , newchannel - > originateprofile - > chan_name , strlen ( newchannel - > originateprofile - > chan_name ) ) ;
}
strncpy ( myuuid , newchannel - > callerprofile - > uuid , strlen ( newchannel - > callerprofile - > uuid ) ) ;
strncpy ( srcchannel , newchannel - > callerprofile - > chan_name , strlen ( newchannel - > callerprofile - > chan_name ) ) ;
if ( switch_channel_test_flag ( newchannel - > channel , CF_ANSWERED ) )
{
disposition = 1 ;
billusec = newchannel - > timetable - > hungup - newchannel - > timetable - > answered ;
}
else
{
disposition = 0 ;
billusec = 0 ;
}
// What was the hangup cause?
hangupcause = switch_channel_get_cause ( newchannel - > channel ) ;
hangupcause_text = switch_channel_cause2str ( hangupcause ) ;
if ( newchannel - > callerextension ! = 0 )
if ( newchannel - > callerextension - > last_application ! = 0 )
{
if ( newchannel - > callerextension - > last_application - > application_name ! = 0 )
strncpy ( lastapp , newchannel - > callerextension - > last_application - > application_name , strlen ( newchannel - > callerextension - > last_application - > application_name ) ) ;
if ( newchannel - > callerextension - > last_application - > application_data ! = 0 )
strncpy ( lastdata , newchannel - > callerextension - > last_application - > application_data , strlen ( newchannel - > callerextension - > last_application - > application_data ) ) ;
}
amaflags = 0 ;
}
}
BaseCDR : : ~ BaseCDR ( )
{
}
/* bool fixed is for checking if this is the fixed or supplemental list */
void BaseCDR : : parse_channel_variables_xconfig ( std : : string & unparsed , std : : list < std : : string > & chanvarlist , bool fixed )
{
std : : string tempstring ;
for ( std : : string : : size_type i = 0 , j = 0 ; j ! = std : : string : : npos ; )
{
j = unparsed . find ( ' , ' , i ) ;
if ( j > 0 )
{
tempstring = unparsed . substr ( i , ( j - i ) ) ;
chanvarlist . push_back ( tempstring ) ;
i = j + 1 ;
}
else
{
tempstring = unparsed . substr ( i ) ;
chanvarlist . push_back ( tempstring ) ;
}
}
// Now we need to clean up in case somebody put in a '*' in the chanvars fixed list
std : : list < std : : string > : : iterator iBeg , iItr , iEnd ;
iBeg = chanvarlist . begin ( ) ;
iEnd = chanvarlist . end ( ) ;
bool exitcode = 1 ;
for ( iItr = chanvarlist . begin ( ) ; iItr ! = iEnd & & exitcode ; )
{
if ( iItr - > find ( ' * ' , 0 ) ! = std : : string : : npos )
{
if ( fixed )
{
switch_console_printf ( SWITCH_CHANNEL_LOG , " Wildcards are not allow in the fixed chanvars list. Item removed. \n " ) ;
iItr = chanvarlist . erase ( iItr ) ;
}
else
{
if ( chanvarlist . size ( ) > 1 )
chanvarlist . clear ( ) ;
std : : string all = " * " ;
chanvarlist . push_back ( all ) ;
exitcode = 0 ;
}
}
else
iItr + + ;
}
}
void BaseCDR : : parse_channel_variables_xconfig ( std : : string & unparsed , std : : list < std : : string > & chanvarlist , std : : vector < switch_mod_cdr_sql_types_t > & chanvars_fixed_types )
{
bool fixed = 1 ;
std : : string tempstring , tempstring2 ;
switch_mod_cdr_sql_types_t sql_type ;
parse_channel_variables_xconfig ( unparsed , chanvarlist , fixed ) ;
std : : list < std : : string > tempchanvarlist ; // = chanvarlist;
std : : list < std : : string > : : iterator iEnd , iItr ;
for ( iItr = chanvarlist . begin ( ) , iEnd = chanvarlist . end ( ) ; iItr ! = iEnd ; iItr + + )
{
sql_type = CDR_STRING ;
std : : string : : size_type i = 0 , j = 0 ;
j = iItr - > find ( ' = ' , i ) ;
if ( j > 0 )
{
tempstring = iItr - > substr ( i , ( j - i ) ) ;
i = j + 1 ;
tempstring2 = iItr - > substr ( i ) ;
if ( tempstring2 . size ( ) = = 1 )
{
switch ( tempstring2 [ 0 ] )
{
case ' I ' :
case ' i ' :
sql_type = CDR_INTEGER ;
break ;
case ' S ' :
case ' s ' :
sql_type = CDR_STRING ;
break ;
case ' D ' :
case ' d ' :
sql_type = CDR_DOUBLE ;
break ;
case ' T ' :
case ' t ' :
sql_type = CDR_TINY ;
break ;
default :
switch_console_printf ( SWITCH_CHANNEL_LOG , " Valid fixed channel variable types are x (decimal), d (double), i (integer), t (tiny), s (string). You tried to give a type of %s to chanvar %s. \n Reverting this chanvar type to a string type. \n " , tempstring2 . c_str ( ) , tempstring . c_str ( ) ) ;
sql_type = CDR_STRING ;
}
}
else
{
switch_console_printf ( SWITCH_CHANNEL_LOG , " Valid fixed channel variable types are x (decimal), d (double), i (integer), t (tiny), s (string). You tried to give a type of %s to chanvar %s. \n Reverting this chanvar type to a string type. \n " , tempstring2 . c_str ( ) , tempstring . c_str ( ) ) ;
sql_type = CDR_STRING ;
}
}
else
{
switch_console_printf ( SWITCH_CHANNEL_LOG , " No parameter set, for channel variable %s, using default type of string. \n " , iItr - > c_str ( ) ) ;
sql_type = CDR_STRING ;
tempstring = * iItr ;
}
tempchanvarlist . push_back ( tempstring ) ;
chanvars_fixed_types . push_back ( sql_type ) ;
}
chanvarlist . clear ( ) ;
chanvarlist = tempchanvarlist ;
}
// This is for processing the fixed channel variables
void BaseCDR : : process_channel_variables ( const std : : list < std : : string > & stringlist , switch_channel_t * channel )
{
std : : list < std : : string > : : const_iterator iItr , iEnd ;
iEnd = stringlist . end ( ) ;
for ( iItr = stringlist . begin ( ) ; iItr ! = iEnd ; iItr + + )
{
std : : vector < char > tempstringvector ( iItr - > begin ( ) , iItr - > end ( ) ) ;
tempstringvector . push_back ( ' \0 ' ) ;
char * tempstring = & tempstringvector [ 0 ] ;
char * tempvariable ;
tempvariable = switch_channel_get_variable ( channel , tempstring ) ;
std : : pair < std : : string , std : : string > temppair ;
temppair . first = * iItr ;
if ( tempvariable ! = 0 )
temppair . second = tempvariable ;
chanvars_fixed . push_back ( temppair ) ;
}
}
// This one is for processing of supplemental chanvars
void BaseCDR : : process_channel_variables ( const std : : list < std : : string > & stringlist , const std : : list < std : : string > & fixedlist , switch_channel_t * channel , bool repeat )
{
if ( stringlist . front ( ) = = " * " )
{
switch_hash_index_t * hi ;
void * val ;
const void * var ;
switch_memory_pool_t * sessionpool ;
sessionpool = switch_core_session_get_pool ( coresession ) ;
for ( hi = switch_channel_variable_first ( channel , sessionpool ) ; hi ; hi = switch_hash_next ( hi ) )
{
switch_hash_this ( hi , & var , 0 , & val ) ;
std : : string tempstring_first , tempstring_second ;
tempstring_first = ( char * ) var ;
tempstring_second = ( char * ) val ;
chanvars_supp [ tempstring_first ] = tempstring_second ;
}
}
else
{
std : : list < std : : string > : : const_iterator iItr , iEnd ;
iEnd = stringlist . end ( ) ;
for ( iItr = stringlist . begin ( ) ; iItr ! = iEnd ; iItr + + )
{
std : : vector < char > tempstringvector ( iItr - > begin ( ) , iItr - > end ( ) ) ;
tempstringvector . push_back ( ' \0 ' ) ;
char * tempstring = & tempstringvector [ 0 ] ;
char * tempvariable ;
tempvariable = switch_channel_get_variable ( channel , tempstring ) ;
if ( tempvariable ! = 0 )
chanvars_supp [ * iItr ] = tempvariable ;
}
}
if ( ! repeat )
{
std : : map < std : : string , std : : string > : : iterator MapItr ;
std : : list < std : : string > : : const_iterator iItr , iEnd ;
for ( iItr = fixedlist . begin ( ) , iEnd = fixedlist . end ( ) ; iItr ! = iEnd ; iItr + + )
{
MapItr = chanvars_supp . find ( * iItr ) ;
if ( MapItr ! = chanvars_supp . end ( ) )
chanvars_supp . erase ( MapItr ) ;
}
}
}