Mon Jun 27 16:50:55 2011

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

Generated on Mon Jun 27 16:50:55 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7