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

Defines

#define SQLITE_BACKEND_NAME   "CEL sqlite3 custom backend"

Functions

static void __reg_module (void)
static void __unreg_module (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, }
static struct ast_module_infoast_module_info = &__mod_info
static char * columns
static const char config_file [] = "cel_sqlite3_custom.conf"
static sqlite3 * db = NULL
static ast_mutex_t lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }
static char table [80]


Detailed Description

Custom SQLite3 CEL records.

Author:
Adapted by Steve Murphy <murf@digium.com> from 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 cel_sqlite3_custom.c.


Define Documentation

#define SQLITE_BACKEND_NAME   "CEL sqlite3 custom backend"

Definition at line 60 of file cel_sqlite3_custom.c.

Referenced by load_module(), and unload_module().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 355 of file cel_sqlite3_custom.c.

static void __unreg_module ( void   )  [static]

Definition at line 355 of file cel_sqlite3_custom.c.

static void free_config ( void   )  [static]

Definition at line 213 of file cel_sqlite3_custom.c.

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

00214 {
00215    struct values *value;
00216 
00217    if (db) {
00218       sqlite3_close(db);
00219       db = NULL;
00220    }
00221 
00222    if (columns) {
00223       ast_free(columns);
00224       columns = NULL;
00225    }
00226 
00227    while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) {
00228       ast_free(value);
00229    }
00230 }

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

Definition at line 83 of file cel_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().

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

static int load_config ( int  reload  )  [static]

Definition at line 159 of file cel_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().

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

static int load_module ( void   )  [static]

Definition at line 292 of file cel_sqlite3_custom.c.

References ast_cel_backend_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, SQLITE_BACKEND_NAME, and write_cel().

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

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

00128 {
00129    char *val = NULL;
00130    char *vals = NULL, *save = NULL;
00131    struct values *value = NULL;
00132 
00133    if (ast_strlen_zero(tmp)) {
00134       ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
00135       return -1;
00136    }
00137    if (!(save = vals = ast_strdup(tmp))) {
00138       ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
00139       return -1;
00140    }
00141    while ((val = strsep(&vals, ","))) {
00142       /* Strip the single quotes off if they are there */
00143       val = ast_strip_quoted(val, "'", "'");
00144       value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1);
00145       if (!value) {
00146          ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val);
00147          ast_free(save);
00148          return -1;
00149       }
00150       value->expression = (char *) value + sizeof(*value);
00151       ast_copy_string(value->expression, val, strlen(val) + 1);
00152       AST_LIST_INSERT_TAIL(&sql_values, value, list);
00153    }
00154    ast_free(save);
00155 
00156    return 0;
00157 }

static int reload ( void   )  [static]

Definition at line 338 of file cel_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 283 of file cel_sqlite3_custom.c.

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

00284 {
00285    ast_cel_backend_unregister(SQLITE_BACKEND_NAME);
00286 
00287    free_config();
00288 
00289    return 0;
00290 }

static void write_cel ( struct ast_event event  )  [static]

Definition at line 232 of file cel_sqlite3_custom.c.

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

Referenced by load_module().

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


Variable Documentation

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

Definition at line 355 of file cel_sqlite3_custom.c.

Definition at line 355 of file cel_sqlite3_custom.c.

char* columns [static]

Bug:
Handling of this var is crash prone on reloads

Definition at line 72 of file cel_sqlite3_custom.c.

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

Definition at line 64 of file cel_sqlite3_custom.c.

sqlite3* db = NULL [static]

Definition at line 66 of file cel_sqlite3_custom.c.

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

Definition at line 62 of file cel_sqlite3_custom.c.

char table[80] [static]

Definition at line 68 of file cel_sqlite3_custom.c.


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