cdr_custom.c File Reference

Custom Comma Separated Value CDR records. More...

#include "asterisk.h"
#include <time.h>
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/threadstorage.h"
#include "asterisk/strings.h"

Include dependency graph for cdr_custom.c:

Go to the source code of this file.

Data Structures

struct  cdr_custom_config
struct  sinks

Defines

#define CONFIG   "cdr_custom.conf"
#define CUSTOM_LOG_DIR   "/cdr_custom"

Functions

static void __fini_sinks (void)
static void __init_custom_buf (void)
static void __init_sinks (void)
static void __reg_module (void)
static void __unreg_module (void)
static int custom_log (struct ast_cdr *cdr)
static void free_config (void)
static int load_config (void)
static enum ast_module_load_result load_module (void)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Customizable Comma Separated Values CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_threadstorage custom_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_custom_buf , .custom_init = NULL , }
static const char name [] = "cdr-custom"


Detailed Description

Custom Comma Separated Value CDR records.

Author:
Mark Spencer <markster@digium.com>
Logs in LOG_DIR/cdr_custom

Definition in file cdr_custom.c.


Define Documentation

#define CONFIG   "cdr_custom.conf"

Definition at line 64 of file cdr_custom.c.

#define CUSTOM_LOG_DIR   "/cdr_custom"

Definition at line 63 of file cdr_custom.c.


Function Documentation

static void __fini_sinks ( void   )  [static]

Definition at line 79 of file cdr_custom.c.

00082 {

static void __init_custom_buf ( void   )  [static]

Definition at line 66 of file cdr_custom.c.

00070 {

static void __init_sinks ( void   )  [static]

Definition at line 79 of file cdr_custom.c.

00082 {

static void __reg_module ( void   )  [static]

Definition at line 234 of file cdr_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 234 of file cdr_custom.c.

static int custom_log ( struct ast_cdr cdr  )  [static]

Definition at line 129 of file cdr_custom.c.

References ast_cdr_dup(), ast_channel_cdr_set(), ast_channel_unref, ast_dummy_channel_alloc(), AST_LIST_TRAVERSE, ast_log, ast_mutex_lock, ast_mutex_unlock, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_buffer(), ast_str_substitute_variables(), ast_str_thread_get(), config, custom_buf, dummy(), errno, cdr_custom_config::filename, cdr_custom_config::format, cdr_custom_config::list, cdr_custom_config::lock, LOG_ERROR, out, and str.

Referenced by load_module(), and unload_module().

00130 {
00131    struct ast_channel *dummy;
00132    struct ast_str *str;
00133    struct cdr_custom_config *config;
00134 
00135    /* Batching saves memory management here.  Otherwise, it's the same as doing an allocation and free each time. */
00136    if (!(str = ast_str_thread_get(&custom_buf, 16))) {
00137       return -1;
00138    }
00139 
00140    dummy = ast_dummy_channel_alloc();
00141    if (!dummy) {
00142       ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
00143       return -1;
00144    }
00145 
00146    /* We need to dup here since the cdr actually belongs to the other channel,
00147       so when we release this channel we don't want the CDR getting cleaned
00148       up prematurely. */
00149    ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
00150 
00151    AST_RWLIST_RDLOCK(&sinks);
00152 
00153    AST_LIST_TRAVERSE(&sinks, config, list) {
00154       FILE *out;
00155 
00156       ast_str_substitute_variables(&str, 0, dummy, config->format);
00157 
00158       /* Even though we have a lock on the list, we could be being chased by
00159          another thread and this lock ensures that we won't step on anyone's
00160          toes.  Once each CDR backend gets it's own thread, this lock can be
00161          removed. */
00162       ast_mutex_lock(&config->lock);
00163 
00164       /* Because of the absolutely unconditional need for the
00165          highest reliability possible in writing billing records,
00166          we open write and close the log file each time */
00167       if ((out = fopen(config->filename, "a"))) {
00168          fputs(ast_str_buffer(str), out);
00169          fflush(out); /* be particularly anal here */
00170          fclose(out);
00171       } else {
00172          ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", config->filename, strerror(errno));
00173       }
00174 
00175       ast_mutex_unlock(&config->lock);
00176    }
00177 
00178    AST_RWLIST_UNLOCK(&sinks);
00179 
00180    ast_channel_unref(dummy);
00181 
00182    return 0;
00183 }

static void free_config ( void   )  [static]

Definition at line 81 of file cdr_custom.c.

References ast_free, ast_mutex_destroy, AST_RWLIST_REMOVE_HEAD, and cdr_custom_config::lock.

00082 {
00083    struct cdr_custom_config *sink;
00084    while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
00085       ast_mutex_destroy(&sink->lock);
00086       ast_free(sink);
00087    }
00088 }

static int load_config ( void   )  [static]

Definition at line 90 of file cdr_custom.c.

References ast_calloc_with_stringfields, ast_config_AST_LOG_DIR, ast_config_destroy(), ast_config_load, ast_log, ast_mutex_init, AST_RWLIST_INSERT_TAIL, ast_string_field_build, ast_strlen_zero, ast_variable_browse(), CONFIG, CONFIG_STATUS_FILEINVALID, cdr_custom_config::filename, cdr_custom_config::format, ast_variable::lineno, cdr_custom_config::list, cdr_custom_config::lock, LOG_ERROR, LOG_NOTICE, ast_variable::name, ast_variable::next, ast_variable::value, and var.

00091 {
00092    struct ast_config *cfg;
00093    struct ast_variable *var;
00094    struct ast_flags config_flags = { 0 };
00095    int res = 0;
00096 
00097    cfg = ast_config_load(CONFIG, config_flags);
00098    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
00099       ast_log(LOG_ERROR, "Unable to load " CONFIG ". Not logging custom CSV CDRs.\n");
00100       return -1;
00101    }
00102 
00103    var = ast_variable_browse(cfg, "mappings");
00104    while (var) {
00105       if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
00106          struct cdr_custom_config *sink = ast_calloc_with_stringfields(1, struct cdr_custom_config, 1024);
00107 
00108          if (!sink) {
00109             ast_log(LOG_ERROR, "Unable to allocate memory for configuration settings.\n");
00110             res = -2;
00111             break;
00112          }
00113 
00114          ast_string_field_build(sink, format, "%s\n", var->value);
00115          ast_string_field_build(sink, filename, "%s/%s/%s", ast_config_AST_LOG_DIR, name, var->name);
00116          ast_mutex_init(&sink->lock);
00117 
00118          AST_RWLIST_INSERT_TAIL(&sinks, sink, list);
00119       } else {
00120          ast_log(LOG_NOTICE, "Mapping must have both a filename and a format at line %d\n", var->lineno);
00121       }
00122       var = var->next;
00123    }
00124    ast_config_destroy(cfg);
00125 
00126    return res;
00127 }

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 202 of file cdr_custom.c.

References ast_cdr_register(), ast_log, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, custom_log(), load_config(), and LOG_ERROR.

00203 {
00204    if (AST_RWLIST_WRLOCK(&sinks)) {
00205       ast_log(LOG_ERROR, "Unable to lock sink list.  Load failed.\n");
00206       return AST_MODULE_LOAD_FAILURE;
00207    }
00208 
00209    load_config();
00210    AST_RWLIST_UNLOCK(&sinks);
00211    ast_cdr_register(name, ast_module_info->description, custom_log);
00212    return AST_MODULE_LOAD_SUCCESS;
00213 }

static int reload ( void   )  [static]

Definition at line 215 of file cdr_custom.c.

References ast_log, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, free_config(), load_config(), and LOG_ERROR.

00216 {
00217    if (AST_RWLIST_WRLOCK(&sinks)) {
00218       ast_log(LOG_ERROR, "Unable to lock sink list.  Load failed.\n");
00219       return AST_MODULE_LOAD_FAILURE;
00220    }
00221 
00222    free_config();
00223    load_config();
00224    AST_RWLIST_UNLOCK(&sinks);
00225    return AST_MODULE_LOAD_SUCCESS;
00226 }

static int unload_module ( void   )  [static]

Definition at line 185 of file cdr_custom.c.

References ast_cdr_register(), ast_cdr_unregister(), ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, custom_log(), free_config(), and LOG_ERROR.

00186 {
00187    if (ast_cdr_unregister(name)) {
00188       return -1;
00189    }
00190 
00191    if (AST_RWLIST_WRLOCK(&sinks)) {
00192       ast_cdr_register(name, ast_module_info->description, custom_log);
00193       ast_log(LOG_ERROR, "Unable to lock sink list.  Unload failed.\n");
00194       return -1;
00195    }
00196 
00197    free_config();
00198    AST_RWLIST_UNLOCK(&sinks);
00199    return 0;
00200 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Customizable Comma Separated Values CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 234 of file cdr_custom.c.

Definition at line 234 of file cdr_custom.c.

struct ast_threadstorage custom_buf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_custom_buf , .custom_init = NULL , } [static]

Definition at line 66 of file cdr_custom.c.

Referenced by custom_log().

const char name[] = "cdr-custom" [static]

Definition at line 68 of file cdr_custom.c.


Generated on Thu Apr 16 06:29:24 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6