Fri Aug 24 02:23:32 2007

Asterisk developer's documentation


cdr_csv.c File Reference

Comma Separated Value CDR records. More...

#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


Detailed Description

Comma Separated Value CDR records.

Author:
Mark Spencer <markster@digium.com>

Definition in file cdr_csv.c.


Define Documentation

#define CSV_LOG_DIR   "/cdr-csv"

Definition at line 51 of file cdr_csv.c.

Referenced by csv_log(), and writefile().

#define CSV_MASTER   "/Master.csv"

Definition at line 52 of file cdr_csv.c.

Referenced by csv_log().

#define DATE_FORMAT   "%Y-%m-%d %T"

Definition at line 54 of file cdr_csv.c.


Function Documentation

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 }


Variable Documentation

char* config = "cdr.conf" [static]

Definition at line 59 of file cdr_csv.c.

int loguniqueid = 0 [static]

Definition at line 57 of file cdr_csv.c.

int loguserfield = 0 [static]

Definition at line 58 of file cdr_csv.c.

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().

char* name = "csv" [static]

Definition at line 92 of file cdr_csv.c.

int usegmtime = 0 [static]

Definition at line 56 of file cdr_csv.c.


Generated on Fri Aug 24 02:23:32 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1