53 #define SQLITE_BACKEND_NAME "CEL sqlite3 custom backend"
55 AST_MUTEX_DEFINE_STATIC(
lock);
57 static const char config_file[] =
"cel_sqlite3_custom.conf";
59 static sqlite3 *db = NULL;
61 static char table[80];
66 static int busy_timeout;
75 static void free_config(
void);
77 static int load_column_config(
const char *tmp)
80 char *cols = NULL, *save = NULL;
82 struct ast_str *column_string = NULL;
84 if (ast_strlen_zero(tmp)) {
85 ast_log(LOG_WARNING,
"Column names not specified. Module not loaded.\n");
89 ast_log(LOG_ERROR,
"Out of memory creating temporary buffer for column list for table '%s.'\n", table);
93 ast_log(LOG_ERROR,
"Out of memory creating temporary buffer for column list for table '%s.'\n", table);
94 ast_free(column_string);
97 while ((col = strsep(&cols,
","))) {
99 escaped = sqlite3_mprintf(
"%q", col);
101 ast_log(LOG_ERROR,
"Out of memory creating entry for column '%s' in table '%s.'\n", col, table);
102 ast_free(column_string);
107 sqlite3_free(escaped);
110 ast_log(LOG_ERROR,
"Out of memory copying columns string for table '%s.'\n", table);
111 ast_free(column_string);
115 ast_free(column_string);
121 static int load_values_config(
const char *tmp)
124 char *vals = NULL, *save = NULL;
125 struct values *value = NULL;
127 if (ast_strlen_zero(tmp)) {
128 ast_log(LOG_WARNING,
"Values not specified. Module not loaded.\n");
132 ast_log(LOG_ERROR,
"Out of memory creating temporary buffer for value '%s'\n", tmp);
135 while ((val = strsep(&vals,
","))) {
138 value =
ast_calloc(
sizeof(
char),
sizeof(*value) + strlen(val) + 1);
140 ast_log(LOG_ERROR,
"Out of memory creating entry for value '%s'\n", val);
144 value->expression = (
char *) value +
sizeof(*value);
153 static int load_config(
int reload)
161 ast_log(LOG_WARNING,
"Failed to %sload configuration file. %s\n",
162 reload ?
"re" :
"", reload ?
"" :
"Module not activated.");
164 }
else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
172 if (!(mappingvar = ast_variable_browse(cfg,
"master"))) {
179 if (!ast_strlen_zero(tmp = ast_variable_retrieve(cfg,
"master",
"table"))) {
182 ast_log(LOG_WARNING,
"Table name not specified. Assuming cel.\n");
183 strcpy(table,
"cel");
187 if ((tmp = ast_variable_retrieve(cfg,
"master",
"busy_timeout")) != NULL) {
188 if (
ast_parse_arg(tmp, PARSE_INT32|PARSE_DEFAULT, &busy_timeout, 1000) != 0) {
189 ast_log(LOG_WARNING,
"Invalid busy_timeout value '%s' specified. Using 1000 instead.\n", tmp);
196 if (load_column_config(ast_variable_retrieve(cfg,
"master",
"columns"))) {
203 if (load_values_config(ast_variable_retrieve(cfg,
"master",
"values"))) {
209 ast_verb(3,
"Logging CEL records to table '%s' in 'master.db'\n", table);
216 static void free_config(
void)
245 ast_mutex_lock(&
lock);
249 char subst_buf[2048];
256 ast_log(LOG_ERROR,
"Unable to fabricate channel from CEL event.\n");
257 ast_free(value_string);
258 ast_mutex_unlock(&
lock);
262 pbx_substitute_variables_helper(dummy, value->expression, subst_buf,
sizeof(subst_buf) - 1);
263 escaped = sqlite3_mprintf(
"%q", subst_buf);
265 sqlite3_free(escaped);
267 sql = sqlite3_mprintf(
"INSERT INTO %q (%s) VALUES (%s)", table,
columns,
ast_str_buffer(value_string));
270 ast_free(value_string);
273 if (sqlite3_exec(db, sql, NULL, NULL, &error) != SQLITE_OK) {
274 ast_log(LOG_ERROR,
"%s. SQL: %s.\n", error, sql);
281 ast_mutex_unlock(&
lock);
286 static int unload_module(
void)
295 static int load_module(
void)
298 char filename[PATH_MAX];
302 if (load_config(0)) {
307 snprintf(filename,
sizeof(filename),
"%s/master.db", ast_config_AST_LOG_DIR);
308 res = sqlite3_open(filename, &db);
309 if (res != SQLITE_OK) {
310 ast_log(LOG_ERROR,
"Could not open database %s.\n", filename);
314 sqlite3_busy_timeout(db, busy_timeout);
316 sql = sqlite3_mprintf(
"SELECT COUNT(*) FROM %q;", table);
317 res = sqlite3_exec(db, sql, NULL, NULL, NULL);
319 if (res != SQLITE_OK) {
321 sql = sqlite3_mprintf(
"CREATE TABLE %q (AcctId INTEGER PRIMARY KEY, %s)", table,
columns);
322 res = sqlite3_exec(db, sql, NULL, NULL, &error);
324 if (res != SQLITE_OK) {
325 ast_log(LOG_WARNING,
"Unable to create table '%s': %s.\n", table, error);
333 ast_log(LOG_ERROR,
"Unable to register custom SQLite3 CEL handling\n");
341 static int reload(
void)
345 ast_mutex_lock(&
lock);
346 res = load_config(1);
347 ast_mutex_unlock(&
lock);
352 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,
"SQLite3 Custom CEL Module",
353 .support_level = AST_MODULE_SUPPORT_EXTENDED,
355 .unload = unload_module,
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
#define ast_channel_unref(c)
Decrease channel reference count.
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_strdup(str)
A wrapper for strdup()
Configuration File Parser.
static const char config_file[]
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Core PBX routines and definitions.
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Support for dynamic strings.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define ast_calloc(num, len)
A wrapper for calloc()
struct ast_channel * ast_cel_fabricate_channel_from_event(const struct ast_event *event)
Create a fake channel from data in a CEL event.
Support for logging to various files, console and syslog Configuration in file logger.conf.
Module has failed to load, may be in an inconsistent state.
Structure used to handle boolean flags.
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Options provided by main asterisk program.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.