00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "klone_conf.h"
00012 #include <sys/types.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015 #ifdef HAVE_LIBOPENSSL
00016 #include <openssl/ssl.h>
00017 #include <openssl/err.h>
00018 #endif
00019 #include <u/libu.h>
00020 #include <klone/utils.h>
00021 #include <klone/os.h>
00022 #include <klone/server.h>
00023 #include <klone/context.h>
00024 #include <klone/broker.h>
00025 #include <klone/request.h>
00026 #include <klone/ses_prv.h>
00027 #include <klone/response.h>
00028 #include <klone/backend.h>
00029 #include <klone/io.h>
00030 #include <klone/timer.h>
00031 #include <klone/tls.h>
00032 #include <klone/ses_prv.h>
00033 #include <klone/hook.h>
00034 #include <klone/hookprv.h>
00035 #include <klone/access.h>
00036 #include <klone/vhost.h>
00037 #include "http_s.h"
00038
00039 struct http_status_map_s
00040 {
00041 int status;
00042 const char *desc;
00043 } http_status_map[] = {
00044 { HTTP_STATUS_OK , "OK" },
00045 { HTTP_STATUS_NOT_MODIFIED , "Not Modified" },
00046 { HTTP_STATUS_NOT_FOUND , "Not Found" },
00047 { HTTP_STATUS_INTERNAL_SERVER_ERROR , "Internal Server Error" },
00048 { HTTP_STATUS_MOVED_PERMANENTLY , "Moved Permanently" },
00049 { HTTP_STATUS_MOVED_TEMPORARILY , "Moved Temporarily" },
00050 { HTTP_STATUS_CREATED , "Created" },
00051 { HTTP_STATUS_ACCEPTED , "Accepted" },
00052 { HTTP_STATUS_NO_CONTENT , "No Content" },
00053 { HTTP_STATUS_BAD_REQUEST , "Bad Request" },
00054 { HTTP_STATUS_UNAUTHORIZED , "Unauthorized" },
00055 { HTTP_STATUS_FORBIDDEN , "Forbidden" },
00056 { HTTP_STATUS_LENGTH_REQUIRED , "Content-Length required" },
00057 { HTTP_STATUS_REQUEST_TOO_LARGE , "Request data too big" },
00058 { HTTP_STATUS_NOT_IMPLEMENTED , "Not Implemented" },
00059 { HTTP_STATUS_BAD_GATEWAY , "Bad Gateway" },
00060 { HTTP_STATUS_SERVICE_UNAVAILABLE , "Service Unavailable" },
00061 { 0 , NULL }
00062 };
00063
00064 enum { URI_MAX = 2048 };
00065
00066
00067 int cgi_set_request(request_t *rq);
00068
00069 session_opt_t *http_get_session_opt(http_t *http)
00070 {
00071 dbg_return_if (http == NULL, NULL);
00072
00073 return http->sess_opt;
00074 }
00075
00076 u_config_t *http_get_config(http_t* http)
00077 {
00078 dbg_return_if (http == NULL, NULL);
00079
00080 return http->config;
00081 }
00082
00083 const char *http_get_status_desc(int status)
00084 {
00085 struct http_status_map_s *map = http_status_map;
00086 const char *msg = "Unknown Status Code";
00087
00088 for( ; map->status; ++map)
00089 if(map->status == status)
00090 {
00091 msg = map->desc;
00092 break;
00093 }
00094
00095 return msg;
00096 }
00097
00098 static int http_try_resolv(const char *alias, char *dst, const char *uri,
00099 size_t sz)
00100 {
00101 static const char *WP = " \t";
00102 char *src, *res, *pp = NULL;
00103 char v[1024];
00104
00105 dbg_err_if(dst == NULL);
00106 dbg_err_if(uri == NULL);
00107 dbg_err_if(alias == NULL);
00108
00109
00110 dbg_err_if(strlcpy(v, alias, sizeof(v)) >= sizeof(v));
00111
00112
00113 src = strtok_r(v, WP, &pp);
00114 dbg_err_if(src == NULL);
00115
00116
00117 nop_err_if(strncmp(src, uri, strlen(src)));
00118
00119
00120 if(src[strlen(src)-1] != '/')
00121 nop_err_if(uri[strlen(src)] != '/');
00122
00123
00124 res = strtok_r(NULL, WP, &pp);
00125 dbg_err_if(res == NULL);
00126
00127
00128 dbg_err_if(u_path_snprintf(dst, sz, '/', "%s/%s", res, uri + strlen(src)));
00129
00130 return 0;
00131 err:
00132 return ~0;
00133 }
00134
00135 vhost_list_t* http_get_vhost_list(http_t *http)
00136 {
00137 dbg_err_if(http == NULL);
00138
00139 return http->vhosts;
00140 err:
00141 return NULL;
00142 }
00143
00144 vhost_t* http_get_vhost(http_t *h, request_t *rq)
00145 {
00146 const char *host;
00147 char *p, hostcp[128];
00148 vhost_t *vh = NULL;
00149
00150 dbg_err_if (h == NULL);
00151 dbg_err_if (rq == NULL);
00152
00153 if((vh = request_get_vhost(rq)) != NULL)
00154 return vh;
00155
00156 if((host = request_get_field_value(rq, "Host")) != NULL)
00157 {
00158 dbg_err_if(strlcpy(hostcp, host, sizeof(hostcp)) >= sizeof(hostcp));
00159
00160
00161 if((p = strrchr(hostcp, ':')) != NULL)
00162 *p = 0;
00163
00164 vh = vhost_list_get(h->vhosts, hostcp);
00165 }
00166
00167 if(vh == NULL)
00168 {
00169
00170 vh = vhost_list_get_n(h->vhosts, 0);
00171 dbg_err_if(vh == NULL);
00172 }
00173
00174 return vh;
00175 err:
00176 return NULL;
00177 }
00178
00179 int http_alias_resolv(http_t *h, request_t *rq, char *dst, const char *uri,
00180 size_t sz)
00181 {
00182 u_config_t *config, *cgi;
00183 vhost_t *vhost;
00184 int i;
00185
00186 dbg_err_if (h == NULL);
00187 dbg_err_if (dst == NULL);
00188 dbg_err_if (uri == NULL);
00189
00190 dbg_err_if((vhost = http_get_vhost(h, rq)) == NULL);
00191
00192
00193 for(i = 0; !u_config_get_subkey_nth(vhost->config,"dir_alias", i, &config);
00194 ++i)
00195 {
00196 if(!http_try_resolv(u_config_get_value(config), dst, uri, sz))
00197 return 0;
00198 }
00199
00200
00201 if(!u_config_get_subkey(vhost->config, "cgi", &cgi))
00202 {
00203 for(i = 0; !u_config_get_subkey_nth(cgi, "script_alias", i, &config);
00204 ++i)
00205 {
00206 if(!http_try_resolv(u_config_get_value(config), dst, uri, sz))
00207 return 0;
00208 }
00209 }
00210
00211
00212 dbg_err_if(u_path_snprintf(dst, sz, '/', "%s/%s", vhost->dir_root, uri));
00213
00214 return 0;
00215 err:
00216 return ~0;
00217 }
00218
00219 static int http_is_valid_uri(request_t *rq, const char *buf, size_t len)
00220 {
00221 char resolved[U_FILENAME_MAX], uri[URI_MAX];
00222 http_t *h = NULL;
00223
00224 dbg_err_if (rq == NULL);
00225 dbg_err_if (buf == NULL);
00226
00227 dbg_err_if (len >= URI_MAX);
00228
00229 h = request_get_http(rq);
00230 dbg_err_if (h == NULL);
00231
00232 strncpy(uri, buf, len);
00233 uri[len] = 0;
00234
00235 dbg_err_if(http_alias_resolv(h, rq, resolved, uri, U_FILENAME_MAX));
00236
00237 return broker_is_valid_uri(h->broker, h, rq, resolved, strlen(resolved));
00238 err:
00239 return 0;
00240 }
00241
00242 static int http_resolv_request(http_t *h, request_t *rq)
00243 {
00244 const char *cstr;
00245 char resolved[U_FILENAME_MAX];
00246
00247 dbg_err_if(h == NULL);
00248 dbg_err_if(rq == NULL);
00249
00250
00251 if((cstr = request_get_filename(rq)) != NULL)
00252 {
00253 dbg_err_if(http_alias_resolv(h, rq, resolved, cstr, U_FILENAME_MAX));
00254
00255 dbg_err_if(request_set_resolved_filename(rq, resolved));
00256 }
00257
00258
00259 if((cstr = request_get_path_info(rq)) != NULL)
00260 {
00261 dbg_err_if(http_alias_resolv(h, rq, resolved, cstr, U_FILENAME_MAX));
00262
00263 dbg_err_if(request_set_resolved_path_info(rq, resolved));
00264 }
00265
00266 return 0;
00267 err:
00268 return ~0;
00269 }
00270
00271 static int http_is_valid_index(http_t *h, request_t *rq, const char *uri)
00272 {
00273 char resolved[U_FILENAME_MAX] = { 0 };
00274
00275 dbg_err_if(u_path_snprintf(resolved, U_FILENAME_MAX, '/', "%s/%s",
00276 request_get_resolved_filename(rq), uri));
00277
00278 if(broker_is_valid_uri(h->broker, h, rq, resolved, strlen(resolved)))
00279 return 1;
00280
00281 err:
00282 return 0;
00283 }
00284
00285 static int http_get_config_index(http_t *h, request_t *rq, char *idx, size_t sz)
00286 {
00287 vhost_t *vhost;
00288 char buf[256], *tok, *src, *pp = NULL;
00289 const char *cindex = NULL;
00290
00291 dbg_err_if (h == NULL);
00292 dbg_err_if (rq == NULL);
00293
00294 dbg_err_if((vhost = http_get_vhost(h, rq)) == NULL);
00295
00296 if((cindex = u_config_get_subkey_value(vhost->config, "index")) == NULL)
00297 return ~0;
00298
00299
00300 dbg_err_if(strlcpy(buf, cindex, sizeof(buf)) >= sizeof(buf));
00301
00302 for(src = buf; (tok = strtok_r(src, " \t", &pp)) != NULL; src = NULL)
00303 {
00304 if(!strcmp(tok, ""))
00305 continue;
00306
00307 if(http_is_valid_index(h, rq, tok))
00308 {
00309 dbg_err_if(strlcpy(idx, tok, sz) >= sz);
00310 return 0;
00311 }
00312 }
00313
00314
00315 err:
00316 return ~0;
00317 }
00318
00319 static int http_get_default_index(http_t *h, request_t *rq, char *cindex,
00320 size_t sz)
00321 {
00322 static const char *indexes[] = { "/index.klone", "/index.kl1",
00323 "/index.html", "/index.htm", NULL };
00324 const char **pg;
00325
00326 dbg_err_if (h == NULL);
00327 dbg_err_if (rq == NULL);
00328
00329
00330 for(pg = indexes; *pg; ++pg)
00331 {
00332 if(http_is_valid_index(h, rq, *pg))
00333 {
00334 dbg_err_if(strlcpy(cindex, *pg, sz) >= sz);
00335 return 0;
00336 }
00337 }
00338
00339
00340 err:
00341 return ~0;
00342 }
00343
00344 static int http_set_index_request(http_t *h, request_t *rq)
00345 {
00346 char idx[128], uri[1024];
00347
00348 dbg_err_if (h == NULL);
00349 dbg_err_if (rq == NULL);
00350
00351
00352 nop_err_if(http_get_config_index(h, rq, idx, sizeof(idx)) &&
00353 http_get_default_index(h, rq, idx, sizeof(idx)));
00354
00355 dbg_err_if(u_snprintf(uri, sizeof(uri), "%s%s",
00356 request_get_filename(rq), idx));
00357
00358 dbg_if(request_set_filename(rq, uri));
00359
00360 dbg_err_if(http_resolv_request(h, rq));
00361
00362 return 0;
00363 err:
00364 return ~0;
00365 }
00366
00367 static int http_add_default_header(http_t *h, request_t *rq, response_t *rs)
00368 {
00369 vhost_t *vhost;
00370 time_t now;
00371
00372 dbg_err_if (h == NULL);
00373 dbg_err_if (rs == NULL);
00374
00375 dbg_err_if((vhost = http_get_vhost(h, rq)) == NULL);
00376
00377
00378 dbg_err_if(response_set_field(rs, "Server", vhost->server_sig));
00379
00380 now = time(NULL);
00381 dbg_err_if(response_set_date(rs, now));
00382
00383 return 0;
00384 err:
00385 return ~0;
00386 }
00387
00388 static int http_print_error_page(http_t *h, request_t *rq, response_t *rs,
00389 int http_status)
00390 {
00391 enum { BUFSZ = 64 };
00392 const char *err_page;
00393 char buf[BUFSZ];
00394 vhost_t *vhost;
00395
00396 dbg_err_if (h == NULL);
00397 dbg_err_if (rq == NULL);
00398 dbg_err_if (rs == NULL);
00399 dbg_err_if (http_status == 0);
00400
00401
00402 if(http_status != 302)
00403 dbg_err_if(header_clear(response_get_header(rs)));
00404
00405
00406 dbg_err_if(http_add_default_header(h, rq, rs));
00407
00408
00409 dbg_err_if(response_disable_caching(rs));
00410
00411
00412 dbg_err_if(u_snprintf(buf, BUFSZ, "error.%d", http_status));
00413 if((vhost = http_get_vhost(h, rq)) == NULL)
00414 err_page = u_config_get_subkey_value(h->config, buf);
00415 else
00416 err_page = u_config_get_subkey_value(vhost->config, buf);
00417
00418 if(err_page && !request_set_uri(rq, err_page, NULL, NULL))
00419 {
00420 dbg_err_if(http_resolv_request(h, rq));
00421 if(http_is_valid_uri(rq, err_page, strlen(err_page)))
00422 {
00423
00424 broker_serve(h->broker, h, rq, rs);
00425 return 0;
00426 }
00427
00428
00429 warn("%d handler page (%s) not found", http_status, err_page);
00430 }
00431
00432
00433 response_set_status(rs, http_status);
00434
00435 response_print_header(rs);
00436
00437 if(request_get_method(rq) == HM_HEAD)
00438 return 0;
00439
00440
00441 dbg_err_if(io_printf(response_io(rs),
00442 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">"
00443 "<html><head><title>%d %s</title></head>\n"
00444 "<body><h1>%s</h1><p>URL: %s</p><hr>"
00445 "<address>KLone/%s web server - www.koanlogic.com</address>"
00446 "</body></html>",
00447 http_status, http_get_status_desc(http_status),
00448 http_get_status_desc(http_status),
00449 (request_get_uri(rq) ? request_get_uri(rq) : ""),
00450 KLONE_VERSION
00451 ) < 0);
00452
00453 return 0;
00454 err:
00455 return ~0;
00456 }
00457
00458 static int http_serve(http_t *h, int fd)
00459 {
00460 request_t *rq = NULL;
00461 response_t *rs = NULL;
00462 io_t *in = NULL, *out = NULL;
00463 int cgi = 0, port, rc = HTTP_STATUS_INTERNAL_SERVER_ERROR;
00464 const char *gwi = NULL, *cstr;
00465 talarm_t *al = NULL;
00466 addr_t *addr;
00467 vhost_t *vhost;
00468 struct sockaddr sa;
00469 size_t sasz;
00470 char *uri, nuri[URI_MAX];
00471
00472 u_unused_args(al);
00473
00474 dbg_err_if (h == NULL);
00475 dbg_err_if (fd < 0);
00476
00477 if(fd == 0 && (gwi = getenv("GATEWAY_INTERFACE")) != NULL)
00478 cgi++;
00479
00480
00481 dbg_err_if(request_create(h, &rq));
00482 request_set_cgi(rq, cgi);
00483
00484
00485 dbg_err_if(addr_create(&addr));
00486
00487 if(cgi)
00488 {
00489 if(getenv("REMOTE_ADDR") && getenv("REMOTE_PORT"))
00490 {
00491 port = atoi(getenv("REMOTE_PORT"));
00492 dbg_err_if(addr_set(addr, getenv("REMOTE_ADDR"), port));
00493 dbg_err_if(request_set_addr(rq, addr));
00494 }
00495
00496 if(getenv("SERVER_ADDR"))
00497 {
00498 if(getenv("SERVER_PORT"))
00499 port = atoi(getenv("SERVER_PORT"));
00500 else
00501 port = 80;
00502 dbg_err_if(addr_set(addr, getenv("SERVER_ADDR"), port));
00503 dbg_err_if(request_set_peer_addr(rq, addr));
00504 }
00505 } else {
00506
00507 sasz = sizeof(struct sockaddr);
00508 dbg_err_if(getsockname(fd, &sa, &sasz));
00509 dbg_err_if(addr_set_from_sa(addr, &sa, sasz));
00510 dbg_err_if(request_set_addr(rq, addr));
00511
00512
00513 sasz = sizeof(struct sockaddr);
00514 dbg_err_if(getpeername(fd, &sa, &sasz));
00515 dbg_err_if(addr_set_from_sa(addr, &sa, sasz));
00516 dbg_err_if(request_set_peer_addr(rq, addr));
00517 }
00518
00519 addr_free(addr);
00520 addr = NULL;
00521
00522 #ifdef HAVE_LIBOPENSSL
00523
00524
00525 if(h->ssl && !cgi)
00526 dbg_err_if(io_ssl_create(fd, IO_FD_CLOSE, 0, h->ssl_ctx, &in));
00527 else
00528 dbg_err_if(io_fd_create(fd, IO_FD_CLOSE, &in));
00529 #else
00530
00531 dbg_err_if(io_fd_create(fd, IO_FD_CLOSE, &in));
00532 #endif
00533
00534
00535 dbg_err_if(request_bind(rq, in));
00536 in = NULL;
00537
00538
00539 dbg_err_if(response_create(h, &rs));
00540
00541 response_set_cgi(rs, cgi);
00542
00543 if(cgi)
00544 dbg_err_if(cgi_set_request(rq));
00545
00546
00547 if(cgi)
00548 dbg_err_if(io_fd_create((cgi ? 1 : fd), IO_FD_CLOSE, &out));
00549 else
00550
00551 dbg_err_if(io_dup(request_io(rq), &out));
00552
00553
00554 response_set_method(rs, HM_GET);
00555
00556
00557 dbg_err_if(response_bind(rs, out));
00558 out = NULL;
00559
00560
00561 dbg_err_if(response_set_status(rs, HTTP_STATUS_BAD_REQUEST));
00562 rc = HTTP_STATUS_BAD_REQUEST;
00563
00564
00565 dbg_err_if(request_parse_header(rq, http_is_valid_uri, rq));
00566
00567 response_set_method(rs, request_get_method(rq));
00568
00569
00570 dbg_err_if((vhost = http_get_vhost(h, rq)) == NULL);
00571 request_set_vhost(rq, vhost);
00572
00573
00574 dbg_err_if(http_resolv_request(h, rq));
00575
00576
00577 if((cstr = request_get_filename(rq)) != NULL && cstr[strlen(cstr)-1] == '/')
00578 dbg_if(http_set_index_request(h, rq));
00579
00580
00581 dbg_err_if(http_add_default_header(h, rq, rs));
00582
00583
00584 dbg_err_if(response_set_status(rs, HTTP_STATUS_OK));
00585
00586
00587 rc = broker_serve(h->broker, h, rq, rs);
00588
00589
00590
00591 if(response_get_status(rs) == 404 && (uri = request_get_uri(rq)) != NULL &&
00592 uri[strlen(uri)-1] != '/')
00593 {
00594 if(!http_set_index_request(h, rq))
00595 {
00596 strlcpy(nuri, request_get_uri(rq), sizeof(nuri));
00597 strlcat(nuri, "/", sizeof(nuri));
00598
00599 if(request_get_path_info(rq))
00600 strlcat(nuri, request_get_path_info(rq), sizeof(nuri));
00601
00602 if(request_get_query_string(rq))
00603 {
00604 strlcat(nuri, "?", sizeof(nuri));
00605 strlcat(nuri, request_get_query_string(rq), sizeof(nuri));
00606 }
00607
00608 response_redirect(rs, nuri);
00609 rc = HTTP_STATUS_MOVED_TEMPORARILY;
00610 }
00611 }
00612
00613
00614 if(vhost->klog)
00615 dbg_if(access_log(h, vhost->al_config, rq, rs));
00616
00617
00618 hook_call(request, rq, rs);
00619
00620
00621 nop_err_if(rc != 0);
00622
00623
00624
00625 request_free(rq);
00626 response_free(rs);
00627
00628
00629
00630 return 0;
00631 err:
00632
00633 if(rq && rs)
00634 hook_call(request, rq, rs);
00635
00636 if(rc && rq && rs && response_io(rs))
00637 http_print_error_page(h, rq, rs, rc);
00638 if(in)
00639 io_free(in);
00640 if(out)
00641 io_free(out);
00642 if(rq)
00643 request_free(rq);
00644 if(rs)
00645 response_free(rs);
00646 return ~0;
00647 }
00648
00649 static int http_free(http_t *h)
00650 {
00651 dbg_return_if (h == NULL, 0);
00652
00653 if(h->broker)
00654 broker_free(h->broker);
00655
00656 if(h->vhosts)
00657 vhost_list_free(h->vhosts);
00658
00659 U_FREE(h);
00660
00661 return 0;
00662 }
00663
00664 static int http_add_vhost(http_t *http, const char *host, u_config_t *c)
00665 {
00666 vhost_t *top, *vhost = NULL;
00667 u_config_t *child;
00668 const char *v;
00669
00670 dbg_err_if (http == NULL);
00671 dbg_err_if (host == NULL);
00672 dbg_err_if (c == NULL);
00673
00674 dbg_err_if(vhost_create(&vhost));
00675
00676 vhost->host = host;
00677 vhost->config = c;
00678 vhost->http = http;
00679
00680
00681 vhost->server_sig = "klone/" KLONE_VERSION;
00682 vhost->dir_root = "";
00683 vhost->index = NULL;
00684 vhost->send_enc_deflate = 0;
00685
00686
00687
00688 if((child = u_config_get_child(c, "access_log")) != NULL)
00689 {
00690 v = u_config_get_value(child);
00691
00692
00693 if(v == NULL || strcasecmp(v, "no"))
00694 dbg_err_if(klog_open_from_config(child, &vhost->klog));
00695
00696 vhost->al_config = child;
00697 } else {
00698
00699 if((top = vhost_list_get_n(http->vhosts, 0)) != NULL)
00700 {
00701
00702 vhost->klog = top->klog;
00703 vhost->al_config = top->al_config;
00704 }
00705 }
00706
00707
00708 dbg_err_if(u_config_get_subkey_value_b(c, "send_enc_deflate", 0,
00709 &vhost->send_enc_deflate));
00710
00711
00712 if((v = u_config_get_subkey_value(c, "server_sig")) != NULL)
00713 vhost->server_sig = v;
00714
00715
00716 if((v = u_config_get_subkey_value(c, "dir_root")) != NULL)
00717 vhost->dir_root = v;
00718 else
00719 crit_err("dir_root must be set (vhost: %s)", vhost->host);
00720
00721
00722 if((v = u_config_get_subkey_value(c, "index")) != NULL)
00723 vhost->index = v;
00724
00725 dbg_err_if(vhost_list_add(http->vhosts, vhost));
00726
00727 return 0;
00728 err:
00729 if(vhost)
00730 vhost_free(vhost);
00731 return ~0;
00732 }
00733
00734 static int config_inherit(u_config_t *dst, u_config_t *from)
00735 {
00736 static const char *dont_inherit[] = {
00737 "addr", "model", "type", "dir_root", "dir_alias", "script_alias",
00738 "access_log", NULL
00739 };
00740 u_config_t *config, *child = NULL;
00741 const char **di, *key, *value;
00742 int n;
00743
00744 dbg_err_if (dst == NULL);
00745 dbg_err_if (from == NULL);
00746
00747 for(n = 0; (config = u_config_get_child_n(from, NULL, n)); ++n)
00748 {
00749 if(u_config_get_child(config, "dir_root"))
00750 continue;
00751
00752 key = u_config_get_key(config);
00753 value = u_config_get_value(config);
00754
00755
00756 for(di = dont_inherit; *di; ++di)
00757 if(strcasecmp(*di, key) == 0)
00758 goto next;
00759
00760 dbg_err_if(u_config_add_child(dst, key, &child));
00761 dbg_err_if(u_config_set_value(child, value));
00762
00763 dbg_err_if(config_inherit(child, config));
00764
00765 next:;
00766 }
00767
00768 return 0;
00769 err:
00770 return ~0;
00771 }
00772
00773 static int http_set_vhost_list(http_t *http)
00774 {
00775 u_config_t *config;
00776 int n;
00777
00778 dbg_err_if (http == NULL);
00779
00780
00781 dbg_err_if(http_add_vhost(http, "", http->config));
00782
00783
00784 for(n = 0; (config = u_config_get_child_n(http->config, NULL, n)); ++n)
00785 {
00786 if(u_config_get_child(config, "dir_root") == NULL)
00787 continue;
00788
00789 dbg_err_if(u_config_get_key(config) == NULL);
00790
00791 info("configuring virtual host [%s]", u_config_get_key(config));
00792
00793
00794 dbg_err_if(config_inherit(config, http->config));
00795
00796 dbg_err_if(http_add_vhost(http, u_config_get_key(config), config));
00797 }
00798
00799 return 0;
00800 err:
00801 return ~0;
00802 }
00803
00804 static int http_create(u_config_t *config, http_t **ph)
00805 {
00806 http_t *h = NULL;
00807
00808 dbg_err_if (config == NULL);
00809 dbg_err_if (ph == NULL);
00810
00811 h = u_zalloc(sizeof(http_t));
00812 dbg_err_if(h == NULL);
00813
00814 h->config = config;
00815
00816 dbg_err_if(vhost_list_create(&h->vhosts));
00817
00818
00819 dbg_err_if(broker_create(&h->broker));
00820
00821
00822 dbg_err_if(http_set_vhost_list(h));
00823
00824
00825 if(ctx->debug > 1)
00826 u_config_print(ctx->config, 0);
00827
00828 *ph = h;
00829
00830 return 0;
00831 err:
00832 if(h)
00833 http_free(h);
00834 return ~0;
00835 }
00836
00837 static int http_backend_serve(struct backend_s *be, int fd)
00838 {
00839 http_t *h;
00840 int rc;
00841
00842 dbg_err_if (be == NULL);
00843 dbg_err_if (be->arg == NULL);
00844 dbg_err_if (fd < 0);
00845
00846 h = (http_t *) be->arg;
00847
00848
00849 rc = http_serve(h, fd);
00850
00851 return rc;
00852 err:
00853 return ~0;
00854 }
00855
00856 static int http_backend_term(struct backend_s *be)
00857 {
00858 http_t *http;
00859
00860 dbg_return_if (be == NULL, 0);
00861 dbg_return_if (be->arg == NULL, 0);
00862
00863 http = (http_t *) be->arg;
00864
00865 dbg_err_if(session_module_term(http->sess_opt));
00866
00867 http_free(http);
00868
00869 return 0;
00870 err:
00871 return ~0;
00872 }
00873
00874 static int http_backend_init(struct backend_s *be)
00875 {
00876 http_t *http = NULL;
00877 broker_t *broker = NULL;
00878
00879 dbg_err_if (be == NULL);
00880
00881 dbg_err_if(http_create(be->config, &http));
00882
00883 be->arg = http;
00884
00885 dbg_err_if(session_module_init(http->config, &http->sess_opt));
00886
00887 return 0;
00888 err:
00889 if(http)
00890 http_free(http);
00891 if(broker)
00892 broker_free(broker);
00893 return ~0;
00894 }
00895
00896 #ifdef HAVE_LIBOPENSSL
00897 static int https_backend_init(struct backend_s *be)
00898 {
00899 http_t *https;
00900
00901 dbg_err_if (be == NULL);
00902
00903 dbg_err_if(http_backend_init(be));
00904
00905 https = (http_t *) be->arg;
00906
00907
00908 https->ssl = 1;
00909
00910
00911 https->ssl_ctx = tls_load_init_ctx(http_get_config(https));
00912 warn_err_ifm (https->ssl_ctx == NULL, "bad or missing HTTPS credentials");
00913
00914 dbg_err_if(session_module_init(https->config, &https->sess_opt));
00915
00916 return 0;
00917 err:
00918 return ~0;
00919 }
00920
00921 static int https_backend_term(struct backend_s *be)
00922 {
00923 http_t *https;
00924
00925 dbg_err_if (be == NULL);
00926
00927 https = (http_t *) be->arg;
00928 if (https == NULL)
00929 return 0;
00930
00931 SSL_CTX_free(https->ssl_ctx);
00932
00933 return http_backend_term(be);
00934 err:
00935 return ~0;
00936 }
00937
00938
00939 backend_t be_https =
00940 BACKEND_STATIC_INITIALIZER( "https",
00941 https_backend_init,
00942 http_backend_serve,
00943 https_backend_term );
00944 #endif
00945
00946 backend_t be_http =
00947 BACKEND_STATIC_INITIALIZER( "http",
00948 http_backend_init,
00949 http_backend_serve,
00950 http_backend_term );
00951