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)
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, }
static struct ast_module_infoast_module_info = &__mod_info
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_MUTEX_INITIALIZER , NULL, 1 }
static const char name [] = "cdr_sqlite3_custom"
static char table [80]


Detailed Description

Custom SQLite3 CDR records.

Author:
Adapted by Alejandro Rios <alejandro.rios@avatar.com.co> and Russell Bryant <russell@digium.com> from cdr_mysql_custom by Edward Eastman <ed@dm3.co.uk>, and cdr_sqlite by Holger Schurig <hs4233@mail.mn-solutions.de>

Definition in file cdr_sqlite3_custom.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 355 of file cdr_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 355 of file cdr_sqlite3_custom.c.

static void free_config ( int  reload  )  [static]

Definition at line 207 of file cdr_sqlite3_custom.c.

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

00208 {
00209    struct values *value;
00210 
00211    if (!reload && db) {
00212       sqlite3_close(db);
00213       db = NULL;
00214    }
00215 
00216    if (columns) {
00217       ast_free(columns);
00218       columns = NULL;
00219    }
00220 
00221    while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
00222       ast_free(value);
00223    }
00224 }

static int load_column_config ( const char *  tmp  )  [static]

Definition at line 76 of file cdr_sqlite3_custom.c.

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, and strsep().

Referenced by load_config().

00077 {
00078    char *col = NULL;
00079    char *cols = NULL, *save = NULL;
00080    char *escaped = NULL;
00081    struct ast_str *column_string = NULL;
00082 
00083    if (ast_strlen_zero(tmp)) {
00084       ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
00085       return -1;
00086    }
00087    if (!(column_string = ast_str_create(1024))) {
00088       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
00089       return -1;
00090    }
00091    if (!(save = cols = ast_strdup(tmp))) {
00092       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
00093       ast_free(column_string);
00094       return -1;
00095    }
00096    while ((col = strsep(&cols, ","))) {
00097       col = ast_strip(col);
00098       escaped = sqlite3_mprintf("%q", col);
00099       if (!escaped) {
00100          ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
00101          ast_free(column_string);
00102          ast_free(save);
00103          return -1;
00104       }
00105       ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
00106       sqlite3_free(escaped);
00107    }
00108    if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
00109       ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
00110       ast_free(column_string);
00111       ast_free(save);
00112       return -1;
00113    }
00114    ast_free(column_string);
00115    ast_free(save);
00116 
00117    return 0;
00118 }

static int load_config ( int  reload  )  [static]

Definition at line 155 of file cdr_sqlite3_custom.c.

References ast_config_destroy(), ast_config_load, ast_copy_string(), ast_log, ast_strlen_zero, ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), LOG_WARNING, and tmp().

00156 {
00157    struct ast_config *cfg;
00158    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00159    const char *tmp;
00160 
00161    if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
00162       ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated.");
00163       return -1;
00164    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
00165       return 0;
00166    }
00167 
00168    if (reload) {
00169       free_config(1);
00170    }
00171 
00172    if (!ast_variable_browse(cfg, "master")) {
00173       /* Nothing configured */
00174       ast_config_destroy(cfg);
00175       return -1;
00176    }
00177 
00178    /* Mapping must have a table name */
00179    if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
00180       ast_copy_string(table, tmp, sizeof(table));
00181    } else {
00182       ast_log(LOG_WARNING, "Table name not specified.  Assuming cdr.\n");
00183       strcpy(table, "cdr");
00184    }
00185 
00186    /* Columns */
00187    if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
00188       ast_config_destroy(cfg);
00189       free_config(0);
00190       return -1;
00191    }
00192 
00193    /* Values */
00194    if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
00195       ast_config_destroy(cfg);
00196       free_config(0);
00197       return -1;
00198    }
00199 
00200    ast_verb(4, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
00201 
00202    ast_config_destroy(cfg);
00203 
00204    return 0;
00205 }

static int load_module ( void   )  [static]

Definition at line 291 of file cdr_sqlite3_custom.c.

References ast_cdr_register(), ast_config_AST_LOG_DIR, ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, error(), free_config(), load_config(), LOG_ERROR, LOG_WARNING, NULL, and write_cdr().

00292 {
00293    char *error;
00294    char filename[PATH_MAX];
00295    int res;
00296    char *sql;
00297 
00298    if (load_config(0)) {
00299       return AST_MODULE_LOAD_DECLINE;
00300    }
00301 
00302    /* is the database there? */
00303    snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
00304    res = sqlite3_open(filename, &db);
00305    if (res != SQLITE_OK) {
00306       ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
00307       free_config(0);
00308       return AST_MODULE_LOAD_DECLINE;
00309    }
00310    sqlite3_busy_timeout(db, 1000);
00311    /* is the table there? */
00312    sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
00313    res = sqlite3_exec(db, sql, NULL, NULL, NULL);
00314    sqlite3_free(sql);
00315    if (res != SQLITE_OK) {
00316       /* We don't use %q for the column list here since we already escaped when building it */
00317       sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
00318       res = sqlite3_exec(db, sql, NULL, NULL, &error);
00319       sqlite3_free(sql);
00320       if (res != SQLITE_OK) {
00321          ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
00322          sqlite3_free(error);
00323          free_config(0);
00324          return AST_MODULE_LOAD_DECLINE;
00325       }
00326    }
00327 
00328    res = ast_cdr_register(name, desc, write_cdr);
00329    if (res) {
00330       ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
00331       free_config(0);
00332       return AST_MODULE_LOAD_DECLINE;
00333    }
00334 
00335    return AST_MODULE_LOAD_SUCCESS;
00336 }

static int load_values_config ( const char *  tmp  )  [static]

Definition at line 120 of file cdr_sqlite3_custom.c.

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::expression, values::list, LOG_ERROR, LOG_WARNING, NULL, and value.

Referenced by load_config().

00121 {
00122    char *vals = NULL, *save = NULL;
00123    struct values *value = NULL;
00124    int i;
00125    AST_DECLARE_APP_ARGS(val,
00126       AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR?  Yeah, right... */
00127    );
00128 
00129    if (ast_strlen_zero(tmp)) {
00130       ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
00131       return -1;
00132    }
00133    if (!(save = vals = ast_strdup(tmp))) {
00134       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
00135       return -1;
00136    }
00137    AST_STANDARD_RAW_ARGS(val, vals);
00138    for (i = 0; i < val.argc; i++) {
00139       /* Strip the single quotes off if they are there */
00140       char *v = ast_strip_quoted(val.ues[i], "'", "'");
00141       value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v));
00142       if (!value) {
00143          ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v);
00144          ast_free(save);
00145          return -1;
00146       }
00147       strcpy(value->expression, v); /* SAFE */
00148       AST_LIST_INSERT_TAIL(&sql_values, value, list);
00149    }
00150    ast_free(save);
00151 
00152    return 0;
00153 }

static int reload ( void   )  [static]

Definition at line 338 of file cdr_sqlite3_custom.c.

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

00339 {
00340    int res = 0;
00341 
00342    ast_mutex_lock(&lock);
00343    res = load_config(1);
00344    ast_mutex_unlock(&lock);
00345 
00346    return res;
00347 }

static int unload_module ( void   )  [static]

Definition at line 280 of file cdr_sqlite3_custom.c.

References ast_cdr_unregister(), and free_config().

00281 {
00282    if (ast_cdr_unregister(name)) {
00283       return -1;
00284    }
00285 
00286    free_config(0);
00287 
00288    return 0;
00289 }

static int write_cdr ( struct ast_cdr cdr  )  [static]

Definition at line 226 of file cdr_sqlite3_custom.c.

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(), dummy(), error(), values::expression, values::list, lock, LOG_ERROR, NULL, pbx_substitute_variables_helper(), and value.

Referenced by load_module().

00227 {
00228    int res = 0;
00229    char *error = NULL;
00230    char *sql = NULL;
00231 
00232    if (db == NULL) {
00233       /* Should not have loaded, but be failsafe. */
00234       return 0;
00235    }
00236 
00237    ast_mutex_lock(&lock);
00238 
00239    { /* Make it obvious that only sql should be used outside of this block */
00240       char *escaped;
00241       char subst_buf[2048];
00242       struct values *value;
00243       struct ast_channel *dummy;
00244       struct ast_str *value_string = ast_str_create(1024);
00245 
00246       dummy = ast_dummy_channel_alloc();
00247       if (!dummy) {
00248          ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
00249          ast_free(value_string);
00250          ast_mutex_unlock(&lock);
00251          return 0;
00252       }
00253       ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
00254       AST_LIST_TRAVERSE(&sql_values, value, list) {
00255          pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
00256          escaped = sqlite3_mprintf("%q", subst_buf);
00257          ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
00258          sqlite3_free(escaped);
00259       }
00260       sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
00261       ast_debug(1, "About to log: %s\n", sql);
00262       ast_channel_unref(dummy);
00263       ast_free(value_string);
00264    }
00265 
00266    if (sqlite3_exec(db, sql, NULL, NULL, &error) != SQLITE_OK) {
00267       ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
00268       sqlite3_free(error);
00269    }
00270 
00271    if (sql) {
00272       sqlite3_free(sql);
00273    }
00274 
00275    ast_mutex_unlock(&lock);
00276 
00277    return res;
00278 }


Variable Documentation

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, } [static]

Definition at line 355 of file cdr_sqlite3_custom.c.

Definition at line 355 of file cdr_sqlite3_custom.c.

char* columns [static]

Definition at line 65 of file cdr_sqlite3_custom.c.

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

Definition at line 58 of file cdr_sqlite3_custom.c.

sqlite3* db = NULL [static]

Definition at line 62 of file cdr_sqlite3_custom.c.

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

Definition at line 60 of file cdr_sqlite3_custom.c.

ast_mutex_t lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 56 of file cdr_sqlite3_custom.c.

const char name[] = "cdr_sqlite3_custom" [static]

Definition at line 61 of file cdr_sqlite3_custom.c.

char table[80] [static]

Definition at line 64 of file cdr_sqlite3_custom.c.


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