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

Go to the source code of this file.
Data Structures | |
| struct | ast_http_server_instance |
Defines | |
| #define | DEFAULT_PREFIX "/asterisk" |
| #define | MAX_PREFIX 80 |
Functions | |
| static int | __ast_http_load (int reload) |
| char * | ast_http_error (int status, const char *title, const char *extra_header, const char *text) |
| Return a malloc()'d string containing an HTTP error message. | |
| int | ast_http_init (void) |
| int | ast_http_reload (void) |
| char * | ast_http_setcookie (const char *var, const char *val, int expires, char *buf, size_t buflen) |
| int | ast_http_uri_link (struct ast_http_uri *urih) |
| Link into the Asterisk HTTP server. | |
| void | ast_http_uri_unlink (struct ast_http_uri *urih) |
| Destroy an HTTP server. | |
| static void * | ast_httpd_helper_thread (void *data) |
| AST_RWLOCK_DEFINE_STATIC (uris_lock) | |
| static const char * | ftype2mtype (const char *ftype, char *wkspace, int wkspacelen) |
| static int | handle_show_http (int fd, int argc, char *argv[]) |
| static char * | handle_uri (struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies) |
| static void * | http_root (void *data) |
| static void | http_server_start (struct sockaddr_in *sin) |
| static char * | httpstatus_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength) |
| static char * | static_callback (struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength) |
Variables | |
| static struct ast_cli_entry | cli_http [] |
| static int | enablestatic |
| static int | httpfd = -1 |
| static pthread_t | master = AST_PTHREADT_NULL |
| struct { | |
| const char * ext | |
| const char * mtype | |
| } | mimetypes [] |
| Limit the kinds of files we're willing to serve up. | |
| static struct sockaddr_in | oldsin |
| static char | prefix [MAX_PREFIX] |
| static int | prefix_len |
| static char | show_http_help [] |
| static struct ast_http_uri | staticuri |
| static struct ast_http_uri | statusuri |
| static struct ast_http_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 631 of file http.c.
References ahp, ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_log(), ast_strlen_zero(), ast_true(), ast_variable_browse(), DEFAULT_PREFIX, enabled, hp, http_server_start(), LOG_WARNING, MAX_PREFIX, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by ast_http_init(), and ast_http_reload().
00632 { 00633 struct ast_config *cfg; 00634 struct ast_variable *v; 00635 int enabled=0; 00636 int newenablestatic=0; 00637 struct sockaddr_in sin; 00638 struct hostent *hp; 00639 struct ast_hostent ahp; 00640 char newprefix[MAX_PREFIX]; 00641 00642 memset(&sin, 0, sizeof(sin)); 00643 sin.sin_port = htons(8088); 00644 00645 strcpy(newprefix, DEFAULT_PREFIX); 00646 00647 cfg = ast_config_load("http.conf"); 00648 if (cfg) { 00649 v = ast_variable_browse(cfg, "general"); 00650 while(v) { 00651 if (!strcasecmp(v->name, "enabled")) 00652 enabled = ast_true(v->value); 00653 else if (!strcasecmp(v->name, "enablestatic")) 00654 newenablestatic = ast_true(v->value); 00655 else if (!strcasecmp(v->name, "bindport")) 00656 sin.sin_port = ntohs(atoi(v->value)); 00657 else if (!strcasecmp(v->name, "bindaddr")) { 00658 if ((hp = ast_gethostbyname(v->value, &ahp))) { 00659 memcpy(&sin.sin_addr, hp->h_addr, sizeof(sin.sin_addr)); 00660 } else { 00661 ast_log(LOG_WARNING, "Invalid bind address '%s'\n", v->value); 00662 } 00663 } else if (!strcasecmp(v->name, "prefix")) { 00664 if (!ast_strlen_zero(v->value)) { 00665 newprefix[0] = '/'; 00666 ast_copy_string(newprefix + 1, v->value, sizeof(newprefix) - 1); 00667 } else { 00668 newprefix[0] = '\0'; 00669 } 00670 00671 } 00672 v = v->next; 00673 } 00674 ast_config_destroy(cfg); 00675 } 00676 if (enabled) 00677 sin.sin_family = AF_INET; 00678 if (strcmp(prefix, newprefix)) { 00679 ast_copy_string(prefix, newprefix, sizeof(prefix)); 00680 prefix_len = strlen(prefix); 00681 } 00682 enablestatic = newenablestatic; 00683 00684 http_server_start(&sin); 00685 00686 00687 return 0; 00688 }
| char* ast_http_error | ( | int | status, | |
| const char * | title, | |||
| const char * | extra_header, | |||
| const char * | text | |||
| ) |
Return a malloc()'d string containing an HTTP error message.
Definition at line 230 of file http.c.
References asprintf.
Referenced by ast_httpd_helper_thread(), handle_uri(), and static_callback().
00231 { 00232 char *c = NULL; 00233 asprintf(&c, 00234 "Content-type: text/html\r\n" 00235 "%s" 00236 "\r\n" 00237 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n" 00238 "<html><head>\r\n" 00239 "<title>%d %s</title>\r\n" 00240 "</head><body>\r\n" 00241 "<h1>%s</h1>\r\n" 00242 "<p>%s</p>\r\n" 00243 "<hr />\r\n" 00244 "<address>Asterisk Server</address>\r\n" 00245 "</body></html>\r\n", 00246 (extra_header ? extra_header : ""), status, title, title, text); 00247 return c; 00248 }
| int ast_http_init | ( | void | ) |
Definition at line 734 of file http.c.
References __ast_http_load(), ast_cli_register_multiple(), ast_http_uri_link(), cli_http, staticuri, and statusuri.
Referenced by main().
00735 { 00736 ast_http_uri_link(&statusuri); 00737 ast_http_uri_link(&staticuri); 00738 ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry)); 00739 00740 return __ast_http_load(0); 00741 }
| int ast_http_reload | ( | void | ) |
Definition at line 719 of file http.c.
References __ast_http_load().
00720 { 00721 return __ast_http_load(1); 00722 }
| char* ast_http_setcookie | ( | const char * | var, | |
| const char * | val, | |||
| int | expires, | |||
| char * | buf, | |||
| size_t | buflen | |||
| ) |
Definition at line 559 of file http.c.
References ast_build_string().
00560 { 00561 char *c; 00562 c = buf; 00563 ast_build_string(&c, &buflen, "Set-Cookie: %s=\"%s\"; Version=\"1\"", var, val); 00564 if (expires) 00565 ast_build_string(&c, &buflen, "; Max-Age=%d", expires); 00566 ast_build_string(&c, &buflen, "\r\n"); 00567 return buf; 00568 }
| int ast_http_uri_link | ( | struct ast_http_uri * | urih | ) |
Link into the Asterisk HTTP server.
Definition at line 250 of file http.c.
References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, ast_http_uri::uri, and uris.
Referenced by ast_http_init(), and init_manager().
00251 { 00252 struct ast_http_uri *prev; 00253 00254 ast_rwlock_wrlock(&uris_lock); 00255 prev = uris; 00256 if (!uris || strlen(uris->uri) <= strlen(urih->uri)) { 00257 urih->next = uris; 00258 uris = urih; 00259 } else { 00260 while (prev->next && (strlen(prev->next->uri) > strlen(urih->uri))) 00261 prev = prev->next; 00262 /* Insert it here */ 00263 urih->next = prev->next; 00264 prev->next = urih; 00265 } 00266 ast_rwlock_unlock(&uris_lock); 00267 00268 return 0; 00269 }
| void ast_http_uri_unlink | ( | struct ast_http_uri * | urih | ) |
Destroy an HTTP server.
Definition at line 271 of file http.c.
References ast_rwlock_unlock(), ast_rwlock_wrlock(), ast_http_uri::next, and uris.
Referenced by init_manager().
00272 { 00273 struct ast_http_uri *prev; 00274 00275 ast_rwlock_wrlock(&uris_lock); 00276 if (!uris) { 00277 ast_rwlock_unlock(&uris_lock); 00278 return; 00279 } 00280 prev = uris; 00281 if (uris == urih) { 00282 uris = uris->next; 00283 } 00284 while(prev->next) { 00285 if (prev->next == urih) { 00286 prev->next = urih->next; 00287 break; 00288 } 00289 prev = prev->next; 00290 } 00291 ast_rwlock_unlock(&uris_lock); 00292 }
| static void* ast_httpd_helper_thread | ( | void * | data | ) | [static] |
Definition at line 377 of file http.c.
References ast_cli(), ast_http_error(), ast_strlen_zero(), ast_variable_new(), ast_variables_destroy(), ast_http_server_instance::f, ast_http_server_instance::fd, free, handle_uri(), ast_http_server_instance::requestor, t, and var.
Referenced by http_root().
00378 { 00379 char buf[4096]; 00380 char cookie[4096]; 00381 char timebuf[256]; 00382 struct ast_http_server_instance *ser = data; 00383 struct ast_variable *var, *prev=NULL, *vars=NULL; 00384 char *uri, *c, *title=NULL; 00385 char *vname, *vval; 00386 int status = 200, contentlength = 0; 00387 time_t t; 00388 00389 if (fgets(buf, sizeof(buf), ser->f)) { 00390 /* Skip method */ 00391 uri = buf; 00392 while(*uri && (*uri > 32)) 00393 uri++; 00394 if (*uri) { 00395 *uri = '\0'; 00396 uri++; 00397 } 00398 00399 /* Skip white space */ 00400 while (*uri && (*uri < 33)) 00401 uri++; 00402 00403 if (*uri) { 00404 c = uri; 00405 while (*c && (*c > 32)) 00406 c++; 00407 if (*c) { 00408 *c = '\0'; 00409 } 00410 } 00411 00412 while (fgets(cookie, sizeof(cookie), ser->f)) { 00413 /* Trim trailing characters */ 00414 while(!ast_strlen_zero(cookie) && (cookie[strlen(cookie) - 1] < 33)) { 00415 cookie[strlen(cookie) - 1] = '\0'; 00416 } 00417 if (ast_strlen_zero(cookie)) 00418 break; 00419 if (!strncasecmp(cookie, "Cookie: ", 8)) { 00420 00421 /* TODO - The cookie parsing code below seems to work 00422 in IE6 and FireFox 1.5. However, it is not entirely 00423 correct, and therefore may not work in all 00424 circumstances. 00425 For more details see RFC 2109 and RFC 2965 */ 00426 00427 /* FireFox cookie strings look like: 00428 Cookie: mansession_id="********" 00429 InternetExplorer's look like: 00430 Cookie: $Version="1"; mansession_id="********" */ 00431 00432 /* If we got a FireFox cookie string, the name's right 00433 after "Cookie: " */ 00434 vname = cookie + 8; 00435 00436 /* If we got an IE cookie string, we need to skip to 00437 past the version to get to the name */ 00438 if (*vname == '$') { 00439 vname = strchr(vname, ';'); 00440 if (vname) { 00441 vname++; 00442 if (*vname == ' ') 00443 vname++; 00444 } 00445 } 00446 00447 if (vname) { 00448 vval = strchr(vname, '='); 00449 if (vval) { 00450 /* Ditch the = and the quotes */ 00451 *vval++ = '\0'; 00452 if (*vval) 00453 vval++; 00454 if (strlen(vval)) 00455 vval[strlen(vval) - 1] = '\0'; 00456 var = ast_variable_new(vname, vval); 00457 if (var) { 00458 if (prev) 00459 prev->next = var; 00460 else 00461 vars = var; 00462 prev = var; 00463 } 00464 } 00465 } 00466 } 00467 } 00468 00469 if (*uri) { 00470 if (!strcasecmp(buf, "get")) 00471 c = handle_uri(&ser->requestor, uri, &status, &title, &contentlength, &vars); 00472 else 00473 c = ast_http_error(501, "Not Implemented", NULL, "Attempt to use unimplemented / unsupported method");\ 00474 } else 00475 c = ast_http_error(400, "Bad Request", NULL, "Invalid Request"); 00476 00477 /* If they aren't mopped up already, clean up the cookies */ 00478 if (vars) 00479 ast_variables_destroy(vars); 00480 00481 if (!c) 00482 c = ast_http_error(500, "Internal Error", NULL, "Internal Server Error"); 00483 if (c) { 00484 time(&t); 00485 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&t)); 00486 ast_cli(ser->fd, "HTTP/1.1 %d %s\r\n", status, title ? title : "OK"); 00487 ast_cli(ser->fd, "Server: Asterisk/%s\r\n", ASTERISK_VERSION); 00488 ast_cli(ser->fd, "Date: %s\r\n", timebuf); 00489 ast_cli(ser->fd, "Connection: close\r\n"); 00490 if (contentlength) { 00491 char *tmp; 00492 tmp = strstr(c, "\r\n\r\n"); 00493 if (tmp) { 00494 ast_cli(ser->fd, "Content-length: %d\r\n", contentlength); 00495 write(ser->fd, c, (tmp + 4 - c)); 00496 write(ser->fd, tmp + 4, contentlength); 00497 } 00498 } else 00499 ast_cli(ser->fd, "%s", c); 00500 free(c); 00501 } 00502 if (title) 00503 free(title); 00504 } 00505 fclose(ser->f); 00506 free(ser); 00507 return NULL; 00508 }
| AST_RWLOCK_DEFINE_STATIC | ( | uris_lock | ) |
| static const char* ftype2mtype | ( | const char * | ftype, | |
| char * | wkspace, | |||
| int | wkspacelen | |||
| ) | [static] |
Definition at line 95 of file http.c.
References ext, mimetypes, and mtype.
Referenced by static_callback().
00096 { 00097 int x; 00098 if (ftype) { 00099 for (x=0;x<sizeof(mimetypes) / sizeof(mimetypes[0]); x++) { 00100 if (!strcasecmp(ftype, mimetypes[x].ext)) 00101 return mimetypes[x].mtype; 00102 } 00103 } 00104 snprintf(wkspace, wkspacelen, "text/%s", ftype ? ftype : "plain"); 00105 return wkspace; 00106 }
| static int handle_show_http | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 690 of file http.c.
References ast_cli(), ast_inet_ntoa(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_http_uri::description, ast_http_uri::has_subtree, ast_http_uri::next, RESULT_SHOWUSAGE, RESULT_SUCCESS, ast_http_uri::uri, and uris.
00691 { 00692 struct ast_http_uri *urih; 00693 00694 if (argc != 3) 00695 return RESULT_SHOWUSAGE; 00696 00697 ast_cli(fd, "HTTP Server Status:\n"); 00698 ast_cli(fd, "Prefix: %s\n", prefix); 00699 if (oldsin.sin_family) 00700 ast_cli(fd, "Server Enabled and Bound to %s:%d\n\n", 00701 ast_inet_ntoa(oldsin.sin_addr), 00702 ntohs(oldsin.sin_port)); 00703 else 00704 ast_cli(fd, "Server Disabled\n\n"); 00705 ast_cli(fd, "Enabled URI's:\n"); 00706 ast_rwlock_rdlock(&uris_lock); 00707 urih = uris; 00708 while(urih){ 00709 ast_cli(fd, "%s/%s%s => %s\n", prefix, urih->uri, (urih->has_subtree ? "/..." : "" ), urih->description); 00710 urih = urih->next; 00711 } 00712 if (!uris) 00713 ast_cli(fd, "None.\n"); 00714 ast_rwlock_unlock(&uris_lock); 00715 00716 return RESULT_SUCCESS; 00717 }
| static char* handle_uri | ( | struct sockaddr_in * | sin, | |
| char * | uri, | |||
| int * | status, | |||
| char ** | title, | |||
| int * | contentlength, | |||
| struct ast_variable ** | cookies | |||
| ) | [static] |
Definition at line 294 of file http.c.
References ast_http_error(), ast_rwlock_rdlock(), ast_rwlock_unlock(), ast_strlen_zero(), ast_uri_decode(), ast_variable_new(), ast_variables_destroy(), ast_http_uri::callback, ast_http_uri::has_subtree, len, ast_http_uri::next, strdup, strsep(), ast_http_uri::uri, uris, and var.
Referenced by ast_httpd_helper_thread().
00295 { 00296 char *c; 00297 char *turi; 00298 char *params; 00299 char *var; 00300 char *val; 00301 struct ast_http_uri *urih=NULL; 00302 int len; 00303 struct ast_variable *vars=NULL, *v, *prev = NULL; 00304 00305 00306 params = strchr(uri, '?'); 00307 if (params) { 00308 *params = '\0'; 00309 params++; 00310 while ((var = strsep(¶ms, "&"))) { 00311 val = strchr(var, '='); 00312 if (val) { 00313 *val = '\0'; 00314 val++; 00315 ast_uri_decode(val); 00316 } else 00317 val = ""; 00318 ast_uri_decode(var); 00319 if ((v = ast_variable_new(var, val))) { 00320 if (vars) 00321 prev->next = v; 00322 else 00323 vars = v; 00324 prev = v; 00325 } 00326 } 00327 } 00328 if (prev) 00329 prev->next = *cookies; 00330 else 00331 vars = *cookies; 00332 *cookies = NULL; 00333 ast_uri_decode(uri); 00334 if (!strncasecmp(uri, prefix, prefix_len)) { 00335 uri += prefix_len; 00336 if (!*uri || (*uri == '/')) { 00337 if (*uri == '/') 00338 uri++; 00339 ast_rwlock_rdlock(&uris_lock); 00340 urih = uris; 00341 while(urih) { 00342 len = strlen(urih->uri); 00343 if (!strncasecmp(urih->uri, uri, len)) { 00344 if (!uri[len] || uri[len] == '/') { 00345 turi = uri + len; 00346 if (*turi == '/') 00347 turi++; 00348 if (!*turi || urih->has_subtree) { 00349 uri = turi; 00350 break; 00351 } 00352 } 00353 } 00354 urih = urih->next; 00355 } 00356 if (!urih) 00357 ast_rwlock_unlock(&uris_lock); 00358 } 00359 } 00360 if (urih) { 00361 c = urih->callback(sin, uri, vars, status, title, contentlength); 00362 ast_rwlock_unlock(&uris_lock); 00363 } else if (ast_strlen_zero(uri) && ast_strlen_zero(prefix)) { 00364 /* Special case: If no prefix, and no URI, send to /static/index.html */ 00365 c = ast_http_error(302, "Moved Temporarily", "Location: /static/index.html\r\n", "This is not the page you are looking for..."); 00366 *status = 302; 00367 *title = strdup("Moved Temporarily"); 00368 } else { 00369 c = ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server."); 00370 *status = 404; 00371 *title = strdup("Not Found"); 00372 } 00373 ast_variables_destroy(vars); 00374 return c; 00375 }
| static void* http_root | ( | void * | data | ) | [static] |
Definition at line 510 of file http.c.
References ast_calloc, ast_httpd_helper_thread(), ast_log(), ast_pthread_create_background, ast_wait_for_input(), free, and LOG_WARNING.
Referenced by http_server_start().
00511 { 00512 int fd; 00513 struct sockaddr_in sin; 00514 socklen_t sinlen; 00515 struct ast_http_server_instance *ser; 00516 pthread_t launched; 00517 pthread_attr_t attr; 00518 00519 for (;;) { 00520 int flags; 00521 00522 ast_wait_for_input(httpfd, -1); 00523 sinlen = sizeof(sin); 00524 fd = accept(httpfd, (struct sockaddr *)&sin, &sinlen); 00525 if (fd < 0) { 00526 if ((errno != EAGAIN) && (errno != EINTR)) 00527 ast_log(LOG_WARNING, "Accept failed: %s\n", strerror(errno)); 00528 continue; 00529 } 00530 ser = ast_calloc(1, sizeof(*ser)); 00531 if (!ser) { 00532 ast_log(LOG_WARNING, "No memory for new session: %s\n", strerror(errno)); 00533 close(fd); 00534 continue; 00535 } 00536 flags = fcntl(fd, F_GETFL); 00537 fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 00538 ser->fd = fd; 00539 memcpy(&ser->requestor, &sin, sizeof(ser->requestor)); 00540 if ((ser->f = fdopen(ser->fd, "w+"))) { 00541 pthread_attr_init(&attr); 00542 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00543 00544 if (ast_pthread_create_background(&launched, &attr, ast_httpd_helper_thread, ser)) { 00545 ast_log(LOG_WARNING, "Unable to launch helper thread: %s\n", strerror(errno)); 00546 fclose(ser->f); 00547 free(ser); 00548 } 00549 pthread_attr_destroy(&attr); 00550 } else { 00551 ast_log(LOG_WARNING, "fdopen failed!\n"); 00552 close(ser->fd); 00553 free(ser); 00554 } 00555 } 00556 return NULL; 00557 }
| static void http_server_start | ( | struct sockaddr_in * | sin | ) | [static] |
Definition at line 571 of file http.c.
References ast_inet_ntoa(), ast_log(), ast_pthread_create_background, AST_PTHREADT_NULL, http_root(), LOG_DEBUG, LOG_NOTICE, and LOG_WARNING.
Referenced by __ast_http_load().
00572 { 00573 int flags; 00574 int x = 1; 00575 00576 /* Do nothing if nothing has changed */ 00577 if (!memcmp(&oldsin, sin, sizeof(oldsin))) { 00578 ast_log(LOG_DEBUG, "Nothing changed in http\n"); 00579 return; 00580 } 00581 00582 memcpy(&oldsin, sin, sizeof(oldsin)); 00583 00584 /* Shutdown a running server if there is one */ 00585 if (master != AST_PTHREADT_NULL) { 00586 pthread_cancel(master); 00587 pthread_kill(master, SIGURG); 00588 pthread_join(master, NULL); 00589 } 00590 00591 if (httpfd != -1) 00592 close(httpfd); 00593 00594 /* If there's no new server, stop here */ 00595 if (!sin->sin_family) 00596 return; 00597 00598 00599 httpfd = socket(AF_INET, SOCK_STREAM, 0); 00600 if (httpfd < 0) { 00601 ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno)); 00602 return; 00603 } 00604 00605 setsockopt(httpfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 00606 if (bind(httpfd, (struct sockaddr *)sin, sizeof(*sin))) { 00607 ast_log(LOG_NOTICE, "Unable to bind http server to %s:%d: %s\n", 00608 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00609 strerror(errno)); 00610 close(httpfd); 00611 httpfd = -1; 00612 return; 00613 } 00614 if (listen(httpfd, 10)) { 00615 ast_log(LOG_NOTICE, "Unable to listen!\n"); 00616 close(httpfd); 00617 httpfd = -1; 00618 return; 00619 } 00620 flags = fcntl(httpfd, F_GETFL); 00621 fcntl(httpfd, F_SETFL, flags | O_NONBLOCK); 00622 if (ast_pthread_create_background(&master, NULL, http_root, NULL)) { 00623 ast_log(LOG_NOTICE, "Unable to launch http server on %s:%d: %s\n", 00624 ast_inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), 00625 strerror(errno)); 00626 close(httpfd); 00627 httpfd = -1; 00628 } 00629 }
| static char* httpstatus_callback | ( | struct sockaddr_in * | req, | |
| const char * | uri, | |||
| struct ast_variable * | vars, | |||
| int * | status, | |||
| char ** | title, | |||
| int * | contentlength | |||
| ) | [static] |
Definition at line 179 of file http.c.
References ast_build_string(), ast_inet_ntoa(), ast_variable::name, ast_variable::next, result, strdup, and ast_variable::value.
00180 { 00181 char result[4096]; 00182 size_t reslen = sizeof(result); 00183 char *c=result; 00184 struct ast_variable *v; 00185 00186 ast_build_string(&c, &reslen, 00187 "\r\n" 00188 "<title>Asterisk HTTP Status</title>\r\n" 00189 "<body bgcolor=\"#ffffff\">\r\n" 00190 "<table bgcolor=\"#f1f1f1\" align=\"center\"><tr><td bgcolor=\"#e0e0ff\" colspan=\"2\" width=\"500\">\r\n" 00191 "<h2> 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 728 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(), bridge_p2p_rtp_write(), console_transfer(), console_transfer_deprecated(), do_directory(), exts_compare(), ftype2mtype(), iax_park_thread(), misdn_call(), misdn_request(), mixmonitor_thread(), moh_scan_files(), oh323_request(), pbx_load_config(), record_exec(), register_peer_exten(), sip_park_thread(), and sip_request_call().
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(), exec_clearhash(), handle_verbose(), hashkeys_read(), 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().
1.5.1