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

Generated on Sat Mar 10 01:54:23 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7