Index: include/asterisk/res_odbc.h =================================================================== --- include/asterisk/res_odbc.h (revision 98980) +++ include/asterisk/res_odbc.h (working copy) @@ -38,6 +38,7 @@ ast_mutex_t lock; SQLHDBC con; /* ODBC Connection Handle */ struct odbc_class *parent; /* Information about the connection is protected */ + struct timeval last_used; unsigned int used:1; unsigned int up:1; AST_LIST_ENTRY(odbc_obj) list; Index: main/acl.c =================================================================== --- main/acl.c (revision 98980) +++ main/acl.c (working copy) @@ -329,6 +329,7 @@ struct ast_hostent ahp; struct hostent *hp; struct in_addr saddr; + int i, j; /* just use the bind address if it is nonzero */ if (ntohl(bindaddr.sin_addr.s_addr)) { @@ -348,9 +349,39 @@ } } ast_debug(3, "Trying to check A.ROOT-SERVERS.NET and get our IP address for that connection\n"); - /* A.ROOT-SERVERS.NET. */ + /* A.ROOT-SERVERS.NET. - This will succeed 99.999% of the time */ if (inet_aton("198.41.0.4", &saddr) && !ast_ouraddrfor(&saddr, ourip)) return 0; + /* Works on *BSD to find local link address */ + if (inet_aton("0.0.0.1", &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + /* Not really a network, but could be */ + if (inet_aton("169.254.0.1", &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + /* Test network */ + if (inet_aton("192.0.2.1", &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + /* Search bogons */ + for (i = 0; i < 256; i++) { + snprintf(ourhost, sizeof(ourhost), "192.168.%d.1", i); + if (inet_aton(ourhost, &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + } + for (i = 16; i < 32; i++) { + for (j = 0; j < 256; j++) { + snprintf(ourhost, sizeof(ourhost), "172.%d.%d.1", i, j); + if (inet_aton(ourhost, &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + } + } + for (i = 0; i < 256; i++) { + for (j = 0; j < 256; j++) { + snprintf(ourhost, sizeof(ourhost), "10.%d.%d.1", i, j); + if (inet_aton(ourhost, &saddr) && !ast_ouraddrfor(&saddr, ourip)) + return 0; + } + } + ast_debug(3, "Failed to find any IP address for us\n"); return -1; } Index: configs/res_odbc.conf.sample =================================================================== --- configs/res_odbc.conf.sample (revision 98980) +++ configs/res_odbc.conf.sample (working copy) @@ -19,6 +19,11 @@ ; statement should return a non-zero value in the first field of its first ; record. The default is "select 1". ;sanitysql => select 1 +; +; On some databases, the connection times out and a reconnection will be +; necessary. This setting configures the amount of time a connection +; may site idle (in seconds) before a reconnection will be attempted. +;idlecheck => 3600 [mysql2] Index: res/res_odbc.c =================================================================== --- res/res_odbc.c (revision 99017) +++ res/res_odbc.c (working copy) @@ -46,6 +46,7 @@ #include "asterisk/cli.h" #include "asterisk/lock.h" #include "asterisk/res_odbc.h" +#include "asterisk/time.h" struct odbc_class { @@ -61,6 +62,7 @@ unsigned int count:10; /* Running count of pooled connections */ unsigned int delme:1; /* Purge the class */ unsigned int backslash_is_escape:1; /* On this database, the backslash is a native escape sequence */ + unsigned int idlecheck; /* Recheck the connection if it is idle for this long */ AST_LIST_HEAD(, odbc_obj) odbc_obj; }; @@ -135,7 +137,8 @@ */ ast_odbc_sanity_check(obj); continue; - } + } else + obj->last_used = ast_tvnow(); break; } else if (attempt == 0) ast_odbc_sanity_check(obj); @@ -180,7 +183,8 @@ odbc_obj_connect(obj); res = SQLExecute(stmt); #endif - } + } else + obj->last_used = ast_tvnow(); return res; } @@ -229,6 +233,7 @@ char *cat; const char *dsn, *username, *password, *sanitysql; int enabled, pooling, limit, bse; + unsigned int idlecheck; int connect = 0, res = 0; struct ast_flags config_flags = { 0 }; @@ -249,7 +254,7 @@ /* Reset all to defaults for each class of odbc connections */ dsn = username = password = sanitysql = NULL; enabled = 1; - connect = 0; + connect = idlecheck = 0; pooling = 0; limit = 0; bse = 1; @@ -267,6 +272,8 @@ enabled = 0; break; } + } else if (!strcasecmp(v->name, "idlecheck")) { + sscanf(v->value, "%d", &idlecheck); } else if (!strcasecmp(v->name, "enabled")) { enabled = ast_true(v->value); } else if (!strcasecmp(v->name, "pre-connect")) { @@ -323,6 +330,7 @@ } new->backslash_is_escape = bse ? 1 : 0; + new->idlecheck = idlecheck; odbc_register_class(new, connect); ast_log(LOG_NOTICE, "Registered ODBC class '%s' dsn->[%s]\n", cat, dsn); @@ -508,7 +516,9 @@ if (obj && check) { ast_odbc_sanity_check(obj); - } + } else if (obj->parent->idlecheck > 0 && ast_tvdiff_sec(ast_tvnow(), obj->last_used) > obj->parent->idlecheck) + odbc_obj_connect(obj); + return obj; } @@ -576,6 +586,7 @@ } else { ast_log(LOG_NOTICE, "res_odbc: Connected to %s [%s]\n", obj->parent->name, obj->parent->dsn); obj->up = 1; + obj->last_used = ast_tvnow(); } ast_mutex_unlock(&obj->lock); @@ -590,6 +601,7 @@ char *cat; const char *dsn, *username, *password, *sanitysql; int enabled, pooling, limit, bse; + unsigned int idlecheck; int connect = 0, res = 0; struct ast_flags config_flags = { CONFIG_FLAG_FILEUNCHANGED }; @@ -615,7 +627,7 @@ /* Reset all to defaults for each class of odbc connections */ dsn = username = password = sanitysql = NULL; enabled = 1; - connect = 0; + connect = idlecheck = 0; pooling = 0; limit = 0; bse = 1; @@ -632,6 +644,8 @@ enabled = 0; break; } + } else if (!strcasecmp(v->name, "idlecheck")) { + sscanf(v->value, "%ud", &idlecheck); } else if (!strcasecmp(v->name, "enabled")) { enabled = ast_true(v->value); } else if (!strcasecmp(v->name, "pre-connect")) { @@ -720,6 +734,7 @@ } new->backslash_is_escape = bse; + new->idlecheck = idlecheck; if (class) { ast_log(LOG_NOTICE, "Refreshing ODBC class '%s' dsn->[%s]\n", cat, dsn);