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