mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-15 08:29:45 +00:00
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3564 d0543943-73ff-0310-b7d9-9358b9ac24b2
260 lines
9.7 KiB
C++
260 lines
9.7 KiB
C++
/*
|
|
* 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 PddCDR class which handles formatting a CDR out to
|
|
* individual text files in a Perl Data Dumper format.
|
|
*
|
|
* pddcdr.cpp
|
|
*
|
|
*/
|
|
|
|
#include <switch.h>
|
|
#include "pddcdr.h"
|
|
|
|
PddCDR::PddCDR() : BaseCDR()
|
|
{
|
|
memset(formattedcallstartdate,0,100);
|
|
memset(formattedcallanswerdate,0,100);
|
|
memset(formattedcallenddate,0,100);
|
|
}
|
|
|
|
PddCDR::PddCDR(switch_mod_cdr_newchannel_t *newchannel) : BaseCDR(newchannel)
|
|
{
|
|
memset(formattedcallstartdate,0,100);
|
|
memset(formattedcallanswerdate,0,100);
|
|
memset(formattedcallenddate,0,100);
|
|
memset(formattedcalltransferdate,0,100);
|
|
|
|
if(newchannel != 0)
|
|
{
|
|
switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend;
|
|
memset(&tempcallstart,0,sizeof(tempcallstart));
|
|
memset(&tempcallanswer,0,sizeof(tempcallanswer));
|
|
memset(&tempcalltransfer,0,sizeof(tempcalltransfer));
|
|
memset(&tempcallend,0,sizeof(tempcallend));
|
|
convert_time(&tempcallstart, callstartdate);
|
|
convert_time(&tempcallanswer, callanswerdate);
|
|
convert_time(&tempcalltransfer, calltransferdate);
|
|
convert_time(&tempcallend, callenddate);
|
|
|
|
// Format the times
|
|
size_t retsizecsd, retsizecad, retsizectd, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
|
|
char format[] = "%Y-%m-%d %H:%M:%S";
|
|
switch_strftime(formattedcallstartdate,&retsizecsd,sizeof(formattedcallstartdate),format,&tempcallstart);
|
|
switch_strftime(formattedcallanswerdate,&retsizecad,sizeof(formattedcallanswerdate),format,&tempcallanswer);
|
|
switch_strftime(formattedcalltransferdate,&retsizectd,sizeof(formattedcalltransferdate),format,&tempcalltransfer);
|
|
switch_strftime(formattedcallenddate,&retsizeced,sizeof(formattedcallenddate),format,&tempcallend);
|
|
|
|
std::ostringstream ostring;
|
|
ostring << (callenddate/1000000);
|
|
std::string callenddate_forfile = ostring.str();
|
|
|
|
outputfile_name = outputfile_path;
|
|
outputfile_name.append(SWITCH_PATH_SEPARATOR);
|
|
outputfile_name.append(callenddate_forfile); // Make sorting a bit easier, kinda like Maildir does
|
|
outputfile_name.append(".");
|
|
outputfile_name.append(myuuid); // The goal is to have a resulting filename of "/path/to/myuuid"
|
|
outputfile_name.append(".pdd"); // .pdd - "perl data dumper"
|
|
bool repeat = 1;
|
|
process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel,repeat);
|
|
}
|
|
}
|
|
|
|
PddCDR::~PddCDR()
|
|
{
|
|
outputfile.close();
|
|
}
|
|
|
|
bool PddCDR::activated=0;
|
|
bool PddCDR::logchanvars=0;
|
|
bool PddCDR::connectionstate=0;
|
|
modcdr_time_convert_t PddCDR::convert_time = switch_time_exp_lt;
|
|
std::string PddCDR::outputfile_path;
|
|
std::list<std::string> PddCDR::chanvars_fixed_list;
|
|
std::list<std::string> PddCDR::chanvars_supp_list;
|
|
std::string PddCDR::display_name = "PddCDR - Perl Data Dumper CDR logger";
|
|
|
|
void PddCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
|
|
{
|
|
switch_console_printf(SWITCH_CHANNEL_LOG, "PddCDR::connect() - Loading configuration file.\n");
|
|
activated = 0; // Set it as inactive initially
|
|
connectionstate = 0; // Initialize it to false to show that we aren't yet connected.
|
|
|
|
if ((settings = switch_xml_child(cfg, "pddcdr")))
|
|
{
|
|
int count_config_params = 0; // Need to make sure all params are set before we load
|
|
for (param = switch_xml_child(settings, "param"); param; param = param->next)
|
|
{
|
|
char *var = (char *) switch_xml_attr_soft(param, "name");
|
|
char *val = (char *) switch_xml_attr_soft(param, "value");
|
|
|
|
if (!strcmp(var, "path"))
|
|
{
|
|
if(val != 0)
|
|
outputfile_path = val;
|
|
count_config_params++;
|
|
}
|
|
else if (!strcmp(var, "chanvars"))
|
|
{
|
|
if(val != 0)
|
|
{
|
|
std::string unparsed;
|
|
unparsed = val;
|
|
if(unparsed.size() > 0)
|
|
{
|
|
bool fixed = 0;
|
|
parse_channel_variables_xconfig(unparsed,chanvars_supp_list,fixed);
|
|
logchanvars=1;
|
|
}
|
|
}
|
|
}
|
|
else if (!strcmp(var, "chanvars_fixed"))
|
|
{
|
|
switch_console_printf(SWITCH_CHANNEL_LOG,"PddCDR has no need for a fixed or supplemental list of channel variables due to the nature of the format. Please use the setting parameter of \"chanvars\" instead and try again.\n");
|
|
}
|
|
else if (!strcmp(var, "chanvars_supp"))
|
|
{
|
|
switch_console_printf(SWITCH_CHANNEL_LOG,"PddCDR has no need for a fixed or supplemental list of channel variables due to the nature of the format. Please use the setting parameter of \"chanvars\" instead and try again.\n");
|
|
}
|
|
else if(!strcmp(var,"timezone"))
|
|
{
|
|
if(!strcmp(val,"utc"))
|
|
convert_time = switch_time_exp_gmt;
|
|
else if(!strcmp(val,"local"))
|
|
convert_time = switch_time_exp_lt;
|
|
else
|
|
{
|
|
switch_console_printf(SWITCH_CHANNEL_LOG,"Invalid configuration parameter for timezone. Possible values are utc and local. You entered: %s\nDefaulting to local.\n",val);
|
|
convert_time = switch_time_exp_lt;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(count_config_params > 0)
|
|
activated = 1;
|
|
else
|
|
switch_console_printf(SWITCH_CHANNEL_LOG,"PddCDR::connect(): You did not specify the minimum parameters for using this module. You must specify at least a path to have the records logged to.\n");
|
|
}
|
|
}
|
|
|
|
bool PddCDR::process_record()
|
|
{
|
|
outputfile.open(outputfile_name.c_str());
|
|
|
|
bool retval = 0;
|
|
if(!outputfile)
|
|
switch_console_printf(SWITCH_CHANNEL_LOG, "PddCDR::process_record(): Unable to open file %s to commit the call record to. Invalid path name, invalid permissions, or no space available?\n",outputfile_name.c_str());
|
|
else
|
|
{
|
|
// Format the call record and proceed from here...
|
|
outputfile << "$VAR1 = {" << std::endl;
|
|
outputfile << "\t\'callstartdate\' = \'" << callstartdate << "\'," << std::endl;
|
|
outputfile << "\t\'formattedcallstartdate\' = \'" << formattedcallstartdate << "\'," << std::endl;
|
|
outputfile << "\t\'callanswerdate\' = \'" << callanswerdate << "\'," << std::endl;
|
|
outputfile << "\t\'formattedcallanswerdate\' = \'" << formattedcallanswerdate << "\'," << std::endl;
|
|
outputfile << "\t\'calltransferdate\' = \'" << calltransferdate << "\'," << std::endl;
|
|
outputfile << "\t\'formattedcalltransferdate\' = \'" << formattedcalltransferdate << "\'," << std::endl;
|
|
outputfile << "\t\'callenddate\' = \'" << callenddate << "\'," << std::endl;
|
|
outputfile << "\t\'formatcallenddate\' = \'" << formattedcallenddate << "\'," << std::endl;
|
|
outputfile << "\t\'hangupcause\' = \'" << hangupcause_text << "\'," << std::endl;
|
|
outputfile << "\t\'hangupcausecode\' = \'" << hangupcause << "\'," << std::endl;
|
|
outputfile << "\t\'clid\' = \'" << clid << "\'," << std::endl;
|
|
outputfile << "\t\'originated\' = \'" << originated << "\'," << std::endl;
|
|
outputfile << "\t\'dialplan\' = \'" << dialplan << "\'," << std::endl;
|
|
outputfile << "\t\'myuuid\' = \'" << myuuid << "\'," << std::endl;
|
|
outputfile << "\t\'destuuid\' = \'" << destuuid << "\'," << std::endl;
|
|
outputfile << "\t\'src\' = \'" << src << "\'," << std::endl;
|
|
outputfile << "\t\'dst\' = \'" << dst << "\'," << std::endl;
|
|
outputfile << "\t\'srcchannel\' = \'" << srcchannel << "\'," << std::endl;
|
|
outputfile << "\t\'dstchannel\' = \'" << dstchannel << "\'," << std::endl;
|
|
outputfile << "\t\'ani\' = \'" << ani << "\'," << std::endl;
|
|
outputfile << "\t\'aniii\' = \'" << aniii << "\'," << std::endl;
|
|
outputfile << "\t\'network_addr\' = \'" << network_addr << "\'," << std::endl;
|
|
outputfile << "\t\'lastapp\' = \'" << lastapp << "\'," << std::endl;
|
|
outputfile << "\t\'lastdata\' = \'" << lastdata << "\'," << std::endl;
|
|
outputfile << "\t\'billusec\' = \'" << billusec << "\'," << std::endl;
|
|
outputfile << "\t\'disposition\' = \'" << disposition << "\'," << std::endl;
|
|
outputfile << "\t\'amaflags\' = \'" << amaflags << "\'," << std::endl;
|
|
|
|
// Now to process chanvars
|
|
outputfile << "\t\'chanvars\' => {" << std::endl;
|
|
if(chanvars_supp.size() > 0 )
|
|
{
|
|
std::map<std::string,std::string>::iterator iItr,iEnd;
|
|
for(iItr = chanvars_supp.begin(), iEnd = chanvars_supp.end() ; iItr != iEnd; iItr++)
|
|
outputfile << "\t\t\'" << iItr->first << "\' = \'" << iItr->second << "\'," << std::endl;
|
|
}
|
|
outputfile << "\t}," << std::endl << "};" << std::endl << std::endl;
|
|
retval = 1;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
bool PddCDR::is_activated()
|
|
{
|
|
return activated;
|
|
}
|
|
|
|
void PddCDR::tempdump_record()
|
|
{
|
|
|
|
}
|
|
|
|
void PddCDR::reread_tempdumped_records()
|
|
{
|
|
|
|
}
|
|
|
|
std::string PddCDR::get_display_name()
|
|
{
|
|
return display_name;
|
|
}
|
|
|
|
void PddCDR::disconnect()
|
|
{
|
|
activated = 0;
|
|
connectionstate = 0;
|
|
logchanvars = 0;
|
|
outputfile_path.clear();
|
|
chanvars_supp_list.clear();
|
|
switch_console_printf(SWITCH_CHANNEL_LOG,"Shutting down PddCDR... Done!");
|
|
}
|
|
|
|
AUTO_REGISTER_BASECDR(PddCDR);
|
|
|
|
/* For Emacs:
|
|
* Local Variables:
|
|
* mode:c++
|
|
* indent-tabs-mode:nil
|
|
* tab-width:4
|
|
* c-basic-offset:4
|
|
* End:
|
|
* For VIM:
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
*/
|