Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:49 2009

## Asterisk developer's documentation

# cdr_custom.c

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * Includes code and algorithms from the Zapata library.
    00009  *
    00010  * See http://www.asterisk.org for more information about
    00011  * the Asterisk project. Please do not directly contact
    00012  * any of the maintainers of this project for assistance;
    00013  * the project provides a web site, mailing lists and IRC
    00014  * channels for your use.
    00015  *
    00016  * This program is free software, distributed under the terms of
    00017  * the GNU General Public License Version 2. See the LICENSE file
    00018  * at the top of the source tree.
    00019  */
    00020
    00021 /*! \file
    00022  *
    00023  * \brief Custom Comma Separated Value CDR records.
    00024  *
    00025  * \arg See also \ref AstCDR
    00026  *
    00027  * Logs in LOG_DIR/cdr_custom
    00028  * \ingroup cdr_drivers
    00029  */
    00030
    00031 #include <sys/types.h>
    00032 #include <stdio.h>
    00033 #include <string.h>
    00034 #include <errno.h>
    00035
    00036 #include <stdlib.h>
    00037 #include <unistd.h>
    00038 #include <time.h>
    00039
    00040 #include "asterisk.h"
    00041
    00042 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 70804 $")
    00043
    00044 #include "asterisk/channel.h"
    00045 #include "asterisk/cdr.h"
    00046 #include "asterisk/module.h"
    00047 #include "asterisk/config.h"
    00048 #include "asterisk/pbx.h"
    00049 #include "asterisk/logger.h"
    00050 #include "asterisk/utils.h"
    00051
    00052 #define CUSTOM_LOG_DIR "/cdr_custom"
    00053
    00054 #define DATE_FORMAT "%Y-%m-%d %T"
    00055
    00056 AST_MUTEX_DEFINE_STATIC(lock);
    00057
    00058 static char *desc = "Customizable Comma Separated Values CDR Backend";
    00059
    00060 static char *name = "cdr-custom";
    00061
    00062 static FILE *mf = NULL;
    00063
    00064 static char master[AST_CONFIG_MAX_PATH];
    00065 static char format[1024]="";
    00066
    00067 static int load_config(int reload)
    00068 {
    00069    struct ast_config *cfg;
    00070    struct ast_variable *var;
    00071    int res = -1;
    00072
    00073    strcpy(format, "");
    00074    strcpy(master, "");
    00075    ast_mutex_lock(&lock);
    00076    if((cfg = ast_config_load("cdr_custom.conf"))) {
    00077       var = ast_variable_browse(cfg, "mappings");
    00078       while(var) {
    00079          if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
    00080             if (strlen(var->value) > (sizeof(format) - 2))
    00081                ast_log(LOG_WARNING, "Format string too long, will be truncated, at line %d\n", var->lineno);
    00082             strncpy(format, var->value, sizeof(format) - 2);
    00083             strcat(format,"\n");
    00084             snprintf(master, sizeof(master),"%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
    00085             if (var->next) {
    00086                ast_log(LOG_NOTICE, "Sorry, only one mapping is supported at this time, mapping '%s' will be ignored at line %d.\n", var->next->name, var->next->lineno);
    00087                break;
    00088             }
    00089          } else
    00090             ast_log(LOG_NOTICE, "Mapping must have both filename and format at line %d\n", var->lineno);
    00091          var = var->next;
    00092       }
    00093       ast_config_destroy(cfg);
    00094       res = 0;
    00095    } else {
    00096       if (reload)
    00097          ast_log(LOG_WARNING, "Failed to reload configuration file.\n");
    00098       else
    00099          ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n");
    00100    }
    00101    ast_mutex_unlock(&lock);
    00102
    00103    return res;
    00104 }
    00105
    00106
    00107
    00108 static int custom_log(struct ast_cdr *cdr)
    00109 {
    00110    /* Make sure we have a big enough buf */
    00111    char buf[2048];
    00112    struct ast_channel dummy;
    00113
    00114    /* Abort if no master file is specified */
    00115    if (ast_strlen_zero(master))
    00116       return 0;
    00117
    00118    memset(buf, 0 , sizeof(buf));
    00119    /* Quite possibly the first use of a static struct ast_channel, we need it so the var funcs will work */
    00120    memset(&dummy, 0, sizeof(dummy));
    00121    dummy.cdr = cdr;
    00122    pbx_substitute_variables_helper(&dummy, format, buf, sizeof(buf) - 1);
    00123
    00124    /* because of the absolutely unconditional need for the
    00125       highest reliability possible in writing billing records,
    00126       we open write and close the log file each time */
    00127    mf = fopen(master, "a");
    00128    if (!mf) {
    00129       ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", master, strerror(errno));
    00130    }
    00131    if (mf) {
    00132       fputs(buf, mf);
    00133       fflush(mf); /* be particularly anal here */
    00134       fclose(mf);
    00135       mf = NULL;
    00136    }
    00137    return 0;
    00138 }
    00139
    00140 char *description(void)
    00141 {
    00142    return desc;
    00143 }
    00144
    00145 int unload_module(void)
    00146 {
    00147    if (mf)
    00148       fclose(mf);
    00149    ast_cdr_unregister(name);
    00150    return 0;
    00151 }
    00152
    00153 int load_module(void)
    00154 {
    00155    int res = 0;
    00156
    00157    if (!load_config(0)) {
    00158       res = ast_cdr_register(name, desc, custom_log);
    00159       if (res)
    00160          ast_log(LOG_ERROR, "Unable to register custom CDR handling\n");
    00161       if (mf)
    00162          fclose(mf);
    00163    }
    00164    return res;
    00165 }
    00166
    00167 int reload(void)
    00168 {
    00169    return load_config(1);
    00170 }
    00171
    00172 int usecount(void)
    00173 {
    00174    return 0;
    00175 }
    00176
    00177 char *key()
    00178 {
    00179    return ASTERISK_GPL_KEY;
    00180 }