| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Asterisk -- An open source telephony toolkit. | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-01-21 07:06:25 +00:00
										 |  |  |  * Copyright (C) 2004 - 2005, Holger Schurig | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * Ideas taken from other cdr_*.c files | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  |  * This program is free software, distributed under the terms of | 
					
						
							| 
									
										
										
										
											2005-09-14 20:46:50 +00:00
										 |  |  |  * the GNU General Public License Version 2. See the LICENSE file | 
					
						
							|  |  |  |  * at the top of the source tree. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 08:08:38 +00:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |  * \file | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * \brief Store CDR records in a SQLite database. | 
					
						
							| 
									
										
										
										
											2008-11-20 17:48:58 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * \author Holger Schurig <hs4233@mail.mn-solutions.de> | 
					
						
							| 
									
										
										
										
											2007-02-24 19:27:50 +00:00
										 |  |  |  * \extref SQLite http://www.sqlite.org/
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * See also | 
					
						
							|  |  |  |  * \arg \ref Config_cdr | 
					
						
							|  |  |  |  * \arg http://www.sqlite.org/
 | 
					
						
							| 
									
										
										
										
											2008-11-20 17:48:58 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  |  * Creates the database and table on-the-fly | 
					
						
							| 
									
										
										
										
											2005-11-06 15:09:47 +00:00
										 |  |  |  * \ingroup cdr_drivers | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \note This module has been marked deprecated in favor for cdr_sqlite3_custom | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-24 17:11:45 +00:00
										 |  |  | /*** MODULEINFO
 | 
					
						
							|  |  |  | 	<depend>sqlite</depend> | 
					
						
							|  |  |  |  ***/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | #include "asterisk.h"
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-06-07 18:54:56 +00:00
										 |  |  | ASTERISK_FILE_VERSION(__FILE__, "$Revision$") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | #include <sqlite.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-06-06 21:09:59 +00:00
										 |  |  | #include "asterisk/channel.h"
 | 
					
						
							|  |  |  | #include "asterisk/module.h"
 | 
					
						
							|  |  |  | #include "asterisk/utils.h"
 | 
					
						
							| 
									
										
										
										
											2007-11-20 23:29:33 +00:00
										 |  |  | #include "asterisk/paths.h"
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #define LOG_UNIQUEID    0
 | 
					
						
							|  |  |  | #define LOG_USERFIELD   0
 | 
					
						
							|  |  |  | #define LOG_HRTIME      0
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* When you change the DATE_FORMAT, be sure to change the CHAR(19) below to something else */ | 
					
						
							|  |  |  | #define DATE_FORMAT "%Y-%m-%d %T"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-26 08:45:11 +00:00
										 |  |  | static const char name[] = "sqlite"; | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | static sqlite* db = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | AST_MUTEX_DEFINE_STATIC(sqlite_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-10-26 13:03:17 +00:00
										 |  |  | /*! \brief SQL table format */ | 
					
						
							| 
									
										
										
										
											2009-05-21 21:13:09 +00:00
										 |  |  | static const char sql_create_table[] = "CREATE TABLE cdr (" | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | "	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)," | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #if LOG_HRTIME
 | 
					
						
							|  |  |  | "	duration	FLOAT," | 
					
						
							|  |  |  | "	billsec		FLOAT," | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | "	duration	INTEGER," | 
					
						
							|  |  |  | "	billsec		INTEGER," | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | "	disposition	INTEGER," | 
					
						
							|  |  |  | "	amaflags	INTEGER," | 
					
						
							|  |  |  | "	accountcode	VARCHAR(20)" | 
					
						
							|  |  |  | #if LOG_UNIQUEID
 | 
					
						
							| 
									
										
										
										
											2004-08-01 18:28:10 +00:00
										 |  |  | "	,uniqueid	VARCHAR(32)" | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | #if LOG_USERFIELD
 | 
					
						
							|  |  |  | "	,userfield	VARCHAR(255)" | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | ");"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-03 13:48:12 +00:00
										 |  |  | static void format_date(char *buffer, size_t length, struct timeval *when) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct ast_tm tm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_localtime(when, &tm, NULL); | 
					
						
							|  |  |  | 	ast_strftime(buffer, length, DATE_FORMAT, &tm); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | static int sqlite_log(struct ast_cdr *cdr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int res = 0; | 
					
						
							|  |  |  | 	char *zErr = 0; | 
					
						
							|  |  |  | 	char startstr[80], answerstr[80], endstr[80]; | 
					
						
							|  |  |  | 	int count; | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #if LOG_HRTIME
 | 
					
						
							|  |  |  | 	double hrbillsec = 0.0; | 
					
						
							|  |  |  | 	double hrduration; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_lock(&sqlite_lock); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-03 13:48:12 +00:00
										 |  |  | 	format_date(startstr, sizeof(startstr), &cdr->start); | 
					
						
							|  |  |  | 	format_date(answerstr, sizeof(answerstr), &cdr->answer); | 
					
						
							|  |  |  | 	format_date(endstr, sizeof(endstr), &cdr->end); | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #if LOG_HRTIME
 | 
					
						
							|  |  |  | 	if (!ast_tvzero(cdr->answer)) { | 
					
						
							|  |  |  | 		hrbillsec = (double) ast_tvdiff_us(cdr->end, cdr->answer) / 1000000.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	hrduration = (double) ast_tvdiff_us(cdr->end, cdr->start) / 1000000.0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	for(count=0; count<5; count++) { | 
					
						
							|  |  |  | 		res = sqlite_exec_printf(db, | 
					
						
							|  |  |  | 			"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', " | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #if LOG_HRTIME
 | 
					
						
							|  |  |  | 				"%f, %f, %d, %d, " | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 				"%d, %d, %d, %d, " | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 				"'%q'" | 
					
						
							|  |  |  | #				if LOG_UNIQUEID
 | 
					
						
							|  |  |  | 				",'%q'" | 
					
						
							|  |  |  | #				endif
 | 
					
						
							|  |  |  | #				if LOG_USERFIELD
 | 
					
						
							|  |  |  | 				",'%q'" | 
					
						
							|  |  |  | #				endif
 | 
					
						
							|  |  |  | 			")", NULL, NULL, &zErr, | 
					
						
							|  |  |  | 				cdr->clid, cdr->src, cdr->dst, cdr->dcontext, | 
					
						
							|  |  |  | 				cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata, | 
					
						
							|  |  |  | 				startstr, answerstr, endstr, | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #if LOG_HRTIME
 | 
					
						
							|  |  |  | 				hrduration, hrbillsec, cdr->disposition, cdr->amaflags, | 
					
						
							|  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 				cdr->duration, cdr->billsec, cdr->disposition, cdr->amaflags, | 
					
						
							| 
									
										
										
										
											2010-06-08 23:48:17 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 				cdr->accountcode | 
					
						
							|  |  |  | #				if LOG_UNIQUEID
 | 
					
						
							|  |  |  | 				,cdr->uniqueid | 
					
						
							|  |  |  | #				endif
 | 
					
						
							|  |  |  | #				if LOG_USERFIELD
 | 
					
						
							|  |  |  | 				,cdr->userfield | 
					
						
							|  |  |  | #				endif
 | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		if (res != SQLITE_BUSY && res != SQLITE_LOCKED) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		usleep(200); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-11-20 17:48:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	if (zErr) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(zErr); | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ast_mutex_unlock(&sqlite_lock); | 
					
						
							|  |  |  | 	return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int unload_module(void) | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	ast_cdr_unregister(name); | 
					
						
							| 
									
										
										
										
											2010-12-16 00:30:04 +00:00
										 |  |  | 	if (db) { | 
					
						
							|  |  |  | 		sqlite_close(db); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | static int load_module(void) | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	char *zErr; | 
					
						
							|  |  |  | 	char fn[PATH_MAX]; | 
					
						
							|  |  |  | 	int res; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-05 16:29:19 +00:00
										 |  |  | 	ast_log(LOG_NOTICE, "This module has been marked deprecated in favor of " | 
					
						
							|  |  |  | 		"using cdr_sqlite3_custom.\n"); | 
					
						
							| 
									
										
										
										
											2007-03-13 21:22:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	/* is the database there? */ | 
					
						
							| 
									
										
										
										
											2004-07-14 13:57:15 +00:00
										 |  |  | 	snprintf(fn, sizeof(fn), "%s/cdr.db", ast_config_AST_LOG_DIR); | 
					
						
							| 
									
										
										
										
											2006-12-21 19:44:20 +00:00
										 |  |  | 	db = sqlite_open(fn, AST_FILE_MODE, &zErr); | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	if (!db) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "cdr_sqlite: %s\n", zErr); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 		ast_free(zErr); | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* is the table there? */ | 
					
						
							|  |  |  | 	res = sqlite_exec(db, "SELECT COUNT(AcctId) FROM cdr;", NULL, NULL, NULL); | 
					
						
							|  |  |  | 	if (res) { | 
					
						
							|  |  |  | 		res = sqlite_exec(db, sql_create_table, NULL, NULL, &zErr); | 
					
						
							|  |  |  | 		if (res) { | 
					
						
							|  |  |  | 			ast_log(LOG_ERROR, "cdr_sqlite: Unable to create table 'cdr': %s\n", zErr); | 
					
						
							| 
									
										
										
										
											2007-06-06 21:20:11 +00:00
										 |  |  | 			ast_free(zErr); | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 			goto err; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		/* TODO: here we should probably create an index */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-11-20 17:48:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-21 02:11:39 +00:00
										 |  |  | 	res = ast_cdr_register(name, ast_module_info->description, sqlite_log); | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	if (res) { | 
					
						
							|  |  |  | 		ast_log(LOG_ERROR, "Unable to register SQLite CDR handling\n"); | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 		return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 	return AST_MODULE_LOAD_SUCCESS; | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | err: | 
					
						
							|  |  |  | 	if (db) | 
					
						
							|  |  |  | 		sqlite_close(db); | 
					
						
							| 
									
										
										
										
											2009-06-26 15:28:53 +00:00
										 |  |  | 	return AST_MODULE_LOAD_DECLINE; | 
					
						
							| 
									
										
										
										
											2004-07-08 08:29:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-20 19:35:02 +00:00
										 |  |  | AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SQLite CDR Backend", | 
					
						
							|  |  |  | 	.load = load_module, | 
					
						
							|  |  |  | 	.unload = unload_module, | 
					
						
							|  |  |  | 	.load_pri = AST_MODPRI_CDR_DRIVER, | 
					
						
							|  |  |  | ); |