#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 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 | 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 = AST_BUILDOPT_SUM, .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 const char | desc [] = "Customizable SQLite3 CDR Backend" |
| static ast_mutex_t | lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| 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 358 of file cdr_sqlite3_custom.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 358 of file cdr_sqlite3_custom.c.
| static void free_config | ( | int | reload | ) | [static] |
Definition at line 204 of file cdr_sqlite3_custom.c.
References ast_free, AST_LIST_REMOVE_HEAD, values::list, and value.
00205 { 00206 struct values *value; 00207 00208 if (!reload && db) { 00209 sqlite3_close(db); 00210 db = NULL; 00211 } 00212 00213 if (columns) { 00214 ast_free(columns); 00215 columns = NULL; 00216 } 00217 00218 while ((value = AST_LIST_REMOVE_HEAD(&sql_values, list))) { 00219 ast_free(value); 00220 } 00221 }
| 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 151 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.
00152 { 00153 struct ast_config *cfg; 00154 struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 }; 00155 struct ast_variable *mappingvar; 00156 const char *tmp; 00157 00158 if ((cfg = ast_config_load(config_file, config_flags)) == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) { 00159 ast_log(LOG_WARNING, "Failed to %sload configuration file. %s\n", reload ? "re" : "", reload ? "" : "Module not activated."); 00160 return -1; 00161 } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) { 00162 return 0; 00163 } 00164 00165 if (reload) { 00166 free_config(1); 00167 } 00168 00169 if (!(mappingvar = ast_variable_browse(cfg, "master"))) { 00170 /* Nothing configured */ 00171 ast_config_destroy(cfg); 00172 return -1; 00173 } 00174 00175 /* Mapping must have a table name */ 00176 if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg, "master", "table"))) { 00177 ast_copy_string(table, tmp, sizeof(table)); 00178 } else { 00179 ast_log(LOG_WARNING, "Table name not specified. Assuming cdr.\n"); 00180 strcpy(table, "cdr"); 00181 } 00182 00183 /* Columns */ 00184 if (load_column_config(ast_variable_retrieve(cfg, "master", "columns"))) { 00185 ast_config_destroy(cfg); 00186 free_config(0); 00187 return -1; 00188 } 00189 00190 /* Values */ 00191 if (load_values_config(ast_variable_retrieve(cfg, "master", "values"))) { 00192 ast_config_destroy(cfg); 00193 free_config(0); 00194 return -1; 00195 } 00196 00197 ast_verb(3, "cdr_sqlite3_custom: Logging CDR records to table '%s' in 'master.db'\n", table); 00198 00199 ast_config_destroy(cfg); 00200 00201 return 0; 00202 }
| static int load_module | ( | void | ) | [static] |
Definition at line 296 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 sqlite3_log().
00297 { 00298 char *error; 00299 char filename[PATH_MAX]; 00300 int res; 00301 char *sql; 00302 00303 if (load_config(0)) { 00304 return AST_MODULE_LOAD_DECLINE; 00305 } 00306 00307 /* is the database there? */ 00308 snprintf(filename, sizeof(filename), "%s/master.db", ast_config_AST_LOG_DIR); 00309 res = sqlite3_open(filename, &db); 00310 if (res != SQLITE_OK) { 00311 ast_log(LOG_ERROR, "Could not open database %s.\n", filename); 00312 free_config(0); 00313 return AST_MODULE_LOAD_DECLINE; 00314 } 00315 00316 /* is the table there? */ 00317 sql = sqlite3_mprintf("SELECT COUNT(AcctId) FROM %q;", table); 00318 res = sqlite3_exec(db, sql, NULL, NULL, NULL); 00319 sqlite3_free(sql); 00320 if (res != SQLITE_OK) { 00321 /* We don't use %q for the column list here since we already escaped when building it */ 00322 sql = sqlite3_mprintf("CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table, columns); 00323 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00324 sqlite3_free(sql); 00325 if (res != SQLITE_OK) { 00326 ast_log(LOG_WARNING, "Unable to create table '%s': %s.\n", table, error); 00327 sqlite3_free(error); 00328 free_config(0); 00329 return AST_MODULE_LOAD_DECLINE; 00330 } 00331 } 00332 00333 res = ast_cdr_register(name, desc, sqlite3_log); 00334 if (res) { 00335 ast_log(LOG_ERROR, "Unable to register custom SQLite3 CDR handling\n"); 00336 free_config(0); 00337 return AST_MODULE_LOAD_DECLINE; 00338 } 00339 00340 return AST_MODULE_LOAD_SUCCESS; 00341 }
| static int load_values_config | ( | const char * | tmp | ) | [static] |
Definition at line 119 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::expression, values::list, LOG_ERROR, LOG_WARNING, strsep(), and value.
Referenced by load_config().
00120 { 00121 char *val = NULL; 00122 char *vals = NULL, *save = NULL; 00123 struct values *value = NULL; 00124 00125 if (ast_strlen_zero(tmp)) { 00126 ast_log(LOG_WARNING, "Values not specified. Module not loaded.\n"); 00127 return -1; 00128 } 00129 if (!(save = vals = ast_strdup(tmp))) { 00130 ast_log(LOG_ERROR, "Out of memory creating temporary buffer for value '%s'\n", tmp); 00131 return -1; 00132 } 00133 while ((val = strsep(&vals, ","))) { 00134 /* Strip the single quotes off if they are there */ 00135 val = ast_strip_quoted(val, "'", "'"); 00136 value = ast_calloc(sizeof(char), sizeof(*value) + strlen(val) + 1); 00137 if (!value) { 00138 ast_log(LOG_ERROR, "Out of memory creating entry for value '%s'\n", val); 00139 ast_free(save); 00140 return -1; 00141 } 00142 value->expression = (char *) value + sizeof(*value); 00143 ast_copy_string(value->expression, val, strlen(val) + 1); 00144 AST_LIST_INSERT_TAIL(&sql_values, value, list); 00145 } 00146 ast_free(save); 00147 00148 return 0; 00149 }
| static int reload | ( | void | ) | [static] |
Definition at line 343 of file cdr_sqlite3_custom.c.
References ast_mutex_lock(), ast_mutex_unlock(), load_config(), and lock.
00344 { 00345 int res = 0; 00346 00347 ast_mutex_lock(&lock); 00348 res = load_config(1); 00349 ast_mutex_unlock(&lock); 00350 00351 return res; 00352 }
| static int sqlite3_log | ( | struct ast_cdr * | cdr | ) | [static] |
Definition at line 223 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(), ast_channel::cdr, dummy(), values::expression, values::list, lock, LOG_ERROR, pbx_substitute_variables_helper(), and value.
Referenced by load_module().
00224 { 00225 int res = 0; 00226 char *error = NULL; 00227 char *sql = NULL; 00228 int count = 0; 00229 00230 if (db == NULL) { 00231 /* Should not have loaded, but be failsafe. */ 00232 return 0; 00233 } 00234 00235 ast_mutex_lock(&lock); 00236 00237 { /* Make it obvious that only sql should be used outside of this block */ 00238 char *escaped; 00239 char subst_buf[2048]; 00240 struct values *value; 00241 struct ast_channel *dummy; 00242 struct ast_str *value_string = ast_str_create(1024); 00243 00244 dummy = ast_dummy_channel_alloc(); 00245 if (!dummy) { 00246 ast_log(LOG_ERROR, "Unable to allocate channel for variable subsitution.\n"); 00247 ast_free(value_string); 00248 ast_mutex_unlock(&lock); 00249 return 0; 00250 } 00251 dummy->cdr = ast_cdr_dup(cdr); 00252 AST_LIST_TRAVERSE(&sql_values, value, list) { 00253 pbx_substitute_variables_helper(dummy, value->expression, subst_buf, sizeof(subst_buf) - 1); 00254 escaped = sqlite3_mprintf("%q", subst_buf); 00255 ast_str_append(&value_string, 0, "%s'%s'", ast_str_strlen(value_string) ? "," : "", escaped); 00256 sqlite3_free(escaped); 00257 } 00258 sql = sqlite3_mprintf("INSERT INTO %q (%s) VALUES (%s)", table, columns, ast_str_buffer(value_string)); 00259 ast_debug(1, "About to log: %s\n", sql); 00260 ast_channel_release(dummy); 00261 ast_free(value_string); 00262 } 00263 00264 /* XXX This seems awful arbitrary... */ 00265 for (count = 0; count < 5; count++) { 00266 res = sqlite3_exec(db, sql, NULL, NULL, &error); 00267 if (res != SQLITE_BUSY && res != SQLITE_LOCKED) { 00268 break; 00269 } 00270 usleep(200); 00271 } 00272 00273 if (error) { 00274 ast_log(LOG_ERROR, "%s. SQL: %s.\n", error, sql); 00275 sqlite3_free(error); 00276 } 00277 00278 if (sql) { 00279 sqlite3_free(sql); 00280 } 00281 00282 ast_mutex_unlock(&lock); 00283 00284 return res; 00285 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 287 of file cdr_sqlite3_custom.c.
References ast_cdr_unregister(), and free_config().
00288 { 00289 ast_cdr_unregister(name); 00290 00291 free_config(0); 00292 00293 return 0; 00294 }
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 358 of file cdr_sqlite3_custom.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 358 of file cdr_sqlite3_custom.c.
char* columns [static] |
Definition at line 64 of file cdr_sqlite3_custom.c.
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 = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [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.
1.5.6