/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application Call Detail Recorder module
*
* Copyright 2006, Author: Yossi Neiman, president of Cartis Solutions, Inc. 
* <freeswitch AT cartissolutions.com>
*
* Description: We don't need any documentation, do we?
*
* 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 Core API is the FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application by
* Anthony Minnesale II <anthmct@yahoo.com>
*
* README
*
*/

mod_cdr has been written in C++ using class inheritence and virtual methods, and registers all classes that
have been built in at load time.  It then calls up the connect() method on each particular object and if successful at initializing the object, it adds it to a data structure that contains 1 instance of every sucessfully configured and connected object.  This means that at any time after loading, it will only try to create objects that are functional, skipping any that are built in but are not desired for use at the current time.

In order to use mod_cdr, you must uncomment this line in the freeswitch.xml configuration file located in the conf directory:  <load module="mod_cdr"/> in the <modules> section.  Then below this section, you need to uncomment this section <configuration name="mod_cdr.conf" description="CDR Configuration"> and input the per class configurations.  All class specific configurations go within this parent section as a subsection.

There are currently the following types of loggers:

Class: 		CsvCDR, located in csvcdr.h and csvcdr.cpp
Description:	This is the standard CSV output class.  It has a default list of CDR elements that it always
		logs, and the user can specify channel variables to be logged in a fixed order (chanvars_fixed) starting after the last default value to be logged.  Additionally, the user can specify additional channel variables to be logged after the fixed order channel variables as key=value pairs.
Configuration:	Section name: <csvcdr>
		<param name="path" value=""/>  value is the location to put the files (required)         <param name="size_limit" value=""/> value is the size limit of the output file, default value of 10MB (optional)
		<param name="chanvars_fixed" value=""/> value is a comma separated list of fixed channel variables to log.  This cannot be a wildcard (*).  (optional)
		<param name="chanvars_supp" value=""/>  value is a comma separated list of supplemental channel variables to log.  It can be a wildcard (*).  (optional)
		<param name="repeat_fixed_in_supp" value=""/> value is a 0 for no, 1 for yes, and is for the case that you might want any fixed channel variables to be repeated in the supplemental list.
		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
		
Class:		PddCDR, located in pddcdr.h and pddcdr.cpp
Description:	This is the Perl Data Dumper output class.  It writes each record to an individual text file
		containing all the information.  It does not distinguish between fixed and supplemental channel variables.  If you are running freeswitch in a high volume environment, it is important to note that these individual files are small,  often times between 750 and 1500 bytes.  It is therefore recommended to use a partition with small cluster sizes or (on systems supporting) on reiserfs or reiser4 filesystems which are both excellent handlers of large numbers of small files.
Configuration:	Section name: <pddcdr>
		<param name="path" value=""/>  value is the path where you want the output files (required)
		<param name="chanvars" value=""/> value is a comma separated list of channel variables to log.  It can accept a wildcard (*) (optional)
		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
		
Class:		XmlCDR
Description:	This works very similar to the PddCDR class, only that the output is formatted as xml.  
Configuration:	Section name: <xmlcdr>
				The configuration options are identical to PddCDR.

Class:		MysqlCDR, located in mysqlcdr.h and mysqlcdr.cpp
Description:	This class logs the call detail record to a MySQL 4.1.x or greater database using prepared
		statements.  This class is a little more complex than the prior two 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 the columns being operated upon.  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 callid 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.  As of 2006-12-05, we have added a new column named "calltransferdate" to match changes in the core.  Please update your schema to match.
Configuration:	Section: <mysqlcdr>
		<param name="hostname" value=""/> value is the hostname or IP of the MySQL server (required)
		<param name="username" value=""/> value is the username to connect to the MySQL server with (required)
		<param name="password" value=""/> value is the password to use to authenticate to the MySQL server with (required)
		<param name="dbname" value=""/> value is the name of the database to connect to (required)
		<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 (*).  You must have a matching column of matching type in the main freeswitchcdr table. (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.
		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.

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.
		<param name="timezone" value=""/> value is utc for utc time, local for localtime.  If not specified or incorrectly specified, localtime is assumed.
				
Class:	SqliteCDR, located in sqlitecdr.h and sqlitecdr.cpp
		This class uses the Sqlite3 library as included with FreeSWITCH's core.  Sqlite is not strict in its handling of column types, and in theory you can toss any sort of data at any sort of column.  That being said, this logger was designed to at least attempt to match the column types to the type of data being sent to it.  It will warn you if the schema does not match what chanvars_fixed types you specify, but it will not fail on them.  However, due to the use of prepared statements, it is likely that you will have unexpected results if you mismatch your chanvars_fixed logging to db schema.  The is the first SQL logger to automatically create the db schema and even update it on its own.
Configuration: Section <sqlitecdr>
		<param name="path" value=""/> value is the path to the database to open or create  (required)
		<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 (*).  You must have a matching column of matching type in the main freeswitchcdr table. The logger will attempt to automatically update the schema, but it cannot if a column by that name already exists.(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++?
A: Why not?  It works well in this design.

Q: Why is there a distinction between fixed and supplemental channel variables?
A: There is a distinction so that a level of uniformity can be maintain on those loggers that require uniformity.  For example, if you expect that channel variable FOO will always been at a specific location on a CSV row, then it is required that it be a fixed channel variable.  The fixed means that it is a fixed position, and needs to be logged even if it is blank.  Supplemental channel variables, on the other hand, are more dynamic, and will only log those channel variables that actually exist on that given leg of the call.  That means that if you supply a wildcard, it will simply iterate all the channel variables.  If you do not want to repeat the fixed channel variables in the supplemental channel variables, it will then remove the fixed channel variables from the data structure holding the supplemental channel variables even before the process_record() method is called up.

Q: What would an example configuration look like?
A: Here is an excerpt from the freeswitch XML configuration file:

Q: What about one-legged calls, such as calls to voicemail or playback?
A:  With the current changes in place (as of 2006-12-01), the value of originated will always be set to 0, but destuuid will always be blank.  This will provide you with a method to bill for specific applications and/or calls if you so desire.
				
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.
		
Q: Are there any API commands (executable from the console) that can be run?
A: Yes, there are the following commands:
	modcdr_reload - causes the freeswitch.xml to be reloaded and reruns the configure on all mod_cdr 	modules
	modcdr_queue_pause - pauses the queue from extracting items for processing, useful if you need to 	free up some free space without taking the system down.
	modcdr_queue_resume - resumes normal processing of items in the queue.
	modcdr_show_active - displays the active backend loggers.
	modcdr_show_available - displays the available (compiled-in) backend loggers.

Example configuration:
		
	<configuration name="mod_cdr.conf" description="CDR Configuration">
		<pddcdr>
			<param name="path" value="/work/temp/pddcdr"/>
			<!-- <param name="chanvars" value="username,accountcode"/> -->
			<!-- <param name="chanvars_fixed" value="foo"/> -->
		</pddcdr>
		<csvcdr>
			<param name="path" value="/work/temp/csvcdr"/>
			<param name="size_limit" value="25"/>
			<!-- <param name="chanvars_fixed" value="username"/> -->
			<!-- <param name="chanvars_supp" value="*"/> -->
			<!-- <param name="repeat_fixed_in_supp" value="0"/> -->
		</csvcdr>
		<mysqlcdr>
			<param name="hostname" value="10.0.0.1"/>
			<param name="username" value="test"/>
			<param name="password" value="test"/>
			<param name="dbname" value="testing"/>
			<!-- This following line logs username as a varchar, and The_Kow as a tiny -->
			<!-- <param name="chanvars_fixed" value="username=s,The_Kow=t"/> -->
			<!-- If you do not want to log any and all chanvars to the chanvar table, comment the next 2 lines out -->
			<param name="chanvars_supp" value="*"/>
			<param name="chanvars_supp_repeat_fixed" value="0"/>
		</mysqlcdr>
	</configuration>
