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