Mon Mar 19 11:30:37 2012

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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }


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 77 of file cdr_tds.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 637 of file cdr_tds.c.

static void __unreg_module ( void   )  [static]

Definition at line 637 of file cdr_tds.c.

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

Definition at line 304 of file cdr_tds.c.

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

Referenced by tds_log().

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

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

Definition at line 350 of file cdr_tds.c.

References ast_vasprintf, and free.

Referenced by mssql_connect().

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

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

Definition at line 338 of file cdr_tds.c.

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

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

static int load_module ( void   )  [static]

Definition at line 597 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().

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

static int mssql_connect ( void   )  [static]

Definition at line 393 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().

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

static int mssql_disconnect ( void   )  [static]

Definition at line 381 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().

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

static int reload ( void   )  [static]

Definition at line 592 of file cdr_tds.c.

References tds_load_module().

00593 {
00594    return tds_load_module(1);
00595 }

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

Definition at line 462 of file cdr_tds.c.

References ast_log(), and LOG_ERROR.

Referenced by load_module().

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

static int tds_load_module ( int  reload  )  [static]

Definition at line 481 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().

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

static int tds_log ( struct ast_cdr cdr  )  [static]

Definition at line 111 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().

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

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 473 of file cdr_tds.c.

References ast_debug, ast_log(), and LOG_NOTICE.

Referenced by load_module().

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

static int tds_unload_module ( void   )  [static]

Definition at line 444 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().

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

static int unload_module ( void   )  [static]

Definition at line 627 of file cdr_tds.c.

References tds_unload_module().

00628 {
00629    return tds_unload_module();
00630 }


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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 637 of file cdr_tds.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 637 of file cdr_tds.c.

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

Definition at line 80 of file cdr_tds.c.

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

Definition at line 79 of file cdr_tds.c.

struct cdr_tds_config* settings [static]

Definition at line 100 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 98 of file cdr_tds.c.

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


Generated on Mon Mar 19 11:30:37 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7