#include "asterisk.h"
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/logger.h"
#include "asterisk/utils.h"
Include dependency graph for cdr_csv.c:
Go to the source code of this file.
Defines | |
#define | CSV_LOG_DIR "/cdr-csv" |
#define | CSV_MASTER "/Master.csv" |
#define | DATE_FORMAT "%Y-%m-%d %T" |
Functions | |
static int | append_date (char *buf, struct timeval tv, size_t bufsize) |
static int | append_int (char *buf, int s, size_t bufsize) |
static int | append_string (char *buf, char *s, size_t bufsize) |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"Comma Separated Values CDR Backend",.load=load_module,.unload=unload_module,.reload=reload,) | |
static int | build_csv_record (char *buf, size_t bufsize, struct ast_cdr *cdr) |
static int | csv_log (struct ast_cdr *cdr) |
static int | load_config (void) |
static int | load_module (void) |
static int | reload (void) |
static int | unload_module (void) |
static int | writefile (char *s, char *acc) |
Variables | |
static char * | config = "cdr.conf" |
static int | loguniqueid = 0 |
static int | loguserfield = 0 |
static FILE * | mf = NULL |
static char * | name = "csv" |
static int | usegmtime = 0 |
Definition in file cdr_csv.c.
#define CSV_LOG_DIR "/cdr-csv" |
static int append_date | ( | char * | buf, | |
struct timeval | tv, | |||
size_t | bufsize | |||
) | [static] |
Definition at line 187 of file cdr_csv.c.
References append_string(), ast_localtime(), DATE_FORMAT, and t.
00188 { 00189 char tmp[80] = ""; 00190 struct tm tm; 00191 time_t t; 00192 t = tv.tv_sec; 00193 if (strlen(buf) > bufsize - 3) 00194 return -1; 00195 if (ast_tvzero(tv)) { 00196 strncat(buf, ",", bufsize - strlen(buf) - 1); 00197 return 0; 00198 } 00199 if (usegmtime) { 00200 gmtime_r(&t,&tm); 00201 } else { 00202 ast_localtime(&t, &tm, NULL); 00203 } 00204 strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm); 00205 return append_string(buf, tmp, bufsize); 00206 }
static int append_int | ( | char * | buf, | |
int | s, | |||
size_t | bufsize | |||
) | [static] |
Definition at line 173 of file cdr_csv.c.
Referenced by build_csv_record().
00174 { 00175 char tmp[32]; 00176 int pos = strlen(buf); 00177 snprintf(tmp, sizeof(tmp), "%d", s); 00178 if (pos + strlen(tmp) > bufsize - 3) 00179 return -1; 00180 strncat(buf, tmp, bufsize - strlen(buf) - 1); 00181 pos = strlen(buf); 00182 buf[pos++] = ','; 00183 buf[pos++] = '\0'; 00184 return 0; 00185 }
static int append_string | ( | char * | buf, | |
char * | s, | |||
size_t | bufsize | |||
) | [static] |
Definition at line 148 of file cdr_csv.c.
References error().
Referenced by append_date(), and build_csv_record().
00149 { 00150 int pos = strlen(buf); 00151 int spos = 0; 00152 int error = 0; 00153 if (pos >= bufsize - 4) 00154 return -1; 00155 buf[pos++] = '\"'; 00156 error = -1; 00157 while(pos < bufsize - 3) { 00158 if (!s[spos]) { 00159 error = 0; 00160 break; 00161 } 00162 if (s[spos] == '\"') 00163 buf[pos++] = '\"'; 00164 buf[pos++] = s[spos]; 00165 spos++; 00166 } 00167 buf[pos++] = '\"'; 00168 buf[pos++] = ','; 00169 buf[pos++] = '\0'; 00170 return error; 00171 }
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"Comma Separated Values CDR Backend" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static int build_csv_record | ( | char * | buf, | |
size_t | bufsize, | |||
struct ast_cdr * | cdr | |||
) | [static] |
Definition at line 208 of file cdr_csv.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr::answer, append_date(), append_int(), append_string(), ast_cdr_disp2str(), ast_cdr_flags2str(), ast_cdr::billsec, ast_cdr::channel, ast_cdr::clid, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_cdr::duration, ast_cdr::end, ast_cdr::lastapp, ast_cdr::lastdata, ast_cdr::src, ast_cdr::start, ast_cdr::uniqueid, and ast_cdr::userfield.
Referenced by csv_log().
00209 { 00210 00211 buf[0] = '\0'; 00212 /* Account code */ 00213 append_string(buf, cdr->accountcode, bufsize); 00214 /* Source */ 00215 append_string(buf, cdr->src, bufsize); 00216 /* Destination */ 00217 append_string(buf, cdr->dst, bufsize); 00218 /* Destination context */ 00219 append_string(buf, cdr->dcontext, bufsize); 00220 /* Caller*ID */ 00221 append_string(buf, cdr->clid, bufsize); 00222 /* Channel */ 00223 append_string(buf, cdr->channel, bufsize); 00224 /* Destination Channel */ 00225 append_string(buf, cdr->dstchannel, bufsize); 00226 /* Last Application */ 00227 append_string(buf, cdr->lastapp, bufsize); 00228 /* Last Data */ 00229 append_string(buf, cdr->lastdata, bufsize); 00230 /* Start Time */ 00231 append_date(buf, cdr->start, bufsize); 00232 /* Answer Time */ 00233 append_date(buf, cdr->answer, bufsize); 00234 /* End Time */ 00235 append_date(buf, cdr->end, bufsize); 00236 /* Duration */ 00237 append_int(buf, cdr->duration, bufsize); 00238 /* Billable seconds */ 00239 append_int(buf, cdr->billsec, bufsize); 00240 /* Disposition */ 00241 append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize); 00242 /* AMA Flags */ 00243 append_string(buf, ast_cdr_flags2str(cdr->amaflags), bufsize); 00244 /* Unique ID */ 00245 if (loguniqueid) 00246 append_string(buf, cdr->uniqueid, bufsize); 00247 /* append the user field */ 00248 if(loguserfield) 00249 append_string(buf, cdr->userfield,bufsize); 00250 /* If we hit the end of our buffer, log an error */ 00251 if (strlen(buf) < bufsize - 5) { 00252 /* Trim off trailing comma */ 00253 buf[strlen(buf) - 1] = '\0'; 00254 strncat(buf, "\n", bufsize - strlen(buf) - 1); 00255 return 0; 00256 } 00257 return -1; 00258 }
static int csv_log | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 279 of file cdr_csv.c.
References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_config_AST_LOG_DIR, ast_log(), ast_strlen_zero(), ast_cdr::billsec, build_csv_record(), ast_cdr::channel, CSV_LOG_DIR, CSV_MASTER, ast_cdr::disposition, ast_cdr::dst, ast_cdr::duration, LOG_ERROR, LOG_WARNING, ast_cdr::src, and writefile().
Referenced by load_module().
00280 { 00281 /* Make sure we have a big enough buf */ 00282 char buf[1024]; 00283 char csvmaster[PATH_MAX]; 00284 snprintf(csvmaster, sizeof(csvmaster),"%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER); 00285 #if 0 00286 printf("[CDR] %s ('%s' -> '%s') Dur: %ds Bill: %ds Disp: %s Flags: %s Account: [%s]\n", cdr->channel, cdr->src, cdr->dst, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), cdr->accountcode); 00287 #endif 00288 if (build_csv_record(buf, sizeof(buf), cdr)) { 00289 ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes. CDR not recorded!\n", (int)sizeof(buf)); 00290 } else { 00291 /* because of the absolutely unconditional need for the 00292 highest reliability possible in writing billing records, 00293 we open write and close the log file each time */ 00294 mf = fopen(csvmaster, "a"); 00295 if (!mf) { 00296 ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno)); 00297 } 00298 if (mf) { 00299 fputs(buf, mf); 00300 fflush(mf); /* be particularly anal here */ 00301 fclose(mf); 00302 mf = NULL; 00303 } 00304 if (!ast_strlen_zero(cdr->accountcode)) { 00305 if (writefile(buf, cdr->accountcode)) 00306 ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno)); 00307 } 00308 } 00309 return 0; 00310 }
static int load_config | ( | void | ) | [static] |
Definition at line 97 of file cdr_csv.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), LOG_DEBUG, LOG_WARNING, and var.
00098 { 00099 struct ast_config *cfg; 00100 struct ast_variable *var; 00101 const char *tmp; 00102 00103 usegmtime = 0; 00104 loguniqueid = 0; 00105 loguserfield = 0; 00106 00107 cfg = ast_config_load(config); 00108 00109 if (!cfg) { 00110 ast_log(LOG_WARNING, "unable to load config: %s\n", config); 00111 return 0; 00112 } 00113 00114 var = ast_variable_browse(cfg, "csv"); 00115 if (!var) { 00116 ast_config_destroy(cfg); 00117 return 0; 00118 } 00119 00120 tmp = ast_variable_retrieve(cfg, "csv", "usegmtime"); 00121 if (tmp) { 00122 usegmtime = ast_true(tmp); 00123 if (usegmtime) { 00124 ast_log(LOG_DEBUG, "logging time in GMT\n"); 00125 } 00126 } 00127 00128 tmp = ast_variable_retrieve(cfg, "csv", "loguniqueid"); 00129 if (tmp) { 00130 loguniqueid = ast_true(tmp); 00131 if (loguniqueid) { 00132 ast_log(LOG_DEBUG, "logging CDR field UNIQUEID\n"); 00133 } 00134 } 00135 00136 tmp = ast_variable_retrieve(cfg, "csv", "loguserfield"); 00137 if (tmp) { 00138 loguserfield = ast_true(tmp); 00139 if (loguserfield) { 00140 ast_log(LOG_DEBUG, "logging CDR user-defined field\n"); 00141 } 00142 } 00143 00144 ast_config_destroy(cfg); 00145 return 1; 00146 }
static int load_module | ( | void | ) | [static] |
Definition at line 320 of file cdr_csv.c.
References ast_cdr_register(), ast_log(), AST_MODULE_LOAD_DECLINE, csv_log(), load_config(), and LOG_ERROR.
00321 { 00322 int res; 00323 00324 if(!load_config()) 00325 return AST_MODULE_LOAD_DECLINE; 00326 00327 res = ast_cdr_register(name, ast_module_info->description, csv_log); 00328 if (res) { 00329 ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n"); 00330 if (mf) 00331 fclose(mf); 00332 } 00333 return res; 00334 }
static int reload | ( | void | ) | [static] |
Definition at line 336 of file cdr_csv.c.
References load_config().
00337 { 00338 load_config(); 00339 00340 return 0; 00341 }
static int unload_module | ( | void | ) | [static] |
Definition at line 312 of file cdr_csv.c.
References ast_cdr_unregister().
00313 { 00314 if (mf) 00315 fclose(mf); 00316 ast_cdr_unregister(name); 00317 return 0; 00318 }
static int writefile | ( | char * | s, | |
char * | acc | |||
) | [static] |
Definition at line 260 of file cdr_csv.c.
References ast_config_AST_LOG_DIR, ast_log(), CSV_LOG_DIR, f, and LOG_WARNING.
Referenced by csv_log().
00261 { 00262 char tmp[PATH_MAX]; 00263 FILE *f; 00264 if (strchr(acc, '/') || (acc[0] == '.')) { 00265 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc); 00266 return -1; 00267 } 00268 snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc); 00269 f = fopen(tmp, "a"); 00270 if (!f) 00271 return -1; 00272 fputs(s, f); 00273 fflush(f); 00274 fclose(f); 00275 return 0; 00276 }
int loguniqueid = 0 [static] |
int loguserfield = 0 [static] |
FILE* mf = NULL [static] |
Definition at line 94 of file cdr_csv.c.
Referenced by ast_say_number_full_de(), ast_say_number_full_es(), ast_say_number_full_fr(), ast_say_number_full_he(), and ast_say_number_full_pt().