Index: cdr_addon_mysql.c =================================================================== RCS file: /usr/cvsroot/asterisk-addons/cdr_addon_mysql.c,v retrieving revision 1.5 diff -r1.5 cdr_addon_mysql.c 10a11,16 > * Modified August 6, 2005 > * Joseph Benden > * Added mysql connection timeout parameter > * Added an automatic reconnect as to not lose a cdr record > * Cleaned up the original code to match the coding guidelines > * 24d29 < #include "asterisk.h" 35a41,44 > #include > #include > #include > 41,42c50,51 < static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *dbsock = NULL; < static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbsock_alloc = 0; --- > static char *hostname = NULL, *dbname = NULL, *dbuser = NULL, *password = NULL, *dbsock = NULL, *dbtable = NULL; > static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbsock_alloc = 0, dbtable_alloc = 0; 48a58 > static unsigned int timeout = 0; 71a82,83 > if (dbtable && *dbtable) > snprintf(status2, 99, " using table %s", dbtable); 105a118,121 > char *clid=NULL, *dcontext=NULL, *channel=NULL, *dstchannel=NULL, *lastapp=NULL, *lastdata=NULL; > #ifdef MYSQL_LOGUNIQUEID > char *uniqueid=NULL; > #endif 109c125 < memset(sqlcmd,0,2048); --- > memset(sqlcmd, 0, 2048); 111,112c127,128 < localtime_r(&cdr->start.tv_sec,&tm); < strftime(timestr,128,DATE_FORMAT,&tm); --- > localtime_r(&cdr->start.tv_sec, &tm); > strftime(timestr, 128, DATE_FORMAT, &tm); 114c130,131 < if ((!connected) && (hostname || dbsock) && dbuser && password && dbname) { --- > db_reconnect: > if ((!connected) && (hostname || dbsock) && dbuser && password && dbname && dbtable ) { 116a134,137 > /* Add option to quickly timeout the connection */ > if (timeout && mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout)!=0) { > ast_log(LOG_ERROR, "cdr_mysql: mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql)); > } 122c143,144 < ast_log(LOG_ERROR, "cdr_mysql: cannot connect to database server %s. Call will not be logged\n", hostname); --- > ast_log(LOG_ERROR, "cdr_mysql: cannot connect to database server %s.\n", hostname); > connected = 0; 132c154,155 < ast_log(LOG_ERROR, "cdr_mysql: Server has gone away\n"); --- > case CR_SERVER_LOST: > ast_log(LOG_WARNING, "cdr_mysql: Server has gone away. Attempting to reconnect.\n"); 135c158 < ast_log(LOG_ERROR, "cdr_mysql: Unknown connection error\n"); --- > ast_log(LOG_ERROR, "cdr_mysql: Unknown connection error: (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql)); 136a160 > goto db_reconnect; 140,144c164 < if (connected) { < char *clid=NULL, *dcontext=NULL, *channel=NULL, *dstchannel=NULL, *lastapp=NULL, *lastdata=NULL; < #ifdef MYSQL_LOGUNIQUEID < char *uniqueid=NULL; < #endif --- > /* Maximum space needed would be if all characters needed to be escaped, plus a trailing NULL */ 146,158c166,184 < /* Maximum space needed would be if all characters needed to be escaped, plus a trailing NULL */ < if ((clid = alloca(strlen(cdr->clid) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, clid, cdr->clid, strlen(cdr->clid)); < if ((dcontext = alloca(strlen(cdr->dcontext) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, dcontext, cdr->dcontext, strlen(cdr->dcontext)); < if ((channel = alloca(strlen(cdr->channel) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, channel, cdr->channel, strlen(cdr->channel)); < if ((dstchannel = alloca(strlen(cdr->dstchannel) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, dstchannel, cdr->dstchannel, strlen(cdr->dstchannel)); < if ((lastapp = alloca(strlen(cdr->lastapp) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, lastapp, cdr->lastapp, strlen(cdr->lastapp)); < if ((lastdata = alloca(strlen(cdr->lastdata) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, lastdata, cdr->lastdata, strlen(cdr->lastdata)); --- > /* WARNING: This code previously used mysql_real_escape_string, but the use of said function > requires an active connection to a database. If we are not connected, then this function > cannot be used. This is a problem since we need to store off the SQL statement into our > spool file for later restoration. > > So the question is, what's the best way to handle this? This works for now. > */ > if ((clid = alloca(strlen(cdr->clid) * 2 + 1)) != NULL) > mysql_escape_string(clid, cdr->clid, strlen(cdr->clid)); > if ((dcontext = alloca(strlen(cdr->dcontext) * 2 + 1)) != NULL) > mysql_escape_string(dcontext, cdr->dcontext, strlen(cdr->dcontext)); > if ((channel = alloca(strlen(cdr->channel) * 2 + 1)) != NULL) > mysql_escape_string(channel, cdr->channel, strlen(cdr->channel)); > if ((dstchannel = alloca(strlen(cdr->dstchannel) * 2 + 1)) != NULL) > mysql_escape_string(dstchannel, cdr->dstchannel, strlen(cdr->dstchannel)); > if ((lastapp = alloca(strlen(cdr->lastapp) * 2 + 1)) != NULL) > mysql_escape_string(lastapp, cdr->lastapp, strlen(cdr->lastapp)); > if ((lastdata = alloca(strlen(cdr->lastdata) * 2 + 1)) != NULL) > mysql_escape_string(lastdata, cdr->lastdata, strlen(cdr->lastdata)); 160,161c186,187 < if ((uniqueid = alloca(strlen(cdr->uniqueid) * 2 + 1)) != NULL) < mysql_real_escape_string(&mysql, uniqueid, cdr->uniqueid, strlen(cdr->uniqueid)); --- > if ((uniqueid = alloca(strlen(cdr->uniqueid) * 2 + 1)) != NULL) > mysql_escape_string(uniqueid, cdr->uniqueid, strlen(cdr->uniqueid)); 162a189,190 > if (userfield && ((userfielddata = alloca(strlen(cdr->userfield) * 2 + 1)) != NULL)) > mysql_escape_string(userfielddata, cdr->userfield, strlen(cdr->userfield)); 164,167c192 < if (userfield && ((userfielddata = alloca(strlen(cdr->userfield) * 2 + 1)) != NULL)) < mysql_real_escape_string(&mysql, userfielddata, cdr->userfield, strlen(cdr->userfield)); < < /* Check for all alloca failures above at once */ --- > /* Check for all alloca failures above at once */ 169c194 < if ((!clid) || (!dcontext) || (!channel) || (!dstchannel) || (!lastapp) || (!lastdata) || (!uniqueid)) { --- > if ((!clid) || (!dcontext) || (!channel) || (!dstchannel) || (!lastapp) || (!lastdata) || (!uniqueid)) { 171c196 < if ((!clid) || (!dcontext) || (!channel) || (!dstchannel) || (!lastapp) || (!lastdata)) { --- > if ((!clid) || (!dcontext) || (!channel) || (!dstchannel) || (!lastapp) || (!lastdata)) { 173,176c198,201 < ast_log(LOG_ERROR, "cdr_mysql: Out of memory error (insert fails)\n"); < ast_mutex_unlock(&mysql_lock); < return -1; < } --- > ast_log(LOG_ERROR, "cdr_mysql: Out of memory error (insert fails)\n"); > ast_mutex_unlock(&mysql_lock); > return -1; > } 178c203 < ast_log(LOG_DEBUG,"cdr_mysql: inserting a CDR record.\n"); --- > ast_log(LOG_DEBUG, "cdr_mysql: inserting a CDR record.\n"); 180,181c205 < if (userfield && userfielddata) < { --- > if (userfield && userfielddata) { 183c207 < sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid, userfielddata); --- > sprintf(sqlcmd, "INSERT INTO %s (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,uniqueid,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s','%s')", dbtable, timestr, clid, cdr->src, cdr->dst, dcontext, channel, dstchannel, lastapp, lastdata, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), cdr->amaflags, cdr->accountcode, uniqueid, userfielddata); 185c209 < sprintf(sqlcmd,"INSERT INTO cdr (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s')",timestr,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, userfielddata); --- > sprintf(sqlcmd, "INSERT INTO %s (calldate,clid,src,dst,dcontext,channel,dstchannel,lastapp,lastdata,duration,billsec,disposition,amaflags,accountcode,userfield) VALUES ('%s','%s','%s','%s','%s', '%s','%s','%s','%s',%i,%i,'%s',%i,'%s','%s')", dbtable, timestr, clid, cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), cdr->amaflags, cdr->accountcode, userfielddata); 187,189c211 < } < else < { --- > } else { 191c213 < 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,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode, uniqueid); --- > sprintf(sqlcmd, "INSERT INTO %s (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')", dbtable, timestr, clid, cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), cdr->amaflags, cdr->accountcode, uniqueid); 193c215 < 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,clid,cdr->src, cdr->dst, dcontext,channel, dstchannel, lastapp, lastdata,cdr->duration,cdr->billsec,ast_cdr_disp2str(cdr->disposition),cdr->amaflags, cdr->accountcode); --- > sprintf(sqlcmd, "INSERT INTO %s (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')", dbtable, timestr, clid, cdr->src, cdr->dst, dcontext, channel, dstchannel, lastapp, lastdata, cdr->duration, cdr->billsec, ast_cdr_disp2str(cdr->disposition), cdr->amaflags, cdr->accountcode); 195c217 < } --- > } 197c219 < ast_log(LOG_DEBUG,"cdr_mysql: SQL command as follows: %s\n",sqlcmd); --- > ast_log(LOG_DEBUG, "cdr_mysql: SQL command as follows: %s\n", sqlcmd); 198a221 > if (connected) { 200,202c223,224 < ast_log(LOG_ERROR,"Failed to insert into database."); < ast_mutex_unlock(&mysql_lock); < return -1; --- > ast_log(LOG_ERROR, "mysql_cdr: Failed to insert into database: (%d) %s", mysql_errno(&mysql), mysql_error(&mysql)); > connected = 0; 244a267,271 > if (dbtable && dbtable_alloc) { > free(dbtable); > dbtable = NULL; > dbtable_alloc = 0; > } 261a289,291 > #if (ASTERISK_VERSION_NUM > 10199) > cfg = ast_config_load(config); > #else 262a293 > #endif 274c305 < tmp = ast_variable_retrieve(cfg,"global","hostname"); --- > tmp = ast_variable_retrieve(cfg, "global", "hostname"); 279c310 < strcpy(hostname,tmp); --- > strcpy(hostname, tmp); 281c312 < ast_log(LOG_ERROR,"Out of memory error.\n"); --- > ast_log(LOG_ERROR, "Out of memory error.\n"); 285c316 < ast_log(LOG_WARNING,"MySQL server hostname not specified. Assuming localhost\n"); --- > ast_log(LOG_WARNING, "MySQL server hostname not specified. Assuming localhost\n"); 289c320 < tmp = ast_variable_retrieve(cfg,"global","dbname"); --- > tmp = ast_variable_retrieve(cfg, "global", "dbname"); 294c325 < strcpy(dbname,tmp); --- > strcpy(dbname, tmp); 296c327 < ast_log(LOG_ERROR,"Out of memory error.\n"); --- > ast_log(LOG_ERROR, "Out of memory error.\n"); 300c331 < ast_log(LOG_WARNING,"MySQL database not specified. Assuming asteriskcdrdb\n"); --- > ast_log(LOG_WARNING, "MySQL database not specified. Assuming asteriskcdrdb\n"); 304c335 < tmp = ast_variable_retrieve(cfg,"global","user"); --- > tmp = ast_variable_retrieve(cfg, "global", "user"); 309c340 < strcpy(dbuser,tmp); --- > strcpy(dbuser, tmp); 311c342 < ast_log(LOG_ERROR,"Out of memory error.\n"); --- > ast_log(LOG_ERROR, "Out of memory error.\n"); 315c346 < ast_log(LOG_WARNING,"MySQL database user not specified. Assuming root\n"); --- > ast_log(LOG_WARNING, "MySQL database user not specified. Assuming root\n"); 319c350 < tmp = ast_variable_retrieve(cfg,"global","sock"); --- > tmp = ast_variable_retrieve(cfg, "global", "sock"); 324c355 < strcpy(dbsock,tmp); --- > strcpy(dbsock, tmp); 326c357 < ast_log(LOG_ERROR,"Out of memory error.\n"); --- > ast_log(LOG_ERROR, "Out of memory error.\n"); 330c361 < ast_log(LOG_WARNING,"MySQL database sock file not specified. Using default\n"); --- > ast_log(LOG_WARNING, "MySQL database sock file not specified. Using default\n"); 334c365,380 < tmp = ast_variable_retrieve(cfg,"global","password"); --- > tmp = ast_variable_retrieve(cfg, "global", "table"); > if (tmp) { > dbtable = malloc(strlen(tmp) + 1); > if (dbtable != NULL) { > dbtable_alloc = 1; > strcpy(dbtable, tmp); > } else { > ast_log(LOG_ERROR, "Out of memory error.\n"); > return -1; > } > } else { > ast_log(LOG_NOTICE, "MySQL database table not specified. Assuming \"cdr\"\n"); > dbtable = "cdr"; > } > > tmp = ast_variable_retrieve(cfg, "global", "password"); 339c385 < strcpy(password,tmp); --- > strcpy(password, tmp); 341c387 < ast_log(LOG_ERROR,"Out of memory error.\n"); --- > ast_log(LOG_ERROR, "Out of memory error.\n"); 345c391 < ast_log(LOG_WARNING,"MySQL database password not specified. Assuming blank\n"); --- > ast_log(LOG_WARNING, "MySQL database password not specified. Assuming blank\n"); 349c395 < tmp = ast_variable_retrieve(cfg,"global","port"); --- > tmp = ast_variable_retrieve(cfg, "global", "port"); 351,352c397,398 < if (sscanf(tmp,"%d",&dbport) < 1) { < ast_log(LOG_WARNING,"Invalid MySQL port number. Using default\n"); --- > if (sscanf(tmp,"%d", &dbport) < 1) { > ast_log(LOG_WARNING, "Invalid MySQL port number. Using default\n"); 355a402,409 > > tmp = ast_variable_retrieve(cfg, "global", "timeout"); > if (tmp) { > if (sscanf(tmp,"%d", &timeout) < 1) { > ast_log(LOG_WARNING, "Invalid MySQL timeout number. Using default\n"); > timeout = 0; > } > } 357c411 < tmp = ast_variable_retrieve(cfg,"global","userfield"); --- > tmp = ast_variable_retrieve(cfg, "global", "userfield"); 359,360c413,414 < if (sscanf(tmp,"%d",&userfield) < 1) { < ast_log(LOG_WARNING,"Invalid MySQL configurtation file\n"); --- > if (sscanf(tmp, "%d", &userfield) < 1) { > ast_log(LOG_WARNING, "Invalid MySQL configurtation file\n"); 364c418,421 < --- > > #if (ASTERISK_VERSION_NUM > 10199) > ast_config_destroy(cfg); > #else 365a423 > #endif 367,368c425,427 < ast_log(LOG_DEBUG,"cdr_mysql: got hostname of %s\n",hostname); < ast_log(LOG_DEBUG,"cdr_mysql: got port of %d\n",dbport); --- > ast_log(LOG_DEBUG, "cdr_mysql: got hostname of %s\n", hostname); > ast_log(LOG_DEBUG, "cdr_mysql: got port of %d\n", dbport); > ast_log(LOG_DEBUG, "cdr_mysql: got a timeout of %d\n", timeout); 370,374c429,433 < ast_log(LOG_DEBUG,"cdr_mysql: got sock file of %s\n",dbsock); < 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); < --- > ast_log(LOG_DEBUG, "cdr_mysql: got sock file of %s\n", dbsock); > 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); > 376a436,439 > if (timeout && mysql_options(&mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *)&timeout)!=0) { > ast_log(LOG_ERROR, "cdr_mysql: mysql_options returned (%d) %s\n", mysql_errno(&mysql), mysql_error(&mysql)); > } > 382c445 < ast_log(LOG_DEBUG,"Successfully connected to MySQL database.\n"); --- > ast_log(LOG_DEBUG, "Successfully connected to MySQL database.\n"); 409a473,475 > int ret; > > ast_mutex_lock(&mysql_lock); 411c477,480 < return my_load_module(); --- > ret = my_load_module(); > ast_mutex_unlock(&mysql_lock); > > return ret;