cel_custom.c File Reference

Custom Comma Separated Value CEL records. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include "asterisk/channel.h"
#include "asterisk/cel.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 cel_custom.c:

Go to the source code of this file.

Data Structures

struct  cel_config
 A container that holds all config-related information. More...
struct  sinks

Defines

#define CONFIG   "cel_custom.conf"
#define CUSTOM_BACKEND_NAME   "CEL Custom CSV Logging"
#define CUSTOM_LOG_DIR   "/cel_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 void custom_log (struct ast_event *event)
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 CEL 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 [] = "cel-custom"


Detailed Description

Custom Comma Separated Value CEL records.

Author:
Steve Murphy <murf@digium.com>
Logs in LOG_DIR/cel_custom

Definition in file cel_custom.c.


Define Documentation

#define CONFIG   "cel_custom.conf"

Definition at line 52 of file cel_custom.c.

#define CUSTOM_BACKEND_NAME   "CEL Custom CSV Logging"

Definition at line 67 of file cel_custom.c.

Referenced by load_module(), and unload_module().

#define CUSTOM_LOG_DIR   "/cel_custom"

Definition at line 51 of file cel_custom.c.


Function Documentation

static void __fini_sinks ( void   )  [static]

Definition at line 69 of file cel_custom.c.

00072 {

static void __init_custom_buf ( void   )  [static]

Definition at line 54 of file cel_custom.c.

00058 {

static void __init_sinks ( void   )  [static]

Definition at line 69 of file cel_custom.c.

00072 {

static void __reg_module ( void   )  [static]

Definition at line 225 of file cel_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 225 of file cel_custom.c.

static void custom_log ( struct ast_event event  )  [static]

Definition at line 127 of file cel_custom.c.

References ast_cel_fabricate_channel_from_event(), ast_channel_unref, 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, cel_config::filename, cel_config::format, cel_config::lock, LOG_ERROR, out, and str.

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

static void free_config ( void   )  [static]

Definition at line 71 of file cel_custom.c.

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

00072 {
00073    struct cel_config *sink;
00074    while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
00075       ast_mutex_destroy(&sink->lock);
00076       ast_free(sink);
00077    }
00078 }

static int load_config ( void   )  [static]

Definition at line 80 of file cel_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(), ast_verb, CONFIG, CONFIG_STATUS_FILEINVALID, cel_config::filename, cel_config::format, ast_variable::lineno, cel_config::lock, LOG_ERROR, LOG_NOTICE, ast_variable::name, ast_variable::next, ast_variable::value, and var.

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

static enum ast_module_load_result load_module ( void   )  [static]

Definition at line 190 of file cel_custom.c.

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

00191 {
00192    if (AST_RWLIST_WRLOCK(&sinks)) {
00193       ast_log(LOG_ERROR, "Unable to lock sink list.  Load failed.\n");
00194       return AST_MODULE_LOAD_FAILURE;
00195    }
00196 
00197    load_config();
00198    AST_RWLIST_UNLOCK(&sinks);
00199 
00200    if (ast_cel_backend_register(CUSTOM_BACKEND_NAME, custom_log)) {
00201       return AST_MODULE_LOAD_FAILURE;
00202    }
00203    return AST_MODULE_LOAD_SUCCESS;
00204 }

static int reload ( void   )  [static]

Definition at line 206 of file cel_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.

00207 {
00208    if (AST_RWLIST_WRLOCK(&sinks)) {
00209       ast_log(LOG_ERROR, "Unable to lock sink list.  Load failed.\n");
00210       return AST_MODULE_LOAD_FAILURE;
00211    }
00212 
00213    free_config();
00214    load_config();
00215    AST_RWLIST_UNLOCK(&sinks);
00216    return AST_MODULE_LOAD_SUCCESS;
00217 }

static int unload_module ( void   )  [static]

Definition at line 176 of file cel_custom.c.

References ast_cel_backend_unregister(), ast_log, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CUSTOM_BACKEND_NAME, free_config(), and LOG_ERROR.

00177 {
00178 
00179    if (AST_RWLIST_WRLOCK(&sinks)) {
00180       ast_log(LOG_ERROR, "Unable to lock sink list.  Unload failed.\n");
00181       return -1;
00182    }
00183 
00184    free_config();
00185    AST_RWLIST_UNLOCK(&sinks);
00186    ast_cel_backend_unregister(CUSTOM_BACKEND_NAME);
00187    return 0;
00188 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Customizable Comma Separated Values CEL 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 225 of file cel_custom.c.

Definition at line 225 of file cel_custom.c.

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

Definition at line 54 of file cel_custom.c.

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

Definition at line 56 of file cel_custom.c.


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