Asterisk - The Open Source Telephony Project GIT-master-2de1a68
Data Structures | Macros | Functions | Variables
cel_sqlite3_custom.c File Reference

Custom SQLite3 CEL records. More...

#include "asterisk.h"
#include <sqlite3.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/logger.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/stringfields.h"
Include dependency graph for cel_sqlite3_custom.c:

Go to the source code of this file.

Data Structures

struct  sql_values
 
struct  values
 

Macros

#define SQLITE_BACKEND_NAME   "CEL sqlite3 custom backend"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void free_config (void)
 
static int load_column_config (const char *tmp)
 
static int load_config (int reload)
 
static int load_module (void)
 
static int load_values_config (const char *tmp)
 
static int reload (void)
 
static int unload_module (void)
 
static void write_cel (struct ast_event *event)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite3 Custom CEL Module" , .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_EXTENDED, .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 int busy_timeout
 
static char * columns
 
static const char config_file [] = "cel_sqlite3_custom.conf"
 
static sqlite3 * db = NULL
 
static ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static struct sql_values sql_values = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static char table [80]
 

Detailed Description

Custom SQLite3 CEL records.

Author
Adapted by Steve Murphy murf@.nosp@m.digi.nosp@m.um.co.nosp@m.m from Alejandro Rios aleja.nosp@m.ndro.nosp@m..rios.nosp@m.@ava.nosp@m.tar.c.nosp@m.om.c.nosp@m.o and Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com from cdr_mysql_custom by Edward Eastman ed@dm.nosp@m.3.co.nosp@m..uk, and cdr_sqlite by Holger Schurig hs423.nosp@m.3@ma.nosp@m.il.mn.nosp@m.-sol.nosp@m.ution.nosp@m.s.de

Definition in file cel_sqlite3_custom.c.

Macro Definition Documentation

◆ SQLITE_BACKEND_NAME

#define SQLITE_BACKEND_NAME   "CEL sqlite3 custom backend"

Definition at line 53 of file cel_sqlite3_custom.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 359 of file cel_sqlite3_custom.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 359 of file cel_sqlite3_custom.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 359 of file cel_sqlite3_custom.c.

◆ free_config()

static void free_config ( void  )
static

Definition at line 216 of file cel_sqlite3_custom.c.

217{
218 struct values *value;
219
220 if (db) {
221 sqlite3_close(db);
222 db = NULL;
223 }
224
225 if (columns) {
227 columns = NULL;
228 }
229
232 }
233}
#define ast_free(a)
Definition: astmm.h:180
static sqlite3 * db
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define NULL
Definition: resample.c:96
struct values::@107 list
int value
Definition: syslog.c:37

References ast_free, AST_LIST_REMOVE_HEAD, db, values::list, NULL, and value.

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

◆ load_column_config()

static int load_column_config ( const char *  tmp)
static

Definition at line 77 of file cel_sqlite3_custom.c.

78{
79 char *col = NULL;
80 char *cols = NULL, *save = NULL;
81 char *escaped = NULL;
82 struct ast_str *column_string = NULL;
83
84 if (ast_strlen_zero(tmp)) {
85 ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
86 return -1;
87 }
88 if (!(column_string = ast_str_create(1024))) {
89 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
90 return -1;
91 }
92 if (!(save = cols = ast_strdup(tmp))) {
93 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
94 ast_free(column_string);
95 return -1;
96 }
97 while ((col = strsep(&cols, ","))) {
98 col = ast_strip(col);
99 escaped = sqlite3_mprintf("%q", col);
100 if (!escaped) {
101 ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
102 ast_free(column_string);
103 ast_free(save);
104 return -1;
105 }
106 ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
107 sqlite3_free(escaped);
108 }
109 if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
110 ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
111 ast_free(column_string);
112 ast_free(save);
113 return -1;
114 }
115 ast_free(column_string);
116 ast_free(save);
117
118 return 0;
119}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
static char table[80]
char * strsep(char **str, const char *delims)
#define LOG_ERROR
#define LOG_WARNING
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
Support for dynamic strings.
Definition: strings.h:623

References ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), ast_strdup, ast_strip(), ast_strlen_zero(), LOG_ERROR, LOG_WARNING, NULL, strsep(), table, and tmp().

Referenced by load_config().

◆ load_config()

static int load_config ( int  reload)
static

Definition at line 153 of file cel_sqlite3_custom.c.

154{
155 struct ast_config *cfg;
156 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
157 struct ast_variable *mappingvar;
158 const char *tmp;
159
160 if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
161 ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n",
162 reload ? "re" : "", reload ? "" : "Module not activated.");
163 return -1;
164 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
165 return 0;
166 }
167
168 if (reload) {
169 free_config();
170 }
171
172 if (!(mappingvar = ast_variable_browse(cfg, "master"))) {
173 /* Nothing configured */
175 return -1;
176 }
177
178 /* Mapping must have a table name */
179 if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
180 ast_copy_string(table, tmp, sizeof(table));
181 } else {
182 ast_log(LOG_WARNING, "Table name not specified. Assuming cel.\n");
183 strcpy(table, "cel");
184 }
185
186 /* sqlite3_busy_timeout in miliseconds */
187 if ((tmp = ast_variable_retrieve(cfg, "master", "busy_timeout")) != NULL) {
189 ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' specified. Using 1000 instead.\n", tmp);
190 }
191 } else {
192 busy_timeout = 1000;
193 }
194
195 /* Columns */
196 if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
198 free_config();
199 return -1;
200 }
201
202 /* Values */
203 if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
205 free_config();
206 return -1;
207 }
208
209 ast_verb(3, "Logging CEL records to table '%s' in 'master.db'\n", table);
210
212
213 return 0;
214}
static int load_values_config(const char *tmp)
static int load_column_config(const char *tmp)
static void free_config(void)
static int busy_timeout
static const char config_file[]
static int reload(void)
#define ast_config_load(filename, flags)
Load a config file.
#define CONFIG_STATUS_FILEMISSING
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
Definition: main/config.c:3827
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:783
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_verb(level,...)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
Structure used to handle boolean flags.
Definition: utils.h:199
Structure for variables, used for configurations and for channel variables.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log, ast_parse_arg(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, busy_timeout, config_file, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), LOG_WARNING, NULL, PARSE_DEFAULT, PARSE_INT32, reload(), table, and tmp().

Referenced by load_module(), and reload().

◆ load_module()

static int load_module ( void  )
static

Definition at line 295 of file cel_sqlite3_custom.c.

296{
297 char *error;
298 char filename[PATH_MAX];
299 int res;
300 char *sql;
301
302 if (load_config(0)) {
304 }
305
306 /* is the database there? */
307 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
308 res = sqlite3_open(filename, &db);
309 if (res != SQLITE_OK) {
310 ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
311 free_config();
313 }
314 sqlite3_busy_timeout(db, busy_timeout);
315 /* is the table there? */
316 sql = sqlite3_mprintf("SELECT COUNT(*) FROM %q;", table);
317 res = sqlite3_exec(db, sql, NULL, NULL, NULL);
318 sqlite3_free(sql);
319 if (res != SQLITE_OK) {
320 /* We don't use %q for the column list here since we already escaped when building it */
321 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
322 res = sqlite3_exec(db, sql, NULL, NULL, &error);
323 sqlite3_free(sql);
324 if (res != SQLITE_OK) {
325 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
326 sqlite3_free(error);
327 free_config();
329 }
330 }
331
333 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CEL handling\n");
334 free_config();
336 }
337
339}
#define PATH_MAX
Definition: asterisk.h:40
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
Definition: cel.c:1781
#define SQLITE_BACKEND_NAME
static void write_cel(struct ast_event *event)
static int load_config(int reload)
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
const char * ast_config_AST_LOG_DIR
Definition: options.c:159
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_cel_backend_register(), ast_config_AST_LOG_DIR, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, busy_timeout, db, error(), free_config(), load_config(), LOG_ERROR, LOG_WARNING, NULL, PATH_MAX, SQLITE_BACKEND_NAME, table, and write_cel().

◆ load_values_config()

static int load_values_config ( const char *  tmp)
static

Definition at line 121 of file cel_sqlite3_custom.c.

122{
123 char *val = NULL;
124 char *vals = NULL, *save = NULL;
125 struct values *value = NULL;
126
127 if (ast_strlen_zero(tmp)) {
128 ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
129 return -1;
130 }
131 if (!(save = vals = ast_strdup(tmp))) {
132 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
133 return -1;
134 }
135 while ((val = strsep(&vals, ","))) {
136 /* Strip the single quotes off if they are there */
137 val = ast_strip_quoted(val, "'", "'");
138 value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1);
139 if (!value) {
140 ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val);
141 ast_free(save);
142 return -1;
143 }
144 value->expression = (char *) value + sizeof(*value);
145 ast_copy_string(value->expression, val, strlen(val) + 1);
147 }
148 ast_free(save);
149
150 return 0;
151}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
Definition: ast_expr2.c:325

References ast_calloc, ast_copy_string(), ast_free, AST_LIST_INSERT_TAIL, ast_log, ast_strdup, ast_strip_quoted(), ast_strlen_zero(), values::list, LOG_ERROR, LOG_WARNING, NULL, strsep(), tmp(), and value.

Referenced by load_config().

◆ reload()

static int reload ( void  )
static

Definition at line 341 of file cel_sqlite3_custom.c.

342{
343 int res = 0;
344
346 res = load_config(1);
348
349 return res;
350}
static ast_mutex_t lock
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189

References ast_mutex_lock, ast_mutex_unlock, load_config(), and lock.

Referenced by load_config().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 286 of file cel_sqlite3_custom.c.

287{
289
290 free_config();
291
292 return 0;
293}
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
Definition: cel.c:1769

References ast_cel_backend_unregister(), free_config(), and SQLITE_BACKEND_NAME.

◆ write_cel()

static void write_cel ( struct ast_event event)
static

Definition at line 235 of file cel_sqlite3_custom.c.

236{
237 char *error = NULL;
238 char *sql = NULL;
239
240 if (db == NULL) {
241 /* Should not have loaded, but be failsafe. */
242 return;
243 }
244
246
247 { /* Make it obvious that only sql should be used outside of this block */
248 char *escaped;
249 char subst_buf[2048];
250 struct values *value;
251 struct ast_channel *dummy;
252 struct ast_str *value_string = ast_str_create(1024);
253
255 if (!dummy) {
256 ast_log(LOG_ERROR, "Unable to fabricate channel from CEL event.\n");
257 ast_free(value_string);
259 return;
260 }
262 pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
263 escaped = sqlite3_mprintf("%q", subst_buf);
264 ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
265 sqlite3_free(escaped);
266 }
267 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
268 ast_debug(1, "About to log: %s\n", sql);
270 ast_free(value_string);
271 }
272
273 if (sqlite3_exec(db, sql, NULL, NULL, &error) != SQLITE_OK) {
274 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
275 sqlite3_free(error);
276 }
277
278 if (sql) {
279 sqlite3_free(sql);
280 }
282
283 return;
284}
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:662
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
Main Channel structure associated with a channel.
Definition: astman.c:222

References ast_cel_fabricate_channel_from_event(), ast_channel_unref, ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log, ast_mutex_lock, ast_mutex_unlock, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), db, dummy(), error(), lock, LOG_ERROR, NULL, pbx_substitute_variables_helper(), table, and value.

Referenced by load_module().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite3 Custom CEL Module" , .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_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, .requires = "cel", }
static

Definition at line 359 of file cel_sqlite3_custom.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 359 of file cel_sqlite3_custom.c.

◆ busy_timeout

int busy_timeout
static

Definition at line 66 of file cel_sqlite3_custom.c.

Referenced by load_config(), and load_module().

◆ columns

char* columns
static
Bug:
Handling of this var is crash prone on reloads

Definition at line 65 of file cel_sqlite3_custom.c.

◆ config_file

const char config_file[] = "cel_sqlite3_custom.conf"
static

Definition at line 57 of file cel_sqlite3_custom.c.

Referenced by load_config().

◆ db

sqlite3* db = NULL
static

Definition at line 59 of file cel_sqlite3_custom.c.

Referenced by free_config(), load_module(), and write_cel().

◆ lock

ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Definition at line 55 of file cel_sqlite3_custom.c.

Referenced by reload(), and write_cel().

◆ sql_values

struct sql_values sql_values = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
static

◆ table

char table[80]
static

Definition at line 61 of file cel_sqlite3_custom.c.

Referenced by load_column_config(), load_config(), load_module(), and write_cel().