Mon Apr 30 07:36:34 2007

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 };
00229    
00230 char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
00231 {
00232    char *c = NULL;
00233    asprintf(&c,
00234       "Content-type: text/html\r\n"
00235       "%s"
00236       "\r\n"
00237       "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
00238       "<html><head>\r\n"
00239       "<title>%d %s</title>\r\n"
00240       "</head><body>\r\n"
00241       "<h1>%s</h1>\r\n"
00242       "<p>%s</p>\r\n"
00243       "<hr />\r\n"
00244       "<address>Asterisk Server</address>\r\n"
00245       "</body></html>\r\n",
00246          (extra_header ? extra_header : ""), status, title, title, text);
00247    return c;
00248 }
00249 
00250 int ast_http_uri_link(struct ast_http_uri *urih)
00251 {
00252    struct ast_http_uri *prev;
00253 
00254    ast_rwlock_wrlock(&uris_lock);
00255    prev = uris;
00256    if (!uris || strlen(uris->uri) <= strlen(urih->uri)) {
00257       urih->next = uris;
00258       uris = urih;
00259    } else {
00260       while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri)))
00261          prev = prev->next;
00262       /* Insert it here */
00263       urih->next = prev->next;
00264       prev->next = urih;
00265    }
00266    ast_rwlock_unlock(&uris_lock);
00267 
00268    return 0;
00269 }  
00270 
00271 void ast_http_uri_unlink(struct ast_http_uri *urih)
00272 {
00273    struct ast_http_uri *prev;
00274 
00275    ast_rwlock_wrlock(&uris_lock);
00276    if (!uris) {
00277       ast_rwlock_unlock(&uris_lock);
00278       return;
00279    }
00280    prev = uris;
00281    if (uris == urih) {
00282       uris = uris->next;
00283    }
00284    while(prev->next) {
00285       if (prev->next == urih) {
00286          prev->next = urih->next;
00287          break;
00288       }
00289       prev = prev->next;
00290    }
00291    ast_rwlock_unlock(&uris_lock);
00292 }
00293 
00294 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
00295 {
00296    char *c;
00297    char *turi;
00298    char *params;
00299    char *var;
00300    char *val;
00301    struct ast_http_uri *urih=NULL;
00302    int len;
00303    struct ast_variable *vars=NULL, *v, *prev = NULL;
00304    
00305    
00306    params = strchr(uri, '?');
00307    if (params) {
00308       *params = '\0';
00309       params++;
00310       while ((var = strsep(&params, "&"))) {
00311          val = strchr(var, '=');
00312          if (val) {
00313             *val = '\0';
00314             val++;
00315             ast_uri_decode(val);
00316          } else 
00317             val = "";
00318          ast_uri_decode(var);
00319          if ((v = ast_variable_new(var, val))) {
00320             if (vars)
00321                prev->next = v;
00322             else
00323                vars = v;
00324             prev = v;
00325          }
00326       }
00327    }
00328    if (prev)
00329       prev->next = *cookies;
00330    else
00331       vars = *cookies;
00332    *cookies = NULL;
00333    ast_uri_decode(uri);
00334    if (!strncasecmp(uri, prefix, prefix_len)) {
00335       uri += prefix_len;
00336       if (!*uri || (*uri == '/')) {
00337          if (*uri == '/')
00338             uri++;
00339          ast_rwlock_rdlock(&uris_lock);
00340          urih = uris;
00341          while(urih) {
00342             len = strlen(urih->uri);
00343             if (!strncasecmp(urih->uri, uri, len)) {
00344                if (!uri[len] || uri[len] == '/') {
00345                   turi = uri + len;
00346                   if (*turi == '/')
00347                      turi++;
00348                   if (!*turi || urih->has_subtree) {
00349                      uri = turi;
00350                      break;
00351                   }
00352                }
00353             }
00354             urih = urih->next;
00355          }
00356          if (!urih)
00357             ast_rwlock_unlock(&uris_lock);
00358       }
00359    }
00360    if (urih) {
00361       c = urih->callback(sin, uri, vars, status, title, contentlength);
00362       ast_rwlock_unlock(&uris_lock);
00363    } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
00364       /* Special case: If no prefix, and no URI, send to /static/index.html */
00365       c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for...");
00366       *status = 302;
00367       *title = strdup("Moved Temporarily");
00368    } else {
00369       c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
00370       *status = 404;
00371       *title = strdup("Not Found");
00372    }
00373    ast_variables_destroy(vars);
00374    return c;
00375 }
00376 
00377 static void *ast_httpd_helper_thread(void *data)
00378 {
00379    char buf[4096];
00380    char cookie[4096];
00381    char timebuf[256];
00382    struct ast_http_server_instance *ser = data;
00383    struct ast_variable *var, *prev=NULL, *vars=NULL;
00384    char *uri, *c, *title=NULL;
00385    char *vname, *vval;
00386    int status = 200, contentlength = 0;
00387    time_t t;
00388 
00389    if (fgets(buf, sizeof(buf), ser->f)) {
00390       /* Skip method */
00391       uri = buf;
00392       while(*uri && (*uri > 32))
00393          uri++;
00394       if (*uri) {
00395          *uri = '\0';
00396          uri++;
00397       }
00398 
00399       /* Skip white space */
00400       while (*uri && (*uri < 33))
00401          uri++;
00402 
00403       if (*uri) {
00404          c = uri;
00405          while (*c && (*c > 32))
00406              c++;
00407          if (*c) {
00408             *c = '\0';
00409          }
00410       }
00411 
00412       while (fgets(cookie, sizeof(cookie), ser->f)) {
00413          /* Trim trailing characters */
00414          while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
00415             cookie[strlen(cookie) - 1] = '\0';
00416          }
00417          if (ast_strlen_zero(cookie))
00418             break;
00419          if (!strncasecmp(cookie, "Cookie: ", 8)) {
00420 
00421             /* TODO - The cookie parsing code below seems to work   
00422                in IE6 and FireFox 1.5.  However, it is not entirely 
00423                correct, and therefore may not work in all           
00424                circumstances.                            
00425                   For more details see RFC 2109 and RFC 2965        */
00426          
00427             /* FireFox cookie strings look like:                    
00428                  Cookie: mansession_id="********"                   
00429                InternetExplorer's look like:                        
00430                  Cookie: $Version="1"; mansession_id="********"     */
00431             
00432             /* If we got a FireFox cookie string, the name's right  
00433                 after "Cookie: "                                    */
00434                                 vname = cookie + 8;
00435             
00436             /* If we got an IE cookie string, we need to skip to    
00437                 past the version to get to the name                 */
00438             if (*vname == '$') {
00439                vname = strchr(vname, ';');
00440                if (vname) { 
00441                   vname++;
00442                   if (*vname == ' ')
00443                      vname++;
00444                }
00445             }
00446             
00447             if (vname) {
00448                vval = strchr(vname, '=');
00449                if (vval) {
00450                   /* Ditch the = and the quotes */
00451                   *vval++ = '\0';
00452                   if (*vval)
00453                      vval++;
00454                   if (strlen(vval))
00455                      vval[strlen(vval) - 1] = '\0';
00456                   var = ast_variable_new(vname, vval);
00457                   if (var) {
00458                      if (prev)
00459                         prev->next = var;
00460                      else
00461                         vars = var;
00462                      prev = var;
00463                   }
00464                }
00465             }
00466          }
00467       }
00468 
00469       if (*uri) {
00470          if (!strcasecmp(buf, "get")) 
00471             c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars);
00472          else 
00473             c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\
00474       } else 
00475          c = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
00476 
00477       /* If they aren't mopped up already, clean up the cookies */
00478       if (vars)
00479          ast_variables_destroy(vars);
00480 
00481       if (!c)
00482          c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error");
00483       if (c) {
00484          time(&t);
00485          strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t));
00486          ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK");
00487          ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION);
00488          ast_cli(ser->fd, "Date: %s\r\n", timebuf);
00489          ast_cli(ser->fd, "Connection: close\r\n");
00490          if (contentlength) {
00491             char *tmp;
00492             tmp = strstr(c, "\r\n\r\n");
00493             if (tmp) {
00494                ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
00495                write(ser->fd, c, (tmp + 4 - c));
00496                write(ser->fd, tmp + 4, contentlength);
00497             }
00498          } else
00499             ast_cli(ser->fd, "%s", c);
00500          free(c);
00501       }
00502       if (title)
00503          free(title);
00504    }
00505    fclose(ser->f);
00506    free(ser);
00507    return NULL;
00508 }
00509 
00510 static void *http_root(void *data)
00511 {
00512    int fd;
00513    struct sockaddr_in sin;
00514    socklen_t sinlen;
00515    struct ast_http_server_instance *ser;
00516    pthread_t launched;
00517    pthread_attr_t attr;
00518    
00519    for (;;) {
00520       int flags;
00521 
00522       ast_wait_for_input(httpfd, -1);
00523       sinlen = sizeof(sin);
00524       fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
00525       if (fd < 0) {
00526          if ((errno != EAGAIN) && (errno != EINTR))
00527             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00528          continue;
00529       }
00530       ser = ast_calloc(1, sizeof(*ser));
00531       if (!ser) {
00532          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00533          close(fd);
00534          continue;
00535       }
00536       flags = fcntl(fd, F_GETFL);
00537       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00538       ser->fd = fd;
00539       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00540       if ((ser->f = fdopen(ser->fd, "w+"))) {
00541          pthread_attr_init(&attr);
00542          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00543          
00544          if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
00545             ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00546             fclose(ser->f);
00547             free(ser);
00548          }
00549          pthread_attr_destroy(&attr);
00550       } else {
00551          ast_log(LOG_WARNING, "fdopen failed!\n");
00552          close(ser->fd);
00553          free(ser);
00554       }
00555    }
00556    return NULL;
00557 }
00558 
00559 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
00560 {
00561    char *c;
00562    c = buf;
00563    ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
00564    if (expires)
00565       ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
00566    ast_build_string(&c, &buflen, "\r\n");
00567    return buf;
00568 }
00569 
00570 
00571 static void http_server_start(struct sockaddr_in *sin)
00572 {
00573    int flags;
00574    int x = 1;
00575    
00576    /* Do nothing if nothing has changed */
00577    if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
00578       ast_log(LOG_DEBUG, "Nothing changed in http\n");
00579       return;
00580    }
00581    
00582    memcpy(&oldsin, sin, sizeof(oldsin));
00583    
00584    /* Shutdown a running server if there is one */
00585    if (master != AST_PTHREADT_NULL) {
00586       pthread_cancel(master);
00587       pthread_kill(master, SIGURG);
00588       pthread_join(master, NULL);
00589    }
00590    
00591    if (httpfd != -1)
00592       close(httpfd);
00593 
00594    /* If there's no new server, stop here */
00595    if (!sin->sin_family)
00596       return;
00597    
00598    
00599    httpfd = socket(AF_INET, SOCK_STREAM, 0);
00600    if (httpfd < 0) {
00601       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00602       return;
00603    }
00604    
00605    setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00606    if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
00607       ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
00608          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00609          strerror(errno));
00610       close(httpfd);
00611       httpfd = -1;
00612       return;
00613    }
00614    if (listen(httpfd, 10)) {
00615       ast_log(LOG_NOTICE, "Unable to listen!\n");
00616       close(httpfd);
00617       httpfd = -1;
00618       return;
00619    }
00620    flags = fcntl(httpfd, F_GETFL);
00621    fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
00622    if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
00623       ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
00624             ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00625             strerror(errno));
00626       close(httpfd);
00627       httpfd = -1;
00628    }
00629 }
00630 
00631 static int __ast_http_load(int reload)
00632 {
00633    struct ast_config *cfg;
00634    struct ast_variable *v;
00635    int enabled=0;
00636    int newenablestatic=0;
00637    struct sockaddr_in sin;
00638    struct hostent *hp;
00639    struct ast_hostent ahp;
00640    char newprefix[MAX_PREFIX];
00641 
00642    memset(&sin, 0, sizeof(sin));
00643    sin.sin_port = htons(8088);
00644 
00645    strcpy(newprefix, DEFAULT_PREFIX);
00646 
00647    cfg = ast_config_load("http.conf");
00648    if (cfg) {
00649       v = ast_variable_browse(cfg, "general");
00650       while(v) {
00651          if (!strcasecmp(v->name, "enabled"))
00652             enabled = ast_true(v->value);
00653          else if (!strcasecmp(v->name, "enablestatic"))
00654             newenablestatic = ast_true(v->value);
00655          else if (!strcasecmp(v->name, "bindport"))
00656             sin.sin_port = ntohs(atoi(v->value));
00657          else if (!strcasecmp(v->name, "bindaddr")) {
00658             if ((hp = ast_gethostbyname(v->value, &ahp))) {
00659                memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00660             } else {
00661                ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
00662             }
00663          } else if (!strcasecmp(v->name, "prefix")) {
00664             if (!ast_strlen_zero(v->value)) {
00665                newprefix[0] = '/';
00666                ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
00667             } else {
00668                newprefix[0] = '\0';
00669             }
00670                
00671          }
00672          v = v->next;
00673       }
00674       ast_config_destroy(cfg);
00675    }
00676    if (enabled)
00677       sin.sin_family = AF_INET;
00678    if (strcmp(prefix, newprefix)) {
00679       ast_copy_string(prefix, newprefix, sizeof(prefix));
00680       prefix_len = strlen(prefix);
00681    }
00682    enablestatic = newenablestatic;
00683 
00684    http_server_start(&sin);
00685 
00686 
00687    return 0;
00688 }
00689 
00690 static int handle_show_http(int fd, int argc, char *argv[])
00691 {
00692    struct ast_http_uri *urih;
00693 
00694    if (argc != 3)
00695       return RESULT_SHOWUSAGE;
00696 
00697    ast_cli(fd, "HTTP Server Status:\n");
00698    ast_cli(fd, "Prefix: %s\n", prefix);
00699    if (oldsin.sin_family)
00700       ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
00701          ast_inet_ntoa(oldsin.sin_addr),
00702          ntohs(oldsin.sin_port));
00703    else
00704       ast_cli(fd, "Server Disabled\n\n");
00705    ast_cli(fd, "Enabled URI's:\n");
00706    ast_rwlock_rdlock(&uris_lock);
00707    urih = uris;
00708    while(urih){
00709       ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
00710       urih = urih->next;
00711    }
00712    if (!uris)
00713       ast_cli(fd, "None.\n");
00714    ast_rwlock_unlock(&uris_lock);
00715 
00716    return RESULT_SUCCESS;
00717 }
00718 
00719 int ast_http_reload(void)
00720 {
00721    return __ast_http_load(1);
00722 }
00723 
00724 static char show_http_help[] =
00725 "Usage: http show status\n"
00726 "       Lists status of internal HTTP engine\n";
00727 
00728 static struct ast_cli_entry cli_http[] = {
00729    { { "http", "show", "status", NULL },
00730    handle_show_http, "Display HTTP server status",
00731    show_http_help },
00732 };
00733 
00734 int ast_http_init(void)
00735 {
00736    ast_http_uri_link(&statusuri);
00737    ast_http_uri_link(&staticuri);
00738    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
00739 
00740    return __ast_http_load(0);
00741 }

Generated on Mon Apr 30 07:36:34 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1