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