#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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 363 of file cdr_sqlite3_custom.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 363 of file cdr_sqlite3_custom.c.
static void free_config | ( | int | reload | ) | [static] |
Definition at line 208 of file cdr_sqlite3_custom.c.
References ast_free, AST_LIST_REMOVE_HEAD, columns, values::list, and value.
00209 { 00210 struct values *value; 00211 00212 if (!reload && db) { 00213 sqlite3_close(db); 00214 db = NULL; 00215 } 00216 00217 if (columns) { 00218 ast_free(columns); 00219 columns = NULL; 00220 } 00221 00222 while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) { 00223 ast_free(value); 00224 } 00225 }
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, 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_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), and LOG_WARNING.
00156 { 00157 struct ast_config *cfg; 00158 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00159 struct ast_variable *mappingvar; 00160 const char *tmp; 00161 00162 if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 00163 ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated."); 00164 return -1; 00165 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 00166 return 0; 00167 } 00168 00169 if (reload) { 00170 free_config(1); 00171 } 00172 00173 if (!(mappingvar = ast_variable_browse(cfg, "master"))) { 00174 /* Nothing configured */ 00175 ast_config_destroy(cfg); 00176 return -1; 00177 } 00178 00179 /* Mapping must have a table name */ 00180 if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) { 00181 ast_copy_string(table, tmp, sizeof(table)); 00182 } else { 00183 ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n"); 00184 strcpy(table, "cdr"); 00185 } 00186 00187 /* Columns */ 00188 if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { 00189 ast_config_destroy(cfg); 00190 free_config(0); 00191 return -1; 00192 } 00193 00194 /* Values */ 00195 if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) { 00196 ast_config_destroy(cfg); 00197 free_config(0); 00198 return -1; 00199 } 00200 00201 ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table); 00202 00203 ast_config_destroy(cfg); 00204 00205 return 0; 00206 }
static int load_module | ( | void | ) | [static] |
Definition at line 300 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().
00301 { 00302 char *error; 00303 char filename[PATH_MAX]; 00304 int res; 00305 char *sql; 00306 00307 if (load_config(0)) { 00308 return AST_MODULE_LOAD_DECLINE; 00309 } 00310 00311 /* is the database there? */ 00312 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR); 00313 res = sqlite3_open(filename, &db); 00314 if (res != SQLITE_OK) { 00315 ast_log(LOG_ERROR, "Could not open database %s.\n", filename); 00316 free_config(0); 00317 return AST_MODULE_LOAD_DECLINE; 00318 } 00319 00320 /* is the table there? */ 00321 sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); 00322 res = sqlite3_exec(db, sql, NULL, NULL, NULL); 00323 sqlite3_free(sql); 00324 if (res != SQLITE_OK) { 00325 /* We don't use %q for the column list here since we already escaped when building it */ 00326 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns); 00327 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00328 sqlite3_free(sql); 00329 if (res != SQLITE_OK) { 00330 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error); 00331 sqlite3_free(error); 00332 free_config(0); 00333 return AST_MODULE_LOAD_DECLINE; 00334 } 00335 } 00336 00337 res = ast_cdr_register(name, desc, write_cdr); 00338 if (res) { 00339 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n"); 00340 free_config(0); 00341 return AST_MODULE_LOAD_DECLINE; 00342 } 00343 00344 return AST_MODULE_LOAD_SUCCESS; 00345 }
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::list, LOG_ERROR, LOG_WARNING, 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 347 of file cdr_sqlite3_custom.c.
References ast_mutex_lock, ast_mutex_unlock, load_config(), and lock.
00348 { 00349 int res = 0; 00350 00351 ast_mutex_lock(&lock); 00352 res = load_config(1); 00353 ast_mutex_unlock(&lock); 00354 00355 return res; 00356 }
static int unload_module | ( | void | ) | [static] |
Definition at line 291 of file cdr_sqlite3_custom.c.
References ast_cdr_unregister(), and free_config().
00292 { 00293 ast_cdr_unregister(name); 00294 00295 free_config(0); 00296 00297 return 0; 00298 }
static int write_cdr | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 227 of file cdr_sqlite3_custom.c.
References ast_cdr_dup(), 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::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.
Referenced by load_module().
00228 { 00229 int res = 0; 00230 char *error = NULL; 00231 char *sql = NULL; 00232 int count = 0; 00233 00234 if (db == NULL) { 00235 /* Should not have loaded, but be failsafe. */ 00236 return 0; 00237 } 00238 00239 ast_mutex_lock(&lock); 00240 00241 { /* Make it obvious that only sql should be used outside of this block */ 00242 char *escaped; 00243 char subst_buf[2048]; 00244 struct values *value; 00245 struct ast_channel *dummy; 00246 struct ast_str *value_string = ast_str_create(1024); 00247 00248 dummy = ast_dummy_channel_alloc(); 00249 if (!dummy) { 00250 ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n"); 00251 ast_free(value_string); 00252 ast_mutex_unlock(&lock); 00253 return 0; 00254 } 00255 dummy->cdr = ast_cdr_dup(cdr); 00256 AST_LIST_TRAVERSE(&sql_values, value, list) { 00257 pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1); 00258 escaped = sqlite3_mprintf("%q", subst_buf); 00259 ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped); 00260 sqlite3_free(escaped); 00261 } 00262 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string)); 00263 ast_debug(1, "About to log: %s\n", sql); 00264 ast_channel_unref(dummy); 00265 ast_free(value_string); 00266 } 00267 00268 /* XXX This seems awful arbitrary... */ 00269 for (count = 0; count < 5; count++) { 00270 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00271 if (res != SQLITE_BUSY && res != SQLITE_LOCKED) { 00272 break; 00273 } 00274 usleep(200); 00275 } 00276 00277 if (error) { 00278 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql); 00279 sqlite3_free(error); 00280 } 00281 00282 if (sql) { 00283 sqlite3_free(sql); 00284 } 00285 00286 ast_mutex_unlock(&lock); 00287 00288 return res; 00289 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static] |
Definition at line 363 of file cdr_sqlite3_custom.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 363 of file cdr_sqlite3_custom.c.
char* columns [static] |
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.
char table[80] [static] |
Definition at line 64 of file cdr_sqlite3_custom.c.