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