Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:24 2009

## Asterisk developer's documentation

# cdr_csv.c File Reference

Comma Separated Value CDR records. More...

`#include <sys/types.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include <errno.h>`
`#include <stdlib.h>`
`#include <unistd.h>`
`#include <time.h>`
`#include "asterisk.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)
static int | build_csv_record (char *buf, size_t bufsize, struct ast_cdr *cdr)
static int | csv_log (struct ast_cdr *cdr)
char * | description (void)
| Provides a description of the module.
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
int | reload (void)
| Reload stuff.
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount (void)
| Provides a usecount.
static int | writefile (char *s, char *acc)

## Variables

static char * | desc = "Comma Separated Values CDR Backend"
static FILE * | mf = NULL
static char * | name = "csv"

## Detailed Description

Comma Separated Value CDR records.

- See also CDR - Call Data Records and billing

Definition in file cdr_csv.c.

## Define Documentation

#define CSV_LOG_DIR "/cdr-csv"

Definition at line 48 of file cdr_csv.c.

Referenced by csv_log(), and writefile().

#define CSV_MASTER "/Master.csv"

Definition at line 49 of file cdr_csv.c.

Referenced by csv_log().

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

Definition at line 51 of file cdr_csv.c.

Referenced by append_date(), get_date(), manager_log(), odbc_log(), pgsql_log(), and sqlite_log().

## Function Documentation

static int append_date | ( | char * | buf,
|  | struct timeval | tv,
|  | size_t | bufsize |
| ) |  |  | `[static]`

Definition at line 129 of file cdr_csv.c.

References append_string(), DATE_FORMAT, and t.

    00130 {
    00131    char tmp[80] = "";
    00132    struct tm tm;
    00133    time_t t;
    00134    t = tv.tv_sec;
    00135    if (strlen(buf) > bufsize - 3)
    00136       return -1;
    00137    if (ast_tvzero(tv)) {
    00138       strncat(buf, ",", bufsize - strlen(buf) - 1);
    00139       return 0;
    00140    }
    00141    localtime_r(&t,&tm);
    00142    strftime(tmp, sizeof(tmp), DATE_FORMAT, &tm);
    00143    return append_string(buf, tmp, bufsize);
    00144 }

static int append_int | ( | char * | buf,
|  | int | s,
|  | size_t | bufsize |
| ) |  |  | `[static]`

Definition at line 115 of file cdr_csv.c.

Referenced by build_csv_record().

    00116 {
    00117    char tmp[32];
    00118    int pos = strlen(buf);
    00119    snprintf(tmp, sizeof(tmp), "%d", s);
    00120    if (pos + strlen(tmp) > bufsize - 3)
    00121       return -1;
    00122    strncat(buf, tmp, bufsize - strlen(buf) - 1);
    00123    pos = strlen(buf);
    00124    buf[pos++] = ',';
    00125    buf[pos++] = '\0';
    00126    return 0;
    00127 }

static int append_string | ( | char * | buf,
|  | char * | s,
|  | size_t | bufsize |
| ) |  |  | `[static]`

Definition at line 90 of file cdr_csv.c.

References error().

Referenced by append_date(), and build_csv_record().

    00091 {
    00092    int pos = strlen(buf);
    00093    int spos = 0;
    00094    int error = 0;
    00095    if (pos >= bufsize - 4)
    00096       return -1;
    00097    buf[pos++] = '\"';
    00098    error = -1;
    00099    while(pos < bufsize - 3) {
    00100       if (!s[spos]) {
    00101          error = 0;
    00102          break;
    00103       }
    00104       if (s[spos] == '\"')
    00105          buf[pos++] = '\"';
    00106       buf[pos++] = s[spos];
    00107       spos++;
    00108    }
    00109    buf[pos++] = '\"';
    00110    buf[pos++] = ',';
    00111    buf[pos++] = '\0';
    00112    return error;
    00113 }

static int build_csv_record | ( | char * | buf,
|  | size_t | bufsize,
|  | struct ast_cdr * | cdr |
| ) |  |  | `[static]`

Definition at line 146 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().

    00147 {
    00148
    00149    buf[0] = '\0';
    00150    /* Account code */
    00151    append_string(buf, cdr->accountcode, bufsize);
    00152    /* Source */
    00153    append_string(buf, cdr->src, bufsize);
    00154    /* Destination */
    00155    append_string(buf, cdr->dst, bufsize);
    00156    /* Destination context */
    00157    append_string(buf, cdr->dcontext, bufsize);
    00158    /* Caller*ID */
    00159    append_string(buf, cdr->clid, bufsize);
    00160    /* Channel */
    00161    append_string(buf, cdr->channel, bufsize);
    00162    /* Destination Channel */
    00163    append_string(buf, cdr->dstchannel, bufsize);
    00164    /* Last Application */
    00165    append_string(buf, cdr->lastapp, bufsize);
    00166    /* Last Data */
    00167    append_string(buf, cdr->lastdata, bufsize);
    00168    /* Start Time */
    00169    append_date(buf, cdr->start, bufsize);
    00170    /* Answer Time */
    00171    append_date(buf, cdr->answer, bufsize);
    00172    /* End Time */
    00173    append_date(buf, cdr->end, bufsize);
    00174    /* Duration */
    00175    append_int(buf, cdr->duration, bufsize);
    00176    /* Billable seconds */
    00177    append_int(buf, cdr->billsec, bufsize);
    00178    /* Disposition */
    00179    append_string(buf, ast_cdr_disp2str(cdr->disposition), bufsize);
    00180    /* AMA Flags */
    00181    append_string(buf, ast_cdr_flags2str(cdr->amaflags), bufsize);
    00182
    00183 #ifdef CSV_LOGUNIQUEID
    00184    /* Unique ID */
    00185    append_string(buf, cdr->uniqueid, bufsize);
    00186 #endif
    00187 #ifdef CSV_LOGUSERFIELD
    00188    /* append the user field */
    00189    append_string(buf, cdr->userfield,bufsize);
    00190 #endif
    00191    /* If we hit the end of our buffer, log an error */
    00192    if (strlen(buf) < bufsize - 5) {
    00193       /* Trim off trailing comma */
    00194       buf[strlen(buf) - 1] = '\0';
    00195       strncat(buf, "\n", bufsize - strlen(buf) - 1);
    00196       return 0;
    00197    }
    00198    return -1;
    00199 }

static int csv_log | ( | struct ast_cdr * | cdr | ) | `[static]`

Definition at line 220 of file cdr_csv.c.

References ast_cdr::accountcode, ast_cdr::amaflags, ast_cdr_disp2str(), ast_cdr_flags2str(), ast_config_AST_LOG_DIR, AST_CONFIG_MAX_PATH, 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().

    00221 {
    00222    /* Make sure we have a big enough buf */
    00223    char buf[1024];
    00224    char csvmaster[AST_CONFIG_MAX_PATH];
    00225    snprintf(csvmaster, sizeof(csvmaster),"%s/%s/%s", ast_config_AST_LOG_DIR, CSV_LOG_DIR, CSV_MASTER);
    00226 #if 0
    00227    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);
    00228 #endif
    00229    if (build_csv_record(buf, sizeof(buf), cdr)) {
    00230       ast_log(LOG_WARNING, "Unable to create CSV record in %d bytes.  CDR not recorded!\n", (int)sizeof(buf));
    00231    } else {
    00232       /* because of the absolutely unconditional need for the
    00233          highest reliability possible in writing billing records,
    00234          we open write and close the log file each time */
    00235       mf = fopen(csvmaster, "a");
    00236       if (!mf) {
    00237          ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno));
    00238       }
    00239       if (mf) {
    00240          fputs(buf, mf);
    00241          fflush(mf); /* be particularly anal here */
    00242          fclose(mf);
    00243          mf = NULL;
    00244       }
    00245       if (!ast_strlen_zero(cdr->accountcode)) {
    00246          if (writefile(buf, cdr->accountcode))
    00247             ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno));
    00248       }
    00249    }
    00250    return 0;
    00251 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 253 of file cdr_csv.c.

    00254 {
    00255    return desc;
    00256 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 289 of file cdr_csv.c.

References ASTERISK_GPL_KEY.

    00290 {
    00291    return ASTERISK_GPL_KEY;
    00292 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 266 of file cdr_csv.c.

References ast_cdr_register(), ast_log(), csv_log(), and LOG_ERROR.

    00267 {
    00268    int res;
    00269
    00270    res = ast_cdr_register(name, desc, csv_log);
    00271    if (res) {
    00272       ast_log(LOG_ERROR, "Unable to register CSV CDR handling\n");
    00273       if (mf)
    00274          fclose(mf);
    00275    }
    00276    return res;
    00277 }

int reload | ( | void |  | ) |

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
  The return value is not used.

Definition at line 279 of file cdr_csv.c.

    00280 {
    00281    return 0;
    00282 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 258 of file cdr_csv.c.

References ast_cdr_unregister().

    00259 {
    00260    if (mf)
    00261       fclose(mf);
    00262    ast_cdr_unregister(name);
    00263    return 0;
    00264 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 284 of file cdr_csv.c.

    00285 {
    00286    return 0;
    00287 }

static int writefile | ( | char * | s,
|  | char * | acc |
| ) |  |  | `[static]`

Definition at line 201 of file cdr_csv.c.

References ast_config_AST_LOG_DIR, AST_CONFIG_MAX_PATH, ast_log(), CSV_LOG_DIR, and LOG_WARNING.

Referenced by csv_log().

    00202 {
    00203    char tmp[AST_CONFIG_MAX_PATH];
    00204    FILE *f;
    00205    if (strchr(acc, '/') || (acc[0] == '.')) {
    00206       ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc);
    00207       return -1;
    00208    }
    00209    snprintf(tmp, sizeof(tmp), "%s/%s/%s.csv", (char *)ast_config_AST_LOG_DIR,CSV_LOG_DIR, acc);
    00210    f = fopen(tmp, "a");
    00211    if (!f)
    00212       return -1;
    00213    fputs(s, f);
    00214    fflush(f);
    00215    fclose(f);
    00216    return 0;
    00217 }

## Variable Documentation

char* desc = "Comma Separated Values CDR Backend"`[static]`

Definition at line 84 of file cdr_csv.c.

FILE* mf = NULL`[static]`

Definition at line 88 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 86 of file cdr_csv.c.