45 #include <mysql/mysql.h> 46 #include <mysql/errmsg.h> 59 #define DATE_FORMAT "%Y-%m-%d %T" 63 # define MYSQL_PORT MARIADB_PORT 65 # define MYSQL_PORT 3306 73 static const char desc[] =
"MySQL CDR Backend";
74 static const char name[] =
"mysql";
75 static const char config[] =
"cdr_mysql.conf";
115 e->
command =
"cdr mysql status";
117 "Usage: cdr mysql status\n" 118 " Shows current connection status for cdr_mysql\n";
129 char status2[100] =
"";
144 snprintf(buf,
sizeof(buf),
"%s%s for ", status, status2);
152 ast_cli(a->
fd,
"Not currently connected to a MySQL server.\n");
166 if (mysql_options(&
mysql, MYSQL_SET_CHARSET_NAME, charset)) {
167 ast_log(
LOG_WARNING,
"Failed to set connection charset. Data inserted might be invalid.\n");
176 #ifdef HAVE_MYSQLCLIENT_BOOL 177 bool my_bool_true = 1;
178 #elif HAVE_MYSQLCLIENT_MY_BOOL 179 my_bool my_bool_true = 1;
182 if (!sql1 || !sql2) {
197 #if MYSQL_VERSION_ID >= 50013 199 if (mysql_options(&
mysql, MYSQL_OPT_RECONNECT, &my_bool_true) != 0) {
220 if ((error = mysql_ping(&
mysql))) {
223 switch (mysql_errno(&
mysql)) {
224 case CR_SERVER_GONE_ERROR:
241 int column_count = 0;
252 if (!strcmp(entry->
name,
"calldate")) {
266 cdrname =
"calldate";
279 }
else if ((!strcmp(cdrname,
"disposition") ||
280 !strcmp(cdrname,
"amaflags")) &&
281 (strstr(entry->
type,
"int") ||
282 strstr(entry->
type,
"dec") ||
283 strstr(entry->
type,
"float") ||
284 strstr(entry->
type,
"double") ||
285 strstr(entry->
type,
"real") ||
286 strstr(entry->
type,
"numeric") ||
287 strstr(entry->
type,
"fixed"))) {
289 }
else if (!strcmp(cdrname,
"start") || !strcmp(cdrname,
"answer") ||
290 !strcmp(cdrname,
"end")) {
296 }
else if (!strcmp(cdrname,
"calldate")) {
305 if (column_count++) {
310 if (!strcasecmp(cdrname,
"billsec") &&
311 (strstr(entry->
type,
"float") ||
312 strstr(entry->
type,
"double") ||
313 strstr(entry->
type,
"decimal") ||
314 strstr(entry->
type,
"numeric") ||
315 strstr(entry->
type,
"real"))) {
318 snprintf(workspace,
sizeof(workspace),
"%lf",
329 if (!strcasecmp(cdrname,
"duration") &&
330 (strstr(entry->
type,
"float") ||
331 strstr(entry->
type,
"double") ||
332 strstr(entry->
type,
"decimal") ||
333 strstr(entry->
type,
"numeric") ||
334 strstr(entry->
type,
"real"))) {
336 snprintf(workspace,
sizeof(workspace),
"%lf",
353 ast_debug(1,
"Inserting a CDR record.\n");
455 if (!tmp || sscanf(tmp,
"%30d", field) < 1)
473 #ifdef HAVE_MYSQLCLIENT_BOOL 474 bool my_bool_true = 1;
475 #elif HAVE_MYSQLCLIENT_MY_BOOL 476 my_bool my_bool_true = 1;
485 #if MYSQL_VERSION_ID >= 50013 487 if (mysql_options(&
mysql, MYSQL_OPT_RECONNECT, &my_bool_true) != 0) {
493 mysql_ssl_set(&
mysql,
511 ast_debug(1,
"Successfully connected to MySQL database.\n");
518 if (mysql_query(&
mysql, sqldesc)) {
519 ast_log(
LOG_ERROR,
"Unable to query table description!! Logging disabled.\n");
526 if (!(result = mysql_store_result(&
mysql))) {
527 ast_log(
LOG_ERROR,
"Unable to query table description!! Logging disabled.\n");
534 while ((row = mysql_fetch_row(result))) {
538 ast_debug(1,
"Got a field '%s' of type '%s'\n", row[0], row[1]);
541 if (strncmp(var->
name,
"alias", 5) == 0 && strcasecmp(var->
value, row[0]) == 0 ) {
544 ast_verb(3,
"Found alias %s for column %s\n", cdrvar, row[0]);
546 }
else if (strncmp(var->
name,
"static", 6) == 0 && strcasecmp(var->
value, row[0]) == 0) {
549 if (item[0] ==
'"' && item[strlen(item) - 1] ==
'"') {
551 item[strlen(item) - 1] =
'\0';
558 entry =
ast_calloc(
sizeof(
char),
sizeof(*entry) + strlen(row[0]) + 1 + strlen(cdrvar) + 1 + strlen(
staticvalue) + 1 + strlen(row[1]) + 1);
560 ast_log(
LOG_ERROR,
"Out of memory creating entry for column '%s'\n", row[0]);
561 mysql_free_result(result);
565 entry->
name = (
char *)entry +
sizeof(*entry);
566 strcpy(entry->
name, row[0]);
570 strcpy(entry->
cdrname, cdrvar);
572 entry->
cdrname = (
char *)entry +
sizeof(*entry);
583 strcpy(entry->
type, row[1]);
592 mysql_free_result(result);
struct ast_variable * next
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
int ast_cdr_backend_suspend(const char *name)
Suspend a CDR backend temporarily.
#define AST_CLI_DEFINE(fn, txt,...)
static struct ast_str * ssl_cert
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk main include file. File version handling, generic pbx functions.
int ast_cdr_unregister(const char *name)
Unregister a CDR handling engine.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static int my_load_config_number(struct ast_config *cfg, const char *category, const char *variable, int *field, int def)
String manipulation functions.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static int calldate_compat
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define ast_str_make_space(buf, new_len)
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
int ast_cdr_backend_unsuspend(const char *name)
Unsuspend a CDR backend.
#define CONFIG_STATUS_FILEINVALID
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Structure for variables, used for configurations and for channel variables.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
static ast_mutex_t mysql_lock
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static struct aco_type item
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
#define ast_mutex_lock(a)
Definitions to aid in the use of thread local storage.
void ast_cli(int fd, const char *fmt,...)
static struct ast_str * ssl_ca
static struct ast_str * password
#define ast_verb(level,...)
static struct ast_str * dbtable
static struct ast_str * dbcharset
#define ast_strlen_zero(foo)
static struct ast_threadstorage sql2_buf
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_config_load(filename, flags)
Load a config file.
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
Register a CDR handling engine.
static struct ast_cli_entry cdr_mysql_status_cli[]
General Asterisk PBX channel definitions.
static char * handle_cli_cdr_mysql_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int my_load_config_string(struct ast_config *cfg, const char *category, const char *variable, struct ast_str **field, const char *def)
#define AST_RWLIST_TRAVERSE
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
#define ast_strdupa(s)
duplicate a string in memory from the stack
static int load_module(void)
A set of macros to manage forward-linked lists.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Responsible for call detail data.
static time_t connect_time
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
static struct ast_str * ssl_key
static void configure_connection_charset(void)
static struct ast_threadstorage sql1_buf
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
static struct ast_str * dbname
#define ast_calloc(num, len)
A wrapper for calloc()
static int mysql_log(struct ast_cdr *cdr)
static int my_unload_module(int reload)
#define AST_RWLIST_REMOVE_HEAD
Module has failed to load, may be in an inconsistent state.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
struct unload_string::@2 entry
Structure used to handle boolean flags.
static int my_connect_db(struct ast_config *cfg)
static struct ast_threadstorage escape_buf
Support for logging to various files, console and syslog Configuration in file logger.conf.
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS|AST_MODFLAG_LOAD_ORDER, "HTTP Phone Provisioning",.support_level=AST_MODULE_SUPPORT_EXTENDED,.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DEPEND,.requires="http",)
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s)
#define CONFIG_STATUS_FILEMISSING
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
static struct ast_str * dbsock
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
static const char config[]
static struct ast_str * dbuser
static struct ast_str * cdrzone
static struct ast_str * hostname
Options provided by main asterisk program.
int error(const char *format,...)
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Asterisk module definitions.
#define AST_MUTEX_DEFINE_STATIC(mutex)
static int unload_module(void)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
#define ast_mutex_unlock(a)
static void free_strings(void)
static int my_load_module(int reload)