Mon Mar 31 07:38:02 2008

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$")
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 void *ast_httpd_helper_thread(void *data)
00383 {
00384    char buf[4096];
00385    char cookie[4096];
00386    char timebuf[256];
00387    struct ast_http_server_instance *ser = data;
00388    struct ast_variable *var, *prev=NULL, *vars=NULL;
00389    char *uri, *c, *title=NULL;
00390    char *vname, *vval;
00391    int status = 200, contentlength = 0;
00392    time_t t;
00393    unsigned int static_content = 0;
00394 
00395    if (fgets(buf, sizeof(buf), ser->f)) {
00396       /* Skip method */
00397       uri = buf;
00398       while(*uri && (*uri > 32))
00399          uri++;
00400       if (*uri) {
00401          *uri = '\0';
00402          uri++;
00403       }
00404 
00405       /* Skip white space */
00406       while (*uri && (*uri < 33))
00407          uri++;
00408 
00409       if (*uri) {
00410          c = uri;
00411          while (*c && (*c > 32))
00412              c++;
00413          if (*c) {
00414             *c = '\0';
00415          }
00416       }
00417 
00418       while (fgets(cookie, sizeof(cookie), ser->f)) {
00419          /* Trim trailing characters */
00420          while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
00421             cookie[strlen(cookie) - 1] = '\0';
00422          }
00423          if (ast_strlen_zero(cookie))
00424             break;
00425          if (!strncasecmp(cookie, "Cookie: ", 8)) {
00426 
00427             /* TODO - The cookie parsing code below seems to work   
00428                in IE6 and FireFox 1.5.  However, it is not entirely 
00429                correct, and therefore may not work in all           
00430                circumstances.                            
00431                   For more details see RFC 2109 and RFC 2965        */
00432          
00433             /* FireFox cookie strings look like:                    
00434                  Cookie: mansession_id="********"                   
00435                InternetExplorer's look like:                        
00436                  Cookie: $Version="1"; mansession_id="********"     */
00437             
00438             /* If we got a FireFox cookie string, the name's right  
00439                 after "Cookie: "                                    */
00440                                 vname = cookie + 8;
00441             
00442             /* If we got an IE cookie string, we need to skip to    
00443                 past the version to get to the name                 */
00444             if (*vname == '$') {
00445                vname = strchr(vname, ';');
00446                if (vname) { 
00447                   vname++;
00448                   if (*vname == ' ')
00449                      vname++;
00450                }
00451             }
00452             
00453             if (vname) {
00454                vval = strchr(vname, '=');
00455                if (vval) {
00456                   /* Ditch the = and the quotes */
00457                   *vval++ = '\0';
00458                   if (*vval)
00459                      vval++;
00460                   if (strlen(vval))
00461                      vval[strlen(vval) - 1] = '\0';
00462                   var = ast_variable_new(vname, vval);
00463                   if (var) {
00464                      if (prev)
00465                         prev->next = var;
00466                      else
00467                         vars = var;
00468                      prev = var;
00469                   }
00470                }
00471             }
00472          }
00473       }
00474 
00475       if (*uri) {
00476          if (!strcasecmp(buf, "get")) 
00477             c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
00478          else 
00479             c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
00480       } else 
00481          c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
00482 
00483       /* If they aren't mopped up already, clean up the cookies */
00484       if (vars)
00485          ast_variables_destroy(vars);
00486 
00487       if (!c)
00488          c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
00489       if (c) {
00490          time(&t);
00491          strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
00492          ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
00493          ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION);
00494          ast_cli(ser->fd, "Date: %s\r\n", timebuf);
00495          ast_cli(ser->fd, "Connection: close\r\n");
00496          if (!static_content)
00497             ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n");
00498             /* We set the no-cache headers only for dynamic content.
00499             * If you want to make sure the static file you requested is not from cache,
00500             * append a random variable to your GET request.  Ex: 'something.html?r=109987734'
00501             */
00502 
00503          if (contentlength) {
00504             char *tmp;
00505             tmp = strstr(c, "\r\n\r\n");
00506             if (tmp) {
00507                ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
00508                write(ser->fd, c, (tmp + 4 - c));
00509                write(ser->fd, tmp + 4, contentlength);
00510             }
00511          } else
00512             ast_cli(ser->fd, "%s", c);
00513          free(c);
00514       }
00515       if (title)
00516          free(title);
00517    }
00518    fclose(ser->f);
00519    free(ser);
00520    return NULL;
00521 }
00522 
00523 static void *http_root(void *data)
00524 {
00525    int fd;
00526    struct sockaddr_in sin;
00527    socklen_t sinlen;
00528    struct ast_http_server_instance *ser;
00529    pthread_t launched;
00530    pthread_attr_t attr;
00531    
00532    for (;;) {
00533       int flags;
00534 
00535       ast_wait_for_input(httpfd, -1);
00536       sinlen = sizeof(sin);
00537       fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
00538       if (fd < 0) {
00539          if ((errno != EAGAIN) && (errno != EINTR))
00540             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00541          continue;
00542       }
00543       ser = ast_calloc(1, sizeof(*ser));
00544       if (!ser) {
00545          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00546          close(fd);
00547          continue;
00548       }
00549       flags = fcntl(fd, F_GETFL);
00550       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00551       ser->fd = fd;
00552       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00553       if ((ser->f = fdopen(ser->fd, "w+"))) {
00554          pthread_attr_init(&attr);
00555          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00556          
00557          if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
00558             ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00559             fclose(ser->f);
00560             free(ser);
00561          }
00562          pthread_attr_destroy(&attr);
00563       } else {
00564          ast_log(LOG_WARNING, "fdopen failed!\n");
00565          close(ser->fd);
00566          free(ser);
00567       }
00568    }
00569    return NULL;
00570 }
00571 
00572 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
00573 {
00574    char *c;
00575    c = buf;
00576    ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
00577    if (expires)
00578       ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
00579    ast_build_string(&c, &buflen, "\r\n");
00580    return buf;
00581 }
00582 
00583 
00584 static void http_server_start(struct sockaddr_in *sin)
00585 {
00586    int flags;
00587    int x = 1;
00588    
00589    /* Do nothing if nothing has changed */
00590    if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
00591       ast_log(LOG_DEBUG, "Nothing changed in http\n");
00592       return;
00593    }
00594    
00595    memcpy(&oldsin, sin, sizeof(oldsin));
00596    
00597    /* Shutdown a running server if there is one */
00598    if (master != AST_PTHREADT_NULL) {
00599       pthread_cancel(master);
00600       pthread_kill(master, SIGURG);
00601       pthread_join(master, NULL);
00602    }
00603    
00604    if (httpfd != -1)
00605       close(httpfd);
00606 
00607    /* If there's no new server, stop here */
00608    if (!sin->sin_family)
00609       return;
00610    
00611    
00612    httpfd = socket(AF_INET, SOCK_STREAM, 0);
00613    if (httpfd < 0) {
00614       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00615       return;
00616    }
00617    
00618    setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00619    if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
00620       ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
00621          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00622          strerror(errno));
00623       close(httpfd);
00624       httpfd = -1;
00625       return;
00626    }
00627    if (listen(httpfd, 10)) {
00628       ast_log(LOG_NOTICE, "Unable to listen!\n");
00629       close(httpfd);
00630       httpfd = -1;
00631       return;
00632    }
00633    flags = fcntl(httpfd, F_GETFL);
00634    fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
00635    if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
00636       ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
00637             ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00638             strerror(errno));
00639       close(httpfd);
00640       httpfd = -1;
00641    }
00642 }
00643 
00644 static int __ast_http_load(int reload)
00645 {
00646    struct ast_config *cfg;
00647    struct ast_variable *v;
00648    int enabled=0;
00649    int newenablestatic=0;
00650    struct sockaddr_in sin;
00651    struct hostent *hp;
00652    struct ast_hostent ahp;
00653    char newprefix[MAX_PREFIX];
00654 
00655    memset(&sin, 0, sizeof(sin));
00656    sin.sin_port = htons(8088);
00657 
00658    strcpy(newprefix, DEFAULT_PREFIX);
00659 
00660    cfg = ast_config_load("http.conf");
00661    if (cfg) {
00662       v = ast_variable_browse(cfg, "general");
00663       while(v) {
00664          if (!strcasecmp(v->name, "enabled"))
00665             enabled = ast_true(v->value);
00666          else if (!strcasecmp(v->name, "enablestatic"))
00667             newenablestatic = ast_true(v->value);
00668          else if (!strcasecmp(v->name, "bindport"))
00669             sin.sin_port = ntohs(atoi(v->value));
00670          else if (!strcasecmp(v->name, "bindaddr")) {
00671             if ((hp = ast_gethostbyname(v->value, &ahp))) {
00672                memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00673             } else {
00674                ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
00675             }
00676          } else if (!strcasecmp(v->name, "prefix")) {
00677             if (!ast_strlen_zero(v->value)) {
00678                newprefix[0] = '/';
00679                ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
00680             } else {
00681                newprefix[0] = '\0';
00682             }
00683                
00684          }
00685          v = v->next;
00686       }
00687       ast_config_destroy(cfg);
00688    }
00689    if (enabled)
00690       sin.sin_family = AF_INET;
00691    if (strcmp(prefix, newprefix)) {
00692       ast_copy_string(prefix, newprefix, sizeof(prefix));
00693       prefix_len = strlen(prefix);
00694    }
00695    enablestatic = newenablestatic;
00696 
00697    http_server_start(&sin);
00698 
00699 
00700    return 0;
00701 }
00702 
00703 static int handle_show_http(int fd, int argc, char *argv[])
00704 {
00705    struct ast_http_uri *urih;
00706 
00707    if (argc != 3)
00708       return RESULT_SHOWUSAGE;
00709 
00710    ast_cli(fd, "HTTP Server Status:\n");
00711    ast_cli(fd, "Prefix: %s\n", prefix);
00712    if (oldsin.sin_family)
00713       ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
00714          ast_inet_ntoa(oldsin.sin_addr),
00715          ntohs(oldsin.sin_port));
00716    else
00717       ast_cli(fd, "Server Disabled\n\n");
00718    ast_cli(fd, "Enabled URI's:\n");
00719    ast_rwlock_rdlock(&uris_lock);
00720    urih = uris;
00721    while(urih){
00722       ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
00723       urih = urih->next;
00724    }
00725    if (!uris)
00726       ast_cli(fd, "None.\n");
00727    ast_rwlock_unlock(&uris_lock);
00728 
00729    return RESULT_SUCCESS;
00730 }
00731 
00732 int ast_http_reload(void)
00733 {
00734    return __ast_http_load(1);
00735 }
00736 
00737 static char show_http_help[] =
00738 "Usage: http show status\n"
00739 "       Lists status of internal HTTP engine\n";
00740 
00741 static struct ast_cli_entry cli_http[] = {
00742    { { "http", "show", "status", NULL },
00743    handle_show_http, "Display HTTP server status",
00744    show_http_help },
00745 };
00746 
00747 int ast_http_init(void)
00748 {
00749    ast_http_uri_link(&statusuri);
00750    ast_http_uri_link(&staticuri);
00751    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
00752 
00753    return __ast_http_load(0);
00754 }

Generated on Mon Mar 31 07:38:02 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1