Sun Dec 18 20:55:40 2011

Asterisk developer's documentation


http.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.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 /*!
00020  * \file 
00021  * \brief http server for AMI access
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * This program implements a tiny http server
00026  * and was inspired by micro-httpd by Jef Poskanzer 
00027  * 
00028  * \ref AstHTTP - AMI over the http protocol
00029  */
00030 
00031 #include "asterisk.h"
00032 
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 114600 $")
00034 
00035 #include <sys/types.h>
00036 #include <stdio.h>
00037 #include <unistd.h>
00038 #include <stdlib.h>
00039 #include <time.h>
00040 #include <string.h>
00041 #include <netinet/in.h>
00042 #include <sys/time.h>
00043 #include <sys/socket.h>
00044 #include <sys/stat.h>
00045 #include <sys/signal.h>
00046 #include <arpa/inet.h>
00047 #include <errno.h>
00048 #include <fcntl.h>
00049 #include <pthread.h>
00050 
00051 #include "asterisk/cli.h"
00052 #include "asterisk/http.h"
00053 #include "asterisk/utils.h"
00054 #include "asterisk/strings.h"
00055 #include "asterisk/options.h"
00056 #include "asterisk/config.h"
00057 #include "asterisk/version.h"
00058 #include "asterisk/manager.h"
00059 
00060 #define MAX_PREFIX 80
00061 #define DEFAULT_PREFIX "/asterisk"
00062 #define DEFAULT_SESSION_LIMIT 100
00063 
00064 struct ast_http_server_instance {
00065    FILE *f;
00066    int fd;
00067    struct sockaddr_in requestor;
00068    ast_http_callback callback;
00069 };
00070 
00071 AST_RWLOCK_DEFINE_STATIC(uris_lock);
00072 static struct ast_http_uri *uris;
00073 
00074 static int httpfd = -1;
00075 static pthread_t master = AST_PTHREADT_NULL;
00076 static char prefix[MAX_PREFIX];
00077 static int prefix_len;
00078 static struct sockaddr_in oldsin;
00079 static int enablestatic;
00080 static int session_limit = DEFAULT_SESSION_LIMIT;
00081 static int session_count = 0;
00082 
00083 /*! \brief Limit the kinds of files we're willing to serve up */
00084 static struct {
00085    const char *ext;
00086    const char *mtype;
00087 } mimetypes[] = {
00088    { "png", "image/png" },
00089    { "jpg", "image/jpeg" },
00090    { "js", "application/x-javascript" },
00091    { "wav", "audio/x-wav" },
00092    { "mp3", "audio/mpeg" },
00093    { "svg", "image/svg+xml" },
00094    { "svgz", "image/svg+xml" },
00095    { "gif", "image/gif" },
00096 };
00097 
00098 static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
00099 {
00100    int x;
00101    if (ftype) {
00102       for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) {
00103          if (!strcasecmp(ftype, mimetypes[x].ext))
00104             return mimetypes[x].mtype;
00105       }
00106    }
00107    snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain");
00108    return wkspace;
00109 }
00110 
00111 static char *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
00112 {
00113    char result[4096];
00114    char *c=result;
00115    char *path;
00116    char *ftype;
00117    const char *mtype;
00118    char wkspace[80];
00119    struct stat st;
00120    int len;
00121    int fd;
00122    void *blob;
00123 
00124    /* Yuck.  I'm not really sold on this, but if you don't deliver static content it makes your configuration 
00125       substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */
00126    if (!enablestatic || ast_strlen_zero(uri))
00127       goto out403;
00128    /* Disallow any funny filenames at all */
00129    if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0]))
00130       goto out403;
00131    if (strstr(uri, "/.."))
00132       goto out403;
00133       
00134    if ((ftype = strrchr(uri, '.')))
00135       ftype++;
00136    mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace));
00137    
00138    /* Cap maximum length */
00139    len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5;
00140    if (len > 1024)
00141       goto out403;
00142       
00143    path = alloca(len);
00144    sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri);
00145    if (stat(path, &st))
00146       goto out404;
00147    if (S_ISDIR(st.st_mode))
00148       goto out404;
00149    fd = open(path, O_RDONLY);
00150    if (fd < 0)
00151       goto out403;
00152    
00153    len = st.st_size + strlen(mtype) + 40;
00154    
00155    blob = malloc(len);
00156    if (blob) {
00157       c = blob;
00158       sprintf(c, "Content-type: %s\r\n\r\n", mtype);
00159       c += strlen(c);
00160       *contentlength = read(fd, c, st.st_size);
00161       if (*contentlength < 0) {
00162          close(fd);
00163          free(blob);
00164          goto out403;
00165       }
00166    }
00167    close(fd);
00168    return blob;
00169 
00170 out404:
00171    *status = 404;
00172    *title = strdup("Not Found");
00173    return ast_http_error(404, "Not Found", NULL, "Nothing to see here.  Move along.");
00174 
00175 out403:
00176    *status = 403;
00177    *title = strdup("Access Denied");
00178    return ast_http_error(403, "Access Denied", NULL, "Sorry, I cannot let you do that, Dave.");
00179 }
00180 
00181 
00182 static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
00183 {
00184    char result[4096];
00185    size_t reslen = sizeof(result);
00186    char *c=result;
00187    struct ast_variable *v;
00188 
00189    ast_build_string(&c, &reslen,
00190       "\r\n"
00191       "<title>Asterisk HTTP Status</title>\r\n"
00192       "<body bgcolor=\"#ffffff\">\r\n"
00193       "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n"
00194       "<h2>&nbsp;&nbsp;Asterisk&trade; HTTP Status</h2></td></tr>\r\n");
00195 
00196    ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix);
00197    ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n",
00198          ast_inet_ntoa(oldsin.sin_addr));
00199    ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n",
00200          ntohs(oldsin.sin_port));
00201    ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
00202    v = vars;
00203    while(v) {
00204       if (strncasecmp(v->name, "cookie_", 7))
00205          ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
00206       v = v->next;
00207    }
00208    ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n");
00209    v = vars;
00210    while(v) {
00211       if (!strncasecmp(v->name, "cookie_", 7))
00212          ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value);
00213       v = v->next;
00214    }
00215    ast_build_string(&c, &reslen, "</table><center><font size=\"-1\"><i>Asterisk and Digium are registered trademarks of Digium, Inc.</i></font></center></body>\r\n");
00216    return strdup(result);
00217 }
00218 
00219 static struct ast_http_uri statusuri = {
00220    .callback = httpstatus_callback,
00221    .description = "Asterisk HTTP General Status",
00222    .uri = "httpstatus",
00223    .has_subtree = 0,
00224 };
00225    
00226 static struct ast_http_uri staticuri = {
00227    .callback = static_callback,
00228    .description = "Asterisk HTTP Static Delivery",
00229    .uri = "static",
00230    .has_subtree = 1,
00231    .static_content = 1,
00232 };
00233    
00234 char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
00235 {
00236    char *c = NULL;
00237    asprintf(&c,
00238       "Content-type: text/html\r\n"
00239       "%s"
00240       "\r\n"
00241       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00242       "<html><head>\r\n"
00243       "<title>%d %s</title>\r\n"
00244       "</head><body>\r\n"
00245       "<h1>%s</h1>\r\n"
00246       "<p>%s</p>\r\n"
00247       "<hr />\r\n"
00248       "<address>Asterisk Server</address>\r\n"
00249       "</body></html>\r\n",
00250          (extra_header ? extra_header : ""), status, title, title, text);
00251    return c;
00252 }
00253 
00254 int ast_http_uri_link(struct ast_http_uri *urih)
00255 {
00256    struct ast_http_uri *prev;
00257 
00258    ast_rwlock_wrlock(&uris_lock);
00259    prev = uris;
00260    if (!uris || strlen(uris->uri) <= strlen(urih->uri)) {
00261       urih->next = uris;
00262       uris = urih;
00263    } else {
00264       while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri)))
00265          prev = prev->next;
00266       /* Insert it here */
00267       urih->next = prev->next;
00268       prev->next = urih;
00269    }
00270    ast_rwlock_unlock(&uris_lock);
00271 
00272    return 0;
00273 }  
00274 
00275 void ast_http_uri_unlink(struct ast_http_uri *urih)
00276 {
00277    struct ast_http_uri *prev;
00278 
00279    ast_rwlock_wrlock(&uris_lock);
00280    if (!uris) {
00281       ast_rwlock_unlock(&uris_lock);
00282       return;
00283    }
00284    prev = uris;
00285    if (uris == urih) {
00286       uris = uris->next;
00287    }
00288    while(prev->next) {
00289       if (prev->next == urih) {
00290          prev->next = urih->next;
00291          break;
00292       }
00293       prev = prev->next;
00294    }
00295    ast_rwlock_unlock(&uris_lock);
00296 }
00297 
00298 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, 
00299    char **title, int *contentlength, struct ast_variable **cookies, 
00300    unsigned int *static_content)
00301 {
00302    char *c;
00303    char *turi;
00304    char *params;
00305    char *var;
00306    char *val;
00307    struct ast_http_uri *urih=NULL;
00308    int len;
00309    struct ast_variable *vars=NULL, *v, *prev = NULL;
00310    
00311    
00312    params = strchr(uri, '?');
00313    if (params) {
00314       *params = '\0';
00315       params++;
00316       while ((var = strsep(&params, "&"))) {
00317          val = strchr(var, '=');
00318          if (val) {
00319             *val = '\0';
00320             val++;
00321             ast_uri_decode(val);
00322          } else 
00323             val = "";
00324          ast_uri_decode(var);
00325          if ((v = ast_variable_new(var, val))) {
00326             if (vars)
00327                prev->next = v;
00328             else
00329                vars = v;
00330             prev = v;
00331          }
00332       }
00333    }
00334    if (prev)
00335       prev->next = *cookies;
00336    else
00337       vars = *cookies;
00338    *cookies = NULL;
00339    ast_uri_decode(uri);
00340    if (!strncasecmp(uri, prefix, prefix_len)) {
00341       uri += prefix_len;
00342       if (!*uri || (*uri == '/')) {
00343          if (*uri == '/')
00344             uri++;
00345          ast_rwlock_rdlock(&uris_lock);
00346          urih = uris;
00347          while(urih) {
00348             len = strlen(urih->uri);
00349             if (!strncasecmp(urih->uri, uri, len)) {
00350                if (!uri[len] || uri[len] == '/') {
00351                   turi = uri + len;
00352                   if (*turi == '/')
00353                      turi++;
00354                   if (!*turi || urih->has_subtree) {
00355                      uri = turi;
00356                      break;
00357                   }
00358                }
00359             }
00360             urih = urih->next;
00361          }
00362          if (!urih)
00363             ast_rwlock_unlock(&uris_lock);
00364       }
00365    }
00366    if (urih) {
00367       if (urih->static_content)
00368          *static_content = 1;
00369       c = urih->callback(sin, uri, vars, status, title, contentlength);
00370       ast_rwlock_unlock(&uris_lock);
00371    } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
00372       /* Special case: If no prefix, and no URI, send to /static/index.html */
00373       c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for...");
00374       *status = 302;
00375       *title = strdup("Moved Temporarily");
00376    } else {
00377       c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
00378       *status = 404;
00379       *title = strdup("Not Found");
00380    }
00381    ast_variables_destroy(vars);
00382    return c;
00383 }
00384 
00385 static struct ast_variable *parse_cookies(char *cookies)
00386 {
00387    char *cur;
00388    struct ast_variable *vars = NULL, *var;
00389 
00390    /* Skip Cookie: */
00391    cookies += 8;
00392 
00393    while ((cur = strsep(&cookies, ";"))) {
00394       char *name, *val;
00395       
00396       name = val = cur;
00397       strsep(&val, "=");
00398 
00399       if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
00400          continue;
00401       }
00402 
00403       name = ast_strip(name);
00404       val = ast_strip_quoted(val, "\"", "\"");
00405 
00406       if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
00407          continue;
00408       }
00409 
00410       if (option_debug) {
00411          ast_log(LOG_DEBUG, "mmm ... cookie!  Name: '%s'  Value: '%s'\n", name, val);
00412       }
00413 
00414       var = ast_variable_new(name, val);
00415       var->next = vars;
00416       vars = var;
00417    }
00418 
00419    return vars;
00420 }
00421 
00422 static void *ast_httpd_helper_thread(void *data)
00423 {
00424    char buf[4096];
00425    char cookie[4096];
00426    char timebuf[256];
00427    struct ast_http_server_instance *ser = data;
00428    struct ast_variable *vars = NULL;
00429    char *uri, *c, *title=NULL;
00430    int status = 200, contentlength = 0;
00431    time_t t;
00432    unsigned int static_content = 0;
00433 
00434    if (fgets(buf, sizeof(buf), ser->f)) {
00435       /* Skip method */
00436       uri = buf;
00437       while(*uri && (*uri > 32))
00438          uri++;
00439       if (*uri) {
00440          *uri = '\0';
00441          uri++;
00442       }
00443 
00444       /* Skip white space */
00445       while (*uri && (*uri < 33))
00446          uri++;
00447 
00448       if (*uri) {
00449          c = uri;
00450          while (*c && (*c > 32))
00451              c++;
00452          if (*c) {
00453             *c = '\0';
00454          }
00455       }
00456 
00457       while (fgets(cookie, sizeof(cookie), ser->f)) {
00458          /* Trim trailing characters */
00459          while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
00460             cookie[strlen(cookie) - 1] = '\0';
00461          }
00462          if (ast_strlen_zero(cookie))
00463             break;
00464          if (!strncasecmp(cookie, "Cookie: ", 8)) {
00465             vars = parse_cookies(cookie);
00466          }
00467       }
00468 
00469       if (*uri) {
00470          if (!strcasecmp(buf, "get")) 
00471             c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
00472          else 
00473             c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
00474       } else 
00475          c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
00476 
00477       /* If they aren't mopped up already, clean up the cookies */
00478       if (vars)
00479          ast_variables_destroy(vars);
00480 
00481       if (!c)
00482          c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
00483       if (c) {
00484          time(&t);
00485          strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
00486          ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
00487          ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION);
00488          ast_cli(ser->fd, "Date: %s\r\n", timebuf);
00489          ast_cli(ser->fd, "Connection: close\r\n");
00490          if (!static_content)
00491             ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n");
00492             /* We set the no-cache headers only for dynamic content.
00493             * If you want to make sure the static file you requested is not from cache,
00494             * append a random variable to your GET request.  Ex: 'something.html?r=109987734'
00495             */
00496 
00497          if (contentlength) {
00498             char *tmp;
00499             tmp = strstr(c, "\r\n\r\n");
00500             if (tmp) {
00501                ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
00502                write(ser->fd, c, (tmp + 4 - c));
00503                write(ser->fd, tmp + 4, contentlength);
00504             }
00505          } else
00506             ast_cli(ser->fd, "%s", c);
00507          free(c);
00508       }
00509       if (title)
00510          free(title);
00511    }
00512    fclose(ser->f);
00513    free(ser);
00514    ast_atomic_fetchadd_int(&session_count, -1);
00515    return NULL;
00516 }
00517 
00518 static void *http_root(void *data)
00519 {
00520    int fd;
00521    struct sockaddr_in sin;
00522    socklen_t sinlen;
00523    struct ast_http_server_instance *ser;
00524    pthread_t launched;
00525    pthread_attr_t attr;
00526    
00527    for (;;) {
00528       int flags;
00529 
00530       ast_wait_for_input(httpfd, -1);
00531       sinlen = sizeof(sin);
00532       fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
00533 
00534       if (fd < 0) {
00535          if ((errno != EAGAIN) && (errno != EINTR))
00536             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00537          continue;
00538       }
00539 
00540       if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) {
00541          close(fd);
00542          continue;
00543       }
00544 
00545       ser = ast_calloc(1, sizeof(*ser));
00546       if (!ser) {
00547          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00548          close(fd);
00549          ast_atomic_fetchadd_int(&session_count, -1);
00550          continue;
00551       }
00552       flags = fcntl(fd, F_GETFL);
00553       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00554       ser->fd = fd;
00555       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00556       if ((ser->f = fdopen(ser->fd, "w+"))) {
00557          pthread_attr_init(&attr);
00558          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00559          
00560          if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
00561             ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00562             fclose(ser->f);
00563             free(ser);
00564             ast_atomic_fetchadd_int(&session_count, -1);
00565          }
00566          pthread_attr_destroy(&attr);
00567       } else {
00568          ast_log(LOG_WARNING, "fdopen failed!\n");
00569          close(ser->fd);
00570          free(ser);
00571          ast_atomic_fetchadd_int(&session_count, -1);
00572       }
00573    }
00574    return NULL;
00575 }
00576 
00577 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
00578 {
00579    char *c;
00580    c = buf;
00581    ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
00582    if (expires)
00583       ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
00584    ast_build_string(&c, &buflen, "\r\n");
00585    return buf;
00586 }
00587 
00588 
00589 static void http_server_start(struct sockaddr_in *sin)
00590 {
00591    int flags;
00592    int x = 1;
00593    
00594    /* Do nothing if nothing has changed */
00595    if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
00596       ast_log(LOG_DEBUG, "Nothing changed in http\n");
00597       return;
00598    }
00599    
00600    memcpy(&oldsin, sin, sizeof(oldsin));
00601    
00602    /* Shutdown a running server if there is one */
00603    if (master != AST_PTHREADT_NULL) {
00604       pthread_cancel(master);
00605       pthread_kill(master, SIGURG);
00606       pthread_join(master, NULL);
00607    }
00608    
00609    if (httpfd != -1)
00610       close(httpfd);
00611 
00612    /* If there's no new server, stop here */
00613    if (!sin->sin_family)
00614       return;
00615    
00616    
00617    httpfd = socket(AF_INET, SOCK_STREAM, 0);
00618    if (httpfd < 0) {
00619       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00620       return;
00621    }
00622    
00623    setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00624    if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
00625       ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
00626          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00627          strerror(errno));
00628       close(httpfd);
00629       httpfd = -1;
00630       return;
00631    }
00632    if (listen(httpfd, 10)) {
00633       ast_log(LOG_NOTICE, "Unable to listen!\n");
00634       close(httpfd);
00635       httpfd = -1;
00636       return;
00637    }
00638    flags = fcntl(httpfd, F_GETFL);
00639    fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
00640    if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
00641       ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
00642             ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00643             strerror(errno));
00644       close(httpfd);
00645       httpfd = -1;
00646    }
00647 }
00648 
00649 static int __ast_http_load(int reload)
00650 {
00651    struct ast_config *cfg;
00652    struct ast_variable *v;
00653    int enabled=0;
00654    int newenablestatic=0;
00655    struct sockaddr_in sin;
00656    struct hostent *hp;
00657    struct ast_hostent ahp;
00658    char newprefix[MAX_PREFIX];
00659 
00660    memset(&sin, 0, sizeof(sin));
00661    sin.sin_port = htons(8088);
00662 
00663    strcpy(newprefix, DEFAULT_PREFIX);
00664 
00665    cfg = ast_config_load("http.conf");
00666    if (cfg) {
00667       v = ast_variable_browse(cfg, "general");
00668       while(v) {
00669          if (!strcasecmp(v->name, "enabled"))
00670             enabled = ast_true(v->value);
00671          else if (!strcasecmp(v->name, "enablestatic"))
00672             newenablestatic = ast_true(v->value);
00673          else if (!strcasecmp(v->name, "bindport"))
00674             sin.sin_port = ntohs(atoi(v->value));
00675          else if (!strcasecmp(v->name, "bindaddr")) {
00676             if ((hp = ast_gethostbyname(v->value, &ahp))) {
00677                memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00678             } else {
00679                ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
00680             }
00681          } else if (!strcasecmp(v->name, "prefix")) {
00682             if (!ast_strlen_zero(v->value)) {
00683                newprefix[0] = '/';
00684                ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
00685             } else {
00686                newprefix[0] = '\0';
00687             }
00688          } else if (!strcasecmp(v->name, "sessionlimit")) {
00689             int limit = atoi(v->value);
00690 
00691             if (limit < 1) {
00692                ast_log(LOG_WARNING, "Invalid sessionlimit value '%s', using default value\n", v->value);
00693                session_limit = DEFAULT_SESSION_LIMIT;
00694             } else {
00695                session_limit = limit;
00696             }
00697          }
00698 
00699          v = v->next;
00700       }
00701       ast_config_destroy(cfg);
00702    }
00703    if (enabled)
00704       sin.sin_family = AF_INET;
00705    if (strcmp(prefix, newprefix)) {
00706       ast_copy_string(prefix, newprefix, sizeof(prefix));
00707       prefix_len = strlen(prefix);
00708    }
00709    enablestatic = newenablestatic;
00710 
00711    http_server_start(&sin);
00712 
00713 
00714    return 0;
00715 }
00716 
00717 static int handle_show_http(int fd, int argc, char *argv[])
00718 {
00719    struct ast_http_uri *urih;
00720 
00721    if (argc != 3)
00722       return RESULT_SHOWUSAGE;
00723 
00724    ast_cli(fd, "HTTP Server Status:\n");
00725    ast_cli(fd, "Prefix: %s\n", prefix);
00726    if (oldsin.sin_family)
00727       ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
00728          ast_inet_ntoa(oldsin.sin_addr),
00729          ntohs(oldsin.sin_port));
00730    else
00731       ast_cli(fd, "Server Disabled\n\n");
00732    ast_cli(fd, "Enabled URI's:\n");
00733    ast_rwlock_rdlock(&uris_lock);
00734    urih = uris;
00735    while(urih){
00736       ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
00737       urih = urih->next;
00738    }
00739    if (!uris)
00740       ast_cli(fd, "None.\n");
00741    ast_rwlock_unlock(&uris_lock);
00742 
00743    return RESULT_SUCCESS;
00744 }
00745 
00746 int ast_http_reload(void)
00747 {
00748    return __ast_http_load(1);
00749 }
00750 
00751 static char show_http_help[] =
00752 "Usage: http show status\n"
00753 "       Lists status of internal HTTP engine\n";
00754 
00755 static struct ast_cli_entry cli_http[] = {
00756    { { "http", "show", "status", NULL },
00757    handle_show_http, "Display HTTP server status",
00758    show_http_help },
00759 };
00760 
00761 int ast_http_init(void)
00762 {
00763    ast_http_uri_link(&statusuri);
00764    ast_http_uri_link(&staticuri);
00765    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
00766 
00767    return __ast_http_load(0);
00768 }

Generated on Sun Dec 18 20:55:40 2011 for Asterisk - the Open Source PBX by  doxygen 1.5.6