Thu Oct 8 21:56:01 2009

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

Generated on Thu Oct 8 21:56:01 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6