#include "asterisk.h"
#include <time.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"
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 int | 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 | sqlite3_log (struct ast_cdr *cdr) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } |
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 char * | desc = "Customizable SQLite3 CDR Backend" |
static ast_mutex_t | lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static 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 int free_config | ( | void | ) | [static] |
Definition at line 217 of file cdr_sqlite3_custom.c.
References ast_free, AST_LIST_REMOVE_HEAD, ast_mutex_lock(), ast_mutex_unlock(), columns, values::list, and lock.
00218 { 00219 struct values *value; 00220 00221 ast_mutex_lock(&lock); 00222 00223 if (db) { 00224 sqlite3_close(db); 00225 db = NULL; 00226 } 00227 00228 if (columns) { 00229 ast_free(columns); 00230 columns = NULL; 00231 } 00232 00233 while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) 00234 ast_free(value); 00235 00236 ast_mutex_unlock(&lock); 00237 00238 return 0; 00239 }
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_create(), ast_str_set(), ast_strdup, ast_strip(), ast_strlen_zero(), LOG_ERROR, LOG_WARNING, ast_str::str, strsep(), and ast_str::used.
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 if (!column_string->used) 00105 ast_str_set(&column_string, 0, "%s", escaped); 00106 else 00107 ast_str_append(&column_string, 0, ",%s", escaped); 00108 sqlite3_free(escaped); 00109 } 00110 if (!(columns = ast_strdup(column_string->str))) { 00111 ast_log(LOG_ERROR, "Out of memory copying columns string for table '%s.'\n", table); 00112 ast_free(column_string); 00113 ast_free(save); 00114 return -1; 00115 } 00116 ast_free(column_string); 00117 ast_free(save); 00118 00119 return 0; 00120 }
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_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEUNCHANGED, free_config(), load_column_config(), load_values_config(), lock, 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))) { 00162 if (reload) 00163 ast_log(LOG_WARNING, "Failed to reload configuration file.\n"); 00164 else 00165 ast_log(LOG_WARNING, "Failed to load configuration file. Module not activated.\n"); 00166 return -1; 00167 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) 00168 return 0; 00169 00170 if (reload) 00171 free_config(); 00172 00173 ast_mutex_lock(&lock); 00174 00175 if (!(mappingvar = ast_variable_browse(cfg, "master"))) { 00176 /* Nothing configured */ 00177 ast_mutex_unlock(&lock); 00178 ast_config_destroy(cfg); 00179 return -1; 00180 } 00181 00182 /* Mapping must have a table name */ 00183 tmp = ast_variable_retrieve(cfg, "master", "table"); 00184 if (!ast_strlen_zero(tmp)) 00185 ast_copy_string(table, tmp, sizeof(table)); 00186 else { 00187 ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n"); 00188 strcpy(table, "cdr"); 00189 } 00190 00191 /* Columns */ 00192 tmp = ast_variable_retrieve(cfg, "master", "columns"); 00193 if (load_column_config(tmp)) { 00194 ast_mutex_unlock(&lock); 00195 ast_config_destroy(cfg); 00196 free_config(); 00197 return -1; 00198 } 00199 00200 /* Values */ 00201 tmp = ast_variable_retrieve(cfg, "master", "values"); 00202 if (load_values_config(tmp)) { 00203 ast_mutex_unlock(&lock); 00204 ast_config_destroy(cfg); 00205 free_config(); 00206 return -1; 00207 } 00208 00209 ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table); 00210 00211 ast_mutex_unlock(&lock); 00212 ast_config_destroy(cfg); 00213 00214 return 0; 00215 }
static int load_module | ( | void | ) | [static] |
Definition at line 307 of file cdr_sqlite3_custom.c.
References ast_cdr_register(), ast_config_AST_LOG_DIR, ast_log(), AST_MODULE_LOAD_DECLINE, free_config(), load_config(), LOG_ERROR, LOG_WARNING, and sqlite3_log().
00308 { 00309 char *error; 00310 char filename[PATH_MAX]; 00311 int res; 00312 char *sql; 00313 00314 if (!load_config(0)) { 00315 res = ast_cdr_register(name, desc, sqlite3_log); 00316 if (res) { 00317 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n"); 00318 free_config(); 00319 return AST_MODULE_LOAD_DECLINE; 00320 } 00321 } else 00322 return AST_MODULE_LOAD_DECLINE; 00323 00324 /* is the database there? */ 00325 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR); 00326 res = sqlite3_open(filename, &db); 00327 if (res != SQLITE_OK) { 00328 ast_log(LOG_ERROR, "Could not open database %s.\n", filename); 00329 free_config(); 00330 return AST_MODULE_LOAD_DECLINE; 00331 } 00332 00333 /* is the table there? */ 00334 sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); 00335 res = sqlite3_exec(db, sql, NULL, NULL, NULL); 00336 sqlite3_free(sql); 00337 if (res != SQLITE_OK) { 00338 /* We don't use %q for the column list here since we already escaped when building it */ 00339 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns); 00340 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00341 sqlite3_free(sql); 00342 if (res != SQLITE_OK) { 00343 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error); 00344 sqlite3_free(error); 00345 free_config(); 00346 return AST_MODULE_LOAD_DECLINE; 00347 } 00348 } 00349 00350 return 0; 00351 }
static int load_values_config | ( | const char * | tmp | ) | [static] |
Definition at line 122 of file cdr_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::list, LOG_ERROR, LOG_WARNING, and strsep().
Referenced by load_config().
00123 { 00124 char *val = NULL; 00125 char *vals = NULL, *save = NULL; 00126 struct values *value = NULL; 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 while ((val = strsep(&vals, ","))) { 00137 /* Strip the single quotes off if they are there */ 00138 val = ast_strip_quoted(val, "'", "'"); 00139 value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1); 00140 if (!value) { 00141 ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val); 00142 ast_free(save); 00143 return -1; 00144 } 00145 value->expression = (char *) value + sizeof(*value); 00146 ast_copy_string(value->expression, val, strlen(val) + 1); 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 353 of file cdr_sqlite3_custom.c.
References load_config().
00354 { 00355 return load_config(1); 00356 }
static int sqlite3_log | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 241 of file cdr_sqlite3_custom.c.
References ast_debug, ast_free, AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_str_append(), ast_str_create(), dummy(), values::expression, values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), ast_str::str, and ast_str::used.
Referenced by load_module().
00242 { 00243 int res = 0; 00244 char *error = NULL; 00245 char *sql = NULL; 00246 struct ast_channel dummy = { 0, }; 00247 int count = 0; 00248 00249 if (db == NULL) { 00250 /* Should not have loaded, but be failsafe. */ 00251 return 0; 00252 } 00253 00254 { /* Make it obvious that only sql should be used outside of this block */ 00255 char *escaped; 00256 char subst_buf[2048]; 00257 struct values *value; 00258 struct ast_str *value_string = ast_str_create(1024); 00259 dummy.cdr = cdr; 00260 AST_LIST_TRAVERSE(&sql_values, value, list) { 00261 memset(subst_buf, 0, sizeof(subst_buf)); 00262 pbx_substitute_variables_helper(&dummy, value->expression, subst_buf, sizeof(subst_buf) - 1); 00263 escaped = sqlite3_mprintf("%q", subst_buf); 00264 if (!value_string->used) 00265 ast_str_append(&value_string, 0, "'%s'", escaped); 00266 else 00267 ast_str_append(&value_string, 0, ",'%s'", escaped); 00268 sqlite3_free(escaped); 00269 } 00270 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, value_string->str); 00271 ast_debug(1, "About to log: %s\n", sql); 00272 ast_free(value_string); 00273 } 00274 00275 ast_mutex_lock(&lock); 00276 00277 /* XXX This seems awful arbitrary... */ 00278 for (count = 0; count < 5; count++) { 00279 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00280 if (res != SQLITE_BUSY && res != SQLITE_LOCKED) 00281 break; 00282 usleep(200); 00283 } 00284 00285 if (error) { 00286 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql); 00287 sqlite3_free(error); 00288 } 00289 00290 if (sql) 00291 sqlite3_free(sql); 00292 00293 ast_mutex_unlock(&lock); 00294 00295 return res; 00296 }
static int unload_module | ( | void | ) | [static] |
Definition at line 298 of file cdr_sqlite3_custom.c.
References ast_cdr_unregister(), and free_config().
00299 { 00300 free_config(); 00301 00302 ast_cdr_unregister(name); 00303 00304 return 0; 00305 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [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.
char* desc = "Customizable SQLite3 CDR Backend" [static] |
Definition at line 59 of file cdr_sqlite3_custom.c.
ast_mutex_t lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 55 of file cdr_sqlite3_custom.c.
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.