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: 314607 $")
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 #include <signal.h>
00051
00052 #include "asterisk/cli.h"
00053 #include "asterisk/http.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/strings.h"
00056 #include "asterisk/options.h"
00057 #include "asterisk/config.h"
00058 #include "asterisk/version.h"
00059 #include "asterisk/manager.h"
00060
00061 #define MAX_PREFIX 80
00062 #define DEFAULT_PREFIX "/asterisk"
00063 #define DEFAULT_SESSION_LIMIT 100
00064
00065 struct ast_http_server_instance {
00066 FILE *f;
00067 int fd;
00068 struct sockaddr_in requestor;
00069 ast_http_callback callback;
00070 };
00071
00072 AST_RWLOCK_DEFINE_STATIC(uris_lock);
00073 static struct ast_http_uri *uris;
00074
00075 static int httpfd = -1;
00076 static pthread_t master = AST_PTHREADT_NULL;
00077 static char prefix[MAX_PREFIX];
00078 static int prefix_len;
00079 static struct sockaddr_in oldsin;
00080 static int enablestatic;
00081 static int session_limit = DEFAULT_SESSION_LIMIT;
00082 static int session_count = 0;
00083
00084
00085 static struct {
00086 const char *ext;
00087 const char *mtype;
00088 } mimetypes[] = {
00089 { "png", "image/png" },
00090 { "jpg", "image/jpeg" },
00091 { "js", "application/x-javascript" },
00092 { "wav", "audio/x-wav" },
00093 { "mp3", "audio/mpeg" },
00094 { "svg", "image/svg+xml" },
00095 { "svgz", "image/svg+xml" },
00096 { "gif", "image/gif" },
00097 };
00098
00099 static const char *ftype2mtype(const char *ftype, char *wkspace, int wkspacelen)
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 }
00111
00112 static char *static_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
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
00126
00127 if (!enablestatic || ast_strlen_zero(uri))
00128 goto out403;
00129
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
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 }
00181
00182
00183 static char *httpstatus_callback(struct sockaddr_in *req, const char *uri, struct ast_variable *vars, int *status, char **title, int *contentlength)
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 }
00219
00220 static struct ast_http_uri statusuri = {
00221 .callback = httpstatus_callback,
00222 .description = "Asterisk HTTP General Status",
00223 .uri = "httpstatus",
00224 .has_subtree = 0,
00225 };
00226
00227 static struct ast_http_uri staticuri = {
00228 .callback = static_callback,
00229 .description = "Asterisk HTTP Static Delivery",
00230 .uri = "static",
00231 .has_subtree = 1,
00232 .static_content = 1,
00233 };
00234
00235 char *ast_http_error(int status, const char *title, const char *extra_header, const char *text)
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 }
00257
00258 int ast_http_uri_link(struct ast_http_uri *urih)
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
00271 urih->next = prev->next;
00272 prev->next = urih;
00273 }
00274 ast_rwlock_unlock(&uris_lock);
00275
00276 return 0;
00277 }
00278
00279 void ast_http_uri_unlink(struct ast_http_uri *urih)
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 }
00301
00302 static char *handle_uri(struct sockaddr_in *sin, char *uri, int *status,
00303 char **title, int *contentlength, struct ast_variable **cookies,
00304 unsigned int *static_content)
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
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 }
00388
00389 static struct ast_variable *parse_cookies(char *cookies)
00390 {
00391 char *cur;
00392 struct ast_variable *vars = NULL, *var;
00393
00394
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 }
00425
00426 static void *ast_httpd_helper_thread(void *data)
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
00440 uri = buf;
00441 while(*uri && (*uri > 32))
00442 uri++;
00443 if (*uri) {
00444 *uri = '\0';
00445 uri++;
00446 }
00447
00448
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
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
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
00497
00498
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 }
00525
00526 static void *http_root(void *data)
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 }
00584
00585 char *ast_http_setcookie(const char *var, const char *val, int expires, char *buf, size_t buflen)
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 }
00595
00596
00597 static void http_server_start(struct sockaddr_in *sin)
00598 {
00599 int flags;
00600 int x = 1;
00601
00602
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
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
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 }
00656
00657 static int __ast_http_load(int 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 }
00724
00725 static int handle_show_http(int fd, int argc, char *argv[])
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 }
00753
00754 int ast_http_reload(void)
00755 {
00756 return __ast_http_load(1);
00757 }
00758
00759 static char show_http_help[] =
00760 "Usage: http show status\n"
00761 " Lists status of internal HTTP engine\n";
00762
00763 static struct ast_cli_entry cli_http[] = {
00764 { { "http", "show", "status", NULL },
00765 handle_show_http, "Display HTTP server status",
00766 show_http_help },
00767 };
00768
00769 int ast_http_init(void)
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 }