Index: channels/chan_sip.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v retrieving revision 1.311 diff -u -r1.311 chan_sip.c --- channels/chan_sip.c 16 Mar 2004 17:07:51 -0000 1.311 +++ channels/chan_sip.c 18 Mar 2004 01:11:15 -0000 @@ -56,6 +56,10 @@ #ifdef MYSQL_FRIENDS #include +#define SQL_FRIENDS 1 +#elif defined(POSTGRES_FRIENDS) +#include +#define SQL_FRIENDS 1 #endif #ifndef IPTOS_MINCOST @@ -85,13 +89,19 @@ #define DEFAULT_RETRANS 1000 /* How frequently to retransmit */ #define MAX_RETRANS 5 /* Try only 5 times for retransmissions */ +#ifdef SQL_FRIENDS +static char dbuser[80]; +static char dbpass[80]; +static char dbhost[80]; +static char dbname[80]; +#endif + #ifdef MYSQL_FRIENDS static ast_mutex_t mysqllock = AST_MUTEX_INITIALIZER; static MYSQL *mysql; -static char mydbuser[80]; -static char mydbpass[80]; -static char mydbhost[80]; -static char mydbname[80]; +#elif defined(POSTGRES_FRIENDS) +static ast_mutex_t pgsqllock = AST_MUTEX_INITIALIZER; +static PGconn *pgsql; #endif static char *desc = "Session Initiation Protocol (SIP)"; @@ -786,7 +796,112 @@ } return p; } -#endif /* MYSQL_FRIENDS */ + +#elif defined(POSTGRES_FRIENDS) + +static void pgsql_update_peer(char *peer, struct sockaddr_in *sin, char *username, int expiry) +{ + if (pgsql && sin && peer && (strlen(peer) < 128)) { + char query[512]; + char *name; + char *uname; + time_t nowtime; + PGresult *res; + + name = alloca(strlen(peer) * 2 + 1); + uname = alloca(strlen(username) * 2 + 1); + time(&nowtime); + PQescapeString(name, peer, strlen(peer)); + PQescapeString(uname, username, strlen(username)); + snprintf(query, sizeof(query), "UPDATE sipfriends SET ipaddr='%s', port='%d', regseconds='%ld', username='%s' WHERE name='%s'", + inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), nowtime + expiry, uname, name); + ast_mutex_lock(&pgsqllock); + res = PQexec(pgsql, query); + + if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) { + ast_log(LOG_WARNING, "Unable to update database\n"); + } + + PQclear(res); + + ast_mutex_unlock(&pgsqllock); + } +} + +static struct sip_peer *pgsql_peer(char *peer, struct sockaddr_in *sin) +{ + struct sip_peer *p; + int success = 0; + + p = malloc(sizeof(struct sip_peer)); + memset(p, 0, sizeof(struct sip_peer)); + + if (pgsql && (!peer || (strlen(peer) < 128))) { + char query[512]; + char *name = NULL; + int port; + time_t regseconds, nowtime; + PGresult *result; + + if (peer) { + name = alloca(strlen(peer) * 2 + 1); + PQescapeString(name, peer, strlen(peer)); + } + if (sin) + snprintf(query, sizeof(query), "SELECT secret,name,context,username,ipaddr,port,regseconds FROM sipfriends WHERE ipaddr='%s' AND port='%d'", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); + else + snprintf(query, sizeof(query), "SELECT secret,name,context,username,ipaddr,port,regseconds FROM sipfriends WHERE name='%s'", name); + + ast_mutex_lock(&pgsqllock); + result = PQexec(pgsql, query); + if (result && (PQresultStatus(result) == PGRES_TUPLES_OK)) { + if (PQntuples(result) >= 1) { + success = 1; + if (PQntuples(result) > 1) { + ast_log(LOG_WARNING, "Found more than one SIP peer, ignoring subsequent matches.."); + } + strncpy(p->secret,PQgetvalue(result,0,0),sizeof(p->secret)); + strncpy(p->name,PQgetvalue(result,0,1),sizeof(p->name)); + strncpy(p->context,PQgetvalue(result,0,2),sizeof(p->context)); + strncpy(p->username,PQgetvalue(result,0,3),sizeof(p->username)); + inet_aton(PQgetvalue(result,0,4),&p->addr.sin_addr); + if (sscanf(PQgetvalue(result,0,5),"%i",&port) != 1) { + port = 0; + } + p->addr.sin_port = htons(port); + if (sscanf(PQgetvalue(result,0,6),"%ld",®seconds) != 1) { + regseconds = 0; + } + time(&nowtime); + if (nowtime > regseconds) { + memset(&p->addr, 0, sizeof(p->addr)); + } + } + } else { + ast_log(LOG_ERROR, "PostgreSQL error: %s\n",PQerrorMessage(pgsql)); + } + PQclear(result); + ast_mutex_unlock(&pgsqllock); + } + + if (!success) { + free(p); + p = NULL; + } else { + p->dynamic = 1; + p->capability = capability; + p->nat = globalnat; + p->dtmfmode = globaldtmfmode; + p->insecure = 1; + p->expire = -1; + p->temponly = 1; + + } + return p; +} + + +#endif /* POSTGRES_FRIENDS / MYSQL_FRIENDS */ static int create_addr(struct sip_pvt *r, char *peer) { @@ -808,6 +923,9 @@ #ifdef MYSQL_FRIENDS if (!p) p = mysql_peer(peer, NULL); +#elif defined(POSTGRES_FRIENDS) + if (!p) + p = pgsql_peer(peer, NULL); #endif if (p) { @@ -3790,6 +3908,9 @@ #ifdef MYSQL_FRIENDS if (!peer) peer = mysql_peer(name, NULL); +#elif defined(POSTGRES_FRIENDS) + if (!peer) + peer = pgsql_peer(name, NULL); #endif if (peer) { if (!peer->dynamic) { @@ -3805,6 +3926,9 @@ #ifdef MYSQL_FRIENDS if (peer->temponly) mysql_update_peer(peer->name, &peer->addr, peer->username, p->expiry); +#elif defined(POSTGRES_FRIENDS) + if (peer->temponly) + pgsql_update_peer(peer->name, &peer->addr, peer->username, p->expiry); #endif /* Say OK and ask subsystem to retransmit msg counter */ transmit_response_with_date(p, "200 OK", req); @@ -4273,6 +4397,9 @@ #ifdef MYSQL_FRIENDS if (!peer) peer = mysql_peer(NULL, sin); +#elif defined(POSTGRES_FRIENDS) + if (!peer) + peer = pgsql_peer(NULL, sin); #endif if (peer) { /* Take the peer */ @@ -6476,15 +6603,15 @@ } else { ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config); } -#ifdef MYSQL_FRIENDS +#ifdef SQL_FRIENDS } else if (!strcasecmp(v->name, "dbuser")) { - strncpy(mydbuser, v->value, sizeof(mydbuser) - 1); + strncpy(dbuser, v->value, sizeof(dbuser) - 1); } else if (!strcasecmp(v->name, "dbpass")) { - strncpy(mydbpass, v->value, sizeof(mydbpass) - 1); + strncpy(dbpass, v->value, sizeof(dbpass) - 1); } else if (!strcasecmp(v->name, "dbhost")) { - strncpy(mydbhost, v->value, sizeof(mydbhost) - 1); + strncpy(dbhost, v->value, sizeof(dbhost) - 1); } else if (!strcasecmp(v->name, "dbname")) { - strncpy(mydbname, v->value, sizeof(mydbname) - 1); + strncpy(dbname, v->value, sizeof(dbname) - 1); #endif } //else if (strcasecmp(v->name,"type")) // ast_log(LOG_WARNING, "Ignoring %s\n", v->name); @@ -6573,17 +6700,35 @@ ast_destroy(cfg); #ifdef MYSQL_FRIENDS /* Connect to db if appropriate */ - if (!mysql && strlen(mydbname)) { + if (!mysql && strlen(dbname)) { mysql = mysql_init(NULL); - if (!mysql_real_connect(mysql, mydbhost[0] ? mydbhost : NULL, mydbuser, mydbpass, mydbname, 0, NULL, 0)) { - memset(mydbpass, '*', strlen(mydbpass)); + if (!mysql_real_connect(mysql, dbhost[0] ? dbhost : NULL, dbuser, dbpass, dbname, 0, NULL, 0)) { + memset(dbpass, '*', strlen(dbpass)); ast_log(LOG_WARNING, "Database connection failed (db=%s, host=%s, user=%s, pass=%s)!\n", - mydbname, mydbhost, mydbuser, mydbpass); + dbname, dbhost, dbuser, dbpass); free(mysql); mysql = NULL; } else ast_verbose(VERBOSE_PREFIX_1 "Connected to database '%s' on '%s' as '%s'\n", - mydbname, mydbhost, mydbuser); + dbname, dbhost, dbuser); + } +#elif defined(POSTGRES_FRIENDS) + if (strlen(dbname) && !pgsql) { + pgsql = PQsetdbLogin( + dbhost[0] ? dbhost:NULL, + NULL, NULL, NULL, + dbname, + dbuser[0] ? dbuser:NULL, + dbpass[0] ? dbpass:NULL); + memset(dbpass, '*', strlen(dbpass)); + if (!pgsql || PQstatus(pgsql) != CONNECTION_OK) { + ast_log(LOG_ERROR, "Database connection failed: %s\n", + PQerrorMessage(pgsql)); + if (pgsql) PQfinish(pgsql); + pgsql = NULL; + } else { + ast_verbose(VERBOSE_PREFIX_1 "Connected to database '%s' on '%s' as '%s'\n",dbname,dbhost,dbuser); + } } #endif return 0; @@ -6894,7 +7039,16 @@ ast_log(LOG_WARNING, "Unable to lock the interface list\n"); return -1; } - + +#ifdef POSTGRES_FRIENDS + if (pgsql) { + ast_mutex_lock(&pgsqllock); + PQfinish(pgsql); + pgsql = NULL; + ast_mutex_unlock(&pgsqllock); + } +#endif + return 0; }