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"
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, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } |
| static struct ast_module_info * | ast_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_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
| static const char | name [] = "cdr_sqlite3_custom" |
| static struct sql_values | sql_values |
| static char | table [80] |
Custom SQLite3 CDR records.
Definition in file cdr_sqlite3_custom.c.
| static void __reg_module | ( | void | ) | [static] |
Definition at line 362 of file cdr_sqlite3_custom.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 362 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, and value.
Referenced by load_config(), load_module(), and unload_module().
| 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, and LOG_WARNING.
Referenced by load_config().
{
char *col = NULL;
char *cols = NULL, *save = NULL;
char *escaped = NULL;
struct ast_str *column_string = NULL;
if (ast_strlen_zero(tmp)) {
ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n");
return -1;
}
if (!(column_string = ast_str_create(1024))) {
ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
return -1;
}
if (!(save = cols = ast_strdup(tmp))) {
ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table);
ast_free(column_string);
return -1;
}
while ((col = strsep(&cols, ","))) {
col = ast_strip(col);
escaped = sqlite3_mprintf("%q", col);
if (!escaped) {
ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
ast_free(column_string);
ast_free(save);
return -1;
}
ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped);
sqlite3_free(escaped);
}
if (!(columns = ast_strdup(ast_str_buffer(column_string)))) {
ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table);
ast_free(column_string);
ast_free(save);
return -1;
}
ast_free(column_string);
ast_free(save);
return 0;
}
| 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(), and LOG_WARNING.
Referenced by load_module(), and reload().
{
struct ast_config *cfg;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
const char *tmp;
if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated.");
return -1;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
return 0;
}
if (reload) {
free_config(1);
}
if (!ast_variable_browse(cfg, "master")) {
/* Nothing configured */
ast_config_destroy(cfg);
return -1;
}
/* Mapping must have a table name */
if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) {
ast_copy_string(table, tmp, sizeof(table));
} else {
ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n");
strcpy(table, "cdr");
}
/* Columns */
if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) {
ast_config_destroy(cfg);
free_config(0);
return -1;
}
/* Values */
if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) {
ast_config_destroy(cfg);
free_config(0);
return -1;
}
ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table);
ast_config_destroy(cfg);
return 0;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 299 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, free_config(), load_config(), LOG_ERROR, LOG_WARNING, and write_cdr().
{
char *error;
char filename[PATH_MAX];
int res;
char *sql;
if (load_config(0)) {
return AST_MODULE_LOAD_DECLINE;
}
/* is the database there? */
snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR);
res = sqlite3_open(filename, &db);
if (res != SQLITE_OK) {
ast_log(LOG_ERROR, "Could not open database %s.\n", filename);
free_config(0);
return AST_MODULE_LOAD_DECLINE;
}
/* is the table there? */
sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table);
res = sqlite3_exec(db, sql, NULL, NULL, NULL);
sqlite3_free(sql);
if (res != SQLITE_OK) {
/* We don't use %q for the column list here since we already escaped when building it */
sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns);
res = sqlite3_exec(db, sql, NULL, NULL, &error);
sqlite3_free(sql);
if (res != SQLITE_OK) {
ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error);
sqlite3_free(error);
free_config(0);
return AST_MODULE_LOAD_DECLINE;
}
}
res = ast_cdr_register(name, desc, write_cdr);
if (res) {
ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n");
free_config(0);
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
| 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, and value.
Referenced by load_config().
{
char *vals = NULL, *save = NULL;
struct values *value = NULL;
int i;
AST_DECLARE_APP_ARGS(val,
AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR? Yeah, right... */
);
if (ast_strlen_zero(tmp)) {
ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n");
return -1;
}
if (!(save = vals = ast_strdup(tmp))) {
ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp);
return -1;
}
AST_STANDARD_RAW_ARGS(val, vals);
for (i = 0; i < val.argc; i++) {
/* Strip the single quotes off if they are there */
char *v = ast_strip_quoted(val.ues[i], "'", "'");
value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v));
if (!value) {
ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v);
ast_free(save);
return -1;
}
strcpy(value->expression, v); /* SAFE */
AST_LIST_INSERT_TAIL(&sql_values, value, list);
}
ast_free(save);
return 0;
}
| static int reload | ( | void | ) | [static] |
Definition at line 346 of file cdr_sqlite3_custom.c.
References ast_mutex_lock, ast_mutex_unlock, load_config(), and lock.
{
int res = 0;
ast_mutex_lock(&lock);
res = load_config(1);
ast_mutex_unlock(&lock);
return res;
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 290 of file cdr_sqlite3_custom.c.
References ast_cdr_unregister(), and free_config().
{
ast_cdr_unregister(name);
free_config(0);
return 0;
}
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(), values::expression, values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.
Referenced by load_module().
{
int res = 0;
char *error = NULL;
char *sql = NULL;
int count = 0;
if (db == NULL) {
/* Should not have loaded, but be failsafe. */
return 0;
}
ast_mutex_lock(&lock);
{ /* Make it obvious that only sql should be used outside of this block */
char *escaped;
char subst_buf[2048];
struct values *value;
struct ast_channel *dummy;
struct ast_str *value_string = ast_str_create(1024);
dummy = ast_dummy_channel_alloc();
if (!dummy) {
ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n");
ast_free(value_string);
ast_mutex_unlock(&lock);
return 0;
}
ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
AST_LIST_TRAVERSE(&sql_values, value, list) {
pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1);
escaped = sqlite3_mprintf("%q", subst_buf);
ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped);
sqlite3_free(escaped);
}
sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string));
ast_debug(1, "About to log: %s\n", sql);
ast_channel_unref(dummy);
ast_free(value_string);
}
/* XXX This seems awful arbitrary... */
for (count = 0; count < 5; count++) {
res = sqlite3_exec(db, sql, NULL, NULL, &error);
if (res != SQLITE_BUSY && res != SQLITE_LOCKED) {
break;
}
usleep(200);
}
if (error) {
ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql);
sqlite3_free(error);
}
if (sql) {
sqlite3_free(sql);
}
ast_mutex_unlock(&lock);
return res;
}
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, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static] |
Definition at line 362 of file cdr_sqlite3_custom.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 362 of file cdr_sqlite3_custom.c.
char* columns [static] |
Definition at line 65 of file cdr_sqlite3_custom.c.
Referenced by display_results(), and realtime_sqlite3_require().
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_RECURSIVE_MUTEX_INITIALIZER_NP , 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.
struct sql_values sql_values [static] |
char table[80] [static] |
Definition at line 64 of file cdr_sqlite3_custom.c.