Mon Oct 8 12:39:04 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: 362354 $")
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    const int EncodeSpecialChars = 1;
00070 
00071    if (!ast_custom_function_find("CURL")) {
00072       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00073       return NULL;
00074    }
00075 
00076    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00077       return NULL;
00078    }
00079 
00080    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00081       return NULL;
00082    }
00083 
00084    ast_str_set(&query, 0, "${CURL(%s/single,", url);
00085 
00086    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00087       newval = va_arg(ap, const char *);
00088       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00089       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00090       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00091    }
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);
00105       if (pair) {
00106          ast_uri_decode(pair);
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    const int EncodeSpecialChars = 1;
00141    struct ast_variable *var = NULL;
00142    struct ast_config *cfg = NULL;
00143    struct ast_category *cat = NULL;
00144 
00145    if (!ast_custom_function_find("CURL")) {
00146       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00147       return NULL;
00148    }
00149 
00150    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00151       return NULL;
00152    }
00153 
00154    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00155       return NULL;
00156    }
00157 
00158    ast_str_set(&query, 0, "${CURL(%s/multi,", url);
00159 
00160    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00161       newval = va_arg(ap, const char *);
00162       if (i == 0) {
00163          char *op;
00164          initfield = ast_strdupa(newparam);
00165          if ((op = strchr(initfield, ' ')))
00166             *op = '\0';
00167       }
00168       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00169       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00170       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00171    }
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);
00196          if (pair) {
00197             ast_uri_decode(pair);
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    const int EncodeSpecialChars = 1;
00238 
00239    if (!ast_custom_function_find("CURL")) {
00240       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00241       return -1;
00242    }
00243 
00244    if (!(query = ast_str_thread_get(&query_buf, 16))) {
00245       return -1;
00246    }
00247 
00248    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00249       return -1;
00250    }
00251 
00252    ast_uri_encode(keyfield, buf1, sizeof(buf1), EncodeSpecialChars);
00253    ast_uri_encode(lookup, buf2, sizeof(buf2), EncodeSpecialChars);
00254    ast_str_set(&query, 0, "${CURL(%s/update?%s=%s,", url, buf1, buf2);
00255 
00256    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00257       newval = va_arg(ap, const char *);
00258       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00259       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00260       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00261    }
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    const int EncodeSpecialChars = 1;
00288 
00289    if (!ast_custom_function_find("CURL")) {
00290       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00291       return -1;
00292    }
00293 
00294    if (!(query = ast_str_thread_get(&query_buf, 1000)))
00295       return -1;
00296 
00297    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00298       return -1;
00299    }
00300 
00301    ast_str_set(&query, 0, "${CURL(%s/update?", url);
00302 
00303    for (;;) {
00304       if ((newparam = va_arg(ap, const char *)) == SENTINEL) {
00305          if (lookup) {
00306             lookup = 0;
00307             ast_str_append(&query, 0, ",");
00308             /* Back to the first parameter; we don't need a starting '&' */
00309             first = 1;
00310             continue;
00311          } else {
00312             break;
00313          }
00314       }
00315       newval = va_arg(ap, const char *);
00316       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00317       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00318       ast_str_append(&query, 0, "%s%s=%s", first ? "" : "&", buf1, buf2);
00319       first = 0;
00320    }
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    const int EncodeSpecialChars = 1;
00364 
00365    if (!ast_custom_function_find("CURL")) {
00366       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00367       return -1;
00368    }
00369 
00370    if (!(query = ast_str_thread_get(&query_buf, 1000))) {
00371       return -1;
00372    }
00373 
00374    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00375       return -1;
00376    }
00377 
00378    ast_str_set(&query, 0, "${CURL(%s/store,", url);
00379 
00380    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00381       newval = va_arg(ap, const char *);
00382       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00383       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00384       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00385    }
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    const int EncodeSpecialChars = 1;
00426 
00427    if (!ast_custom_function_find("CURL")) {
00428       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00429       return -1;
00430    }
00431 
00432    if (!(query = ast_str_thread_get(&query_buf, 1000))) {
00433       return -1;
00434    }
00435 
00436    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00437       return -1;
00438    }
00439 
00440    ast_uri_encode(keyfield, buf1, sizeof(buf1), EncodeSpecialChars);
00441    ast_uri_encode(lookup, buf2, sizeof(buf2), EncodeSpecialChars);
00442    ast_str_set(&query, 0, "${CURL(%s/destroy,%s=%s&", url, buf1, buf2);
00443 
00444    for (i = 0; (newparam = va_arg(ap, const char *)); i++) {
00445       newval = va_arg(ap, const char *);
00446       ast_uri_encode(newparam, buf1, sizeof(buf1), EncodeSpecialChars);
00447       ast_uri_encode(newval, buf2, sizeof(buf2), EncodeSpecialChars);
00448       ast_str_append(&query, 0, "%s%s=%s", i > 0 ? "&" : "", buf1, buf2);
00449    }
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    const int EncodeSpecialChars = 1;
00474 
00475    if (!ast_custom_function_find("CURL")) {
00476       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00477       return -1;
00478    }
00479 
00480    if (!(query = ast_str_thread_get(&query_buf, 100))) {
00481       return -1;
00482    }
00483 
00484    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00485       return -1;
00486    }
00487 
00488    ast_str_set(&query, 0, "${CURL(%s/require,", url);
00489 
00490    while ((elm = va_arg(ap, char *))) {
00491       type = va_arg(ap, require_type);
00492       size = va_arg(ap, int);
00493       ast_uri_encode(elm, field, sizeof(field), EncodeSpecialChars);
00494       ast_str_append(&query, 0, "%s=%s%%3A%d", field,
00495          type == RQ_CHAR ? "char" :
00496          type == RQ_INTEGER1 ? "integer1" :
00497          type == RQ_UINTEGER1 ? "uinteger1" :
00498          type == RQ_INTEGER2 ? "integer2" :
00499          type == RQ_UINTEGER2 ? "uinteger2" :
00500          type == RQ_INTEGER3 ? "integer3" :
00501          type == RQ_UINTEGER3 ? "uinteger3" :
00502          type == RQ_INTEGER4 ? "integer4" :
00503          type == RQ_UINTEGER4 ? "uinteger4" :
00504          type == RQ_INTEGER8 ? "integer8" :
00505          type == RQ_UINTEGER8 ? "uinteger8" :
00506          type == RQ_DATE ? "date" :
00507          type == RQ_DATETIME ? "datetime" :
00508          type == RQ_FLOAT ? "float" :
00509          "unknown", size);
00510    }
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    const int EncodeSpecialChars = 1;
00523    int last_cat_metric = -1, cat_metric = -1;
00524    struct ast_category *cat = NULL;
00525    char *cur_cat = "";
00526    char *category = "", *var_name = "", *var_val = "";
00527    struct ast_flags loader_flags = { 0 };
00528 
00529    if (!ast_custom_function_find("CURL")) {
00530       ast_log(LOG_ERROR, "func_curl.so must be loaded in order to use res_config_curl.so!!\n");
00531       return NULL;
00532    }
00533 
00534    if (!(query = ast_str_thread_get(&query_buf, 100))) {
00535       return NULL;
00536    }
00537 
00538    if (!(buffer = ast_str_thread_get(&result_buf, 16))) {
00539       return NULL;
00540    }
00541 
00542    ast_uri_encode(file, buf1, sizeof(buf1), EncodeSpecialChars);
00543    ast_str_set(&query, 0, "${CURL(%s/static?file=%s)}", url, buf1);
00544 
00545    /* Do the CURL query */
00546    ast_str_substitute_variables(&buffer, 0, NULL, ast_str_buffer(query));
00547 
00548    /* Line oriented output */
00549    stringp = ast_str_buffer(buffer);
00550    cat = ast_config_get_current_category(cfg);
00551 
00552    while ((line = strsep(&stringp, "\r\n"))) {
00553       if (ast_strlen_zero(line)) {
00554          continue;
00555       }
00556 
00557       while ((pair = strsep(&line, "&"))) {
00558          key = strsep(&pair, "=");
00559          ast_uri_decode(key);
00560          if (pair) {
00561             ast_uri_decode(pair);
00562          }
00563 
00564          if (!strcasecmp(key, "category")) {
00565             category = S_OR(pair, "");
00566          } else if (!strcasecmp(key, "var_name")) {
00567             var_name = S_OR(pair, "");
00568          } else if (!strcasecmp(key, "var_val")) {
00569             var_val = S_OR(pair, "");
00570          } else if (!strcasecmp(key, "cat_metric")) {
00571             cat_metric = pair ? atoi(pair) : 0;
00572          }
00573       }
00574 
00575       if (!strcmp(var_name, "#include")) {
00576          if (!ast_config_internal_load(var_val, cfg, loader_flags, "", who_asked))
00577             return NULL;
00578       }
00579 
00580       if (!cat || strcmp(category, cur_cat) || last_cat_metric != cat_metric) {
00581          if (!(cat = ast_category_new(category, "", 99999)))
00582             break;
00583          cur_cat = category;
00584          last_cat_metric = cat_metric;
00585          ast_category_append(cfg, cat);
00586       }
00587       ast_variable_append(cat, ast_variable_new(var_name, var_val, ""));
00588    }
00589 
00590    return cfg;
00591 }
00592 
00593 static struct ast_config_engine curl_engine = {
00594    .name = "curl",
00595    .load_func = config_curl,
00596    .realtime_func = realtime_curl,
00597    .realtime_multi_func = realtime_multi_curl,
00598    .store_func = store_curl,
00599    .destroy_func = destroy_curl,
00600    .update_func = update_curl,
00601    .update2_func = update2_curl,
00602    .require_func = require_curl,
00603 };
00604 
00605 static int reload_module(void)
00606 {
00607    struct ast_flags flags = { CONFIG_FLAG_NOREALTIME };
00608    struct ast_config *cfg;
00609    struct ast_variable *var;
00610 
00611    if (!(cfg = ast_config_load("res_curl.conf", flags))) {
00612       return 0;
00613    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
00614       ast_log(LOG_WARNING, "res_curl.conf could not be parsed!\n");
00615       return 0;
00616    }
00617 
00618    if (!(var = ast_variable_browse(cfg, "globals")) && !(var = ast_variable_browse(cfg, "global")) && !(var = ast_variable_browse(cfg, "general"))) {
00619       ast_log(LOG_WARNING, "[globals] not found in res_curl.conf\n");
00620       ast_config_destroy(cfg);
00621       return 0;
00622    }
00623 
00624    for (; var; var = var->next) {
00625       if (strncmp(var->name, "CURLOPT(", 8)) {
00626          char name[256];
00627          snprintf(name, sizeof(name), "CURLOPT(%s)", var->name);
00628          pbx_builtin_setvar_helper(NULL, name, var->value);
00629       } else {
00630          pbx_builtin_setvar_helper(NULL, var->name, var->value);
00631       }
00632    }
00633    ast_config_destroy(cfg);
00634    return 0;
00635 }
00636 
00637 static int unload_module(void)
00638 {
00639    ast_config_engine_deregister(&curl_engine);
00640    ast_verb(1, "res_config_curl unloaded.\n");
00641    return 0;
00642 }
00643 
00644 static int load_module(void)
00645 {
00646    if (!ast_module_check("res_curl.so")) {
00647       if (ast_load_resource("res_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00648          ast_log(LOG_ERROR, "Cannot load res_curl, so res_config_curl cannot be loaded\n");
00649          return AST_MODULE_LOAD_DECLINE;
00650       }
00651    }
00652 
00653    if (!ast_module_check("func_curl.so")) {
00654       if (ast_load_resource("func_curl.so") != AST_MODULE_LOAD_SUCCESS) {
00655          ast_log(LOG_ERROR, "Cannot load func_curl, so res_config_curl cannot be loaded\n");
00656          return AST_MODULE_LOAD_DECLINE;
00657       }
00658    }
00659 
00660    reload_module();
00661 
00662    ast_config_engine_register(&curl_engine);
00663    ast_verb(1, "res_config_curl loaded.\n");
00664    return 0;
00665 }
00666 
00667 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Realtime Curl configuration",
00668       .load = load_module,
00669       .unload = unload_module,
00670       .reload = reload_module,
00671       .load_pri = AST_MODPRI_REALTIME_DRIVER,
00672    );

Generated on Mon Oct 8 12:39:04 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7