#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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 char | table [80] |
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, columns, values::list, 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 75 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, and strsep().
Referenced by load_config().
00076 { 00077 char *col = NULL; 00078 char *cols = NULL, *save = NULL; 00079 char *escaped = NULL; 00080 struct ast_str *column_string = NULL; 00081 00082 if (ast_strlen_zero(tmp)) { 00083 ast_log(LOG_WARNING, "Column names not specified. Module not loaded.\n"); 00084 return -1; 00085 } 00086 if (!(column_string = ast_str_create(1024))) { 00087 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table); 00088 return -1; 00089 } 00090 if (!(save = cols = ast_strdup(tmp))) { 00091 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for column list for table '%s.'\n", table); 00092 ast_free(column_string); 00093 return -1; 00094 } 00095 while ((col = strsep(&cols, ","))) { 00096 col = ast_strip(col); 00097 escaped = sqlite3_mprintf("%q", col); 00098 if (!escaped) { 00099 ast_log(LOG_ERROR, "Out of memory creating entry for column '%s' in table '%s.'\n", col, table); 00100 ast_free(column_string); 00101 ast_free(save); 00102 return -1; 00103 } 00104 ast_str_append(&column_string, 0, "%s%s", ast_str_strlen(column_string) ? "," : "", escaped); 00105 sqlite3_free(escaped); 00106 } 00107 if (!(columns = ast_strdup(ast_str_buffer(column_string)))) { 00108 ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table); 00109 ast_free(column_string); 00110 ast_free(save); 00111 return -1; 00112 } 00113 ast_free(column_string); 00114 ast_free(save); 00115 00116 return 0; 00117 }
static int load_config | ( | int | reload | ) | [static] |
Definition at line 154 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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), and LOG_WARNING.
00155 { 00156 struct ast_config *cfg; 00157 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00158 struct ast_variable *mappingvar; 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 (!(mappingvar = 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(3, "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 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().
00300 { 00301 char *error; 00302 char filename[PATH_MAX]; 00303 int res; 00304 char *sql; 00305 00306 if (load_config(0)) { 00307 return AST_MODULE_LOAD_DECLINE; 00308 } 00309 00310 /* is the database there? */ 00311 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR); 00312 res = sqlite3_open(filename, &db); 00313 if (res != SQLITE_OK) { 00314 ast_log(LOG_ERROR, "Could not open database %s.\n", filename); 00315 free_config(0); 00316 return AST_MODULE_LOAD_DECLINE; 00317 } 00318 00319 /* is the table there? */ 00320 sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); 00321 res = sqlite3_exec(db, sql, NULL, NULL, NULL); 00322 sqlite3_free(sql); 00323 if (res != SQLITE_OK) { 00324 /* We don't use %q for the column list here since we already escaped when building it */ 00325 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns); 00326 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00327 sqlite3_free(sql); 00328 if (res != SQLITE_OK) { 00329 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error); 00330 sqlite3_free(error); 00331 free_config(0); 00332 return AST_MODULE_LOAD_DECLINE; 00333 } 00334 } 00335 00336 res = ast_cdr_register(name, desc, write_cdr); 00337 if (res) { 00338 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n"); 00339 free_config(0); 00340 return AST_MODULE_LOAD_DECLINE; 00341 } 00342 00343 return AST_MODULE_LOAD_SUCCESS; 00344 }
static int load_values_config | ( | const char * | tmp | ) | [static] |
Definition at line 119 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::list, LOG_ERROR, LOG_WARNING, and value.
Referenced by load_config().
00120 { 00121 char *vals = NULL, *save = NULL; 00122 struct values *value = NULL; 00123 int i; 00124 AST_DECLARE_APP_ARGS(val, 00125 AST_APP_ARG(ues)[200]; /* More than 200 columns in this CDR? Yeah, right... */ 00126 ); 00127 00128 if (ast_strlen_zero(tmp)) { 00129 ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n"); 00130 return -1; 00131 } 00132 if (!(save = vals = ast_strdup(tmp))) { 00133 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp); 00134 return -1; 00135 } 00136 AST_STANDARD_RAW_ARGS(val, vals); 00137 for (i = 0; i < val.argc; i++) { 00138 /* Strip the single quotes off if they are there */ 00139 char *v = ast_strip_quoted(val.ues[i], "'", "'"); 00140 value = ast_calloc(sizeof(char), sizeof(*value) + strlen(v)); 00141 if (!value) { 00142 ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", v); 00143 ast_free(save); 00144 return -1; 00145 } 00146 strcpy(value->expression, v); /* SAFE */ 00147 AST_LIST_INSERT_TAIL(&sql_values, value, list); 00148 } 00149 ast_free(save); 00150 00151 return 0; 00152 }
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.
00347 { 00348 int res = 0; 00349 00350 ast_mutex_lock(&lock); 00351 res = load_config(1); 00352 ast_mutex_unlock(&lock); 00353 00354 return res; 00355 }
static int unload_module | ( | void | ) | [static] |
Definition at line 290 of file cdr_sqlite3_custom.c.
References ast_cdr_unregister(), and free_config().
00291 { 00292 ast_cdr_unregister(name); 00293 00294 free_config(0); 00295 00296 return 0; 00297 }
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_release(), 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::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.
Referenced by load_module().
00227 { 00228 int res = 0; 00229 char *error = NULL; 00230 char *sql = NULL; 00231 int count = 0; 00232 00233 if (db == NULL) { 00234 /* Should not have loaded, but be failsafe. */ 00235 return 0; 00236 } 00237 00238 ast_mutex_lock(&lock); 00239 00240 { /* Make it obvious that only sql should be used outside of this block */ 00241 char *escaped; 00242 char subst_buf[2048]; 00243 struct values *value; 00244 struct ast_channel *dummy; 00245 struct ast_str *value_string = ast_str_create(1024); 00246 00247 dummy = ast_dummy_channel_alloc(); 00248 if (!dummy) { 00249 ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n"); 00250 ast_free(value_string); 00251 ast_mutex_unlock(&lock); 00252 return 0; 00253 } 00254 dummy->cdr = ast_cdr_dup(cdr); 00255 AST_LIST_TRAVERSE(&sql_values, value, list) { 00256 pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1); 00257 escaped = sqlite3_mprintf("%q", subst_buf); 00258 ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped); 00259 sqlite3_free(escaped); 00260 } 00261 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string)); 00262 ast_debug(1, "About to log: %s\n", sql); 00263 ast_channel_release(dummy); 00264 ast_free(value_string); 00265 } 00266 00267 /* XXX This seems awful arbitrary... */ 00268 for (count = 0; count < 5; count++) { 00269 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00270 if (res != SQLITE_BUSY && res != SQLITE_LOCKED) { 00271 break; 00272 } 00273 usleep(200); 00274 } 00275 00276 if (error) { 00277 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql); 00278 sqlite3_free(error); 00279 } 00280 00281 if (sql) { 00282 sqlite3_free(sql); 00283 } 00284 00285 ast_mutex_unlock(&lock); 00286 00287 return res; 00288 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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] |
const char config_file[] = "cdr_sqlite3_custom.conf" [static] |
Definition at line 57 of file cdr_sqlite3_custom.c.
sqlite3* db = NULL [static] |
Definition at line 61 of file cdr_sqlite3_custom.c.
const char desc[] = "Customizable SQLite3 CDR Backend" [static] |
Definition at line 59 of file cdr_sqlite3_custom.c.
ast_mutex_t lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
Definition at line 55 of file cdr_sqlite3_custom.c.
const char name[] = "cdr_sqlite3_custom" [static] |
Definition at line 60 of file cdr_sqlite3_custom.c.
char table[80] [static] |
Definition at line 63 of file cdr_sqlite3_custom.c.