[Freeswitch-svn] [commit] r1696 - in freeswitch/branches/mishehu/src: . mod/codecs/mod_ilbc mod/codecs/mod_l16 mod/loggers/mod_cdr
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;
participants (1)
-
Freeswitch SVN