Mon Apr 30 07:43:18 2007

Asterisk developer's documentation


http.c File Reference

http server for AMI access More...

#include "asterisk.h"
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include "asterisk/cli.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
#include "asterisk/strings.h"
#include "asterisk/options.h"
#include "asterisk/config.h"
#include "asterisk/version.h"
#include "asterisk/manager.h"

Include dependency graph for http.c:

Go to the source code of this file.

Data Structures

struct  ast_http_server_instance

Defines

#define DEFAULT_PREFIX   "/asterisk"
#define MAX_PREFIX   80

Functions

static int __ast_http_load (int reload)
char * ast_http_error (int status, const char *title, const char *extra_header, const char *text)
 Return a malloc()'d string containing an HTTP error message.
int ast_http_init (void)
int ast_http_reload (void)
char * ast_http_setcookie (const char *var, const char *val, int expires, char *buf, size_t buflen)
int ast_http_uri_link (struct ast_http_uri *urih)
 Link into the Asterisk HTTP server.
void ast_http_uri_unlink (struct ast_http_uri *urih)
 Destroy an HTTP server.
static void * ast_httpd_helper_thread (void *data)
 AST_RWLOCK_DEFINE_STATIC (uris_lock)
static const char * ftype2mtype (const char *ftype, char *wkspace, int wkspacelen)
static int handle_show_http (int fd, int argc, char *argv[])
static char * handle_uri (struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
static void * http_root (void *data)
static void http_server_start (struct sockaddr_in *sin)
static char * httpstatus_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
static char * static_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)

Variables

static struct ast_cli_entry cli_http []
static int enablestatic
static int httpfd = -1
static pthread_t master = AST_PTHREADT_NULL
struct {
   const char *   ext
   const char *   mtype
mimetypes []
 Limit the kinds of files we're willing to serve up.
static struct sockaddr_in oldsin
static char prefix [MAX_PREFIX]
static int prefix_len
static char show_http_help []
static struct ast_http_uri staticuri
static struct ast_http_uri statusuri
static struct ast_http_uriuris


Detailed Description

http server for AMI access

Author:
Mark Spencer <markster@digium.com>
This program implements a tiny http server and was inspired by micro-httpd by Jef Poskanzer

AMI over HTTP support - AMI over the http protocol

Definition in file http.c.


Define Documentation

#define DEFAULT_PREFIX   "/asterisk"

Definition at line 61 of file http.c.

Referenced by __ast_http_load().

#define MAX_PREFIX   80

Definition at line 60 of file http.c.

Referenced by __ast_http_load().


Function Documentation

static int __ast_http_load ( int  reload  )  [static]

Definition at line 631 of file http.c.

References ahp, ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable_browse(), DEFAULT_PREFIX, enabled, hp, http_server_start(), LOG_WARNING, MAX_PREFIX, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by ast_http_init(), and ast_http_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 }

char* ast_http_error ( int  status,
const char *  title,
const char *  extra_header,
const char *  text 
)

Return a malloc()'d string containing an HTTP error message.

Definition at line 230 of file http.c.

References asprintf.

Referenced by ast_httpd_helper_thread(), handle_uri(), and static_callback().

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 }

int ast_http_init ( void   ) 

Definition at line 734 of file http.c.

References __ast_http_load(), ast_cli_register_multiple(), ast_http_uri_link(), cli_http, staticuri, and statusuri.

Referenced by main().

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 }

int ast_http_reload ( void   ) 

Definition at line 719 of file http.c.

References __ast_http_load().

00720 {
00721    return __ast_http_load(1);
00722 }

char* ast_http_setcookie ( const char *  var,
const char *  val,
int  expires,
char *  buf,
size_t  buflen 
)

Definition at line 559 of file http.c.

References ast_build_string().

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 }

int ast_http_uri_link ( struct ast_http_uri urih  ) 

Link into the Asterisk HTTP server.

Definition at line 250 of file http.c.

References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, ast_http_uri::uri, and uris.

Referenced by ast_http_init(), and init_manager().

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 }  

void ast_http_uri_unlink ( struct ast_http_uri urih  ) 

Destroy an HTTP server.

Definition at line 271 of file http.c.

References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, and uris.

Referenced by init_manager().

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 }

static void* ast_httpd_helper_thread ( void *  data  )  [static]

Definition at line 377 of file http.c.

References ast_cli(), ast_http_error(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), ast_http_server_instance::f, ast_http_server_instance::fd, free, handle_uri(), ast_http_server_instance::requestor, t, and var.

Referenced by http_root().

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 }

AST_RWLOCK_DEFINE_STATIC ( uris_lock   ) 

static const char* ftype2mtype ( const char *  ftype,
char *  wkspace,
int  wkspacelen 
) [static]

Definition at line 95 of file http.c.

References ext, mimetypes, and mtype.

Referenced by static_callback().

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 }

static int handle_show_http ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 690 of file http.c.

References ast_cli(), ast_inet_ntoa(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_http_uri::description, ast_http_uri::has_subtree, ast_http_uri::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_http_uri::uri, and uris.

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 }

static char* handle_uri ( struct sockaddr_in *  sin,
char *  uri,
int *  status,
char **  title,
int *  contentlength,
struct ast_variable **  cookies 
) [static]

Definition at line 294 of file http.c.

References ast_http_error(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strlen_zero(), ast_uri_decode(), ast_variable_new(), ast_variables_destroy(), ast_http_uri::callback, ast_http_uri::has_subtree, len, ast_http_uri::next, strdup, strsep(), ast_http_uri::uri, uris, and var.

Referenced by ast_httpd_helper_thread().

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 }

static void* http_root ( void *  data  )  [static]

Definition at line 510 of file http.c.

References ast_calloc, ast_httpd_helper_thread(), ast_log(), ast_pthread_create_background, ast_wait_for_input(), free, and LOG_WARNING.

Referenced by http_server_start().

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 }

static void http_server_start ( struct sockaddr_in *  sin  )  [static]

Definition at line 571 of file http.c.

References ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, http_root(), LOG_DEBUG, LOG_NOTICE, and LOG_WARNING.

Referenced by __ast_http_load().

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 }

static char* httpstatus_callback ( struct sockaddr_in *  req,
const char *  uri,
struct ast_variable vars,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 179 of file http.c.

References ast_build_string(), ast_inet_ntoa(), ast_variable::name, ast_variable::next, result, strdup, and ast_variable::value.

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 }

static char* static_callback ( struct sockaddr_in *  req,
const char *  uri,
struct ast_variable vars,
int *  status,
char **  title,
int *  contentlength 
) [static]

Definition at line 108 of file http.c.

References ast_config_AST_DATA_DIR, ast_http_error(), ast_strlen_zero(), free, ftype2mtype(), len, malloc, mtype, result, and strdup.

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 }


Variable Documentation

struct ast_cli_entry cli_http[] [static]

Initial value:

 {
   { { "http", "show", "status", NULL },
   handle_show_http, "Display HTTP server status",
   show_http_help },
}

Definition at line 728 of file http.c.

Referenced by ast_http_init().

int enablestatic [static]

Definition at line 78 of file http.c.

const char* ext

Definition at line 82 of file http.c.

Referenced by ast_filehelper(), ast_rtp_read(), bridge_p2p_rtp_write(), console_transfer(), console_transfer_deprecated(), do_directory(), exts_compare(), ftype2mtype(), iax_park_thread(), misdn_call(), misdn_request(), mixmonitor_thread(), moh_scan_files(), oh323_request(), pbx_load_config(), record_exec(), register_peer_exten(), sip_park_thread(), and sip_request_call().

int httpfd = -1 [static]

Definition at line 73 of file http.c.

pthread_t master = AST_PTHREADT_NULL [static]

Definition at line 74 of file http.c.

Referenced by __unload_module(), zt_bridge(), zt_link(), and zt_unlink().

struct { ... } mimetypes[] [static]

Limit the kinds of files we're willing to serve up.

Referenced by ftype2mtype().

const char* mtype

Definition at line 83 of file http.c.

Referenced by ftype2mtype(), and static_callback().

struct sockaddr_in oldsin [static]

Definition at line 77 of file http.c.

char prefix[MAX_PREFIX] [static]

Definition at line 75 of file http.c.

Referenced by _while_exec(), ast_db_deltree(), ast_db_gettree(), database_show(), exec_clearhash(), handle_verbose(), hashkeys_read(), read_config(), realtime_exec(), and while_continue_exec().

int prefix_len [static]

Definition at line 76 of file http.c.

char show_http_help[] [static]

Initial value:

"Usage: http show status\n"
"       Lists status of internal HTTP engine\n"

Definition at line 724 of file http.c.

struct ast_http_uri staticuri [static]

Definition at line 223 of file http.c.

Referenced by ast_http_init().

struct ast_http_uri statusuri [static]

Definition at line 216 of file http.c.

Referenced by ast_http_init().

struct ast_http_uri* uris [static]

Definition at line 71 of file http.c.

Referenced by ast_http_uri_link(), ast_http_uri_unlink(), handle_show_http(), and handle_uri().


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