Index: build_tools/menuselect-deps.in =================================================================== --- build_tools/menuselect-deps.in (revision 49049) +++ build_tools/menuselect-deps.in (working copy) @@ -23,6 +23,7 @@ RADIUS=@PBX_RADIUS@ SPEEX=@PBX_SPEEX@ SQLITE=@PBX_SQLITE@ +SQLITE3=@PBX_SQLITE3@ SSL=@PBX_OPENSSL@ TONEZONE=@PBX_TONEZONE@ UNIXODBC=@PBX_UNIXODBC@ Index: configure.ac =================================================================== --- configure.ac (revision 49049) +++ configure.ac (working copy) @@ -206,6 +206,7 @@ AST_EXT_LIB_SETUP([RADIUS], [Radius Client], [radius]) AST_EXT_LIB_SETUP([SPEEX], [Speex], [speex]) AST_EXT_LIB_SETUP([SQLITE], [SQLite], [sqlite]) +AST_EXT_LIB_SETUP([SQLITE3], [SQLite3], [sqlite3]) AST_EXT_LIB_SETUP([SUPPSERV], [mISDN Supplemental Services], [suppserv]) AST_EXT_LIB_SETUP([OPENSSL], [OpenSSL], [ssl]) AST_EXT_LIB_SETUP([FREETDS], [FreeTDS], [tds]) @@ -771,6 +772,8 @@ AST_EXT_LIB_CHECK([SQLITE], [sqlite], [sqlite_exec], [sqlite.h]) +AST_EXT_LIB_CHECK([SQLITE3], [sqlite3], [sqlite3_exec], [sqlite3.h]) + AST_EXT_LIB_CHECK([OPENSSL], [ssl], [ssl2_connect], [openssl/ssl.h], [-lcrypto]) AST_EXT_LIB_CHECK([FREETDS], [tds], [tds_version], [tds.h]) Index: makeopts.in =================================================================== --- makeopts.in (revision 49049) +++ makeopts.in (working copy) @@ -136,6 +136,9 @@ SQLITE_INCLUDE=@SQLITE_INCLUDE@ SQLITE_LIB=@SQLITE_LIB@ +SQLITE3_INCLUDE=@SQLITE3_INCLUDE@ +SQLITE3_LIB=@SQLITE3_LIB@ + SSL_INCLUDE=@OPENSSL_INCLUDE@ SSL_LIB=@OPENSSL_LIB@ Index: cdr/cdr_sqlite3.c =================================================================== --- cdr/cdr_sqlite3.c (revision 0) +++ cdr/cdr_sqlite3.c (revision 0) @@ -0,0 +1,224 @@ + +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2006, Balwinder S "bsd" Dheeman + * + * Adapted from cdr_sqlite.c file, written by Holger Schurig + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Store CDR records in a SQLite3 database. + * + * \author Holger Schurig + * + * See also + * \arg \ref Config_cdr + * \arg http://www.sqlite.org/ + * + * Creates the database and table on-the-fly + * \ingroup cdr_drivers + */ + +/*** MODULEINFO + sqlite3 + ***/ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision") +#include +#include +#include +#include +#include +#include +#include "asterisk/channel.h" +#include "asterisk/module.h" +#include "asterisk/logger.h" +#include "asterisk/utils.h" + +#define LOG_UNIQUEID 0 +#define LOG_USERFIELD 0 + +/* When you change the DATE_FORMAT, be sure to change the CHAR(19) below + * to something else + */ +#define DATE_FORMAT "%Y-%m-%d %T" + +static const char *name = "cdr_sqlite3"; + +AST_MUTEX_DEFINE_STATIC(sqlite3_lock); + +sqlite3 *db; + +/*! \brief SQL table format */ +static char sql_create_table[] = "CREATE TABLE cdr (" + " AcctId INTEGER PRIMARY KEY," + " clid VARCHAR(80)," + " src VARCHAR(80)," + " dst VARCHAR(80)," + " dcontext VARCHAR(80)," + " channel VARCHAR(80)," + " dstchannel VARCHAR(80)," + " lastapp VARCHAR(80)," + " lastdata VARCHAR(80)," + " start CHAR(19)," + " answer CHAR(19)," + " end CHAR(19)," + " duration INTEGER," + " billsec INTEGER," + " disposition INTEGER," + " amaflags INTEGER," + " accountcode VARCHAR(20)" +#if LOG_UNIQUEID + " ,uniqueid VARCHAR(32)" +#endif +#if LOG_USERFIELD + " ,userfield VARCHAR(255)" +#endif + ");"; + +static int sqlite3_log(struct ast_cdr *cdr) +{ + int res = 0; + char *errmsg = NULL; + char *query = NULL; + struct tm tm; + time_t t; + char startstr[80], answerstr[80], endstr[80]; + int count; + + ast_mutex_lock(&sqlite3_lock); + + t = cdr->start.tv_sec; + localtime_r(&t, &tm); + strftime(startstr, sizeof(startstr), DATE_FORMAT, &tm); + + t = cdr->answer.tv_sec; + localtime_r(&t, &tm); + strftime(answerstr, sizeof(answerstr), DATE_FORMAT, &tm); + + t = cdr->end.tv_sec; + localtime_r(&t, &tm); + strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm); + + query = sqlite3_mprintf("INSERT INTO cdr (" + "clid,src,dst,dcontext," + "channel,dstchannel,lastapp,lastdata," + "start,answer,end," + "duration,billsec,disposition,amaflags," + "accountcode" +#if LOG_UNIQUEID + ",uniqueid" +#endif +#if LOG_USERFIELD + ",userfield" +#endif + ") VALUES (" + "'%q','%q','%q','%q'," + "'%q','%q','%q','%q'," + "'%q','%q','%q'," + "%ld,%ld,%ld,%ld," + "'%q'" +#if LOG_UNIQUEID + ",'%q'" +#endif +#if LOG_USERFIELD + ",'%q'" +#endif + ")", + cdr->clid, cdr->src, cdr->dst, cdr->dcontext, + cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, + startstr, answerstr, endstr, + cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, + cdr->accountcode +#if LOG_UNIQUEID + , cdr->uniqueid +#endif +#if LOG_USERFIELD + , cdr->userfield +#endif + ); + + for (count = 0; count < 5; count++) { + res = sqlite3_exec(db, query, NULL, NULL, &errmsg); + if (errmsg != NULL) + sqlite3_free(errmsg); + if (res != SQLITE_BUSY && res != SQLITE_LOCKED) + break; + usleep(200); + } + + if (query) + sqlite3_free(query); + + if (errmsg) { + ast_log(LOG_ERROR, "cdr_sqlite3: %s\n", errmsg); + sqlite3_free(errmsg); + } + + ast_mutex_unlock(&sqlite3_lock); + return res; +} + +static int unload_module(void) +{ + if (db) + sqlite3_close(db); + ast_cdr_unregister(name); + return 0; +} + +static int load_module(void) +{ + char *errmsg; + char fn[PATH_MAX]; + int res; + + /* is the database there? */ + snprintf(fn, sizeof(fn), "%s/cdr_sqlite3.db", ast_config_AST_LOG_DIR); + if (SQLITE_OK != sqlite3_open(fn, &db)) { + ast_log(LOG_ERROR, "cdr_sqlite3: %s\n", sqlite3_errmsg(db)); + return -1; + } + + /* is the table there? */ + res = sqlite3_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, &errmsg); + if (errmsg != NULL) { + sqlite3_free(errmsg); + res = sqlite3_exec(db, sql_create_table, NULL, NULL, &errmsg); + if (errmsg != NULL) { + ast_log(LOG_ERROR, "cdr_sqlite3: Unable to create table 'cdr': %s\n", errmsg); + sqlite3_free(errmsg); + goto err; + } + + /* TODO: here we should probably create an index */ + } + + res = ast_cdr_register(name, ast_module_info->description, sqlite3_log); + if (res) { + ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n"); + return -1; + } + return 0; + + err: + if (db) + sqlite3_close(db); + return -1; +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SQLite3 CDR Backend");