00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "asterisk.h"
00030
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00032
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <libpq-fe.h>
00037
00038 #include "asterisk/file.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/config.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/lock.h"
00045 #include "asterisk/options.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/cli.h"
00048
00049 AST_MUTEX_DEFINE_STATIC(pgsql_lock);
00050
00051 #define RES_CONFIG_PGSQL_CONF "res_pgsql.conf"
00052
00053 PGconn *pgsqlConn = NULL;
00054
00055 #define MAX_DB_OPTION_SIZE 64
00056
00057 static char dbhost[MAX_DB_OPTION_SIZE] = "";
00058 static char dbuser[MAX_DB_OPTION_SIZE] = "";
00059 static char dbpass[MAX_DB_OPTION_SIZE] = "";
00060 static char dbname[MAX_DB_OPTION_SIZE] = "";
00061 static char dbsock[MAX_DB_OPTION_SIZE] = "";
00062 static int dbport = 5432;
00063 static time_t connect_time = 0;
00064
00065 static int parse_config(void);
00066 static int pgsql_reconnect(const char *database);
00067 static int realtime_pgsql_status(int fd, int argc, char **argv);
00068
00069 static char cli_realtime_pgsql_status_usage[] =
00070 "Usage: realtime pgsql status\n"
00071 " Shows connection information for the Postgresql RealTime driver\n";
00072
00073 static struct ast_cli_entry cli_realtime[] = {
00074 { { "realtime", "pgsql", "status", NULL },
00075 realtime_pgsql_status, "Shows connection information for the Postgresql RealTime driver",
00076 cli_realtime_pgsql_status_usage },
00077 };
00078
00079 static struct ast_variable *realtime_pgsql(const char *database, const char *table, va_list ap)
00080 {
00081 PGresult *result = NULL;
00082 int num_rows = 0;
00083 char sql[256];
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
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
00109
00110 op = strchr(newparam, ' ') ? "" : " =";
00111
00112 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
00113 newval);
00114 while ((newparam = va_arg(ap, const char *))) {
00115 newval = va_arg(ap, const char *);
00116 if (!strchr(newparam, ' '))
00117 op = " =";
00118 else
00119 op = "";
00120 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
00121 op, newval);
00122 }
00123 va_end(ap);
00124
00125
00126 ast_mutex_lock(&pgsql_lock);
00127 if (!pgsql_reconnect(database)) {
00128 ast_mutex_unlock(&pgsql_lock);
00129 return NULL;
00130 }
00131
00132 if (!(result = PQexec(pgsqlConn, sql))) {
00133 ast_log(LOG_WARNING,
00134 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00135 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00136 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00137 PQerrorMessage(pgsqlConn));
00138 ast_mutex_unlock(&pgsql_lock);
00139 return NULL;
00140 } else {
00141 ExecStatusType result_status = PQresultStatus(result);
00142 if (result_status != PGRES_COMMAND_OK
00143 && result_status != PGRES_TUPLES_OK
00144 && result_status != PGRES_NONFATAL_ERROR) {
00145 ast_log(LOG_WARNING,
00146 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00147 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00148 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00149 PQresultErrorMessage(result), PQresStatus(result_status));
00150 ast_mutex_unlock(&pgsql_lock);
00151 return NULL;
00152 }
00153 }
00154
00155 ast_log(LOG_DEBUG, "1Postgresql RealTime: Result=%p Query: %s\n", result, sql);
00156
00157 if ((num_rows = PQntuples(result)) > 0) {
00158 int i = 0;
00159 int rowIndex = 0;
00160 int numFields = PQnfields(result);
00161 char **fieldnames = NULL;
00162
00163 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
00164
00165 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00166 ast_mutex_unlock(&pgsql_lock);
00167 PQclear(result);
00168 return NULL;
00169 }
00170 for (i = 0; i < numFields; i++)
00171 fieldnames[i] = PQfname(result, i);
00172 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00173 for (i = 0; i < numFields; i++) {
00174 stringp = PQgetvalue(result, rowIndex, i);
00175 while (stringp) {
00176 chunk = strsep(&stringp, ";");
00177 if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
00178 if (prev) {
00179 prev->next = ast_variable_new(fieldnames[i], chunk);
00180 if (prev->next) {
00181 prev = prev->next;
00182 }
00183 } else {
00184 prev = var = ast_variable_new(fieldnames[i], chunk);
00185 }
00186 }
00187 }
00188 }
00189 }
00190 free(fieldnames);
00191 } else {
00192 ast_log(LOG_WARNING,
00193 "Postgresql RealTime: Could not find any rows in table %s.\n", table);
00194 }
00195
00196 ast_mutex_unlock(&pgsql_lock);
00197 PQclear(result);
00198
00199 return var;
00200 }
00201
00202 static struct ast_config *realtime_multi_pgsql(const char *database, const char *table, va_list ap)
00203 {
00204 PGresult *result = NULL;
00205 int num_rows = 0;
00206 char sql[256];
00207 const char *initfield = NULL;
00208 char *stringp;
00209 char *chunk;
00210 char *op;
00211 const char *newparam, *newval;
00212 struct ast_realloca ra;
00213 struct ast_variable *var = NULL;
00214 struct ast_config *cfg = NULL;
00215 struct ast_category *cat = NULL;
00216
00217 if (!table) {
00218 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00219 return NULL;
00220 }
00221
00222 memset(&ra, 0, sizeof(ra));
00223
00224 if (!(cfg = ast_config_new()))
00225 return NULL;
00226
00227
00228 newparam = va_arg(ap, const char *);
00229 newval = va_arg(ap, const char *);
00230 if (!newparam || !newval) {
00231 ast_log(LOG_WARNING,
00232 "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00233 if (pgsqlConn) {
00234 PQfinish(pgsqlConn);
00235 pgsqlConn = NULL;
00236 };
00237 return NULL;
00238 }
00239
00240 initfield = ast_strdupa(newparam);
00241 if ((op = strchr(initfield, ' '))) {
00242 *op = '\0';
00243 }
00244
00245
00246
00247
00248 if (!strchr(newparam, ' '))
00249 op = " =";
00250 else
00251 op = "";
00252
00253 snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op,
00254 newval);
00255 while ((newparam = va_arg(ap, const char *))) {
00256 newval = va_arg(ap, const char *);
00257 if (!strchr(newparam, ' '))
00258 op = " =";
00259 else
00260 op = "";
00261 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam,
00262 op, newval);
00263 }
00264
00265 if (initfield) {
00266 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00267 }
00268
00269 va_end(ap);
00270
00271
00272 ast_mutex_lock(&pgsql_lock);
00273 if (!pgsql_reconnect(database)) {
00274 ast_mutex_unlock(&pgsql_lock);
00275 return NULL;
00276 }
00277
00278 if (!(result = PQexec(pgsqlConn, sql))) {
00279 ast_log(LOG_WARNING,
00280 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00281 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00282 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00283 PQerrorMessage(pgsqlConn));
00284 ast_mutex_unlock(&pgsql_lock);
00285 return NULL;
00286 } else {
00287 ExecStatusType result_status = PQresultStatus(result);
00288 if (result_status != PGRES_COMMAND_OK
00289 && result_status != PGRES_TUPLES_OK
00290 && result_status != PGRES_NONFATAL_ERROR) {
00291 ast_log(LOG_WARNING,
00292 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00293 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00294 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00295 PQresultErrorMessage(result), PQresStatus(result_status));
00296 ast_mutex_unlock(&pgsql_lock);
00297 return NULL;
00298 }
00299 }
00300
00301 ast_log(LOG_DEBUG, "2Postgresql RealTime: Result=%p Query: %s\n", result, sql);
00302
00303 if ((num_rows = PQntuples(result)) > 0) {
00304 int numFields = PQnfields(result);
00305 int i = 0;
00306 int rowIndex = 0;
00307 char **fieldnames = NULL;
00308
00309 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %d rows.\n", num_rows);
00310
00311 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00312 ast_mutex_unlock(&pgsql_lock);
00313 PQclear(result);
00314 return NULL;
00315 }
00316 for (i = 0; i < numFields; i++)
00317 fieldnames[i] = PQfname(result, i);
00318
00319 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00320 var = NULL;
00321 if (!(cat = ast_category_new("")))
00322 continue;
00323 for (i = 0; i < numFields; i++) {
00324 stringp = PQgetvalue(result, rowIndex, i);
00325 while (stringp) {
00326 chunk = strsep(&stringp, ";");
00327 if (chunk && !ast_strlen_zero(ast_strip(chunk))) {
00328 if (initfield && !strcmp(initfield, fieldnames[i])) {
00329 ast_category_rename(cat, chunk);
00330 }
00331 var = ast_variable_new(fieldnames[i], chunk);
00332 ast_variable_append(cat, var);
00333 }
00334 }
00335 }
00336 ast_category_append(cfg, cat);
00337 }
00338 free(fieldnames);
00339 } else {
00340 ast_log(LOG_WARNING,
00341 "Postgresql RealTime: Could not find any rows in table %s.\n", table);
00342 }
00343
00344 ast_mutex_unlock(&pgsql_lock);
00345 PQclear(result);
00346
00347 return cfg;
00348 }
00349
00350 static int update_pgsql(const char *database, const char *table, const char *keyfield,
00351 const char *lookup, va_list ap)
00352 {
00353 PGresult *result = NULL;
00354 int numrows = 0;
00355 char sql[256];
00356 const char *newparam, *newval;
00357
00358 if (!table) {
00359 ast_log(LOG_WARNING, "Postgresql RealTime: No table specified.\n");
00360 return -1;
00361 }
00362
00363
00364 newparam = va_arg(ap, const char *);
00365 newval = va_arg(ap, const char *);
00366 if (!newparam || !newval) {
00367 ast_log(LOG_WARNING,
00368 "Postgresql RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
00369 if (pgsqlConn) {
00370 PQfinish(pgsqlConn);
00371 pgsqlConn = NULL;
00372 };
00373 return -1;
00374 }
00375
00376
00377
00378
00379 snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
00380 while ((newparam = va_arg(ap, const char *))) {
00381 newval = va_arg(ap, const char *);
00382 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam,
00383 newval);
00384 }
00385 va_end(ap);
00386 snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield,
00387 lookup);
00388
00389 ast_log(LOG_DEBUG, "Postgresql RealTime: Update SQL: %s\n", sql);
00390
00391
00392 ast_mutex_lock(&pgsql_lock);
00393 if (!pgsql_reconnect(database)) {
00394 ast_mutex_unlock(&pgsql_lock);
00395 return -1;
00396 }
00397
00398 if (!(result = PQexec(pgsqlConn, sql))) {
00399 ast_log(LOG_WARNING,
00400 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00401 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00402 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00403 PQerrorMessage(pgsqlConn));
00404 ast_mutex_unlock(&pgsql_lock);
00405 return -1;
00406 } else {
00407 ExecStatusType result_status = PQresultStatus(result);
00408 if (result_status != PGRES_COMMAND_OK
00409 && result_status != PGRES_TUPLES_OK
00410 && result_status != PGRES_NONFATAL_ERROR) {
00411 ast_log(LOG_WARNING,
00412 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00413 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00414 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00415 PQresultErrorMessage(result), PQresStatus(result_status));
00416 ast_mutex_unlock(&pgsql_lock);
00417 return -1;
00418 }
00419 }
00420
00421 numrows = atoi(PQcmdTuples(result));
00422 ast_mutex_unlock(&pgsql_lock);
00423
00424 ast_log(LOG_DEBUG, "Postgresql RealTime: Updated %d rows on table: %s\n", numrows,
00425 table);
00426
00427
00428
00429
00430
00431
00432
00433 if (numrows >= 0)
00434 return (int) numrows;
00435
00436 return -1;
00437 }
00438
00439 static struct ast_config *config_pgsql(const char *database, const char *table,
00440 const char *file, struct ast_config *cfg,
00441 int withcomments)
00442 {
00443 PGresult *result = NULL;
00444 long num_rows;
00445 struct ast_variable *new_v;
00446 struct ast_category *cur_cat = NULL;
00447 char sql[250] = "";
00448 char last[80] = "";
00449 int last_cat_metric = 0;
00450
00451 last[0] = '\0';
00452
00453 if (!file || !strcmp(file, RES_CONFIG_PGSQL_CONF)) {
00454 ast_log(LOG_WARNING, "Postgresql RealTime: Cannot configure myself.\n");
00455 return NULL;
00456 }
00457
00458 snprintf(sql, sizeof(sql),
00459 "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id",
00460 table, file);
00461
00462 ast_log(LOG_DEBUG, "Postgresql RealTime: Static SQL: %s\n", sql);
00463
00464
00465 ast_mutex_lock(&pgsql_lock);
00466 if (!pgsql_reconnect(database)) {
00467 ast_mutex_unlock(&pgsql_lock);
00468 return NULL;
00469 }
00470
00471 if (!(result = PQexec(pgsqlConn, sql))) {
00472 ast_log(LOG_WARNING,
00473 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00474 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00475 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s\n",
00476 PQerrorMessage(pgsqlConn));
00477 ast_mutex_unlock(&pgsql_lock);
00478 return NULL;
00479 } else {
00480 ExecStatusType result_status = PQresultStatus(result);
00481 if (result_status != PGRES_COMMAND_OK
00482 && result_status != PGRES_TUPLES_OK
00483 && result_status != PGRES_NONFATAL_ERROR) {
00484 ast_log(LOG_WARNING,
00485 "Postgresql RealTime: Failed to query database. Check debug for more info.\n");
00486 ast_log(LOG_DEBUG, "Postgresql RealTime: Query: %s\n", sql);
00487 ast_log(LOG_DEBUG, "Postgresql RealTime: Query Failed because: %s (%s)\n",
00488 PQresultErrorMessage(result), PQresStatus(result_status));
00489 ast_mutex_unlock(&pgsql_lock);
00490 return NULL;
00491 }
00492 }
00493
00494 if ((num_rows = PQntuples(result)) > 0) {
00495 int numFields = PQnfields(result);
00496 int i = 0;
00497 int rowIndex = 0;
00498 char **fieldnames = NULL;
00499
00500 ast_log(LOG_DEBUG, "Postgresql RealTime: Found %ld rows.\n", num_rows);
00501
00502 if (!(fieldnames = ast_calloc(1, numFields * sizeof(char *)))) {
00503 ast_mutex_unlock(&pgsql_lock);
00504 PQclear(result);
00505 return NULL;
00506 }
00507 for (i = 0; i < numFields; i++)
00508 fieldnames[i] = PQfname(result, i);
00509
00510 for (rowIndex = 0; rowIndex < num_rows; rowIndex++) {
00511 char *field_category = PQgetvalue(result, rowIndex, 0);
00512 char *field_var_name = PQgetvalue(result, rowIndex, 1);
00513 char *field_var_val = PQgetvalue(result, rowIndex, 2);
00514 char *field_cat_metric = PQgetvalue(result, rowIndex, 3);
00515 if (!strcmp(field_var_name, "#include")) {
00516 if (!ast_config_internal_load(field_var_val, cfg, 0)) {
00517 PQclear(result);
00518 ast_mutex_unlock(&pgsql_lock);
00519 return NULL;
00520 }
00521 continue;
00522 }
00523
00524 if (strcmp(last, field_category) || last_cat_metric != atoi(field_cat_metric)) {
00525 cur_cat = ast_category_new(field_category);
00526 if (!cur_cat)
00527 break;
00528 strcpy(last, field_category);
00529 last_cat_metric = atoi(field_cat_metric);
00530 ast_category_append(cfg, cur_cat);
00531 }
00532 new_v = ast_variable_new(field_var_name, field_var_val);
00533 ast_variable_append(cur_cat, new_v);
00534 }
00535 } else {
00536 ast_log(LOG_WARNING,
00537 "Postgresql RealTime: Could not find config '%s' in database.\n", file);
00538 }
00539
00540 PQclear(result);
00541 ast_mutex_unlock(&pgsql_lock);
00542
00543 return cfg;
00544 }
00545
00546 static struct ast_config_engine pgsql_engine = {
00547 .name = "pgsql",
00548 .load_func = config_pgsql,
00549 .realtime_func = realtime_pgsql,
00550 .realtime_multi_func = realtime_multi_pgsql,
00551 .update_func = update_pgsql
00552 };
00553
00554 static int load_module(void)
00555 {
00556 if(!parse_config())
00557 return AST_MODULE_LOAD_DECLINE;
00558
00559 ast_mutex_lock(&pgsql_lock);
00560
00561 if (!pgsql_reconnect(NULL)) {
00562 ast_log(LOG_WARNING,
00563 "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00564 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00565 PQerrorMessage(pgsqlConn));
00566 }
00567
00568 ast_config_engine_register(&pgsql_engine);
00569 if (option_verbose) {
00570 ast_verbose("Postgresql RealTime driver loaded.\n");
00571 }
00572 ast_cli_register_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00573
00574 ast_mutex_unlock(&pgsql_lock);
00575
00576 return 0;
00577 }
00578
00579 static int unload_module(void)
00580 {
00581
00582 ast_mutex_lock(&pgsql_lock);
00583
00584 if (pgsqlConn) {
00585 PQfinish(pgsqlConn);
00586 pgsqlConn = NULL;
00587 };
00588 ast_cli_unregister_multiple(cli_realtime, sizeof(cli_realtime) / sizeof(struct ast_cli_entry));
00589 ast_config_engine_deregister(&pgsql_engine);
00590 if (option_verbose) {
00591 ast_verbose("Postgresql RealTime unloaded.\n");
00592 }
00593
00594 ast_module_user_hangup_all();
00595
00596
00597 ast_mutex_unlock(&pgsql_lock);
00598
00599 return 0;
00600 }
00601
00602 static int reload(void)
00603 {
00604
00605 ast_mutex_lock(&pgsql_lock);
00606
00607 if (pgsqlConn) {
00608 PQfinish(pgsqlConn);
00609 pgsqlConn = NULL;
00610 };
00611 parse_config();
00612
00613 if (!pgsql_reconnect(NULL)) {
00614 ast_log(LOG_WARNING,
00615 "Postgresql RealTime: Couldn't establish connection. Check debug.\n");
00616 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00617 PQerrorMessage(pgsqlConn));
00618 }
00619
00620 ast_verbose(VERBOSE_PREFIX_2 "Postgresql RealTime reloaded.\n");
00621
00622
00623 ast_mutex_unlock(&pgsql_lock);
00624
00625 return 0;
00626 }
00627
00628 static int parse_config(void)
00629 {
00630 struct ast_config *config;
00631 const char *s;
00632
00633 config = ast_config_load(RES_CONFIG_PGSQL_CONF);
00634
00635 if (!config) {
00636 ast_log(LOG_WARNING, "Unable to load config %s\n",RES_CONFIG_PGSQL_CONF);
00637 return 0;
00638 }
00639 if (!(s = ast_variable_retrieve(config, "general", "dbuser"))) {
00640 ast_log(LOG_WARNING,
00641 "Postgresql RealTime: No database user found, using 'asterisk' as default.\n");
00642 strcpy(dbuser, "asterisk");
00643 } else {
00644 ast_copy_string(dbuser, s, sizeof(dbuser));
00645 }
00646
00647 if (!(s = ast_variable_retrieve(config, "general", "dbpass"))) {
00648 ast_log(LOG_WARNING,
00649 "Postgresql RealTime: No database password found, using 'asterisk' as default.\n");
00650 strcpy(dbpass, "asterisk");
00651 } else {
00652 ast_copy_string(dbpass, s, sizeof(dbpass));
00653 }
00654
00655 if (!(s = ast_variable_retrieve(config, "general", "dbhost"))) {
00656 ast_log(LOG_WARNING,
00657 "Postgresql RealTime: No database host found, using localhost via socket.\n");
00658 dbhost[0] = '\0';
00659 } else {
00660 ast_copy_string(dbhost, s, sizeof(dbhost));
00661 }
00662
00663 if (!(s = ast_variable_retrieve(config, "general", "dbname"))) {
00664 ast_log(LOG_WARNING,
00665 "Postgresql RealTime: No database name found, using 'asterisk' as default.\n");
00666 strcpy(dbname, "asterisk");
00667 } else {
00668 ast_copy_string(dbname, s, sizeof(dbname));
00669 }
00670
00671 if (!(s = ast_variable_retrieve(config, "general", "dbport"))) {
00672 ast_log(LOG_WARNING,
00673 "Postgresql RealTime: No database port found, using 5432 as default.\n");
00674 dbport = 5432;
00675 } else {
00676 dbport = atoi(s);
00677 }
00678
00679 if (dbhost && !(s = ast_variable_retrieve(config, "general", "dbsock"))) {
00680 ast_log(LOG_WARNING,
00681 "Postgresql RealTime: No database socket found, using '/tmp/pgsql.sock' as default.\n");
00682 strcpy(dbsock, "/tmp/pgsql.sock");
00683 } else {
00684 ast_copy_string(dbsock, s, sizeof(dbsock));
00685 }
00686 ast_config_destroy(config);
00687
00688 if (dbhost) {
00689 ast_log(LOG_DEBUG, "Postgresql RealTime Host: %s\n", dbhost);
00690 ast_log(LOG_DEBUG, "Postgresql RealTime Port: %i\n", dbport);
00691 } else {
00692 ast_log(LOG_DEBUG, "Postgresql RealTime Socket: %s\n", dbsock);
00693 }
00694 ast_log(LOG_DEBUG, "Postgresql RealTime User: %s\n", dbuser);
00695 ast_log(LOG_DEBUG, "Postgresql RealTime Password: %s\n", dbpass);
00696 ast_log(LOG_DEBUG, "Postgresql RealTime DBName: %s\n", dbname);
00697
00698 return 1;
00699 }
00700
00701 static int pgsql_reconnect(const char *database)
00702 {
00703 char my_database[50];
00704
00705 ast_copy_string(my_database, S_OR(database, dbname), sizeof(my_database));
00706
00707
00708
00709 if (pgsqlConn && PQstatus(pgsqlConn) != CONNECTION_OK) {
00710 PQfinish(pgsqlConn);
00711 pgsqlConn = NULL;
00712 }
00713
00714 if ((!pgsqlConn) && (dbhost || dbsock) && dbuser && dbpass && my_database) {
00715 char *connInfo = NULL;
00716 unsigned int size = 100 + strlen(dbhost)
00717 + strlen(dbuser)
00718 + strlen(dbpass)
00719 + strlen(my_database);
00720
00721 if (!(connInfo = ast_malloc(size)))
00722 return 0;
00723
00724 sprintf(connInfo, "host=%s port=%d dbname=%s user=%s password=%s",
00725 dbhost, dbport, my_database, dbuser, dbpass);
00726 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
00727 pgsqlConn = PQconnectdb(connInfo);
00728 ast_log(LOG_DEBUG, "%u connInfo=%s\n", size, connInfo);
00729 free(connInfo);
00730 connInfo = NULL;
00731 ast_log(LOG_DEBUG, "pgsqlConn=%p\n", pgsqlConn);
00732 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
00733 ast_log(LOG_DEBUG, "Postgresql RealTime: Successfully connected to database.\n");
00734 connect_time = time(NULL);
00735 return 1;
00736 } else {
00737 ast_log(LOG_ERROR,
00738 "Postgresql RealTime: Failed to connect database server %s on %s. Check debug for more info.\n",
00739 dbname, dbhost);
00740 ast_log(LOG_DEBUG, "Postgresql RealTime: Cannot Connect: %s\n",
00741 PQresultErrorMessage(NULL));
00742 return 0;
00743 }
00744 } else {
00745 ast_log(LOG_DEBUG, "Postgresql RealTime: Everything is fine.\n");
00746 return 1;
00747 }
00748 }
00749
00750 static int realtime_pgsql_status(int fd, int argc, char **argv)
00751 {
00752 char status[256], status2[100] = "";
00753 int ctime = time(NULL) - connect_time;
00754
00755 if (pgsqlConn && PQstatus(pgsqlConn) == CONNECTION_OK) {
00756 if (dbhost) {
00757 snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
00758 } else if (dbsock) {
00759 snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
00760 } else {
00761 snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
00762 }
00763
00764 if (dbuser && *dbuser) {
00765 snprintf(status2, 99, " with username %s", dbuser);
00766 }
00767
00768 if (ctime > 31536000) {
00769 ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n",
00770 status, status2, ctime / 31536000, (ctime % 31536000) / 86400,
00771 (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
00772 } else if (ctime > 86400) {
00773 ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status,
00774 status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60,
00775 ctime % 60);
00776 } else if (ctime > 3600) {
00777 ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2,
00778 ctime / 3600, (ctime % 3600) / 60, ctime % 60);
00779 } else if (ctime > 60) {
00780 ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60,
00781 ctime % 60);
00782 } else {
00783 ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
00784 }
00785
00786 return RESULT_SUCCESS;
00787 } else {
00788 return RESULT_FAILURE;
00789 }
00790 }
00791
00792
00793 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "PostgreSQL RealTime Configuration Driver",
00794 .load = load_module,
00795 .unload = unload_module,
00796 .reload = reload
00797 );