1 #include "first.h" 2 3 #include "base.h" 4 #include "buffer.h" 5 #include "burl.h" /* HTTP_PARSEOPT_HEADER_STRICT */ 6 #include "settings.h" /* BUFFER_MAX_REUSE_SIZE MAX_READ_LIMIT MAX_WRITE_LIMIT */ 7 #include "log.h" 8 #include "connections.h" 9 #include "fdevent.h" 10 #include "http_header.h" 11 12 #include "request.h" 13 #include "response.h" 14 #include "network.h" 15 #include "http_chunk.h" 16 #include "stat_cache.h" 17 18 #include "plugin.h" 19 20 #include "inet_ntop_cache.h" 21 22 #include <sys/stat.h> 23 24 #include <stdlib.h> 25 #include <unistd.h> 26 #include <errno.h> 27 #include <string.h> 28 29 #ifdef HAVE_SYS_FILIO_H 30 # include <sys/filio.h> 31 #endif 32 33 #include "sys-socket.h" 34 35 #define HTTP_LINGER_TIMEOUT 5 36 37 #define connection_set_state(r, n) ((r)->state = (n)) 38 39 __attribute_cold__ 40 static connection *connection_init(server *srv); 41 42 static int connection_reset(connection *con); 43 44 45 static connection *connections_get_new_connection(server *srv) { 46 connections * const conns = &srv->conns; 47 size_t i; 48 49 if (conns->size == conns->used) { 50 conns->size += srv->max_conns >= 128 ? 128 : srv->max_conns > 16 ? 16 : srv->max_conns; 51 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size); 52 force_assert(NULL != conns->ptr); 53 54 for (i = conns->used; i < conns->size; i++) { 55 conns->ptr[i] = connection_init(srv); 56 connection_reset(conns->ptr[i]); 57 } 58 } 59 60 conns->ptr[conns->used]->ndx = conns->used; 61 return conns->ptr[conns->used++]; 62 } 63 64 static void connection_del(server *srv, connection *con) { 65 connections * const conns = &srv->conns; 66 67 if (-1 == con->ndx) return; 68 uint32_t i = (uint32_t)con->ndx; 69 70 /* not last element */ 71 72 if (i != --conns->used) { 73 connection * const temp = conns->ptr[i]; 74 conns->ptr[i] = conns->ptr[conns->used]; 75 conns->ptr[conns->used] = temp; 76 77 conns->ptr[i]->ndx = i; 78 conns->ptr[conns->used]->ndx = -1; 79 } 80 81 con->ndx = -1; 82 #if 0 83 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used); 84 for (i = 0; i < conns->used; i++) { 85 fprintf(stderr, "%d ", conns->ptr[i]->fd); 86 } 87 fprintf(stderr, "\n"); 88 #endif 89 } 90 91 __attribute_cold__ 92 static void connection_plugin_ctx_check(server * const srv, request_st * const r) { 93 /* plugins should have cleaned themselves up */ 94 for (uint32_t i = 0; i < srv->plugins.used; ++i) { 95 plugin *p = ((plugin **)(srv->plugins.ptr))[i]; 96 plugin_data_base *pd = p->data; 97 if (!pd || NULL == r->plugin_ctx[pd->id]) continue; 98 log_error(r->conf.errh, __FILE__, __LINE__, 99 "missing cleanup in %s", p->name); 100 r->plugin_ctx[pd->id] = NULL; 101 } 102 } 103 104 static void connection_close(connection *con) { 105 if (con->fd < 0) con->fd = -con->fd; 106 107 plugins_call_handle_connection_close(con); 108 109 server * const srv = con->srv; 110 request_st * const r = &con->request; 111 112 /* plugins should have cleaned themselves up */ 113 for (uint32_t i = 0; i < srv->plugins.used; ++i) { 114 if (NULL != r->plugin_ctx[i]) { 115 connection_plugin_ctx_check(srv, r); 116 break; 117 } 118 } 119 120 connection_set_state(r, CON_STATE_CONNECT); 121 buffer_clear(&r->uri.authority); 122 buffer_reset(&r->uri.path); 123 buffer_reset(&r->uri.query); 124 buffer_reset(&r->target_orig); 125 buffer_reset(&r->target); /*(see comments in connection_reset())*/ 126 buffer_reset(&r->pathinfo); /*(see comments in connection_reset())*/ 127 128 chunkqueue_reset(con->read_queue); 129 con->request_count = 0; 130 con->is_ssl_sock = 0; 131 132 fdevent_fdnode_event_del(srv->ev, con->fdn); 133 fdevent_unregister(srv->ev, con->fd); 134 con->fdn = NULL; 135 #ifdef __WIN32 136 if (0 == closesocket(con->fd)) 137 #else 138 if (0 == close(con->fd)) 139 #endif 140 --srv->cur_fds; 141 else 142 log_perror(r->conf.errh, __FILE__, __LINE__, 143 "(warning) close: %d", con->fd); 144 145 if (r->conf.log_state_handling) { 146 log_error(r->conf.errh, __FILE__, __LINE__, 147 "connection closed for fd %d", con->fd); 148 } 149 con->fd = -1; 150 151 connection_del(srv, con); 152 } 153 154 static void connection_read_for_eos_plain(connection * const con) { 155 /* we have to do the linger_on_close stuff regardless 156 * of r->keep_alive; even non-keepalive sockets 157 * may still have unread data, and closing before reading 158 * it will make the client not see all our output. 159 */ 160 ssize_t len; 161 const int type = con->dst_addr.plain.sa_family; 162 char buf[16384]; 163 do { 164 len = fdevent_socket_read_discard(con->fd, buf, sizeof(buf), 165 type, SOCK_STREAM); 166 } while (len > 0 || (len < 0 && errno == EINTR)); 167 168 if (len < 0 && errno == EAGAIN) return; 169 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 170 if (len < 0 && errno == EWOULDBLOCK) return; 171 #endif 172 173 /* 0 == len || (len < 0 && (errno is a non-recoverable error)) */ 174 con->close_timeout_ts = log_epoch_secs - (HTTP_LINGER_TIMEOUT+1); 175 } 176 177 static void connection_read_for_eos_ssl(connection * const con) { 178 if (con->network_read(con, con->read_queue, MAX_READ_LIMIT) < 0) 179 con->close_timeout_ts = log_epoch_secs - (HTTP_LINGER_TIMEOUT+1); 180 chunkqueue_reset(con->read_queue); 181 } 182 183 static void connection_read_for_eos(connection * const con) { 184 !con->is_ssl_sock 185 ? connection_read_for_eos_plain(con) 186 : connection_read_for_eos_ssl(con); 187 } 188 189 static void connection_handle_close_state(connection *con) { 190 connection_read_for_eos(con); 191 192 if (log_epoch_secs - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) { 193 connection_close(con); 194 } 195 } 196 197 static void connection_handle_shutdown(connection *con) { 198 plugins_call_handle_connection_shut_wr(con); 199 200 connection_reset(con); 201 ++con->srv->con_closed; 202 203 /* close the connection */ 204 if (con->fd >= 0 205 && (con->is_ssl_sock || 0 == shutdown(con->fd, SHUT_WR))) { 206 con->close_timeout_ts = log_epoch_secs; 207 208 request_st * const r = &con->request; 209 connection_set_state(r, CON_STATE_CLOSE); 210 if (r->conf.log_state_handling) { 211 log_error(r->conf.errh, __FILE__, __LINE__, 212 "shutdown for fd %d", con->fd); 213 } 214 } else { 215 connection_close(con); 216 } 217 } 218 219 __attribute_cold__ 220 static void connection_fdwaitqueue_append(connection *con) { 221 connection_list_append(&con->srv->fdwaitqueue, con); 222 } 223 224 static void connection_handle_response_end_state(request_st * const r, connection * const con) { 225 /* call request_done hook if http_status set (e.g. to log request) */ 226 /* (even if error, connection dropped, as long as http_status is set) */ 227 if (r->http_status) plugins_call_handle_request_done(r); 228 229 if (r->state != CON_STATE_ERROR) ++con->srv->con_written; 230 231 if (r->reqbody_length != r->reqbody_queue->bytes_in 232 || r->state == CON_STATE_ERROR) { 233 /* request body is present and has not been read completely */ 234 r->keep_alive = 0; 235 } 236 237 if (r->keep_alive) { 238 connection_reset(con); 239 #if 0 240 r->start_ts = con->read_idle_ts = log_epoch_secs; 241 #endif 242 connection_set_state(r, CON_STATE_REQUEST_START); 243 } else { 244 connection_handle_shutdown(con); 245 } 246 } 247 248 __attribute_cold__ 249 static void connection_handle_errdoc_init(request_st * const r) { 250 /* modules that produce headers required with error response should 251 * typically also produce an error document. Make an exception for 252 * mod_auth WWW-Authenticate response header. */ 253 buffer *www_auth = NULL; 254 if (401 == r->http_status) { 255 const buffer *vb = http_header_response_get(r, HTTP_HEADER_OTHER, CONST_STR_LEN("WWW-Authenticate")); 256 if (NULL != vb) www_auth = buffer_init_buffer(vb); 257 } 258 259 buffer_reset(&r->physical.path); 260 r->resp_htags = 0; 261 array_reset_data_strings(&r->resp_headers); 262 http_response_body_clear(r, 0); 263 264 if (NULL != www_auth) { 265 http_header_response_set(r, HTTP_HEADER_OTHER, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(www_auth)); 266 buffer_free(www_auth); 267 } 268 } 269 270 __attribute_cold__ 271 static void connection_handle_errdoc(request_st * const r) { 272 if (NULL == r->handler_module 273 ? r->error_handler_saved_status >= 65535 274 : (!r->conf.error_intercept||r->error_handler_saved_status)) 275 return; 276 277 connection_handle_errdoc_init(r); 278 r->resp_body_finished = 1; 279 280 /* try to send static errorfile */ 281 if (!buffer_string_is_empty(r->conf.errorfile_prefix)) { 282 buffer_copy_buffer(&r->physical.path, r->conf.errorfile_prefix); 283 buffer_append_int(&r->physical.path, r->http_status); 284 buffer_append_string_len(&r->physical.path, CONST_STR_LEN(".html")); 285 if (0 == http_chunk_append_file(r, &r->physical.path)) { 286 stat_cache_entry *sce = stat_cache_get_entry(&r->physical.path); 287 const buffer *content_type = (NULL != sce) 288 ? stat_cache_content_type_get(sce, r) 289 : NULL; 290 if (content_type) 291 http_header_response_set(r, HTTP_HEADER_CONTENT_TYPE, 292 CONST_STR_LEN("Content-Type"), 293 CONST_BUF_LEN(content_type)); 294 return; 295 } 296 } 297 298 /* build default error-page */ 299 buffer_reset(&r->physical.path); 300 buffer * const b = r->tmp_buf; 301 buffer_copy_string_len(b, CONST_STR_LEN( 302 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" 303 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" 304 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" 305 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" 306 " <head>\n" 307 " <title>")); 308 http_status_append(b, r->http_status); 309 buffer_append_string_len(b, CONST_STR_LEN( 310 "</title>\n" 311 " </head>\n" 312 " <body>\n" 313 " <h1>")); 314 http_status_append(b, r->http_status); 315 buffer_append_string_len(b, CONST_STR_LEN( 316 "</h1>\n" 317 " </body>\n" 318 "</html>\n")); 319 (void)http_chunk_append_mem(r, CONST_BUF_LEN(b)); 320 321 http_header_response_set(r, HTTP_HEADER_CONTENT_TYPE, 322 CONST_STR_LEN("Content-Type"), 323 CONST_STR_LEN("text/html")); 324 } 325 326 static int connection_handle_write_prepare(request_st * const r) { 327 if (NULL == r->handler_module) { 328 /* static files */ 329 switch(r->http_method) { 330 case HTTP_METHOD_GET: 331 case HTTP_METHOD_POST: 332 case HTTP_METHOD_HEAD: 333 break; 334 case HTTP_METHOD_OPTIONS: 335 /* 336 * 400 is coming from the request-parser BEFORE uri.path is set 337 * 403 is from the response handler when noone else catched it 338 * 339 * */ 340 if ((!r->http_status || r->http_status == 200) 341 && !buffer_string_is_empty(&r->uri.path) 342 && r->uri.path.ptr[0] != '*') { 343 http_response_body_clear(r, 0); 344 http_header_response_append(r, HTTP_HEADER_OTHER, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); 345 r->http_status = 200; 346 r->resp_body_finished = 1; 347 348 } 349 break; 350 default: 351 if (0 == r->http_status) { 352 r->http_status = 501; 353 } 354 break; 355 } 356 } 357 358 if (r->http_status == 0) { 359 r->http_status = 403; 360 } 361 362 switch(r->http_status) { 363 case 204: /* class: header only */ 364 case 205: 365 case 304: 366 /* disable chunked encoding again as we have no body */ 367 http_response_body_clear(r, 1); 368 r->resp_body_finished = 1; 369 break; 370 default: /* class: header + body */ 371 /* only custom body for 4xx and 5xx */ 372 if (r->http_status >= 400 && r->http_status < 600) 373 connection_handle_errdoc(r); 374 break; 375 } 376 377 /* Allow filter plugins to change response headers before they are written. */ 378 switch(plugins_call_handle_response_start(r)) { 379 case HANDLER_GO_ON: 380 case HANDLER_FINISHED: 381 break; 382 default: 383 log_error(r->conf.errh, __FILE__, __LINE__, 384 "response_start plugin failed"); 385 return -1; 386 } 387 388 if (r->resp_body_finished) { 389 /* we have all the content and chunked encoding is not used, set a content-length */ 390 391 if (!(r->resp_htags & (HTTP_HEADER_CONTENT_LENGTH|HTTP_HEADER_TRANSFER_ENCODING))) { 392 off_t qlen = chunkqueue_length(r->write_queue); 393 394 /** 395 * The Content-Length header only can be sent if we have content: 396 * - HEAD doesn't have a content-body (but have a content-length) 397 * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3) 398 * 399 * Otherwise generate a Content-Length header as chunked encoding is not 400 * available 401 */ 402 if ((r->http_status >= 100 && r->http_status < 200) || 403 r->http_status == 204 || 404 r->http_status == 304) { 405 /* no Content-Body, no Content-Length */ 406 http_header_response_unset(r, HTTP_HEADER_CONTENT_LENGTH, CONST_STR_LEN("Content-Length")); 407 } else if (qlen > 0) { 408 buffer * const tb = r->tmp_buf; 409 buffer_clear(tb); 410 buffer_append_int(tb, qlen); 411 http_header_response_set(r, HTTP_HEADER_CONTENT_LENGTH, 412 CONST_STR_LEN("Content-Length"), 413 CONST_BUF_LEN(tb)); 414 } else if (r->http_method != HTTP_METHOD_HEAD) { 415 /* qlen = 0 is important for Redirects (301, ...) as they MAY have 416 * a content. Browsers are waiting for a Content otherwise 417 */ 418 http_header_response_set(r, HTTP_HEADER_CONTENT_LENGTH, 419 CONST_STR_LEN("Content-Length"), 420 CONST_STR_LEN("0")); 421 } 422 } 423 } else { 424 /** 425 * the file isn't finished yet, but we have all headers 426 * 427 * to get keep-alive we either need: 428 * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or 429 * - Transfer-Encoding: chunked (HTTP/1.1) 430 * - Upgrade: ... (lighttpd then acts as transparent proxy) 431 */ 432 433 if (!(r->resp_htags & (HTTP_HEADER_CONTENT_LENGTH|HTTP_HEADER_TRANSFER_ENCODING|HTTP_HEADER_UPGRADE))) { 434 if (r->http_method == HTTP_METHOD_CONNECT 435 && r->http_status == 200) { 436 /*(no transfer-encoding if successful CONNECT)*/ 437 } else if (r->http_version == HTTP_VERSION_1_1) { 438 off_t qlen = chunkqueue_length(r->write_queue); 439 r->resp_send_chunked = 1; 440 if (qlen) { 441 /* create initial Transfer-Encoding: chunked segment */ 442 buffer * const b = chunkqueue_prepend_buffer_open(r->write_queue); 443 buffer_append_uint_hex(b, (uintmax_t)qlen); 444 buffer_append_string_len(b, CONST_STR_LEN("\r\n")); 445 chunkqueue_prepend_buffer_commit(r->write_queue); 446 chunkqueue_append_mem(r->write_queue, CONST_STR_LEN("\r\n")); 447 } 448 http_header_response_append(r, HTTP_HEADER_TRANSFER_ENCODING, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked")); 449 } else { 450 r->keep_alive = 0; 451 } 452 } 453 } 454 455 if (r->http_method == HTTP_METHOD_HEAD) { 456 /** 457 * a HEAD request has the same as a GET 458 * without the content 459 */ 460 http_response_body_clear(r, 1); 461 r->resp_body_finished = 1; 462 } 463 464 http_response_write_header(r); 465 466 return 0; 467 } 468 469 static void connection_handle_write(connection *con) { 470 int rc = connection_write_chunkqueue(con, con->write_queue, MAX_WRITE_LIMIT); 471 request_st * const r = &con->request; 472 switch (rc) { 473 case 0: 474 if (r->resp_body_finished) { 475 connection_set_state(r, CON_STATE_RESPONSE_END); 476 } 477 break; 478 case -1: /* error on our side */ 479 log_error(r->conf.errh, __FILE__, __LINE__, 480 "connection closed: write failed on fd %d", con->fd); 481 connection_set_state(r, CON_STATE_ERROR); 482 break; 483 case -2: /* remote close */ 484 connection_set_state(r, CON_STATE_ERROR); 485 break; 486 case 1: 487 con->is_writable = 0; 488 489 /* not finished yet -> WRITE */ 490 break; 491 } 492 } 493 494 static void connection_handle_write_state(request_st * const r, connection * const con) { 495 do { 496 /* only try to write if we have something in the queue */ 497 if (!chunkqueue_is_empty(con->write_queue)) { 498 if (con->is_writable) { 499 connection_handle_write(con); 500 if (r->state != CON_STATE_WRITE) break; 501 } 502 } else if (r->resp_body_finished) { 503 connection_set_state(r, CON_STATE_RESPONSE_END); 504 break; 505 } 506 507 if (r->handler_module && !r->resp_body_finished) { 508 const plugin * const p = r->handler_module; 509 int rc = p->handle_subrequest(r, p->data); 510 switch(rc) { 511 case HANDLER_WAIT_FOR_EVENT: 512 case HANDLER_FINISHED: 513 case HANDLER_GO_ON: 514 break; 515 case HANDLER_WAIT_FOR_FD: 516 connection_fdwaitqueue_append(con); 517 break; 518 case HANDLER_COMEBACK: 519 default: 520 log_error(r->conf.errh, __FILE__, __LINE__, 521 "unexpected subrequest handler ret-value: %d %d", 522 con->fd, rc); 523 /* fall through */ 524 case HANDLER_ERROR: 525 connection_set_state(r, CON_STATE_ERROR); 526 break; 527 } 528 } 529 } while (r->state == CON_STATE_WRITE 530 && (!chunkqueue_is_empty(con->write_queue) 531 ? con->is_writable 532 : r->resp_body_finished)); 533 } 534 535 536 __attribute_cold__ 537 static connection *connection_init(server *srv) { 538 connection * const con = calloc(1, sizeof(*con)); 539 force_assert(NULL != con); 540 541 con->fd = 0; 542 con->ndx = -1; 543 con->bytes_written = 0; 544 con->bytes_read = 0; 545 546 con->dst_addr_buf = buffer_init(); 547 con->srv = srv; 548 con->plugin_slots = srv->plugin_slots; 549 con->config_data_base = srv->config_data_base; 550 551 request_st * const r = &con->request; 552 553 con->write_queue = r->write_queue = chunkqueue_init(); 554 con->read_queue = r->read_queue = chunkqueue_init(); 555 556 /* init plugin specific connection structures */ 557 558 r->resp_header_len = 0; 559 r->loops_per_request = 0; 560 r->con = con; 561 r->tmp_buf = srv->tmp_buf; 562 563 r->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *)); 564 force_assert(NULL != r->plugin_ctx); 565 566 r->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t)); 567 force_assert(NULL != r->cond_cache); 568 569 #ifdef HAVE_PCRE_H 570 if (srv->config_context->used > 1) {/*save 128b per con if no conditions)*/ 571 r->cond_match = 572 calloc(srv->config_context->used, sizeof(cond_match_t)); 573 force_assert(NULL != r->cond_match); 574 } 575 #endif 576 577 r->reqbody_queue = chunkqueue_init(); 578 579 config_reset_config(r); 580 581 return con; 582 } 583 584 void connections_free(server *srv) { 585 connections * const conns = &srv->conns; 586 for (uint32_t i = 0; i < conns->size; ++i) { 587 connection *con = conns->ptr[i]; 588 request_st * const r = &con->request; 589 590 connection_reset(con); 591 592 chunkqueue_free(r->reqbody_queue); 593 chunkqueue_free(r->write_queue); 594 chunkqueue_free(r->read_queue); 595 array_free_data(&r->rqst_headers); 596 array_free_data(&r->resp_headers); 597 array_free_data(&r->env); 598 599 free(r->target.ptr); 600 free(r->target_orig.ptr); 601 602 free(r->uri.scheme.ptr); 603 free(r->uri.authority.ptr); 604 free(r->uri.path.ptr); 605 free(r->uri.query.ptr); 606 607 free(r->physical.doc_root.ptr); 608 free(r->physical.path.ptr); 609 free(r->physical.basedir.ptr); 610 free(r->physical.etag.ptr); 611 free(r->physical.rel_path.ptr); 612 613 free(r->pathinfo.ptr); 614 free(r->server_name_buf.ptr); 615 616 free(r->plugin_ctx); 617 free(r->cond_cache); 618 free(r->cond_match); 619 620 buffer_free(con->dst_addr_buf); 621 622 free(con); 623 } 624 625 free(conns->ptr); 626 conns->ptr = NULL; 627 } 628 629 630 static int connection_reset(connection *con) { 631 request_st * const r = &con->request; 632 plugins_call_connection_reset(r); 633 634 connection_response_reset(r); 635 con->is_readable = 1; 636 637 con->bytes_written = 0; 638 con->bytes_written_cur_second = 0; 639 con->bytes_read = 0; 640 641 r->resp_header_len = 0; 642 r->loops_per_request = 0; 643 644 r->http_method = HTTP_METHOD_UNSET; 645 r->http_version = HTTP_VERSION_UNSET; 646 647 /*con->proto_default_port = 80;*//*set to default in connection_accepted()*/ 648 649 r->http_host = NULL; 650 r->reqbody_length = 0; 651 r->te_chunked = 0; 652 r->rqst_htags = 0; 653 654 buffer_clear(&r->uri.scheme); 655 656 if (r->rqst_header_len <= BUFFER_MAX_REUSE_SIZE) { 657 r->rqst_headers.used = 0; 658 /* (Note: total header size not recalculated on HANDLER_COMEBACK 659 * even if other request headers changed during processing) 660 * (While this might delay release of larger buffers, it is not 661 * expected to be the general case. For those systems where it 662 * is a typical case, the larger buffers are likely to be reused) */ 663 buffer_clear(&r->target); 664 buffer_clear(&r->pathinfo); 665 /*buffer_clear(&r->target_orig);*/ /* reset later; used by mod_status*/ 666 /*buffer_clear(&r->uri.path);*/ /* reset later; used by mod_status*/ 667 /*buffer_clear(&r->uri.query);*/ /* reset later; used by mod_status*/ 668 /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ 669 /*buffer_clear(&r->server_name_buf);*//* reset when used */ 670 } 671 else { 672 buffer_reset(&r->target); 673 buffer_reset(&r->pathinfo); 674 /*buffer_reset(&r->target_orig);*/ /* reset later; used by mod_status*/ 675 /*buffer_reset(&r->uri.path);*/ /* reset later; used by mod_status*/ 676 /*buffer_reset(&r->uri.query);*/ /* reset later; used by mod_status*/ 677 /*buffer_clear(&r->uri.authority);*//* reset later; used by mod_status*/ 678 /*buffer_clear(&r->server_name_buf);*//* reset when used */ 679 array_reset_data_strings(&r->rqst_headers); 680 } 681 r->rqst_header_len = 0; 682 if (0 != r->env.used) 683 array_reset_data_strings(&r->env); 684 685 chunkqueue_reset(r->reqbody_queue); 686 687 /* The cond_cache gets reset in response.c */ 688 /* config_cond_cache_reset(r); */ 689 690 r->async_callback = 0; 691 r->error_handler_saved_status = 0; 692 /*r->error_handler_saved_method = HTTP_METHOD_UNSET;*/ 693 /*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/ 694 695 config_reset_config(r); 696 697 return 0; 698 } 699 700 __attribute_noinline__ 701 static void connection_discard_blank_line(request_st * const r, const char * const s, unsigned short * const hoff) { 702 if ((s[0] == '\r' && s[1] == '\n') 703 || (s[0] == '\n' 704 && !(r->conf.http_parseopts & HTTP_PARSEOPT_HEADER_STRICT))) { 705 hoff[2] += hoff[1]; 706 memmove(hoff+1, hoff+2, (--hoff[0] - 1) * sizeof(unsigned short)); 707 } 708 } 709 710 static chunk * connection_read_header_more(connection *con, chunkqueue *cq, chunk *c, const size_t olen) { 711 if ((NULL == c || NULL == c->next) && con->is_readable) { 712 con->read_idle_ts = log_epoch_secs; 713 if (0 != con->network_read(con, cq, MAX_READ_LIMIT)) { 714 request_st * const r = &con->request; 715 connection_set_state(r, CON_STATE_ERROR); 716 } 717 } 718 719 if (cq->first != cq->last && 0 != olen) { 720 const size_t clen = chunkqueue_length(cq); 721 size_t block = (olen + (16384-1)) & (16384-1); 722 block += (block - olen > 1024 ? 0 : 16384); 723 chunkqueue_compact_mem(cq, block > clen ? clen : block); 724 } 725 726 /* detect if data is added to chunk */ 727 c = cq->first; 728 return (c && (size_t)c->offset + olen < buffer_string_length(c->mem)) 729 ? c 730 : NULL; 731 } 732 733 __attribute_hot__ 734 static uint32_t connection_read_header_hoff(const char *n, const uint32_t clen, unsigned short hoff[8192]) { 735 uint32_t hlen = 0; 736 for (const char *b; (n = memchr((b = n),'\n',clen-hlen)); ++n) { 737 uint32_t x = (uint32_t)(n - b + 1); 738 hlen += x; 739 if (x <= 2 && (x == 1 || n[-1] == '\r')) { 740 hoff[hoff[0]+1] = hlen; 741 return hlen; 742 } 743 if (++hoff[0] >= /*sizeof(hoff)/sizeof(hoff[0])-1*/ 8192-1) break; 744 hoff[hoff[0]] = hlen; 745 } 746 return 0; 747 } 748 749 /** 750 * handle request header read 751 * 752 * we get called by the state-engine and by the fdevent-handler 753 */ 754 static int connection_handle_read_state(connection * const con) { 755 chunkqueue * const cq = con->read_queue; 756 chunk *c = cq->first; 757 uint32_t clen = 0; 758 uint32_t header_len = 0; 759 request_st * const r = &con->request; 760 int keepalive_request_start = 0; 761 int pipelined_request_start = 0; 762 unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */ 763 764 if (con->request_count > 1 && 0 == con->bytes_read) { 765 keepalive_request_start = 1; 766 if (NULL != c) { /* !chunkqueue_is_empty(cq)) */ 767 pipelined_request_start = 1; 768 /* partial header of next request has already been read, 769 * so optimistically check for more data received on 770 * socket while processing the previous request */ 771 con->is_readable = 1; 772 /*(if partially read next request and unable to read() any bytes, 773 * then will unnecessarily scan again before subsequent read())*/ 774 } 775 } 776 777 do { 778 if (NULL == c) continue; 779 clen = buffer_string_length(c->mem) - c->offset; 780 if (0 == clen) continue; 781 if (c->offset > USHRT_MAX) /*(highly unlikely)*/ 782 chunkqueue_compact_mem(cq, clen); 783 784 hoff[0] = 1; /* number of lines */ 785 hoff[1] = (unsigned short)c->offset; /* base offset for all lines */ 786 /*hoff[2] = ...;*/ /* offset from base for 2nd line */ 787 788 header_len = 789 connection_read_header_hoff(c->mem->ptr + c->offset, clen, hoff); 790 791 /* casting to (unsigned short) might truncate, and the hoff[] 792 * addition might overflow, but max_request_field_size is USHRT_MAX, 793 * so failure will be detected below */ 794 const uint32_t max_request_field_size=r->conf.max_request_field_size; 795 if ((header_len ? header_len : clen) > max_request_field_size 796 || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1) { 797 log_error(r->conf.errh, __FILE__, __LINE__, "%s", 798 "oversized request-header -> sending Status 431"); 799 r->http_status = 431; /* Request Header Fields Too Large */ 800 r->keep_alive = 0; 801 return 1; 802 } 803 804 if (0 != header_len) break; 805 } while ((c = connection_read_header_more(con, cq, c, clen))); 806 807 if (keepalive_request_start) { 808 if (0 != con->bytes_read) { 809 /* update r->start_ts timestamp when first byte of 810 * next request is received on a keep-alive connection */ 811 r->start_ts = log_epoch_secs; 812 if (r->conf.high_precision_timestamps) 813 log_clock_gettime_realtime(&r->start_hp); 814 } 815 if (pipelined_request_start && c) con->read_idle_ts = log_epoch_secs; 816 } 817 818 if (NULL == c) return 0; /* incomplete request headers */ 819 820 #ifdef __COVERITY__ 821 if (buffer_string_length(c->mem) < hoff[1]) { 822 return 1; 823 } 824 #endif 825 826 char * const hdrs = c->mem->ptr + hoff[1]; 827 828 if (con->request_count > 1) { 829 /* skip past \r\n or \n after previous POST request when keep-alive */ 830 if (hoff[2] - hoff[1] <= 2) 831 connection_discard_blank_line(r, hdrs, hoff); 832 833 /* clear buffers which may have been kept for reporting on keep-alive, 834 * (e.g. mod_status) */ 835 buffer_clear(&r->uri.authority); 836 buffer_reset(&r->uri.path); 837 buffer_reset(&r->uri.query); 838 buffer_reset(&r->target_orig); 839 } 840 841 if (r->conf.log_request_header) { 842 log_error(r->conf.errh, __FILE__, __LINE__, 843 "fd: %d request-len: %d\n%.*s", con->fd, (int)header_len, 844 (int)header_len, hdrs); 845 } 846 847 r->http_status = http_request_parse(r, hdrs, hoff, con->proto_default_port); 848 if (0 == r->http_status) { 849 r->conditional_is_valid = (1 << COMP_SERVER_SOCKET) 850 | (1 << COMP_HTTP_SCHEME) 851 | (1 << COMP_HTTP_HOST) 852 | (1 << COMP_HTTP_REMOTE_IP) 853 | (1 << COMP_HTTP_REQUEST_METHOD) 854 | (1 << COMP_HTTP_URL) 855 | (1 << COMP_HTTP_QUERY_STRING) 856 | (1 << COMP_HTTP_REQUEST_HEADER); 857 } 858 else { 859 r->keep_alive = 0; 860 r->reqbody_length = 0; 861 862 if (r->conf.log_request_header_on_error) { 863 /*(http_request_parse() modifies hdrs only to 864 * undo line-wrapping in-place using spaces)*/ 865 log_error(r->conf.errh, __FILE__, __LINE__, "request-header:\n%.*s", 866 (int)header_len, hdrs); 867 } 868 } 869 870 r->rqst_header_len = header_len; 871 chunkqueue_mark_written(cq, header_len); 872 connection_set_state(r, CON_STATE_REQUEST_END); 873 return 1; 874 } 875 876 static handler_t connection_handle_fdevent(void *context, int revents) { 877 connection *con = context; 878 879 joblist_append(con); 880 881 if (con->is_ssl_sock) { 882 /* ssl may read and write for both reads and writes */ 883 if (revents & (FDEVENT_IN | FDEVENT_OUT)) { 884 con->is_readable = 1; 885 con->is_writable = 1; 886 } 887 } else { 888 if (revents & FDEVENT_IN) { 889 con->is_readable = 1; 890 } 891 if (revents & FDEVENT_OUT) { 892 con->is_writable = 1; 893 /* we don't need the event twice */ 894 } 895 } 896 897 request_st * const r = &con->request; 898 899 if (r->state == CON_STATE_READ) { 900 connection_handle_read_state(con); 901 } 902 903 if (r->state == CON_STATE_WRITE && 904 !chunkqueue_is_empty(con->write_queue) && 905 con->is_writable) { 906 connection_handle_write(con); 907 } 908 909 if (r->state == CON_STATE_CLOSE) { 910 /* flush the read buffers */ 911 connection_read_for_eos(con); 912 } 913 914 915 /* attempt (above) to read data in kernel socket buffers 916 * prior to handling FDEVENT_HUP and FDEVENT_ERR */ 917 918 if ((revents & ~(FDEVENT_IN | FDEVENT_OUT)) && r->state != CON_STATE_ERROR) { 919 if (r->state == CON_STATE_CLOSE) { 920 con->close_timeout_ts = log_epoch_secs - (HTTP_LINGER_TIMEOUT+1); 921 } else if (revents & FDEVENT_HUP) { 922 connection_set_state(r, CON_STATE_ERROR); 923 } else if (revents & FDEVENT_RDHUP) { 924 int events = fdevent_fdnode_interest(con->fdn); 925 events &= ~(FDEVENT_IN|FDEVENT_RDHUP); 926 r->conf.stream_request_body &= ~(FDEVENT_STREAM_REQUEST_BUFMIN|FDEVENT_STREAM_REQUEST_POLLIN); 927 r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLRDHUP; 928 con->is_readable = 1; /*(can read 0 for end-of-stream)*/ 929 if (chunkqueue_is_empty(con->read_queue)) r->keep_alive = 0; 930 if (r->reqbody_length < -1) { /*(transparent proxy mode; no more data to read)*/ 931 r->reqbody_length = r->reqbody_queue->bytes_in; 932 } 933 if (sock_addr_get_family(&con->dst_addr) == AF_UNIX) { 934 /* future: will getpeername() on AF_UNIX properly check if still connected? */ 935 fdevent_fdnode_event_set(con->srv->ev, con->fdn, events); 936 } else if (fdevent_is_tcp_half_closed(con->fd)) { 937 /* Success of fdevent_is_tcp_half_closed() after FDEVENT_RDHUP indicates TCP FIN received, 938 * but does not distinguish between client shutdown(fd, SHUT_WR) and client close(fd). 939 * Remove FDEVENT_RDHUP so that we do not spin on the ready event. 940 * However, a later TCP RST will not be detected until next write to socket. 941 * future: might getpeername() to check for TCP RST on half-closed sockets 942 * (without FDEVENT_RDHUP interest) when checking for write timeouts 943 * once a second in server.c, though getpeername() on Windows might not indicate this */ 944 r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_TCP_FIN; 945 fdevent_fdnode_event_set(con->srv->ev, con->fdn, events); 946 } else { 947 /* Failure of fdevent_is_tcp_half_closed() indicates TCP RST 948 * (or unable to tell (unsupported OS), though should not 949 * be setting FDEVENT_RDHUP in that case) */ 950 connection_set_state(r, CON_STATE_ERROR); 951 } 952 } else if (revents & FDEVENT_ERR) { /* error, connection reset */ 953 connection_set_state(r, CON_STATE_ERROR); 954 } else { 955 log_error(r->conf.errh, __FILE__, __LINE__, 956 "connection closed: poll() -> ??? %d", revents); 957 } 958 } 959 960 return HANDLER_FINISHED; 961 } 962 963 964 connection *connection_accept(server *srv, server_socket *srv_socket) { 965 int cnt; 966 sock_addr cnt_addr; 967 size_t cnt_len = sizeof(cnt_addr); /*(size_t intentional; not socklen_t)*/ 968 969 /** 970 * check if we can still open a new connections 971 * 972 * see #1216 973 */ 974 975 if (srv->conns.used >= srv->max_conns) { 976 return NULL; 977 } 978 979 cnt = fdevent_accept_listenfd(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len); 980 if (-1 == cnt) { 981 switch (errno) { 982 case EAGAIN: 983 #if EWOULDBLOCK != EAGAIN 984 case EWOULDBLOCK: 985 #endif 986 case EINTR: 987 /* we were stopped _before_ we had a connection */ 988 case ECONNABORTED: /* this is a FreeBSD thingy */ 989 /* we were stopped _after_ we had a connection */ 990 break; 991 case EMFILE: 992 /* out of fds */ 993 break; 994 default: 995 log_perror(srv->errh, __FILE__, __LINE__, "accept failed"); 996 } 997 return NULL; 998 } else { 999 if (sock_addr_get_family(&cnt_addr) != AF_UNIX) { 1000 network_accept_tcp_nagle_disable(cnt); 1001 } 1002 return connection_accepted(srv, srv_socket, &cnt_addr, cnt); 1003 } 1004 } 1005 1006 1007 __attribute_cold__ 1008 static int connection_read_cq_err(connection *con) { 1009 request_st * const r = &con->request; 1010 #if defined(__WIN32) 1011 int lastError = WSAGetLastError(); 1012 switch (lastError) { 1013 case EAGAIN: 1014 return 0; 1015 case EINTR: 1016 /* we have been interrupted before we could read */ 1017 con->is_readable = 1; 1018 return 0; 1019 case ECONNRESET: 1020 /* suppress logging for this error, expected for keep-alive */ 1021 break; 1022 default: 1023 log_error(r->conf.errh, __FILE__, __LINE__, 1024 "connection closed - recv failed: %d", lastError); 1025 break; 1026 } 1027 #else /* __WIN32 */ 1028 switch (errno) { 1029 case EAGAIN: 1030 return 0; 1031 case EINTR: 1032 /* we have been interrupted before we could read */ 1033 con->is_readable = 1; 1034 return 0; 1035 case ECONNRESET: 1036 /* suppress logging for this error, expected for keep-alive */ 1037 break; 1038 default: 1039 log_perror(r->conf.errh, __FILE__, __LINE__, 1040 "connection closed - read failed"); 1041 break; 1042 } 1043 #endif /* __WIN32 */ 1044 1045 connection_set_state(r, CON_STATE_ERROR); 1046 return -1; 1047 } 1048 1049 1050 /* 0: everything ok, -1: error, -2: con closed */ 1051 static int connection_read_cq(connection *con, chunkqueue *cq, off_t max_bytes) { 1052 ssize_t len; 1053 size_t mem_len = 0; 1054 1055 do { 1056 /* obtain chunk memory into which to read 1057 * fill previous chunk if it has a reasonable amount of space available 1058 * (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz) 1059 */ 1060 chunk *ckpt = cq->last; 1061 char * const mem = chunkqueue_get_memory(cq, &mem_len); 1062 if (mem_len > (size_t)max_bytes) mem_len = (size_t)max_bytes; 1063 1064 #if defined(__WIN32) 1065 len = recv(con->fd, mem, mem_len, 0); 1066 #else 1067 len = read(con->fd, mem, mem_len); 1068 #endif 1069 1070 chunkqueue_use_memory(cq, ckpt, len > 0 ? len : 0); 1071 1072 if (len != (ssize_t)mem_len) { 1073 /* we got less then expected, wait for the next fd-event */ 1074 con->is_readable = 0; 1075 1076 if (len > 0) { 1077 con->bytes_read += len; 1078 return 0; 1079 } 1080 else if (0 == len) /* other end close connection -> KEEP-ALIVE */ 1081 return -2; /* (pipelining) */ 1082 else 1083 return connection_read_cq_err(con); 1084 } 1085 1086 con->bytes_read += len; 1087 max_bytes -= len; 1088 1089 int frd; 1090 mem_len = (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd)) 1091 ? (frd < max_bytes) ? (size_t)frd : (size_t)max_bytes 1092 : 0; 1093 } while (max_bytes); 1094 return 0; 1095 } 1096 1097 1098 static int connection_write_cq(connection *con, chunkqueue *cq, off_t max_bytes) { 1099 request_st * const r = &con->request; 1100 return con->srv->network_backend_write(con->fd,cq,max_bytes,r->conf.errh); 1101 } 1102 1103 1104 connection *connection_accepted(server *srv, server_socket *srv_socket, sock_addr *cnt_addr, int cnt) { 1105 connection *con; 1106 1107 srv->cur_fds++; 1108 1109 /* ok, we have the connection, register it */ 1110 #if 0 1111 log_error(srv->errh, __FILE__, __LINE__, "accepted() %d", cnt); 1112 #endif 1113 srv->con_opened++; 1114 1115 con = connections_get_new_connection(srv); 1116 1117 con->fd = cnt; 1118 con->fdn = fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con); 1119 con->network_read = connection_read_cq; 1120 con->network_write = connection_write_cq; 1121 1122 request_st * const r = &con->request; 1123 connection_set_state(r, CON_STATE_REQUEST_START); 1124 1125 con->connection_start = log_epoch_secs; 1126 con->dst_addr = *cnt_addr; 1127 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr))); 1128 con->srv_socket = srv_socket; 1129 con->is_ssl_sock = srv_socket->is_ssl; 1130 con->proto_default_port = 80; /* "http" */ 1131 1132 config_cond_cache_reset(r); 1133 r->conditional_is_valid = (1 << COMP_SERVER_SOCKET) 1134 | (1 << COMP_HTTP_REMOTE_IP); 1135 1136 if (HANDLER_GO_ON != plugins_call_handle_connection_accept(con)) { 1137 connection_reset(con); 1138 connection_close(con); 1139 return NULL; 1140 } 1141 if (r->http_status < 0) connection_set_state(r, CON_STATE_WRITE); 1142 return con; 1143 } 1144 1145 1146 static int connection_handle_request(request_st * const r) { 1147 const plugin *p = r->handler_module; 1148 int rc; 1149 if (NULL != p 1150 || ((rc = http_response_prepare(r)) == HANDLER_GO_ON 1151 && NULL != (p = r->handler_module))) 1152 rc = p->handle_subrequest(r, p->data); 1153 switch (rc) { 1154 case HANDLER_WAIT_FOR_EVENT: 1155 if (!r->resp_body_finished && (!r->resp_body_started || 0 == r->conf.stream_response_body)) { 1156 break; /* come back here */ 1157 } 1158 /* response headers received from backend; fall through to start response */ 1159 /* fall through */ 1160 case HANDLER_GO_ON: /*(HANDLER_FINISHED if request not handled)*/ 1161 case HANDLER_FINISHED: 1162 if (r->http_status == 0) r->http_status = 200; 1163 if (r->error_handler_saved_status > 0) { 1164 r->http_method = r->error_handler_saved_method; 1165 } 1166 if (NULL == r->handler_module || r->conf.error_intercept) { 1167 if (r->error_handler_saved_status) { 1168 const int subreq_status = r->http_status; 1169 if (r->error_handler_saved_status > 0) { 1170 r->http_status = r->error_handler_saved_status; 1171 } else if (r->http_status == 404 || r->http_status == 403) { 1172 /* error-handler-404 is a 404 */ 1173 r->http_status = -r->error_handler_saved_status; 1174 } else { 1175 /* error-handler-404 is back and has generated content */ 1176 /* if Status: was set, take it otherwise use 200 */ 1177 } 1178 if (200 <= subreq_status && subreq_status <= 299) { 1179 /*(flag value to indicate that error handler succeeded) 1180 *(for (NULL == r->handler_module))*/ 1181 r->error_handler_saved_status = 65535; /* >= 1000 */ 1182 } 1183 } else if (r->http_status >= 400) { 1184 const buffer *error_handler = NULL; 1185 if (!buffer_string_is_empty(r->conf.error_handler)) { 1186 error_handler = r->conf.error_handler; 1187 } else if ((r->http_status == 404 || r->http_status == 403) 1188 && !buffer_string_is_empty(r->conf.error_handler_404)) { 1189 error_handler = r->conf.error_handler_404; 1190 } 1191 1192 if (error_handler) { 1193 /* call error-handler */ 1194 1195 /* set REDIRECT_STATUS to save current HTTP status code 1196 * for access by dynamic handlers 1197 * https://redmine.lighttpd.net/issues/1828 */ 1198 buffer * const tb = r->tmp_buf; 1199 buffer_clear(tb); 1200 buffer_append_int(tb, r->http_status); 1201 http_header_env_set(r, CONST_STR_LEN("REDIRECT_STATUS"), CONST_BUF_LEN(tb)); 1202 1203 if (error_handler == r->conf.error_handler) { 1204 plugins_call_connection_reset(r); 1205 1206 if (r->reqbody_length) { 1207 if (r->reqbody_length != r->reqbody_queue->bytes_in) { 1208 r->keep_alive = 0; 1209 } 1210 r->reqbody_length = 0; 1211 chunkqueue_reset(r->reqbody_queue); 1212 } 1213 1214 r->con->is_writable = 1; 1215 r->resp_body_finished = 0; 1216 r->resp_body_started = 0; 1217 1218 r->error_handler_saved_status = r->http_status; 1219 r->error_handler_saved_method = r->http_method; 1220 1221 r->http_method = HTTP_METHOD_GET; 1222 } else { /*(preserve behavior for server.error-handler-404)*/ 1223 r->error_handler_saved_status = -r->http_status; /*(negative to flag old behavior)*/ 1224 } 1225 1226 if (r->http_version == HTTP_VERSION_UNSET) r->http_version = HTTP_VERSION_1_0; 1227 1228 buffer_copy_buffer(&r->target, error_handler); 1229 connection_handle_errdoc_init(r); 1230 r->http_status = 0; /*(after connection_handle_errdoc_init())*/ 1231 http_response_comeback(r); 1232 return 1; 1233 } 1234 } 1235 } 1236 1237 /* we have something to send, go on */ 1238 connection_set_state(r, CON_STATE_RESPONSE_START); 1239 break; 1240 case HANDLER_WAIT_FOR_FD: 1241 connection_fdwaitqueue_append(r->con); 1242 break; 1243 case HANDLER_COMEBACK: 1244 http_response_comeback(r); 1245 return 1; 1246 /*case HANDLER_ERROR:*/ 1247 default: 1248 /* something went wrong */ 1249 connection_set_state(r, CON_STATE_ERROR); 1250 break; 1251 } 1252 1253 return 0; 1254 } 1255 1256 1257 int connection_state_machine(connection *con) { 1258 request_st * const r = &con->request; 1259 request_state_t ostate; 1260 int rc; 1261 const int log_state_handling = r->conf.log_state_handling; 1262 1263 if (log_state_handling) { 1264 log_error(r->conf.errh, __FILE__, __LINE__, 1265 "state at enter %d %s", con->fd, connection_get_state(r->state)); 1266 } 1267 1268 do { 1269 if (log_state_handling) { 1270 log_error(r->conf.errh, __FILE__, __LINE__, 1271 "state for fd %d %s", con->fd, connection_get_state(r->state)); 1272 } 1273 1274 switch ((ostate = r->state)) { 1275 case CON_STATE_REQUEST_START: /* transient */ 1276 r->start_ts = con->read_idle_ts = log_epoch_secs; 1277 if (r->conf.high_precision_timestamps) 1278 log_clock_gettime_realtime(&r->start_hp); 1279 1280 con->request_count++; 1281 r->loops_per_request = 0; 1282 1283 connection_set_state(r, CON_STATE_READ); 1284 /* fall through */ 1285 case CON_STATE_READ: 1286 if (!connection_handle_read_state(con)) break; 1287 /*if (r->state != CON_STATE_REQUEST_END) break;*/ 1288 /* fall through */ 1289 case CON_STATE_REQUEST_END: /* transient */ 1290 ostate = (0 == r->reqbody_length) 1291 ? CON_STATE_HANDLE_REQUEST 1292 : CON_STATE_READ_POST; 1293 connection_set_state(r, ostate); 1294 /* fall through */ 1295 case CON_STATE_READ_POST: 1296 case CON_STATE_HANDLE_REQUEST: 1297 if (connection_handle_request(r)) { 1298 /* redo loop; will not match r->state */ 1299 ostate = CON_STATE_CONNECT; 1300 break; 1301 } 1302 1303 if (r->state == CON_STATE_HANDLE_REQUEST 1304 && ostate == CON_STATE_READ_POST) { 1305 ostate = CON_STATE_HANDLE_REQUEST; 1306 } 1307 1308 if (r->state != CON_STATE_RESPONSE_START) break; 1309 /* fall through */ 1310 case CON_STATE_RESPONSE_START: /* transient */ 1311 if (-1 == connection_handle_write_prepare(r)) { 1312 connection_set_state(r, CON_STATE_ERROR); 1313 break; 1314 } 1315 connection_set_state(r, CON_STATE_WRITE); 1316 /* fall through */ 1317 case CON_STATE_WRITE: 1318 connection_handle_write_state(r, con); 1319 if (r->state != CON_STATE_RESPONSE_END) break; 1320 /* fall through */ 1321 case CON_STATE_RESPONSE_END: /* transient */ 1322 case CON_STATE_ERROR: /* transient */ 1323 connection_handle_response_end_state(r, con); 1324 break; 1325 case CON_STATE_CLOSE: 1326 connection_handle_close_state(con); 1327 break; 1328 case CON_STATE_CONNECT: 1329 break; 1330 default: 1331 log_error(r->conf.errh, __FILE__, __LINE__, 1332 "unknown state: %d %d", con->fd, r->state); 1333 break; 1334 } 1335 } while (ostate != (request_state_t)r->state); 1336 1337 if (log_state_handling) { 1338 log_error(r->conf.errh, __FILE__, __LINE__, 1339 "state at exit: %d %s", con->fd, connection_get_state(r->state)); 1340 } 1341 1342 rc = 0; 1343 switch(r->state) { 1344 case CON_STATE_READ: 1345 rc = FDEVENT_IN | FDEVENT_RDHUP; 1346 break; 1347 case CON_STATE_WRITE: 1348 /* request write-fdevent only if we really need it 1349 * - if we have data to write 1350 * - if the socket is not writable yet 1351 */ 1352 if (!chunkqueue_is_empty(con->write_queue) && 1353 (con->is_writable == 0) && 1354 (con->traffic_limit_reached == 0)) { 1355 rc |= FDEVENT_OUT; 1356 } 1357 /* fall through */ 1358 case CON_STATE_READ_POST: 1359 if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) { 1360 rc |= FDEVENT_IN | FDEVENT_RDHUP; 1361 } 1362 break; 1363 case CON_STATE_CLOSE: 1364 rc = FDEVENT_IN; 1365 break; 1366 default: 1367 break; 1368 } 1369 if (con->fd >= 0) { 1370 const int events = fdevent_fdnode_interest(con->fdn); 1371 if (con->is_readable < 0) { 1372 con->is_readable = 0; 1373 rc |= FDEVENT_IN; 1374 } 1375 if (con->is_writable < 0) { 1376 con->is_writable = 0; 1377 rc |= FDEVENT_OUT; 1378 } 1379 if (events & FDEVENT_RDHUP) { 1380 rc |= FDEVENT_RDHUP; 1381 } 1382 if (rc != events) { 1383 /* update timestamps when enabling interest in events */ 1384 if ((rc & FDEVENT_IN) && !(events & FDEVENT_IN)) { 1385 con->read_idle_ts = log_epoch_secs; 1386 } 1387 if ((rc & FDEVENT_OUT) && !(events & FDEVENT_OUT)) { 1388 con->write_request_ts = log_epoch_secs; 1389 } 1390 fdevent_fdnode_event_set(con->srv->ev, con->fdn, rc); 1391 } 1392 } 1393 1394 return 0; 1395 } 1396 1397 static void connection_check_timeout (connection * const con, const time_t cur_ts) { 1398 const int waitevents = fdevent_fdnode_interest(con->fdn); 1399 int changed = 0; 1400 int t_diff; 1401 1402 request_st * const r = &con->request; 1403 if (r->state == CON_STATE_CLOSE) { 1404 if (cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) { 1405 changed = 1; 1406 } 1407 } else if (waitevents & FDEVENT_IN) { 1408 if (con->request_count == 1 || r->state != CON_STATE_READ) { 1409 /* e.g. CON_STATE_READ_POST || CON_STATE_WRITE */ 1410 if (cur_ts - con->read_idle_ts > r->conf.max_read_idle) { 1411 /* time - out */ 1412 if (r->conf.log_request_handling) { 1413 log_error(r->conf.errh, __FILE__, __LINE__, 1414 "connection closed - read timeout: %d", con->fd); 1415 } 1416 1417 connection_set_state(r, CON_STATE_ERROR); 1418 changed = 1; 1419 } 1420 } else { 1421 if (cur_ts - con->read_idle_ts > con->keep_alive_idle) { 1422 /* time - out */ 1423 if (r->conf.log_request_handling) { 1424 log_error(r->conf.errh, __FILE__, __LINE__, 1425 "connection closed - keep-alive timeout: %d", 1426 con->fd); 1427 } 1428 1429 connection_set_state(r, CON_STATE_ERROR); 1430 changed = 1; 1431 } 1432 } 1433 } 1434 1435 /* max_write_idle timeout currently functions as backend timeout, 1436 * too, after response has been started. 1437 * future: have separate backend timeout, and then change this 1438 * to check for write interest before checking for timeout */ 1439 /*if (waitevents & FDEVENT_OUT)*/ 1440 if ((r->state == CON_STATE_WRITE) && 1441 (con->write_request_ts != 0)) { 1442 #if 0 1443 if (cur_ts - con->write_request_ts > 60) { 1444 log_error(r->conf.errh, __FILE__, __LINE__, 1445 "connection closed - pre-write-request-timeout: %d %d", 1446 con->fd, cur_ts - con->write_request_ts); 1447 } 1448 #endif 1449 1450 if (cur_ts - con->write_request_ts > r->conf.max_write_idle) { 1451 /* time - out */ 1452 if (r->conf.log_timeouts) { 1453 log_error(r->conf.errh, __FILE__, __LINE__, 1454 "NOTE: a request from %.*s for %.*s timed out after writing " 1455 "%zd bytes. We waited %d seconds. If this is a problem, " 1456 "increase server.max-write-idle", 1457 BUFFER_INTLEN_PTR(con->dst_addr_buf), 1458 BUFFER_INTLEN_PTR(&r->target), 1459 con->bytes_written, (int)r->conf.max_write_idle); 1460 } 1461 connection_set_state(r, CON_STATE_ERROR); 1462 changed = 1; 1463 } 1464 } 1465 1466 if (0 == (t_diff = cur_ts - con->connection_start)) t_diff = 1; 1467 1468 if (con->traffic_limit_reached && 1469 (r->conf.bytes_per_second == 0 || 1470 con->bytes_written < (off_t)r->conf.bytes_per_second * t_diff)) { 1471 /* enable connection again */ 1472 con->traffic_limit_reached = 0; 1473 1474 changed = 1; 1475 } 1476 1477 con->bytes_written_cur_second = 0; 1478 1479 if (changed) { 1480 connection_state_machine(con); 1481 } 1482 } 1483 1484 void connection_periodic_maint (server * const srv, const time_t cur_ts) { 1485 /* check all connections for timeouts */ 1486 connections * const conns = &srv->conns; 1487 for (size_t ndx = 0; ndx < conns->used; ++ndx) { 1488 connection_check_timeout(conns->ptr[ndx], cur_ts); 1489 } 1490 } 1491 1492 void connection_graceful_shutdown_maint (server *srv) { 1493 connections * const conns = &srv->conns; 1494 for (size_t ndx = 0; ndx < conns->used; ++ndx) { 1495 connection * const con = conns->ptr[ndx]; 1496 int changed = 0; 1497 1498 request_st * const r = &con->request; 1499 if (r->state == CON_STATE_CLOSE) { 1500 /* reduce remaining linger timeout to be 1501 * (from zero) *up to* one more second, but no more */ 1502 if (HTTP_LINGER_TIMEOUT > 1) 1503 con->close_timeout_ts -= (HTTP_LINGER_TIMEOUT - 1); 1504 if (log_epoch_secs - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) 1505 changed = 1; 1506 } 1507 else if (r->state == CON_STATE_READ && con->request_count > 1 1508 && chunkqueue_is_empty(con->read_queue)) { 1509 /* close connections in keep-alive waiting for next request */ 1510 connection_set_state(r, CON_STATE_ERROR); 1511 changed = 1; 1512 } 1513 1514 r->keep_alive = 0; /* disable keep-alive */ 1515 1516 r->conf.bytes_per_second = 0; /* disable rate limit */ 1517 r->conf.global_bytes_per_second = 0; /* disable rate limit */ 1518 if (con->traffic_limit_reached) { 1519 con->traffic_limit_reached = 0; 1520 changed = 1; 1521 } 1522 1523 if (changed) { 1524 connection_state_machine(con); 1525 } 1526 } 1527 } 1528