static switch_status_t my_on_hangup(switch_core_session_t *session) { switch_xml_t cdr; char *xml_text; char *path; int fd = -1; uint32_t curTry; long httpRes; CURL *curl_handle = NULL; char *curl_xml_text; char *logdir; switch_channel_t *channel = switch_core_session_get_channel(session); if (switch_ivr_generate_xml_cdr(session, &cdr) == SWITCH_STATUS_SUCCESS) { /* build the XML */ if(!(xml_text = switch_mprintf("\n%s",switch_xml_toxml(cdr)) )) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); return SWITCH_STATUS_FALSE; } /* do we log to the disk no matter what? */ /* all previous functionality is retained */ if (!(logdir = switch_channel_get_variable(channel, "xml_cdr_base"))) { logdir = globals.logDir; } if(!switch_strlen_zero(logdir)) { if ((path = switch_mprintf("%s/xml_cdr/%s.cdr.xml", logdir, switch_core_session_get_uuid(session)))) { if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { write(fd, xml_text, (unsigned) strlen(xml_text)); close(fd); fd = -1; } else { char ebuf[512] = { 0 }; #ifdef WIN32 strerror_s(ebuf, sizeof(ebuf), errno); #else strerror_r(errno, ebuf, sizeof(ebuf)); #endif switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n", ebuf); } free(path); } } /* try to post it to the web server */ if(!switch_strlen_zero(globals.url)) { curl_handle = curl_easy_init(); if(!(curl_xml_text = switch_mprintf("cdr=%s",xml_text) )) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); free(xml_text); return SWITCH_STATUS_FALSE; } if (!switch_strlen_zero(globals.cred)) { curl_easy_setopt(curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(curl_handle, CURLOPT_USERPWD, globals.cred); } curl_easy_setopt(curl_handle, CURLOPT_POST, 1); curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, curl_xml_text); curl_easy_setopt(curl_handle, CURLOPT_URL, globals.url); curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-xml/1.0"); /* these were used for testing, optionally they may be enabled if someone desires curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, 120); // tcp timeout curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); // 302 recursion level */ for(curTry=0;curTry<=globals.retries;curTry++) { curl_easy_perform(curl_handle); curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE,&httpRes); if(httpRes==200) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "DEBUG XXX success posting\n"); curl_easy_cleanup(curl_handle); free(curl_xml_text); free(xml_text); return SWITCH_STATUS_SUCCESS; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Got error [%ld] posting to web server\n",httpRes); } /* bug? feature? we sleep even on the last failure before writing the file */ switch_sleep(globals.delay * 1000); } free(curl_xml_text); curl_easy_cleanup(curl_handle); } /* if we are here the web post failed for some reason */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to post to web server, writing to file\n"); if ((path = switch_mprintf("%s/%s.cdr.xml", globals.errLogDir, switch_core_session_get_uuid(session)))) { if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) { write(fd, xml_text, (unsigned) strlen(xml_text)); close(fd); fd = -1; } else { char ebuf[512] = { 0 }; #ifdef WIN32 strerror_s(ebuf, sizeof(ebuf), errno); #else strerror_r(errno, ebuf, sizeof(ebuf)); #endif switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error![%s]\n", ebuf); } free(path); } free(xml_text); switch_xml_free(cdr); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Generating Data!\n"); } return SWITCH_STATUS_SUCCESS; } static switch_status_t do_config(void) { char *cf = "xml_cdr.conf"; switch_xml_t cfg, xml, settings, param; if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf); return SWITCH_STATUS_TERM; } if ((settings = switch_xml_child(cfg, "settings"))) { 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 (!strcasecmp(var, "cred")) { globals.cred = val; } else if (!strcasecmp(var, "url")) { globals.url = val; } else if (!strcasecmp(var, "delay")) { globals.delay = (uint32_t) atoi(val); } else if (!strcasecmp(var, "retries")) { globals.retries = (uint32_t) atoi(val); } else if (!strcasecmp(var, "logDir")) { if (switch_strlen_zero(val)) { globals.logDir = SWITCH_GLOBAL_dirs.log_dir; } else { globals.logDir = val; } } else if (!strcasecmp(var, "errLogDir")) { globals.errLogDir = val; } } } if(globals.retries < 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "retries is negative, setting to 0\n"); globals.retries = 0; } if(globals.retries && globals.delay<=0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "retries set but delay 0 setting to 5000ms\n"); globals.delay = 5000; } if(!switch_strlen_zero(globals.url) && switch_strlen_zero(globals.errLogDir)) { if ((globals.errLogDir = switch_mprintf("%s/xml_cdr", SWITCH_GLOBAL_dirs.log_dir))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); return SWITCH_STATUS_FALSE; } } return SWITCH_STATUS_SUCCESS; }