add core ODBC
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@4846 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
ed0cfa9f15
commit
4d62a1adb2
|
@ -103,6 +103,11 @@ CORE_CFLAGS += $(RESAMPLE_CFLAGS)
|
|||
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)
|
||||
|
|
|
@ -314,10 +314,14 @@ AC_SUBST(LIBCURL_DEPS)
|
|||
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
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@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@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@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:
|
||||
*/
|
|
@ -12,6 +12,8 @@ LOCAL_CFLAGS += -I$(SOFIAUA_DIR)/sdp -I$(SOFIAUA_DIR)/sip
|
|||
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
|
||||
|
||||
|
|
|
@ -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 @@ struct sofia_profile {
|
|||
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 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session);
|
|||
|
||||
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 @@ void sofia_presence_handle_sip_i_subscribe(int status,
|
|||
|
||||
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 @@ void sofia_presence_set_chat_hash(private_object_t * tech_pvt, sip_t const *sip)
|
|||
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);
|
||||
|
|
|
@ -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 @@ void event_handler(switch_event_t *event)
|
|||
}
|
||||
|
||||
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 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t * thread, void
|
|||
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 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t * thread, void
|
|||
}
|
||||
|
||||
|
||||
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 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t * thread, void
|
|||
|
||||
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 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t * thread, void
|
|||
|
||||
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 @@ switch_status_t config_sofia(int reload)
|
|||
|
||||
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 @@ switch_status_t config_sofia(int reload)
|
|||
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)) {
|
||||
|
|
|
@ -1119,7 +1119,91 @@ void sofia_glue_add_profile(char *key, sofia_profile_t * profile)
|
|||
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 @@ void sofia_glue_execute_sql(char *dbname, char *sql, switch_mutex_t * mutex)
|
|||
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 @@ void sofia_glue_execute_sql(char *dbname, char *sql, switch_mutex_t * mutex)
|
|||
}
|
||||
|
||||
|
||||
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;
|
||||
|
|
|
@ -105,8 +105,7 @@ switch_status_t sofia_presence_chat_send(char *proto, char *from, char *to, char
|
|||
|
||||
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 @@ void sofia_presence_cancel(void)
|
|||
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 (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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
switch_core_db_close(db);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,9 +178,7 @@ void sofia_presence_mwi_event_handler(switch_event_t *event)
|
|||
{
|
||||
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 @@ void sofia_presence_mwi_event_handler(switch_event_t *event)
|
|||
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 @@ void sofia_presence_mwi_event_handler(switch_event_t *event)
|
|||
|
||||
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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
//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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
} 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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
}
|
||||
|
||||
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 @@ void sofia_presence_event_handler(switch_event_t *event)
|
|||
}
|
||||
|
||||
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 @@ void sofia_presence_handle_sip_i_subscribe(int status,
|
|||
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 @@ void sofia_presence_handle_sip_i_subscribe(int status,
|
|||
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 @@ void sofia_presence_handle_sip_i_subscribe(int status,
|
|||
|
||||
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 @@ void sofia_presence_handle_sip_i_publish(nua_t * nua, sofia_profile_t * profile,
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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_unregister(sofia_profile_t * profile)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ int sofia_reg_del_callback(void *pArg, int argc, char **argv, char **columnNames
|
|||
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
|
||||
|
||||
snprintf(sql, sizeof(sql), "select '%s',* from sip_registrations where expires > 0 and expires <= %ld", profile->name, (long) now);
|
||||
|
||||
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), "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);
|
||||
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_find_reg_url(sofia_profile_t * profile, const char *user, const
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_ha
|
|||
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 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_ha
|
|||
|
||||
}
|
||||
|
||||
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 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_ha
|
|||
}
|
||||
|
||||
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 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_ha
|
|||
}
|
||||
} 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 @@ uint8_t sofia_reg_handle_register(nua_t * nua, sofia_profile_t * profile, nua_ha
|
|||
|
||||
|
||||
|
||||
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_i_register(nua_t * nua, sofia_profile_t * profile, nua
|
|||
|
||||
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_register(int status,
|
|||
|
||||
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 @@ void sofia_reg_handle_sip_r_challenge(int status,
|
|||
|
||||
}
|
||||
|
||||
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 @@ auth_res_t parse_auth(sofia_profile_t * profile, sip_authorization_t const *auth
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -2761,16 +2761,19 @@ static void message_query_handler(switch_event_t *event)
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 @@ static odbc_obj_t *new_odbc_obj(char *dsn, char *username, char *password)
|
|||
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 @@ static void destroy_odbc_obj(odbc_obj_t ** objp)
|
|||
|
||||
/* 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 @@ static JSBool odbc_construct(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
|||
}
|
||||
}
|
||||
|
||||
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 void odbc_destroy(JSContext * cx, JSObject * obj)
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ static JSBool odbc_connect(JSContext * cx, JSObject * obj, uintN argc, jsval * a
|
|||
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 @@ static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval * argv
|
|||
|
||||
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 @@ static JSBool odbc_exec(JSContext * cx, JSObject * obj, uintN argc, jsval * argv
|
|||
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_num_rows(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
|||
}
|
||||
|
||||
|
||||
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 char *escape_data(char *in)
|
|||
}
|
||||
|
||||
|
||||
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 @@ static JSBool odbc_get_data(JSContext * cx, JSObject * obj, uintN argc, jsval *
|
|||
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);
|
||||
|
||||
|
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
||||
* Copyright (C) 2005/2006, Anthony Minessale II <anthmct@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@yahoo.com>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@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:
|
||||
*/
|
Loading…
Reference in New Issue