Skip to content
Snippets Groups Projects
cdr_mysql.c 6.44 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    /*
     * Asterisk -- A telephony toolkit for Linux.
     *
     * MySQL CDR logger 
     * 
     * James Sharp <jsharp@psychoses.org>
     *
    
     * Modified August 2003
     * Tilghman Lesher <asterisk__cdr__cdr_mysql__200308@the-tilghman.com>
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     * This program is free software, distributed under the terms of
     * the GNU General Public License.
     *
     */
    
    
    #include <sys/types.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <asterisk/config.h>
    #include <asterisk/options.h>
    #include <asterisk/channel.h>
    #include <asterisk/cdr.h>
    #include <asterisk/module.h>
    #include <asterisk/logger.h>
    #include "../asterisk.h"
    
    #include <stdio.h>
    #include <string.h>
    
    #include <stdlib.h>
    #include <unistd.h>
    #include <time.h>
    
    #include <mysql.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <mysql/errmsg.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    #define DATE_FORMAT "%Y-%m-%d %T"
    
    static char *desc = "MySQL CDR Backend";
    static char *name = "mysql";
    static char *config = "cdr_mysql.conf";
    
    Mark Spencer's avatar
    Mark Spencer committed
    static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL;
    
    static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int connected = 0;
    
    static ast_mutex_t mysql_lock = AST_MUTEX_INITIALIZER;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static MYSQL mysql;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static int mysql_log(struct ast_cdr *cdr)
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct tm tm;
    	struct timeval tv;
    	char sqlcmd[2048], timestr[128];
    	time_t t;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	memset(sqlcmd,0,2048);
    
    	gettimeofday(&tv,NULL);
    	t = tv.tv_sec;
    	localtime_r(&t,&tm);
    	strftime(timestr,128,DATE_FORMAT,&tm);
    
    	if ((!connected) && hostname && dbuser && password && dbname) {
    		/* Attempt to connect */
    		mysql_init(&mysql);
    		if (mysql_real_connect(&mysql, hostname, dbuser, password, dbname, 0, NULL, 0)) {
    			connected = 1;
    		} else {
    
    			ast_log(LOG_ERROR, "cdr_mysql: cannot connect to database server %s.  Call will not be logged\n", hostname);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    	} else {
    		/* Long connection - ping the server */
    		int error;
    		if ((error = mysql_ping(&mysql))) {
    			connected = 0;
    			switch (error) {
    				case CR_SERVER_GONE_ERROR:
    					ast_log(LOG_ERROR, "cdr_mysql: Server has gone away\n");
    					break;
    				default:
    					ast_log(LOG_ERROR, "cdr_mysql: Unknown connection error\n");
    			}
    		}
    	}
    
    	if (connected) {
    		ast_log(LOG_DEBUG,"cdr_mysql: inserting a CDR record.\n");
    
    #ifdef MYSQL_LOGUNIQUEID
    
    Mark Spencer's avatar
    Mark Spencer committed
    		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,'%s',%i,'%s','%s')",timestr,cdr->clid,cdr->src, cdr->dst, cdr->dcontext,cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, cdr->uniqueid);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		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,'%s',%i,'%s')",timestr,cdr->clid,cdr->src, cdr->dst, cdr->dcontext,cdr->channel, cdr->dstchannel, cdr->lastapp, cdr->lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode);
    
    #endif  
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_DEBUG,"cdr_mysql: SQL command as follows:  %s\n",sqlcmd);
    	
    		if (mysql_real_query(&mysql,sqlcmd,strlen(sqlcmd))) {
    			ast_log(LOG_ERROR,"Failed to insert into database.");
    
    Mark Spencer's avatar
    Mark Spencer committed
    			return -1;
    		}
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    char *description(void)
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return desc;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    int unload_module(void)
    { 
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (connected) {
    		mysql_close(&mysql);
    		connected = 0;
    	}
    
    	if (hostname && hostname_alloc) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		free(hostname);
    		hostname = NULL;
    
    		hostname_alloc = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	if (dbname && dbname_alloc) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		free(dbname);
    		dbname = NULL;
    
    		dbname_alloc = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	if (dbuser && dbuser_alloc) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		free(dbuser);
    		dbuser = NULL;
    
    		dbuser_alloc = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	if (password && password_alloc) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		free(password);
    		password = NULL;
    
    		password_alloc = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    	ast_cdr_unregister(name);
    	return 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    int load_module(void)
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int res;
    	struct ast_config *cfg;
    	struct ast_variable *var;
    	char *tmp;
    
    	cfg = ast_load(config);
    	if (!cfg) {
    		ast_log(LOG_WARNING, "Unable to load config for mysql CDR's: %s\n", config);
    		return 0;
    	}
    	
    	var = ast_variable_browse(cfg, "global");
    	if (!var) {
    		/* nothing configured */
    		return 0;
    	}
    
    	tmp = ast_variable_retrieve(cfg,"global","hostname");
    
    	if (tmp) {
    		hostname = malloc(strlen(tmp) + 1);
    		if (hostname != NULL) {
    			hostname_alloc = 1;
    			strcpy(hostname,tmp);
    		} else {
    			ast_log(LOG_ERROR,"Out of memory error.\n");
    			return -1;
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		ast_log(LOG_WARNING,"MySQL server hostname not specified.  Assuming localhost");
    		hostname = "localhost";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	tmp = ast_variable_retrieve(cfg,"global","dbname");
    
    	if (tmp) {
    		dbname = malloc(strlen(tmp) + 1);
    		if (dbname != NULL) {
    			dbname_alloc = 1;
    			strcpy(dbname,tmp);
    		} else {
    			ast_log(LOG_ERROR,"Out of memory error.\n");
    			return -1;
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		ast_log(LOG_WARNING,"MySQL database not specified.  Assuming asteriskcdrdb\n");
    		dbname = "asteriskcdrdb";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	tmp = ast_variable_retrieve(cfg,"global","user");
    
    	if (tmp) {
    		dbuser = malloc(strlen(tmp) + 1);
    		if (dbuser != NULL) {
    			dbuser_alloc = 1;
    			strcpy(dbuser,tmp);
    		} else {
    			ast_log(LOG_ERROR,"Out of memory error.\n");
    			return -1;
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		ast_log(LOG_WARNING,"MySQL database user not specified.  Assuming root\n");
    		dbuser = "root";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	tmp = ast_variable_retrieve(cfg,"global","password");
    
    	if (tmp) {
    		password = malloc(strlen(tmp) + 1);
    		if (password != NULL) {
    			password_alloc = 1;
    			strcpy(password,tmp);
    		} else {
    			ast_log(LOG_ERROR,"Out of memory error.\n");
    			return -1;
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		ast_log(LOG_WARNING,"MySQL database password not specified.  Assuming blank\n");
    		password = "";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	ast_destroy(cfg);
    
    	ast_log(LOG_DEBUG,"cdr_mysql: got hostname of %s\n",hostname);
    	ast_log(LOG_DEBUG,"cdr_mysql: got user of %s\n",dbuser);
    	ast_log(LOG_DEBUG,"cdr_mysql: got dbname of %s\n",dbname);
    	ast_log(LOG_DEBUG,"cdr_mysql: got password of %s\n",password);
    
    	mysql_init(&mysql);
    
    	if (!mysql_real_connect(&mysql, hostname, dbuser, password, dbname, 0, NULL, 0)) {
    		ast_log(LOG_ERROR, "Failed to connect to mysql database %s on %s.\n", dbname, hostname);
    		connected = 0;
    	} else {
    		ast_log(LOG_DEBUG,"Successfully connected to MySQL database.\n");
    		connected = 1;
    	}
    
    	res = ast_cdr_register(name, desc, mysql_log);
    	if (res) {
    		ast_log(LOG_ERROR, "Unable to register MySQL CDR handling\n");
    	}
    	return res;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    int reload(void)
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	unload_module();
    	return load_module();
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    int usecount(void)
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return connected;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    char *key()
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return ASTERISK_GPL_KEY;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }