[Freeswitch-svn] [commit] r4846 - in freeswitch/trunk: . src src/include src/mod/endpoints/mod_sofia src/mod/languages/mod_spidermonkey src/mod/languages/mod_spidermonkey_odbc

Freeswitch SVN anthm at freeswitch.org
Tue Apr 3 23:08:17 EDT 2007


Author: anthm
Date: Tue Apr  3 23:08:17 2007
New Revision: 4846

Added:
   freeswitch/trunk/src/include/switch_odbc.h
   freeswitch/trunk/src/switch_odbc.c
Modified:
   freeswitch/trunk/Makefile.am
   freeswitch/trunk/configure.in
   freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile
   freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
   freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/Makefile
   freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/mod_spidermonkey_odbc.c

Log:
add core ODBC

Modified: freeswitch/trunk/Makefile.am
==============================================================================
--- freeswitch/trunk/Makefile.am	(original)
+++ freeswitch/trunk/Makefile.am	Tue Apr  3 23:08:17 2007
@@ -103,6 +103,11 @@
 CORE_LIBS      = libs/apr/libapr-1.la libs/apr-util/libaprutil-1.la
 CORE_LIBS     += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la
 CORE_LIBS     += libs/srtp/libsrtp.la $(RESAMPLE_LIB)
+if ADD_ODBC
+libfreeswitch_la_SOURCES += src/switch_odbc.c
+library_include_HEADERS += src/include/switch_odbc.h
+CORE_LIBS     += -lodbc
+endif
 
 lib_LTLIBRARIES	          = libfreeswitch.la
 libfreeswitch_la_CFLAGS   = $(CORE_CFLAGS) $(AM_CFLAGS)

Modified: freeswitch/trunk/configure.in
==============================================================================
--- freeswitch/trunk/configure.in	(original)
+++ freeswitch/trunk/configure.in	Tue Apr  3 23:08:17 2007
@@ -314,10 +314,14 @@
 AC_ARG_ENABLE(crash-protection,     
 	[  --enable-crash-protection         Compile with CRASH Protection],,[enable_crash_prot="no"])
 
+AC_ARG_ENABLE(core-odbc-support,     
+	[  --enable-core-odbc-support         Compile with ODBC Support],,[enable_core_odbc_support="no"])
+
 #AX_LIB_MYSQL([MINIMUM-VERSION]) 
 AX_LIB_MYSQL
 
 AM_CONDITIONAL([CRASHPROT],[test "x$enable_crash_prot" != "xno"])
+AM_CONDITIONAL([ADD_ODBC],[test "x$enable_core_odbc_support" != "xno"])
 AM_CONDITIONAL([HAVE_MYSQL],[test "$have_mysql" = "yes"])
 
 AC_CONFIG_FILES([Makefile

Added: freeswitch/trunk/src/include/switch_odbc.h
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/include/switch_odbc.h	Tue Apr  3 23:08:17 2007
@@ -0,0 +1,82 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * switch_odbc.h -- ODBC
+ *
+ */
+
+#ifndef SWITCH_ODBC_H
+#define SWITCH_ODBC_H
+
+#include <switch.h>
+#include <sql.h>
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4201)
+#include <sqlext.h>
+#pragma warning(pop)
+#else
+#include <sqlext.h>
+#endif
+#include <sqltypes.h>
+
+SWITCH_BEGIN_EXTERN_C struct switch_odbc_handle;
+
+typedef enum {
+	SWITCH_ODBC_STATE_INIT,
+	SWITCH_ODBC_STATE_DOWN,
+	SWITCH_ODBC_STATE_CONNECTED,
+	SWITCH_ODBC_STATE_ERROR
+} switch_odbc_state_t;
+typedef struct switch_odbc_handle switch_odbc_handle_t;
+
+typedef enum {
+	SWITCH_ODBC_SUCCESS = 0,
+	SWITCH_ODBC_FAIL = -1
+} switch_odbc_status_t;
+
+SWITCH_DECLARE(switch_odbc_handle_t) * switch_odbc_handle_new(char *dsn, char *username, char *password);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle);
+SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep);
+SWITCH_DECLARE(switch_odbc_state_t) switch_odbc_handle_get_state(switch_odbc_handle_t *handle);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_t *handle, char *sql, SQLHSTMT * rstmt);
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec(switch_odbc_handle_t *handle,
+																	  char *sql, switch_core_db_callback_func_t callback, void *pdata);
+SWITCH_DECLARE(char *) switch_odbc_handle_get_error(switch_odbc_handle_t *handle, SQLHSTMT stmt);
+SWITCH_END_EXTERN_C
+#endif
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/Makefile	Tue Apr  3 23:08:17 2007
@@ -12,6 +12,8 @@
 LOCAL_CFLAGS += -I$(SOFIAUA_DIR)/soa -I$(SOFIAUA_DIR)/sresolv
 LOCAL_CFLAGS += -I$(SOFIAUA_DIR)/stun -I$(SOFIAUA_DIR)/su
 LOCAL_CFLAGS += -I$(SOFIAUA_DIR)/tport -I$(SOFIAUA_DIR)/url
+LOCAL_CFLAGS += `if test -f $(BASE)/.libs/libfreeswitch_la-switch_odbc.o ; then echo -DSWITCH_HAVE_ODBC; fi ;`
+
 LOCAL_OBJS=sofia.o sofia_glue.o sofia_presence.o sofia_reg.o
 LOCAL_SOURCES=sofia.c sofia_glue.c sofia_presense.c sofia_reg.c mod_sofia.c
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/mod_sofia.h	Tue Apr  3 23:08:17 2007
@@ -40,6 +40,9 @@
 
 #define HAVE_APR
 #include <switch.h>
+#ifdef SWITCH_HAVE_ODBC
+#include <switch_odbc.h>
+#endif
 
 static const char modname[] = "mod_sofia";
 static const switch_state_handler_table_t noop_state_handler = { 0 };
@@ -221,6 +224,13 @@
 	su_home_t *home;
 	switch_hash_t *profile_hash;
 	switch_hash_t *chat_hash;
+	switch_core_db_t *master_db;
+#ifdef SWITCH_HAVE_ODBC
+	char *odbc_dsn;
+	char *odbc_user;
+	char *odbc_pass;
+	switch_odbc_handle_t *master_odbc;
+#endif
 };
 
 
@@ -328,8 +338,6 @@
 
 uint8_t negotiate_sdp(switch_core_session_t *session, sdp_session_t * sdp);
 
-char *sofia_reg_get_auth_data(char *dbname, char *nonce, char *npassword, size_t len, switch_mutex_t * mutex);
-
 void sofia_presence_establish_presence(sofia_profile_t * profile);
 
 void sofia_handle_sip_i_state(int status,
@@ -387,8 +395,8 @@
 
 sofia_profile_t *sofia_glue_find_profile(char *key);
 void sofia_glue_add_profile(char *key, sofia_profile_t * profile);
-void sofia_glue_execute_sql(char *dbname, char *sql, switch_mutex_t * mutex);
-void sofia_reg_check_expire(switch_core_db_t *db, sofia_profile_t * profile, time_t now);
+void sofia_glue_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex);
+void sofia_reg_check_expire(sofia_profile_t * profile, time_t now);
 void sofia_reg_check_gateway(sofia_profile_t * profile, time_t now);
 void sofia_reg_unregister(sofia_profile_t * profile);
 switch_status_t sofia_glue_ext_address_lookup(char **ip, switch_port_t *port, char *sourceip, switch_memory_pool_t *pool);
@@ -404,3 +412,12 @@
 switch_status_t sofia_on_hangup(switch_core_session_t *session);
 char *sofia_glue_get_url_from_contact(char *buf, uint8_t to_dup);
 void sofia_presence_set_hash_key(char *hash_key, int32_t len, sip_t const *sip);
+void sofia_glue_sql_close(sofia_profile_t *profile);
+int sofia_glue_init_sql(sofia_profile_t *profile);
+switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile,
+											  switch_bool_t master,
+											  switch_mutex_t *mutex,
+											  char *sql,
+											  switch_core_db_callback_func_t callback,
+											  void *pdata);
+char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len);

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia.c	Tue Apr  3 23:08:17 2007
@@ -36,41 +36,6 @@
 extern su_log_t tport_log[];
 
 
-static char reg_sql[] =
-	"CREATE TABLE sip_registrations (\n"
-	"   user            VARCHAR(255),\n"
-	"   host            VARCHAR(255),\n"
-	"   contact         VARCHAR(1024),\n" 
-	"   status          VARCHAR(255),\n" 
-	"   rpid            VARCHAR(255),\n" 
-	"   expires         INTEGER(8)" ");\n";
-
-
-static char sub_sql[] =
-	"CREATE TABLE sip_subscriptions (\n"
-	"   proto           VARCHAR(255),\n"
-	"   user            VARCHAR(255),\n"
-	"   host            VARCHAR(255),\n"
-	"   sub_to_user     VARCHAR(255),\n"
-	"   sub_to_host     VARCHAR(255),\n"
-	"   event           VARCHAR(255),\n"
-	"   contact         VARCHAR(1024),\n"
-	"   call_id         VARCHAR(255),\n" 
-	"   full_from       VARCHAR(255),\n" 
-	"   full_via        VARCHAR(255),\n" 
-	"   expires         INTEGER(8)" ");\n";
-
-
-static char auth_sql[] =
-	"CREATE TABLE sip_authentication (\n"
-	"   user            VARCHAR(255),\n"
-	"   host            VARCHAR(255),\n" 
-	"   passwd            VARCHAR(255),\n" 
-	"   nonce           VARCHAR(255),\n" 
-	"   expires         INTEGER(8)"
-	");\n";
-
-
 void sofia_event_callback(nua_event_t event,
 						   int status,
 						   char const *phrase,
@@ -253,7 +218,7 @@
 		}
 
 		if (sql) {
-			sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
+			sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex);
 			switch_safe_free(sql);
 			sql = NULL;
 			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Propagating registration for %s@%s->%s\n", from_user, from_host, contact_str);
@@ -272,7 +237,6 @@
 	sip_alias_node_t *node;
 	uint32_t ireg_loops = 0;
 	uint32_t gateway_loops = 0;
-	switch_core_db_t *db;
 	switch_event_t *s_event;
 
 	profile->s_root = su_root_create(NULL);
@@ -320,11 +284,7 @@
 	}
 
 
-	if ((db = switch_core_db_open_file(profile->dbname))) {
-		switch_core_db_test_reactive(db, "select contact from sip_registrations", reg_sql);
-		switch_core_db_test_reactive(db, "select contact from sip_subscriptions", sub_sql);
-		switch_core_db_test_reactive(db, "select * from sip_authentication", auth_sql);
-	} else {
+	if (!sofia_glue_init_sql(profile)) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Cannot Open SQL Database!\n");
 		return NULL;
 	}
@@ -362,7 +322,7 @@
 
 	while (mod_sofia_globals.running == 1) {
 		if (++ireg_loops >= IREG_SECONDS) {
-			sofia_reg_check_expire(db, profile, time(NULL));
+			sofia_reg_check_expire(profile, time(NULL));
 			ireg_loops = 0;
 		}
 
@@ -373,8 +333,9 @@
 
 		su_root_step(profile->s_root, 1000);
 	}
+	
+	sofia_glue_sql_close(profile);
 
-	switch_core_db_close(db);
 	sofia_reg_unregister(profile);
 	su_home_unref(profile->home);
 
@@ -496,6 +457,7 @@
 
 				profile->name = switch_core_strdup(profile->pool, xprofilename);
 				snprintf(url, sizeof(url), "sofia_reg_%s", xprofilename);
+				
 				profile->dbname = switch_core_strdup(profile->pool, url);
 				switch_core_hash_init(&profile->chat_hash, profile->pool);
 
@@ -510,6 +472,22 @@
 						profile->debug = atoi(val);
 					} else if (!strcasecmp(var, "use-rtp-timer") && switch_true(val)) {
 						switch_set_flag(profile, TFLAG_TIMER);
+
+					} else if (!strcasecmp(var, "odbc-dsn")) {
+#ifdef SWITCH_HAVE_ODBC
+						profile->odbc_dsn = switch_core_strdup(profile->pool, val);
+						if ((profile->odbc_user = strchr(profile->odbc_dsn, ':'))) {
+							*profile->odbc_user++ = '\0';
+						}
+						if ((profile->odbc_pass = strchr(profile->odbc_user, ':'))) {
+							*profile->odbc_pass++ = '\0';
+						}
+
+				
+#else
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ODBC IS NOT AVAILABLE!\n");
+#endif
+						
 					} else if (!strcasecmp(var, "inbound-no-media") && switch_true(val)) {
 						switch_set_flag(profile, TFLAG_INB_NOMEDIA);
 					} else if (!strcasecmp(var, "inbound-late-negotiation") && switch_true(val)) {

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_glue.c	Tue Apr  3 23:08:17 2007
@@ -1119,7 +1119,91 @@
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 }
 
-void sofia_glue_execute_sql(char *dbname, char *sql, switch_mutex_t * mutex)
+int sofia_glue_init_sql(sofia_profile_t *profile)
+{
+
+	
+	char reg_sql[] =
+		"CREATE TABLE sip_registrations (\n"
+		"   user            VARCHAR(255),\n"
+		"   host            VARCHAR(255),\n"
+		"   contact         VARCHAR(1024),\n" 
+		"   status          VARCHAR(255),\n" 
+		"   rpid            VARCHAR(255),\n" 
+		"   expires         INTEGER(8)" ");\n";
+
+
+	char sub_sql[] =
+		"CREATE TABLE sip_subscriptions (\n"
+		"   proto           VARCHAR(255),\n"
+		"   user            VARCHAR(255),\n"
+		"   host            VARCHAR(255),\n"
+		"   sub_to_user     VARCHAR(255),\n"
+		"   sub_to_host     VARCHAR(255),\n"
+		"   event           VARCHAR(255),\n"
+		"   contact         VARCHAR(1024),\n"
+		"   call_id         VARCHAR(255),\n" 
+		"   full_from       VARCHAR(255),\n" 
+		"   full_via        VARCHAR(255),\n" 
+		"   expires         INTEGER(8)" ");\n";
+
+
+	char auth_sql[] =
+		"CREATE TABLE sip_authentication (\n"
+		"   user            VARCHAR(255),\n"
+		"   host            VARCHAR(255),\n" 
+		"   passwd            VARCHAR(255),\n" 
+		"   nonce           VARCHAR(255),\n" 
+		"   expires         INTEGER(8)"
+		");\n";
+	
+#ifdef SWITCH_HAVE_ODBC
+	if (profile->odbc_dsn) {
+		if (!(profile->master_odbc = switch_odbc_handle_new(profile->odbc_dsn, profile->odbc_user, profile->odbc_pass))) {
+			return 0;
+		}
+		if (switch_odbc_handle_connect(profile->master_odbc) != SWITCH_ODBC_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Connecting ODBC DSN: %s\n", profile->odbc_dsn);
+			return 0;
+		}
+
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected ODBC DSN: %s\n", profile->odbc_dsn);
+			
+		switch_odbc_handle_exec(profile->master_odbc, reg_sql, NULL);
+		switch_odbc_handle_exec(profile->master_odbc, sub_sql, NULL);
+		switch_odbc_handle_exec(profile->master_odbc, auth_sql, NULL);
+	} else {
+#endif
+		if (!(profile->master_db = switch_core_db_open_file(profile->dbname))) {
+			return 0;
+		}
+
+		switch_core_db_test_reactive(profile->master_db, "select contact from sip_registrations", reg_sql);
+		switch_core_db_test_reactive(profile->master_db, "select contact from sip_subscriptions", sub_sql);
+		switch_core_db_test_reactive(profile->master_db, "select * from sip_authentication", auth_sql);
+
+#ifdef SWITCH_HAVE_ODBC
+	}
+#endif
+
+	return 1;
+}
+
+void sofia_glue_sql_close(sofia_profile_t *profile)
+{
+#ifdef SWITCH_HAVE_ODBC
+    if (profile->odbc_dsn) {
+		switch_odbc_handle_destroy(&profile->master_odbc);
+	} else {
+#endif
+		switch_core_db_close(profile->master_db);
+#ifdef SWITCH_HAVE_ODBC
+	}
+#endif
+}
+
+
+void sofia_glue_execute_sql(sofia_profile_t *profile, switch_bool_t master, char *sql, switch_mutex_t *mutex)
 {
 	switch_core_db_t *db;
 
@@ -1127,12 +1211,38 @@
 		switch_mutex_lock(mutex);
 	}
 
-	if (!(db = switch_core_db_open_file(dbname))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", dbname);
-		goto end;
+#ifdef SWITCH_HAVE_ODBC
+    if (profile->odbc_dsn) {
+		SQLHSTMT stmt;
+		if (switch_odbc_handle_exec(profile->master_odbc, sql, &stmt) != SWITCH_ODBC_SUCCESS) {
+			char *err_str;
+			err_str = switch_odbc_handle_get_error(profile->master_odbc, stmt);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERR: [%s]\n[%s]\n", sql, switch_str_nil(err_str));
+			switch_safe_free(err_str);
+		}
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+	} else {
+#endif
+
+
+	if (master) {
+		db = profile->master_db;
+	} else {
+		if (!(db = switch_core_db_open_file(profile->dbname))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+			goto end;
+		}
 	}
 	switch_core_db_persistant_execute(db, sql, 25);
-	switch_core_db_close(db);
+	if (!master) {
+		switch_core_db_close(db);
+	}
+
+
+#ifdef SWITCH_HAVE_ODBC
+    }
+#endif
+
 
   end:
 	if (mutex) {
@@ -1141,6 +1251,159 @@
 }
 
 
+switch_bool_t sofia_glue_execute_sql_callback(sofia_profile_t *profile,
+											  switch_bool_t master,
+											  switch_mutex_t *mutex,
+											  char *sql,
+											  switch_core_db_callback_func_t callback,
+											  void *pdata)
+{
+	switch_bool_t ret = SWITCH_FALSE;
+	switch_core_db_t *db;
+	char *errmsg = NULL;
+	
+	if (mutex) {
+        switch_mutex_lock(mutex);
+    }
+
+
+#ifdef SWITCH_HAVE_ODBC
+    if (profile->odbc_dsn) {
+		switch_odbc_handle_callback_exec(profile->master_odbc, sql, callback, pdata);
+	} else {
+#endif
+
+
+	if (master) {
+		db = profile->master_db;
+	} else {
+		if (!(db = switch_core_db_open_file(profile->dbname))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+			goto end;
+		}
+	}
+	
+	switch_core_db_exec(db, sql, callback, pdata, &errmsg);
+
+	if (errmsg) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: [%s] %s\n", sql, errmsg);
+		free(errmsg);
+	}
+
+	if (!master && db) {
+		switch_core_db_close(db);
+	}
+
+#ifdef SWITCH_HAVE_ODBC
+    }
+#endif
+
+
+ end:
+
+	if (mutex) {
+        switch_mutex_unlock(mutex);
+    }
+	
+
+
+	return ret;
+
+}
+
+#ifdef SWITCH_HAVE_ODBC
+static char *sofia_glue_execute_sql2str_odbc(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len)
+{
+	char *ret = NULL;
+	SQLHSTMT stmt;
+	SQLCHAR name[1024];
+	SQLINTEGER m = 0;
+
+	if (switch_odbc_handle_exec(profile->master_odbc, sql, &stmt) == SWITCH_ODBC_SUCCESS) {
+		SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
+		SQLUINTEGER ColumnSize;
+		SQLRowCount(stmt, &m);
+
+		if (m <= 0) {
+			return NULL;
+		}
+
+		if (SQLFetch(stmt) != SQL_SUCCESS) {
+			return NULL;
+		}
+
+		SQLDescribeCol(stmt, 1, name, sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
+		SQLGetData(stmt, 1, SQL_C_CHAR, (SQLCHAR *)resbuf, len, NULL);
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+		ret = resbuf;
+	}
+
+	return ret;
+}
+
+#endif
+
+char *sofia_glue_execute_sql2str(sofia_profile_t *profile, switch_mutex_t *mutex, char *sql, char *resbuf, size_t len)
+{
+	switch_core_db_t *db;
+	switch_core_db_stmt_t *stmt;
+	char *ret = NULL;
+
+#ifdef SWITCH_HAVE_ODBC
+    if (profile->odbc_dsn) {
+		return sofia_glue_execute_sql2str_odbc(profile, mutex, sql, resbuf, len);
+	}
+#endif
+
+	if (mutex) {
+		switch_mutex_lock(mutex);
+	}
+
+	if (!(db = switch_core_db_open_file(profile->dbname))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+		goto end;
+	}
+
+	if (switch_core_db_prepare(db, sql, -1, &stmt, 0)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error!\n");
+		goto fail;
+	} else {
+		int running = 1;
+		int colcount;
+
+		while (running < 5000) {
+			int result = switch_core_db_step(stmt);
+
+			if (result == SWITCH_CORE_DB_ROW) {
+				if ((colcount = switch_core_db_column_count(stmt))) {
+					switch_copy_string(resbuf, (char *) switch_core_db_column_text(stmt, 0), len);
+					ret = resbuf;
+				}
+				break;
+			} else if (result == SWITCH_CORE_DB_BUSY) {
+				running++;
+				switch_yield(1000);
+				continue;
+			}
+			break;
+		}
+
+		switch_core_db_finalize(stmt);
+	}
+
+
+  fail:
+
+	switch_core_db_close(db);
+
+  end:
+	if (mutex) {
+		switch_mutex_unlock(mutex);
+	}
+
+	return ret;
+}
+
 int sofia_glue_get_user_host(char *in, char **user, char **host)
 {
 	char *p, *h, *u = in;

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_presence.c	Tue Apr  3 23:08:17 2007
@@ -105,8 +105,7 @@
 
 void sofia_presence_cancel(void)
 {
-	char *sql, *errmsg = NULL;
-	switch_core_db_t *db;
+	char *sql;
 	sofia_profile_t *profile;
 	switch_hash_index_t *hi;
 	void *val;
@@ -120,47 +119,30 @@
 				continue;
 			}
 
-			if (!(db = switch_core_db_open_file(profile->dbname))) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+			if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, sql, sofia_presence_sub_callback, profile) != SWITCH_TRUE) {
 				continue;
 			}
-			switch_mutex_lock(profile->ireg_mutex);
-			switch_core_db_exec(db, sql, sofia_presence_sub_callback, profile, &errmsg);
-			switch_mutex_unlock(profile->ireg_mutex);
-			switch_core_db_close(db);
 		}
 		switch_safe_free(sql);
+		switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 	}
-	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
 }
 
 void sofia_presence_establish_presence(sofia_profile_t * profile)
 {
-	char *sql, *errmsg = NULL;
-	switch_core_db_t *db;
 
-	if (!(db = switch_core_db_open_file(profile->dbname))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+	if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex, 
+										"select user,host,'Registered','unknown','' from sip_registrations", 
+										sofia_presence_resub_callback, profile) != SWITCH_TRUE) {
 		return;
 	}
 
-	if ((sql = switch_mprintf("select user,host,'Registered','unknown','' sip_registrations"))) {
-		switch_mutex_lock(profile->ireg_mutex);
-		switch_core_db_exec(db, sql, sofia_presence_resub_callback, profile, &errmsg);
-		switch_mutex_unlock(profile->ireg_mutex);
-		switch_safe_free(sql);
-	}
-
-	if ((sql = switch_mprintf("select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions "
-							  "where proto='ext' or proto='user' or proto='conf'"))) {
-		switch_mutex_lock(profile->ireg_mutex);
-		switch_core_db_exec(db, sql, sofia_presence_resub_callback, profile, &errmsg);
-		switch_mutex_unlock(profile->ireg_mutex);
-		switch_safe_free(sql);
+	if (sofia_glue_execute_sql_callback(profile, SWITCH_FALSE, profile->ireg_mutex,
+										"select sub_to_user,sub_to_host,'Online','unknown',proto from sip_subscriptions "
+										"where proto='ext' or proto='user' or proto='conf'",
+										sofia_presence_resub_callback, profile) != SWITCH_TRUE) {
+		return;
 	}
-
-	switch_core_db_close(db);
-
 }
 
 
@@ -196,9 +178,7 @@
 {
 	char *account, *dup_account, *yn, *host, *user;
 	char *sql;
-	switch_core_db_t *db;
 	sofia_profile_t *profile;
-	char *errmsg = NULL;
 	switch_stream_handle_t stream = { 0 };
 	switch_event_header_t *hp;
 
@@ -222,13 +202,7 @@
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot find profile for host %s\n", switch_str_nil(host));
 		return;
 	}
-
-
-	if (!(db = switch_core_db_open_file(profile->dbname))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-		return;
-	}
-
+	
 	SWITCH_STANDARD_STREAM(stream);
 
 	for (hp = event->headers; hp; hp = hp->next) {
@@ -246,12 +220,14 @@
 
 	assert (sql != NULL);
 
-	switch_mutex_lock(profile->ireg_mutex);
-	switch_core_db_exec(db, sql, sofia_presence_mwi_callback, profile, &errmsg);
-	if (errmsg) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR: %s\n", errmsg);
-	}
-	switch_mutex_unlock(profile->ireg_mutex);		
+	sofia_glue_execute_sql_callback(profile,
+									SWITCH_FALSE,
+									profile->ireg_mutex,
+									sql,
+									sofia_presence_mwi_callback,
+									profile);
+
+
 	switch_safe_free(sql);
 	switch_safe_free(dup_account);
 }
@@ -269,8 +245,6 @@
 	//char *event_subtype = switch_event_get_header(event, "event_subtype");
 	char *sql = NULL;
 	char *euser = NULL, *user = NULL, *host = NULL;
-	char *errmsg;
-	switch_core_db_t *db;
 
 
 	if (rpid && !strcasecmp(rpid, "n/a")) {
@@ -310,7 +284,8 @@
 		} else {
 			sql = switch_mprintf("select 1,'%q','%q',* from sip_subscriptions where event='presence'", status, rpid);
 		}
-
+		
+		assert(sql != NULL);
 		switch_mutex_lock(mod_sofia_globals.hash_mutex);
 		for (hi = switch_hash_first(switch_hash_pool_get(mod_sofia_globals.profile_hash), mod_sofia_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
 			switch_hash_this(hi, NULL, NULL, &val);
@@ -319,20 +294,18 @@
 				continue;
 			}
 
-			if (sql) {
-				if (!(db = switch_core_db_open_file(profile->dbname))) {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-					continue;
-				}
-				switch_mutex_lock(profile->ireg_mutex);
-				switch_core_db_exec(db, sql, sofia_presence_sub_callback, profile, &errmsg);
-				switch_mutex_unlock(profile->ireg_mutex);
-				switch_core_db_close(db);
-			}
+		
+			sofia_glue_execute_sql_callback(profile,
+											SWITCH_FALSE,
+											profile->ireg_mutex,
+											sql,
+											sofia_presence_sub_callback,
+											profile);
+		
 
 		}
 		switch_mutex_unlock(mod_sofia_globals.hash_mutex);
-
+		free(sql);
 		return;
 	}
 
@@ -365,7 +338,6 @@
 	switch (event->event_id) {
 	case SWITCH_EVENT_PRESENCE_PROBE:
 		if (proto) {
-			switch_core_db_t *db = NULL;
 			char *to = switch_event_get_header(event, "to");
 			char *user, *euser, *host, *p;
 
@@ -382,23 +354,19 @@
 			}
 
 			if (euser && host &&
-				(sql =
-				 switch_mprintf("select user,host,status,rpid,'' from sip_registrations where user='%q' and host='%q'",
-								euser, host)) && (profile = sofia_glue_find_profile(host))) {
-				if (!(db = switch_core_db_open_file(profile->dbname))) {
-					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-					switch_safe_free(user);
-					switch_safe_free(sql);
-					return;
-				}
+				(sql = switch_mprintf("select user,host,status,rpid,'' from sip_registrations where user='%q' and host='%q'",
+									  euser, host)) && (profile = sofia_glue_find_profile(host))) {
+				
+				sofia_glue_execute_sql_callback(profile,
+												SWITCH_FALSE,
+												profile->ireg_mutex,
+												sql,
+												sofia_presence_resub_callback,
+												profile);
 
-				switch_mutex_lock(profile->ireg_mutex);
-				switch_core_db_exec(db, sql, sofia_presence_resub_callback, profile, &errmsg);
-				switch_mutex_unlock(profile->ireg_mutex);
 				switch_safe_free(sql);
 			}
 			switch_safe_free(user);
-			switch_core_db_close(db);
 		}
 		return;
 	case SWITCH_EVENT_PRESENCE_IN:
@@ -426,15 +394,13 @@
 		}
 
 		if (sql) {
-			if (!(db = switch_core_db_open_file(profile->dbname))) {
-				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-				continue;
-			}
-			switch_mutex_lock(profile->ireg_mutex);
-			switch_core_db_exec(db, sql, sofia_presence_sub_callback, profile, &errmsg);
-			switch_mutex_unlock(profile->ireg_mutex);
+			sofia_glue_execute_sql_callback(profile,
+											SWITCH_FALSE,
+											profile->ireg_mutex,
+											sql,
+											sofia_presence_sub_callback,
+											profile);
 
-			switch_core_db_close(db);
 		}
 	}
 	switch_mutex_unlock(mod_sofia_globals.hash_mutex);
@@ -665,8 +631,6 @@
 		char *to_str = NULL;
 		char *full_from = NULL;
 		char *full_via = NULL;
-		switch_core_db_t *db;
-		char *errmsg;
 		char *sstr;
 		const char *display = "\"user\"";
 		switch_event_t *sevent;
@@ -762,17 +726,28 @@
 			from_host = "n/a";
 		}
 
-		if ((sql = switch_mprintf("delete from sip_subscriptions where "
-								  "proto='%q' and user='%q' and host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q';\n"
-								  "insert into sip_subscriptions values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
-								  proto,
-								  from_user,
-								  from_host,
-								  to_user,
-								  to_host, event, proto, from_user, from_host, to_user, to_host, event, contact_str, call_id, full_from, full_via, exp))) {
-			sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
-			switch_safe_free(sql);
-		}
+		switch_mutex_lock(profile->ireg_mutex);
+
+		sql = switch_mprintf("delete from sip_subscriptions where "
+							 "proto='%q' and user='%q' and host='%q' and sub_to_user='%q' and sub_to_host='%q' and event='%q'",
+							 proto,
+							 from_user,
+							 from_host,
+							 to_user,
+							 to_host, event, proto
+							 );
+
+		assert(sql != NULL);
+		sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL);
+		free(sql);
+		sql = switch_mprintf("insert into sip_subscriptions values ('%q','%q','%q','%q','%q','%q','%q','%q','%q','%q',%ld)",
+							 proto, from_user, from_host, to_user, to_host, event, contact_str, call_id, full_from, full_via, exp);
+
+		assert(sql != NULL);
+		sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL);
+		free(sql);
+
+		switch_mutex_unlock(profile->ireg_mutex);
 
 		sstr = switch_mprintf("active;expires=%ld", exp_raw);
 
@@ -784,18 +759,17 @@
 
 		switch_safe_free(sstr);
 
-		if (!(db = switch_core_db_open_file(profile->dbname))) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-			goto end;
-		}
 		if ((sql = switch_mprintf("select * from sip_subscriptions where user='%q' and host='%q'", to_user, to_host, to_user, to_host))) {
-			switch_mutex_lock(profile->ireg_mutex);
-			switch_core_db_exec(db, sql, sofia_presence_sub_reg_callback, profile, &errmsg);
-			switch_mutex_unlock(profile->ireg_mutex);
+			sofia_glue_execute_sql_callback(profile,
+											SWITCH_FALSE,
+											profile->ireg_mutex,
+											sql,
+											sofia_presence_sub_reg_callback,
+											profile);
+
 			switch_safe_free(sql);
 		}
-		switch_core_db_close(db);
-	  end:
+	end:
 
 		if (event) {
 			su_free(profile->home, event);
@@ -878,7 +852,7 @@
 				if ((sql =
 					 switch_mprintf("update sip_registrations set status='%q',rpid='%q' where user='%q' and host='%q'",
 									note_txt, rpid, from_user, from_host))) {
-					sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
+					sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex);
 					switch_safe_free(sql);
 				}
 

Modified: freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c
==============================================================================
--- freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	(original)
+++ freeswitch/trunk/src/mod/endpoints/mod_sofia/sofia_reg.c	Tue Apr  3 23:08:17 2007
@@ -35,7 +35,7 @@
 #include "mod_sofia.h"
 
 
-void sofia_reg_unregister(sofia_profile_t * profile)
+void sofia_reg_unregister(sofia_profile_t *profile)
 {
 	outbound_reg_t *gateway_ptr;
 	for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
@@ -48,7 +48,7 @@
 	}
 }
 
-void sofia_reg_check_gateway(sofia_profile_t * profile, time_t now)
+void sofia_reg_check_gateway(sofia_profile_t *profile, time_t now)
 {
 	outbound_reg_t *gateway_ptr;
 	for (gateway_ptr = profile->gateways; gateway_ptr; gateway_ptr = gateway_ptr->next) {
@@ -133,73 +133,74 @@
 	return 0;
 }
 
-void sofia_reg_check_expire(switch_core_db_t *db, sofia_profile_t * profile, time_t now)
+void sofia_reg_check_expire(sofia_profile_t *profile, time_t now)
 {
 	char sql[1024];
-	char *errmsg;
 
-	if (!db) {
+#ifdef SWITCH_HAVE_ODBC
+    if (profile->odbc_dsn) {
+     	if (!profile->master_odbc) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
+			return;
+		}   
+    } else {
+#endif
+	if (!profile->master_db) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
 		return;
 	}
+#ifdef SWITCH_HAVE_ODBC
+    }
+#endif
 
-	switch_mutex_lock(profile->ireg_mutex);
-	snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires < %ld", profile->name, (long) now);
-	switch_core_db_exec(db, sql, sofia_reg_del_callback, NULL, &errmsg);
-
-	if (errmsg) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", sql, errmsg);
-		switch_safe_free(errmsg);
-		errmsg = NULL;
-	}
+	snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
 
-	snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires < %ld", (long) now);
-	switch_core_db_persistant_execute(db, sql, 1000);
-	snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires < %ld", (long) now);
-	switch_core_db_persistant_execute(db, sql, 1000);
-	snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires < %ld", (long) now);
-	switch_core_db_persistant_execute(db, sql, 1000);
+	switch_mutex_lock(profile->ireg_mutex);
+	sofia_glue_execute_sql_callback(profile,
+									SWITCH_TRUE,
+									NULL,
+									sql,
+									sofia_reg_del_callback,
+									NULL);
+	
+	snprintf(sql, sizeof(sql), "delete from sip_registrations where expires > 0 and expires <= %ld", (long) now);
+	sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
+	snprintf(sql, sizeof(sql), "delete from sip_authentication where expires > 0 and expires <= %ld", (long) now);
+	sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
+	snprintf(sql, sizeof(sql), "delete from sip_subscriptions where expires > 0 and expires <= %ld", (long) now);
+	sofia_glue_execute_sql(profile, SWITCH_TRUE, sql, NULL);
 
 	switch_mutex_unlock(profile->ireg_mutex);
 
 }
 
-char *sofia_reg_find_reg_url(sofia_profile_t * profile, const char *user, const char *host, char *val, switch_size_t len)
+char *sofia_reg_find_reg_url(sofia_profile_t *profile, const char *user, const char *host, char *val, switch_size_t len)
 {
-	char *errmsg;
 	struct callback_t cbt = { 0 };
-	switch_core_db_t *db;
 
 	if (!user) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Called with null user!\n");
 		return NULL;
 	}
 
-	if (!(db = switch_core_db_open_file(profile->dbname))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", profile->dbname);
-		return NULL;
-	}
-
 	cbt.val = val;
 	cbt.len = len;
-	switch_mutex_lock(profile->ireg_mutex);
+
 	if (host) {
 		snprintf(val, len, "select contact from sip_registrations where user='%s' and host='%s'", user, host);
 	} else {
 		snprintf(val, len, "select contact from sip_registrations where user='%s'", user);
 	}
 
-	switch_core_db_exec(db, val, sofia_reg_find_callback, &cbt, &errmsg);
 
-	if (errmsg) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "SQL ERR [%s][%s]\n", val, errmsg);
-		switch_safe_free(errmsg);
-		errmsg = NULL;
-	}
+	sofia_glue_execute_sql_callback(profile,
+									SWITCH_FALSE,
+									profile->ireg_mutex,
+									val,
+									sofia_reg_find_callback,
+									&cbt);
 
-	switch_mutex_unlock(profile->ireg_mutex);
 
-	switch_core_db_close(db);
 	if (cbt.matches) {
 		return val;
 	} else {
@@ -207,73 +208,20 @@
 	}
 }
 
-char *sofia_reg_get_auth_data(char *dbname, char *nonce, char *npassword, size_t len, switch_mutex_t * mutex)
+static char *sofia_reg_get_auth_data(sofia_profile_t *profile, char *nonce, char *npassword, size_t len, switch_mutex_t *mutex)
 {
-	switch_core_db_t *db;
-	switch_core_db_stmt_t *stmt;
-	char *sql = NULL, *ret = NULL;
-
-	if (mutex) {
-		switch_mutex_lock(mutex);
-	}
-
-	if (!dbname) {
-		goto end;
-	}
-
-	if (!(db = switch_core_db_open_file(dbname))) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Opening DB %s\n", dbname);
-		goto end;
-	}
-
+	char *sql, *ret;
+	
 	sql = switch_mprintf("select passwd from sip_authentication where nonce='%q'", nonce);
-	if (switch_core_db_prepare(db, sql, -1, &stmt, 0)) {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Statement Error!\n");
-		goto fail;
-	} else {
-		int running = 1;
-		int colcount;
+	assert(sql != NULL);
 
-		while (running < 5000) {
-			int result = switch_core_db_step(stmt);
-
-			if (result == SWITCH_CORE_DB_ROW) {
-				if ((colcount = switch_core_db_column_count(stmt))) {
-					switch_copy_string(npassword, (char *) switch_core_db_column_text(stmt, 0), len);
-					ret = npassword;
-				}
-				break;
-			} else if (result == SWITCH_CORE_DB_BUSY) {
-				running++;
-				switch_yield(1000);
-				continue;
-			}
-			break;
-		}
-
-		switch_core_db_finalize(stmt);
-	}
-
-
-  fail:
-
-	switch_core_db_close(db);
-
-  end:
-	if (mutex) {
-		switch_mutex_unlock(mutex);
-	}
-
-	if (sql) {
-		switch_safe_free(sql);
-	}
+	ret = sofia_glue_execute_sql2str(profile, mutex, sql, npassword, len);
 
+	free(sql);
 	return ret;
 }
 
-
-
-uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_handle_t * nh, sip_t const *sip, sofia_regtype_t regtype, char *key,
+uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, sip_t const *sip, sofia_regtype_t regtype, char *key,
 							   uint32_t keylen)
 {
 	sip_from_t const *from = NULL;
@@ -433,9 +381,18 @@
 				a1_hash = hexdigest;
 			}
 
-			sql = switch_mprintf("delete from sip_authentication where user='%q' and host='%q';\n"
-								 "insert into sip_authentication values('%q','%q','%q','%q', %ld)",
-								 from_user, from_host, from_user, from_host, a1_hash, uuid_str, time(NULL) + profile->nonce_ttl);
+			switch_mutex_lock(profile->ireg_mutex);
+			sql = switch_mprintf("delete from sip_authentication where user='%q' and host='%q';", from_user, from_host);
+			assert(sql != NULL);
+			sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL);
+			switch_safe_free(sql);
+			sql = switch_mprintf("insert into sip_authentication values('%q','%q','%q','%q', %ld)",
+								 from_user, from_host, a1_hash, uuid_str, time(NULL) + profile->nonce_ttl);
+			assert(sql != NULL);
+			sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, NULL);
+			switch_safe_free(sql);
+			switch_mutex_unlock(profile->ireg_mutex);
+
 			auth_str =
 				switch_mprintf("Digest realm=\"%q\", nonce=\"%q\",%s algorithm=MD5, qop=\"auth\"", from_host, uuid_str, stale ? " stale=\"true\"," : "");
 
@@ -448,8 +405,6 @@
 
 			}
 
-			sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
-			switch_safe_free(sql);
 			switch_safe_free(auth_str);
 			ret = 1;
 		} else {
@@ -488,7 +443,7 @@
 		}
 
 		if (sql) {
-			sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
+			sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex);
 			switch_safe_free(sql);
 			sql = NULL;
 		}
@@ -509,7 +464,7 @@
 		}
 	} else {
 		if ((sql = switch_mprintf("delete from sip_subscriptions where user='%q' and host='%q'", from_user, from_host))) {
-			sofia_glue_execute_sql(profile->dbname, sql, profile->ireg_mutex);
+			sofia_glue_execute_sql(profile, SWITCH_FALSE, sql, profile->ireg_mutex);
 			switch_safe_free(sql);
 			sql = NULL;
 		}
@@ -542,7 +497,7 @@
 
 
 
-void sofia_reg_handle_sip_i_register(nua_t * nua, sofia_profile_t * profile, nua_handle_t * nh, sofia_private_t * sofia_private, sip_t const *sip, tagi_t tags[])
+void sofia_reg_handle_sip_i_register(nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, sofia_private_t * sofia_private, sip_t const *sip, tagi_t tags[])
 {
 	char key[128] = "";
 
@@ -564,7 +519,7 @@
 
 void sofia_reg_handle_sip_r_register(int status,
 						   char const *phrase,
-						   nua_t * nua, sofia_profile_t * profile, nua_handle_t * nh, sofia_private_t * sofia_private, sip_t const *sip, tagi_t tags[])
+						   nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, sofia_private_t * sofia_private, sip_t const *sip, tagi_t tags[])
 {
 	if (sofia_private && sofia_private->gateway) {
 		switch (status) {
@@ -594,7 +549,7 @@
 
 void sofia_reg_handle_sip_r_challenge(int status,
 							char const *phrase,
-							nua_t * nua, sofia_profile_t * profile, nua_handle_t * nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
+							nua_t * nua, sofia_profile_t *profile, nua_handle_t * nh, switch_core_session_t *session, sip_t const *sip, tagi_t tags[])
 {
 	outbound_reg_t *gateway = NULL;
 	sip_www_authenticate_t const *authenticate = NULL;
@@ -698,7 +653,7 @@
 
 }
 
-auth_res_t parse_auth(sofia_profile_t * profile, sip_authorization_t const *authorization, const char *regstr, char *np, size_t nplen)
+auth_res_t parse_auth(sofia_profile_t *profile, sip_authorization_t const *authorization, const char *regstr, char *np, size_t nplen)
 {
 	int indexnum;
 	const char *cur;
@@ -758,7 +713,7 @@
 	}
 
 	if (switch_strlen_zero(np)) {
-		if (!sofia_reg_get_auth_data(profile->dbname, nonce, np, nplen, profile->ireg_mutex)) {
+		if (!sofia_reg_get_auth_data(profile, nonce, np, nplen, profile->ireg_mutex)) {
 			ret = AUTH_STALE;
 			goto end;
 		}

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Tue Apr  3 23:08:17 2007
@@ -2761,16 +2761,19 @@
 	char *account = switch_event_get_header(event, "message-account");
 
 	if (account) {
-		char *text;
+		char *path, *cmd;
 
-		text = switch_mprintf("%s%smwi.js", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR);
-		assert(text != NULL);
+		path  = switch_mprintf("%s%smwi.js", SWITCH_GLOBAL_dirs.script_dir, SWITCH_PATH_SEPARATOR);
+		assert(path != NULL);
 
-		if (switch_file_exists(text) == SWITCH_STATUS_SUCCESS) {
-			js_thread_launch(text);
+		if (switch_file_exists(path) == SWITCH_STATUS_SUCCESS) {
+			cmd = switch_mprintf("%s %s", path, account);
+			assert(cmd != NULL);
+			js_thread_launch(cmd);
+			switch_safe_free(cmd);
 		}
 
-		free(text);
+		switch_safe_free(path);
 	}
 
 }

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/Makefile
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/Makefile	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/Makefile	Tue Apr  3 23:08:17 2007
@@ -1,28 +1,4 @@
 switch_srcdir=../../../..
 
-ODBC=unixODBC-2.2.12
-ODBC_DIR=$(switch_srcdir)/libs/$(ODBC)
-ODBCLA=libodbc.la
-
-UNINST_ODBCLA=$(ODBC_DIR)/DriverManager/$(ODBCLA)
-INST_ODBCLA=$(DESTDIR)$(PREFIX)/lib/$(ODBCLA)
-
-LOCAL_CFLAGS=-I$(ODBC_DIR)/include
-LOCAL_LDFLAGS=
-LOCAL_LIBADD=$(UNINST_ODBCLA)
-
 include ../mod_spidermonkey/sm.mak
 
-$(ODBC_DIR):
-	$(GETLIB) $(ODBC).tar.gz
-	cd $(ODBC_DIR) && ./configure --prefix=$(PREFIX) --disable-gui --without-x --with-pic 
-
-$(UNINST_ODBCLA): $(ODBC_DIR)
-	cd $(ODBC_DIR) && $(MAKE)
-	$(TOUCH_TARGET)
-
-depend_install: $(INST_ODBCLA)
-
-$(INST_ODBCLA): $(UNINST_ODBCLA)
-	cd $(ODBC_DIR) && $(MAKE) install
-	@$(TOUCH_TARGET)

Modified: freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/mod_spidermonkey_odbc.c
==============================================================================
--- freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/mod_spidermonkey_odbc.c	(original)
+++ freeswitch/trunk/src/mod/languages/mod_spidermonkey_odbc/mod_spidermonkey_odbc.c	Tue Apr  3 23:08:17 2007
@@ -30,48 +30,19 @@
  *
  */
 #include "mod_spidermonkey.h"
-
-
-#include <sql.h>
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable:4201)
-#include <sqlext.h>
-#pragma warning(pop)
-#else
-#include <sqlext.h>
-#endif
-#include <sqltypes.h>
+#include <switch_odbc.h>
 
 static const char modname[] = "ODBC";
 
 struct odbc_obj {
-	char *dsn;
-	char *username;
-	char *password;
-	SQLHENV env;
-	SQLHDBC con;
+	switch_odbc_handle_t *handle;
 	SQLHSTMT stmt;
-	uint32_t state;
 	SQLCHAR *colbuf;
 	int32 cblen;
 	SQLCHAR *code;
 	int32 codelen;
 };
-
-typedef enum {
-	ODBC_STATE_INIT,
-	ODBC_STATE_DOWN,
-	ODBC_STATE_CONNECTED,
-	ODBC_STATE_ERROR
-} odbc_state_t;
-typedef struct odbc_obj odbc_obj_t;
-
-typedef enum {
-	ODBC_SUCCESS = 0,
-	ODBC_FAIL = -1
-} odbc_status_t;
-
+typedef struct odbc_obj  odbc_obj_t;
 
 static odbc_obj_t *new_odbc_obj(char *dsn, char *username, char *password)
 {
@@ -81,122 +52,39 @@
 		goto err;
 	}
 
-	if (!(new_obj->dsn = strdup(dsn))) {
+	if (!(new_obj->handle = switch_odbc_handle_new(dsn, username, password))) {
 		goto err;
 	}
-
-	if (!(new_obj->username = strdup(username))) {
-		goto err;
-	}
-
-	if (!(new_obj->password = strdup(password))) {
-		goto err;
-	}
-
-	new_obj->env = SQL_NULL_HANDLE;
-	new_obj->state = ODBC_STATE_INIT;
-
+	
 	return new_obj;
 
   err:
 	if (new_obj) {
-		switch_safe_free(new_obj->dsn);
-		switch_safe_free(new_obj->username);
-		switch_safe_free(new_obj->password);
+		if (new_obj->handle) {
+			switch_odbc_handle_destroy(&new_obj->handle);
+		}
 		switch_safe_free(new_obj);
 	}
 
 	return NULL;
 }
 
-odbc_status_t odbc_obj_disconnect(odbc_obj_t * obj)
+switch_odbc_status_t odbc_obj_connect(odbc_obj_t *obj)
 {
-	int result;
-
-	if (obj->state == ODBC_STATE_CONNECTED) {
-		result = SQLDisconnect(obj->con);
-		if (result == ODBC_SUCCESS) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected %d from [%s]\n", result, obj->dsn);
-		} else {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Disconnectiong [%s]\n", obj->dsn);
-		}
-	} else {
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "[%s] already disconnected\n", obj->dsn);
-	}
-
-	obj->state = ODBC_STATE_DOWN;
-
-	return ODBC_SUCCESS;
-}
-
-odbc_status_t odbc_obj_connect(odbc_obj_t * obj)
-{
-	int result;
-	SQLINTEGER err;
-	int16_t mlen;
-	unsigned char msg[200], stat[10];
-
-	if (obj->env == SQL_NULL_HANDLE) {
-		result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &obj->env);
-
-		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error AllocHandle\n");
-			return ODBC_FAIL;
-		}
-
-		result = SQLSetEnvAttr(obj->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
-
-		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error SetEnv\n");
-			SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
-			return ODBC_FAIL;
-		}
-
-		result = SQLAllocHandle(SQL_HANDLE_DBC, obj->env, &obj->con);
-
-		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
-			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error AllocHDB %d\n", result);
-			SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
-			return ODBC_FAIL;
-		}
-		SQLSetConnectAttr(obj->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
-	}
-	if (obj->state == ODBC_STATE_CONNECTED) {
-		odbc_obj_disconnect(obj);
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-connecting %s\n", obj->dsn);
-	}
-
-	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connecting %s\n", obj->dsn);
-
-	result = SQLConnect(obj->con, (SQLCHAR *) obj->dsn, SQL_NTS, (SQLCHAR *) obj->username, SQL_NTS, (SQLCHAR *) obj->password, SQL_NTS);
-
-	if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
-		SQLGetDiagRec(SQL_HANDLE_DBC, obj->con, 1, stat, &err, msg, 100, &mlen);
-		SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg);
-		return ODBC_FAIL;
-	} else {
-
-		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to [%s]\n", obj->dsn);
-		obj->state = ODBC_STATE_CONNECTED;
-	}
-
-	return ODBC_SUCCESS;
+	
+	return switch_odbc_handle_connect(obj->handle);
 }
 
 static void destroy_odbc_obj(odbc_obj_t ** objp)
 {
 	odbc_obj_t *obj = *objp;
 
-	odbc_obj_disconnect(obj);
-
-	SQLFreeHandle(SQL_HANDLE_STMT, obj->stmt);
-	SQLFreeHandle(SQL_HANDLE_DBC, obj->con);
-	SQLFreeHandle(SQL_HANDLE_ENV, obj->env);
-
-	switch_safe_free(obj->dsn);
-	switch_safe_free(obj->username);
-	switch_safe_free(obj->password);
+	if (obj->handle) {
+		switch_odbc_handle_destroy(&obj->handle);
+	}
+	if (obj->stmt) {
+		SQLFreeHandle(SQL_HANDLE_STMT, obj->stmt);
+	}
 	switch_safe_free(obj->colbuf);
 	switch_safe_free(obj->code);
 	switch_safe_free(obj);
@@ -205,7 +93,7 @@
 
 /* ODBC Object */
 /*********************************************************************************/
-static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 	odbc_obj_t *odbc_obj = NULL;
 	char *dsn, *username, *password;
@@ -228,7 +116,15 @@
 		}
 	}
 
-	if (dsn && username && password) {
+	if (switch_strlen_zero(username)) {
+		username = NULL;
+	}
+
+	if (switch_strlen_zero(password)) {
+		password = NULL;
+	}
+
+	if (dsn) {
 		odbc_obj = new_odbc_obj(dsn, username, password);
 	}
 
@@ -266,13 +162,13 @@
 	}
 }
 
-static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 	odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
 	JSBool tf = JS_TRUE;
 
 	if (odbc_obj) {
-		if (odbc_obj_connect(odbc_obj) == ODBC_SUCCESS) {
+		if (odbc_obj_connect(odbc_obj) == SWITCH_ODBC_SUCCESS) {
 			tf = JS_TRUE;
 		} else {
 			tf = JS_FALSE;
@@ -284,18 +180,18 @@
 	return JS_TRUE;
 }
 
-static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 	odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
 	char *sql;
 	JSBool tf = JS_FALSE;
-	int result;
 
 	if (argc < 1) {
 		goto done;
 	}
 
-	if (odbc_obj->state != ODBC_STATE_CONNECTED) {
+	if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
 		goto done;
 	}
 
@@ -306,17 +202,8 @@
 
 	sql = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
 
-	if (SQLAllocHandle(SQL_HANDLE_STMT, odbc_obj->con, &odbc_obj->stmt) != SQL_SUCCESS) {
-		goto done;
-	}
-
-	if (SQLPrepare(odbc_obj->stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
-		goto done;
-	}
-
-	result = SQLExecute(odbc_obj->stmt);
 
-	if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
+	if (switch_odbc_handle_exec(odbc_obj->handle, sql, &odbc_obj->stmt) != SWITCH_ODBC_SUCCESS) {
 		goto done;
 	}
 
@@ -329,13 +216,14 @@
 	return JS_TRUE;
 }
 
-static JSBool odbc_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 	odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
 
 	SQLSMALLINT rows = 0;
 
-	if (odbc_obj->state != ODBC_STATE_CONNECTED) {
+	if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
 		goto done;
 	}
 
@@ -352,15 +240,17 @@
 }
 
 
-static JSBool odbc_next_row(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_next_row(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 	odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
 	int result = 0;
 	JSBool tf = JS_FALSE;
 
-	if (odbc_obj->state != ODBC_STATE_CONNECTED) {
-		goto done;
-	}
+	if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
+        goto done;
+    }
+
 
 	if (odbc_obj->stmt) {
 		if ((result = SQLFetch(odbc_obj->stmt) == SQL_SUCCESS)) {
@@ -412,19 +302,20 @@
 }
 
 
-static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval * argv, jsval * rval)
+static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *argv, jsval *rval)
 {
 
 	odbc_obj_t *odbc_obj = (odbc_obj_t *) JS_GetPrivate(cx, obj);
 	JSBool tf = JS_FALSE;
 
-	if (odbc_obj->state != ODBC_STATE_CONNECTED) {
-		goto done;
-	}
+	if (switch_odbc_handle_get_state(odbc_obj->handle) != SWITCH_ODBC_STATE_CONNECTED) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Database is not connected!\n");
+        goto done;
+    }
 
 	if (odbc_obj->stmt) {
 		SQLSMALLINT c = 0, x = 0;
-		int result;
+		SQLINTEGER m = 0;
 		char code[66560];
 
 		snprintf(code, sizeof(code), "~var _oDbC_dB_RoW_DaTa_ = {}");
@@ -433,15 +324,16 @@
 			return JS_TRUE;
 		}
 
-		result = SQLNumResultCols(odbc_obj->stmt, &c);
-		if (result == SQL_SUCCESS || result == SQL_SUCCESS_WITH_INFO) {
+		SQLNumResultCols(odbc_obj->stmt, &c);
+		SQLRowCount(odbc_obj->stmt, &m);
+		if (m > 0) {
 			for (x = 1; x <= c; x++) {
 				SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
 				SQLUINTEGER ColumnSize;
 				SQLCHAR name[1024] = "";
 				SQLCHAR *data = odbc_obj->colbuf;
 				SQLCHAR *esc = NULL;
-
+				
 				SQLDescribeCol(odbc_obj->stmt, x, name, sizeof(name), &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
 				SQLGetData(odbc_obj->stmt, x, SQL_C_CHAR, odbc_obj->colbuf, odbc_obj->cblen, NULL);
 

Added: freeswitch/trunk/src/switch_odbc.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/switch_odbc.c	Tue Apr  3 23:08:17 2007
@@ -0,0 +1,407 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * switch_odbc.c -- ODBC
+ *
+ */
+#include <switch_odbc.h>
+
+struct switch_odbc_handle {
+	char *dsn;
+	char *username;
+	char *password;
+	SQLHENV env;
+	SQLHDBC con;
+	switch_odbc_state_t state;
+};
+
+
+SWITCH_DECLARE(switch_odbc_handle_t *) switch_odbc_handle_new(char *dsn, char *username, char *password)
+{
+	switch_odbc_handle_t *new_handle;
+
+	if (!(new_handle = malloc(sizeof(*new_handle)))) {
+		goto err;
+	}
+	
+	memset(new_handle, 0, sizeof(*new_handle));
+
+	if (!(new_handle->dsn = strdup(dsn))) {
+		goto err;
+	}
+
+	if (username) {
+		if (!(new_handle->username = strdup(username))) {
+			goto err;
+		}
+	}
+
+	if (password) {
+		if (!(new_handle->password = strdup(password))) {
+			goto err;
+		}
+	}
+
+	new_handle->env = SQL_NULL_HANDLE;
+	new_handle->state = SWITCH_ODBC_STATE_INIT;
+
+	return new_handle;
+
+  err:
+	if (new_handle) {
+		switch_safe_free(new_handle->dsn);
+		switch_safe_free(new_handle->username);
+		switch_safe_free(new_handle->password);
+		switch_safe_free(new_handle);
+	}
+
+	return NULL;
+}
+
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_disconnect(switch_odbc_handle_t *handle)
+{
+	int result;
+
+	if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
+		result = SQLDisconnect(handle->con);
+		if (result == SWITCH_ODBC_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Disconnected %d from [%s]\n", result, handle->dsn);
+		} else {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error Disconnectiong [%s]\n", handle->dsn);
+		}
+	} 
+	//else {
+	//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "[%s] already disconnected\n", handle->dsn);
+	//}
+
+	handle->state = SWITCH_ODBC_STATE_DOWN;
+
+	return SWITCH_ODBC_SUCCESS;
+}
+
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_connect(switch_odbc_handle_t *handle)
+{
+	int result;
+	SQLINTEGER err;
+	int16_t mlen;
+	unsigned char msg[200], stat[10];
+
+	if (handle->env == SQL_NULL_HANDLE) {
+		result = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &handle->env);
+
+		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error AllocHandle\n");
+			return SWITCH_ODBC_FAIL;
+		}
+
+		result = SQLSetEnvAttr(handle->env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
+
+		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error SetEnv\n");
+			SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+			return SWITCH_ODBC_FAIL;
+		}
+
+		result = SQLAllocHandle(SQL_HANDLE_DBC, handle->env, &handle->con);
+
+		if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error AllocHDB %d\n", result);
+			SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+			return SWITCH_ODBC_FAIL;
+		}
+		SQLSetConnectAttr(handle->con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *) 10, 0);
+	}
+	if (handle->state == SWITCH_ODBC_STATE_CONNECTED) {
+		switch_odbc_handle_disconnect(handle);
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Re-connecting %s\n", handle->dsn);
+	}
+
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connecting %s\n", handle->dsn);
+	
+	result = SQLConnect(handle->con, (SQLCHAR *) handle->dsn, SQL_NTS, (SQLCHAR *) handle->username, SQL_NTS, (SQLCHAR *) handle->password, SQL_NTS);
+	
+	if ((result != SQL_SUCCESS) && (result != SQL_SUCCESS_WITH_INFO)) {
+		char *err_str;
+		if ((err_str = switch_odbc_handle_get_error(handle, NULL))) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n",err_str);
+			free(err_str);
+		} else {
+			SQLGetDiagRec(SQL_HANDLE_DBC, handle->con, 1, stat, &err, msg, 100, &mlen);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error SQLConnect=%d errno=%d %s\n", result, (int) err, msg);
+		}
+		SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+		return SWITCH_ODBC_FAIL;
+	} else {
+
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to [%s]\n", handle->dsn);
+		handle->state = SWITCH_ODBC_STATE_CONNECTED;
+		return SWITCH_ODBC_SUCCESS;
+	}
+
+	return SWITCH_ODBC_FAIL;
+}
+
+static int db_is_up(switch_odbc_handle_t *handle)
+{
+	int ret = 0;
+	SQLHSTMT stmt;
+	SQLINTEGER m = 0;
+	int result;
+	switch_event_t *event;
+	switch_odbc_status_t recon;
+	char *err_str = NULL;
+	SQLCHAR sql[] = "select 1";
+
+    if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
+        goto error;
+    }
+	
+    if (SQLPrepare(stmt, sql, SQL_NTS) != SQL_SUCCESS) {
+        goto error;
+    }
+	
+    result = SQLExecute(stmt);
+
+	SQLRowCount(stmt, &m);
+	ret = (int) m;
+
+	goto done;
+
+ error:
+	
+	recon = switch_odbc_handle_connect(handle);
+	err_str = switch_odbc_handle_get_error(handle, stmt);
+
+	if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
+		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Failure-Message", "The sql server is not responding for DSN %s [%s]", 
+								switch_str_nil(handle->dsn), switch_str_nil(err_str));
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The sql server is not responding for DSN %s [%s]\n",
+						  switch_str_nil(handle->dsn), switch_str_nil(err_str));
+
+		if (recon == SWITCH_ODBC_SUCCESS) {
+			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection has been re-established");
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "The connection has been re-established\n");
+		} else {
+			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Additional-Info", "The connection could not be re-established");
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "The connection could not be re-established\n");
+		}
+		switch_event_fire(&event);
+	}
+	
+ done:
+
+	switch_safe_free(err_str);
+
+	if (stmt) {
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+	}
+
+	return ret;
+	
+}
+
+
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_exec(switch_odbc_handle_t *handle, char *sql, SQLHSTMT *rstmt)
+{
+	SQLHSTMT stmt;
+	int result;
+
+	if (!db_is_up(handle)) {
+		goto error;
+	}
+	
+	if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
+		goto error;
+	}
+
+	if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
+		goto error;
+	}
+
+	result = SQLExecute(stmt);
+
+	if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
+		goto error;
+	}
+
+	if (rstmt) {
+		*rstmt = stmt;
+	} else {
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+	}
+
+	return SWITCH_ODBC_SUCCESS;
+
+ error:
+	if (rstmt) {
+        *rstmt = stmt;
+    } else if (stmt) {
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+	}
+	return SWITCH_ODBC_FAIL;
+	
+}
+
+
+SWITCH_DECLARE(switch_odbc_status_t) switch_odbc_handle_callback_exec(switch_odbc_handle_t *handle,
+																	  char *sql, switch_core_db_callback_func_t callback, void *pdata)
+{
+	SQLHSTMT stmt;
+	SQLSMALLINT c = 0, x = 0;
+	SQLINTEGER m = 0;
+	int result;
+
+	assert(callback != NULL);
+
+	if (!db_is_up(handle)) {
+		goto error;
+	}
+
+	if (SQLAllocHandle(SQL_HANDLE_STMT, handle->con, &stmt) != SQL_SUCCESS) {
+		goto error;
+	}
+
+	if (SQLPrepare(stmt, (unsigned char *) sql, SQL_NTS) != SQL_SUCCESS) {
+		goto error;
+	}
+
+	result = SQLExecute(stmt);
+
+	if (result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO) {
+		goto error;
+	}
+
+
+	SQLNumResultCols(stmt, &c);
+	SQLRowCount(stmt, &m);
+
+	if (m > 0) {
+		int name_len = 256;
+		char **names;
+		char **vals;
+		int y = 0;
+		
+		if (!(result = SQLFetch(stmt)) == SQL_SUCCESS) {
+			goto error;
+		}
+		
+		names = calloc(c, sizeof(*names));
+		vals = calloc(c, sizeof(*names));
+		
+		assert(names && vals);
+		
+		for (x = 1; x <= c; x++) {
+			SQLSMALLINT NameLength, DataType, DecimalDigits, Nullable;
+			SQLUINTEGER ColumnSize;
+			names[y] = malloc(name_len);
+			memset(names[y], 0, name_len);
+
+			SQLDescribeCol(stmt, x, (SQLCHAR *) names[y], name_len, &NameLength, &DataType, &ColumnSize, &DecimalDigits, &Nullable);
+			ColumnSize++;
+
+			vals[y] = malloc(ColumnSize);
+			memset(vals[y], 0, ColumnSize);
+			SQLGetData(stmt, x, SQL_C_CHAR, (SQLCHAR *) vals[y], ColumnSize, NULL);
+			y++;
+		}
+		
+		callback(pdata, y, vals, names);
+
+		for (x = 0; x < y; x++) {
+			free(names[x]);
+			free(vals[x]);
+		}
+		free(names);
+		free(vals);
+	}
+
+	SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+
+	return SWITCH_ODBC_SUCCESS;
+
+  error:
+
+	if (stmt) {
+		SQLFreeHandle(SQL_HANDLE_STMT, stmt);
+	}
+
+	return SWITCH_ODBC_FAIL;
+
+}
+
+
+SWITCH_DECLARE(void) switch_odbc_handle_destroy(switch_odbc_handle_t **handlep)
+{
+	switch_odbc_handle_t *handle = NULL;
+
+	if (handlep) {
+		handle = *handlep;
+	}
+
+	if (handle) {
+		switch_odbc_handle_disconnect(handle);
+
+		SQLFreeHandle(SQL_HANDLE_DBC, handle->con);
+		SQLFreeHandle(SQL_HANDLE_ENV, handle->env);
+		switch_safe_free(handle->dsn);
+		switch_safe_free(handle->username);
+		switch_safe_free(handle->password);
+		free(handle);
+	}
+}
+
+SWITCH_DECLARE(switch_odbc_state_t) switch_odbc_handle_get_state(switch_odbc_handle_t *handle)
+{
+	return handle ? handle->state : SWITCH_ODBC_STATE_INIT;
+}
+
+SWITCH_DECLARE(char *) switch_odbc_handle_get_error(switch_odbc_handle_t *handle, SQLHSTMT stmt)
+{
+	char buffer[SQL_MAX_MESSAGE_LENGTH + 1];
+	char sqlstate[SQL_SQLSTATE_SIZE + 1];
+	SQLINTEGER sqlcode;
+	SQLSMALLINT length;
+	char *ret = NULL;
+
+	if (SQLError(handle->env, handle->con, stmt, (SQLCHAR *)sqlstate, &sqlcode, (SQLCHAR *)buffer, sizeof(buffer), &length) == SQL_SUCCESS) {
+		ret = switch_mprintf("STATE: %s CODE %ld ERROR: %s\n", switch_str_nil(sqlstate),  sqlcode,  switch_str_nil(buffer));
+	};
+
+	return ret;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */



More information about the Freeswitch-svn mailing list