#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 | DEFAULT_SESSION_LIMIT 100 |
#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 struct ast_variable * | parse_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 int | session_count = 0 |
static int | session_limit = DEFAULT_SESSION_LIMIT |
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 DEFAULT_SESSION_LIMIT 100 |
#define MAX_PREFIX 80 |
static int __ast_http_load | ( | int | reload | ) | [static] |
Definition at line 649 of file http.c.
References ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable_browse(), DEFAULT_PREFIX, DEFAULT_SESSION_LIMIT, 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().
00650 { 00651 struct ast_config *cfg; 00652 struct ast_variable *v; 00653 int enabled=0; 00654 int newenablestatic=0; 00655 struct sockaddr_in sin; 00656 struct hostent *hp; 00657 struct ast_hostent ahp; 00658 char newprefix[MAX_PREFIX]; 00659 00660 memset(&sin, 0, sizeof(sin)); 00661 sin.sin_port = htons(8088); 00662 00663 strcpy(newprefix, DEFAULT_PREFIX); 00664 00665 cfg = ast_config_load("http.conf"); 00666 if (cfg) { 00667 v = ast_variable_browse(cfg, "general"); 00668 while(v) { 00669 if (!strcasecmp(v->name, "enabled")) 00670 enabled = ast_true(v->value); 00671 else if (!strcasecmp(v->name, "enablestatic")) 00672 newenablestatic = ast_true(v->value); 00673 else if (!strcasecmp(v->name, "bindport")) 00674 sin.sin_port = ntohs(atoi(v->value)); 00675 else if (!strcasecmp(v->name, "bindaddr")) { 00676 if ((hp = ast_gethostbyname(v->value, &ahp))) { 00677 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00678 } else { 00679 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value); 00680 } 00681 } else if (!strcasecmp(v->name, "prefix")) { 00682 if (!ast_strlen_zero(v->value)) { 00683 newprefix[0] = '/'; 00684 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1); 00685 } else { 00686 newprefix[0] = '\0'; 00687 } 00688 } else if (!strcasecmp(v->name, "sessionlimit")) { 00689 int limit = atoi(v->value); 00690 00691 if (limit < 1) { 00692 ast_log(LOG_WARNING, "Invalid sessionlimit value '%s', using default value\n", v->value); 00693 session_limit = DEFAULT_SESSION_LIMIT; 00694 } else { 00695 session_limit = limit; 00696 } 00697 } 00698 00699 v = v->next; 00700 } 00701 ast_config_destroy(cfg); 00702 } 00703 if (enabled) 00704 sin.sin_family = AF_INET; 00705 if (strcmp(prefix, newprefix)) { 00706 ast_copy_string(prefix, newprefix, sizeof(prefix)); 00707 prefix_len = strlen(prefix); 00708 } 00709 enablestatic = newenablestatic; 00710 00711 http_server_start(&sin); 00712 00713 00714 return 0; 00715 }
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 234 of file http.c.
References asprintf.
Referenced by ast_httpd_helper_thread(), generic_http_callback(), handle_uri(), and static_callback().
00235 { 00236 char *c = NULL; 00237 asprintf(&c, 00238 "Content-type: text/html\r\n" 00239 "%s" 00240 "\r\n" 00241 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 00242 "<html><head>\r\n" 00243 "<title>%d %s</title>\r\n" 00244 "</head><body>\r\n" 00245 "<h1>%s</h1>\r\n" 00246 "<p>%s</p>\r\n" 00247 "<hr />\r\n" 00248 "<address>Asterisk Server</address>\r\n" 00249 "</body></html>\r\n", 00250 (extra_header ? extra_header : ""), status, title, title, text); 00251 return c; 00252 }
int ast_http_init | ( | void | ) |
Definition at line 761 of file http.c.
References __ast_http_load(), ast_cli_register_multiple(), and ast_http_uri_link().
Referenced by main().
00762 { 00763 ast_http_uri_link(&statusuri); 00764 ast_http_uri_link(&staticuri); 00765 ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry)); 00766 00767 return __ast_http_load(0); 00768 }
int ast_http_reload | ( | void | ) |
Definition at line 746 of file http.c.
References __ast_http_load().
00747 { 00748 return __ast_http_load(1); 00749 }
char* ast_http_setcookie | ( | const char * | var, | |
const char * | val, | |||
int | expires, | |||
char * | buf, | |||
size_t | buflen | |||
) |
Definition at line 577 of file http.c.
References ast_build_string().
Referenced by generic_http_callback().
00578 { 00579 char *c; 00580 c = buf; 00581 ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val); 00582 if (expires) 00583 ast_build_string(&c, &buflen, "; Max-Age=%d", expires); 00584 ast_build_string(&c, &buflen, "\r\n"); 00585 return buf; 00586 }
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, and ast_http_uri::uri.
Referenced by ast_http_init(), and init_manager().
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(), and ast_http_uri::next.
Referenced by init_manager().
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_strlen_zero(), ast_variables_destroy(), ASTERISK_VERSION, ast_http_server_instance::f, ast_http_server_instance::fd, free, handle_uri(), 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 write(ser->fd, c, (tmp + 4 - c)); 00503 write(ser->fd, tmp + 4, contentlength); 00504 } 00505 } else 00506 ast_cli(ser->fd, "%s", c); 00507 free(c); 00508 } 00509 if (title) 00510 free(title); 00511 } 00512 fclose(ser->f); 00513 free(ser); 00514 ast_atomic_fetchadd_int(&session_count, -1); 00515 return NULL; 00516 }
AST_RWLOCK_DEFINE_STATIC | ( | uris_lock | ) |
static const char* ftype2mtype | ( | const char * | ftype, | |
char * | wkspace, | |||
int | wkspacelen | |||
) | [static] |
Definition at line 98 of file http.c.
References ext, mimetypes, and mtype.
Referenced by static_callback().
00099 { 00100 int x; 00101 if (ftype) { 00102 for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) { 00103 if (!strcasecmp(ftype, mimetypes[x].ext)) 00104 return mimetypes[x].mtype; 00105 } 00106 } 00107 snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain"); 00108 return wkspace; 00109 }
static int handle_show_http | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 717 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, oldsin, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_http_uri::uri.
00718 { 00719 struct ast_http_uri *urih; 00720 00721 if (argc != 3) 00722 return RESULT_SHOWUSAGE; 00723 00724 ast_cli(fd, "HTTP Server Status:\n"); 00725 ast_cli(fd, "Prefix: %s\n", prefix); 00726 if (oldsin.sin_family) 00727 ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n", 00728 ast_inet_ntoa(oldsin.sin_addr), 00729 ntohs(oldsin.sin_port)); 00730 else 00731 ast_cli(fd, "Server Disabled\n\n"); 00732 ast_cli(fd, "Enabled URI's:\n"); 00733 ast_rwlock_rdlock(&uris_lock); 00734 urih = uris; 00735 while(urih){ 00736 ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description); 00737 urih = urih->next; 00738 } 00739 if (!uris) 00740 ast_cli(fd, "None.\n"); 00741 ast_rwlock_unlock(&uris_lock); 00742 00743 return RESULT_SUCCESS; 00744 }
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_variable::next, ast_http_uri::static_content, strdup, strsep(), ast_http_uri::uri, 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(¶ms, "&"))) { 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", "This is not the page you are looking for..."); 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 518 of file http.c.
References ast_calloc, ast_httpd_helper_thread(), ast_log(), ast_pthread_create_background, ast_wait_for_input(), errno, ast_http_server_instance::f, ast_http_server_instance::fd, free, LOG_WARNING, and ast_http_server_instance::requestor.
Referenced by http_server_start().
00519 { 00520 int fd; 00521 struct sockaddr_in sin; 00522 socklen_t sinlen; 00523 struct ast_http_server_instance *ser; 00524 pthread_t launched; 00525 pthread_attr_t attr; 00526 00527 for (;;) { 00528 int flags; 00529 00530 ast_wait_for_input(httpfd, -1); 00531 sinlen = sizeof(sin); 00532 fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen); 00533 00534 if (fd < 0) { 00535 if ((errno != EAGAIN) && (errno != EINTR)) 00536 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00537 continue; 00538 } 00539 00540 if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) { 00541 close(fd); 00542 continue; 00543 } 00544 00545 ser = ast_calloc(1, sizeof(*ser)); 00546 if (!ser) { 00547 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00548 close(fd); 00549 ast_atomic_fetchadd_int(&session_count, -1); 00550 continue; 00551 } 00552 flags = fcntl(fd, F_GETFL); 00553 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00554 ser->fd = fd; 00555 memcpy(&ser->requestor, &sin, sizeof(ser->requestor)); 00556 if ((ser->f = fdopen(ser->fd, "w+"))) { 00557 pthread_attr_init(&attr); 00558 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00559 00560 if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) { 00561 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00562 fclose(ser->f); 00563 free(ser); 00564 ast_atomic_fetchadd_int(&session_count, -1); 00565 } 00566 pthread_attr_destroy(&attr); 00567 } else { 00568 ast_log(LOG_WARNING, "fdopen failed!\n"); 00569 close(ser->fd); 00570 free(ser); 00571 ast_atomic_fetchadd_int(&session_count, -1); 00572 } 00573 } 00574 return NULL; 00575 }
static void http_server_start | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 589 of file http.c.
References ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, errno, http_root(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, and oldsin.
Referenced by __ast_http_load().
00590 { 00591 int flags; 00592 int x = 1; 00593 00594 /* Do nothing if nothing has changed */ 00595 if (!memcmp(&oldsin, sin, sizeof(oldsin))) { 00596 ast_log(LOG_DEBUG, "Nothing changed in http\n"); 00597 return; 00598 } 00599 00600 memcpy(&oldsin, sin, sizeof(oldsin)); 00601 00602 /* Shutdown a running server if there is one */ 00603 if (master != AST_PTHREADT_NULL) { 00604 pthread_cancel(master); 00605 pthread_kill(master, SIGURG); 00606 pthread_join(master, NULL); 00607 } 00608 00609 if (httpfd != -1) 00610 close(httpfd); 00611 00612 /* If there's no new server, stop here */ 00613 if (!sin->sin_family) 00614 return; 00615 00616 00617 httpfd = socket(AF_INET, SOCK_STREAM, 0); 00618 if (httpfd < 0) { 00619 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00620 return; 00621 } 00622 00623 setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00624 if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) { 00625 ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n", 00626 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00627 strerror(errno)); 00628 close(httpfd); 00629 httpfd = -1; 00630 return; 00631 } 00632 if (listen(httpfd, 10)) { 00633 ast_log(LOG_NOTICE, "Unable to listen!\n"); 00634 close(httpfd); 00635 httpfd = -1; 00636 return; 00637 } 00638 flags = fcntl(httpfd, F_GETFL); 00639 fcntl(httpfd, F_SETFL, flags | O_NONBLOCK); 00640 if (ast_pthread_create_background(&master, NULL, http_root, NULL)) { 00641 ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n", 00642 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00643 strerror(errno)); 00644 close(httpfd); 00645 httpfd = -1; 00646 } 00647 }
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 182 of file http.c.
References ast_build_string(), ast_inet_ntoa(), ast_variable::name, ast_variable::next, oldsin, strdup, and ast_variable::value.
00183 { 00184 char result[4096]; 00185 size_t reslen = sizeof(result); 00186 char *c=result; 00187 struct ast_variable *v; 00188 00189 ast_build_string(&c, &reslen, 00190 "\r\n" 00191 "<title>Asterisk HTTP Status</title>\r\n" 00192 "<body bgcolor=\"#ffffff\">\r\n" 00193 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n" 00194 "<h2> Asterisk™ HTTP Status</h2></td></tr>\r\n"); 00195 00196 ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix); 00197 ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n", 00198 ast_inet_ntoa(oldsin.sin_addr)); 00199 ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n", 00200 ntohs(oldsin.sin_port)); 00201 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00202 v = vars; 00203 while(v) { 00204 if (strncasecmp(v->name, "cookie_", 7)) 00205 ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00206 v = v->next; 00207 } 00208 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00209 v = vars; 00210 while(v) { 00211 if (!strncasecmp(v->name, "cookie_", 7)) 00212 ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00213 v = v->next; 00214 } 00215 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"); 00216 return strdup(result); 00217 }
static struct ast_variable* parse_cookies | ( | char * | cookies | ) | [static, read] |
Definition at line 385 of file http.c.
References ast_log(), ast_strip_quoted(), ast_strlen_zero(), ast_variable_new(), LOG_DEBUG, name, option_debug, strsep(), 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 111 of file http.c.
References ast_config_AST_DATA_DIR, ast_http_error(), ast_strlen_zero(), free, ftype2mtype(), len, malloc, mtype, and strdup.
00112 { 00113 char result[4096]; 00114 char *c=result; 00115 char *path; 00116 char *ftype; 00117 const char *mtype; 00118 char wkspace[80]; 00119 struct stat st; 00120 int len; 00121 int fd; 00122 void *blob; 00123 00124 /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration 00125 substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */ 00126 if (!enablestatic || ast_strlen_zero(uri)) 00127 goto out403; 00128 /* Disallow any funny filenames at all */ 00129 if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) 00130 goto out403; 00131 if (strstr(uri, "/..")) 00132 goto out403; 00133 00134 if ((ftype = strrchr(uri, '.'))) 00135 ftype++; 00136 mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace)); 00137 00138 /* Cap maximum length */ 00139 len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5; 00140 if (len > 1024) 00141 goto out403; 00142 00143 path = alloca(len); 00144 sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri); 00145 if (stat(path, &st)) 00146 goto out404; 00147 if (S_ISDIR(st.st_mode)) 00148 goto out404; 00149 fd = open(path, O_RDONLY); 00150 if (fd < 0) 00151 goto out403; 00152 00153 len = st.st_size + strlen(mtype) + 40; 00154 00155 blob = malloc(len); 00156 if (blob) { 00157 c = blob; 00158 sprintf(c, "Content-type: %s\r\n\r\n", mtype); 00159 c += strlen(c); 00160 *contentlength = read(fd, c, st.st_size); 00161 if (*contentlength < 0) { 00162 close(fd); 00163 free(blob); 00164 goto out403; 00165 } 00166 } 00167 close(fd); 00168 return blob; 00169 00170 out404: 00171 *status = 404; 00172 *title = strdup("Not Found"); 00173 return ast_http_error(404, "Not Found", NULL, "Nothing to see here. Move along."); 00174 00175 out403: 00176 *status = 403; 00177 *title = strdup("Access Denied"); 00178 return ast_http_error(403, "Access Denied", NULL, "Sorry, I cannot let you do that, Dave."); 00179 }
struct ast_cli_entry cli_http[] [static] |
Initial value:
{ { { "http", "show", "status", NULL }, handle_show_http, "Display HTTP server status", show_http_help }, }
int enablestatic [static] |
const char* ext |
Definition at line 85 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] |
struct { ... } mimetypes[] [static] |
const char* mtype |
struct sockaddr_in oldsin [static] |
Definition at line 78 of file http.c.
Referenced by handle_show_http(), http_server_start(), and httpstatus_callback().
char prefix[MAX_PREFIX] [static] |
Definition at line 76 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] |
int session_count = 0 [static] |
int session_limit = DEFAULT_SESSION_LIMIT [static] |
char show_http_help[] [static] |
struct ast_http_uri staticuri [static] |
struct ast_http_uri statusuri [static] |
struct ast_http_uri* uris [static] |