2 * Asterisk -- A telephony toolkit for Linux.
6 * Brian K. West <brian@bkw.org>
8 * This program is free software, distributed under the terms of
9 * the GNU General Public License.
13 #include <sys/types.h>
14 #include <asterisk/config.h>
15 #include <asterisk/options.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/cdr.h>
18 #include <asterisk/module.h>
19 #include <asterisk/logger.h>
20 #include "../asterisk.h"
33 #define DATE_FORMAT "%Y-%m-%d %T"
35 static char *desc = "unixODBC CDR Backend";
36 static char *name = "unixODBC";
37 static char *config = "cdr_unixodbc.conf";
38 static char *dsn = NULL, *username = NULL, *password = NULL, *loguniqueid = NULL;
39 static int dsn_alloc = 0, username_alloc = 0, password_alloc = 0;
40 static int connected = 0;
42 static ast_mutex_t unixodbc_lock = AST_MUTEX_INITIALIZER;
44 extern int unixodbc_do_query(char *sqlcmd);
45 extern int unixodbc_init(void);
47 static SQLHENV ODBC_env = SQL_NULL_HANDLE; /* global ODBC Environment */
48 static int ODBC_res; /* global ODBC Result of Functions */
49 static SQLHDBC ODBC_con; /* global ODBC Connection Handle */
50 static SQLHSTMT ODBC_stmt; /* global ODBC Statement Handle */
52 static int unixodbc_log(struct ast_cdr *cdr)
56 long int ODBC_err, ODBC_id;
58 char ODBC_msg[200], ODBC_buffer[200], ODBC_stat[10];
63 char sqlcmd[2048], timestr[128];
65 ast_mutex_lock(&unixodbc_lock);
67 gettimeofday(&tv,NULL);
70 strftime(timestr,128,DATE_FORMAT,&tm);
72 memset(sqlcmd,0,2048);
74 if((strcmp(loguniqueid, "1") == 0) || (strcmp(loguniqueid, "yes") == 0))
76 sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,%i,%i,'%s','%s')", timestr, cdr->clid, cdr->src, cdr->dst, cdr->dcontext, cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, cdr->accountcode, cdr->uniqueid);
80 sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,%i,%i,'%s')", timestr, cdr->clid, cdr->src, cdr->dst, cdr->dcontext, cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, cdr->accountcode);
85 res = unixodbc_do_query(sqlcmd);
88 if(option_verbose > 3)
89 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Query FAILED Call not logged!\n");
90 res = unixodbc_init();
91 if(option_verbose > 3)
92 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Reconnecting to dsn %s\n", dsn);
95 if(option_verbose > 3)
96 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: %s has gone away!\n", dsn);
101 if(option_verbose > 3)
102 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Trying Query again!\n");
103 res = unixodbc_do_query(sqlcmd);
106 if(option_verbose > 3)
107 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Query FAILED Call not logged!\n");
114 if(option_verbose > 3)
115 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Reconnecting to dsn %s\n", dsn);
116 res = unixodbc_init();
119 if(option_verbose > 3)
121 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: %s has gone away!\n", dsn);
122 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Call not logged!\n");
127 if(option_verbose > 3)
128 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Trying Query again!\n");
129 res = unixodbc_do_query(sqlcmd);
132 if(option_verbose > 3)
133 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Query FAILED Call not logged!\n");
137 ast_mutex_unlock(&unixodbc_lock);
141 char *description(void)
146 static int unixodbc_unload_module(void)
150 if(option_verbose > 3)
151 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Disconnecting from %s\n", dsn);
152 SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
153 SQLDisconnect(ODBC_con);
154 SQLFreeHandle(SQL_HANDLE_DBC, ODBC_con);
155 SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
158 if (dsn && dsn_alloc)
160 if(option_verbose > 3)
161 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: free dsn\n");
166 if (username && username_alloc)
168 if(option_verbose > 3)
169 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: free username\n");
174 if (password && password_alloc)
176 if(option_verbose > 3)
177 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: free password\n");
182 ast_cdr_unregister(name);
186 static int unixodbc_load_module(void)
189 struct ast_config *cfg;
190 struct ast_variable *var;
193 cfg = ast_load(config);
196 ast_log(LOG_WARNING, "cdr_unixodbc: Unable to load config for unixODBC CDR's: %s\n", config);
200 var = ast_variable_browse(cfg, "global");
202 /* nothing configured */
206 tmp = ast_variable_retrieve(cfg,"global","dsn");
209 dsn = malloc(strlen(tmp) + 1);
217 ast_log(LOG_ERROR,"cdr_unixodbc: Out of memory error.\n");
223 ast_log(LOG_WARNING,"cdr_unixodbc: dsn not specified. Assuming asteriskdb\n");
227 tmp = ast_variable_retrieve(cfg,"global","username");
230 username = malloc(strlen(tmp) + 1);
231 if (username != NULL)
234 strcpy(username,tmp);
238 ast_log(LOG_ERROR,"cdr_unixodbc: Out of memory error.\n");
244 ast_log(LOG_WARNING,"cdr_unixodbc: username not specified. Assuming root\n");
248 tmp = ast_variable_retrieve(cfg,"global","password");
251 password = malloc(strlen(tmp) + 1);
252 if (password != NULL)
255 strcpy(password,tmp);
259 ast_log(LOG_ERROR,"cdr_unixodbc: Out of memory error.\n");
265 ast_log(LOG_WARNING,"cdr_unixodbc: database password not specified. Assuming blank\n");
269 tmp = ast_variable_retrieve(cfg,"global","loguniqueid");
272 loguniqueid = malloc(strlen(tmp) + 1);
273 if (loguniqueid != NULL)
275 strcpy(loguniqueid,tmp);
276 ast_log(LOG_WARNING,"cdr_unixodbc: Logging uniqueid\n");
280 ast_log(LOG_ERROR,"cdr_unixodbc: Not logging uniqueid\n");
285 ast_log(LOG_WARNING,"cdr_unixodbc: Not logging uniqueid\n");
290 if(option_verbose > 3)
292 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: dsn is %s\n",dsn);
293 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: username is %s\n",username);
294 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: password is [secret]\n");
298 res = unixodbc_init();
301 ast_log(LOG_ERROR, "cdr_unixodbc: Unable to connect to datasource: %s\n", dsn);
302 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Unable to connect to datasource: %s\n", dsn);
305 res = ast_cdr_register(name, desc, unixodbc_log);
308 ast_log(LOG_ERROR, "cdr_unixodbc: Unable to register unixODBC CDR handling\n");
313 int unixodbc_do_query(char *sqlcmd)
317 char ODBC_msg[200], ODBC_stat[10];
319 ODBC_res = SQLAllocHandle(SQL_HANDLE_STMT, ODBC_con, &ODBC_stmt);
321 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
323 if(option_verbose > 3)
324 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Failure in AllocStatement %d\n", ODBC_res);
325 SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
326 SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
331 ODBC_res = SQLPrepare(ODBC_stmt, sqlcmd, SQL_NTS);
333 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
335 if(option_verbose > 3)
336 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error in PREPARE %d\n", ODBC_res);
337 SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
338 SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
342 ODBC_res = SQLExecute(ODBC_stmt);
344 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
346 if(option_verbose > 3)
347 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error in Query %d\n", ODBC_res);
348 SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
349 SQLFreeHandle(SQL_HANDLE_STMT, ODBC_stmt);
355 if(option_verbose > 3)
356 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Query Successful!\n");
366 char ODBC_msg[200], ODBC_stat[10];
368 if ( ODBC_env == SQL_NULL_HANDLE || connected == 0)
370 ODBC_res = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &ODBC_env);
372 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
374 if(option_verbose > 3)
375 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error AllocHandle\n");
380 ODBC_res = SQLSetEnvAttr(ODBC_env, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
382 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
384 if(option_verbose > 3)
385 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error SetEnv\n");
386 SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
391 ODBC_res = SQLAllocHandle(SQL_HANDLE_DBC, ODBC_env, &ODBC_con);
393 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
395 if(option_verbose > 3)
396 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error AllocHDB %d\n", ODBC_res);
397 SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
402 SQLSetConnectAttr(ODBC_con, SQL_LOGIN_TIMEOUT, (SQLPOINTER *)10, 0);
405 ODBC_res = SQLConnect(ODBC_con, (SQLCHAR*)dsn, SQL_NTS, (SQLCHAR*)username, SQL_NTS, (SQLCHAR*)password, SQL_NTS);
407 if((ODBC_res != SQL_SUCCESS) && (ODBC_res != SQL_SUCCESS_WITH_INFO))
409 if(option_verbose > 3)
410 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Error SQLConnect %d\n", ODBC_res);
411 SQLGetDiagRec(SQL_HANDLE_DBC, ODBC_con, 1, ODBC_stat, &ODBC_err, ODBC_msg, 100, &ODBC_mlen);
412 SQLFreeHandle(SQL_HANDLE_ENV, ODBC_env);
418 if(option_verbose > 3)
419 ast_verbose( VERBOSE_PREFIX_4 "cdr_unixodbc: Connected to %s\n", dsn);
426 int load_module(void)
428 return unixodbc_load_module();
431 int unload_module(void)
433 return unixodbc_unload_module();
438 unixodbc_unload_module();
439 return unixodbc_load_module();
449 return ASTERISK_GPL_KEY;