[Freeswitch-svn] [commit] r1696 - in freeswitch/branches/mishehu/src: . mod/codecs/mod_ilbc mod/codecs/mod_l16 mod/loggers/mod_cdr
Freeswitch SVN
mishehu at freeswitch.org
Wed Jun 28 17:46:05 EDT 2006
Author: mishehu
Date: Wed Jun 28 17:46:04 2006
New Revision: 1696
Added:
freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.cpp
freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.h
Removed:
freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/chanvars_parser.cpp
freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/chanvars_parser.h
Modified:
freeswitch/branches/mishehu/src/mod/codecs/mod_ilbc/mod_ilbc.c
freeswitch/branches/mishehu/src/mod/codecs/mod_l16/mod_l16.c
freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/anthmcdr.cpp
freeswitch/branches/mishehu/src/switch_core.c
freeswitch/branches/mishehu/src/switch_xml.c
Log:
Added in CsvCDR standard CSV output using a fixed format output for everything except chanvars. Mostly tested. Merged to trunk r1695.
Modified: freeswitch/branches/mishehu/src/mod/codecs/mod_ilbc/mod_ilbc.c
==============================================================================
--- freeswitch/branches/mishehu/src/mod/codecs/mod_ilbc/mod_ilbc.c (original)
+++ freeswitch/branches/mishehu/src/mod/codecs/mod_ilbc/mod_ilbc.c Wed Jun 28 17:46:04 2006
@@ -225,7 +225,7 @@
static const switch_codec_implementation_t ilbc_102_8k_30ms_implementation = {
- /*.ianacode */ 97,
+ /*.ianacode */ 102,
/*.iananame */ "iLBC",
/*.samples_per_second */ 8000,
/*.bits_per_second */ NO_OF_BYTES_30MS*8*8000/BLOCKL_30MS,
Modified: freeswitch/branches/mishehu/src/mod/codecs/mod_l16/mod_l16.c
==============================================================================
--- freeswitch/branches/mishehu/src/mod/codecs/mod_l16/mod_l16.c (original)
+++ freeswitch/branches/mishehu/src/mod/codecs/mod_l16/mod_l16.c Wed Jun 28 17:46:04 2006
@@ -57,7 +57,6 @@
void *encoded_data,
uint32_t *encoded_data_len, uint32_t *encoded_rate, unsigned int *flag)
{
-
/* NOOP indicates that the audio in is already the same as the audio out, so no conversion was necessary. */
if (codec && other_codec && codec->implementation->samples_per_second != other_codec->implementation->samples_per_second) {
memcpy(encoded_data, decoded_data, decoded_data_len);
Modified: freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/anthmcdr.cpp
==============================================================================
--- freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/anthmcdr.cpp (original)
+++ freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/anthmcdr.cpp Wed Jun 28 17:46:04 2006
@@ -43,8 +43,8 @@
outputfile.open(outputfile_name.c_str());
- //bool fixed = 0;
- process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel);
+ bool repeat = 1;
+ process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel,repeat);
}
}
@@ -96,7 +96,7 @@
}
else if (!strcmp(var, "chanvars_fixed"))
{
- switch_console_printf(SWITCH_CHANNEL_LOG,"AnthmCDR 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\" or \"chanvars_supp\" instead and try again.\n");
+ switch_console_printf(SWITCH_CHANNEL_LOG,"AnthmCDR 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"))
{
@@ -147,8 +147,8 @@
outputfile << "\t\'chanvars\' => {" << std::endl;
if(chanvars_supp.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++)
+ 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;
Added: freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.cpp
==============================================================================
--- (empty file)
+++ freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.cpp Wed Jun 28 17:46:04 2006
@@ -0,0 +1,249 @@
+#include <switch.h>
+#include "csvcdr.h"
+
+CsvCDR::CsvCDR() : BaseCDR()
+{
+ memset(formattedcallstartdate,0,100);
+ memset(formattedcallanswerdate,0,100);
+ memset(formattedcallenddate,0,100);
+}
+
+CsvCDR::CsvCDR(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
+ apr_size_t retsizecsd, retsizecad, retsizeced; //csd == callstartdate, cad == callanswerdate, ced == callenddate, ceff == callenddate_forfile
+ char format[] = "%F %T";
+ switch_strftime(formattedcallstartdate,&retsizecsd,sizeof(formattedcallstartdate),format,&tempcallstart);
+ switch_strftime(formattedcallanswerdate,&retsizecad,sizeof(formattedcallanswerdate),format,&tempcallanswer);
+ switch_strftime(formattedcallenddate,&retsizeced,sizeof(formattedcallenddate),format,&tempcallend);
+
+ process_channel_variables(chanvars_fixed_list,newchannel->channel);
+ process_channel_variables(chanvars_supp_list,chanvars_fixed_list,newchannel->channel,repeat_fixed_in_supp);
+ }
+}
+
+CsvCDR::~CsvCDR()
+{
+
+}
+
+bool CsvCDR::activated=0;
+bool CsvCDR::logchanvars=0;
+bool CsvCDR::connectionstate=0;
+bool CsvCDR::repeat_fixed_in_supp=0;
+std::string CsvCDR::outputfile_path;
+std::ofstream CsvCDR::outputfile;
+std::ofstream::pos_type CsvCDR::filesize_limit = (10 * 1024 * 1024); // Default file size is 10MB
+std::list<std::string> CsvCDR::chanvars_fixed_list;
+std::list<std::string> CsvCDR::chanvars_supp_list;
+
+void CsvCDR::connect(switch_xml_t& cfg, switch_xml_t& xml, switch_xml_t& settings, switch_xml_t& param)
+{
+ switch_console_printf(SWITCH_CHANNEL_LOG, "CsvCDR::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, "csvcdr")))
+ {
+ 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_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;
+ }
+ }
+ }
+ else if (!strcmp(var, "repeat_fixed_in_supp"))
+ {
+ if(!strcmp(val,"1"))
+ repeat_fixed_in_supp = val;
+ else if (!strcmp(val,"y") || !strcmp(val,"y"))
+ repeat_fixed_in_supp = 0;
+ }
+ else if (!strcmp(var, "size_limit"))
+ {
+ if(val != 0)
+ {
+ filesize_limit = atoi(val) * 1024 * 1024; // Value is in MB
+ std::cout << "File size limit from config file is " << filesize_limit << " byte(s)." << std::endl;
+ }
+ }
+ }
+
+ if(count_config_params > 0)
+ {
+ open_file();
+ if(outputfile.good())
+ {
+ activated = 1;
+ switch_console_printf(SWITCH_CHANNEL_LOG,"CsvCDR activated, log rotation will occur at or after %d MB",(filesize_limit/1024/1024));
+ }
+ }
+ else
+ switch_console_printf(SWITCH_CHANNEL_LOG,"CsvCDR::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");
+ }
+}
+
+void CsvCDR::check_file_size_and_open()
+{
+ // Test if the file has been opened or not
+ if(outputfile)
+ {
+ if(outputfile.tellp() > filesize_limit)
+ outputfile.close();
+ }
+
+ if (!outputfile)
+ {
+ open_file();
+ }
+}
+
+void CsvCDR::open_file()
+{
+ switch_time_t now = switch_time_now();
+ switch_time_exp_t now_converted;
+ memset(&now_converted,0,sizeof(now_converted));
+
+ switch_time_exp_lt(&now_converted,now);
+
+ apr_size_t retsize;
+ char format[] = "%F %T";
+ char formatteddate[100];
+ memset(formatteddate,0,100);
+ switch_strftime(formatteddate,&retsize,100,format,&now_converted);
+
+ std::string filename = outputfile_path;
+ filename.append("/");
+ filename.append(formatteddate);
+ filename.append(".csv");
+ outputfile.clear();
+
+ outputfile.open(filename.c_str(),std::ios_base::app|std::ios_base::binary);
+ if(outputfile.fail())
+ {
+ switch_console_printf(SWITCH_CHANNEL_LOG,"Could not open the CSV file %s . CsvCDR logger will not be functional until this is resolved and a reload is issued. Failbit is set to %d.\n",filename.c_str(),outputfile.fail());
+ activated = 0;
+ }
+
+}
+
+bool CsvCDR::process_record()
+{
+ check_file_size_and_open();
+ bool retval = 0;
+ if(active)
+ {
+ // Format the call record and proceed from here...
+ outputfile << "\"" << callstartdate << "\",\"";
+ outputfile << callanswerdate << "\",\"";
+ outputfile << callenddate << "\",\"";
+ outputfile << hangupcause_text << "\",\"";
+ outputfile << hangupcause << "\",\"";
+ outputfile << clid << "\",\"";
+ outputfile << originated << "\",\"";
+ outputfile << dialplan << "\",\"";
+ outputfile << myuuid << "\",\"";
+ outputfile << destuuid << "\",\"";
+ outputfile << src << "\",\"";
+ outputfile << dst << "\",\"";
+ outputfile << srcchannel << "\",\"";
+ outputfile << dstchannel << "\",\"";
+ outputfile << ani << "\",\"";
+ outputfile << ani2 << "\",\"";
+ outputfile << network_addr << "\",\"";
+ outputfile << lastapp << "\",\"";
+ outputfile << lastdata << "\",\"";
+ outputfile << billusec << "\",\"";
+ outputfile << disposition << "\",\"";
+ outputfile << 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++)
+ outputfile << ",\"" << 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++)
+ outputfile << ",\"" << iItr->first << "=" << iItr->second << "\"";
+ }
+ outputfile << std::endl;
+ retval = 1;
+ }
+
+ return retval;
+}
+
+bool CsvCDR::is_activated()
+{
+ return activated;
+}
+
+void CsvCDR::tempdump_record()
+{
+
+}
+
+void CsvCDR::reread_tempdumped_records()
+{
+
+}
+
+void CsvCDR::disconnect()
+{
+ outputfile.close();
+ switch_console_printf(SWITCH_CHANNEL_LOG,"Shutting down CsvCDR... Done!");
+}
+
+AUTO_REGISTER_BASECDR(CsvCDR);
Added: freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.h
==============================================================================
--- (empty file)
+++ freeswitch/branches/mishehu/src/mod/loggers/mod_cdr/csvcdr.h Wed Jun 28 17:46:04 2006
@@ -0,0 +1,43 @@
+#include "baseregistry.h"
+#include <switch.h>
+// #include <sys/types.h>
+// #include <sys/stat.h>
+// #include <fcntl.h>
+#include <iostream>
+#include <fstream>
+#include <list>
+
+#ifndef CSVCDR
+#define CSVCDR
+
+class CsvCDR : public BaseCDR {
+ public:
+ CsvCDR();
+ CsvCDR(switch_mod_cdr_newchannel_t *newchannel);
+ //CsvCDR(const CsvCDR& copyFrom);
+ virtual ~CsvCDR();
+ 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 bool repeat_fixed_in_supp; // Repeat the fixed chanvars in the supplemental?
+ 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];
+ static std::ofstream outputfile;
+ static std::ofstream::pos_type filesize_limit;
+ void check_file_size_and_open(); // Checks the size of the file, and if it's greater than size allowed, rotates it.
+ void open_file();
+};
+
+#endif
Modified: freeswitch/branches/mishehu/src/switch_core.c
==============================================================================
--- freeswitch/branches/mishehu/src/switch_core.c (original)
+++ freeswitch/branches/mishehu/src/switch_core.c Wed Jun 28 17:46:04 2006
@@ -1057,9 +1057,13 @@
int timeout, int stream_id)
{
switch_io_event_hook_read_frame_t *ptr;
- switch_status_t status = SWITCH_STATUS_FALSE;
- int need_codec = 0, perfect = 0;
-
+ switch_status_t status;
+ int need_codec, perfect;
+ top:
+
+ status = SWITCH_STATUS_FALSE;
+ need_codec = perfect = 0;
+
assert(session != NULL);
*frame = NULL;
@@ -1180,18 +1184,22 @@
session->raw_read_frame.rate = (*frame)->rate;
} else {
session->raw_read_frame.datalen = (uint32_t)switch_buffer_read(session->raw_read_buffer,
- session->raw_read_frame.data,
- session->read_codec->implementation->
- bytes_per_frame);
+ session->raw_read_frame.data,
+ session->read_codec->implementation->bytes_per_frame);
+
session->raw_read_frame.rate = session->read_codec->implementation->samples_per_second;
enc_frame = &session->raw_read_frame;
}
session->enc_read_frame.datalen = session->enc_read_frame.buflen;
+ assert(session->read_codec != NULL);
+ assert(enc_frame != NULL);
+ assert(enc_frame->data != NULL);
+
status = switch_core_codec_encode(session->read_codec,
enc_frame->codec,
enc_frame->data,
enc_frame->datalen,
- enc_frame->codec->implementation->samples_per_second,
+ session->read_codec->implementation->samples_per_second,
session->enc_read_frame.data,
&session->enc_read_frame.datalen,
&session->enc_read_frame.rate,
@@ -1215,6 +1223,8 @@
status = SWITCH_STATUS_GENERR;
break;
}
+ } else {
+ goto top;
}
}
}
Modified: freeswitch/branches/mishehu/src/switch_xml.c
==============================================================================
--- freeswitch/branches/mishehu/src/switch_xml.c (original)
+++ freeswitch/branches/mishehu/src/switch_xml.c Wed Jun 28 17:46:04 2006
@@ -1001,26 +1001,32 @@
return *dst;
}
+#define XML_INDENT " "
// Recursively converts each tag to xml appending it to *s. Reallocates *s if
// its length excedes max. start is the location of the previous tag in the
// parent tag's character content. Returns *s.
static char *switch_xml_toxml_r(switch_xml_t xml, char **s, switch_size_t *len, switch_size_t *max,
- switch_size_t start, char ***attr)
+ switch_size_t start, char ***attr, uint32_t *count)
{
int i, j;
char *txt = (xml->parent) ? xml->parent->txt : "";
switch_size_t off = 0;
+ uint32_t lcount = 0;
// parent character content up to this tag
*s = switch_xml_ampencode(txt + start, xml->off - start, s, len, max, 0);
- while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+ while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
*s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
+ for (lcount = 0; lcount < *count; lcount++) {
+ *len += sprintf(*s + *len, "%s", XML_INDENT); // indent
+ }
+
*len += sprintf(*s + *len, "<%s", xml->name); // open tag
for (i = 0; xml->attr[i]; i += 2) { // tag attributes
if (switch_xml_attr(xml, xml->attr[i]) != xml->attr[i + 1]) continue;
- while (*len + strlen(xml->attr[i]) + 7 > *max) // reallocate s
+ while (*len + strlen(xml->attr[i]) + 7 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
*s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
*len += sprintf(*s + *len, " %s=\"", xml->attr[i]);
@@ -1032,26 +1038,43 @@
for (j = 1; attr[i] && attr[i][j]; j += 3) { // default attributes
if (! attr[i][j + 1] || switch_xml_attr(xml, attr[i][j]) != attr[i][j + 1])
continue; // skip duplicates and non-values
- while (*len + strlen(attr[i][j]) + 7 > *max) // reallocate s
+ while (*len + strlen(attr[i][j]) + 8 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
*s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
*len += sprintf(*s + *len, " %s=\"", attr[i][j]);
switch_xml_ampencode(attr[i][j + 1], 0, s, len, max, 1);
*len += sprintf(*s + *len, "\"");
}
- *len += sprintf(*s + *len, ">");
+ *len += sprintf(*s + *len, xml->child ? ">\n" : "/>\n");
- *s = (xml->child) ? switch_xml_toxml_r(xml->child, s, len, max, 0, attr) //child
- : switch_xml_ampencode(xml->txt, 0, s, len, max, 0); //data
-
- while (*len + strlen(xml->name) + 4 > *max) // reallocate s
+ if (xml->child) {
+ (*count)++;
+ *s = switch_xml_toxml_r(xml->child, s, len, max, 0, attr, count);
+ } else {
+ *s = switch_xml_ampencode(xml->txt, 0, s, len, max, 0); //data
+ }
+
+ while (*len + strlen(xml->name) + 5 + (strlen(XML_INDENT) * (*count)) > *max) // reallocate s
*s = realloc(*s, *max += SWITCH_XML_BUFSIZE);
- *len += sprintf(*s + *len, "</%s>", xml->name); // close tag
+ if (xml->child) {
+ for (lcount = 0; lcount < *count; lcount++) {
+ *len += sprintf(*s + *len, "%s", XML_INDENT); // indent
+ }
+ *len += sprintf(*s + (*len), "</%s>\n", xml->name); // close tag
+ }
+
while (txt[off] && off < xml->off) off++; // make sure off is within bounds
- return (xml->ordered) ? switch_xml_toxml_r(xml->ordered, s, len, max, off, attr)
- : switch_xml_ampencode(txt + off, 0, s, len, max, 0);
+
+ if (xml->ordered) {
+ return switch_xml_toxml_r(xml->ordered, s, len, max, off, attr, count);
+
+ } else {
+ if (*count > 0)
+ (*count)--;
+ return switch_xml_ampencode(txt + off, 0, s, len, max, 0);
+ }
}
// converts an switch_xml structure back to xml, returning it as a string that must
@@ -1063,6 +1086,7 @@
switch_size_t len = 0, max = SWITCH_XML_BUFSIZE;
char *s = strcpy(malloc(max), ""), *t, *n;
int i, j, k;
+ uint32_t count = 0;
if (! xml || ! xml->name) return realloc(s, len + 1);
while (root->xml.parent) root = (switch_xml_root_t)root->xml.parent; // root tag
@@ -1073,12 +1097,12 @@
if (root->pi[i][k][j - 1] == '>') continue; // not pre-root
while (len + strlen(t = root->pi[i][0]) + strlen(n) + 7 > max)
s = realloc(s, max += SWITCH_XML_BUFSIZE);
- len += sprintf(s + len, "<?%s%s%s?>\n", t, *n ? " " : "", n);
+ len += sprintf(s + len, "<?%s%s%s?>", t, *n ? " " : "", n);
}
}
xml->parent = xml->ordered = NULL;
- s = switch_xml_toxml_r(xml, &s, &len, &max, 0, root->attr);
+ s = switch_xml_toxml_r(xml, &s, &len, &max, 0, root->attr, &count);
xml->parent = p;
xml->ordered = o;
More information about the Freeswitch-svn
mailing list