[Freeswitch-svn] [commit] r3093 - in freeswitch/trunk: . src/mod/event_handlers/mod_cdr

Freeswitch SVN mikej at freeswitch.org
Wed Oct 18 23:51:46 EDT 2006


Author: mikej
Date: Wed Oct 18 23:51:46 2006
New Revision: 3093

Added:
   freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.cpp
   freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.h
Modified:
   freeswitch/trunk/AUTHORS
   freeswitch/trunk/src/mod/event_handlers/mod_cdr/Makefile
   freeswitch/trunk/src/mod/event_handlers/mod_cdr/README
   freeswitch/trunk/src/mod/event_handlers/mod_cdr/schema.sql

Log:
add XmlCDR (like pddcdr, but xml format).  Thanks ken for another great contribution.

Modified: freeswitch/trunk/AUTHORS
==============================================================================
--- freeswitch/trunk/AUTHORS	(original)
+++ freeswitch/trunk/AUTHORS	Wed Oct 18 23:51:46 2006
@@ -27,6 +27,7 @@
  Stefan Knoblich - Various patches and support.  Thanks.
  Justin Unger - <justinunger at gmail dot com> Lots of help with patches and SIP testing. Thanks! 
  Paul D. Tinsley - Various patches and support. <pdt at jackhammer.org>
+ Ken Rice of Asteria Solutions Group, INC <ken AT asteriasgi.com> - xmlcdr, sofia improvements, load testing.
 
 A big THANK YOU goes to:
 

Modified: freeswitch/trunk/src/mod/event_handlers/mod_cdr/Makefile
==============================================================================
--- freeswitch/trunk/src/mod/event_handlers/mod_cdr/Makefile	(original)
+++ freeswitch/trunk/src/mod/event_handlers/mod_cdr/Makefile	Wed Oct 18 23:51:46 2006
@@ -3,7 +3,7 @@
 LDFLAGS += $(shell mysql_config --libs)
 
 CPPCC = g++
-OBJS=cdrcontainer.o basecdr.o baseregistry.o mysqlcdr.o pddcdr.o csvcdr.o
+OBJS=cdrcontainer.o basecdr.o baseregistry.o mysqlcdr.o pddcdr.o csvcdr.o xmlcdr.o
 
 all:	depends $(OBJS) $(MODNAME).$(DYNAMIC_LIB_EXTEN)
 

Modified: freeswitch/trunk/src/mod/event_handlers/mod_cdr/README
==============================================================================
--- freeswitch/trunk/src/mod/event_handlers/mod_cdr/README	(original)
+++ freeswitch/trunk/src/mod/event_handlers/mod_cdr/README	Wed Oct 18 23:51:46 2006
@@ -59,6 +59,21 @@
 		<param name="chanvars_supp" value=""/> value is a comma separated list of supplemental channel variables to log.  Can be a wildcard (*) (optional)
 		<param name="chanvars_supp_repeat_fixed" value=""/> value is 0 for no, 1 for yes, and determines whether or not to repeat any of the fixed channel variables as key / value pairs in the chanvars table.
 
+Class:		OdbcCDR, located in odbccdr.h and odbccdr.cpp
+		This class logs the call detail record to an ODBC database using prepared
+		statements.  This class is similar to MysqlCDR in that the fixed channel variables are treated as additional columns on the main freeswitchcdr database table for improved normalization of the database.  As such, you need to specify the format of each fixed channel variable as well.  If you do not specify, it will default to a varchar column type, and will not execute if the table schema does not match.  Therefore it is very important to make sure that any fixed channel variables you log exist as columns on the table.  The supplemental channel variables are stored in a separate table using a key / value pair linking to the myuuid of the call.  Recommended to use at least one other logger in conjuction with this one just to be on the safe side, as failover handling of errors to write to the db are not yet implemented, and therefore there is a risk of data loss if the database connection is lost entirely (it will be limited to only those records created at the time of the loss of connection) or some other fatal error is encountered.  Additionally, since there is no uniform method to handling columns of type sequence/autoincrement/autonumber in the rdbms world, it should be noted that each row in the chanvars (supplemental channel variables) table will cost 36 bytes for the myuuid to be posted to it instead of 8 bytes for a bigint as in MysqlCDR.
+Configuration:  Section <odbccdr>
+		<param name="dsn" value=""/> - Not yet implemented, but meant for future use in ease of config
+		<param name="hostname" value=""/> - The hostname or IP of the backend server
+		<param name="username" value=""/> - The username used to authenticate to the backend server
+		<param name="password" value=""/> - The password used to authenticate to the backend server
+		<param name="dbname" value=""/> - The database to use for logging
+		<param name="main_db_table" value=""/> - Optional: the name of the main logging table (defaults to freeswitchcdr)
+		<param name="supp_chanvars_db_table" value=""/> - Optional: the name of the supplemental chanvars table (defaults to chanvars)
+		<param name="chanvars_fixed" value=""/> Is a comma separated list of key=type pairs.  Types are x for decimal, s for string (varchar), d for double, i for integer, t for tiny.  If no type is provided, it defaults that column to string (varchar).  It cannot accept wildcards (*).  (optional)
+		<param name="chanvars_supp" value=""/> value is a comma separated list of supplemental channel variables to log.  Can be a wildcard (*) (optional)
+		<param name="chanvars_supp_repeat_fixed" value=""/> value is 0 for no, 1 for yes, and determines whether or not to repeat any of the fixed channel variables as key / value pairs in the chanvars table.
+		
 FAQ:
 
 Q: Why C++?
@@ -69,6 +84,9 @@
 
 Q: What would an example configuration look like?
 A: Here is an excerpt from the freeswitch XML configuration file:
+
+Q: What happened to the ani2 field?
+A: Oops, you caught us.  The real name for is it aniii.  You will need to update any database schemas or external handlers for this change.
 
 	<configuration name="mod_cdr.conf" description="CDR Configuration">
 		<pddcdr>

Modified: freeswitch/trunk/src/mod/event_handlers/mod_cdr/schema.sql
==============================================================================
--- freeswitch/trunk/src/mod/event_handlers/mod_cdr/schema.sql	(original)
+++ freeswitch/trunk/src/mod/event_handlers/mod_cdr/schema.sql	Wed Oct 18 23:51:46 2006
@@ -8,7 +8,7 @@
 	src varchar(80) NOT NULL,
 	dst varchar(80) NOT NULL,
 	ani varchar(80) default "",
-	ani2 varchar(80) default "",
+	aniii varchar(80) default "",
 	dialplan varchar(80) default "",
 	myuuid char(36) NOT NULL,
 	destuuid char(36) NOT NULL,
@@ -19,13 +19,7 @@
 	billusec bigint default 0,
 	disposition tinyint default 0, /* 0 = Busy or Unanswered, 1 = Answered */
 	hangupcause int default 0,
-	amaflags tinyint default 0,
-	/*
-	This section not needed, because it was an old asteriskism.  A chan_var table is to replace it perhaps.
-	accountcode varchar(80) default "",
-	uniqueid varchar(32) default "",
-	userfield varchar(255) default ""
-	*/
+	amaflags tinyint default 0
 );
 
 create index myuuid_index on freeswitchcdr (myuuid);
@@ -37,4 +31,4 @@
 	varvalue varchar(255) default ""
 );
 
-create index callid_index on chanvars(callid,varname);
\ No newline at end of file
+create index callid_index on chanvars(callid,varname);

Added: freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.cpp
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.cpp	Wed Oct 18 23:51:46 2006
@@ -0,0 +1,221 @@
+/*
+ * 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>
+ * Ken Rice of Asteria Solutions Group, INC <ken AT asteriasgi.com>
+ * 
+ * Description: This C++ source file describes the XmlCDR class which handles formatting a CDR out to
+ * individual text files in a XML format.
+ *
+ * xmlcdr.cpp
+ *
+ */
+
+#include <switch.h>
+#include "xmlcdr.h"
+
+XmlCDR::XmlCDR() : BaseCDR()
+{
+	memset(formattedcallstartdate,0,100);
+	memset(formattedcallanswerdate,0,100);
+	memset(formattedcallenddate,0,100);
+}
+
+XmlCDR::XmlCDR(switch_mod_cdr_newchannel_t *newchannel) : BaseCDR(newchannel)
+{
+	memset(formattedcallstartdate,0,100);
+	memset(formattedcallanswerdate,0,100);
+	memset(formattedcallenddate,0,100);
+	
+	if(newchannel != 0)
+	{
+		switch_time_exp_t tempcallstart, tempcallanswer, tempcallend;
+		memset(&tempcallstart,0,sizeof(tempcallstart));
+		memset(&tempcallanswer,0,sizeof(tempcallanswer));
+		memset(&tempcallend,0,sizeof(tempcallend));
+		switch_time_exp_lt(&tempcallstart, callstartdate);
+		switch_time_exp_lt(&tempcallanswer, callanswerdate);
+		switch_time_exp_lt(&tempcallend, callenddate);
+		
+		// Format the times
+		size_t retsizecsd, retsizecad, 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(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(".xml");  // .xml - "XML Data Dumper"
+	
+		outputfile.open(outputfile_name.c_str());
+	
+		bool repeat = 1;
+		process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel,repeat);
+	}
+}
+
+XmlCDR::~XmlCDR()
+{
+	outputfile.close();	
+}
+
+bool XmlCDR::activated=0;
+bool XmlCDR::logchanvars=0;
+bool XmlCDR::connectionstate=0;
+std::string XmlCDR::outputfile_path;
+std::list<std::string> XmlCDR::chanvars_fixed_list;
+std::list<std::string> XmlCDR::chanvars_supp_list;
+
+void XmlCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
+{
+	switch_console_printf(SWITCH_CHANNEL_LOG, "XmlCDR::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, "xmlcdr"))) 
+	{
+		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,"XmlCDR 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,"XmlCDR 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");
+			}
+		}
+		
+		if(count_config_params > 0)
+			activated = 1;
+		else
+			switch_console_printf(SWITCH_CHANNEL_LOG,"XmlCDR::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 XmlCDR::process_record()
+{
+	bool retval = 0;
+	if(!outputfile)
+		switch_console_printf(SWITCH_CHANNEL_LOG, "XmlCDR::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
+	{
+		switch_console_printf(SWITCH_CHANNEL_LOG, "XmlCDR::process_record():  Preping the CDR to %s.\n",outputfile_name.c_str());
+		// Format the call record and proceed from here...
+		outputfile << "<?xml version=\"1.0\"?>" << std::endl;
+		outputfile << "<document type=\"freeswitch-cdr/xml\">" << std::endl;
+		outputfile << "\t<callstartdate data=\"" << callstartdate << "\" />" << std::endl;
+		outputfile << "\t<callanswerdate data=\"" << callanswerdate << "\" />" << std::endl;
+		outputfile << "\t<callenddate data=\"" << callenddate << "\" />" << std::endl;
+		outputfile << "\t<hangupcause data=\"" << hangupcause_text << "\" />" << std::endl;
+		outputfile << "\t<hangupcausecode data=\"" << hangupcause << "\" />" << std::endl;
+		outputfile << "\t<clid data=\"" << clid << "\" />" << std::endl;
+		outputfile << "\t<originated data=\"" << originated << "\" />" << std::endl;
+		outputfile << "\t<dialplan data=\"" << dialplan << "\" />" << std::endl;
+		outputfile << "\t<myuuid data=\"" << myuuid << "\" />" << std::endl;
+		outputfile << "\t<destuuid data=\"" << destuuid << "\" />" << std::endl;
+		outputfile << "\t<src data=\"" << src << "\" />" << std::endl;
+		outputfile << "\t<dst data=\"" << dst << "\" />" << std::endl;
+		outputfile << "\t<srcchannel data=\"" << srcchannel << "\" />" << std::endl;
+		outputfile << "\t<dstchannel data=\"" << dstchannel << "\" />" << std::endl;
+		outputfile << "\t<ani data=\"" << ani << "\" />" << std::endl;
+		outputfile << "\t<aniii data=\"" << aniii << "\" />" << std::endl;
+		outputfile << "\t<network_addr data=\"" << network_addr << "\" />" << std::endl;
+		outputfile << "\t<lastapp data=\"" << lastapp << "\" />" << std::endl;
+		outputfile << "\t<lastdata data=\"" << lastdata << "\" />" << std::endl;
+		outputfile << "\t<billusec data=\"" << billusec << "\" />" << std::endl;
+		outputfile << "\t<disposition data=\"" << disposition << "\" />" << std::endl;
+		outputfile << "\t<amaflags data=\"" << 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<variable name=\"" << iItr->first << "\" data= \"" << iItr->second << "\" />" << std::endl;
+		}
+		outputfile << "\t</chanvars>" << std::endl << "</document>" << std::endl << std::endl;
+
+		switch_console_printf(SWITCH_CHANNEL_LOG, "XmlCDR::process_record():  Dumping the CDR to %s.\n",outputfile_name.c_str());
+		retval = 1;
+	}
+	
+	return retval;
+}
+
+bool XmlCDR::is_activated()
+{
+	return activated;
+}
+
+void XmlCDR::tempdump_record()
+{
+
+}
+
+void XmlCDR::reread_tempdumped_records()
+{
+
+}
+
+void XmlCDR::disconnect()
+{
+	switch_console_printf(SWITCH_CHANNEL_LOG,"Shutting down XmlCDR...  Done!");	
+}
+
+AUTO_REGISTER_BASECDR(XmlCDR);

Added: freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/event_handlers/mod_cdr/xmlcdr.h	Wed Oct 18 23:51:46 2006
@@ -0,0 +1,72 @@
+/*
+ * 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>
+ * Ken Rice, Asteria Solutions Group, Inc. <ken AT asteriasgi.com>
+ *
+ * Description: This C++ header file describes the XmlCDR class which handles formatting a CDR out to
+ * individual text files in a XML format.
+ *
+ * xmlcdr.h
+ *
+ */
+
+#include "baseregistry.h"
+#include <switch.h>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+#include <list>
+
+#ifndef XMLCDR
+#define XMLCDR
+
+class XmlCDR : public BaseCDR {
+	public:
+		XmlCDR();
+		XmlCDR(switch_mod_cdr_newchannel_t *newchannel);
+		virtual ~XmlCDR();
+		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();
+
+	private:
+		static bool activated; // Is this module activated?
+		static bool connectionstate; // What is the status of the connection?
+		static bool logchanvars;
+		static std::string outputfile_path; // The directory we'll dump these into
+		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
+		char formattedcallstartdate[100];
+		char formattedcallanswerdate[100];
+		char formattedcallenddate[100];
+		std::string outputfile_name;
+		std::ofstream outputfile;
+};
+
+#endif



More information about the Freeswitch-svn mailing list