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