Wed Apr 6 11:29:54 2011

Asterisk developer's documentation


cdr_tds.c File Reference

FreeTDS CDR logger. More...

#include "asterisk.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/cdr.h"
#include "asterisk/module.h"
#include <sqlfront.h>
#include <sybdb.h>

Go to the source code of this file.

Data Structures

struct  cdr_tds_config

Defines

#define DATE_FORMAT   "%Y/%m/%d %T"

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * anti_injection (const char *, int)
static int execute_and_consume (DBPROCESS *dbproc, const char *fmt,...)
static void get_date (char *, size_t len, struct timeval)
static int load_module (void)
static int mssql_connect (void)
static int mssql_disconnect (void)
static int reload (void)
static int tds_error_handler (DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
static int tds_load_module (int reload)
static int tds_log (struct ast_cdr *cdr)
static int tds_message_handler (DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext, char *srvname, char *procname, int line)
static int tds_unload_module (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, }
static struct ast_module_infoast_module_info = &__mod_info
static const char config [] = "cdr_tds.conf"
static const char name [] = "FreeTDS (MSSQL)"
static struct cdr_tds_configsettings
static ast_mutex_t tds_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }


Detailed Description

FreeTDS CDR logger.

See also

Definition in file cdr_tds.c.


Define Documentation

#define DATE_FORMAT   "%Y/%m/%d %T"

 *
 * Table Structure for `cdr`
 *
 * Created on: 05/20/2004 16:16
 * Last changed on: 07/27/2004 20:01

CREATE TABLE [dbo].[cdr] (
	[accountcode] [varchar] (20) NULL ,
	[src] [varchar] (80) NULL ,
	[dst] [varchar] (80) NULL ,
	[dcontext] [varchar] (80) NULL ,
	[clid] [varchar] (80) NULL ,
	[channel] [varchar] (80) NULL ,
	[dstchannel] [varchar] (80) NULL ,
	[lastapp] [varchar] (80) NULL ,
	[lastdata] [varchar] (80) NULL ,
	[start] [datetime] NULL ,
	[answer] [datetime] NULL ,
	[end] [datetime] NULL ,
	[duration] [int] NULL ,
	[billsec] [int] NULL ,
	[disposition] [varchar] (20) NULL ,
	[amaflags] [varchar] (16) NULL ,
	[uniqueid] [varchar] (32) NULL ,
	[userfield] [varchar] (256) NULL
) ON [PRIMARY]

Definition at line 76 of file cdr_tds.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 636 of file cdr_tds.c.

static void __unreg_module ( void   )  [static]

Definition at line 636 of file cdr_tds.c.

static char * anti_injection ( const char *  ,
int   
) [static]

Definition at line 303 of file cdr_tds.c.

References ast_calloc, ast_log(), LOG_ERROR, and strcasestr().

Referenced by tds_log().

00304 {
00305    /* Reference to http://www.nextgenss.com/papers/advanced_sql_injection.pdf */
00306    char *buf;
00307    char *buf_ptr, *srh_ptr;
00308    char *known_bad[] = {"select", "insert", "update", "delete", "drop", ";", "--", "\0"};
00309    int idx;
00310 
00311    if (!(buf = ast_calloc(1, len + 1))) {
00312       ast_log(LOG_ERROR, "Out of memory\n");
00313       return NULL;
00314    }
00315 
00316    buf_ptr = buf;
00317 
00318    /* Escape single quotes */
00319    for (; *str && strlen(buf) < len; str++) {
00320       if (*str == '\'') {
00321          *buf_ptr++ = '\'';
00322       }
00323       *buf_ptr++ = *str;
00324    }
00325    *buf_ptr = '\0';
00326 
00327    /* Erase known bad input */
00328    for (idx = 0; *known_bad[idx]; idx++) {
00329       while ((srh_ptr = strcasestr(buf, known_bad[idx]))) {
00330          memmove(srh_ptr, srh_ptr + strlen(known_bad[idx]), strlen(srh_ptr + strlen(known_bad[idx])) + 1);
00331       }
00332    }
00333 
00334    return buf;
00335 }

static int execute_and_consume ( DBPROCESS *  dbproc,
const char *  fmt,
  ... 
) [static]

Definition at line 349 of file cdr_tds.c.

References ast_vasprintf, and free.

Referenced by mssql_connect().

00350 {
00351    va_list ap;
00352    char *buffer;
00353 
00354    va_start(ap, fmt);
00355    if (ast_vasprintf(&buffer, fmt, ap) < 0) {
00356       va_end(ap);
00357       return 1;
00358    }
00359    va_end(ap);
00360 
00361    if (dbfcmd(dbproc, buffer) == FAIL) {
00362       free(buffer);
00363       return 1;
00364    }
00365 
00366    free(buffer);
00367 
00368    if (dbsqlexec(dbproc) == FAIL) {
00369       return 1;
00370    }
00371 
00372    /* Consume the result set (we don't really care about the result, though) */
00373    while (dbresults(dbproc) != NO_MORE_RESULTS) {
00374       while (dbnextrow(dbproc) != NO_MORE_ROWS);
00375    }
00376 
00377    return 0;
00378 }

static void get_date ( char *  ,
size_t  len,
struct  timeval 
) [static]

Definition at line 337 of file cdr_tds.c.

References ast_copy_string(), ast_localtime(), ast_strftime(), ast_tvzero(), and DATE_FORMAT.

00338 {
00339    /* To make sure we have date variable if not insert null to SQL */
00340    if (!ast_tvzero(when)) {
00341       struct ast_tm tm;
00342       ast_localtime(&when, &tm, NULL);
00343       ast_strftime(dateField, len, "'" DATE_FORMAT "'", &tm);
00344    } else {
00345       ast_copy_string(dateField, "null", len);
00346    }
00347 }

static int load_module ( void   )  [static]

Definition at line 596 of file cdr_tds.c.

References ast_calloc_with_stringfields, ast_cdr_register(), ast_free, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_string_field_free_memory, dbinit(), LOG_ERROR, settings, tds_error_handler(), tds_load_module(), tds_log(), and tds_message_handler().

00597 {
00598    if (dbinit() == FAIL) {
00599       ast_log(LOG_ERROR, "Failed to initialize FreeTDS db-lib\n");
00600       return AST_MODULE_LOAD_DECLINE;
00601    }
00602 
00603    dberrhandle(tds_error_handler);
00604    dbmsghandle(tds_message_handler);
00605 
00606    settings = ast_calloc_with_stringfields(1, struct cdr_tds_config, 256);
00607 
00608    if (!settings) {
00609       dbexit();
00610       return AST_MODULE_LOAD_DECLINE;
00611    }
00612 
00613    if (!tds_load_module(0)) {
00614       ast_string_field_free_memory(settings);
00615       ast_free(settings);
00616       settings = NULL;
00617       dbexit();
00618       return AST_MODULE_LOAD_DECLINE;
00619    }
00620 
00621    ast_cdr_register(name, ast_module_info->description, tds_log);
00622 
00623    return AST_MODULE_LOAD_SUCCESS;
00624 }

static int mssql_connect ( void   )  [static]

Definition at line 392 of file cdr_tds.c.

References ast_log(), cdr_tds_config::charset, cdr_tds_config::connected, cdr_tds_config::database, cdr_tds_config::dbproc, execute_and_consume(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::language, LOG_ERROR, LOG_NOTICE, cdr_tds_config::password, settings, cdr_tds_config::table, and cdr_tds_config::username.

Referenced by tds_load_module(), and tds_log().

00393 {
00394    LOGINREC *login;
00395 
00396    if ((login = dblogin()) == NULL) {
00397       ast_log(LOG_ERROR, "Unable to allocate login structure for db-lib\n");
00398       return -1;
00399    }
00400 
00401    DBSETLAPP(login,     "TSQL");
00402    DBSETLUSER(login,    (char *) settings->username);
00403    DBSETLPWD(login,     (char *) settings->password);
00404    DBSETLCHARSET(login, (char *) settings->charset);
00405    DBSETLNATLANG(login, (char *) settings->language);
00406 
00407    if ((settings->dbproc = dbopen(login, (char *) settings->hostname)) == NULL) {
00408       ast_log(LOG_ERROR, "Unable to connect to %s\n", settings->hostname);
00409       dbloginfree(login);
00410       return -1;
00411    }
00412 
00413    dbloginfree(login);
00414 
00415    if (dbuse(settings->dbproc, (char *) settings->database) == FAIL) {
00416       ast_log(LOG_ERROR, "Unable to select database %s\n", settings->database);
00417       goto failed;
00418    }
00419 
00420    if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s] WHERE 1 = 0", settings->table)) {
00421       ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
00422       goto failed;
00423    }
00424 
00425    /* Check to see if we have a userfield column in the table */
00426    if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) {
00427       ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table);
00428       settings->has_userfield = 0;
00429    } else {
00430       settings->has_userfield = 1;
00431    }
00432 
00433    settings->connected = 1;
00434 
00435    return 0;
00436 
00437 failed:
00438    dbclose(settings->dbproc);
00439    settings->dbproc = NULL;
00440    return -1;
00441 }

static int mssql_disconnect ( void   )  [static]

Definition at line 380 of file cdr_tds.c.

References cdr_tds_config::connected, cdr_tds_config::dbproc, and settings.

Referenced by tds_load_module(), tds_log(), and tds_unload_module().

00381 {
00382    if (settings->dbproc) {
00383       dbclose(settings->dbproc);
00384       settings->dbproc = NULL;
00385    }
00386 
00387    settings->connected = 0;
00388 
00389    return 0;
00390 }

static int reload ( void   )  [static]

Definition at line 591 of file cdr_tds.c.

References tds_load_module().

00592 {
00593    return tds_load_module(1);
00594 }

static int tds_error_handler ( DBPROCESS *  dbproc,
int  severity,
int  dberr,
int  oserr,
char *  dberrstr,
char *  oserrstr 
) [static]

Definition at line 461 of file cdr_tds.c.

References ast_log(), and LOG_ERROR.

Referenced by load_module().

00462 {
00463    ast_log(LOG_ERROR, "%s (%d)\n", dberrstr, dberr);
00464 
00465    if (oserr != DBNOERR) {
00466       ast_log(LOG_ERROR, "%s (%d)\n", oserrstr, oserr);
00467    }
00468 
00469    return INT_CANCEL;
00470 }

static int tds_load_module ( int  reload  )  [static]

Definition at line 480 of file cdr_tds.c.

References ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_string_field_init, ast_string_field_set, ast_true(), ast_variable_browse(), ast_variable_retrieve(), charset, CONFIG_FLAG_FILEUNCHANGED, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, hostname, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), settings, table, and tds_lock.

Referenced by load_module(), and reload().

00481 {
00482    struct ast_config *cfg;
00483    const char *ptr = NULL;
00484    struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
00485 
00486    cfg = ast_config_load(config, config_flags);
00487    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
00488       ast_log(LOG_NOTICE, "Unable to load TDS config for CDRs: %s\n", config);
00489       return 0;
00490    } else if (cfg == CONFIG_STATUS_FILEUNCHANGED)
00491       return 0;
00492 
00493    if (!ast_variable_browse(cfg, "global")) {
00494       /* nothing configured */
00495       ast_config_destroy(cfg);
00496       return 0;
00497    }
00498 
00499    ast_mutex_lock(&tds_lock);
00500 
00501    /* Clear out any existing settings */
00502    ast_string_field_init(settings, 0);
00503 
00504    /* 'connection' is the new preferred configuration option */
00505    ptr = ast_variable_retrieve(cfg, "global", "connection");
00506    if (ptr) {
00507       ast_string_field_set(settings, hostname, ptr);
00508    } else {
00509       /* But we keep 'hostname' for backwards compatibility */
00510       ptr = ast_variable_retrieve(cfg, "global", "hostname");
00511       if (ptr) {
00512          ast_string_field_set(settings, hostname, ptr);
00513       } else {
00514          ast_log(LOG_ERROR, "Failed to connect: Database server connection not specified.\n");
00515          goto failed;
00516       }
00517    }
00518 
00519    ptr = ast_variable_retrieve(cfg, "global", "dbname");
00520    if (ptr) {
00521       ast_string_field_set(settings, database, ptr);
00522    } else {
00523       ast_log(LOG_ERROR, "Failed to connect: Database dbname not specified.\n");
00524       goto failed;
00525    }
00526 
00527    ptr = ast_variable_retrieve(cfg, "global", "user");
00528    if (ptr) {
00529       ast_string_field_set(settings, username, ptr);
00530    } else {
00531       ast_log(LOG_ERROR, "Failed to connect: Database dbuser not specified.\n");
00532       goto failed;
00533    }
00534 
00535    ptr = ast_variable_retrieve(cfg, "global", "password");
00536    if (ptr) {
00537       ast_string_field_set(settings, password, ptr);
00538    } else {
00539       ast_log(LOG_ERROR, "Failed to connect: Database password not specified.\n");
00540       goto failed;
00541    }
00542 
00543    ptr = ast_variable_retrieve(cfg, "global", "charset");
00544    if (ptr) {
00545       ast_string_field_set(settings, charset, ptr);
00546    } else {
00547       ast_string_field_set(settings, charset, "iso_1");
00548    }
00549 
00550    ptr = ast_variable_retrieve(cfg, "global", "language");
00551    if (ptr) {
00552       ast_string_field_set(settings, language, ptr);
00553    } else {
00554       ast_string_field_set(settings, language, "us_english");
00555    }
00556 
00557    ptr = ast_variable_retrieve(cfg, "global", "table");
00558    if (ptr) {
00559       ast_string_field_set(settings, table, ptr);
00560    } else {
00561       ast_log(LOG_NOTICE, "Table name not specified, using 'cdr' by default.\n");
00562       ast_string_field_set(settings, table, "cdr");
00563    }
00564 
00565    ptr = ast_variable_retrieve(cfg, "global", "hrtime");
00566    if (ptr && ast_true(ptr)) {
00567       ast_string_field_set(settings, hrtime, ptr);
00568    } else {
00569       ast_log(LOG_NOTICE, "High Resolution Time not found, using integers for billsec and duration fields by default.\n");
00570    }
00571 
00572    mssql_disconnect();
00573 
00574    if (mssql_connect()) {
00575       /* We failed to connect (mssql_connect takes care of logging it) */
00576       goto failed;
00577    }
00578 
00579    ast_mutex_unlock(&tds_lock);
00580    ast_config_destroy(cfg);
00581 
00582    return 1;
00583 
00584 failed:
00585    ast_mutex_unlock(&tds_lock);
00586    ast_config_destroy(cfg);
00587 
00588    return 0;
00589 }

static int tds_log ( struct ast_cdr cdr  )  [static]

Definition at line 110 of file cdr_tds.c.

References accountcode, anti_injection(), ast_cdr_disp2str(), ast_cdr_flags2str(), ast_free, ast_log(), AST_MAX_USER_FIELD, ast_mutex_lock, ast_mutex_unlock, ast_tvdiff_us(), ast_tvzero(), cdr_tds_config::connected, cdr_tds_config::dbproc, get_date(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::hrtime, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), settings, cdr_tds_config::table, and tds_lock.

Referenced by load_module().

00111 {
00112    char start[80], answer[80], end[80];
00113    char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL;
00114    RETCODE erc;
00115    int res = -1;
00116    int attempt = 1;
00117 
00118    accountcode = anti_injection(cdr->accountcode, 20);
00119    src         = anti_injection(cdr->src, 80);
00120    dst         = anti_injection(cdr->dst, 80);
00121    dcontext    = anti_injection(cdr->dcontext, 80);
00122    clid        = anti_injection(cdr->clid, 80);
00123    channel     = anti_injection(cdr->channel, 80);
00124    dstchannel  = anti_injection(cdr->dstchannel, 80);
00125    lastapp     = anti_injection(cdr->lastapp, 80);
00126    lastdata    = anti_injection(cdr->lastdata, 80);
00127    uniqueid    = anti_injection(cdr->uniqueid, 32);
00128 
00129    get_date(start, sizeof(start), cdr->start);
00130    get_date(answer, sizeof(answer), cdr->answer);
00131    get_date(end, sizeof(end), cdr->end);
00132 
00133    ast_mutex_lock(&tds_lock);
00134 
00135    if (settings->has_userfield) {
00136       userfield = anti_injection(cdr->userfield, AST_MAX_USER_FIELD);
00137    }
00138 
00139 retry:
00140    /* Ensure that we are connected */
00141    if (!settings->connected) {
00142       ast_log(LOG_NOTICE, "Attempting to reconnect to %s (Attempt %d)\n", settings->hostname, attempt);
00143       if (mssql_connect()) {
00144          /* Connect failed */
00145          if (attempt++ < 3) {
00146             goto retry;
00147          }
00148          goto done;
00149       }
00150    }
00151 
00152    if (settings->has_userfield) {
00153       if (settings->hrtime) {
00154          double hrbillsec = 0.0;
00155          double hrduration;
00156 
00157          if (!ast_tvzero(cdr->answer)) {
00158             hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
00159          }
00160          hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
00161 
00162          erc = dbfcmd(settings->dbproc,
00163                 "INSERT INTO %s "
00164                 "("
00165                 "accountcode, src, dst, dcontext, clid, channel, "
00166                 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
00167                 "billsec, disposition, amaflags, uniqueid, userfield"
00168                 ") "
00169                 "VALUES "
00170                 "("
00171                 "'%s', '%s', '%s', '%s', '%s', '%s', "
00172                 "'%s', '%s', '%s', %s, %s, %s, %lf, "
00173                 "%lf, '%s', '%s', '%s', '%s'"
00174                 ")",
00175                 settings->table,
00176                 accountcode, src, dst, dcontext, clid, channel,
00177                 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
00178                 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid,
00179                 userfield
00180          );
00181       } else {
00182          erc = dbfcmd(settings->dbproc,
00183                 "INSERT INTO %s "
00184                 "("
00185                 "accountcode, src, dst, dcontext, clid, channel, "
00186                 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
00187                 "billsec, disposition, amaflags, uniqueid, userfield"
00188                 ") "
00189                 "VALUES "
00190                 "("
00191                 "'%s', '%s', '%s', '%s', '%s', '%s', "
00192                 "'%s', '%s', '%s', %s, %s, %s, %ld, "
00193                 "%ld, '%s', '%s', '%s', '%s'"
00194                 ")",
00195                 settings->table,
00196                 accountcode, src, dst, dcontext, clid, channel,
00197                 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
00198                 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid,
00199                 userfield
00200          );
00201       }
00202    } else {
00203       if (settings->hrtime) {
00204          double hrbillsec = 0.0;
00205          double hrduration;
00206 
00207          if (!ast_tvzero(cdr->answer)) {
00208             hrbillsec = (double)(ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0);
00209          }
00210          hrduration = (double)(ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0);
00211 
00212          erc = dbfcmd(settings->dbproc,
00213                 "INSERT INTO %s "
00214                 "("
00215                 "accountcode, src, dst, dcontext, clid, channel, "
00216                 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
00217                 "billsec, disposition, amaflags, uniqueid"
00218                 ") "
00219                 "VALUES "
00220                 "("
00221                 "'%s', '%s', '%s', '%s', '%s', '%s', "
00222                 "'%s', '%s', '%s', %s, %s, %s, %lf, "
00223                 "%lf, '%s', '%s', '%s'"
00224                 ")",
00225                 settings->table,
00226                 accountcode, src, dst, dcontext, clid, channel,
00227                 dstchannel, lastapp, lastdata, start, answer, end, hrduration,
00228                 hrbillsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid
00229          );
00230       } else {
00231          erc = dbfcmd(settings->dbproc,
00232                 "INSERT INTO %s "
00233                 "("
00234                 "accountcode, src, dst, dcontext, clid, channel, "
00235                 "dstchannel, lastapp, lastdata, start, answer, [end], duration, "
00236                 "billsec, disposition, amaflags, uniqueid"
00237                 ") "
00238                 "VALUES "
00239                 "("
00240                 "'%s', '%s', '%s', '%s', '%s', '%s', "
00241                 "'%s', '%s', '%s', %s, %s, %s, %ld, "
00242                 "%ld, '%s', '%s', '%s'"
00243                 ")",
00244                 settings->table,
00245                 accountcode, src, dst, dcontext, clid, channel,
00246                 dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
00247                 cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid
00248          );
00249       }
00250    }
00251 
00252    if (erc == FAIL) {
00253       if (attempt++ < 3) {
00254          ast_log(LOG_NOTICE, "Failed to build INSERT statement, retrying...\n");
00255          mssql_disconnect();
00256          goto retry;
00257       } else {
00258          ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n");
00259          goto done;
00260       }
00261    }
00262 
00263    if (dbsqlexec(settings->dbproc) == FAIL) {
00264       if (attempt++ < 3) {
00265          ast_log(LOG_NOTICE, "Failed to execute INSERT statement, retrying...\n");
00266          mssql_disconnect();
00267          goto retry;
00268       } else {
00269          ast_log(LOG_ERROR, "Failed to execute INSERT statement, no CDR was logged.\n");
00270          goto done;
00271       }
00272    }
00273 
00274    /* Consume any results we might get back (this is more of a sanity check than
00275     * anything else, since an INSERT shouldn't return results). */
00276    while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
00277       while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
00278    }
00279 
00280    res = 0;
00281 
00282 done:
00283    ast_mutex_unlock(&tds_lock);
00284 
00285    ast_free(accountcode);
00286    ast_free(src);
00287    ast_free(dst);
00288    ast_free(dcontext);
00289    ast_free(clid);
00290    ast_free(channel);
00291    ast_free(dstchannel);
00292    ast_free(lastapp);
00293    ast_free(lastdata);
00294    ast_free(uniqueid);
00295 
00296    if (userfield) {
00297       ast_free(userfield);
00298    }
00299 
00300    return res;
00301 }

static int tds_message_handler ( DBPROCESS *  dbproc,
DBINT  msgno,
int  msgstate,
int  severity,
char *  msgtext,
char *  srvname,
char *  procname,
int  line 
) [static]

Definition at line 472 of file cdr_tds.c.

References ast_debug, ast_log(), and LOG_NOTICE.

Referenced by load_module().

00473 {
00474    ast_debug(1, "Msg %d, Level %d, State %d, Line %d\n", msgno, severity, msgstate, line);
00475    ast_log(LOG_NOTICE, "%s\n", msgtext);
00476 
00477    return 0;
00478 }

static int tds_unload_module ( void   )  [static]

Definition at line 443 of file cdr_tds.c.

References ast_cdr_unregister(), ast_free, ast_mutex_lock, ast_mutex_unlock, ast_string_field_free_memory, mssql_disconnect(), settings, and tds_lock.

Referenced by unload_module().

00444 {
00445    if (settings) {
00446       ast_mutex_lock(&tds_lock);
00447       mssql_disconnect();
00448       ast_mutex_unlock(&tds_lock);
00449 
00450       ast_string_field_free_memory(settings);
00451       ast_free(settings);
00452    }
00453 
00454    ast_cdr_unregister(name);
00455 
00456    dbexit();
00457 
00458    return 0;
00459 }

static int unload_module ( void   )  [static]

Definition at line 626 of file cdr_tds.c.

References tds_unload_module().

00627 {
00628    return tds_unload_module();
00629 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "FreeTDS CDR Backend" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 636 of file cdr_tds.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 636 of file cdr_tds.c.

const char config[] = "cdr_tds.conf" [static]

Definition at line 79 of file cdr_tds.c.

const char name[] = "FreeTDS (MSSQL)" [static]

Definition at line 78 of file cdr_tds.c.

struct cdr_tds_config* settings [static]

Definition at line 99 of file cdr_tds.c.

Referenced by load_module(), mssql_connect(), mssql_disconnect(), tds_load_module(), tds_log(), and tds_unload_module().

ast_mutex_t tds_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 97 of file cdr_tds.c.

Referenced by tds_load_module(), tds_log(), and tds_unload_module().


Generated on Wed Apr 6 11:29:54 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7