00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "asterisk.h"
00039
00040 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00041
00042 #include <sys/types.h>
00043 #include <unistd.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include <stdio.h>
00047 #include <sqlite.h>
00048
00049 #include "asterisk/channel.h"
00050 #include "asterisk/module.h"
00051 #include "asterisk/logger.h"
00052 #include "asterisk/utils.h"
00053
00054 #define LOG_UNIQUEID 0
00055 #define LOG_USERFIELD 0
00056
00057
00058 #define DATE_FORMAT "%Y-%m-%d %T"
00059
00060 static char *name = "sqlite";
00061 static sqlite* db = NULL;
00062
00063 AST_MUTEX_DEFINE_STATIC(sqlite_lock);
00064
00065
00066 static char sql_create_table[] = "CREATE TABLE cdr ("
00067 " AcctId INTEGER PRIMARY KEY,"
00068 " clid VARCHAR(80),"
00069 " src VARCHAR(80),"
00070 " dst VARCHAR(80),"
00071 " dcontext VARCHAR(80),"
00072 " channel VARCHAR(80),"
00073 " dstchannel VARCHAR(80),"
00074 " lastapp VARCHAR(80),"
00075 " lastdata VARCHAR(80),"
00076 " start CHAR(19),"
00077 " answer CHAR(19),"
00078 " end CHAR(19),"
00079 " duration INTEGER,"
00080 " billsec INTEGER,"
00081 " disposition INTEGER,"
00082 " amaflags INTEGER,"
00083 " accountcode VARCHAR(20)"
00084 #if LOG_UNIQUEID
00085 " ,uniqueid VARCHAR(32)"
00086 #endif
00087 #if LOG_USERFIELD
00088 " ,userfield VARCHAR(255)"
00089 #endif
00090 ");";
00091
00092 static int sqlite_log(struct ast_cdr *cdr)
00093 {
00094 int res = 0;
00095 char *zErr = 0;
00096 struct tm tm;
00097 time_t t;
00098 char startstr[80], answerstr[80], endstr[80];
00099 int count;
00100
00101 ast_mutex_lock(&sqlite_lock);
00102
00103 t = cdr->start.tv_sec;
00104 localtime_r(&t, &tm);
00105 strftime(startstr, sizeof(startstr), DATE_FORMAT, &tm);
00106
00107 t = cdr->answer.tv_sec;
00108 localtime_r(&t, &tm);
00109 strftime(answerstr, sizeof(answerstr), DATE_FORMAT, &tm);
00110
00111 t = cdr->end.tv_sec;
00112 localtime_r(&t, &tm);
00113 strftime(endstr, sizeof(endstr), DATE_FORMAT, &tm);
00114
00115 for(count=0; count<5; count++) {
00116 res = sqlite_exec_printf(db,
00117 "INSERT INTO cdr ("
00118 "clid,src,dst,dcontext,"
00119 "channel,dstchannel,lastapp,lastdata, "
00120 "start,answer,end,"
00121 "duration,billsec,disposition,amaflags, "
00122 "accountcode"
00123 # if LOG_UNIQUEID
00124 ",uniqueid"
00125 # endif
00126 # if LOG_USERFIELD
00127 ",userfield"
00128 # endif
00129 ") VALUES ("
00130 "'%q', '%q', '%q', '%q', "
00131 "'%q', '%q', '%q', '%q', "
00132 "'%q', '%q', '%q', "
00133 "%d, %d, %d, %d, "
00134 "'%q'"
00135 # if LOG_UNIQUEID
00136 ",'%q'"
00137 # endif
00138 # if LOG_USERFIELD
00139 ",'%q'"
00140 # endif
00141 ")", NULL, NULL, &zErr,
00142 cdr->clid, cdr->src, cdr->dst, cdr->dcontext,
00143 cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,
00144 startstr, answerstr, endstr,
00145 cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags,
00146 cdr->accountcode
00147 # if LOG_UNIQUEID
00148 ,cdr->uniqueid
00149 # endif
00150 # if LOG_USERFIELD
00151 ,cdr->userfield
00152 # endif
00153 );
00154 if (res != SQLITE_BUSY && res != SQLITE_LOCKED)
00155 break;
00156 usleep(200);
00157 }
00158
00159 if (zErr) {
00160 ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00161 free(zErr);
00162 }
00163
00164 ast_mutex_unlock(&sqlite_lock);
00165 return res;
00166 }
00167
00168 static int unload_module(void)
00169 {
00170 if (db)
00171 sqlite_close(db);
00172 ast_cdr_unregister(name);
00173 return 0;
00174 }
00175
00176 static int load_module(void)
00177 {
00178 char *zErr;
00179 char fn[PATH_MAX];
00180 int res;
00181
00182
00183 snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR);
00184 db = sqlite_open(fn, 0660, &zErr);
00185 if (!db) {
00186 ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr);
00187 free(zErr);
00188 return -1;
00189 }
00190
00191
00192 res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL);
00193 if (res) {
00194 res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr);
00195 if (res) {
00196 ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr);
00197 free(zErr);
00198 goto err;
00199 }
00200
00201
00202 }
00203
00204 res = ast_cdr_register(name, ast_module_info->description, sqlite_log);
00205 if (res) {
00206 ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n");
00207 return -1;
00208 }
00209 return 0;
00210
00211 err:
00212 if (db)
00213 sqlite_close(db);
00214 return -1;
00215 }
00216
00217 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "SQLite CDR Backend");