diff options
Diffstat (limited to 'package/asterisk/patches/asterisk-1.2.0-res_mysql.patch')
| -rw-r--r-- | package/asterisk/patches/asterisk-1.2.0-res_mysql.patch | 698 | 
1 files changed, 698 insertions, 0 deletions
diff --git a/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch b/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch new file mode 100644 index 000000000..5de810741 --- /dev/null +++ b/package/asterisk/patches/asterisk-1.2.0-res_mysql.patch @@ -0,0 +1,698 @@ +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; ++	} ++}  | 
