Thu May 14 15:13:33 2009

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"

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)
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, unsigned int *static_content)
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 struct ast_variableparse_cookies (char *cookies)
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
static ast_rwlock_t uris_lock = PTHREAD_RWLOCK_INITIALIZER


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 642 of file http.c.

References ahp, ast_config_destroy(), ast_config_load(), ast_copy_string(), 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().

00643 {
00644    struct ast_config *cfg;
00645    struct ast_variable *v;
00646    int enabled=0;
00647    int newenablestatic=0;
00648    struct sockaddr_in sin;
00649    struct hostent *hp;
00650    struct ast_hostent ahp;
00651    char newprefix[MAX_PREFIX];
00652 
00653    memset(&sin, 0, sizeof(sin));
00654    sin.sin_port = htons(8088);
00655 
00656    strcpy(newprefix, DEFAULT_PREFIX);
00657 
00658    cfg = ast_config_load("http.conf");
00659    if (cfg) {
00660       v = ast_variable_browse(cfg, "general");
00661       while(v) {
00662          if (!strcasecmp(v->name, "enabled"))
00663             enabled = ast_true(v->value);
00664          else if (!strcasecmp(v->name, "enablestatic"))
00665             newenablestatic = ast_true(v->value);
00666          else if (!strcasecmp(v->name, "bindport"))
00667             sin.sin_port = ntohs(atoi(v->value));
00668          else if (!strcasecmp(v->name, "bindaddr")) {
00669             if ((hp = ast_gethostbyname(v->value, &ahp))) {
00670                memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr));
00671             } else {
00672                ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value);
00673             }
00674          } else if (!strcasecmp(v->name, "prefix")) {
00675             if (!ast_strlen_zero(v->value)) {
00676                newprefix[0] = '/';
00677                ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1);
00678             } else {
00679                newprefix[0] = '\0';
00680             }
00681                
00682          }
00683          v = v->next;
00684       }
00685       ast_config_destroy(cfg);
00686    }
00687    if (enabled)
00688       sin.sin_family = AF_INET;
00689    if (strcmp(prefix, newprefix)) {
00690       ast_copy_string(prefix, newprefix, sizeof(prefix));
00691       prefix_len = strlen(prefix);
00692    }
00693    enablestatic = newenablestatic;
00694 
00695    http_server_start(&sin);
00696 
00697 
00698    return 0;
00699 }

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 231 of file http.c.

References asprintf, ast_log(), errno, and LOG_WARNING.

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

00232 {
00233    char *c = NULL;
00234    if (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) < 0) {
00248       ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00249       c = NULL;
00250    }
00251    return c;
00252 }

int ast_http_init ( void   ) 

Definition at line 745 of file http.c.

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

Referenced by main().

00746 {
00747    ast_http_uri_link(&statusuri);
00748    ast_http_uri_link(&staticuri);
00749    ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
00750 
00751    return __ast_http_load(0);
00752 }

int ast_http_reload ( void   ) 

Definition at line 730 of file http.c.

References __ast_http_load().

00731 {
00732    return __ast_http_load(1);
00733 }

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

Definition at line 570 of file http.c.

References ast_build_string().

00571 {
00572    char *c;
00573    c = buf;
00574    ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val);
00575    if (expires)
00576       ast_build_string(&c, &buflen, "; Max-Age=%d", expires);
00577    ast_build_string(&c, &buflen, "\r\n");
00578    return buf;
00579 }

int ast_http_uri_link ( struct ast_http_uri urih  ) 

Link into the Asterisk HTTP server.

Definition at line 254 of file http.c.

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

Referenced by ast_http_init().

00255 {
00256    struct ast_http_uri *prev;
00257 
00258    ast_rwlock_wrlock(&uris_lock);
00259    prev = uris;
00260    if (!uris || strlen(uris->uri) <= strlen(urih->uri)) {
00261       urih->next = uris;
00262       uris = urih;
00263    } else {
00264       while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri)))
00265          prev = prev->next;
00266       /* Insert it here */
00267       urih->next = prev->next;
00268       prev->next = urih;
00269    }
00270    ast_rwlock_unlock(&uris_lock);
00271 
00272    return 0;
00273 }  

void ast_http_uri_unlink ( struct ast_http_uri urih  ) 

Destroy an HTTP server.

Definition at line 275 of file http.c.

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

00276 {
00277    struct ast_http_uri *prev;
00278 
00279    ast_rwlock_wrlock(&uris_lock);
00280    if (!uris) {
00281       ast_rwlock_unlock(&uris_lock);
00282       return;
00283    }
00284    prev = uris;
00285    if (uris == urih) {
00286       uris = uris->next;
00287    }
00288    while(prev->next) {
00289       if (prev->next == urih) {
00290          prev->next = urih->next;
00291          break;
00292       }
00293       prev = prev->next;
00294    }
00295    ast_rwlock_unlock(&uris_lock);
00296 }

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

Definition at line 422 of file http.c.

References ast_cli(), ast_http_error(), ast_log(), ast_strlen_zero(), ast_variables_destroy(), ASTERISK_VERSION, errno, ast_http_server_instance::f, ast_http_server_instance::fd, free, handle_uri(), LOG_WARNING, parse_cookies(), ast_http_server_instance::requestor, and t.

Referenced by http_root().

00423 {
00424    char buf[4096];
00425    char cookie[4096];
00426    char timebuf[256];
00427    struct ast_http_server_instance *ser = data;
00428    struct ast_variable *vars = NULL;
00429    char *uri, *c, *title=NULL;
00430    int status = 200, contentlength = 0;
00431    time_t t;
00432    unsigned int static_content = 0;
00433 
00434    if (fgets(buf, sizeof(buf), ser->f)) {
00435       /* Skip method */
00436       uri = buf;
00437       while(*uri && (*uri > 32))
00438          uri++;
00439       if (*uri) {
00440          *uri = '\0';
00441          uri++;
00442       }
00443 
00444       /* Skip white space */
00445       while (*uri && (*uri < 33))
00446          uri++;
00447 
00448       if (*uri) {
00449          c = uri;
00450          while (*c && (*c > 32))
00451              c++;
00452          if (*c) {
00453             *c = '\0';
00454          }
00455       }
00456 
00457       while (fgets(cookie, sizeof(cookie), ser->f)) {
00458          /* Trim trailing characters */
00459          while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) {
00460             cookie[strlen(cookie) - 1] = '\0';
00461          }
00462          if (ast_strlen_zero(cookie))
00463             break;
00464          if (!strncasecmp(cookie, "Cookie: ", 8)) {
00465             vars = parse_cookies(cookie);
00466          }
00467       }
00468 
00469       if (*uri) {
00470          if (!strcasecmp(buf, "get")) 
00471             c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content);
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 (!static_content)
00491             ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n");
00492             /* We set the no-cache headers only for dynamic content.
00493             * If you want to make sure the static file you requested is not from cache,
00494             * append a random variable to your GET request.  Ex: 'something.html?r=109987734'
00495             */
00496 
00497          if (contentlength) {
00498             char *tmp;
00499             tmp = strstr(c, "\r\n\r\n");
00500             if (tmp) {
00501                ast_cli(ser->fd, "Content-length: %d\r\n", contentlength);
00502                if (write(ser->fd, c, (tmp + 4 - c)) < 0) {
00503                   ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00504                }
00505                if (write(ser->fd, tmp + 4, contentlength) < 0) {
00506                   ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00507                }
00508             }
00509          } else
00510             ast_cli(ser->fd, "%s", c);
00511          free(c);
00512       }
00513       if (title)
00514          free(title);
00515    }
00516    fclose(ser->f);
00517    free(ser);
00518    return NULL;
00519 }

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 701 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, uris, and uris_lock.

00702 {
00703    struct ast_http_uri *urih;
00704 
00705    if (argc != 3)
00706       return RESULT_SHOWUSAGE;
00707 
00708    ast_cli(fd, "HTTP Server Status:\n");
00709    ast_cli(fd, "Prefix: %s\n", prefix);
00710    if (oldsin.sin_family)
00711       ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n",
00712          ast_inet_ntoa(oldsin.sin_addr),
00713          ntohs(oldsin.sin_port));
00714    else
00715       ast_cli(fd, "Server Disabled\n\n");
00716    ast_cli(fd, "Enabled URI's:\n");
00717    ast_rwlock_rdlock(&uris_lock);
00718    urih = uris;
00719    while(urih){
00720       ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description);
00721       urih = urih->next;
00722    }
00723    if (!uris)
00724       ast_cli(fd, "None.\n");
00725    ast_rwlock_unlock(&uris_lock);
00726 
00727    return RESULT_SUCCESS;
00728 }

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

Definition at line 298 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, ast_http_uri::static_content, strdup, ast_http_uri::uri, uris, uris_lock, and var.

Referenced by ast_httpd_helper_thread().

00301 {
00302    char *c;
00303    char *turi;
00304    char *params;
00305    char *var;
00306    char *val;
00307    struct ast_http_uri *urih=NULL;
00308    int len;
00309    struct ast_variable *vars=NULL, *v, *prev = NULL;
00310    
00311    
00312    params = strchr(uri, '?');
00313    if (params) {
00314       *params = '\0';
00315       params++;
00316       while ((var = strsep(&params, "&"))) {
00317          val = strchr(var, '=');
00318          if (val) {
00319             *val = '\0';
00320             val++;
00321             ast_uri_decode(val);
00322          } else 
00323             val = "";
00324          ast_uri_decode(var);
00325          if ((v = ast_variable_new(var, val))) {
00326             if (vars)
00327                prev->next = v;
00328             else
00329                vars = v;
00330             prev = v;
00331          }
00332       }
00333    }
00334    if (prev)
00335       prev->next = *cookies;
00336    else
00337       vars = *cookies;
00338    *cookies = NULL;
00339    ast_uri_decode(uri);
00340    if (!strncasecmp(uri, prefix, prefix_len)) {
00341       uri += prefix_len;
00342       if (!*uri || (*uri == '/')) {
00343          if (*uri == '/')
00344             uri++;
00345          ast_rwlock_rdlock(&uris_lock);
00346          urih = uris;
00347          while(urih) {
00348             len = strlen(urih->uri);
00349             if (!strncasecmp(urih->uri, uri, len)) {
00350                if (!uri[len] || uri[len] == '/') {
00351                   turi = uri + len;
00352                   if (*turi == '/')
00353                      turi++;
00354                   if (!*turi || urih->has_subtree) {
00355                      uri = turi;
00356                      break;
00357                   }
00358                }
00359             }
00360             urih = urih->next;
00361          }
00362          if (!urih)
00363             ast_rwlock_unlock(&uris_lock);
00364       }
00365    }
00366    if (urih) {
00367       if (urih->static_content)
00368          *static_content = 1;
00369       c = urih->callback(sin, uri, vars, status, title, contentlength);
00370       ast_rwlock_unlock(&uris_lock);
00371    } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) {
00372       /* Special case: If no prefix, and no URI, send to /static/index.html */
00373       c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "Redirecting to /static/index.html.");
00374       *status = 302;
00375       *title = strdup("Moved Temporarily");
00376    } else {
00377       c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
00378       *status = 404;
00379       *title = strdup("Not Found");
00380    }
00381    ast_variables_destroy(vars);
00382    return c;
00383 }

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

Definition at line 521 of file http.c.

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

Referenced by http_server_start().

00522 {
00523    int fd;
00524    struct sockaddr_in sin;
00525    socklen_t sinlen;
00526    struct ast_http_server_instance *ser;
00527    pthread_t launched;
00528    pthread_attr_t attr;
00529    
00530    for (;;) {
00531       int flags;
00532 
00533       ast_wait_for_input(httpfd, -1);
00534       sinlen = sizeof(sin);
00535       fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen);
00536       if (fd < 0) {
00537          if ((errno != EAGAIN) && (errno != EINTR))
00538             ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno));
00539          continue;
00540       }
00541       ser = ast_calloc(1, sizeof(*ser));
00542       if (!ser) {
00543          ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno));
00544          close(fd);
00545          continue;
00546       }
00547       flags = fcntl(fd, F_GETFL);
00548       fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
00549       ser->fd = fd;
00550       memcpy(&ser->requestor, &sin, sizeof(ser->requestor));
00551       if ((ser->f = fdopen(ser->fd, "w+"))) {
00552          pthread_attr_init(&attr);
00553          pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00554          
00555          if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) {
00556             ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno));
00557             fclose(ser->f);
00558             free(ser);
00559          }
00560          pthread_attr_destroy(&attr);
00561       } else {
00562          ast_log(LOG_WARNING, "fdopen failed!\n");
00563          close(ser->fd);
00564          free(ser);
00565       }
00566    }
00567    return NULL;
00568 }

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

Definition at line 582 of file http.c.

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

Referenced by __ast_http_load().

00583 {
00584    int flags;
00585    int x = 1;
00586    
00587    /* Do nothing if nothing has changed */
00588    if (!memcmp(&oldsin, sin, sizeof(oldsin))) {
00589       ast_log(LOG_DEBUG, "Nothing changed in http\n");
00590       return;
00591    }
00592    
00593    memcpy(&oldsin, sin, sizeof(oldsin));
00594    
00595    /* Shutdown a running server if there is one */
00596    if (master != AST_PTHREADT_NULL) {
00597       pthread_cancel(master);
00598       pthread_kill(master, SIGURG);
00599       pthread_join(master, NULL);
00600    }
00601    
00602    if (httpfd != -1)
00603       close(httpfd);
00604 
00605    /* If there's no new server, stop here */
00606    if (!sin->sin_family)
00607       return;
00608    
00609    
00610    httpfd = socket(AF_INET, SOCK_STREAM, 0);
00611    if (httpfd < 0) {
00612       ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
00613       return;
00614    }
00615    
00616    setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
00617    if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) {
00618       ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n",
00619          ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00620          strerror(errno));
00621       close(httpfd);
00622       httpfd = -1;
00623       return;
00624    }
00625    if (listen(httpfd, 10)) {
00626       ast_log(LOG_NOTICE, "Unable to listen!\n");
00627       close(httpfd);
00628       httpfd = -1;
00629       return;
00630    }
00631    flags = fcntl(httpfd, F_GETFL);
00632    fcntl(httpfd, F_SETFL, flags | O_NONBLOCK);
00633    if (ast_pthread_create_background(&master, NULL, http_root, NULL)) {
00634       ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n",
00635             ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port),
00636             strerror(errno));
00637       close(httpfd);
00638       httpfd = -1;
00639    }
00640 }

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, 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 struct ast_variable* parse_cookies ( char *  cookies  )  [static]

Definition at line 385 of file http.c.

References ast_log(), ast_strip(), ast_strip_quoted(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, name, option_debug, and var.

Referenced by ast_httpd_helper_thread().

00386 {
00387    char *cur;
00388    struct ast_variable *vars = NULL, *var;
00389 
00390    /* Skip Cookie: */
00391    cookies += 8;
00392 
00393    while ((cur = strsep(&cookies, ";"))) {
00394       char *name, *val;
00395       
00396       name = val = cur;
00397       strsep(&val, "=");
00398 
00399       if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
00400          continue;
00401       }
00402 
00403       name = ast_strip(name);
00404       val = ast_strip_quoted(val, "\"", "\"");
00405 
00406       if (ast_strlen_zero(name) || ast_strlen_zero(val)) {
00407          continue;
00408       }
00409 
00410       if (option_debug) {
00411          ast_log(LOG_DEBUG, "mmm ... cookie!  Name: '%s'  Value: '%s'\n", name, val);
00412       }
00413 
00414       var = ast_variable_new(name, val);
00415       var->next = vars;
00416       vars = var;
00417    }
00418 
00419    return vars;
00420 }

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, 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, "The requested URL was not found on this server.");
00171 
00172 out403:
00173    *status = 403;
00174    *title = strdup("Access Denied");
00175    return ast_http_error(403, "Access Denied", NULL, "You do not have permission to access the requested URL.");
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 739 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(), 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(), dahdi_bridge(), dahdi_link(), dahdi_restart(), and dahdi_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(), handle_verbose(), 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 735 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().

ast_rwlock_t uris_lock = PTHREAD_RWLOCK_INITIALIZER [static]

Definition at line 70 of file http.c.

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


Generated on Thu May 14 15:13:33 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7