diff options
Diffstat (limited to 'cdr')
-rwxr-xr-x | cdr/cdr_csv.c | 8 | ||||
-rwxr-xr-x | cdr/cdr_odbc.c | 253 | ||||
-rwxr-xr-x | cdr/cdr_pgsql.c | 40 | ||||
-rwxr-xr-x | cdr/cdr_tds.c | 255 |
4 files changed, 281 insertions, 275 deletions
diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c index a1d391cfb..bd18a7775 100755 --- a/cdr/cdr_csv.c +++ b/cdr/cdr_csv.c @@ -33,6 +33,7 @@ #include <stdio.h> #include <string.h> +#include <errno.h> #include <stdlib.h> #include <unistd.h> @@ -184,7 +185,7 @@ static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr) static int writefile(char *s, char *acc) { - char tmp[256]; + char tmp[AST_CONFIG_MAX_PATH]; FILE *f; if (strchr(acc, '/') || (acc[0] == '.')) { ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n", acc); @@ -195,6 +196,7 @@ static int writefile(char *s, char *acc) if (!f) return -1; fputs(s, f); + fflush(f); fclose(f); return 0; } @@ -217,7 +219,7 @@ static int csv_log(struct ast_cdr *cdr) we open write and close the log file each time */ mf = fopen(csvmaster, "a"); if (!mf) { - ast_log(LOG_ERROR, "Unable to re-open master file %s\n", csvmaster); + ast_log(LOG_ERROR, "Unable to re-open master file %s : %s\n", csvmaster, strerror(errno)); } if (mf) { fputs(buf, mf); @@ -227,7 +229,7 @@ static int csv_log(struct ast_cdr *cdr) } if (!ast_strlen_zero(cdr->accountcode)) { if (writefile(buf, cdr->accountcode)) - ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s'\n", cdr->accountcode); + ast_log(LOG_WARNING, "Unable to write CSV record to account file '%s' : %s\n", cdr->accountcode, strerror(errno)); } } return 0; diff --git a/cdr/cdr_odbc.c b/cdr/cdr_odbc.c index e52730f2e..80bd97334 100755 --- a/cdr/cdr_odbc.c +++ b/cdr/cdr_odbc.c @@ -3,13 +3,12 @@ * * ODBC CDR Backend * + * Copyright (C) 2003-2005, Digium, Inc. + * * Brian K. West <brian@bkw.org> * * This program is free software, distributed under the terms of - * the GNU General Public License. - * - * Copyright (c) 2003 Digium, Inc. - * + * the GNU General Public License */ #include <sys/types.h> @@ -37,8 +36,9 @@ static char *desc = "ODBC CDR Backend"; static char *name = "ODBC"; static char *config = "cdr_odbc.conf"; -static char *dsn = NULL, *username = NULL, *password = NULL, *loguniqueid = NULL; -static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0, loguniqueid_alloc = 0; +static char *dsn = NULL, *username = NULL, *password = NULL; +static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0; +static int loguniqueid = 0; static int connected = 0; AST_MUTEX_DEFINE_STATIC(odbc_lock); @@ -65,38 +65,31 @@ static int odbc_log(struct ast_cdr *cdr) ast_mutex_lock(&odbc_lock); strftime(timestr, sizeof(timestr), DATE_FORMAT, &tm); memset(sqlcmd,0,2048); - if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0))) - { + if (loguniqueid) { snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr " "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp," "lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); - } - else - { + } else { snprintf(sqlcmd,sizeof(sqlcmd),"INSERT INTO cdr " "(calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata," "duration,billsec,disposition,amaflags,accountcode) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); } - if(!connected) - { - res = odbc_init(); - if(res < 0) - { + if (!connected) { + res = odbc_init(); + if (res < 0) { connected = 0; ast_mutex_unlock(&odbc_lock); return 0; } - } ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt); - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Failure in AllocStatement %d\n", ODBC_res); SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen); SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt); @@ -111,9 +104,8 @@ static int odbc_log(struct ast_cdr *cdr) ODBC_res = SQLPrepare(ODBC_stmt, sqlcmd, SQL_NTS); - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in PREPARE %d\n", ODBC_res); SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen); SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt); @@ -137,46 +129,38 @@ static int odbc_log(struct ast_cdr *cdr) SQLBindParameter(ODBC_stmt, 13, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 0, 0, &cdr->amaflags, 0, NULL); SQLBindParameter(ODBC_stmt, 14, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->accountcode), 0, cdr->accountcode, 0, NULL); - if((loguniqueid != NULL) && ((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0))) - { + if (loguniqueid) { SQLBindParameter(ODBC_stmt, 15, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->uniqueid), 0, cdr->uniqueid, 0, NULL); SQLBindParameter(ODBC_stmt, 16, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, sizeof(cdr->userfield), 0, cdr->userfield, 0, NULL); } - if(connected) - { + if (connected) { res = odbc_do_query(); - if(res < 0) - { - if(option_verbose > 10) + if (res < 0) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n"); res = odbc_init(); - if(option_verbose > 10) + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Reconnecting to dsn %s\n", dsn); - if(res < 0) - { - if(option_verbose > 10) + if (res < 0) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: %s has gone away!\n", dsn); connected = 0; - } - else - { - if(option_verbose > 10) + } else { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Trying Query again!\n"); res = odbc_do_query(); - if(res < 0) - { - if(option_verbose > 10) + if (res < 0) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n"); } } } - } - else - { - if(option_verbose > 10) + } else { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query FAILED Call not logged!\n"); } + SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt); ast_mutex_unlock(&odbc_lock); return 0; } @@ -189,9 +173,8 @@ char *description(void) static int odbc_unload_module(void) { ast_mutex_lock(&odbc_lock); - if (connected) - { - if(option_verbose > 10) + if (connected) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Disconnecting from %s\n", dsn); SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt); SQLDisconnect(ODBC_con); @@ -199,38 +182,29 @@ static int odbc_unload_module(void) SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env); connected = 0; } - if (dsn && dsn_alloc) - { - if(option_verbose > 10) + if (dsn && dsn_alloc) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free dsn\n"); free(dsn); dsn = NULL; dsn_alloc = 0; } - if (username && username_alloc) - { - if(option_verbose > 10) + if (username && username_alloc) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free username\n"); free(username); username = NULL; username_alloc = 0; } - if (password && password_alloc) - { - if(option_verbose > 10) + if (password && password_alloc) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free password\n"); free(password); password = NULL; password_alloc = 0; } - if (loguniqueid && loguniqueid_alloc) - { - if(option_verbose > 10) - ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: free loguniqueid\n"); - free(loguniqueid); - loguniqueid = NULL; - loguniqueid_alloc = 0; - } + loguniqueid = 0; + ast_cdr_unregister(name); ast_mutex_unlock(&odbc_lock); return 0; @@ -246,8 +220,7 @@ static int odbc_load_module(void) ast_mutex_lock(&odbc_lock); cfg = ast_load(config); - if (!cfg) - { + if (!cfg) { ast_log(LOG_WARNING, "cdr_odbc: Unable to load config for ODBC CDR's: %s\n", config); goto out; } @@ -259,113 +232,85 @@ static int odbc_load_module(void) } tmp = ast_variable_retrieve(cfg,"global","dsn"); - if (tmp) - { + if (tmp) { dsn = malloc(strlen(tmp) + 1); - if (dsn != NULL) - { + if (dsn != NULL) { memset(dsn, 0, strlen(tmp) + 1); dsn_alloc = 1; strncpy(dsn, tmp, strlen(tmp)); - } - else - { + } else { ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - return -1; + res = -1; + goto out; } - } - else - { + } else { ast_log(LOG_WARNING,"cdr_odbc: dsn not specified. Assuming asteriskdb\n"); dsn = "asteriskdb"; } tmp = ast_variable_retrieve(cfg,"global","username"); - if (tmp) - { + if (tmp) { username = malloc(strlen(tmp) + 1); - if (username != NULL) - { + if (username != NULL) { memset(username, 0, strlen(tmp) + 1); username_alloc = 1; strncpy(username, tmp, strlen(tmp)); - } - else - { + } else { ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - return -1; + res = -1; + goto out; } - } - else - { + } else { ast_log(LOG_WARNING,"cdr_odbc: username not specified. Assuming root\n"); username = "root"; } tmp = ast_variable_retrieve(cfg,"global","password"); - if (tmp) - { + if (tmp) { password = malloc(strlen(tmp) + 1); - if (password != NULL) - { + if (password != NULL) { memset(password, 0, strlen(tmp) + 1); password_alloc = 1; strncpy(password, tmp, strlen(tmp)); - } - else - { + } else { ast_log(LOG_ERROR,"cdr_odbc: Out of memory error.\n"); - return -1; + res = -1; + goto out; } - } - else - { + } else { ast_log(LOG_WARNING,"cdr_odbc: database password not specified. Assuming blank\n"); password = ""; } tmp = ast_variable_retrieve(cfg,"global","loguniqueid"); - if (tmp) - { - loguniqueid = malloc(strlen(tmp) + 1); - if (loguniqueid != NULL) - { - strcpy(loguniqueid,tmp); - loguniqueid_alloc = 1; + if (tmp) { + loguniqueid = ast_true(tmp); + if (loguniqueid) { ast_log(LOG_NOTICE,"cdr_odbc: Logging uniqueid\n"); - } - else - { + } else { ast_log(LOG_ERROR,"cdr_odbc: Not logging uniqueid\n"); - loguniqueid_alloc = 1; - loguniqueid = NULL; } - } - else - { + } else { ast_log(LOG_WARNING,"cdr_odbc: Not logging uniqueid\n"); - loguniqueid = NULL; + loguniqueid = 0; } ast_destroy(cfg); - if(option_verbose > 3) - { - ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: dsn is %s\n",dsn); - ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: username is %s\n",username); - ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: password is [secret]\n"); - + if (option_verbose > 2) { + ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: dsn is %s\n",dsn); + ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: username is %s\n",username); + ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: password is [secret]\n"); } res = odbc_init(); - if(res < 0) - { + if (res < 0) { ast_log(LOG_ERROR, "cdr_odbc: Unable to connect to datasource: %s\n", dsn); - ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Unable to connect to datasource: %s\n", dsn); + if (option_verbose > 2) { + ast_verbose( VERBOSE_PREFIX_3 "cdr_odbc: Unable to connect to datasource: %s\n", dsn); + } } - res = ast_cdr_register(name, desc, odbc_log); - if (res) - { + if (res) { ast_log(LOG_ERROR, "cdr_odbc: Unable to register ODBC CDR handling\n"); } out: @@ -375,25 +320,22 @@ out: static int odbc_do_query(void) { - long int ODBC_err; + long int ODBC_err; int ODBC_res; - short int ODBC_mlen; - char ODBC_msg[200], ODBC_stat[10]; - + short int ODBC_mlen; + char ODBC_msg[200], ODBC_stat[10]; + ODBC_res = SQLExecute(ODBC_stmt); - - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error in Query %d\n", ODBC_res); SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen); SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt); connected = 0; return -1; - } - else - { - if(option_verbose > 10) + } else { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Query Successful!\n"); connected = 1; } @@ -407,13 +349,10 @@ static int odbc_init(void) int ODBC_res; char ODBC_msg[200], ODBC_stat[10]; - if ( ODBC_env == SQL_NULL_HANDLE || connected == 0 ) - { + if (ODBC_env == SQL_NULL_HANDLE || connected == 0) { ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env); - - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHandle\n"); connected = 0; return -1; @@ -421,9 +360,8 @@ static int odbc_init(void) ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0); - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SetEnv\n"); SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env); connected = 0; @@ -432,32 +370,27 @@ static int odbc_init(void) ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con); - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error AllocHDB %d\n", ODBC_res); SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env); connected = 0; return -1; } - SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0); } ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS); - if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) - { - if(option_verbose > 10) + if ((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO)) { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Error SQLConnect %d\n", ODBC_res); SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen); SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env); connected = 0; return -1; - } - else - { - if(option_verbose > 10) + } else { + if (option_verbose > 10) ast_verbose( VERBOSE_PREFIX_4 "cdr_odbc: Connected to %s\n", dsn); connected = 1; } diff --git a/cdr/cdr_pgsql.c b/cdr/cdr_pgsql.c index ccec5f9e5..90d386fdc 100755 --- a/cdr/cdr_pgsql.c +++ b/cdr/cdr_pgsql.c @@ -127,6 +127,19 @@ static int pgsql_log(struct ast_cdr *cdr) pgerror = PQresultErrorMessage(result); ast_log(LOG_ERROR,"cdr_pgsql: Failed to insert call detail record into database!\n"); ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror); + ast_log(LOG_ERROR,"cdr_pgsql: Connection may have been lost... attempting to reconnect.\n"); + PQreset(conn); + if (PQstatus(conn) == CONNECTION_OK) { + ast_log(LOG_ERROR, "cdr_pgsql: Connection reestablished.\n"); + connected = 1; + result = PQexec(conn, sqlcmd); + if ( PQresultStatus(result) != PGRES_COMMAND_OK) + { + pgerror = PQresultErrorMessage(result); + ast_log(LOG_ERROR,"cdr_pgsql: HARD ERROR! Attempted reconnection failed. DROPPING CALL RECORD!\n"); + ast_log(LOG_ERROR,"cdr_pgsql: Reason: %s\n", pgerror); + } + } ast_mutex_unlock(&pgsql_lock); return -1; } @@ -180,20 +193,13 @@ static int my_unload_module(void) return 0; } -static int my_load_module(void) +static int process_my_load_module(struct ast_config *cfg) { int res; - struct ast_config *cfg; struct ast_variable *var; char *pgerror; char *tmp; - cfg = ast_load(config); - if (!cfg) { - ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config); - return 0; - } - var = ast_variable_browse(cfg, "global"); if (!var) { /* nothing configured */ @@ -280,8 +286,6 @@ static int my_load_module(void) pgdbport = "5432"; } - ast_destroy(cfg); - ast_log(LOG_DEBUG,"cdr_pgsql: got hostname of %s\n",pghostname); ast_log(LOG_DEBUG,"cdr_pgsql: got port of %s\n",pgdbport); if (pgdbsock) @@ -296,7 +300,7 @@ static int my_load_module(void) connected = 1; } else { pgerror = PQerrorMessage(conn); - ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. Calls will not be logged!\n", pghostname); + ast_log(LOG_ERROR, "cdr_pgsql: Unable to connect to database server %s. CALLS WILL NOT BE LOGGED!!\n", pghostname); ast_log(LOG_ERROR, "cdr_pgsql: Reason: %s\n", pgerror); connected = 0; } @@ -308,6 +312,20 @@ static int my_load_module(void) return res; } +static int my_load_module(void) +{ + struct ast_config *cfg; + int res; + cfg = ast_load(config); + if (!cfg) { + ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config); + return 0; + } + res = process_my_load_module(cfg); + ast_destroy(cfg); + return res; +} + int load_module(void) { return my_load_module(); diff --git a/cdr/cdr_tds.c b/cdr/cdr_tds.c index 448c02495..5d678067c 100755 --- a/cdr/cdr_tds.c +++ b/cdr/cdr_tds.c @@ -65,6 +65,11 @@ 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; +static time_t connect_time = 0; + AST_MUTEX_DEFINE_STATIC(tds_lock); static TDSSOCKET *tds; @@ -75,11 +80,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 +173,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 +388,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_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 +521,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_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() |