Log the userfield CDR variable like the other CDR backends, assuming the
column is actually there. If it's not, we still log everything else as before. (closes issue #13281) Reported by: falves11 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@137203 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
parent
37133a6993
commit
9c7099faae
|
@ -168,7 +168,8 @@ CDR:
|
||||||
systemname was too long, the uniqueid would have been truncated.
|
systemname was too long, the uniqueid would have been truncated.
|
||||||
|
|
||||||
* The cdr_tds module now supports all versions of FreeTDS that contain
|
* The cdr_tds module now supports all versions of FreeTDS that contain
|
||||||
the db-lib frontend.
|
the db-lib frontend. It will also now log the userfield variable if
|
||||||
|
the target database table contains a column for it.
|
||||||
|
|
||||||
Formats:
|
Formats:
|
||||||
|
|
||||||
|
|
166
cdr/cdr_tds.c
166
cdr/cdr_tds.c
|
@ -48,7 +48,8 @@ CREATE TABLE [dbo].[cdr] (
|
||||||
[billsec] [int] NULL ,
|
[billsec] [int] NULL ,
|
||||||
[disposition] [varchar] (20) NULL ,
|
[disposition] [varchar] (20) NULL ,
|
||||||
[amaflags] [varchar] (16) NULL ,
|
[amaflags] [varchar] (16) NULL ,
|
||||||
[uniqueid] [varchar] (32) NULL
|
[uniqueid] [varchar] (32) NULL ,
|
||||||
|
[userfield] [varchar] (256) NULL
|
||||||
) ON [PRIMARY]
|
) ON [PRIMARY]
|
||||||
|
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
@ -91,6 +92,7 @@ struct cdr_tds_config {
|
||||||
);
|
);
|
||||||
DBPROCESS *dbproc;
|
DBPROCESS *dbproc;
|
||||||
unsigned int connected:1;
|
unsigned int connected:1;
|
||||||
|
unsigned int has_userfield:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
AST_MUTEX_DEFINE_STATIC(tds_lock);
|
AST_MUTEX_DEFINE_STATIC(tds_lock);
|
||||||
|
@ -100,13 +102,16 @@ static struct cdr_tds_config *settings;
|
||||||
static char *anti_injection(const char *, int);
|
static char *anti_injection(const char *, int);
|
||||||
static void get_date(char *, size_t len, struct timeval);
|
static void get_date(char *, size_t len, struct timeval);
|
||||||
|
|
||||||
|
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
|
||||||
|
__attribute__ ((format (printf, 2, 3)));
|
||||||
|
|
||||||
static int mssql_connect(void);
|
static int mssql_connect(void);
|
||||||
static int mssql_disconnect(void);
|
static int mssql_disconnect(void);
|
||||||
|
|
||||||
static int tds_log(struct ast_cdr *cdr)
|
static int tds_log(struct ast_cdr *cdr)
|
||||||
{
|
{
|
||||||
char start[80], answer[80], end[80];
|
char start[80], answer[80], end[80];
|
||||||
char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid;
|
char *accountcode, *src, *dst, *dcontext, *clid, *channel, *dstchannel, *lastapp, *lastdata, *uniqueid, *userfield = NULL;
|
||||||
RETCODE erc;
|
RETCODE erc;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
|
|
||||||
|
@ -127,6 +132,10 @@ static int tds_log(struct ast_cdr *cdr)
|
||||||
|
|
||||||
ast_mutex_lock(&tds_lock);
|
ast_mutex_lock(&tds_lock);
|
||||||
|
|
||||||
|
if (settings->has_userfield) {
|
||||||
|
userfield = anti_injection(cdr->userfield, AST_MAX_USER_FIELD);
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure that we are connected */
|
/* Ensure that we are connected */
|
||||||
if (!settings->connected) {
|
if (!settings->connected) {
|
||||||
if (mssql_connect()) {
|
if (mssql_connect()) {
|
||||||
|
@ -135,66 +144,46 @@ static int tds_log(struct ast_cdr *cdr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
erc = dbfcmd(settings->dbproc,
|
if (settings->has_userfield) {
|
||||||
"INSERT INTO %s "
|
erc = dbfcmd(settings->dbproc,
|
||||||
"("
|
"INSERT INTO %s "
|
||||||
"accountcode, "
|
"("
|
||||||
"src, "
|
"accountcode, src, dst, dcontext, clid, channel, "
|
||||||
"dst, "
|
"dstchannel, lastapp, lastdata, start, answer, [end], duration, "
|
||||||
"dcontext, "
|
"billsec, disposition, amaflags, uniqueid, userfield"
|
||||||
"clid, "
|
") "
|
||||||
"channel, "
|
"VALUES "
|
||||||
"dstchannel, "
|
"("
|
||||||
"lastapp, "
|
"'%s', '%s', '%s', '%s', '%s', '%s', "
|
||||||
"lastdata, "
|
"'%s', '%s', '%s', %s, %s, %s, %ld, "
|
||||||
"start, "
|
"%ld, '%s', '%s', '%s', '%s'"
|
||||||
"answer, "
|
")",
|
||||||
"[end], "
|
settings->table,
|
||||||
"duration, "
|
accountcode, src, dst, dcontext, clid, channel,
|
||||||
"billsec, "
|
dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
|
||||||
"disposition, "
|
cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid,
|
||||||
"amaflags, "
|
userfield
|
||||||
"uniqueid"
|
);
|
||||||
") "
|
} else {
|
||||||
"VALUES "
|
erc = dbfcmd(settings->dbproc,
|
||||||
"("
|
"INSERT INTO %s "
|
||||||
"'%s', " /* accountcode */
|
"("
|
||||||
"'%s', " /* src */
|
"accountcode, src, dst, dcontext, clid, channel, "
|
||||||
"'%s', " /* dst */
|
"dstchannel, lastapp, lastdata, start, answer, [end], duration, "
|
||||||
"'%s', " /* dcontext */
|
"billsec, disposition, amaflags, uniqueid"
|
||||||
"'%s', " /* clid */
|
") "
|
||||||
"'%s', " /* channel */
|
"VALUES "
|
||||||
"'%s', " /* dstchannel */
|
"("
|
||||||
"'%s', " /* lastapp */
|
"'%s', '%s', '%s', '%s', '%s', '%s', "
|
||||||
"'%s', " /* lastdata */
|
"'%s', '%s', '%s', %s, %s, %s, %ld, "
|
||||||
"%s, " /* start */
|
"%ld, '%s', '%s', '%s'"
|
||||||
"%s, " /* answer */
|
")",
|
||||||
"%s, " /* end */
|
settings->table,
|
||||||
"%ld, " /* duration */
|
accountcode, src, dst, dcontext, clid, channel,
|
||||||
"%ld, " /* billsec */
|
dstchannel, lastapp, lastdata, start, answer, end, cdr->duration,
|
||||||
"'%s', " /* disposition */
|
cdr->billsec, ast_cdr_disp2str(cdr->disposition), ast_cdr_flags2str(cdr->amaflags), uniqueid
|
||||||
"'%s', " /* amaflags */
|
);
|
||||||
"'%s'" /* uniqueid */
|
}
|
||||||
")",
|
|
||||||
settings->table,
|
|
||||||
accountcode,
|
|
||||||
src,
|
|
||||||
dst,
|
|
||||||
dcontext,
|
|
||||||
clid,
|
|
||||||
channel,
|
|
||||||
dstchannel,
|
|
||||||
lastapp,
|
|
||||||
lastdata,
|
|
||||||
start,
|
|
||||||
answer,
|
|
||||||
end,
|
|
||||||
cdr->duration,
|
|
||||||
cdr->billsec,
|
|
||||||
ast_cdr_disp2str(cdr->disposition),
|
|
||||||
ast_cdr_flags2str(cdr->amaflags),
|
|
||||||
uniqueid
|
|
||||||
);
|
|
||||||
|
|
||||||
if (erc == FAIL) {
|
if (erc == FAIL) {
|
||||||
ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n");
|
ast_log(LOG_ERROR, "Failed to build INSERT statement, no CDR was logged.\n");
|
||||||
|
@ -228,6 +217,10 @@ done:
|
||||||
ast_free(lastdata);
|
ast_free(lastdata);
|
||||||
ast_free(uniqueid);
|
ast_free(uniqueid);
|
||||||
|
|
||||||
|
if (userfield) {
|
||||||
|
ast_free(userfield);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,6 +270,37 @@ static void get_date(char *dateField, size_t len, struct timeval when)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int execute_and_consume(DBPROCESS *dbproc, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
if (vasprintf(&buffer, fmt, ap) < 0) {
|
||||||
|
va_end(ap);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (dbfcmd(dbproc, buffer) == FAIL) {
|
||||||
|
free(buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
if (dbsqlexec(dbproc) == FAIL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume the result set (we don't really care about the result, though) */
|
||||||
|
while (dbresults(dbproc) != NO_MORE_RESULTS) {
|
||||||
|
while (dbnextrow(dbproc) != NO_MORE_ROWS);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mssql_disconnect(void)
|
static int mssql_disconnect(void)
|
||||||
{
|
{
|
||||||
if (settings->dbproc) {
|
if (settings->dbproc) {
|
||||||
|
@ -317,19 +341,17 @@ static int mssql_connect(void)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbfcmd(settings->dbproc, "SELECT 1 FROM [%s]", settings->table) == FAIL) {
|
if (execute_and_consume(settings->dbproc, "SELECT 1 FROM [%s]", settings->table)) {
|
||||||
ast_log(LOG_ERROR, "Unable to build query while verifying the existence of table '%s'\n", settings->table);
|
ast_log(LOG_ERROR, "Unable to find table '%s'\n", settings->table);
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dbsqlexec(settings->dbproc) == FAIL) {
|
/* Check to see if we have a userfield column in the table */
|
||||||
ast_log(LOG_ERROR, "Unable to verify existence of table '%s'\n", settings->table);
|
if (execute_and_consume(settings->dbproc, "SELECT userfield FROM [%s] WHERE 1 = 0", settings->table)) {
|
||||||
goto failed;
|
ast_log(LOG_NOTICE, "Unable to find 'userfield' column in table '%s'\n", settings->table);
|
||||||
}
|
settings->has_userfield = 0;
|
||||||
|
} else {
|
||||||
/* Consume the result set (we don't really care about the result, though) */
|
settings->has_userfield = 1;
|
||||||
while (dbresults(settings->dbproc) != NO_MORE_RESULTS) {
|
|
||||||
while (dbnextrow(settings->dbproc) != NO_MORE_ROWS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
settings->connected = 1;
|
settings->connected = 1;
|
||||||
|
|
Loading…
Reference in New Issue