#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libpq-fe.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/options.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
Go to the source code of this file.
Defines | |
#define | MAX_DB_OPTION_SIZE 64 |
#define | RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
Functions | |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,"PostgreSQL RealTime Configuration Driver",.load=load_module,.unload=unload_module,.reload=reload) | |
AST_MUTEX_DEFINE_STATIC (pgsql_lock) | |
static struct ast_config * | config_pgsql (const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments) |
static int | load_module (void) |
static int | parse_config (void) |
static int | pgsql_reconnect (const char *database) |
static struct ast_config * | realtime_multi_pgsql (const char *database, const char *table, va_list ap) |
static struct ast_variable * | realtime_pgsql (const char *database, const char *table, va_list ap) |
static int | realtime_pgsql_status (int fd, int argc, char **argv) |
static int | reload (void) |
static int | unload_module (void) |
static int | update_pgsql (const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap) |
Variables | |
static struct ast_cli_entry | cli_realtime [] |
static char | cli_realtime_pgsql_status_usage [] |
static time_t | connect_time = 0 |
static char | dbhost [MAX_DB_OPTION_SIZE] = "" |
static char | dbname [MAX_DB_OPTION_SIZE] = "" |
static char | dbpass [MAX_DB_OPTION_SIZE] = "" |
static int | dbport = 5432 |
static char | dbsock [MAX_DB_OPTION_SIZE] = "" |
static char | dbuser [MAX_DB_OPTION_SIZE] = "" |
static struct ast_config_engine | pgsql_engine |
PGconn * | pgsqlConn = NULL |
Manuel Guesdon <mguesdon@oxymium.net> - Postgresql RealTime Driver Author/Adaptor
Definition in file res_config_pgsql.c.
#define MAX_DB_OPTION_SIZE 64 |
Definition at line 55 of file res_config_pgsql.c.
#define RES_CONFIG_PGSQL_CONF "res_pgsql.conf" |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_GLOBAL_SYMBOLS | , | |||
"PostgreSQL RealTime Configuration Driver" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
AST_MUTEX_DEFINE_STATIC | ( | pgsql_lock | ) |
static struct ast_config* config_pgsql | ( | const char * | database, | |
const char * | table, | |||
const char * | file, | |||
struct ast_config * | cfg, | |||
int | withcomments | |||
) | [static] |
Definition at line 491 of file res_config_pgsql.c.
References ast_build_string(), ast_category_append(), ast_category_new(), ast_config_internal_load(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_append(), ast_variable_new(), last, LOG_DEBUG, LOG_WARNING, pgsql_reconnect(), pgsqlConn, and RES_CONFIG_PGSQL_CONF.
00494 { 00495 PGresult *result = NULL; 00496 long num_rows; 00497 struct ast_variable *new_v; 00498 struct ast_category *cur_cat = NULL; 00499 char sqlbuf[1024] = ""; 00500 char *sql = sqlbuf; 00501 size_t sqlleft = sizeof(sqlbuf); 00502 char last[80] = ""; 00503 int last_cat_metric = 0; 00504 00505 last[0] = '\0'; 00506 00507 if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) { 00508 ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n"); 00509 return NULL; 00510 } 00511 00512 ast_build_string(&sql, &sqlleft, "SELECT category, var_name, var_val, cat_metric FROM %s ", table); 00513 ast_build_string(&sql, &sqlleft, "WHERE filename='%s' and commented=0", file); 00514 ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name "); 00515 00516 ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sqlbuf); 00517 00518 /* We now have our complete statement; Lets connect to the server and execute it. */ 00519 ast_mutex_lock(&pgsql_lock); 00520 if (!pgsql_reconnect(database)) { 00521 ast_mutex_unlock(&pgsql_lock); 00522 return NULL; 00523 } 00524 00525 if (!(result = PQexec(pgsqlConn, sqlbuf))) { 00526 ast_log(LOG_WARNING, 00527 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00528 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00529 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", 00530 PQerrorMessage(pgsqlConn)); 00531 ast_mutex_unlock(&pgsql_lock); 00532 return NULL; 00533 } else { 00534 ExecStatusType result_status = PQresultStatus(result); 00535 if (result_status != PGRES_COMMAND_OK 00536 && result_status != PGRES_TUPLES_OK 00537 && result_status != PGRES_NONFATAL_ERROR) { 00538 ast_log(LOG_WARNING, 00539 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00540 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00541 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", 00542 PQresultErrorMessage(result), PQresStatus(result_status)); 00543 ast_mutex_unlock(&pgsql_lock); 00544 return NULL; 00545 } 00546 } 00547 00548 if ((num_rows = PQntuples(result)) > 0) { 00549 int rowIndex = 0; 00550 00551 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows); 00552 00553 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00554 char *field_category = PQgetvalue(result, rowIndex, 0); 00555 char *field_var_name = PQgetvalue(result, rowIndex, 1); 00556 char *field_var_val = PQgetvalue(result, rowIndex, 2); 00557 char *field_cat_metric = PQgetvalue(result, rowIndex, 3); 00558 if (!strcmp(field_var_name, "#include")) { 00559 if (!ast_config_internal_load(field_var_val, cfg, 0)) { 00560 PQclear(result); 00561 ast_mutex_unlock(&pgsql_lock); 00562 return NULL; 00563 } 00564 continue; 00565 } 00566 00567 if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) { 00568 cur_cat = ast_category_new(field_category); 00569 if (!cur_cat) 00570 break; 00571 strcpy(last, field_category); 00572 last_cat_metric = atoi(field_cat_metric); 00573 ast_category_append(cfg, cur_cat); 00574 } 00575 new_v = ast_variable_new(field_var_name, field_var_val); 00576 ast_variable_append(cur_cat, new_v); 00577 } 00578 } else { 00579 ast_log(LOG_WARNING, 00580 "Postgresql RealTime: Could not find config '%s' in database.\n", file); 00581 } 00582 00583 PQclear(result); 00584 ast_mutex_unlock(&pgsql_lock); 00585 00586 return cfg; 00587 }
static int load_module | ( | void | ) | [static] |
Definition at line 597 of file res_config_pgsql.c.
References ast_cli_register_multiple(), ast_config_engine_register(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), cli_realtime, LOG_DEBUG, LOG_WARNING, option_verbose, parse_config(), pgsql_engine, pgsql_reconnect(), and pgsqlConn.
00598 { 00599 if(!parse_config()) 00600 return AST_MODULE_LOAD_DECLINE; 00601 00602 ast_mutex_lock(&pgsql_lock); 00603 00604 if (!pgsql_reconnect(NULL)) { 00605 ast_log(LOG_WARNING, 00606 "Postgresql RealTime: Couldn't establish connection. Check debug.\n"); 00607 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", 00608 PQerrorMessage(pgsqlConn)); 00609 } 00610 00611 ast_config_engine_register(&pgsql_engine); 00612 if (option_verbose) { 00613 ast_verbose("Postgresql RealTime driver loaded.\n"); 00614 } 00615 ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); 00616 00617 ast_mutex_unlock(&pgsql_lock); 00618 00619 return 0; 00620 }
static int parse_config | ( | void | ) | [static] |
Definition at line 671 of file res_config_pgsql.c.
References ast_config_destroy(), ast_config_load(), ast_log(), ast_strlen_zero(), ast_variable_retrieve(), config, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_DEBUG, LOG_WARNING, RES_CONFIG_PGSQL_CONF, and s.
00672 { 00673 struct ast_config *config; 00674 const char *s; 00675 00676 config = ast_config_load(RES_CONFIG_PGSQL_CONF); 00677 00678 if (!config) { 00679 ast_log(LOG_WARNING, "Unable to load config %s\n",RES_CONFIG_PGSQL_CONF); 00680 return 0; 00681 } 00682 if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) { 00683 ast_log(LOG_WARNING, 00684 "Postgresql RealTime: No database user found, using 'asterisk' as default.\n"); 00685 strcpy(dbuser, "asterisk"); 00686 } else { 00687 ast_copy_string(dbuser, s, sizeof(dbuser)); 00688 } 00689 00690 if (!(s = ast_variable_retrieve(config, "general", "dbpass"))) { 00691 ast_log(LOG_WARNING, 00692 "Postgresql RealTime: No database password found, using 'asterisk' as default.\n"); 00693 strcpy(dbpass, "asterisk"); 00694 } else { 00695 ast_copy_string(dbpass, s, sizeof(dbpass)); 00696 } 00697 00698 if (!(s = ast_variable_retrieve(config, "general", "dbhost"))) { 00699 ast_log(LOG_WARNING, 00700 "Postgresql RealTime: No database host found, using localhost via socket.\n"); 00701 dbhost[0] = '\0'; 00702 } else { 00703 ast_copy_string(dbhost, s, sizeof(dbhost)); 00704 } 00705 00706 if (!(s = ast_variable_retrieve(config, "general", "dbname"))) { 00707 ast_log(LOG_WARNING, 00708 "Postgresql RealTime: No database name found, using 'asterisk' as default.\n"); 00709 strcpy(dbname, "asterisk"); 00710 } else { 00711 ast_copy_string(dbname, s, sizeof(dbname)); 00712 } 00713 00714 if (!(s = ast_variable_retrieve(config, "general", "dbport"))) { 00715 ast_log(LOG_WARNING, 00716 "Postgresql RealTime: No database port found, using 5432 as default.\n"); 00717 dbport = 5432; 00718 } else { 00719 dbport = atoi(s); 00720 } 00721 00722 if (!ast_strlen_zero(dbhost)) { 00723 /* No socket needed */ 00724 } else if (!(s = ast_variable_retrieve(config, "general", "dbsock"))) { 00725 ast_log(LOG_WARNING, 00726 "Postgresql RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n"); 00727 strcpy(dbsock, "/tmp/pgsql.sock"); 00728 } else { 00729 ast_copy_string(dbsock, s, sizeof(dbsock)); 00730 } 00731 ast_config_destroy(config); 00732 00733 if (!ast_strlen_zero(dbhost)) { 00734 ast_log(LOG_DEBUG, "Postgresql RealTime Host: %s\n", dbhost); 00735 ast_log(LOG_DEBUG, "Postgresql RealTime Port: %i\n", dbport); 00736 } else { 00737 ast_log(LOG_DEBUG, "Postgresql RealTime Socket: %s\n", dbsock); 00738 } 00739 ast_log(LOG_DEBUG, "Postgresql RealTime User: %s\n", dbuser); 00740 ast_log(LOG_DEBUG, "Postgresql RealTime Password: %s\n", dbpass); 00741 ast_log(LOG_DEBUG, "Postgresql RealTime DBName: %s\n", dbname); 00742 00743 return 1; 00744 }
static int pgsql_reconnect | ( | const char * | database | ) | [static] |
Definition at line 746 of file res_config_pgsql.c.
References ast_free, ast_log(), ast_malloc, ast_strlen_zero(), connect_time, dbhost, dbname, dbpass, dbport, dbsock, dbuser, LOG_DEBUG, LOG_ERROR, pgsqlConn, and S_OR.
Referenced by config_pgsql(), load_module(), realtime_multi_pgsql(), realtime_pgsql(), reload(), and update_pgsql().
00747 { 00748 char my_database[50]; 00749 00750 ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database)); 00751 00752 /* mutex lock should have been locked before calling this function. */ 00753 00754 if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) { 00755 PQfinish(pgsqlConn); 00756 pgsqlConn = NULL; 00757 } 00758 00759 if ((!pgsqlConn) && (!ast_strlen_zero(dbhost) || !ast_strlen_zero(dbsock)) && !ast_strlen_zero(dbuser) && !ast_strlen_zero(dbpass) && !ast_strlen_zero(my_database)) { 00760 char *connInfo = NULL; 00761 unsigned int size = 100 + strlen(dbhost) 00762 + strlen(dbuser) 00763 + strlen(dbpass) 00764 + strlen(my_database); 00765 00766 if (!(connInfo = ast_malloc(size))) 00767 return 0; 00768 00769 sprintf(connInfo, "host=%s port=%d dbname=%s user=%s password=%s", 00770 dbhost, dbport, my_database, dbuser, dbpass); 00771 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo); 00772 pgsqlConn = PQconnectdb(connInfo); 00773 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo); 00774 ast_free(connInfo); 00775 connInfo = NULL; 00776 ast_log(LOG_DEBUG, "pgsqlConn=%p\n", pgsqlConn); 00777 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) { 00778 ast_log(LOG_DEBUG, "Postgresql RealTime: Successfully connected to database.\n"); 00779 connect_time = time(NULL); 00780 return 1; 00781 } else { 00782 ast_log(LOG_ERROR, 00783 "Postgresql RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", 00784 dbname, dbhost); 00785 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", 00786 PQresultErrorMessage(NULL)); 00787 return 0; 00788 } 00789 } else { 00790 ast_log(LOG_DEBUG, "Postgresql RealTime: Everything is fine.\n"); 00791 return 1; 00792 } 00793 }
static struct ast_config* realtime_multi_pgsql | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 216 of file res_config_pgsql.c.
References ast_calloc, ast_category_append(), ast_category_new(), ast_category_rename(), ast_config_new(), ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), ast_variable_append(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, pgsql_reconnect(), pgsqlConn, strsep(), and var.
00217 { 00218 PGresult *result = NULL; 00219 int num_rows = 0, pgerror; 00220 char sql[256], escapebuf[513]; 00221 const char *initfield = NULL; 00222 char *stringp; 00223 char *chunk; 00224 char *op; 00225 const char *newparam, *newval; 00226 struct ast_realloca ra; 00227 struct ast_variable *var = NULL; 00228 struct ast_config *cfg = NULL; 00229 struct ast_category *cat = NULL; 00230 00231 if (!table) { 00232 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n"); 00233 return NULL; 00234 } 00235 00236 memset(&ra, 0, sizeof(ra)); 00237 00238 if (!(cfg = ast_config_new())) 00239 return NULL; 00240 00241 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00242 newparam = va_arg(ap, const char *); 00243 newval = va_arg(ap, const char *); 00244 if (!newparam || !newval) { 00245 ast_log(LOG_WARNING, 00246 "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00247 if (pgsqlConn) { 00248 PQfinish(pgsqlConn); 00249 pgsqlConn = NULL; 00250 }; 00251 return NULL; 00252 } 00253 00254 initfield = ast_strdupa(newparam); 00255 if ((op = strchr(initfield, ' '))) { 00256 *op = '\0'; 00257 } 00258 00259 /* Create the first part of the query using the first parameter/value pairs we just extracted 00260 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00261 00262 if (!strchr(newparam, ' ')) 00263 op = " ="; 00264 else 00265 op = ""; 00266 00267 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00268 if (pgerror) { 00269 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00270 va_end(ap); 00271 return NULL; 00272 } 00273 00274 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, 00275 escapebuf); 00276 while ((newparam = va_arg(ap, const char *))) { 00277 newval = va_arg(ap, const char *); 00278 if (!strchr(newparam, ' ')) 00279 op = " ="; 00280 else 00281 op = ""; 00282 00283 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00284 if (pgerror) { 00285 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00286 va_end(ap); 00287 return NULL; 00288 } 00289 00290 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, 00291 op, escapebuf); 00292 } 00293 00294 if (initfield) { 00295 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield); 00296 } 00297 00298 va_end(ap); 00299 00300 /* We now have our complete statement; Lets connect to the server and execute it. */ 00301 ast_mutex_lock(&pgsql_lock); 00302 if (!pgsql_reconnect(database)) { 00303 ast_mutex_unlock(&pgsql_lock); 00304 return NULL; 00305 } 00306 00307 if (!(result = PQexec(pgsqlConn, sql))) { 00308 ast_log(LOG_WARNING, 00309 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00310 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00311 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", 00312 PQerrorMessage(pgsqlConn)); 00313 ast_mutex_unlock(&pgsql_lock); 00314 return NULL; 00315 } else { 00316 ExecStatusType result_status = PQresultStatus(result); 00317 if (result_status != PGRES_COMMAND_OK 00318 && result_status != PGRES_TUPLES_OK 00319 && result_status != PGRES_NONFATAL_ERROR) { 00320 ast_log(LOG_WARNING, 00321 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00322 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00323 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", 00324 PQresultErrorMessage(result), PQresStatus(result_status)); 00325 ast_mutex_unlock(&pgsql_lock); 00326 return NULL; 00327 } 00328 } 00329 00330 ast_log(LOG_DEBUG, "2Postgresql RealTime: Result=%p Query: %s\n", result, sql); 00331 00332 if ((num_rows = PQntuples(result)) > 0) { 00333 int numFields = PQnfields(result); 00334 int i = 0; 00335 int rowIndex = 0; 00336 char **fieldnames = NULL; 00337 00338 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows); 00339 00340 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { 00341 ast_mutex_unlock(&pgsql_lock); 00342 PQclear(result); 00343 return NULL; 00344 } 00345 for (i = 0; i < numFields; i++) 00346 fieldnames[i] = PQfname(result, i); 00347 00348 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00349 var = NULL; 00350 if (!(cat = ast_category_new(""))) 00351 continue; 00352 for (i = 0; i < numFields; i++) { 00353 stringp = PQgetvalue(result, rowIndex, i); 00354 while (stringp) { 00355 chunk = strsep(&stringp, ";"); 00356 if (chunk && !ast_strlen_zero(ast_strip(chunk))) { 00357 if (initfield && !strcmp(initfield, fieldnames[i])) { 00358 ast_category_rename(cat, chunk); 00359 } 00360 var = ast_variable_new(fieldnames[i], chunk); 00361 ast_variable_append(cat, var); 00362 } 00363 } 00364 } 00365 ast_category_append(cfg, cat); 00366 } 00367 ast_free(fieldnames); 00368 } else { 00369 ast_log(LOG_WARNING, 00370 "Postgresql RealTime: Could not find any rows in table %s.\n", table); 00371 } 00372 00373 ast_mutex_unlock(&pgsql_lock); 00374 PQclear(result); 00375 00376 return cfg; 00377 }
static struct ast_variable* realtime_pgsql | ( | const char * | database, | |
const char * | table, | |||
va_list | ap | |||
) | [static] |
Definition at line 79 of file res_config_pgsql.c.
References ast_calloc, ast_free, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_variable::next, pgsql_reconnect(), strsep(), and var.
00080 { 00081 PGresult *result = NULL; 00082 int num_rows = 0, pgerror; 00083 char sql[256], escapebuf[513]; 00084 char *stringp; 00085 char *chunk; 00086 char *op; 00087 const char *newparam, *newval; 00088 struct ast_variable *var = NULL, *prev = NULL; 00089 00090 if (!table) { 00091 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n"); 00092 return NULL; 00093 } 00094 00095 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00096 newparam = va_arg(ap, const char *); 00097 newval = va_arg(ap, const char *); 00098 if (!newparam || !newval) { 00099 ast_log(LOG_WARNING, 00100 "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00101 if (pgsqlConn) { 00102 PQfinish(pgsqlConn); 00103 pgsqlConn = NULL; 00104 }; 00105 return NULL; 00106 } 00107 00108 /* Create the first part of the query using the first parameter/value pairs we just extracted 00109 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00110 op = strchr(newparam, ' ') ? "" : " ="; 00111 00112 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00113 if (pgerror) { 00114 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00115 va_end(ap); 00116 return NULL; 00117 } 00118 00119 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, 00120 escapebuf); 00121 while ((newparam = va_arg(ap, const char *))) { 00122 newval = va_arg(ap, const char *); 00123 if (!strchr(newparam, ' ')) 00124 op = " ="; 00125 else 00126 op = ""; 00127 00128 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00129 if (pgerror) { 00130 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00131 va_end(ap); 00132 return NULL; 00133 } 00134 00135 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, 00136 op, escapebuf); 00137 } 00138 va_end(ap); 00139 00140 /* We now have our complete statement; Lets connect to the server and execute it. */ 00141 ast_mutex_lock(&pgsql_lock); 00142 if (!pgsql_reconnect(database)) { 00143 ast_mutex_unlock(&pgsql_lock); 00144 return NULL; 00145 } 00146 00147 if (!(result = PQexec(pgsqlConn, sql))) { 00148 ast_log(LOG_WARNING, 00149 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00150 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00151 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", 00152 PQerrorMessage(pgsqlConn)); 00153 ast_mutex_unlock(&pgsql_lock); 00154 return NULL; 00155 } else { 00156 ExecStatusType result_status = PQresultStatus(result); 00157 if (result_status != PGRES_COMMAND_OK 00158 && result_status != PGRES_TUPLES_OK 00159 && result_status != PGRES_NONFATAL_ERROR) { 00160 ast_log(LOG_WARNING, 00161 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00162 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00163 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", 00164 PQresultErrorMessage(result), PQresStatus(result_status)); 00165 ast_mutex_unlock(&pgsql_lock); 00166 return NULL; 00167 } 00168 } 00169 00170 ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql); 00171 00172 if ((num_rows = PQntuples(result)) > 0) { 00173 int i = 0; 00174 int rowIndex = 0; 00175 int numFields = PQnfields(result); 00176 char **fieldnames = NULL; 00177 00178 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows); 00179 00180 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) { 00181 ast_mutex_unlock(&pgsql_lock); 00182 PQclear(result); 00183 return NULL; 00184 } 00185 for (i = 0; i < numFields; i++) 00186 fieldnames[i] = PQfname(result, i); 00187 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) { 00188 for (i = 0; i < numFields; i++) { 00189 stringp = PQgetvalue(result, rowIndex, i); 00190 while (stringp) { 00191 chunk = strsep(&stringp, ";"); 00192 if (chunk && !ast_strlen_zero(ast_strip(chunk))) { 00193 if (prev) { 00194 prev->next = ast_variable_new(fieldnames[i], chunk); 00195 if (prev->next) { 00196 prev = prev->next; 00197 } 00198 } else { 00199 prev = var = ast_variable_new(fieldnames[i], chunk); 00200 } 00201 } 00202 } 00203 } 00204 } 00205 ast_free(fieldnames); 00206 } else { 00207 ast_log(LOG_DEBUG, "Postgresql RealTime: Could not find any rows in table %s.\n", table); 00208 } 00209 00210 ast_mutex_unlock(&pgsql_lock); 00211 PQclear(result); 00212 00213 return var; 00214 }
static int realtime_pgsql_status | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 795 of file res_config_pgsql.c.
References ast_cli(), ast_strlen_zero(), connect_time, dbhost, dbname, dbport, dbsock, dbuser, pgsqlConn, RESULT_FAILURE, and RESULT_SUCCESS.
00796 { 00797 char status[256], status2[100] = ""; 00798 int ctime = time(NULL) - connect_time; 00799 00800 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) { 00801 if (!ast_strlen_zero(dbhost)) { 00802 snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport); 00803 } else if (!ast_strlen_zero(dbsock)) { 00804 snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock); 00805 } else { 00806 snprintf(status, 255, "Connected to %s@%s", dbname, dbhost); 00807 } 00808 00809 if (!ast_strlen_zero(dbuser)) { 00810 snprintf(status2, 99, " with username %s", dbuser); 00811 } 00812 00813 if (ctime > 31536000) { 00814 ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", 00815 status, status2, ctime / 31536000, (ctime % 31536000) / 86400, 00816 (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60); 00817 } else if (ctime > 86400) { 00818 ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, 00819 status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, 00820 ctime % 60); 00821 } else if (ctime > 3600) { 00822 ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, 00823 ctime / 3600, (ctime % 3600) / 60, ctime % 60); 00824 } else if (ctime > 60) { 00825 ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, 00826 ctime % 60); 00827 } else { 00828 ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime); 00829 } 00830 00831 return RESULT_SUCCESS; 00832 } else { 00833 return RESULT_FAILURE; 00834 } 00835 }
static int reload | ( | void | ) | [static] |
Definition at line 645 of file res_config_pgsql.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), LOG_DEBUG, LOG_WARNING, parse_config(), pgsql_reconnect(), pgsqlConn, and VERBOSE_PREFIX_2.
00646 { 00647 /* Aquire control before doing anything to the module itself. */ 00648 ast_mutex_lock(&pgsql_lock); 00649 00650 if (pgsqlConn) { 00651 PQfinish(pgsqlConn); 00652 pgsqlConn = NULL; 00653 }; 00654 parse_config(); 00655 00656 if (!pgsql_reconnect(NULL)) { 00657 ast_log(LOG_WARNING, 00658 "Postgresql RealTime: Couldn't establish connection. Check debug.\n"); 00659 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n", 00660 PQerrorMessage(pgsqlConn)); 00661 } 00662 00663 ast_verbose(VERBOSE_PREFIX_2 "Postgresql RealTime reloaded.\n"); 00664 00665 /* Done reloading. Release lock so others can now use driver. */ 00666 ast_mutex_unlock(&pgsql_lock); 00667 00668 return 0; 00669 }
static int unload_module | ( | void | ) | [static] |
Definition at line 622 of file res_config_pgsql.c.
References ast_cli_unregister_multiple(), ast_config_engine_deregister(), ast_module_user_hangup_all, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), cli_realtime, option_verbose, pgsql_engine, and pgsqlConn.
00623 { 00624 /* Aquire control before doing anything to the module itself. */ 00625 ast_mutex_lock(&pgsql_lock); 00626 00627 if (pgsqlConn) { 00628 PQfinish(pgsqlConn); 00629 pgsqlConn = NULL; 00630 }; 00631 ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry)); 00632 ast_config_engine_deregister(&pgsql_engine); 00633 if (option_verbose) { 00634 ast_verbose("Postgresql RealTime unloaded.\n"); 00635 } 00636 00637 ast_module_user_hangup_all(); 00638 00639 /* Unlock so something else can destroy the lock. */ 00640 ast_mutex_unlock(&pgsql_lock); 00641 00642 return 0; 00643 }
static int update_pgsql | ( | const char * | database, | |
const char * | table, | |||
const char * | keyfield, | |||
const char * | lookup, | |||
va_list | ap | |||
) | [static] |
Definition at line 379 of file res_config_pgsql.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, pgsql_reconnect(), and pgsqlConn.
00381 { 00382 PGresult *result = NULL; 00383 int numrows = 0, pgerror; 00384 char sql[256], escapebuf[513]; 00385 const char *newparam, *newval; 00386 00387 if (!table) { 00388 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n"); 00389 return -1; 00390 } 00391 00392 /* Get the first parameter and first value in our list of passed paramater/value pairs */ 00393 newparam = va_arg(ap, const char *); 00394 newval = va_arg(ap, const char *); 00395 if (!newparam || !newval) { 00396 ast_log(LOG_WARNING, 00397 "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n"); 00398 if (pgsqlConn) { 00399 PQfinish(pgsqlConn); 00400 pgsqlConn = NULL; 00401 }; 00402 return -1; 00403 } 00404 00405 /* Create the first part of the query using the first parameter/value pairs we just extracted 00406 If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */ 00407 00408 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00409 if (pgerror) { 00410 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00411 va_end(ap); 00412 return -1; 00413 } 00414 snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, escapebuf); 00415 00416 while ((newparam = va_arg(ap, const char *))) { 00417 newval = va_arg(ap, const char *); 00418 00419 PQescapeStringConn(pgsqlConn, escapebuf, newval, (sizeof(escapebuf) - 1) / 2, &pgerror); 00420 if (pgerror) { 00421 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", newval); 00422 va_end(ap); 00423 return -1; 00424 } 00425 00426 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, 00427 escapebuf); 00428 } 00429 va_end(ap); 00430 00431 PQescapeStringConn(pgsqlConn, escapebuf, lookup, (sizeof(escapebuf) - 1) / 2, &pgerror); 00432 if (pgerror) { 00433 ast_log(LOG_ERROR, "Postgres detected invalid input: '%s'\n", lookup); 00434 va_end(ap); 00435 return -1; 00436 } 00437 00438 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, 00439 escapebuf); 00440 00441 ast_log(LOG_DEBUG, "Postgresql RealTime: Update SQL: %s\n", sql); 00442 00443 /* We now have our complete statement; Lets connect to the server and execute it. */ 00444 ast_mutex_lock(&pgsql_lock); 00445 if (!pgsql_reconnect(database)) { 00446 ast_mutex_unlock(&pgsql_lock); 00447 return -1; 00448 } 00449 00450 if (!(result = PQexec(pgsqlConn, sql))) { 00451 ast_log(LOG_WARNING, 00452 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00453 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00454 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n", 00455 PQerrorMessage(pgsqlConn)); 00456 ast_mutex_unlock(&pgsql_lock); 00457 return -1; 00458 } else { 00459 ExecStatusType result_status = PQresultStatus(result); 00460 if (result_status != PGRES_COMMAND_OK 00461 && result_status != PGRES_TUPLES_OK 00462 && result_status != PGRES_NONFATAL_ERROR) { 00463 ast_log(LOG_WARNING, 00464 "Postgresql RealTime: Failed to query database. Check debug for more info.\n"); 00465 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql); 00466 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n", 00467 PQresultErrorMessage(result), PQresStatus(result_status)); 00468 ast_mutex_unlock(&pgsql_lock); 00469 return -1; 00470 } 00471 } 00472 00473 numrows = atoi(PQcmdTuples(result)); 00474 ast_mutex_unlock(&pgsql_lock); 00475 00476 ast_log(LOG_DEBUG, "Postgresql RealTime: Updated %d rows on table: %s\n", numrows, 00477 table); 00478 00479 /* From http://dev.pgsql.com/doc/pgsql/en/pgsql-affected-rows.html 00480 * An integer greater than zero indicates the number of rows affected 00481 * Zero indicates that no records were updated 00482 * -1 indicates that the query returned an error (although, if the query failed, it should have been caught above.) 00483 */ 00484 00485 if (numrows >= 0) 00486 return (int) numrows; 00487 00488 return -1; 00489 }
struct ast_cli_entry cli_realtime[] [static] |
Initial value:
{ { { "realtime", "pgsql", "status", NULL }, realtime_pgsql_status, "Shows connection information for the Postgresql RealTime driver", cli_realtime_pgsql_status_usage }, }
Definition at line 73 of file res_config_pgsql.c.
char cli_realtime_pgsql_status_usage[] [static] |
Initial value:
"Usage: realtime pgsql status\n" " Shows connection information for the Postgresql RealTime driver\n"
Definition at line 69 of file res_config_pgsql.c.
time_t connect_time = 0 [static] |
Definition at line 63 of file res_config_pgsql.c.
Referenced by pgsql_reconnect(), and realtime_pgsql_status().
char dbhost[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 57 of file res_config_pgsql.c.
Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().
char dbname[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 60 of file res_config_pgsql.c.
char dbpass[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 59 of file res_config_pgsql.c.
Referenced by parse_config(), and pgsql_reconnect().
int dbport = 5432 [static] |
Definition at line 62 of file res_config_pgsql.c.
Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().
char dbsock[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 61 of file res_config_pgsql.c.
Referenced by parse_config(), pgsql_reconnect(), and realtime_pgsql_status().
char dbuser[MAX_DB_OPTION_SIZE] = "" [static] |
Definition at line 58 of file res_config_pgsql.c.
struct ast_config_engine pgsql_engine [static] |
Definition at line 589 of file res_config_pgsql.c.
Referenced by load_module(), and unload_module().
PGconn* pgsqlConn = NULL |
Definition at line 53 of file res_config_pgsql.c.
Referenced by config_pgsql(), load_module(), pgsql_reconnect(), realtime_multi_pgsql(), realtime_pgsql_status(), reload(), unload_module(), and update_pgsql().