#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 | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
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_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "PostgreSQL RealTime Configuration Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
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 |
static ast_mutex_t | pgsql_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
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" |
static void __reg_module | ( | void | ) | [static] |
Definition at line 842 of file res_config_pgsql.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 842 of file res_config_pgsql.c.
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_lock, 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_lock, 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_copy_string(), 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_copy_string(), 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_strip(), ast_strlen_zero(), ast_variable_append(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, pgsql_lock, pgsql_reconnect(), pgsqlConn, 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_strip(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_variable::next, pgsql_lock, pgsql_reconnect(), 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_lock, 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, pgsql_lock, 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_lock, 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_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "PostgreSQL RealTime Configuration Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload } [static] |
Definition at line 842 of file res_config_pgsql.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 842 of file res_config_pgsql.c.
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().
ast_mutex_t pgsql_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 49 of file res_config_pgsql.c.
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().