diff options
Diffstat (limited to 'cdr')
-rwxr-xr-x | cdr/cdr_tds.c | 254 |
1 files changed, 153 insertions, 101 deletions
diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index 15a7be84d..c70e62eaf 100755 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -65,6 +65,10 @@ static char *desc = "MSSQL CDR Backend"; static char *name = "mssql"; static char *config = "cdr_tds.conf"; +static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL; + +static int connected = 0; + AST_MUTEX_DEFINE_STATIC(tds_lock); static TDSSOCKET *tds; @@ -75,11 +79,15 @@ static char *stristr(const char*, const char*); static char *anti_injection(const char *, int); static void get_date(char *, struct timeval); +static int mssql_connect(void); +static int mssql_disconnect(void); + static int tds_log(struct ast_cdr *cdr) { char sqlcmd[2048], start[80], answer[80], end[80]; char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid; int res = 0; + int retried = 0; #ifdef TDS_PRE_0_62 TDS_INT result_type; #endif @@ -164,16 +172,27 @@ static int tds_log(struct ast_cdr *cdr) uniqueid ); + do { + if (!connected) { + if (mssql_connect()) + ast_log(LOG_ERROR, "Failed to reconnect to SQL database.\n"); + else + ast_log(LOG_WARNING, "Reconnected to SQL database.\n"); + + retried = 1; /* note that we have now tried */ + } + #ifdef TDS_PRE_0_62 - if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) + if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) #else - if ((tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) + if (!connected || (tds_submit_query(tds, sqlcmd) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) #endif - { - ast_log(LOG_ERROR, "Failed to insert record into database.\n"); + { + ast_log(LOG_ERROR, "Failed to insert Call Data Record into SQL database.\n"); - res = -1; - } + mssql_disconnect(); /* this is ok even if we are already disconnected */ + } + } while (!connected && !retried); free(accountcode); free(src); @@ -368,32 +387,129 @@ char *description(void) return desc; } +static int mssql_disconnect(void) +{ + if (tds) { + tds_free_socket(tds); + tds = NULL; + } + + if (context) { + tds_free_context(context); + context = NULL; + } + + if (login) { + tds_free_login(login); + login = NULL; + } + + connected = 0; + + return 0; +} + +static int mssql_connect(void) +{ + TDSCONNECTINFO *connection = NULL; + char query[128]; + + /* Connect to M$SQL Server */ + if (!(login = tds_alloc_login())) + { + ast_log(LOG_ERROR, "tds_alloc_login() failed.\n"); + return -1; + } + + tds_set_server(login, hostname); + tds_set_user(login, dbuser); + tds_set_passwd(login, password); + tds_set_app(login, "TSQL"); + tds_set_library(login, "TDS-Library"); +#ifndef TDS_PRE_0_62 + tds_set_client_charset(login, charset); +#endif + tds_set_language(login, language); + tds_set_packet(login, 512); + tds_set_version(login, 7, 0); + + if (!(context = tds_alloc_context())) + { + ast_log(LOG_ERROR, "tds_alloc_context() failed.\n"); + goto connect_fail; + } + + if (!(tds = tds_alloc_socket(context, 512))) { + ast_log(LOG_ERROR, "tds_alloc_socket() failed.\n"); + goto connect_fail; + } + + tds_set_parent(tds, NULL); + connection = tds_read_config_info(tds, login, context->locale); + if (!connection) + { + ast_log(LOG_ERROR, "tds_read_config() failed.\n"); + goto connect_fail; + } + + if (tds_connect(tds, connection) == TDS_FAIL) + { + ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n"); + tds = NULL; /* freed by tds_connect() on error */ + tds_free_connect(connection); + connection = NULL; + goto connect_fail; + } + tds_free_connect(connection); + connection = NULL; + + sprintf(query, "USE %s", dbname); +#ifdef TDS_PRE_0_62 + if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) +#else + if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) +#endif + { + ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname); + goto connect_fail; + } + + connected = 1; + return 0; + +connect_fail: + mssql_disconnect(); + return -1; +} + int unload_module(void) { - tds_free_socket(tds); - tds_free_login(login); - tds_free_context(context); + mssql_disconnect(); ast_cdr_unregister(name); + if (hostname) free(hostname); + if (dbname) free(dbname); + if (dbuser) free(dbuser); + if (password) free(password); + if (charset) free(charset); + if (language) free(language); + return 0; } int load_module(void) { - TDSCONNECTINFO *connection; int res = 0; struct ast_config *cfg; struct ast_variable *var; - char query[1024], *ptr = NULL; - char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *charset = NULL, *language = NULL; + char *ptr = NULL; #ifdef TDS_PRE_0_62 TDS_INT result_type; #endif cfg = ast_config_load(config); - if (!cfg) - { + if (!cfg) { ast_log(LOG_NOTICE, "Unable to load config for MSSQL CDR's: %s\n", config); return 0; } @@ -404,133 +520,69 @@ int load_module(void) ptr = ast_variable_retrieve(cfg, "global", "hostname"); if (ptr) - { - hostname = strdupa(ptr); - } + hostname = strdup(ptr); else - { ast_log(LOG_ERROR,"Database server hostname not specified.\n"); - } ptr = ast_variable_retrieve(cfg, "global", "dbname"); if (ptr) - { - dbname = strdupa(ptr); - } + dbname = strdup(ptr); else - { ast_log(LOG_ERROR,"Database dbname not specified.\n"); - } ptr = ast_variable_retrieve(cfg, "global", "user"); if (ptr) - { - dbuser = strdupa(ptr); - } + dbuser = strdup(ptr); else - { ast_log(LOG_ERROR,"Database dbuser not specified.\n"); - } ptr = ast_variable_retrieve(cfg, "global", "password"); if (ptr) - { - password = strdupa(ptr); - } + password = strdup(ptr); else - { ast_log(LOG_ERROR,"Database password not specified.\n"); - } ptr = ast_variable_retrieve(cfg, "global", "charset"); if (ptr) - { - charset = strdupa(ptr); - } + charset = strdup(ptr); else - { - charset = strdupa("iso_1"); - } + charset = strdup("iso_1"); ptr = ast_variable_retrieve(cfg, "global", "language"); if (ptr) - { - language = strdupa(ptr); - } + language = strdup(ptr); else - { - language = strdupa("us_english"); - } + language = strdup("us_english"); ast_config_destroy(cfg); - /* Connect to M$SQL Server */ - if (!(login = tds_alloc_login())) + mssql_connect(); + + /* Register MSSQL CDR handler */ + res = ast_cdr_register(name, desc, tds_log); + if (res) { - ast_log(LOG_ERROR, "tds_alloc_login() failed.\n"); - res = -1; + ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n"); } - else - { - tds_set_server(login, hostname); - tds_set_user(login, dbuser); - tds_set_passwd(login, password); - tds_set_app(login, "TSQL"); - tds_set_library(login, "TDS-Library"); -#ifndef TDS_PRE_0_62 - tds_set_client_charset(login, charset); -#endif - tds_set_language(login, language); - tds_set_packet(login, 512); - tds_set_version(login, 7, 0); - - context = tds_alloc_context(); - tds = tds_alloc_socket(context, 512); - - tds_set_parent(tds, NULL); - connection = tds_read_config_info(NULL, login, context->locale); - if (!connection || tds_connect(tds, connection) == TDS_FAIL) - { - ast_log(LOG_ERROR, "Failed to connect to MSSQL server.\n"); - res = -1; - } - tds_free_connect(connection); - if (!res) - { - memset(query, 0, sizeof(query)); - sprintf(query, "USE %s", dbname); -#ifdef TDS_PRE_0_62 - if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds, &result_type) != TDS_SUCCEED || result_type != TDS_CMD_SUCCEED)) -#else - if ((tds_submit_query(tds, query) != TDS_SUCCEED) || (tds_process_simple_query(tds) != TDS_SUCCEED)) -#endif - { - ast_log(LOG_ERROR, "Could not change database (%s)\n", dbname); - res = -1; - } - else - { - /* Register MSSQL CDR handler */ - res = ast_cdr_register(name, desc, tds_log); - if (res) - { - ast_log(LOG_ERROR, "Unable to register MSSQL CDR handling\n"); - } - } - } - } return res; } int reload(void) { - return 0; + unload_module(); + return load_module(); } int usecount(void) { - return 0; + /* Simplistic use count */ + if (ast_mutex_trylock(&tds_lock)) { + return 1; + } else { + ast_mutex_unlock(&tds_lock); + return 0; + } } char *key() |