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