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>

Include dependency graph for cdr_tds.c:

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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .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_MUTEX_INITIALIZER , 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 640 of file cdr_tds.c.

static void __unreg_module ( void   )  [static]

Definition at line 640 of file cdr_tds.c.

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

Definition at line 304 of file cdr_tds.c.

References ast_calloc, ast_log, buf, LOG_ERROR, NULL, 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_free, and ast_vasprintf.

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       ast_free(buffer);
00364       return 1;
00365    }
00366 
00367    ast_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 *  dateField,
size_t  len,
struct timeval  when 
) [static]

Definition at line 338 of file cdr_tds.c.

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

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 599 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, LOG_ERROR, NULL, tds_error_handler(), tds_load_module(), tds_log(), and tds_message_handler().

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

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, dbopen(), cdr_tds_config::dbproc, execute_and_consume(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::language, LOG_ERROR, LOG_NOTICE, NULL, cdr_tds_config::password, 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 NULL.

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

References tds_load_module().

00595 {
00596    return tds_load_module(1);
00597 }

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

Definition at line 464 of file cdr_tds.c.

References ast_log, and LOG_ERROR.

Referenced by load_module().

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

static int tds_load_module ( int  reload  )  [static]

Definition at line 483 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(), CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, hostname, language, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, password, table, and tds_lock.

Referenced by load_module(), and reload().

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

static int tds_log ( struct ast_cdr cdr  )  [static]

Definition at line 111 of file cdr_tds.c.

References accountcode, answer(), anti_injection(), ast_cdr_disp2str(), ast_channel_amaflags2string(), 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, end, get_date(), cdr_tds_config::has_userfield, cdr_tds_config::hostname, cdr_tds_config::hrtime, LOG_ERROR, LOG_NOTICE, mssql_connect(), mssql_disconnect(), NULL, 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_channel_amaflags2string(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_channel_amaflags2string(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_channel_amaflags2string(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_channel_amaflags2string(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 475 of file cdr_tds.c.

References ast_debug, ast_log, and LOG_NOTICE.

Referenced by load_module().

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

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(), and tds_lock.

Referenced by unload_module().

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

static int unload_module ( void   )  [static]

Definition at line 629 of file cdr_tds.c.

References tds_unload_module().

00630 {
00631    return tds_unload_module();
00632 }


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 = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_EXTENDED, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CDR_DRIVER, } [static]

Definition at line 640 of file cdr_tds.c.

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

ast_mutex_t tds_lock = { PTHREAD_MUTEX_INITIALIZER , 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 Thu Apr 16 06:29:27 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6