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

Generated on Sat Aug 6 00:39:29 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7