Fri Sep 25 19:28:12 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: 62414 $")
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          if (contentlength) {
00499             char *tmp;
00500             tmp = strstr(c, "\r\n\r\n");
00501             if (tmp) {
00502                ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
00503                write(ser->fd, c, (tmp + 4 - c));
00504                write(ser->fd, tmp + 4, contentlength);
00505             }
00506          } else
00507             ast_cli(ser->fd, "%s", c);
00508          free(c);
00509       }
00510       if (title)
00511          free(title);
00512    }
00513    fclose(ser->f);
00514    free(ser);
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       if (fd < 0) {
00534          if ((errno != EAGAIN) && (errno != EINTR))
00535             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00536          continue;
00537       }
00538       ser = ast_calloc(1, sizeof(*ser));
00539       if (!ser) {
00540          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00541          close(fd);
00542          continue;
00543       }
00544       flags = fcntl(fd, F_GETFL);
00545       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00546       ser->fd = fd;
00547       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00548       if ((ser->f = fdopen(ser->fd, "w+"))) {
00549          pthread_attr_init(&attr);
00550          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00551          
00552          if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
00553             ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00554             fclose(ser->f);
00555             free(ser);
00556          }
00557          pthread_attr_destroy(&attr);
00558       } else {
00559          ast_log(LOG_WARNING, "fdopen failed!\n");
00560          close(ser->fd);
00561          free(ser);
00562       }
00563    }
00564    return NULL;
00565 }
00566 
00567 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
00568 {
00569    char *c;
00570    c = buf;
00571    ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
00572    if (expires)
00573       ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
00574    ast_build_string(&c, &buflen, "\r\n");
00575    return buf;
00576 }
00577 
00578 
00579 static void http_server_start(struct sockaddr_in *sin)
00580 {
00581    int flags;
00582    int x = 1;
00583    
00584    /* Do nothing if nothing has changed */
00585    if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
00586       ast_log(LOG_DEBUG, "Nothing changed in http\n");
00587       return;
00588    }
00589    
00590    memcpy(&oldsin, sin, sizeof(oldsin));
00591    
00592    /* Shutdown a running server if there is one */
00593    if (master != AST_PTHREADT_NULL) {
00594       pthread_cancel(master);
00595       pthread_kill(master, SIGURG);
00596       pthread_join(master, NULL);
00597    }
00598    
00599    if (httpfd != -1)
00600       close(httpfd);
00601 
00602    /* If there's no new server, stop here */
00603    if (!sin->sin_family)
00604       return;
00605    
00606    
00607    httpfd = socket(AF_INET, SOCK_STREAM, 0);
00608    if (httpfd < 0) {
00609       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00610       return;
00611    }
00612    
00613    setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00614    if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
00615       ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
00616          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00617          strerror(errno));
00618       close(httpfd);
00619       httpfd = -1;
00620       return;
00621    }
00622    if (listen(httpfd, 10)) {
00623       ast_log(LOG_NOTICE, "Unable to listen!\n");
00624       close(httpfd);
00625       httpfd = -1;
00626       return;
00627    }
00628    flags = fcntl(httpfd, F_GETFL);
00629    fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
00630    if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
00631       ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
00632             ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00633             strerror(errno));
00634       close(httpfd);
00635       httpfd = -1;
00636    }
00637 }
00638 
00639 static int __ast_http_load(int reload)
00640 {
00641    struct ast_config *cfg;
00642    struct ast_variable *v;
00643    int enabled=0;
00644    int newenablestatic=0;
00645    struct sockaddr_in sin;
00646    struct hostent *hp;
00647    struct ast_hostent ahp;
00648    char newprefix[MAX_PREFIX];
00649 
00650    memset(&sin, 0, sizeof(sin));
00651    sin.sin_port = htons(8088);
00652 
00653    strcpy(newprefix, DEFAULT_PREFIX);
00654 
00655    cfg = ast_config_load("http.conf");
00656    if (cfg) {
00657       v = ast_variable_browse(cfg, "general");
00658       while(v) {
00659          if (!strcasecmp(v->name, "enabled"))
00660             enabled = ast_true(v->value);
00661          else if (!strcasecmp(v->name, "enablestatic"))
00662             newenablestatic = ast_true(v->value);
00663          else if (!strcasecmp(v->name, "bindport"))
00664             sin.sin_port = ntohs(atoi(v->value));
00665          else if (!strcasecmp(v->name, "bindaddr")) {
00666             if ((hp = ast_gethostbyname(v->value, &ahp))) {
00667                memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00668             } else {
00669                ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
00670             }
00671          } else if (!strcasecmp(v->name, "prefix")) {
00672             if (!ast_strlen_zero(v->value)) {
00673                newprefix[0] = '/';
00674                ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
00675             } else {
00676                newprefix[0] = '\0';
00677             }
00678                
00679          }
00680          v = v->next;
00681       }
00682       ast_config_destroy(cfg);
00683    }
00684    if (enabled)
00685       sin.sin_family = AF_INET;
00686    if (strcmp(prefix, newprefix)) {
00687       ast_copy_string(prefix, newprefix, sizeof(prefix));
00688       prefix_len = strlen(prefix);
00689    }
00690    enablestatic = newenablestatic;
00691 
00692    http_server_start(&sin);
00693 
00694 
00695    return 0;
00696 }
00697 
00698 static int handle_show_http(int fd, int argc, char *argv[])
00699 {
00700    struct ast_http_uri *urih;
00701 
00702    if (argc != 3)
00703       return RESULT_SHOWUSAGE;
00704 
00705    ast_cli(fd, "HTTP Server Status:\n");
00706    ast_cli(fd, "Prefix: %s\n", prefix);
00707    if (oldsin.sin_family)
00708       ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
00709          ast_inet_ntoa(oldsin.sin_addr),
00710          ntohs(oldsin.sin_port));
00711    else
00712       ast_cli(fd, "Server Disabled\n\n");
00713    ast_cli(fd, "Enabled URI's:\n");
00714    ast_rwlock_rdlock(&uris_lock);
00715    urih = uris;
00716    while(urih){
00717       ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
00718       urih = urih->next;
00719    }
00720    if (!uris)
00721       ast_cli(fd, "None.\n");
00722    ast_rwlock_unlock(&uris_lock);
00723 
00724    return RESULT_SUCCESS;
00725 }
00726 
00727 int ast_http_reload(void)
00728 {
00729    return __ast_http_load(1);
00730 }
00731 
00732 static char show_http_help[] =
00733 "Usage: http show status\n"
00734 "       Lists status of internal HTTP engine\n";
00735 
00736 static struct ast_cli_entry cli_http[] = {
00737    { { "http", "show", "status", NULL },
00738    handle_show_http, "Display HTTP server status",
00739    show_http_help },
00740 };
00741 
00742 int ast_http_init(void)
00743 {
00744    ast_http_uri_link(&statusuri);
00745    ast_http_uri_link(&staticuri);
00746    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
00747 
00748    return __ast_http_load(0);
00749 }

Generated on Fri Sep 25 19:28:12 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.5