Thu Oct 11 06:33:52 2012

Asterisk developer's documentation


res_config_curl.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2008, Digium, Inc.
00005  *
00006  * Tilghman Lesher <res_config_curl_v1@the-tilghman.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief curl plugin for portable configuration engine
00022  *
00023  * \author Tilghman Lesher <res_config_curl_v1@the-tilghman.com>
00024  *
00025  * Depends on the CURL library - http://curl.haxx.se/
00026  * 
00027  */
00028 
00029 /*** MODULEINFO
00030    <depend>curl</depend>
00031    <support_level>core</support_level>
00032  ***/
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 373330 $")
00037 
00038 #include <curl/curl.h>
00039 
00040 #include "asterisk/file.h"
00041 #include "asterisk/channel.h"
00042 #include "asterisk/pbx.h"
00043 #include "asterisk/config.h"
00044 #include "asterisk/module.h"
00045 #include "asterisk/lock.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/threadstorage.h"
00048 
00049 AST_THREADSTORAGE(query_buf);
00050 AST_THREADSTORAGE(result_buf);
00051 
00052 /*!
00053  * \brief Execute a curl query and return ast_variable list
00054  * \param url The base URL from which to retrieve data
00055  * \param unused Not currently used
00056  * \param ap list containing one or more field/operator/value set.
00057  *
00058  * \retval var on success
00059  * \retval NULL on failure
00060 */
00061 static struct ast_variable *realtime_curl(const char *url, const char *unused, va_list ap)
00062 {
00063    struct ast_str *query, *buffer;
00064    char buf1[256], buf2[256];
00065    const char *newparam, *newval;
00066    char *stringp, *pair, *key;
00067    int i;
00068    struct ast_variable *var = NULL, *prev = NULL;
00069 
00070    if (!ast_custom_function_find("CURL")) {
00071       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00072       return NULL;
00073    }
00074 
00075    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00076       return NULL;
00077    }
00078 
00079    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00080       return NULL;
00081    }
00082 
00083    ast_str_set(&query, 0, "${CURL(%s/single,", url);
00084 
00085    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00086       newval = va_arg(ap, const char *);
00087       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00088       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00089       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00090    }
00091 
00092    ast_str_append(&query, 0, ")}");
00093    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00094 
00095    /* Remove any trailing newline characters */
00096    if ((stringp = strchr(ast_str_buffer(buffer), '\r')) || (stringp = strchr(ast_str_buffer(buffer), '\n'))) {
00097       *stringp = '\0';
00098    }
00099 
00100    stringp = ast_str_buffer(buffer);
00101    while ((pair = strsep(&stringp, "&"))) {
00102       key = strsep(&pair, "=");
00103       ast_uri_decode(key, ast_uri_http);
00104       if (pair) {
00105          ast_uri_decode(pair, ast_uri_http);
00106       }
00107 
00108       if (!ast_strlen_zero(key)) {
00109          if (prev) {
00110             prev->next = ast_variable_new(key, S_OR(pair, ""), "");
00111             if (prev->next) {
00112                prev = prev->next;
00113             }
00114          } else {
00115             prev = var = ast_variable_new(key, S_OR(pair, ""), "");
00116          }
00117       }
00118    }
00119 
00120    return var;
00121 }
00122 
00123 /*!
00124  * \brief Excute an Select query and return ast_config list
00125  * \param url
00126  * \param unused
00127  * \param ap list containing one or more field/operator/value set.
00128  *
00129  * \retval struct ast_config pointer on success
00130  * \retval NULL on failure
00131 */
00132 static struct ast_config *realtime_multi_curl(const char *url, const char *unused, va_list ap)
00133 {
00134    struct ast_str *query, *buffer;
00135    char buf1[256], buf2[256];
00136    const char *newparam, *newval;
00137    char *stringp, *line, *pair, *key, *initfield = NULL;
00138    int i;
00139    struct ast_variable *var = NULL;
00140    struct ast_config *cfg = NULL;
00141    struct ast_category *cat = NULL;
00142 
00143    if (!ast_custom_function_find("CURL")) {
00144       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00145       return NULL;
00146    }
00147 
00148    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00149       return NULL;
00150    }
00151 
00152    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00153       return NULL;
00154    }
00155 
00156    ast_str_set(&query, 0, "${CURL(%s/multi,", url);
00157 
00158    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00159       newval = va_arg(ap, const char *);
00160       if (i == 0) {
00161          char *op;
00162          initfield = ast_strdupa(newparam);
00163          if ((op = strchr(initfield, ' ')))
00164             *op = '\0';
00165       }
00166       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00167       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00168       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00169    }
00170 
00171    ast_str_append(&query, 0, ")}");
00172 
00173    /* Do the CURL query */
00174    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00175 
00176    if (!(cfg = ast_config_new())) {
00177       return NULL;
00178    }
00179 
00180    /* Line oriented output */
00181    stringp = ast_str_buffer(buffer);
00182    while ((line = strsep(&stringp, "\r\n"))) {
00183       if (ast_strlen_zero(line)) {
00184          continue;
00185       }
00186 
00187       if (!(cat = ast_category_new("", "", 99999))) {
00188          continue;
00189       }
00190 
00191       while ((pair = strsep(&line, "&"))) {
00192          key = strsep(&pair, "=");
00193          ast_uri_decode(key, ast_uri_http);
00194          if (pair) {
00195             ast_uri_decode(pair, ast_uri_http);
00196          }
00197 
00198          if (!strcasecmp(key, initfield) && pair) {
00199             ast_category_rename(cat, pair);
00200          }
00201 
00202          if (!ast_strlen_zero(key)) {
00203             var = ast_variable_new(key, S_OR(pair, ""), "");
00204             ast_variable_append(cat, var);
00205          }
00206       }
00207       ast_category_append(cfg, cat);
00208    }
00209 
00210    return cfg;
00211 }
00212 
00213 /*!
00214  * \brief Execute an UPDATE query
00215  * \param url
00216  * \param unused
00217  * \param keyfield where clause field
00218  * \param lookup value of field for where clause
00219  * \param ap list containing one or more field/value set(s).
00220  *
00221  * Update a database table, prepare the sql statement using keyfield and lookup
00222  * control the number of records to change. All values to be changed are stored in ap list.
00223  * Sub-in the values to the prepared statement and execute it.
00224  *
00225  * \retval number of rows affected
00226  * \retval -1 on failure
00227 */
00228 static int update_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
00229 {
00230    struct ast_str *query, *buffer;
00231    char buf1[256], buf2[256];
00232    const char *newparam, *newval;
00233    char *stringp;
00234    int i, rowcount = -1;
00235 
00236    if (!ast_custom_function_find("CURL")) {
00237       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00238       return -1;
00239    }
00240 
00241    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00242       return -1;
00243    }
00244 
00245    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00246       return -1;
00247    }
00248 
00249    ast_uri_encode(keyfield, buf1, sizeof(buf1), ast_uri_http);
00250    ast_uri_encode(lookup, buf2, sizeof(buf2), ast_uri_http);
00251    ast_str_set(&query, 0, "${CURL(%s/update?%s=%s,", url, buf1, buf2);
00252 
00253    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00254       newval = va_arg(ap, const char *);
00255       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00256       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00257       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00258    }
00259 
00260    ast_str_append(&query, 0, ")}");
00261    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00262 
00263    /* Line oriented output */
00264    stringp = ast_str_buffer(buffer);
00265    while (*stringp <= ' ') {
00266       stringp++;
00267    }
00268    sscanf(stringp, "%30d", &rowcount);
00269 
00270    if (rowcount >= 0) {
00271       return (int)rowcount;
00272    }
00273 
00274    return -1;
00275 }
00276 
00277 static int update2_curl(const char *url, const char *unused, va_list ap)
00278 {
00279    struct ast_str *query, *buffer;
00280    char buf1[200], buf2[200];
00281    const char *newparam, *newval;
00282    char *stringp;
00283    int rowcount = -1, lookup = 1, first = 1;
00284 
00285    if (!ast_custom_function_find("CURL")) {
00286       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00287       return -1;
00288    }
00289 
00290    if (!(query = ast_str_thread_get(&query_buf, 1000)))
00291       return -1;
00292 
00293    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00294       return -1;
00295    }
00296 
00297    ast_str_set(&query, 0, "${CURL(%s/update?", url);
00298 
00299    for (;;) {
00300       if ((newparam = va_arg(ap, const char *)) == SENTINEL) {
00301          if (lookup) {
00302             lookup = 0;
00303             ast_str_append(&query, 0, ",");
00304             /* Back to the first parameter; we don't need a starting '&' */
00305             first = 1;
00306             continue;
00307          } else {
00308             break;
00309          }
00310       }
00311       newval = va_arg(ap, const char *);
00312       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00313       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00314       ast_str_append(&query, 0, "%s%s=%s", first ? "" : "&", buf1, buf2);
00315       first = 0;
00316    }
00317 
00318    ast_str_append(&query, 0, ")}");
00319    /* Proxies work, by setting CURLOPT options in the [globals] section of
00320     * extensions.conf.  Unfortunately, this means preloading pbx_config.so
00321     * so that they have an opportunity to be set prior to startup realtime
00322     * queries. */
00323    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00324 
00325    /* Line oriented output */
00326    stringp = ast_str_buffer(buffer);
00327    while (*stringp <= ' ') {
00328       stringp++;
00329    }
00330    sscanf(stringp, "%30d", &rowcount);
00331 
00332    if (rowcount >= 0) {
00333       return (int)rowcount;
00334    }
00335 
00336    return -1;
00337 }
00338 
00339 /*!
00340  * \brief Execute an INSERT query
00341  * \param url
00342  * \param unused
00343  * \param ap list containing one or more field/value set(s)
00344  *
00345  * Insert a new record into database table, prepare the sql statement.
00346  * All values to be changed are stored in ap list.
00347  * Sub-in the values to the prepared statement and execute it.
00348  *
00349  * \retval number of rows affected
00350  * \retval -1 on failure
00351 */
00352 static int store_curl(const char *url, const char *unused, va_list ap)
00353 {
00354    struct ast_str *query, *buffer;
00355    char buf1[256], buf2[256];
00356    const char *newparam, *newval;
00357    char *stringp;
00358    int i, rowcount = -1;
00359 
00360    if (!ast_custom_function_find("CURL")) {
00361       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00362       return -1;
00363    }
00364 
00365    if (!(query = ast_str_thread_get(&query_buf, 1000))) {
00366       return -1;
00367    }
00368 
00369    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00370       return -1;
00371    }
00372 
00373    ast_str_set(&query, 0, "${CURL(%s/store,", url);
00374 
00375    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00376       newval = va_arg(ap, const char *);
00377       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00378       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00379       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00380    }
00381 
00382    ast_str_append(&query, 0, ")}");
00383    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00384 
00385    stringp = ast_str_buffer(buffer);
00386    while (*stringp <= ' ') {
00387       stringp++;
00388    }
00389    sscanf(stringp, "%30d", &rowcount);
00390 
00391    if (rowcount >= 0) {
00392       return rowcount;
00393    }
00394 
00395    return -1;
00396 }
00397 
00398 /*!
00399  * \brief Execute an DELETE query
00400  * \param url
00401  * \param unused
00402  * \param keyfield where clause field
00403  * \param lookup value of field for where clause
00404  * \param ap list containing one or more field/value set(s)
00405  *
00406  * Delete a row from a database table, prepare the sql statement using keyfield and lookup
00407  * control the number of records to change. Additional params to match rows are stored in ap list.
00408  * Sub-in the values to the prepared statement and execute it.
00409  *
00410  * \retval number of rows affected
00411  * \retval -1 on failure
00412 */
00413 static int destroy_curl(const char *url, const char *unused, const char *keyfield, const char *lookup, va_list ap)
00414 {
00415    struct ast_str *query, *buffer;
00416    char buf1[200], buf2[200];
00417    const char *newparam, *newval;
00418    char *stringp;
00419    int i, rowcount = -1;
00420 
00421    if (!ast_custom_function_find("CURL")) {
00422       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00423       return -1;
00424    }
00425 
00426    if (!(query = ast_str_thread_get(&query_buf, 1000))) {
00427       return -1;
00428    }
00429 
00430    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00431       return -1;
00432    }
00433 
00434    ast_uri_encode(keyfield, buf1, sizeof(buf1), ast_uri_http);
00435    ast_uri_encode(lookup, buf2, sizeof(buf2), ast_uri_http);
00436    ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);
00437 
00438    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00439       newval = va_arg(ap, const char *);
00440       ast_uri_encode(newparam, buf1, sizeof(buf1), ast_uri_http);
00441       ast_uri_encode(newval, buf2, sizeof(buf2), ast_uri_http);
00442       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00443    }
00444 
00445    ast_str_append(&query, 0, ")}");
00446    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00447 
00448    /* Line oriented output */
00449    stringp = ast_str_buffer(buffer);
00450    while (*stringp <= ' ') {
00451       stringp++;
00452    }
00453    sscanf(stringp, "%30d", &rowcount);
00454 
00455    if (rowcount >= 0) {
00456       return (int)rowcount;
00457    }
00458 
00459    return -1;
00460 }
00461 
00462 static int require_curl(const char *url, const char *unused, va_list ap)
00463 {
00464    struct ast_str *query, *buffer;
00465    char *elm, field[256];
00466    int type, size;
00467 
00468    if (!ast_custom_function_find("CURL")) {
00469       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00470       return -1;
00471    }
00472 
00473    if (!(query = ast_str_thread_get(&query_buf, 100))) {
00474       return -1;
00475    }
00476 
00477    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00478       return -1;
00479    }
00480 
00481    ast_str_set(&query, 0, "${CURL(%s/require,", url);
00482 
00483    while ((elm = va_arg(ap, char *))) {
00484       type = va_arg(ap, require_type);
00485       size = va_arg(ap, int);
00486       ast_uri_encode(elm, field, sizeof(field), ast_uri_http);
00487       ast_str_append(&query, 0, "%s=%s%%3A%d", field,
00488          type == RQ_CHAR ? "char" :
00489          type == RQ_INTEGER1 ? "integer1" :
00490          type == RQ_UINTEGER1 ? "uinteger1" :
00491          type == RQ_INTEGER2 ? "integer2" :
00492          type == RQ_UINTEGER2 ? "uinteger2" :
00493          type == RQ_INTEGER3 ? "integer3" :
00494          type == RQ_UINTEGER3 ? "uinteger3" :
00495          type == RQ_INTEGER4 ? "integer4" :
00496          type == RQ_UINTEGER4 ? "uinteger4" :
00497          type == RQ_INTEGER8 ? "integer8" :
00498          type == RQ_UINTEGER8 ? "uinteger8" :
00499          type == RQ_DATE ? "date" :
00500          type == RQ_DATETIME ? "datetime" :
00501          type == RQ_FLOAT ? "float" :
00502          "unknown", size);
00503    }
00504 
00505    ast_str_append(&query, 0, ")}");
00506    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00507    return atoi(ast_str_buffer(buffer));
00508 }
00509 
00510 static struct ast_config *config_curl(const char *url, const char *unused, const char *file, struct ast_config *cfg, struct ast_flags flags, const char *sugg_incl, const char *who_asked)
00511 {
00512    struct ast_str *query, *buffer;
00513    char buf1[200];
00514    char *stringp, *line, *pair, *key;
00515    int last_cat_metric = -1, cat_metric = -1;
00516    struct ast_category *cat = NULL;
00517    char *cur_cat = "";
00518    char *category = "", *var_name = "", *var_val = "";
00519    struct ast_flags loader_flags = { 0 };
00520 
00521    if (!ast_custom_function_find("CURL")) {
00522       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00523       return NULL;
00524    }
00525 
00526    if (!(query = ast_str_thread_get(&query_buf, 100))) {
00527       return NULL;
00528    }
00529 
00530    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00531       return NULL;
00532    }
00533 
00534    ast_uri_encode(file, buf1, sizeof(buf1), ast_uri_http);
00535    ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
00536 
00537    /* Do the CURL query */
00538    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00539 
00540    /* Line oriented output */
00541    stringp = ast_str_buffer(buffer);
00542    cat = ast_config_get_current_category(cfg);
00543 
00544    while ((line = strsep(&stringp, "\r\n"))) {
00545       if (ast_strlen_zero(line)) {
00546          continue;
00547       }
00548 
00549       while ((pair = strsep(&line, "&"))) {
00550          key = strsep(&pair, "=");
00551          ast_uri_decode(key, ast_uri_http);
00552          if (pair) {
00553             ast_uri_decode(pair, ast_uri_http);
00554          }
00555 
00556          if (!strcasecmp(key, "category")) {
00557             category = S_OR(pair, "");
00558          } else if (!strcasecmp(key, "var_name")) {
00559             var_name = S_OR(pair, "");
00560          } else if (!strcasecmp(key, "var_val")) {
00561             var_val = S_OR(pair, "");
00562          } else if (!strcasecmp(key, "cat_metric")) {
00563             cat_metric = pair ? atoi(pair) : 0;
00564          }
00565       }
00566 
00567       if (!strcmp(var_name, "#include")) {
00568          if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
00569             return NULL;
00570       }
00571 
00572       if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
00573          if (!(cat = ast_category_new(category, "", 99999)))
00574             break;
00575          cur_cat = category;
00576          last_cat_metric = cat_metric;
00577          ast_category_append(cfg, cat);
00578       }
00579       ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
00580    }
00581 
00582    return cfg;
00583 }
00584 
00585 static struct ast_config_engine curl_engine = {
00586    .name = "curl",
00587    .load_func = config_curl,
00588    .realtime_func = realtime_curl,
00589    .realtime_multi_func = realtime_multi_curl,
00590    .store_func = store_curl,
00591    .destroy_func = destroy_curl,
00592    .update_func = update_curl,
00593    .update2_func = update2_curl,
00594    .require_func = require_curl,
00595 };
00596 
00597 static int reload_module(void)
00598 {
00599    struct ast_flags flags = { CONFIG_FLAG_NOREALTIME };
00600    struct ast_config *cfg;
00601    struct ast_variable *var;
00602 
00603    if (!(cfg = ast_config_load("res_curl.conf", flags))) {
00604       return 0;
00605    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
00606       ast_log(LOG_WARNING, "res_curl.conf could not be parsed!\n");
00607       return 0;
00608    }
00609 
00610    if (!(var = ast_variable_browse(cfg, "globals")) && !(var = ast_variable_browse(cfg, "global")) && !(var = ast_variable_browse(cfg, "general"))) {
00611       ast_log(LOG_WARNING, "[globals] not found in res_curl.conf\n");
00612       ast_config_destroy(cfg);
00613       return 0;
00614    }
00615 
00616    for (; var; var = var->next) {
00617       if (strncmp(var->name, "CURLOPT(", 8)) {
00618          char name[256];
00619          snprintf(name, sizeof(name), "CURLOPT(%s)", var->name);
00620          pbx_builtin_setvar_helper(NULL, name, var->value);
00621       } else {
00622          pbx_builtin_setvar_helper(NULL, var->name, var->value);
00623       }
00624    }
00625    ast_config_destroy(cfg);
00626    return 0;
00627 }
00628 
00629 static int unload_module(void)
00630 {
00631    ast_config_engine_deregister(&curl_engine);
00632    ast_verb(1, "res_config_curl unloaded.\n");
00633    return 0;
00634 }
00635 
00636 static int load_module(void)
00637 {
00638    if (!ast_module_check("res_curl.so")) {
00639       if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00640          ast_log(LOG_ERROR, "Cannot load res_curl, so res_config_curl cannot be loaded\n");
00641          return AST_MODULE_LOAD_DECLINE;
00642       }
00643    }
00644 
00645    if (!ast_module_check("func_curl.so")) {
00646       if (ast_load_resource("func_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00647          ast_log(LOG_ERROR, "Cannot load func_curl, so res_config_curl cannot be loaded\n");
00648          return AST_MODULE_LOAD_DECLINE;
00649       }
00650    }
00651 
00652    reload_module();
00653 
00654    ast_config_engine_register(&curl_engine);
00655    ast_verb(1, "res_config_curl loaded.\n");
00656    return 0;
00657 }
00658 
00659 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime Curl configuration",
00660       .load = load_module,
00661       .unload = unload_module,
00662       .reload = reload_module,
00663       .load_pri = AST_MODPRI_REALTIME_DRIVER,
00664    );

Generated on Thu Oct 11 06:33:52 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6