#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 <signal.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) |
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 |
static ast_rwlock_t | uris_lock = PTHREAD_RWLOCK_INITIALIZER |
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 657 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, 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().
00658 { 00659 struct ast_config *cfg; 00660 struct ast_variable *v; 00661 int enabled=0; 00662 int newenablestatic=0; 00663 struct sockaddr_in sin; 00664 struct hostent *hp; 00665 struct ast_hostent ahp; 00666 char newprefix[MAX_PREFIX]; 00667 00668 memset(&sin, 0, sizeof(sin)); 00669 sin.sin_port = htons(8088); 00670 00671 strcpy(newprefix, DEFAULT_PREFIX); 00672 00673 cfg = ast_config_load("http.conf"); 00674 if (cfg) { 00675 v = ast_variable_browse(cfg, "general"); 00676 while(v) { 00677 if (!strcasecmp(v->name, "enabled")) 00678 enabled = ast_true(v->value); 00679 else if (!strcasecmp(v->name, "enablestatic")) 00680 newenablestatic = ast_true(v->value); 00681 else if (!strcasecmp(v->name, "bindport")) 00682 sin.sin_port = ntohs(atoi(v->value)); 00683 else if (!strcasecmp(v->name, "bindaddr")) { 00684 if ((hp = ast_gethostbyname(v->value, &ahp))) { 00685 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00686 } else { 00687 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value); 00688 } 00689 } else if (!strcasecmp(v->name, "prefix")) { 00690 if (!ast_strlen_zero(v->value)) { 00691 newprefix[0] = '/'; 00692 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1); 00693 } else { 00694 newprefix[0] = '\0'; 00695 } 00696 } else if (!strcasecmp(v->name, "sessionlimit")) { 00697 int limit = atoi(v->value); 00698 00699 if (limit < 1) { 00700 ast_log(LOG_WARNING, "Invalid sessionlimit value '%s', using default value\n", v->value); 00701 session_limit = DEFAULT_SESSION_LIMIT; 00702 } else { 00703 session_limit = limit; 00704 } 00705 } 00706 00707 v = v->next; 00708 } 00709 ast_config_destroy(cfg); 00710 } 00711 if (enabled) 00712 sin.sin_family = AF_INET; 00713 if (strcmp(prefix, newprefix)) { 00714 ast_copy_string(prefix, newprefix, sizeof(prefix)); 00715 prefix_len = strlen(prefix); 00716 } 00717 enablestatic = newenablestatic; 00718 00719 http_server_start(&sin); 00720 00721 00722 return 0; 00723 }
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 235 of file http.c.
References asprintf, ast_log(), errno, and LOG_WARNING.
Referenced by ast_httpd_helper_thread(), handle_uri(), and static_callback().
00236 { 00237 char *c = NULL; 00238 if (asprintf(&c, 00239 "Content-type: text/html\r\n" 00240 "%s" 00241 "\r\n" 00242 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 00243 "<html><head>\r\n" 00244 "<title>%d %s</title>\r\n" 00245 "</head><body>\r\n" 00246 "<h1>%s</h1>\r\n" 00247 "<p>%s</p>\r\n" 00248 "<hr />\r\n" 00249 "<address>Asterisk Server</address>\r\n" 00250 "</body></html>\r\n", 00251 (extra_header ? extra_header : ""), status, title, title, text) < 0) { 00252 ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno)); 00253 c = NULL; 00254 } 00255 return c; 00256 }
int ast_http_init | ( | void | ) |
Definition at line 769 of file http.c.
References __ast_http_load(), ast_cli_register_multiple(), ast_http_uri_link(), cli_http, staticuri, and statusuri.
Referenced by main().
00770 { 00771 ast_http_uri_link(&statusuri); 00772 ast_http_uri_link(&staticuri); 00773 ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry)); 00774 00775 return __ast_http_load(0); 00776 }
int ast_http_reload | ( | void | ) |
Definition at line 754 of file http.c.
References __ast_http_load().
00755 { 00756 return __ast_http_load(1); 00757 }
char* ast_http_setcookie | ( | const char * | var, | |
const char * | val, | |||
int | expires, | |||
char * | buf, | |||
size_t | buflen | |||
) |
Definition at line 585 of file http.c.
References ast_build_string().
00586 { 00587 char *c; 00588 c = buf; 00589 ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=1", var, val); 00590 if (expires) 00591 ast_build_string(&c, &buflen, "; Max-Age=%d", expires); 00592 ast_build_string(&c, &buflen, "\r\n"); 00593 return buf; 00594 }
int ast_http_uri_link | ( | struct ast_http_uri * | urih | ) |
Link into the Asterisk HTTP server.
Definition at line 258 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().
00259 { 00260 struct ast_http_uri *prev; 00261 00262 ast_rwlock_wrlock(&uris_lock); 00263 prev = uris; 00264 if (!uris || strlen(uris->uri) <= strlen(urih->uri)) { 00265 urih->next = uris; 00266 uris = urih; 00267 } else { 00268 while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri))) 00269 prev = prev->next; 00270 /* Insert it here */ 00271 urih->next = prev->next; 00272 prev->next = urih; 00273 } 00274 ast_rwlock_unlock(&uris_lock); 00275 00276 return 0; 00277 }
void ast_http_uri_unlink | ( | struct ast_http_uri * | urih | ) |
Destroy an HTTP server.
Definition at line 279 of file http.c.
References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, uris, and uris_lock.
00280 { 00281 struct ast_http_uri *prev; 00282 00283 ast_rwlock_wrlock(&uris_lock); 00284 if (!uris) { 00285 ast_rwlock_unlock(&uris_lock); 00286 return; 00287 } 00288 prev = uris; 00289 if (uris == urih) { 00290 uris = uris->next; 00291 } 00292 while(prev->next) { 00293 if (prev->next == urih) { 00294 prev->next = urih->next; 00295 break; 00296 } 00297 prev = prev->next; 00298 } 00299 ast_rwlock_unlock(&uris_lock); 00300 }
static void* ast_httpd_helper_thread | ( | void * | data | ) | [static] |
Definition at line 426 of file http.c.
References ast_atomic_fetchadd_int(), 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().
00427 { 00428 char buf[4096]; 00429 char cookie[4096]; 00430 char timebuf[256]; 00431 struct ast_http_server_instance *ser = data; 00432 struct ast_variable *vars = NULL; 00433 char *uri, *c, *title=NULL; 00434 int status = 200, contentlength = 0; 00435 time_t t; 00436 unsigned int static_content = 0; 00437 00438 if (fgets(buf, sizeof(buf), ser->f)) { 00439 /* Skip method */ 00440 uri = buf; 00441 while(*uri && (*uri > 32)) 00442 uri++; 00443 if (*uri) { 00444 *uri = '\0'; 00445 uri++; 00446 } 00447 00448 /* Skip white space */ 00449 while (*uri && (*uri < 33)) 00450 uri++; 00451 00452 if (*uri) { 00453 c = uri; 00454 while (*c && (*c > 32)) 00455 c++; 00456 if (*c) { 00457 *c = '\0'; 00458 } 00459 } 00460 00461 while (fgets(cookie, sizeof(cookie), ser->f)) { 00462 /* Trim trailing characters */ 00463 while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) { 00464 cookie[strlen(cookie) - 1] = '\0'; 00465 } 00466 if (ast_strlen_zero(cookie)) 00467 break; 00468 if (!strncasecmp(cookie, "Cookie: ", 8)) { 00469 vars = parse_cookies(cookie); 00470 } 00471 } 00472 00473 if (*uri) { 00474 if (!strcasecmp(buf, "get")) 00475 c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars, &static_content); 00476 else 00477 c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\ 00478 } else 00479 c = ast_http_error(400, "Bad Request", NULL, "Invalid Request"); 00480 00481 /* If they aren't mopped up already, clean up the cookies */ 00482 if (vars) 00483 ast_variables_destroy(vars); 00484 00485 if (!c) 00486 c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error"); 00487 if (c) { 00488 time(&t); 00489 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); 00490 ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK"); 00491 ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION); 00492 ast_cli(ser->fd, "Date: %s\r\n", timebuf); 00493 ast_cli(ser->fd, "Connection: close\r\n"); 00494 if (!static_content) 00495 ast_cli(ser->fd, "Cache-Control: no-cache, no-store\r\n"); 00496 /* We set the no-cache headers only for dynamic content. 00497 * If you want to make sure the static file you requested is not from cache, 00498 * append a random variable to your GET request. Ex: 'something.html?r=109987734' 00499 */ 00500 00501 if (contentlength) { 00502 char *tmp; 00503 tmp = strstr(c, "\r\n\r\n"); 00504 if (tmp) { 00505 ast_cli(ser->fd, "Content-length: %d\r\n", contentlength); 00506 if (write(ser->fd, c, (tmp + 4 - c)) < 0) { 00507 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00508 } 00509 if (write(ser->fd, tmp + 4, contentlength) < 0) { 00510 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00511 } 00512 } 00513 } else 00514 ast_cli(ser->fd, "%s", c); 00515 free(c); 00516 } 00517 if (title) 00518 free(title); 00519 } 00520 fclose(ser->f); 00521 free(ser); 00522 ast_atomic_fetchadd_int(&session_count, -1); 00523 return NULL; 00524 }
static const char* ftype2mtype | ( | const char * | ftype, | |
char * | wkspace, | |||
int | wkspacelen | |||
) | [static] |
Definition at line 99 of file http.c.
References ext, mimetypes, and mtype.
Referenced by static_callback().
00100 { 00101 int x; 00102 if (ftype) { 00103 for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) { 00104 if (!strcasecmp(ftype, mimetypes[x].ext)) 00105 return mimetypes[x].mtype; 00106 } 00107 } 00108 snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain"); 00109 return wkspace; 00110 }
static int handle_show_http | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 725 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.
00726 { 00727 struct ast_http_uri *urih; 00728 00729 if (argc != 3) 00730 return RESULT_SHOWUSAGE; 00731 00732 ast_cli(fd, "HTTP Server Status:\n"); 00733 ast_cli(fd, "Prefix: %s\n", prefix); 00734 if (oldsin.sin_family) 00735 ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n", 00736 ast_inet_ntoa(oldsin.sin_addr), 00737 ntohs(oldsin.sin_port)); 00738 else 00739 ast_cli(fd, "Server Disabled\n\n"); 00740 ast_cli(fd, "Enabled URI's:\n"); 00741 ast_rwlock_rdlock(&uris_lock); 00742 urih = uris; 00743 while(urih){ 00744 ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description); 00745 urih = urih->next; 00746 } 00747 if (!uris) 00748 ast_cli(fd, "None.\n"); 00749 ast_rwlock_unlock(&uris_lock); 00750 00751 return RESULT_SUCCESS; 00752 }
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 302 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().
00305 { 00306 char *c; 00307 char *turi; 00308 char *params; 00309 char *var; 00310 char *val; 00311 struct ast_http_uri *urih=NULL; 00312 int len; 00313 struct ast_variable *vars=NULL, *v, *prev = NULL; 00314 00315 00316 params = strchr(uri, '?'); 00317 if (params) { 00318 *params = '\0'; 00319 params++; 00320 while ((var = strsep(¶ms, "&"))) { 00321 val = strchr(var, '='); 00322 if (val) { 00323 *val = '\0'; 00324 val++; 00325 ast_uri_decode(val); 00326 } else 00327 val = ""; 00328 ast_uri_decode(var); 00329 if ((v = ast_variable_new(var, val))) { 00330 if (vars) 00331 prev->next = v; 00332 else 00333 vars = v; 00334 prev = v; 00335 } 00336 } 00337 } 00338 if (prev) 00339 prev->next = *cookies; 00340 else 00341 vars = *cookies; 00342 *cookies = NULL; 00343 ast_uri_decode(uri); 00344 if (!strncasecmp(uri, prefix, prefix_len)) { 00345 uri += prefix_len; 00346 if (!*uri || (*uri == '/')) { 00347 if (*uri == '/') 00348 uri++; 00349 ast_rwlock_rdlock(&uris_lock); 00350 urih = uris; 00351 while(urih) { 00352 len = strlen(urih->uri); 00353 if (!strncasecmp(urih->uri, uri, len)) { 00354 if (!uri[len] || uri[len] == '/') { 00355 turi = uri + len; 00356 if (*turi == '/') 00357 turi++; 00358 if (!*turi || urih->has_subtree) { 00359 uri = turi; 00360 break; 00361 } 00362 } 00363 } 00364 urih = urih->next; 00365 } 00366 if (!urih) 00367 ast_rwlock_unlock(&uris_lock); 00368 } 00369 } 00370 if (urih) { 00371 if (urih->static_content) 00372 *static_content = 1; 00373 c = urih->callback(sin, uri, vars, status, title, contentlength); 00374 ast_rwlock_unlock(&uris_lock); 00375 } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) { 00376 /* Special case: If no prefix, and no URI, send to /static/index.html */ 00377 c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "Redirecting to /static/index.html."); 00378 *status = 302; 00379 *title = strdup("Moved Temporarily"); 00380 } else { 00381 c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); 00382 *status = 404; 00383 *title = strdup("Not Found"); 00384 } 00385 ast_variables_destroy(vars); 00386 return c; 00387 }
static void* http_root | ( | void * | data | ) | [static] |
Definition at line 526 of file http.c.
References ast_atomic_fetchadd_int(), 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().
00527 { 00528 int fd; 00529 struct sockaddr_in sin; 00530 socklen_t sinlen; 00531 struct ast_http_server_instance *ser; 00532 pthread_t launched; 00533 pthread_attr_t attr; 00534 00535 for (;;) { 00536 int flags; 00537 00538 ast_wait_for_input(httpfd, -1); 00539 sinlen = sizeof(sin); 00540 fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen); 00541 00542 if (fd < 0) { 00543 if ((errno != EAGAIN) && (errno != EINTR)) 00544 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00545 continue; 00546 } 00547 00548 if (ast_atomic_fetchadd_int(&session_count, +1) >= session_limit) { 00549 close(fd); 00550 continue; 00551 } 00552 00553 ser = ast_calloc(1, sizeof(*ser)); 00554 if (!ser) { 00555 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00556 close(fd); 00557 ast_atomic_fetchadd_int(&session_count, -1); 00558 continue; 00559 } 00560 flags = fcntl(fd, F_GETFL); 00561 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00562 ser->fd = fd; 00563 memcpy(&ser->requestor, &sin, sizeof(ser->requestor)); 00564 if ((ser->f = fdopen(ser->fd, "w+"))) { 00565 pthread_attr_init(&attr); 00566 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00567 00568 if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) { 00569 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00570 fclose(ser->f); 00571 free(ser); 00572 ast_atomic_fetchadd_int(&session_count, -1); 00573 } 00574 pthread_attr_destroy(&attr); 00575 } else { 00576 ast_log(LOG_WARNING, "fdopen failed!\n"); 00577 close(ser->fd); 00578 free(ser); 00579 ast_atomic_fetchadd_int(&session_count, -1); 00580 } 00581 } 00582 return NULL; 00583 }
static void http_server_start | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 597 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().
00598 { 00599 int flags; 00600 int x = 1; 00601 00602 /* Do nothing if nothing has changed */ 00603 if (!memcmp(&oldsin, sin, sizeof(oldsin))) { 00604 ast_log(LOG_DEBUG, "Nothing changed in http\n"); 00605 return; 00606 } 00607 00608 memcpy(&oldsin, sin, sizeof(oldsin)); 00609 00610 /* Shutdown a running server if there is one */ 00611 if (master != AST_PTHREADT_NULL) { 00612 pthread_cancel(master); 00613 pthread_kill(master, SIGURG); 00614 pthread_join(master, NULL); 00615 } 00616 00617 if (httpfd != -1) 00618 close(httpfd); 00619 00620 /* If there's no new server, stop here */ 00621 if (!sin->sin_family) 00622 return; 00623 00624 00625 httpfd = socket(AF_INET, SOCK_STREAM, 0); 00626 if (httpfd < 0) { 00627 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00628 return; 00629 } 00630 00631 setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00632 if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) { 00633 ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n", 00634 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00635 strerror(errno)); 00636 close(httpfd); 00637 httpfd = -1; 00638 return; 00639 } 00640 if (listen(httpfd, 10)) { 00641 ast_log(LOG_NOTICE, "Unable to listen!\n"); 00642 close(httpfd); 00643 httpfd = -1; 00644 return; 00645 } 00646 flags = fcntl(httpfd, F_GETFL); 00647 fcntl(httpfd, F_SETFL, flags | O_NONBLOCK); 00648 if (ast_pthread_create_background(&master, NULL, http_root, NULL)) { 00649 ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n", 00650 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00651 strerror(errno)); 00652 close(httpfd); 00653 httpfd = -1; 00654 } 00655 }
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 183 of file http.c.
References ast_build_string(), ast_inet_ntoa(), ast_variable::name, ast_variable::next, strdup, and ast_variable::value.
00184 { 00185 char result[4096]; 00186 size_t reslen = sizeof(result); 00187 char *c=result; 00188 struct ast_variable *v; 00189 00190 ast_build_string(&c, &reslen, 00191 "\r\n" 00192 "<title>Asterisk HTTP Status</title>\r\n" 00193 "<body bgcolor=\"#ffffff\">\r\n" 00194 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n" 00195 "<h2> Asterisk™ HTTP Status</h2></td></tr>\r\n"); 00196 00197 ast_build_string(&c, &reslen, "<tr><td><i>Prefix</i></td><td><b>%s</b></td></tr>\r\n", prefix); 00198 ast_build_string(&c, &reslen, "<tr><td><i>Bind Address</i></td><td><b>%s</b></td></tr>\r\n", 00199 ast_inet_ntoa(oldsin.sin_addr)); 00200 ast_build_string(&c, &reslen, "<tr><td><i>Bind Port</i></td><td><b>%d</b></td></tr>\r\n", 00201 ntohs(oldsin.sin_port)); 00202 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00203 v = vars; 00204 while(v) { 00205 if (strncasecmp(v->name, "cookie_", 7)) 00206 ast_build_string(&c, &reslen, "<tr><td><i>Submitted Variable '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00207 v = v->next; 00208 } 00209 ast_build_string(&c, &reslen, "<tr><td colspan=\"2\"><hr></td></tr>\r\n"); 00210 v = vars; 00211 while(v) { 00212 if (!strncasecmp(v->name, "cookie_", 7)) 00213 ast_build_string(&c, &reslen, "<tr><td><i>Cookie '%s'</i></td><td>%s</td></tr>\r\n", v->name, v->value); 00214 v = v->next; 00215 } 00216 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"); 00217 return strdup(result); 00218 }
static struct ast_variable* parse_cookies | ( | char * | cookies | ) | [static] |
Definition at line 389 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().
00390 { 00391 char *cur; 00392 struct ast_variable *vars = NULL, *var; 00393 00394 /* Skip Cookie: */ 00395 cookies += 8; 00396 00397 while ((cur = strsep(&cookies, ";"))) { 00398 char *name, *val; 00399 00400 name = val = cur; 00401 strsep(&val, "="); 00402 00403 if (ast_strlen_zero(name) || ast_strlen_zero(val)) { 00404 continue; 00405 } 00406 00407 name = ast_strip(name); 00408 val = ast_strip_quoted(val, "\"", "\""); 00409 00410 if (ast_strlen_zero(name) || ast_strlen_zero(val)) { 00411 continue; 00412 } 00413 00414 if (option_debug) { 00415 ast_log(LOG_DEBUG, "mmm ... cookie! Name: '%s' Value: '%s'\n", name, val); 00416 } 00417 00418 var = ast_variable_new(name, val); 00419 var->next = vars; 00420 vars = var; 00421 } 00422 00423 return vars; 00424 }
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 112 of file http.c.
References ast_config_AST_DATA_DIR, ast_http_error(), ast_strlen_zero(), free, ftype2mtype(), len(), malloc, mtype, and strdup.
00113 { 00114 char result[4096]; 00115 char *c=result; 00116 char *path; 00117 char *ftype; 00118 const char *mtype; 00119 char wkspace[80]; 00120 struct stat st; 00121 int len; 00122 int fd; 00123 void *blob; 00124 00125 /* Yuck. I'm not really sold on this, but if you don't deliver static content it makes your configuration 00126 substantially more challenging, but this seems like a rather irritating feature creep on Asterisk. */ 00127 if (!enablestatic || ast_strlen_zero(uri)) 00128 goto out403; 00129 /* Disallow any funny filenames at all */ 00130 if ((uri[0] < 33) || strchr("./|~@#$%^&*() \t", uri[0])) 00131 goto out403; 00132 if (strstr(uri, "/..")) 00133 goto out403; 00134 00135 if ((ftype = strrchr(uri, '.'))) 00136 ftype++; 00137 mtype = ftype2mtype(ftype, wkspace, sizeof(wkspace)); 00138 00139 /* Cap maximum length */ 00140 len = strlen(uri) + strlen(ast_config_AST_DATA_DIR) + strlen("/static-http/") + 5; 00141 if (len > 1024) 00142 goto out403; 00143 00144 path = alloca(len); 00145 sprintf(path, "%s/static-http/%s", ast_config_AST_DATA_DIR, uri); 00146 if (stat(path, &st)) 00147 goto out404; 00148 if (S_ISDIR(st.st_mode)) 00149 goto out404; 00150 fd = open(path, O_RDONLY); 00151 if (fd < 0) 00152 goto out403; 00153 00154 len = st.st_size + strlen(mtype) + 40; 00155 00156 blob = malloc(len); 00157 if (blob) { 00158 c = blob; 00159 sprintf(c, "Content-type: %s\r\n\r\n", mtype); 00160 c += strlen(c); 00161 *contentlength = read(fd, c, st.st_size); 00162 if (*contentlength < 0) { 00163 close(fd); 00164 free(blob); 00165 goto out403; 00166 } 00167 } 00168 close(fd); 00169 return blob; 00170 00171 out404: 00172 *status = 404; 00173 *title = strdup("Not Found"); 00174 return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); 00175 00176 out403: 00177 *status = 403; 00178 *title = strdup("Access Denied"); 00179 return ast_http_error(403, "Access Denied", NULL, "You do not have permission to access the requested URL."); 00180 }
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 763 of file http.c.
Referenced by ast_http_init().
int enablestatic [static] |
const char* ext |
Definition at line 86 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 76 of file http.c.
Referenced by __unload_module(), dahdi_bridge(), dahdi_link(), dahdi_restart(), dahdi_unlink(), init_mfcr2_globals(), and setup_dahdi().
struct { ... } mimetypes[] [static] |
const char* mtype |
char prefix[MAX_PREFIX] [static] |
Definition at line 77 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] |
Definition at line 73 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 72 of file http.c.
Referenced by ast_http_uri_link(), ast_http_uri_unlink(), handle_show_http(), and handle_uri().