1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-26 08:30:37 +02:00
openwrt-xburst/openwrt/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch
nico 9d5362a82a update asterisk to new upstream release (v1.2.1)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@2682 3c298f89-4303-0410-b956-a3cf2f4a3e73
2005-12-15 08:22:57 +00:00

699 lines
23 KiB
Diff

diff -ruN asterisk-1.2.0-old/configs/res_mysql.conf.sample asterisk-1.2.0-new/configs/res_mysql.conf.sample
--- asterisk-1.2.0-old/configs/res_mysql.conf.sample 1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.2.0-new/configs/res_mysql.conf.sample 2004-12-03 15:33:44.000000000 +0100
@@ -0,0 +1,15 @@
+;
+; Sample configuration for res_config_mysql.c
+;
+; The value of dbhost may be either a hostname or an IP address.
+; If dbhost is commented out or the string "localhost", a connection
+; to the local host is assumed and dbsock is used instead of TCP/IP
+; to connect to the server.
+;
+[general]
+;dbhost = 127.0.0.1
+;dbname = asterisk
+;dbuser = myuser
+;dbpass = mypass
+;dbport = 3306
+;dbsock = /tmp/mysql.sock
diff -ruN asterisk-1.2.0-old/res/res_config_mysql.c asterisk-1.2.0-new/res/res_config_mysql.c
--- asterisk-1.2.0-old/res/res_config_mysql.c 1970-01-01 01:00:00.000000000 +0100
+++ asterisk-1.2.0-new/res/res_config_mysql.c 2005-10-13 21:43:54.000000000 +0200
@@ -0,0 +1,675 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Copyright (C) 1999-2005, Digium, Inc.
+ *
+ * Mark Spencer <markster@digium.com> - Asterisk Author
+ * Matthew Boehm <mboehm@cytelcom.com> - MySQL RealTime Driver Author
+ *
+ * res_config_mysql.c <mysql plugin for RealTime configuration engine>
+ *
+ * v2.0 - (10-07-05) - mutex_lock fixes (bug #4973, comment #0034602)
+ *
+ * v1.9 - (08-19-05) - Added support to correctly honor the family database specified
+ * in extconfig.conf (bug #4973)
+ *
+ * v1.8 - (04-21-05) - Modified return values of update_mysql to better indicate
+ * what really happened.
+ *
+ * v1.7 - (01-28-05) - Fixed non-initialization of ast_category struct
+ * in realtime_multi_mysql function which caused segfault.
+ *
+ * v1.6 - (00-00-00) - Skipped to bring comments into sync with version number in CVS.
+ *
+ * v1.5.1 - (01-26-05) - Added better(?) locking stuff
+ *
+ * v1.5 - (01-26-05) - Brought up to date with new config.h changes (bug #3406)
+ * - Added in extra locking provided by georg (bug #3248)
+ *
+ * v1.4 - (12-02-04) - Added realtime_multi_mysql function
+ * This function will return an ast_config with categories,
+ * unlike standard realtime_mysql which only returns
+ * a linked list of ast_variables
+ *
+ * v1.3 - (12-01-04) - Added support other operators
+ * Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
+ *
+ * v1.2 - (11-DD-04) - Added reload. Updated load and unload.
+ * Code beautification (doc/CODING-GUIDELINES)
+ */
+
+#include <asterisk/channel.h>
+#include <asterisk/logger.h>
+#include <asterisk/config.h>
+#include <asterisk/module.h>
+#include <asterisk/lock.h>
+#include <asterisk/options.h>
+#include <asterisk/cli.h>
+#include <asterisk/utils.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mysql.h>
+#include <mysql_version.h>
+#include <errmsg.h>
+
+static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
+
+AST_MUTEX_DEFINE_STATIC(mysql_lock);
+#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
+MYSQL mysql;
+static char dbhost[50];
+static char dbuser[50];
+static char dbpass[50];
+static char dbname[50];
+static char dbsock[50];
+static int dbport;
+static int connected;
+static time_t connect_time;
+
+static int parse_config(void);
+static int mysql_reconnect(const char *database);
+static int realtime_mysql_status(int fd, int argc, char **argv);
+
+STANDARD_LOCAL_USER;
+
+LOCAL_USER_DECL;
+
+static char cli_realtime_mysql_status_usage[] =
+"Usage: realtime mysql status\n"
+" Shows connection information for the MySQL RealTime driver\n";
+
+static struct ast_cli_entry cli_realtime_mysql_status = {
+ { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
+ "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };
+
+static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MYSQL_FIELD *fields;
+ int numFields, i;
+ char sql[256];
+ char *stringp;
+ char *chunk;
+ char *op;
+ const char *newparam, *newval;
+ struct ast_variable *var=NULL, *prev=NULL;
+
+ if(!table) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ return NULL;
+ }
+
+ /* Get the first parameter and first value in our list of passed paramater/value pairs */
+ newparam = va_arg(ap, const char *);
+ newval = va_arg(ap, const char *);
+ if(!newparam || !newval) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
+ mysql_close(&mysql);
+ return NULL;
+ }
+
+ /* Create the first part of the query using the first parameter/value pairs we just extracted
+ If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+
+ if(!strchr(newparam, ' ')) op = " ="; else op = "";
+
+ snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
+ while((newparam = va_arg(ap, const char *))) {
+ newval = va_arg(ap, const char *);
+ if(!strchr(newparam, ' ')) op = " ="; else op = "";
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
+ }
+ va_end(ap);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
+
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ ast_mutex_lock(&mysql_lock);
+ if(!mysql_reconnect(database)) {
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if(mysql_real_query(&mysql, sql, strlen(sql))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if((result = mysql_store_result(&mysql))) {
+ numFields = mysql_num_fields(result);
+ fields = mysql_fetch_fields(result);
+
+ while((row = mysql_fetch_row(result))) {
+ for(i = 0; i < numFields; i++) {
+ stringp = row[i];
+ while(stringp) {
+ chunk = strsep(&stringp, ";");
+ if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
+ if(prev) {
+ prev->next = ast_variable_new(fields[i].name, chunk);
+ if (prev->next) {
+ prev = prev->next;
+ }
+ } else {
+ prev = var = ast_variable_new(fields[i].name, chunk);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
+ }
+
+ ast_mutex_unlock(&mysql_lock);
+ mysql_free_result(result);
+
+ return var;
+}
+
+static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ MYSQL_FIELD *fields;
+ int numFields, i;
+ char sql[256];
+ const char *initfield = NULL;
+ char *stringp;
+ char *chunk;
+ char *op;
+ const char *newparam, *newval;
+ struct ast_realloca ra;
+ struct ast_variable *var=NULL;
+ struct ast_config *cfg = NULL;
+ struct ast_category *cat = NULL;
+
+ if(!table) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ return NULL;
+ }
+
+ memset(&ra, 0, sizeof(ra));
+
+ cfg = ast_config_new();
+ if (!cfg) {
+ /* If I can't alloc memory at this point, why bother doing anything else? */
+ ast_log(LOG_WARNING, "Out of memory!\n");
+ return NULL;
+ }
+
+ /* Get the first parameter and first value in our list of passed paramater/value pairs */
+ newparam = va_arg(ap, const char *);
+ newval = va_arg(ap, const char *);
+ if(!newparam || !newval) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
+ mysql_close(&mysql);
+ return NULL;
+ }
+
+ initfield = ast_strdupa(newparam);
+ if(initfield && (op = strchr(initfield, ' '))) {
+ *op = '\0';
+ }
+
+ /* Create the first part of the query using the first parameter/value pairs we just extracted
+ If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+
+ if(!strchr(newparam, ' ')) op = " ="; else op = "";
+
+ snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
+ while((newparam = va_arg(ap, const char *))) {
+ newval = va_arg(ap, const char *);
+ if(!strchr(newparam, ' ')) op = " ="; else op = "";
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
+ }
+
+ if(initfield) {
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
+ }
+
+ va_end(ap);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
+
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ ast_mutex_lock(&mysql_lock);
+ if(!mysql_reconnect(database)) {
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if(mysql_real_query(&mysql, sql, strlen(sql))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if((result = mysql_store_result(&mysql))) {
+ numFields = mysql_num_fields(result);
+ fields = mysql_fetch_fields(result);
+
+ while((row = mysql_fetch_row(result))) {
+ var = NULL;
+ cat = ast_category_new("");
+ if(!cat) {
+ ast_log(LOG_WARNING, "Out of memory!\n");
+ continue;
+ }
+ for(i = 0; i < numFields; i++) {
+ stringp = row[i];
+ while(stringp) {
+ chunk = strsep(&stringp, ";");
+ if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
+ if(initfield && !strcmp(initfield, fields[i].name)) {
+ ast_category_rename(cat, chunk);
+ }
+ var = ast_variable_new(fields[i].name, chunk);
+ ast_variable_append(cat, var);
+ }
+ }
+ }
+ ast_category_append(cfg, cat);
+ }
+ } else {
+ ast_log(LOG_WARNING, "MySQL RealTime: Could not find any rows in table %s.\n", table);
+ }
+
+ ast_mutex_unlock(&mysql_lock);
+ mysql_free_result(result);
+
+ return cfg;
+}
+
+static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
+{
+ my_ulonglong numrows;
+ char sql[256];
+ const char *newparam, *newval;
+
+ if(!table) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
+ return -1;
+ }
+
+ /* Get the first parameter and first value in our list of passed paramater/value pairs */
+ newparam = va_arg(ap, const char *);
+ newval = va_arg(ap, const char *);
+ if(!newparam || !newval) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
+ mysql_close(&mysql);
+ return -1;
+ }
+
+ /* Create the first part of the query using the first parameter/value pairs we just extracted
+ If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
+
+ snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
+ while((newparam = va_arg(ap, const char *))) {
+ newval = va_arg(ap, const char *);
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
+ }
+ va_end(ap);
+ snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
+
+ ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
+
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ ast_mutex_lock(&mysql_lock);
+ if(!mysql_reconnect(database)) {
+ ast_mutex_unlock(&mysql_lock);
+ return -1;
+ }
+
+ if(mysql_real_query(&mysql, sql, strlen(sql))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+ ast_mutex_unlock(&mysql_lock);
+ return -1;
+ }
+
+ numrows = mysql_affected_rows(&mysql);
+ ast_mutex_unlock(&mysql_lock);
+
+ ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);
+
+ /* From http://dev.mysql.com/doc/mysql/en/mysql-affected-rows.html
+ * An integer greater than zero indicates the number of rows affected
+ * Zero indicates that no records were updated
+ * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.)
+ */
+
+ if(numrows >= 0)
+ return (int)numrows;
+
+ return -1;
+}
+
+static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *cfg)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ my_ulonglong num_rows;
+ struct ast_config *new;
+ struct ast_variable *cur_v, *new_v;
+ struct ast_category *cur_cat, *new_cat;
+ char sql[250] = "";
+ char last[80] = "";
+ int cat_started = 0;
+ int var_started = 0;
+ int last_cat_metric = 0;
+
+ last[0] = '\0';
+
+ if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
+ return NULL;
+ }
+
+ snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);
+
+ /* We now have our complete statement; Lets connect to the server and execute it. */
+ ast_mutex_lock(&mysql_lock);
+ if(!mysql_reconnect(database)) {
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if(mysql_real_query(&mysql, sql, strlen(sql))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+
+ if((result = mysql_store_result(&mysql))) {
+ num_rows = mysql_num_rows(result);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);
+
+ /* There might exist a better way to access the column names other than counting,
+ but I believe that would require another loop that we don't need. */
+
+ while((row = mysql_fetch_row(result))) {
+ if(!strcmp(row[1], "#include")) {
+ if (!ast_config_internal_load(row[2], cfg)) {
+ mysql_free_result(result);
+ ast_mutex_unlock(&mysql_lock);
+ return NULL;
+ }
+ continue;
+ }
+
+ if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
+ cur_cat = ast_category_new(row[0]);
+ if (!cur_cat) {
+ ast_log(LOG_WARNING, "Out of memory!\n");
+ break;
+ }
+ strcpy(last, row[0]);
+ last_cat_metric = atoi(row[3]);
+ ast_category_append(cfg, cur_cat);
+ }
+ new_v = ast_variable_new(row[1], row[2]);
+ ast_variable_append(cur_cat, new_v);
+ }
+ } else {
+ ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
+ }
+
+ mysql_free_result(result);
+ ast_mutex_unlock(&mysql_lock);
+
+ return cfg;
+}
+
+static struct ast_config_engine mysql_engine = {
+ .name = "mysql",
+ .load_func = config_mysql,
+ .realtime_func = realtime_mysql,
+ .realtime_multi_func = realtime_multi_mysql,
+ .update_func = update_mysql
+};
+
+int load_module (void)
+{
+ parse_config();
+
+ ast_mutex_lock(&mysql_lock);
+
+ if(!mysql_reconnect(NULL)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
+ }
+
+ ast_config_engine_register(&mysql_engine);
+ if(option_verbose) {
+ ast_verbose("MySQL RealTime driver loaded.\n");
+ }
+ ast_cli_register(&cli_realtime_mysql_status);
+
+ ast_mutex_unlock(&mysql_lock);
+
+ return 0;
+}
+
+int unload_module (void)
+{
+ /* Aquire control before doing anything to the module itself. */
+ ast_mutex_lock(&mysql_lock);
+
+ mysql_close(&mysql);
+ ast_cli_unregister(&cli_realtime_mysql_status);
+ ast_config_engine_deregister(&mysql_engine);
+ if(option_verbose) {
+ ast_verbose("MySQL RealTime unloaded.\n");
+ }
+
+ STANDARD_HANGUP_LOCALUSERS;
+
+ /* Unlock so something else can destroy the lock. */
+ ast_mutex_unlock(&mysql_lock);
+
+ return 0;
+}
+
+int reload (void)
+{
+ /* Aquire control before doing anything to the module itself. */
+ ast_mutex_lock(&mysql_lock);
+
+ mysql_close(&mysql);
+ connected = 0;
+ parse_config();
+
+ if(!mysql_reconnect(NULL)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
+ }
+
+ ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
+
+ /* Done reloading. Release lock so others can now use driver. */
+ ast_mutex_unlock(&mysql_lock);
+
+ return 0;
+}
+
+int parse_config (void)
+{
+ struct ast_config *config;
+ char *s;
+
+ config = ast_config_load(RES_CONFIG_MYSQL_CONF);
+
+ if(config) {
+ if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
+ strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
+ } else {
+ strncpy(dbuser, s, sizeof(dbuser) - 1);
+ }
+
+ if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
+ strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
+ } else {
+ strncpy(dbpass, s, sizeof(dbpass) - 1);
+ }
+
+ if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
+ dbhost[0] = '\0';
+ } else {
+ strncpy(dbhost, s, sizeof(dbhost) - 1);
+ }
+
+ if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
+ strncpy(dbname, "asterisk", sizeof(dbname) - 1);
+ } else {
+ strncpy(dbname, s, sizeof(dbname) - 1);
+ }
+
+ if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
+ dbport = 3306;
+ } else {
+ dbport = atoi(s);
+ }
+
+ if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
+ ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
+ strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
+ } else {
+ strncpy(dbsock, s, sizeof(dbsock) - 1);
+ }
+ }
+ ast_config_destroy(config);
+
+ if(dbhost) {
+ ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
+ ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
+ } else {
+ ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
+ }
+ ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
+ ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);
+
+ return 1;
+}
+
+char *description (void)
+{
+ return res_config_mysql_desc;
+}
+
+int usecount (void)
+{
+ /* Try and get a lock. If unsuccessful, than that means another thread is using the mysql object. */
+ if(ast_mutex_trylock(&mysql_lock)) {
+ ast_log(LOG_DEBUG, "MySQL RealTime: Module usage count is 1.\n");
+ return 1;
+ }
+ ast_mutex_unlock(&mysql_lock);
+ return 0;
+}
+
+char *key ()
+{
+ return ASTERISK_GPL_KEY;
+}
+
+static int mysql_reconnect(const char *database)
+{
+ char my_database[50];
+
+ if(!database || ast_strlen_zero(database))
+ ast_copy_string(my_database, dbname, sizeof(my_database));
+ else
+ ast_copy_string(my_database, database, sizeof(my_database));
+
+ /* mutex lock should have been locked before calling this function. */
+
+ if((!connected) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
+ if(!mysql_init(&mysql)) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
+ connected = 0;
+ return 0;
+ }
+ if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, my_database, dbport, dbsock, 0)) {
+ ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
+ connected = 1;
+ connect_time = time(NULL);
+ return 1;
+ } else {
+ ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
+ connected = 0;
+ return 0;
+ }
+ } else {
+ if(mysql_ping(&mysql) != 0) {
+ connected = 0;
+ ast_log(LOG_ERROR, "MySQL RealTime: Failed to reconnect. Check debug for more info.\n");
+ ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
+ return 0;
+ }
+
+ connected = 1;
+
+ if(mysql_select_db(&mysql, my_database) != 0) {
+ ast_log(LOG_WARNING, "MySQL RealTime: Unable to select database: %s. Still Connected.\n", my_database);
+ ast_log(LOG_DEBUG, "MySQL RealTime: Database Select Failed: %s\n", mysql_error(&mysql));
+ return 0;
+ }
+
+ ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
+ return 1;
+ }
+}
+
+static int realtime_mysql_status(int fd, int argc, char **argv)
+{
+ char status[256], status2[100] = "";
+ int ctime = time(NULL) - connect_time;
+
+ if(mysql_reconnect(NULL)) {
+ if(dbhost) {
+ snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
+ } else if(dbsock) {
+ snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
+ } else {
+ snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
+ }
+
+ if(dbuser && *dbuser) {
+ snprintf(status2, 99, " with username %s", dbuser);
+ }
+
+ if (ctime > 31536000) {
+ ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
+ } else if (ctime > 86400) {
+ ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
+ } else if (ctime > 3600) {
+ ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
+ } else if (ctime > 60) {
+ ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
+ } else {
+ ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
+ }
+
+ return RESULT_SUCCESS;
+ } else {
+ return RESULT_FAILURE;
+ }
+}