Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Functions | Variables
cdr_sqlite3_custom.c File Reference

Custom SQLite3 CDR records. More...

#include "asterisk.h"
#include <sqlite3.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/cli.h"
#include "asterisk/app.h"
Include dependency graph for cdr_sqlite3_custom.c:

Go to the source code of this file.

Data Structures

struct  sql_values
 
struct  values
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void free_config (int reload)
 
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 int write_cdr (struct ast_cdr *cdr)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "SQLite3 Custom CDR 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 = "cdr", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static int busy_timeout
 
static char * columns
 
static const char config_file [] = "cdr_sqlite3_custom.conf"
 
static sqlite3 * db = NULL
 
static const char desc [] = "Customizable SQLite3 CDR Backend"
 
static ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static const char name [] = "cdr_sqlite3_custom"
 
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 CDR records.

Author
Adapted by 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 cdr_sqlite3_custom.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 364 of file cdr_sqlite3_custom.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 364 of file cdr_sqlite3_custom.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 364 of file cdr_sqlite3_custom.c.

◆ free_config()

static void free_config ( int  reload)
static

Definition at line 215 of file cdr_sqlite3_custom.c.

216{
217 struct values *value;
218
219 if (!reload && db) {
220 sqlite3_close(db);
221 db = NULL;
222 }
223
224 if (columns) {
226 columns = NULL;
227 }
228
231 }
232}
#define ast_free(a)
Definition: astmm.h:180
static int reload(void)
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, reload(), 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 75 of file cdr_sqlite3_custom.c.

76{
77 char *col = NULL;
78 char *cols = NULL, *save = NULL;
79 char *escaped = NULL;
80 struct ast_str *column_string = NULL;
81
82 if (ast_strlen_zero(tmp)) {
83 ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
84 return -1;
85 }
86 if (!(column_string = ast_str_create(1024))) {
87 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
88 return -1;
89 }
90 if (!(save = cols = ast_strdup(tmp))) {
91 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
92 ast_free(column_string);
93 return -1;
94 }
95 while ((col = strsep(&cols, ","))) {
96 col = ast_strip(col);
97 escaped = sqlite3_mprintf("%q", col);
98 if (!escaped) {
99 ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
100 ast_free(column_string);
101 ast_free(save);
102 return -1;
103 }
104 ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
105 sqlite3_free(escaped);
106 }
107 if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
108 ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
109 ast_free(column_string);
110 ast_free(save);
111 return -1;
112 }
113 ast_free(column_string);
114 ast_free(save);
115
116 return 0;
117}
#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 154 of file cdr_sqlite3_custom.c.

155{
156 struct ast_config *cfg;
157 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
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", reload ? "re" : "", reload ? "" : "Module not activated.");
162 return -1;
163 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
164 return 0;
165 }
166
167 if (reload) {
168 free_config(1);
169 }
170
171 if (!ast_variable_browse(cfg, "master")) {
172 /* Nothing configured */
174 return -1;
175 }
176
177 /* Mapping must have a table name */
178 if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
179 ast_copy_string(table, tmp, sizeof(table));
180 } else {
181 ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n");
182 strcpy(table, "cdr");
183 }
184
185 /* sqlite3_busy_timeout in miliseconds */
186 if ((tmp = ast_variable_retrieve(cfg, "master", "busy_timeout")) != NULL) {
188 ast_log(LOG_WARNING, "Invalid busy_timeout value '%s' specified. Using 1000 instead.\n", tmp);
189 }
190 } else {
191 busy_timeout = 1000;
192 }
193
194 /* Columns */
195 if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
197 free_config(0);
198 return -1;
199 }
200
201 /* Values */
202 if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
204 free_config(0);
205 return -1;
206 }
207
208 ast_verb(4, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
209
211
212 return 0;
213}
static int load_values_config(const char *tmp)
static int load_column_config(const char *tmp)
static int busy_timeout
static const char config_file[]
static void free_config(int reload)
#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

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 299 of file cdr_sqlite3_custom.c.

300{
301 char *error;
302 char filename[PATH_MAX];
303 int res;
304 char *sql;
305
306 if (load_config(0)) {
308 }
309
310 /* is the database there? */
311 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
312 res = sqlite3_open(filename, &db);
313 if (res != SQLITE_OK) {
314 ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
315 free_config(0);
317 }
318 sqlite3_busy_timeout(db, busy_timeout);
319 /* is the table there? */
320 sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
321 res = sqlite3_exec(db, sql, NULL, NULL, NULL);
322 sqlite3_free(sql);
323 if (res != SQLITE_OK) {
324 /* We don't use %q for the column list here since we already escaped when building it */
325 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
326 res = sqlite3_exec(db, sql, NULL, NULL, &error);
327 sqlite3_free(sql);
328 if (res != SQLITE_OK) {
329 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
330 sqlite3_free(error);
331 free_config(0);
333 }
334 }
335
337 if (res) {
338 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
339 free_config(0);
341 }
342
344}
#define PATH_MAX
Definition: asterisk.h:40
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
Definition: cdr.c:3005
static const char name[]
static const char desc[]
static int write_cdr(struct ast_cdr *cdr)
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_cdr_register(), ast_config_AST_LOG_DIR, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, busy_timeout, db, desc, error(), free_config(), load_config(), LOG_ERROR, LOG_WARNING, name, NULL, PATH_MAX, table, and write_cdr().

◆ load_values_config()

static int load_values_config ( const char *  tmp)
static

Definition at line 119 of file cdr_sqlite3_custom.c.

120{
121 char *vals = NULL, *save = NULL;
122 struct values *value = NULL;
123 int i;
125 AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR? Yeah, right... */
126 );
127
128 if (ast_strlen_zero(tmp)) {
129 ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
130 return -1;
131 }
132 if (!(save = vals = ast_strdup(tmp))) {
133 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
134 return -1;
135 }
137 for (i = 0; i < val.argc; i++) {
138 /* Strip the single quotes off if they are there */
139 char *v = ast_strip_quoted(val.ues[i], "'", "'");
140 value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v));
141 if (!value) {
142 ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v);
143 ast_free(save);
144 return -1;
145 }
146 strcpy(value->expression, v); /* SAFE */
148 }
149 ast_free(save);
150
151 return 0;
152}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_APP_ARG(name)
Define an application argument.
#define AST_STANDARD_RAW_ARGS(args, parse)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#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_APP_ARG, ast_calloc, AST_DECLARE_APP_ARGS, ast_free, AST_LIST_INSERT_TAIL, ast_log, AST_STANDARD_RAW_ARGS, ast_strdup, ast_strip_quoted(), ast_strlen_zero(), values::list, LOG_ERROR, LOG_WARNING, NULL, tmp(), and value.

Referenced by load_config().

◆ reload()

static int reload ( void  )
static

Definition at line 346 of file cdr_sqlite3_custom.c.

347{
348 int res = 0;
349
351 res = load_config(1);
353
354 return res;
355}
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 free_config(), and load_config().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 288 of file cdr_sqlite3_custom.c.

289{
291 return -1;
292 }
293
294 free_config(0);
295
296 return 0;
297}
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
Definition: cdr.c:3050

References ast_cdr_unregister(), free_config(), and name.

◆ write_cdr()

static int write_cdr ( struct ast_cdr cdr)
static

Definition at line 234 of file cdr_sqlite3_custom.c.

235{
236 int res = 0;
237 char *error = NULL;
238 char *sql = NULL;
239
240 if (db == NULL) {
241 /* Should not have loaded, but be failsafe. */
242 return 0;
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 allocate channel for variable subsitution.\n");
257 ast_free(value_string);
259 return 0;
260 }
263 pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
264 escaped = sqlite3_mprintf("%q", subst_buf);
265 ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
266 sqlite3_free(escaped);
267 }
268 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
269 ast_debug(1, "About to log: %s\n", sql);
271 ast_free(value_string);
272 }
273
274 if (sqlite3_exec(db, sql, NULL, NULL, &error) != SQLITE_OK) {
275 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
276 sqlite3_free(error);
277 }
278
279 if (sql) {
280 sqlite3_free(sql);
281 }
282
284
285 return res;
286}
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a public CDR.
Definition: cdr.c:3060
static void dummy(char *unused,...)
Definition: chan_unistim.c:220
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
void ast_channel_cdr_set(struct ast_channel *chan, struct ast_cdr *value)
#define ast_dummy_channel_alloc()
Create a fake channel structure.
Definition: channel.h:1282
#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.

References ast_cdr_dup(), ast_channel_cdr_set(), ast_channel_unref, ast_debug, ast_dummy_channel_alloc, 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 CDR 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 = "cdr", }
static

Definition at line 364 of file cdr_sqlite3_custom.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 364 of file cdr_sqlite3_custom.c.

◆ busy_timeout

int busy_timeout
static

Definition at line 64 of file cdr_sqlite3_custom.c.

Referenced by load_config(), and load_module().

◆ columns

char* columns
static

Definition at line 63 of file cdr_sqlite3_custom.c.

Referenced by display_results(), and realtime_sqlite3_require().

◆ config_file

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

Definition at line 56 of file cdr_sqlite3_custom.c.

Referenced by load_config().

◆ db

sqlite3* db = NULL
static

◆ desc

const char desc[] = "Customizable SQLite3 CDR Backend"
static

Definition at line 58 of file cdr_sqlite3_custom.c.

Referenced by load_module().

◆ lock

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

Definition at line 54 of file cdr_sqlite3_custom.c.

Referenced by reload(), and write_cdr().

◆ name

const char name[] = "cdr_sqlite3_custom"
static

Definition at line 59 of file cdr_sqlite3_custom.c.

Referenced by load_module(), and unload_module().

◆ 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 62 of file cdr_sqlite3_custom.c.

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