[core] chunkqueue perf: code reuse
[lighttpd.git] / src / connections.c
blob6375e1fa135ebe90a7a9409f1abd492680d4890d
1 #include "first.h"
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"
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"
19 #include "plugin.h"
21 #include "inet_ntop_cache.h"
23 #include <sys/stat.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <string.h>
30 #ifdef HAVE_SYS_FILIO_H
31 # include <sys/filio.h>
32 #endif
34 #include "sys-socket.h"
36 typedef struct {
37 PLUGIN_DATA;
38 } plugin_data;
40 __attribute_cold__
41 static connection *connection_init(server *srv);
43 static int connection_reset(server *srv, connection *con);
46 static connection *connections_get_new_connection(server *srv) {
47 connections *conns = srv->conns;
48 size_t i;
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);
55 for (i = conns->used; i < conns->size; i++) {
56 conns->ptr[i] = connection_init(srv);
57 connection_reset(srv, conns->ptr[i]);
61 conns->ptr[conns->used]->ndx = conns->used;
62 return conns->ptr[conns->used++];
65 static int connection_del(server *srv, connection *con) {
66 size_t i;
67 connections *conns = srv->conns;
68 connection *temp;
70 if (con == NULL) return -1;
72 if (-1 == con->ndx) return -1;
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);
79 i = con->ndx;
81 /* not last element */
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;
88 conns->ptr[i]->ndx = i;
89 conns->ptr[conns->used - 1]->ndx = -1;
92 conns->used--;
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);
100 fprintf(stderr, "\n");
101 #endif
102 return 0;
105 static int connection_close(server *srv, connection *con) {
106 if (con->fd < 0) con->fd = -con->fd;
108 plugins_call_handle_connection_close(srv, con);
110 con->request_count = 0;
111 chunkqueue_reset(con->read_queue);
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));
121 #else
122 if (close(con->fd)) {
123 log_error_write(srv, __FILE__, __LINE__, "sds",
124 "(warning) close:", con->fd, strerror(errno));
126 #endif
127 else {
128 srv->cur_fds--;
131 if (srv->srvconf.log_state_handling) {
132 log_error_write(srv, __FILE__, __LINE__, "sd",
133 "connection closed for fd", con->fd);
135 con->fd = -1;
136 con->is_ssl_sock = 0;
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;
148 connection_del(srv, con);
149 connection_set_state(srv, con, CON_STATE_CONNECT);
151 return 0;
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.
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));
168 if (len < 0 && errno == EAGAIN) return;
169 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
170 if (len < 0 && errno == EWOULDBLOCK) return;
171 #endif
173 /* 0 == len || (len < 0 && (errno is a non-recoverable error)) */
174 con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
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);
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);
189 static void connection_handle_close_state(server *srv, connection *con) {
190 connection_read_for_eos(srv, con);
192 if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
193 connection_close(srv, con);
197 static void connection_handle_shutdown(server *srv, connection *con) {
198 plugins_call_handle_connection_shut_wr(srv, con);
200 srv->con_closed++;
201 connection_reset(srv, con);
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);
209 if (srv->srvconf.log_state_handling) {
210 log_error_write(srv, __FILE__, __LINE__, "sd",
211 "shutdown for fd", con->fd);
213 } else {
214 connection_close(srv, con);
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);
225 if (con->state != CON_STATE_ERROR) srv->con_written++;
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;
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);
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);
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);
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);
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:
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
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;
288 break;
289 default:
290 if (0 == con->http_status) {
291 con->http_status = 501;
293 break;
297 if (con->http_status == 0) {
298 con->http_status = 403;
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;
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;
316 con->file_finished = 0;
318 connection_handle_errdoc_init(con);
320 /* try to send static errorfile */
321 if (!buffer_string_is_empty(con->conf.errorfile_prefix)) {
322 stat_cache_entry *sce = NULL;
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"));
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));
337 if (!con->file_finished) {
338 buffer *b = srv->tmp_buf;
340 buffer_reset(con->physical.path);
342 con->file_finished = 1;
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);
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);
361 buffer_append_string_len(b, CONST_STR_LEN("</h1>\n"
362 " </body>\n"
363 "</html>\n"
366 (void)http_chunk_append_mem(srv, con, CONST_BUF_LEN(b));
368 http_header_response_set(con, HTTP_HEADER_CONTENT_TYPE, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
370 break;
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;
383 if (con->file_finished) {
384 /* we have all the content and chunked encoding is not used, set a content-length */
386 if (!(con->response.htags & (HTTP_HEADER_CONTENT_LENGTH|HTTP_HEADER_TRANSFER_ENCODING))) {
387 off_t qlen = chunkqueue_length(con->write_queue);
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)
394 * Otherwise generate a Content-Length header as chunked encoding is not
395 * available
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
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));
410 } else {
412 * the file isn't finished yet, but we have all headers
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)
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"));
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;
442 if (con->request.http_method == HTTP_METHOD_HEAD) {
444 * a HEAD request has the same as a GET
445 * without the content
447 http_response_body_clear(con, 1);
448 con->file_finished = 1;
451 http_response_write_header(srv, con);
453 return 0;
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);
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;
476 /* not finished yet -> WRITE */
477 break;
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;
489 } else if (con->file_finished) {
490 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
491 break;
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;
516 } while (con->state == CON_STATE_WRITE
517 && (!chunkqueue_is_empty(con->write_queue)
518 ? con->is_writable
519 : con->file_finished));
524 __attribute_cold__
525 static connection *connection_init(server *srv) {
526 connection *con;
528 UNUSED(srv);
530 con = calloc(1, sizeof(*con));
531 force_assert(NULL != con);
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;
540 #define CLEAN(x) \
541 con->x = buffer_init();
543 CLEAN(request.uri);
544 CLEAN(request.request);
545 CLEAN(request.pathinfo);
547 CLEAN(request.orig_uri);
549 CLEAN(uri.scheme);
550 CLEAN(uri.authority);
551 CLEAN(uri.path);
552 CLEAN(uri.path_raw);
553 CLEAN(uri.query);
555 CLEAN(physical.doc_root);
556 CLEAN(physical.path);
557 CLEAN(physical.basedir);
558 CLEAN(physical.rel_path);
559 CLEAN(physical.etag);
561 CLEAN(server_name);
562 CLEAN(proto);
563 CLEAN(dst_addr_buf);
565 #undef CLEAN
566 con->write_queue = chunkqueue_init();
567 con->read_queue = chunkqueue_init();
568 con->request_content_queue = chunkqueue_init();
570 con->request.headers = array_init();
571 con->response.headers = array_init();
572 con->environment = array_init();
574 /* init plugin specific connection structures */
576 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
577 force_assert(NULL != con->plugin_ctx);
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);
583 return con;
586 void connections_free(server *srv) {
587 connections *conns = srv->conns;
588 size_t i;
590 if (NULL == conns) return;
592 for (i = 0; i < conns->size; i++) {
593 connection *con = conns->ptr[i];
595 connection_reset(srv, con);
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);
604 #define CLEAN(x) \
605 buffer_free(con->x);
607 CLEAN(request.uri);
608 CLEAN(request.request);
609 CLEAN(request.pathinfo);
611 CLEAN(request.orig_uri);
613 CLEAN(uri.scheme);
614 CLEAN(uri.authority);
615 CLEAN(uri.path);
616 CLEAN(uri.path_raw);
617 CLEAN(uri.query);
619 CLEAN(physical.doc_root);
620 CLEAN(physical.path);
621 CLEAN(physical.basedir);
622 CLEAN(physical.etag);
623 CLEAN(physical.rel_path);
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);
632 free(con);
635 free(conns->ptr);
636 free(conns);
637 srv->conns = NULL;
641 static int connection_reset(server *srv, connection *con) {
642 plugins_call_connection_reset(srv, con);
644 connection_response_reset(srv, con);
645 con->is_readable = 1;
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;
653 con->request.http_method = HTTP_METHOD_UNSET;
654 con->request.http_version = HTTP_VERSION_UNSET;
656 #define CLEAN(x) \
657 buffer_reset(con->x);
659 CLEAN(request.uri);
660 CLEAN(request.pathinfo);
662 /* CLEAN(request.orig_uri); */
664 /* CLEAN(uri.path); */
665 CLEAN(uri.path_raw);
666 /* CLEAN(uri.query); */
667 #undef CLEAN
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);
674 con->request.http_host = NULL;
675 con->request.content_length = 0;
676 con->request.te_chunked = 0;
677 con->request.htags = 0;
679 array_reset_data_strings(con->request.headers);
680 array_reset_data_strings(con->environment);
682 chunkqueue_reset(con->request_content_queue);
684 /* The cond_cache gets reset in response.c */
685 /* config_cond_cache_reset(srv, con); */
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)*/
693 config_setup_connection(srv, con);
695 return 0;
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;
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;
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; }
721 if (n) break;
722 hlen += clen;
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);
733 if (NULL == c) return; /* incomplete request headers */
735 con->header_len = hlen;
737 buffer_clear(con->request.request);
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 if (0 == (hlen -= len)) break;
747 chunkqueue_mark_written(cq, con->header_len);
749 /* skip past \r\n or \n after previous POST request when keep-alive */
750 if (con->request_count > 1) {
751 char * const s = con->request.request->ptr;
752 #ifdef __COVERITY__
753 if (buffer_string_length(con->request.request) < 2) {
754 return;
756 #endif
757 if (s[0] == '\r' && s[1] == '\n') {
758 size_t len = buffer_string_length(con->request.request);
759 memmove(s, s+2, len-2);
760 buffer_string_set_length(con->request.request, len-2);
762 else if (s[0] == '\n') {
763 if (!(con->conf.http_parseopts & HTTP_PARSEOPT_HEADER_STRICT)) {
764 size_t len = buffer_string_length(con->request.request);
765 memmove(s, s+1, len-1);
766 buffer_string_set_length(con->request.request, len-1);
771 if (con->conf.log_request_header) {
772 log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
773 "fd:", con->fd,
774 "request-len:", buffer_string_length(con->request.request),
775 "\n", con->request.request);
778 buffer_clear(con->uri.authority);
779 buffer_reset(con->uri.path);
780 buffer_reset(con->uri.query);
781 buffer_reset(con->request.orig_uri);
783 if (srv->srvconf.log_request_header_on_error) {
784 /* copy request only if we may need to log it upon error */
785 save = buffer_init_buffer(con->request.request);
788 con->http_status = http_request_parse(srv, con, con->request.request);
789 if (0 != con->http_status) {
790 con->keep_alive = 0;
791 con->request.content_length = 0;
793 if (srv->srvconf.log_request_header_on_error) {
794 log_error_write(srv, __FILE__, __LINE__, "Sb",
795 "request-header:\n", save);
799 if (NULL != save) buffer_free(save);
800 buffer_reset(con->request.request);
802 connection_set_state(srv, con, CON_STATE_REQUEST_END);
806 * handle request header read
808 * we get called by the state-engine and by the fdevent-handler
810 static int connection_handle_read_state(server *srv, connection *con) {
811 int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */
813 if (con->request_count > 1 && 0 == con->bytes_read) {
815 /* update request_start timestamp when first byte of
816 * next request is received on a keep-alive connection */
817 con->request_start = srv->cur_ts;
818 if (con->conf.high_precision_timestamps)
819 log_clock_gettime_realtime(&con->request_start_hp);
821 if (!chunkqueue_is_empty(con->read_queue)) {
822 /*(if partially read next request and unable to read() any bytes below,
823 * then will unnecessarily scan again here before subsequent read())*/
824 connection_read_header(srv, con);
825 if (con->state != CON_STATE_READ) {
826 con->read_idle_ts = srv->cur_ts;
827 return 0;
832 if (con->is_readable) {
833 con->read_idle_ts = srv->cur_ts;
835 switch (con->network_read(srv, con, con->read_queue, MAX_READ_LIMIT)) {
836 case -1:
837 connection_set_state(srv, con, CON_STATE_ERROR);
838 return -1;
839 case -2:
840 is_closed = 1;
841 break;
842 default:
843 break;
847 connection_read_header(srv, con);
849 if (con->state == CON_STATE_READ && is_closed) {
850 /* the connection got closed and we didn't got enough data to leave CON_STATE_READ;
851 * the only way is to leave here */
852 connection_set_state(srv, con, CON_STATE_ERROR);
855 return 0;
858 static handler_t connection_handle_fdevent(server *srv, void *context, int revents) {
859 connection *con = context;
861 joblist_append(srv, con);
863 if (con->is_ssl_sock) {
864 /* ssl may read and write for both reads and writes */
865 if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
866 con->is_readable = 1;
867 con->is_writable = 1;
869 } else {
870 if (revents & FDEVENT_IN) {
871 con->is_readable = 1;
873 if (revents & FDEVENT_OUT) {
874 con->is_writable = 1;
875 /* we don't need the event twice */
880 if (con->state == CON_STATE_READ) {
881 connection_handle_read_state(srv, con);
884 if (con->state == CON_STATE_WRITE &&
885 !chunkqueue_is_empty(con->write_queue) &&
886 con->is_writable) {
887 connection_handle_write(srv, con);
890 if (con->state == CON_STATE_CLOSE) {
891 /* flush the read buffers */
892 connection_read_for_eos(srv, con);
896 /* attempt (above) to read data in kernel socket buffers
897 * prior to handling FDEVENT_HUP and FDEVENT_ERR */
899 if ((revents & ~(FDEVENT_IN | FDEVENT_OUT)) && con->state != CON_STATE_ERROR) {
900 if (con->state == CON_STATE_CLOSE) {
901 con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
902 } else if (revents & FDEVENT_HUP) {
903 connection_set_state(srv, con, CON_STATE_ERROR);
904 } else if (revents & FDEVENT_RDHUP) {
905 int events = fdevent_fdnode_interest(con->fdn);
906 events &= ~(FDEVENT_IN|FDEVENT_RDHUP);
907 con->conf.stream_request_body &= ~(FDEVENT_STREAM_REQUEST_BUFMIN|FDEVENT_STREAM_REQUEST_POLLIN);
908 con->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLRDHUP;
909 con->is_readable = 1; /*(can read 0 for end-of-stream)*/
910 if (chunkqueue_is_empty(con->read_queue)) con->keep_alive = 0;
911 if (con->request.content_length < -1) { /*(transparent proxy mode; no more data to read)*/
912 con->request.content_length = con->request_content_queue->bytes_in;
914 if (sock_addr_get_family(&con->dst_addr) == AF_UNIX) {
915 /* future: will getpeername() on AF_UNIX properly check if still connected? */
916 fdevent_fdnode_event_set(srv->ev, con->fdn, events);
917 } else if (fdevent_is_tcp_half_closed(con->fd)) {
918 /* Success of fdevent_is_tcp_half_closed() after FDEVENT_RDHUP indicates TCP FIN received,
919 * but does not distinguish between client shutdown(fd, SHUT_WR) and client close(fd).
920 * Remove FDEVENT_RDHUP so that we do not spin on the ready event.
921 * However, a later TCP RST will not be detected until next write to socket.
922 * future: might getpeername() to check for TCP RST on half-closed sockets
923 * (without FDEVENT_RDHUP interest) when checking for write timeouts
924 * once a second in server.c, though getpeername() on Windows might not indicate this */
925 con->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_TCP_FIN;
926 fdevent_fdnode_event_set(srv->ev, con->fdn, events);
927 } else {
928 /* Failure of fdevent_is_tcp_half_closed() indicates TCP RST
929 * (or unable to tell (unsupported OS), though should not
930 * be setting FDEVENT_RDHUP in that case) */
931 connection_set_state(srv, con, CON_STATE_ERROR);
933 } else if (revents & FDEVENT_ERR) { /* error, connection reset */
934 connection_set_state(srv, con, CON_STATE_ERROR);
935 } else {
936 log_error_write(srv, __FILE__, __LINE__, "sd",
937 "connection closed: poll() -> ???", revents);
941 return HANDLER_FINISHED;
945 connection *connection_accept(server *srv, server_socket *srv_socket) {
946 int cnt;
947 sock_addr cnt_addr;
948 size_t cnt_len = sizeof(cnt_addr); /*(size_t intentional; not socklen_t)*/
951 * check if we can still open a new connections
953 * see #1216
956 if (srv->conns->used >= srv->max_conns) {
957 return NULL;
960 cnt = fdevent_accept_listenfd(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len);
961 if (-1 == cnt) {
962 switch (errno) {
963 case EAGAIN:
964 #if EWOULDBLOCK != EAGAIN
965 case EWOULDBLOCK:
966 #endif
967 case EINTR:
968 /* we were stopped _before_ we had a connection */
969 case ECONNABORTED: /* this is a FreeBSD thingy */
970 /* we were stopped _after_ we had a connection */
971 break;
972 case EMFILE:
973 /* out of fds */
974 break;
975 default:
976 log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
978 return NULL;
979 } else {
980 if (sock_addr_get_family(&cnt_addr) != AF_UNIX) {
981 network_accept_tcp_nagle_disable(cnt);
983 return connection_accepted(srv, srv_socket, &cnt_addr, cnt);
988 /* 0: everything ok, -1: error, -2: con closed */
989 static int connection_read_cq(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
990 ssize_t len;
991 char *mem = NULL;
992 size_t mem_len = 0;
993 force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
994 force_assert(max_bytes == MAX_READ_LIMIT); /*(code transform assumption; minimize diff)*/
996 /* check avail data to read and obtain memory into which to read
997 * fill previous chunk if it has sufficient space
998 * (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
1001 int frd;
1002 if (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd)) {
1003 mem_len = (frd < MAX_READ_LIMIT) ? (size_t)frd : MAX_READ_LIMIT;
1006 mem = chunkqueue_get_memory(con->read_queue, &mem_len);
1008 #if defined(__WIN32)
1009 len = recv(con->fd, mem, mem_len, 0);
1010 #else
1011 len = read(con->fd, mem, mem_len);
1012 #endif /* __WIN32 */
1014 chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
1016 if (len < 0) {
1017 con->is_readable = 0;
1019 #if defined(__WIN32)
1021 int lastError = WSAGetLastError();
1022 switch (lastError) {
1023 case EAGAIN:
1024 return 0;
1025 case EINTR:
1026 /* we have been interrupted before we could read */
1027 con->is_readable = 1;
1028 return 0;
1029 case ECONNRESET:
1030 /* suppress logging for this error, expected for keep-alive */
1031 break;
1032 default:
1033 log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - recv failed: ", lastError);
1034 break;
1037 #else /* __WIN32 */
1038 switch (errno) {
1039 case EAGAIN:
1040 return 0;
1041 case EINTR:
1042 /* we have been interrupted before we could read */
1043 con->is_readable = 1;
1044 return 0;
1045 case ECONNRESET:
1046 /* suppress logging for this error, expected for keep-alive */
1047 break;
1048 default:
1049 log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
1050 break;
1052 #endif /* __WIN32 */
1054 connection_set_state(srv, con, CON_STATE_ERROR);
1056 return -1;
1057 } else if (len == 0) {
1058 con->is_readable = 0;
1059 /* the other end close the connection -> KEEP-ALIVE */
1061 /* pipelining */
1063 return -2;
1064 } else if (len != (ssize_t) mem_len) {
1065 /* we got less then expected, wait for the next fd-event */
1067 con->is_readable = 0;
1070 con->bytes_read += len;
1071 return 0;
1075 static int connection_write_cq(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
1076 return srv->network_backend_write(srv, con->fd, cq, max_bytes);
1080 connection *connection_accepted(server *srv, server_socket *srv_socket, sock_addr *cnt_addr, int cnt) {
1081 connection *con;
1083 srv->cur_fds++;
1085 /* ok, we have the connection, register it */
1086 #if 0
1087 log_error_write(srv, __FILE__, __LINE__, "sd",
1088 "appected()", cnt);
1089 #endif
1090 srv->con_opened++;
1092 con = connections_get_new_connection(srv);
1093 con->errh = srv->errh;
1095 con->fd = cnt;
1096 con->fdn = fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
1097 con->network_read = connection_read_cq;
1098 con->network_write = connection_write_cq;
1100 connection_set_state(srv, con, CON_STATE_REQUEST_START);
1102 con->connection_start = srv->cur_ts;
1103 con->dst_addr = *cnt_addr;
1104 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
1105 con->srv_socket = srv_socket;
1106 con->is_ssl_sock = srv_socket->is_ssl;
1108 config_cond_cache_reset(srv, con);
1109 con->conditional_is_valid[COMP_SERVER_SOCKET] = 1;
1110 con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1;
1112 buffer_copy_string_len(con->proto, CONST_STR_LEN("http"));
1113 if (HANDLER_GO_ON != plugins_call_handle_connection_accept(srv, con)) {
1114 connection_reset(srv, con);
1115 connection_close(srv, con);
1116 return NULL;
1118 if (con->http_status < 0) connection_set_state(srv, con, CON_STATE_WRITE);
1119 return con;
1123 static int connection_handle_request(server *srv, connection *con) {
1124 int r = http_response_prepare(srv, con);
1125 switch (r) {
1126 case HANDLER_WAIT_FOR_EVENT:
1127 if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) {
1128 break; /* come back here */
1130 /* response headers received from backend; fall through to start response */
1131 /* fall through */
1132 case HANDLER_FINISHED:
1133 if (con->http_status == 0) con->http_status = 200;
1134 if (con->error_handler_saved_status > 0) {
1135 con->request.http_method = con->error_handler_saved_method;
1137 if (con->mode == DIRECT || con->conf.error_intercept) {
1138 if (con->error_handler_saved_status) {
1139 const int subreq_status = con->http_status;
1140 if (con->error_handler_saved_status > 0) {
1141 con->http_status = con->error_handler_saved_status;
1142 } else if (con->http_status == 404 || con->http_status == 403) {
1143 /* error-handler-404 is a 404 */
1144 con->http_status = -con->error_handler_saved_status;
1145 } else {
1146 /* error-handler-404 is back and has generated content */
1147 /* if Status: was set, take it otherwise use 200 */
1149 if (200 <= subreq_status && subreq_status <= 299) {
1150 /*(flag value to indicate that error handler succeeded)
1151 *(for (con->mode == DIRECT))*/
1152 con->error_handler_saved_status = 65535; /* >= 1000 */
1154 } else if (con->http_status >= 400) {
1155 buffer *error_handler = NULL;
1156 if (!buffer_string_is_empty(con->conf.error_handler)) {
1157 error_handler = con->conf.error_handler;
1158 } else if ((con->http_status == 404 || con->http_status == 403)
1159 && !buffer_string_is_empty(con->conf.error_handler_404)) {
1160 error_handler = con->conf.error_handler_404;
1163 if (error_handler) {
1164 /* call error-handler */
1166 /* set REDIRECT_STATUS to save current HTTP status code
1167 * for access by dynamic handlers
1168 * https://redmine.lighttpd.net/issues/1828 */
1169 buffer_copy_int(srv->tmp_buf, con->http_status);
1170 http_header_env_set(con, CONST_STR_LEN("REDIRECT_STATUS"), CONST_BUF_LEN(srv->tmp_buf));
1172 if (error_handler == con->conf.error_handler) {
1173 plugins_call_connection_reset(srv, con);
1175 if (con->request.content_length) {
1176 if (con->request.content_length != con->request_content_queue->bytes_in) {
1177 con->keep_alive = 0;
1179 con->request.content_length = 0;
1180 chunkqueue_reset(con->request_content_queue);
1183 con->is_writable = 1;
1184 con->file_finished = 0;
1185 con->file_started = 0;
1187 con->error_handler_saved_status = con->http_status;
1188 con->error_handler_saved_method = con->request.http_method;
1190 con->request.http_method = HTTP_METHOD_GET;
1191 } else { /*(preserve behavior for server.error-handler-404)*/
1192 con->error_handler_saved_status = -con->http_status; /*(negative to flag old behavior)*/
1195 if (con->request.http_version == HTTP_VERSION_UNSET) con->request.http_version = HTTP_VERSION_1_0;
1197 buffer_copy_buffer(con->request.uri, error_handler);
1198 connection_handle_errdoc_init(con);
1199 con->http_status = 0; /*(after connection_handle_errdoc_init())*/
1201 return 1;
1206 /* we have something to send, go on */
1207 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
1208 break;
1209 case HANDLER_WAIT_FOR_FD:
1210 srv->want_fds++;
1212 fdwaitqueue_append(srv, con);
1214 break;
1215 case HANDLER_COMEBACK:
1216 return 1;
1217 case HANDLER_ERROR:
1218 /* something went wrong */
1219 connection_set_state(srv, con, CON_STATE_ERROR);
1220 break;
1221 default:
1222 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
1223 break;
1226 return 0;
1230 int connection_state_machine(server *srv, connection *con) {
1231 connection_state_t ostate;
1232 int r;
1233 const int log_state_handling = srv->srvconf.log_state_handling;
1235 if (log_state_handling) {
1236 log_error_write(srv, __FILE__, __LINE__, "sds",
1237 "state at enter",
1238 con->fd,
1239 connection_get_state(con->state));
1242 do {
1243 if (log_state_handling) {
1244 log_error_write(srv, __FILE__, __LINE__, "sds",
1245 "state for fd", con->fd, connection_get_state(con->state));
1248 switch ((ostate = con->state)) {
1249 case CON_STATE_REQUEST_START: /* transient */
1250 con->request_start = srv->cur_ts;
1251 con->read_idle_ts = srv->cur_ts;
1252 if (con->conf.high_precision_timestamps)
1253 log_clock_gettime_realtime(&con->request_start_hp);
1255 con->request_count++;
1256 con->loops_per_request = 0;
1258 connection_set_state(srv, con, CON_STATE_READ);
1259 /* fall through */
1260 case CON_STATE_READ:
1261 connection_handle_read_state(srv, con);
1262 if (con->state != CON_STATE_REQUEST_END) break;
1263 /* fall through */
1264 case CON_STATE_REQUEST_END: /* transient */
1265 ostate = (0 == con->request.content_length)
1266 ? CON_STATE_HANDLE_REQUEST
1267 : CON_STATE_READ_POST;
1268 connection_set_state(srv, con, ostate);
1269 /* fall through */
1270 case CON_STATE_READ_POST:
1271 case CON_STATE_HANDLE_REQUEST:
1272 if (connection_handle_request(srv, con)) {
1273 /* redo loop; will not match con->state */
1274 ostate = CON_STATE_CONNECT;
1275 break;
1278 if (con->state == CON_STATE_HANDLE_REQUEST
1279 && ostate == CON_STATE_READ_POST) {
1280 ostate = CON_STATE_HANDLE_REQUEST;
1283 if (con->state != CON_STATE_RESPONSE_START) break;
1284 /* fall through */
1285 case CON_STATE_RESPONSE_START: /* transient */
1286 if (-1 == connection_handle_write_prepare(srv, con)) {
1287 connection_set_state(srv, con, CON_STATE_ERROR);
1288 break;
1290 connection_set_state(srv, con, CON_STATE_WRITE);
1291 /* fall through */
1292 case CON_STATE_WRITE:
1293 connection_handle_write_state(srv, con);
1294 if (con->state != CON_STATE_RESPONSE_END) break;
1295 /* fall through */
1296 case CON_STATE_RESPONSE_END: /* transient */
1297 case CON_STATE_ERROR: /* transient */
1298 connection_handle_response_end_state(srv, con);
1299 break;
1300 case CON_STATE_CLOSE:
1301 connection_handle_close_state(srv, con);
1302 break;
1303 case CON_STATE_CONNECT:
1304 break;
1305 default:
1306 log_error_write(srv, __FILE__, __LINE__, "sdd",
1307 "unknown state:", con->fd, con->state);
1308 break;
1310 } while (ostate != con->state);
1312 if (log_state_handling) {
1313 log_error_write(srv, __FILE__, __LINE__, "sds",
1314 "state at exit:",
1315 con->fd,
1316 connection_get_state(con->state));
1319 r = 0;
1320 switch(con->state) {
1321 case CON_STATE_READ:
1322 r = FDEVENT_IN | FDEVENT_RDHUP;
1323 break;
1324 case CON_STATE_WRITE:
1325 /* request write-fdevent only if we really need it
1326 * - if we have data to write
1327 * - if the socket is not writable yet
1329 if (!chunkqueue_is_empty(con->write_queue) &&
1330 (con->is_writable == 0) &&
1331 (con->traffic_limit_reached == 0)) {
1332 r |= FDEVENT_OUT;
1334 /* fall through */
1335 case CON_STATE_READ_POST:
1336 if (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) {
1337 r |= FDEVENT_IN | FDEVENT_RDHUP;
1339 break;
1340 case CON_STATE_CLOSE:
1341 r = FDEVENT_IN;
1342 break;
1343 default:
1344 break;
1346 if (con->fd >= 0) {
1347 const int events = fdevent_fdnode_interest(con->fdn);
1348 if (con->is_readable < 0) {
1349 con->is_readable = 0;
1350 r |= FDEVENT_IN;
1352 if (con->is_writable < 0) {
1353 con->is_writable = 0;
1354 r |= FDEVENT_OUT;
1356 if (events & FDEVENT_RDHUP) {
1357 r |= FDEVENT_RDHUP;
1359 if (r != events) {
1360 /* update timestamps when enabling interest in events */
1361 if ((r & FDEVENT_IN) && !(events & FDEVENT_IN)) {
1362 con->read_idle_ts = srv->cur_ts;
1364 if ((r & FDEVENT_OUT) && !(events & FDEVENT_OUT)) {
1365 con->write_request_ts = srv->cur_ts;
1367 fdevent_fdnode_event_set(srv->ev, con->fdn, r);
1371 return 0;