Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
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
 

Macros

#define CONFIG   "cel_custom.conf"
 
#define CUSTOM_BACKEND_NAME   "CEL Custom CSV Logging"
 
#define CUSTOM_LOG_DIR   "/cel_custom"
 

Functions

static void __init_custom_buf (void)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
 
static const 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"
 
static struct sinks sinks = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

Custom Comma Separated Value CEL records.

Author
Steve Murphy murf@.nosp@m.digi.nosp@m.um.co.nosp@m.m

Logs in LOG_DIR/cel_custom

Definition in file cel_custom.c.

Macro Definition Documentation

◆ CONFIG

#define CONFIG   "cel_custom.conf"

Definition at line 50 of file cel_custom.c.

Referenced by load_config().

◆ CUSTOM_BACKEND_NAME

#define CUSTOM_BACKEND_NAME   "CEL Custom CSV Logging"

Definition at line 65 of file cel_custom.c.

Referenced by load_module(), and unload_module().

◆ CUSTOM_LOG_DIR

#define CUSTOM_LOG_DIR   "/cel_custom"

Definition at line 49 of file cel_custom.c.

Function Documentation

◆ __init_custom_buf()

static void __init_custom_buf ( void  )
static

Definition at line 52 of file cel_custom.c.

56 {

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 227 of file cel_custom.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 227 of file cel_custom.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 227 of file cel_custom.c.

◆ custom_log()

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.

Referenced by load_module().

128 {
129  struct ast_channel *dummy;
130  struct ast_str *str;
131  struct cel_config *config;
132 
133  /* Batching saves memory management here. Otherwise, it's the same as doing an allocation and free each time. */
134  if (!(str = ast_str_thread_get(&custom_buf, 16))) {
135  return;
136  }
137 
139  if (!dummy) {
140  ast_log(LOG_ERROR, "Unable to fabricate channel from CEL event.\n");
141  return;
142  }
143 
145 
146  AST_LIST_TRAVERSE(&sinks, config, list) {
147  FILE *out;
148 
149  ast_str_substitute_variables(&str, 0, dummy, config->format);
150 
151  /* Even though we have a lock on the list, we could be being chased by
152  another thread and this lock ensures that we won't step on anyone's
153  toes. Once each CEL backend gets it's own thread, this lock can be
154  removed. */
155  ast_mutex_lock(&config->lock);
156 
157  /* Because of the absolutely unconditional need for the
158  highest reliability possible in writing billing records,
159  we open write and close the log file each time */
160  if ((out = fopen(config->filename, "a"))) {
161  fputs(ast_str_buffer(str), out);
162  fflush(out); /* be particularly anal here */
163  fclose(out);
164  } else {
165  ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", config->filename, strerror(errno));
166  }
167 
168  ast_mutex_unlock(&config->lock);
169  }
170 
172 
173  ast_channel_unref(dummy);
174 }
Main Channel structure associated with a channel.
A container that holds all config-related information.
Definition: cel_custom.c:56
char * config
Definition: conf2ael.c:66
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
static struct ast_threadstorage custom_buf
Definition: cel_custom.c:52
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
const ast_string_field filename
Definition: cel_custom.c:60
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#define ast_mutex_lock(a)
Definition: lock.h:187
const char * str
Definition: app_jack.c:147
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
int errno
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct ast_channel * ast_cel_fabricate_channel_from_event(const struct ast_event *event)
Create a fake channel from data in a CEL event.
Definition: cel.c:660
FILE * out
Definition: utils/frame.c:33
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:861
const ast_string_field format
Definition: cel_custom.c:60
ast_mutex_t lock
Definition: cel_custom.c:61
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ free_config()

static void free_config ( void  )
static

Definition at line 69 of file cel_custom.c.

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

Referenced by load_module(), reload(), and unload_module().

70 {
71  struct cel_config *sink;
72 
73  while ((sink = AST_RWLIST_REMOVE_HEAD(&sinks, list))) {
74  ast_mutex_destroy(&sink->lock);
76  ast_free(sink);
77  }
78 }
A container that holds all config-related information.
Definition: cel_custom.c:56
#define ast_free(a)
Definition: astmm.h:182
#define AST_RWLIST_REMOVE_HEAD
Definition: linkedlists.h:843
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
ast_mutex_t lock
Definition: cel_custom.c:61

◆ load_config()

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, name, ast_variable::name, ast_variable::next, ast_variable::value, and var.

Referenced by load_module(), and reload().

81 {
82  struct ast_config *cfg;
83  struct ast_variable *var;
84  struct ast_flags config_flags = { 0 };
85  int mappings = 0;
86  int res = 0;
87 
88  cfg = ast_config_load(CONFIG, config_flags);
89  if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
90  ast_log(LOG_ERROR, "Unable to load " CONFIG ". Not logging CEL to custom CSVs.\n");
91  return -1;
92  }
93 
94  if (!(var = ast_variable_browse(cfg, "mappings"))) {
95  ast_log(LOG_NOTICE, "No mappings found in " CONFIG ". Not logging CEL to custom CSVs.\n");
96  }
97 
98  while (var) {
99  if (!ast_strlen_zero(var->name) && !ast_strlen_zero(var->value)) {
100  struct cel_config *sink = ast_calloc_with_stringfields(1, struct cel_config, 1024);
101 
102  if (!sink) {
103  ast_log(LOG_ERROR, "Unable to allocate memory for configuration settings.\n");
104  res = -2;
105  break;
106  }
107 
108  ast_string_field_build(sink, format, "%s\n", var->value);
110  ast_mutex_init(&sink->lock);
111 
112  ast_verb(3, "Added CEL CSV mapping for '%s'.\n", sink->filename);
113  mappings += 1;
114  AST_RWLIST_INSERT_TAIL(&sinks, sink, list);
115  } else {
116  ast_log(LOG_NOTICE, "Mapping must have both a filename and a format at line %d\n", var->lineno);
117  }
118  var = var->next;
119  }
120  ast_config_destroy(cfg);
121 
122  ast_verb(1, "Added CEL CSV mapping for %d files.\n", mappings);
123 
124  return res;
125 }
struct ast_variable * next
A container that holds all config-related information.
Definition: cel_custom.c:56
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1216
#define CONFIG
Definition: cel_custom.c:50
#define CONFIG_STATUS_FILEINVALID
const ast_string_field filename
Definition: cel_custom.c:60
Structure for variables, used for configurations and for channel variables.
#define var
Definition: ast_expr2f.c:614
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:426
static const char name[]
Definition: cel_custom.c:54
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_config_load(filename, flags)
Load a config file.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define LOG_ERROR
Definition: logger.h:285
#define LOG_NOTICE
Definition: logger.h:263
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
Definition: stringfields.h:550
Structure used to handle boolean flags.
Definition: utils.h:199
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:740
#define ast_mutex_init(pmutex)
Definition: lock.h:184
static snd_pcm_format_t format
Definition: chan_alsa.c:102
ast_mutex_t lock
Definition: cel_custom.c:61

◆ load_module()

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_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, CUSTOM_BACKEND_NAME, custom_log(), free_config(), load_config(), and LOG_ERROR.

Referenced by reload().

191 {
192  if (AST_RWLIST_WRLOCK(&sinks)) {
193  ast_log(LOG_ERROR, "Unable to lock sink list. Load failed.\n");
195  }
196 
197  load_config();
199 
201  free_config();
203  }
205 }
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
Definition: cel.c:1740
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define CUSTOM_BACKEND_NAME
Definition: cel_custom.c:65
static void custom_log(struct ast_event *event)
Definition: cel_custom.c:127
static int load_config(void)
Definition: cel_custom.c:80
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void free_config(void)
Definition: cel_custom.c:69

◆ reload()

static int reload ( void  )
static

Definition at line 207 of file cel_custom.c.

References ast_log, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CDR_DRIVER, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ASTERISK_GPL_KEY, free_config(), load_config(), load_module(), LOG_ERROR, and unload_module().

208 {
209  if (AST_RWLIST_WRLOCK(&sinks)) {
210  ast_log(LOG_ERROR, "Unable to lock sink list. Load failed.\n");
212  }
213 
214  free_config();
215  load_config();
218 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
static int load_config(void)
Definition: cel_custom.c:80
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void free_config(void)
Definition: cel_custom.c:69

◆ unload_module()

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.

Referenced by reload().

177 {
178 
179  if (AST_RWLIST_WRLOCK(&sinks)) {
180  ast_log(LOG_ERROR, "Unable to lock sink list. Unload failed.\n");
181  return -1;
182  }
183 
184  free_config();
187  return 0;
188 }
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
#define ast_log
Definition: astobj2.c:42
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
Definition: cel.c:1728
#define LOG_ERROR
Definition: logger.h:285
#define CUSTOM_BACKEND_NAME
Definition: cel_custom.c:65
static void free_config(void)
Definition: cel_custom.c:69

Variable Documentation

◆ __mod_info

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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
static

Definition at line 227 of file cel_custom.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 227 of file cel_custom.c.

◆ custom_buf

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

Definition at line 52 of file cel_custom.c.

Referenced by custom_log().

◆ name

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

Definition at line 54 of file cel_custom.c.

Referenced by load_config().

◆ sinks

struct sinks sinks = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static