Author: cparker Date: Wed Feb 7 11:09:35 2007 New Revision: 4145 Added: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.cpp freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.h Removed: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr_radius/ Modified: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/Makefile Log: Added the mod_cdr radius instance, removed unused mod_cdr_radius directory Modified: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/Makefile ============================================================================== --- freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/Makefile (original) +++ freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/Makefile Wed Feb 7 11:09:35 2007 @@ -1,14 +1,35 @@ +<<<<<<< .mine + +======= +>>>>>>> .r4141 #CFLAGS += -DSWITCH_QUEUE_ENHANCED +<<<<<<< .mine +======= #LDFLAGS += -lcurl +>>>>>>> .r4141 CPPCC = g++ OBJS=cdrcontainer.o basecdr.o baseregistry.o pddcdr.o csvcdr.o xmlcdr.o sqlitecdr.o +<<<<<<< .mine +# uncomment to build radiuscdr +OBJS += radiuscdr.o +LDFLAGS += -lfreeradius-client + +# uncomment to build mysqlcdr +#OBJS += mysqlcdr.o +#CFLAGS += $(shell mysql_config --include) +#LDFLAGS += $(shell mysql_config --libs) + +# + +======= ifneq ($(shell which mysql_config),) CFLAGS += $(shell mysql_config --include) LDFLAGS += $(shell mysql_config --libs) OBJS += mysqlcdr.o endif +>>>>>>> .r4141 all: depends $(OBJS) $(MODNAME).$(DYNAMIC_LIB_EXTEN) depends: @@ -17,7 +38,6 @@ $(CPPCC) $(CFLAGS) -fPIC -c $(MODNAME).cpp -o $(MODNAME).o $(CPPCC) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(MODNAME).o $(OBJS) $(LDFLAGS) - %.o: %.cpp $(CPPCC) -Wall -Werror -fPIC $(CFLAGS) -c -o $@ $< Added: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.cpp ============================================================================== --- (empty file) +++ freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.cpp Wed Feb 7 11:09:35 2007 @@ -0,0 +1,343 @@ +/* + * 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> - Original CDR Class interface + * Chris Parker <cparker AT segv.org> - RADIUS CDR subclass + * + * Description: This C++ source file describes the RADIUS CDR class that handles processing CDRs to a + * RADIUS Server. + * + * This is the standard CSV module, and has a list of predefined variables to log out which can be + * added to, but never have the default ones removed. If you want to use one that allows you to explicity + * set all data variables to be logged and in what order, then this is not the class you want to use, and + * one will be coming in the future to do just that. + * + * radiuscdr.cpp + * + */ + +#include <switch.h> +#include "radiuscdr.h" +#include <string> + +RadiusCDR::RadiusCDR() : BaseCDR() +{ + memset(formattedcallstartdate,0,100); + memset(formattedcallanswerdate,0,100); + memset(formattedcallenddate,0,100); +} + +RadiusCDR::RadiusCDR(switch_mod_cdr_newchannel_t *newchannel) : BaseCDR(newchannel) +{ + memset(formattedcallstartdate,0,100); + memset(formattedcallanswerdate,0,100); + memset(formattedcalltransferdate,0,100); + memset(formattedcallenddate,0,100); + + if(newchannel != 0) + { + switch_time_exp_t tempcallstart, tempcallanswer, tempcalltransfer, tempcallend; + memset(&tempcallstart,0,sizeof(tempcallstart)); + memset(&tempcalltransfer,0,sizeof(tempcalltransfer)); + memset(&tempcallanswer,0,sizeof(tempcallanswer)); + memset(&tempcallend,0,sizeof(tempcallend)); + convert_time(&tempcallstart, callstartdate); + convert_time(&tempcallanswer, callanswerdate); + convert_time(&tempcalltransfer, calltransferdate); + convert_time(&tempcallend, callenddate); + + // Format the times + apr_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); + + if(chanvars_fixed_list.size() > 0) + process_channel_variables(chanvars_fixed_list,newchannel->channel); + + if(chanvars_supp_list.size() > 0) + process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel,repeat_fixed_in_supp); + } +} + +RadiusCDR::~RadiusCDR() +{ + +} + +std::string RadiusCDR::display_name = "RadiusCDR - The RADIUS CDR logger"; +bool RadiusCDR::activated=0; +bool RadiusCDR::connectionstate=0; +bool RadiusCDR::logchanvars=0; +std::list<std::string> RadiusCDR::chanvars_supp_list; +std::list<std::string> RadiusCDR::chanvars_fixed_list; +bool RadiusCDR::repeat_fixed_in_supp=0; +modcdr_time_convert_t RadiusCDR::convert_time = switch_time_exp_lt; +//char RadiusCDR::formattedcallstartdate[100] = ""; +//char RadiusCDR::formattedcallanswerdate[100] = ""; +//char RadiusCDR::formattedcalltransferdate[100] = ""; +//char RadiusCDR::formattedcallenddate[100] = ""; +char RadiusCDR::path_radiusclient_conf[255] = ""; +rc_handle *RadiusCDR::rh = NULL; +char RadiusCDR::accounting_server1[255] = ""; +int RadiusCDR::accounting_port1 = 1813; +char RadiusCDR::accounting_secret1[255] = ""; +//char RadiusCDR::accounting_server2 = ""; +//int RadiusCDR::accounting_port2 = 1813; +//char RadiusCDR::accounting_secret2 = ""; + +void RadiusCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param) +{ + switch_console_printf(SWITCH_CHANNEL_LOG, "[RadiusCDR] connect() - Loading configuration file.\n"); + activated = 0; // Set it as inactive initially + + if ((settings = switch_xml_child(cfg, "radiuscdr"))) + { + 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, "radiuscdr_conf")) + { + if(val != 0) { + strncpy(path_radiusclient_conf,val,strlen(val)); + count_config_params++; + } + } + + else if (!strcmp(var, "acct_server1")) + { + if(val != 0) { + strncpy(accounting_server1,val,strlen(val)); + } + } + else if (!strcmp(var, "acct_port1")) + { + if(val != 0) + accounting_port1 = atoi(val); + } + else if (!strcmp(var, "acct_secret1")) + { + if(val != 0) { + strncpy(accounting_secret1,val,strlen(val)); + } + } + else if (!strcmp(var, "chanvars_supp")) + { + 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")) + { + if(val != 0) + { + std::string unparsed; + unparsed = val; + if(unparsed.size() > 0) + { + bool fixed = 1; + parse_channel_variables_xconfig(unparsed,chanvars_fixed_list,fixed); + logchanvars=1; + } + } + } + } + + if( count_config_params > 0 && + (accounting_server1 != NULL && accounting_secret1 != NULL)) + { + if ((rh = rc_read_config(path_radiusclient_conf)) == NULL) { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed to initialize radius config\n"); + } else if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed to initialize radius dictionary\n"); + } else { + activated = 1; + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] activated\n"); + } + } else { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR]You did not specify the minimum parameters for using this module. You must specify at least one radius server to send records to.\n"); + } + } +} + +bool RadiusCDR::process_record() +{ + bool retval = 0; + UINT4 client_port = 0; + UINT4 status_type = PW_STATUS_STOP; + VALUE_PAIR *send = NULL; +// VALUE_PAIR *vp = NULL; +// DICT_VALUE *dval = NULL; + + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Processing Record: %s to %s\n", src, dst); + + if (rc_avpair_add(rh, &send, PW_ACCT_STATUS_TYPE, &status_type, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding Acct-Status-Type: to %d\n", status_type); + return -1; + } + if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_ID, myuuid, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding Acct-Session-ID: to %s\n", myuuid); + return -1; + } + if (rc_avpair_add(rh, &send, PW_USER_NAME, src, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding User-Name: to %s\n", src); + return -1; + } + if (rc_avpair_add(rh, &send, PW_CALLED_STATION_ID, dst, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding Called-Station-ID: to %s\n", dst); + return -1; + } + if (rc_avpair_add(rh, &send, PW_CALLING_STATION_ID, src, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding Calling-Station-ID: to %s\n", src); + return -1; + } + if (rc_avpair_add(rh, &send, PW_ACCT_SESSION_TIME, &billusec, -1, 0) == NULL) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Failed adding Acct-Session-Time: to %d\n", billusec); + return -1; + } + + // Format the call record and proceed from here... + //callstartdate + //formattedcallstartdate << "\",\""; + //callanswerdate << "\",\""; + //formattedcallanswerdate << "\",\""; + //calltransferdate << "\",\""; + //formattedcalltransferdate << "\",\""; + //callenddate << "\",\""; + //formattedcallenddate << "\",\""; + //hangupcause_text << "\",\""; + //hangupcause << "\",\""; + //clid << "\",\""; + + + //originated << "\",\""; + //dialplan << "\",\""; + //myuuid << "\",\""; + //destuuid << "\",\""; + //src << "\",\""; + //dst << "\",\""; + //srcchannel << "\",\""; + //dstchannel << "\",\""; + //ani << "\",\""; + //aniii << "\",\""; + //network_addr << "\",\""; + //lastapp << "\",\""; + //lastdata << "\",\""; + //billusec << "\",\""; + //disposition << "\",\""; + //amaflags << "\""; + + // Now to process chanvars, fixed ones first + //if(chanvars_fixed.size() > 0 ) + //{ + // std::list<std::pair<std::string,std::string> >::iterator iItr, iEnd; + // for(iItr = chanvars_fixed.begin(), iEnd = chanvars_fixed.end(); iItr != iEnd; iItr++) + // //",\"" << iItr->second << "\""; + //} + + //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++) + // //",\"" << iItr->first << "=" << iItr->second << "\""; + //} + //std::endl; + + if(rc_acct(rh, client_port, send) == OK_RC) + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Accounting OK: %s to %s\n", src, dst); + retval = 1; + } + else + { + switch_console_printf(SWITCH_CHANNEL_LOG,"[RadiusCDR] Accounting Failed: %s to %s\n", src, dst); + retval = -1; + } + rc_avpair_free(send); + return retval; +} + +bool RadiusCDR::is_activated() +{ + return activated; +} + +void RadiusCDR::tempdump_record() +{ + +} + +void RadiusCDR::reread_tempdumped_records() +{ + +} + +std::string RadiusCDR::get_display_name() +{ + return display_name; +} + +void RadiusCDR::disconnect() +{ + activated = 0; + logchanvars = 0; + repeat_fixed_in_supp = 0; + chanvars_fixed_list.clear(); + chanvars_supp_list.clear(); + switch_console_printf(SWITCH_CHANNEL_LOG,"Shutting down RadiusCDR... Done!\n"); +} + +AUTO_REGISTER_BASECDR(RadiusCDR); + +/* 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: + */ Added: freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.h ============================================================================== --- (empty file) +++ freeswitch/branches/cparker/src/mod/event_handlers/mod_cdr/radiuscdr.h Wed Feb 7 11:09:35 2007 @@ -0,0 +1,92 @@ +/* + * 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> + * Chris Parker <cparker AT segv.org> + * + * Description: This C++ header file describes the RadiusCDR class. + * + * radiuscdr.h + * + */ + +#include "baseregistry.h" +#include <switch.h> +#include <list> +#include <freeradius-client.h> + +#ifndef RADIUSCDR +#define RADIUSCDR + +class RadiusCDR : public BaseCDR { + public: + RadiusCDR(); + RadiusCDR(switch_mod_cdr_newchannel_t *newchannel); + //RadiusCDR(const RadiusCDR& copyFrom); + virtual ~RadiusCDR(); + virtual bool process_record(); + virtual void connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param); // connect and disconnect need to be static because we're persisting connections until shutdown + virtual void disconnect(); + virtual bool is_activated(); + virtual void tempdump_record(); + virtual void reread_tempdumped_records(); + virtual std::string get_display_name(); + + private: + static std::string display_name; + static bool activated; // Is this module activated? + static bool connectionstate; // What is the status of the connection? + static bool logchanvars; + static std::list<std::string> chanvars_fixed_list; // Normally this would be used, but not in this class + static std::list<std::string> chanvars_supp_list; // This will hold the list for all chanvars here + static bool repeat_fixed_in_supp; + static modcdr_time_convert_t convert_time; + char formattedcallstartdate[100]; + char formattedcallanswerdate[100]; + char formattedcalltransferdate[100]; + char formattedcallenddate[100]; + // radius vars + static char path_radiusclient_conf[255]; + static rc_handle *rh; + static char accounting_server1[255]; + static int accounting_port1; + static char accounting_secret1[255]; + //static char accounting_server2[255]; + //static int accounting_port2; + //static char accounting_secret2[255]; +}; + +#endif + +/* 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: + */