00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 114600 $")
00034
00035 #include <sys/types.h>
00036 #include <stdio.h>
00037 #include <unistd.h>
00038 #include <stdlib.h>
00039 #include <time.h>
00040 #include <string.h>
00041 #include <netinet/in.h>
00042 #include <sys/time.h>
00043 #include <sys/socket.h>
00044 #include <sys/stat.h>
00045 #include <sys/signal.h>
00046 #include <arpa/inet.h>
00047 #include <errno.h>
00048 #include <fcntl.h>
00049 #include <pthread.h>
00050
00051 #include "asterisk/cli.h"
00052 #include "asterisk/http.h"
00053 #include "asterisk/utils.h"
00054 #include "asterisk/strings.h"
00055 #include "asterisk/options.h"
00056 #include "asterisk/config.h"
00057 #include "asterisk/version.h"
00058 #include "asterisk/manager.h"
00059
00060 #define MAX_PREFIX 80
00061 #define DEFAULT_PREFIX "/asterisk"
00062 #define DEFAULT_SESSION_LIMIT 100
00063
00064 struct ast_http_server_instance {
00065 FILE *f;
00066 int fd;
00067 struct sockaddr_in requestor;
00068 ast_http_callback callback;
00069 };
00070
00071 AST_RWLOCK_DEFINE_STATIC(uris_lock);
00072 static struct ast_http_uri *uris;
00073
00074 static int httpfd = -1;
00075 static pthread_t master = AST_PTHREADT_NULL;
00076 static char prefix[MAX_PREFIX];
00077 static int prefix_len;
00078 static struct sockaddr_in oldsin;
00079 static int enablestatic;
00080 static int session_limit = DEFAULT_SESSION_LIMIT;
00081 static int session_count = 0;
00082
00083
00084 static struct {
00085 const char *ext;
00086 const char *mtype;
00087 } mimetypes[] = {
00088 { "png", "image/png" },
00089 { "jpg", "image/jpeg" },
00090 { "js", "application/x-javascript" },
00091 { "wav", "audio/x-wav" },
00092 { "mp3", "audio/mpeg" },
00093 { "svg", "image/svg+xml" },
00094 { "svgz", "image/svg+xml" },
00095 { "gif", "image/gif" },
00096 };
00097
00098 static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
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 }
00110
00111 static char *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
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
00125
00126 if (!enablestatic || ast_strlen_zero(uri))
00127 goto out403;
00128
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
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 }
00180
00181
00182 static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
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 }
00218
00219 static struct ast_http_uri statusuri = {
00220 .callback = httpstatus_callback,
00221 .description = "Asterisk HTTP General Status",
00222 .uri = "httpstatus",
00223 .has_subtree = 0,
00224 };
00225
00226 static struct ast_http_uri staticuri = {
00227 .callback = static_callback,
00228 .description = "Asterisk HTTP Static Delivery",
00229 .uri = "static",
00230 .has_subtree = 1,
00231 .static_content = 1,
00232 };
00233
00234 char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
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 }
00253
00254 int ast_http_uri_link(struct ast_http_uri *urih)
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
00267 urih->next = prev->next;
00268 prev->next = urih;
00269 }
00270 ast_rwlock_unlock(&uris_lock);
00271
00272 return 0;
00273 }
00274
00275 void ast_http_uri_unlink(struct ast_http_uri *urih)
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 }
00297
00298 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status,
00299 char **title, int *contentlength, struct ast_variable **cookies,
00300 unsigned int *static_content)
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
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 }
00384
00385 static struct ast_variable *parse_cookies(char *cookies)
00386 {
00387 char *cur;
00388 struct ast_variable *vars = NULL, *var;
00389
00390
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 }
00421
00422 static void *ast_httpd_helper_thread(void *data)
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
00436 uri = buf;
00437 while(*uri && (*uri > 32))
00438 uri++;
00439 if (*uri) {
00440 *uri = '\0';
00441 uri++;
00442 }
00443
00444
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
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
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
00493
00494
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 }
00517
00518 static void *http_root(void *data)
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 }
00576
00577 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
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 }
00587
00588
00589 static void http_server_start(struct sockaddr_in *sin)
00590 {
00591 int flags;
00592 int x = 1;
00593
00594
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
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
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 }
00648
00649 static int __ast_http_load(int 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 }
00716
00717 static int handle_show_http(int fd, int argc, char *argv[])
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 }
00745
00746 int ast_http_reload(void)
00747 {
00748 return __ast_http_load(1);
00749 }
00750
00751 static char show_http_help[] =
00752 "Usage: http show status\n"
00753 " Lists status of internal HTTP engine\n";
00754
00755 static struct ast_cli_entry cli_http[] = {
00756 { { "http", "show", "status", NULL },
00757 handle_show_http, "Display HTTP server status",
00758 show_http_help },
00759 };
00760
00761 int ast_http_init(void)
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 }