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

Generated on Sat Feb 11 06:33:21 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6