[core] consolidate backend network write handlers
[lighttpd.git] / src / connections.c
blob985667e907b4129f3c6390882d9a67a8ac4ba185
1 #include "first.h"
3 #include "buffer.h"
4 #include "server.h"
5 #include "log.h"
6 #include "connections.h"
7 #include "fdevent.h"
9 #include "configfile.h"
10 #include "request.h"
11 #include "response.h"
12 #include "network.h"
13 #include "http_chunk.h"
14 #include "stat_cache.h"
15 #include "joblist.h"
17 #include "plugin.h"
19 #include "inet_ntop_cache.h"
21 #include <sys/stat.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
28 #ifdef HAVE_SYS_FILIO_H
29 # include <sys/filio.h>
30 #endif
32 #include "sys-socket.h"
34 typedef struct {
35 PLUGIN_DATA;
36 } plugin_data;
38 static connection *connections_get_new_connection(server *srv) {
39 connections *conns = srv->conns;
40 size_t i;
42 if (conns->size == 0) {
43 conns->size = srv->max_conns >= 128 ? 128 : srv->max_conns > 16 ? 16 : srv->max_conns;
44 conns->ptr = NULL;
45 conns->ptr = malloc(sizeof(*conns->ptr) * conns->size);
46 force_assert(NULL != conns->ptr);
47 for (i = 0; i < conns->size; i++) {
48 conns->ptr[i] = connection_init(srv);
50 } else if (conns->size == conns->used) {
51 conns->size += srv->max_conns >= 128 ? 128 : 16;
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);
60 connection_reset(srv, conns->ptr[conns->used]);
61 #if 0
62 fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
63 for (i = 0; i < conns->used + 1; i++) {
64 fprintf(stderr, "%d ", conns->ptr[i]->fd);
66 fprintf(stderr, "\n");
67 #endif
69 conns->ptr[conns->used]->ndx = conns->used;
70 return conns->ptr[conns->used++];
73 static int connection_del(server *srv, connection *con) {
74 size_t i;
75 connections *conns = srv->conns;
76 connection *temp;
78 if (con == NULL) return -1;
80 if (-1 == con->ndx) return -1;
82 buffer_reset(con->uri.authority);
83 buffer_reset(con->uri.path);
84 buffer_reset(con->uri.query);
85 buffer_reset(con->request.orig_uri);
87 i = con->ndx;
89 /* not last element */
91 if (i != conns->used - 1) {
92 temp = conns->ptr[i];
93 conns->ptr[i] = conns->ptr[conns->used - 1];
94 conns->ptr[conns->used - 1] = temp;
96 conns->ptr[i]->ndx = i;
97 conns->ptr[conns->used - 1]->ndx = -1;
100 conns->used--;
102 con->ndx = -1;
103 #if 0
104 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
105 for (i = 0; i < conns->used; i++) {
106 fprintf(stderr, "%d ", conns->ptr[i]->fd);
108 fprintf(stderr, "\n");
109 #endif
110 return 0;
113 static int connection_close(server *srv, connection *con) {
114 if (con->fd < 0) con->fd = -con->fd;
116 plugins_call_handle_connection_close(srv, con);
118 fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
119 fdevent_unregister(srv->ev, con->fd);
120 #ifdef __WIN32
121 if (closesocket(con->fd)) {
122 log_error_write(srv, __FILE__, __LINE__, "sds",
123 "(warning) close:", con->fd, strerror(errno));
125 #else
126 if (close(con->fd)) {
127 log_error_write(srv, __FILE__, __LINE__, "sds",
128 "(warning) close:", con->fd, strerror(errno));
130 #endif
131 else {
132 srv->cur_fds--;
135 if (srv->srvconf.log_state_handling) {
136 log_error_write(srv, __FILE__, __LINE__, "sd",
137 "connection closed for fd", con->fd);
139 con->fd = -1;
141 /* plugins should have cleaned themselves up */
142 for (size_t i = 0; i < srv->plugins.used; ++i) {
143 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
144 plugin_data *pd = p->data;
145 if (!pd || NULL == con->plugin_ctx[pd->id]) continue;
146 log_error_write(srv, __FILE__, __LINE__, "sb",
147 "missing cleanup in", p->name);
148 con->plugin_ctx[pd->id] = NULL;
151 connection_del(srv, con);
152 connection_set_state(srv, con, CON_STATE_CONNECT);
154 return 0;
157 static void connection_read_for_eos(server *srv, connection *con) {
158 /* we have to do the linger_on_close stuff regardless
159 * of con->keep_alive; even non-keepalive sockets may
160 * still have unread data, and closing before reading
161 * it will make the client not see all our output.
163 ssize_t len;
164 char buf[4096];
166 do {
167 len = read(con->fd, buf, sizeof(buf));
168 } while (len > 0 || (len < 0 && errno == EINTR));
170 if (len < 0 && errno == EAGAIN) return;
171 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
172 if (len < 0 && errno == EWOULDBLOCK) return;
173 #endif
175 /* 0 == len || (len < 0 && (errno is a non-recoverable error)) */
176 con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
179 static void connection_handle_close_state(server *srv, connection *con) {
180 connection_read_for_eos(srv, con);
182 if (srv->cur_ts - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
183 connection_close(srv, con);
187 static void connection_handle_shutdown(server *srv, connection *con) {
188 plugins_call_handle_connection_shut_wr(srv, con);
190 srv->con_closed++;
191 connection_reset(srv, con);
193 /* close the connection */
194 if (con->fd >= 0 && 0 == shutdown(con->fd, SHUT_WR)) {
195 con->close_timeout_ts = srv->cur_ts;
196 connection_set_state(srv, con, CON_STATE_CLOSE);
198 if (srv->srvconf.log_state_handling) {
199 log_error_write(srv, __FILE__, __LINE__, "sd",
200 "shutdown for fd", con->fd);
202 } else {
203 connection_close(srv, con);
207 static void connection_handle_response_end_state(server *srv, connection *con) {
208 /* log the request */
209 /* (even if error, connection dropped, still write to access log if http_status) */
210 if (con->http_status) {
211 plugins_call_handle_request_done(srv, con);
214 if (con->state != CON_STATE_ERROR) srv->con_written++;
216 if (con->request.content_length != con->request_content_queue->bytes_in
217 || con->state == CON_STATE_ERROR) {
218 /* request body is present and has not been read completely */
219 con->keep_alive = 0;
222 if (con->keep_alive) {
223 connection_reset(srv, con);
224 #if 0
225 con->request_start = srv->cur_ts;
226 con->read_idle_ts = srv->cur_ts;
227 #endif
228 connection_set_state(srv, con, CON_STATE_REQUEST_START);
229 } else {
230 connection_handle_shutdown(srv, con);
234 static void connection_handle_errdoc_init(server *srv, connection *con) {
235 /* modules that produce headers required with error response should
236 * typically also produce an error document. Make an exception for
237 * mod_auth WWW-Authenticate response header. */
238 buffer *www_auth = NULL;
239 if (401 == con->http_status) {
240 data_string *ds = (data_string *)array_get_element(con->response.headers, "WWW-Authenticate");
241 if (NULL != ds) {
242 www_auth = buffer_init_buffer(ds->value);
246 con->response.transfer_encoding = 0;
247 buffer_reset(con->physical.path);
248 array_reset(con->response.headers);
249 chunkqueue_reset(con->write_queue);
251 if (NULL != www_auth) {
252 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(www_auth));
253 buffer_free(www_auth);
257 static int connection_handle_write_prepare(server *srv, connection *con) {
258 if (con->mode == DIRECT) {
259 /* static files */
260 switch(con->request.http_method) {
261 case HTTP_METHOD_GET:
262 case HTTP_METHOD_POST:
263 case HTTP_METHOD_HEAD:
264 break;
265 case HTTP_METHOD_OPTIONS:
267 * 400 is coming from the request-parser BEFORE uri.path is set
268 * 403 is from the response handler when noone else catched it
270 * */
271 if ((!con->http_status || con->http_status == 200) && !buffer_string_is_empty(con->uri.path) &&
272 con->uri.path->ptr[0] != '*') {
273 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
275 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
276 con->parsed_response &= ~HTTP_CONTENT_LENGTH;
278 con->http_status = 200;
279 con->file_finished = 1;
281 chunkqueue_reset(con->write_queue);
283 break;
284 default:
285 if (0 == con->http_status) {
286 con->http_status = 501;
288 break;
292 if (con->http_status == 0) {
293 con->http_status = 403;
296 switch(con->http_status) {
297 case 204: /* class: header only */
298 case 205:
299 case 304:
300 /* disable chunked encoding again as we have no body */
301 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
302 con->parsed_response &= ~HTTP_CONTENT_LENGTH;
303 chunkqueue_reset(con->write_queue);
305 con->file_finished = 1;
306 break;
307 default: /* class: header + body */
308 /* only custom body for 4xx and 5xx */
309 if (con->http_status < 400 || con->http_status >= 600) break;
311 if (con->mode != DIRECT && (!con->conf.error_intercept || con->error_handler_saved_status)) break;
313 con->file_finished = 0;
315 connection_handle_errdoc_init(srv, con);
317 /* try to send static errorfile */
318 if (!buffer_string_is_empty(con->conf.errorfile_prefix)) {
319 stat_cache_entry *sce = NULL;
321 buffer_copy_buffer(con->physical.path, con->conf.errorfile_prefix);
322 buffer_append_int(con->physical.path, con->http_status);
323 buffer_append_string_len(con->physical.path, CONST_STR_LEN(".html"));
325 if (0 == http_chunk_append_file(srv, con, con->physical.path)) {
326 con->file_finished = 1;
327 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
328 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
333 if (!con->file_finished) {
334 buffer *b;
336 buffer_reset(con->physical.path);
338 con->file_finished = 1;
339 b = buffer_init();
341 /* build default error-page */
342 buffer_copy_string_len(b, CONST_STR_LEN(
343 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
344 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
345 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
346 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
347 " <head>\n"
348 " <title>"));
349 buffer_append_int(b, con->http_status);
350 buffer_append_string_len(b, CONST_STR_LEN(" - "));
351 buffer_append_string(b, get_http_status_name(con->http_status));
353 buffer_append_string_len(b, CONST_STR_LEN(
354 "</title>\n"
355 " </head>\n"
356 " <body>\n"
357 " <h1>"));
358 buffer_append_int(b, con->http_status);
359 buffer_append_string_len(b, CONST_STR_LEN(" - "));
360 buffer_append_string(b, get_http_status_name(con->http_status));
362 buffer_append_string_len(b, CONST_STR_LEN("</h1>\n"
363 " </body>\n"
364 "</html>\n"
367 (void)http_chunk_append_buffer(srv, con, b);
368 buffer_free(b);
370 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
372 break;
375 /* Allow filter plugins to change response headers before they are written. */
376 switch(plugins_call_handle_response_start(srv, con)) {
377 case HANDLER_GO_ON:
378 case HANDLER_FINISHED:
379 break;
380 default:
381 log_error_write(srv, __FILE__, __LINE__, "s", "response_start plugin failed");
382 return -1;
385 if (con->file_finished) {
386 /* we have all the content and chunked encoding is not used, set a content-length */
388 if (!(con->parsed_response & (HTTP_CONTENT_LENGTH|HTTP_TRANSFER_ENCODING))) {
389 off_t qlen = chunkqueue_length(con->write_queue);
392 * The Content-Length header only can be sent if we have content:
393 * - HEAD doesn't have a content-body (but have a content-length)
394 * - 1xx, 204 and 304 don't have a content-body (RFC 2616 Section 4.3)
396 * Otherwise generate a Content-Length header as chunked encoding is not
397 * available
399 if ((con->http_status >= 100 && con->http_status < 200) ||
400 con->http_status == 204 ||
401 con->http_status == 304) {
402 data_string *ds;
403 /* no Content-Body, no Content-Length */
404 if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Content-Length"))) {
405 buffer_reset(ds->value); /* Headers with empty values are ignored for output */
407 } else if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) {
408 /* qlen = 0 is important for Redirects (301, ...) as they MAY have
409 * a content. Browsers are waiting for a Content otherwise
411 buffer_copy_int(srv->tmp_buf, qlen);
413 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
416 } else {
418 * the file isn't finished yet, but we have all headers
420 * to get keep-alive we either need:
421 * - Content-Length: ... (HTTP/1.0 and HTTP/1.0) or
422 * - Transfer-Encoding: chunked (HTTP/1.1)
423 * - Upgrade: ... (lighttpd then acts as transparent proxy)
426 if (!(con->parsed_response & (HTTP_CONTENT_LENGTH|HTTP_TRANSFER_ENCODING|HTTP_UPGRADE))) {
427 if (con->request.http_version == HTTP_VERSION_1_1) {
428 off_t qlen = chunkqueue_length(con->write_queue);
429 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
430 if (qlen) {
431 /* create initial Transfer-Encoding: chunked segment */
432 buffer *b = srv->tmp_chunk_len;
433 buffer_string_set_length(b, 0);
434 buffer_append_uint_hex(b, (uintmax_t)qlen);
435 buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
436 chunkqueue_prepend_buffer(con->write_queue, b);
437 chunkqueue_append_mem(con->write_queue, CONST_STR_LEN("\r\n"));
439 response_header_append(srv, con, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked"));
440 } else {
441 con->keep_alive = 0;
446 * if the backend sent a Connection: close, follow the wish
448 * NOTE: if the backend sent Connection: Keep-Alive, but no Content-Length, we
449 * will close the connection. That's fine. We can always decide the close
450 * the connection
452 * FIXME: to be nice we should remove the Connection: ...
454 if (con->parsed_response & HTTP_CONNECTION) {
455 /* a subrequest disable keep-alive although the client wanted it */
456 if (con->keep_alive && !con->response.keep_alive) {
457 con->keep_alive = 0;
462 if (con->request.http_method == HTTP_METHOD_HEAD) {
464 * a HEAD request has the same as a GET
465 * without the content
467 con->file_finished = 1;
469 chunkqueue_reset(con->write_queue);
470 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
471 if (con->parsed_response & HTTP_TRANSFER_ENCODING) {
472 data_string *ds;
473 if (NULL != (ds = (data_string*) array_get_element(con->response.headers, "Transfer-Encoding"))) {
474 buffer_reset(ds->value); /* Headers with empty values are ignored for output */
479 http_response_write_header(srv, con);
481 return 0;
484 static int connection_handle_write(server *srv, connection *con) {
485 switch(connection_write_chunkqueue(srv, con, con->write_queue, MAX_WRITE_LIMIT)) {
486 case 0:
487 con->write_request_ts = srv->cur_ts;
488 if (con->file_finished) {
489 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
491 break;
492 case -1: /* error on our side */
493 log_error_write(srv, __FILE__, __LINE__, "sd",
494 "connection closed: write failed on fd", con->fd);
495 connection_set_state(srv, con, CON_STATE_ERROR);
496 break;
497 case -2: /* remote close */
498 connection_set_state(srv, con, CON_STATE_ERROR);
499 break;
500 case 1:
501 con->write_request_ts = srv->cur_ts;
502 con->is_writable = 0;
504 /* not finished yet -> WRITE */
505 break;
508 return 0;
513 connection *connection_init(server *srv) {
514 connection *con;
516 UNUSED(srv);
518 con = calloc(1, sizeof(*con));
519 force_assert(NULL != con);
521 con->fd = 0;
522 con->ndx = -1;
523 con->fde_ndx = -1;
524 con->bytes_written = 0;
525 con->bytes_read = 0;
526 con->bytes_header = 0;
527 con->loops_per_request = 0;
529 #define CLEAN(x) \
530 con->x = buffer_init();
532 CLEAN(request.uri);
533 CLEAN(request.request_line);
534 CLEAN(request.request);
535 CLEAN(request.pathinfo);
537 CLEAN(request.orig_uri);
539 CLEAN(uri.scheme);
540 CLEAN(uri.authority);
541 CLEAN(uri.path);
542 CLEAN(uri.path_raw);
543 CLEAN(uri.query);
545 CLEAN(physical.doc_root);
546 CLEAN(physical.path);
547 CLEAN(physical.basedir);
548 CLEAN(physical.rel_path);
549 CLEAN(physical.etag);
550 CLEAN(parse_request);
552 CLEAN(server_name);
553 CLEAN(proto);
554 CLEAN(dst_addr_buf);
556 #undef CLEAN
557 con->write_queue = chunkqueue_init();
558 con->read_queue = chunkqueue_init();
559 con->request_content_queue = chunkqueue_init();
561 con->request.headers = array_init();
562 con->response.headers = array_init();
563 con->environment = array_init();
565 /* init plugin specific connection structures */
567 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
568 force_assert(NULL != con->plugin_ctx);
570 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
571 force_assert(NULL != con->cond_cache);
572 config_setup_connection(srv, con);
574 return con;
577 void connections_free(server *srv) {
578 connections *conns = srv->conns;
579 size_t i;
581 if (NULL == conns) return;
583 for (i = 0; i < conns->size; i++) {
584 connection *con = conns->ptr[i];
586 connection_reset(srv, con);
588 chunkqueue_free(con->write_queue);
589 chunkqueue_free(con->read_queue);
590 chunkqueue_free(con->request_content_queue);
591 array_free(con->request.headers);
592 array_free(con->response.headers);
593 array_free(con->environment);
595 #define CLEAN(x) \
596 buffer_free(con->x);
598 CLEAN(request.uri);
599 CLEAN(request.request_line);
600 CLEAN(request.request);
601 CLEAN(request.pathinfo);
603 CLEAN(request.orig_uri);
605 CLEAN(uri.scheme);
606 CLEAN(uri.authority);
607 CLEAN(uri.path);
608 CLEAN(uri.path_raw);
609 CLEAN(uri.query);
611 CLEAN(physical.doc_root);
612 CLEAN(physical.path);
613 CLEAN(physical.basedir);
614 CLEAN(physical.etag);
615 CLEAN(physical.rel_path);
616 CLEAN(parse_request);
618 CLEAN(server_name);
619 CLEAN(proto);
620 CLEAN(dst_addr_buf);
621 #undef CLEAN
622 free(con->plugin_ctx);
623 free(con->cond_cache);
625 free(con);
628 free(conns->ptr);
629 free(conns);
630 srv->conns = NULL;
634 int connection_reset(server *srv, connection *con) {
635 plugins_call_connection_reset(srv, con);
637 connection_response_reset(srv, con);
638 con->is_readable = 1;
640 con->bytes_written = 0;
641 con->bytes_written_cur_second = 0;
642 con->bytes_read = 0;
643 con->bytes_header = 0;
644 con->loops_per_request = 0;
646 con->request.http_method = HTTP_METHOD_UNSET;
647 con->request.http_version = HTTP_VERSION_UNSET;
649 con->request.http_if_modified_since = NULL;
650 con->request.http_if_none_match = NULL;
652 #define CLEAN(x) \
653 if (con->x) buffer_reset(con->x);
655 CLEAN(request.uri);
656 CLEAN(request.request_line);
657 CLEAN(request.pathinfo);
658 CLEAN(request.request);
660 /* CLEAN(request.orig_uri); */
662 CLEAN(uri.scheme);
663 /* CLEAN(uri.authority); */
664 /* CLEAN(uri.path); */
665 CLEAN(uri.path_raw);
666 /* CLEAN(uri.query); */
668 CLEAN(parse_request);
670 CLEAN(server_name);
671 /*CLEAN(proto);*//* set to default in connection_accepted() */
672 #undef CLEAN
674 #define CLEAN(x) \
675 if (con->x) con->x->used = 0;
677 #undef CLEAN
679 #define CLEAN(x) \
680 con->request.x = NULL;
682 CLEAN(http_host);
683 CLEAN(http_range);
684 CLEAN(http_content_type);
685 #undef CLEAN
686 con->request.content_length = 0;
687 con->request.te_chunked = 0;
689 array_reset(con->request.headers);
690 array_reset(con->environment);
692 chunkqueue_reset(con->request_content_queue);
694 /* The cond_cache gets reset in response.c */
695 /* config_cond_cache_reset(srv, con); */
697 con->header_len = 0;
698 con->error_handler_saved_status = 0;
699 /*con->error_handler_saved_method = HTTP_METHOD_UNSET;*/
700 /*(error_handler_saved_method value is not valid unless error_handler_saved_status is set)*/
702 config_setup_connection(srv, con);
704 return 0;
708 * handle all header and content read
710 * we get called by the state-engine and by the fdevent-handler
712 static int connection_handle_read_state(server *srv, connection *con) {
713 chunk *c, *last_chunk;
714 off_t last_offset;
715 chunkqueue *cq = con->read_queue;
716 int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */
717 /* when in CON_STATE_READ: about to receive first byte for a request: */
718 int is_request_start = chunkqueue_is_empty(cq);
720 if (con->is_readable) {
721 con->read_idle_ts = srv->cur_ts;
723 switch(con->network_read(srv, con, con->read_queue, MAX_READ_LIMIT)) {
724 case -1:
725 connection_set_state(srv, con, CON_STATE_ERROR);
726 return -1;
727 case -2:
728 is_closed = 1;
729 break;
730 default:
731 break;
735 chunkqueue_remove_finished_chunks(cq);
737 /* we might have got several packets at once
740 /* update request_start timestamp when first byte of
741 * next request is received on a keep-alive connection */
742 if (con->request_count > 1 && is_request_start) {
743 con->request_start = srv->cur_ts;
744 if (con->conf.high_precision_timestamps)
745 log_clock_gettime_realtime(&con->request_start_hp);
748 /* if there is a \r\n\r\n in the chunkqueue
750 * scan the chunk-queue twice
751 * 1. to find the \r\n\r\n
752 * 2. to copy the header-packet
756 last_chunk = NULL;
757 last_offset = 0;
759 for (c = cq->first; c; c = c->next) {
760 size_t i;
761 size_t len = buffer_string_length(c->mem) - c->offset;
762 const char *b = c->mem->ptr + c->offset;
764 for (i = 0; i < len; ++i) {
765 char ch = b[i];
767 if ('\r' == ch) {
768 /* chec if \n\r\n follows */
769 size_t j = i+1;
770 chunk *cc = c;
771 const char header_end[] = "\r\n\r\n";
772 int header_end_match_pos = 1;
774 for ( ; cc; cc = cc->next, j = 0 ) {
775 size_t bblen = buffer_string_length(cc->mem) - cc->offset;
776 const char *bb = cc->mem->ptr + cc->offset;
778 for ( ; j < bblen; j++) {
779 ch = bb[j];
781 if (ch == header_end[header_end_match_pos]) {
782 header_end_match_pos++;
783 if (4 == header_end_match_pos) {
784 last_chunk = cc;
785 last_offset = j+1;
786 goto found_header_end;
788 } else {
789 goto reset_search;
793 } else if ('\n' == ch) {
794 /* check if \n follows */
795 if (i+1 < len) {
796 if (b[i+1] == '\n') {
797 last_chunk = c;
798 last_offset = i+2;
799 break;
800 } /* else goto reset_search; */
801 } else {
802 for (chunk *cc = c->next; cc; cc = cc->next) {
803 size_t bblen = buffer_string_length(cc->mem) - cc->offset;
804 const char *bb = cc->mem->ptr + cc->offset;
805 if (0 == bblen) continue;
806 if (bb[0] == '\n') {
807 last_chunk = cc;
808 last_offset = 1;
809 goto found_header_end;
810 } else {
811 goto reset_search;
816 reset_search: ;
819 found_header_end:
821 /* found */
822 if (last_chunk) {
823 buffer_reset(con->request.request);
825 for (c = cq->first; c; c = c->next) {
826 size_t len = buffer_string_length(c->mem) - c->offset;
828 if (c == last_chunk) {
829 len = last_offset;
832 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, len);
833 c->offset += len;
834 cq->bytes_out += len;
836 if (c == last_chunk) break;
839 connection_set_state(srv, con, CON_STATE_REQUEST_END);
840 } else if (is_closed) {
841 /* the connection got closed and we didn't got enough data to leave CON_STATE_READ;
842 * the only way is to leave here */
843 connection_set_state(srv, con, CON_STATE_ERROR);
846 if ((last_chunk ? buffer_string_length(con->request.request) : (size_t)chunkqueue_length(cq))
847 > srv->srvconf.max_request_field_size) {
848 log_error_write(srv, __FILE__, __LINE__, "s", "oversized request-header -> sending Status 431");
849 con->http_status = 431; /* Request Header Fields Too Large */
850 con->keep_alive = 0;
851 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
854 chunkqueue_remove_finished_chunks(cq);
856 return 0;
859 static handler_t connection_handle_fdevent(server *srv, void *context, int revents) {
860 connection *con = context;
862 joblist_append(srv, con);
864 if (con->srv_socket->is_ssl) {
865 /* ssl may read and write for both reads and writes */
866 if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
867 con->is_readable = 1;
868 con->is_writable = 1;
870 } else {
871 if (revents & FDEVENT_IN) {
872 con->is_readable = 1;
874 if (revents & FDEVENT_OUT) {
875 con->is_writable = 1;
876 /* we don't need the event twice */
881 if (con->state == CON_STATE_READ) {
882 connection_handle_read_state(srv, con);
885 if (con->state == CON_STATE_WRITE &&
886 !chunkqueue_is_empty(con->write_queue) &&
887 con->is_writable) {
889 if (-1 == connection_handle_write(srv, con)) {
890 connection_set_state(srv, con, CON_STATE_ERROR);
892 log_error_write(srv, __FILE__, __LINE__, "ds",
893 con->fd,
894 "handle write failed.");
898 if (con->state == CON_STATE_CLOSE) {
899 /* flush the read buffers */
900 connection_read_for_eos(srv, con);
904 /* attempt (above) to read data in kernel socket buffers
905 * prior to handling FDEVENT_HUP and FDEVENT_ERR */
907 if ((revents & ~(FDEVENT_IN | FDEVENT_OUT)) && con->state != CON_STATE_ERROR) {
908 if (con->state == CON_STATE_CLOSE) {
909 con->close_timeout_ts = srv->cur_ts - (HTTP_LINGER_TIMEOUT+1);
910 } else if (revents & FDEVENT_HUP) {
911 if (fdevent_is_tcp_half_closed(con->fd)) {
912 con->keep_alive = 0;
913 } else {
914 connection_set_state(srv, con, CON_STATE_ERROR);
916 } else if (revents & FDEVENT_ERR) { /* error, connection reset */
917 connection_set_state(srv, con, CON_STATE_ERROR);
918 } else {
919 log_error_write(srv, __FILE__, __LINE__, "sd",
920 "connection closed: poll() -> ???", revents);
924 return HANDLER_FINISHED;
928 connection *connection_accept(server *srv, server_socket *srv_socket) {
929 int cnt;
930 sock_addr cnt_addr;
931 size_t cnt_len = sizeof(cnt_addr); /*(size_t intentional; not socklen_t)*/
934 * check if we can still open a new connections
936 * see #1216
939 if (srv->conns->used >= srv->max_conns) {
940 return NULL;
943 cnt = fdevent_accept_listenfd(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len);
944 if (-1 == cnt) {
945 switch (errno) {
946 case EAGAIN:
947 #if EWOULDBLOCK != EAGAIN
948 case EWOULDBLOCK:
949 #endif
950 case EINTR:
951 /* we were stopped _before_ we had a connection */
952 case ECONNABORTED: /* this is a FreeBSD thingy */
953 /* we were stopped _after_ we had a connection */
954 break;
955 case EMFILE:
956 /* out of fds */
957 break;
958 default:
959 log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
961 return NULL;
962 } else {
963 if (sock_addr_get_family(&cnt_addr) != AF_UNIX) {
964 network_accept_tcp_nagle_disable(cnt);
966 return connection_accepted(srv, srv_socket, &cnt_addr, cnt);
971 /* 0: everything ok, -1: error, -2: con closed */
972 static int connection_read_cq(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
973 int len;
974 char *mem = NULL;
975 size_t mem_len = 0;
976 int toread;
977 force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
978 force_assert(max_bytes == MAX_READ_LIMIT); /*(code transform assumption; minimize diff)*/
980 /* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
981 * us more than 4kb is available
982 * if FIONREAD doesn't signal a big chunk we fill the previous buffer
983 * if it has >= 1kb free
985 if (0 != fdevent_ioctl_fionread(con->fd, S_IFSOCK, &toread) || toread <= 4096) {
986 toread = 4096;
988 else if (toread > MAX_READ_LIMIT) {
989 toread = MAX_READ_LIMIT;
991 chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, toread);
993 #if defined(__WIN32)
994 len = recv(con->fd, mem, mem_len, 0);
995 #else
996 len = read(con->fd, mem, mem_len);
997 #endif /* __WIN32 */
999 chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
1001 if (len < 0) {
1002 con->is_readable = 0;
1004 #if defined(__WIN32)
1006 int lastError = WSAGetLastError();
1007 switch (lastError) {
1008 case EAGAIN:
1009 return 0;
1010 case EINTR:
1011 /* we have been interrupted before we could read */
1012 con->is_readable = 1;
1013 return 0;
1014 case ECONNRESET:
1015 /* suppress logging for this error, expected for keep-alive */
1016 break;
1017 default:
1018 log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - recv failed: ", lastError);
1019 break;
1022 #else /* __WIN32 */
1023 switch (errno) {
1024 case EAGAIN:
1025 return 0;
1026 case EINTR:
1027 /* we have been interrupted before we could read */
1028 con->is_readable = 1;
1029 return 0;
1030 case ECONNRESET:
1031 /* suppress logging for this error, expected for keep-alive */
1032 break;
1033 default:
1034 log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
1035 break;
1037 #endif /* __WIN32 */
1039 connection_set_state(srv, con, CON_STATE_ERROR);
1041 return -1;
1042 } else if (len == 0) {
1043 con->is_readable = 0;
1044 /* the other end close the connection -> KEEP-ALIVE */
1046 /* pipelining */
1048 return -2;
1049 } else if (len != (ssize_t) mem_len) {
1050 /* we got less then expected, wait for the next fd-event */
1052 con->is_readable = 0;
1055 con->bytes_read += len;
1056 return 0;
1060 static int connection_write_cq(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
1061 return srv->network_backend_write(srv, con->fd, cq, max_bytes);
1065 connection *connection_accepted(server *srv, server_socket *srv_socket, sock_addr *cnt_addr, int cnt) {
1066 connection *con;
1068 srv->cur_fds++;
1070 /* ok, we have the connection, register it */
1071 #if 0
1072 log_error_write(srv, __FILE__, __LINE__, "sd",
1073 "appected()", cnt);
1074 #endif
1075 srv->con_opened++;
1077 con = connections_get_new_connection(srv);
1079 con->fd = cnt;
1080 con->fde_ndx = -1;
1081 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
1082 con->network_read = connection_read_cq;
1083 con->network_write = connection_write_cq;
1085 connection_set_state(srv, con, CON_STATE_REQUEST_START);
1087 con->connection_start = srv->cur_ts;
1088 con->dst_addr = *cnt_addr;
1089 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
1090 con->srv_socket = srv_socket;
1092 config_cond_cache_reset(srv, con);
1093 con->conditional_is_valid[COMP_SERVER_SOCKET] = 1;
1094 con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1;
1096 if (-1 == fdevent_fcntl_set_nb_cloexec_sock(srv->ev, con->fd)) {
1097 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
1098 connection_close(srv, con);
1099 return NULL;
1101 buffer_copy_string_len(con->proto, CONST_STR_LEN("http"));
1102 if (HANDLER_GO_ON != plugins_call_handle_connection_accept(srv, con)) {
1103 connection_close(srv, con);
1104 return NULL;
1106 return con;
1110 int connection_state_machine(server *srv, connection *con) {
1111 int done = 0, r;
1113 if (srv->srvconf.log_state_handling) {
1114 log_error_write(srv, __FILE__, __LINE__, "sds",
1115 "state at start",
1116 con->fd,
1117 connection_get_state(con->state));
1120 while (done == 0) {
1121 size_t ostate = con->state;
1123 if (srv->srvconf.log_state_handling) {
1124 log_error_write(srv, __FILE__, __LINE__, "sds",
1125 "state for fd", con->fd, connection_get_state(con->state));
1128 switch (con->state) {
1129 case CON_STATE_REQUEST_START: /* transient */
1130 con->request_start = srv->cur_ts;
1131 con->read_idle_ts = srv->cur_ts;
1132 if (con->conf.high_precision_timestamps)
1133 log_clock_gettime_realtime(&con->request_start_hp);
1135 con->request_count++;
1136 con->loops_per_request = 0;
1138 connection_set_state(srv, con, CON_STATE_READ);
1140 break;
1141 case CON_STATE_REQUEST_END: /* transient */
1142 buffer_reset(con->uri.authority);
1143 buffer_reset(con->uri.path);
1144 buffer_reset(con->uri.query);
1145 buffer_reset(con->request.orig_uri);
1147 if (http_request_parse(srv, con)) {
1148 /* we have to read some data from the POST request */
1150 connection_set_state(srv, con, CON_STATE_READ_POST);
1152 break;
1155 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
1157 break;
1158 case CON_STATE_READ_POST:
1159 case CON_STATE_HANDLE_REQUEST:
1161 * the request is parsed
1163 * decided what to do with the request
1169 switch (r = http_response_prepare(srv, con)) {
1170 case HANDLER_WAIT_FOR_EVENT:
1171 if (!con->file_finished && (!con->file_started || 0 == con->conf.stream_response_body)) {
1172 break; /* come back here */
1174 /* response headers received from backend; fall through to start response */
1175 /* fall through */
1176 case HANDLER_FINISHED:
1177 if (con->error_handler_saved_status > 0) {
1178 con->request.http_method = con->error_handler_saved_method;
1180 if (con->mode == DIRECT || con->conf.error_intercept) {
1181 if (con->error_handler_saved_status) {
1182 if (con->error_handler_saved_status > 0) {
1183 con->http_status = con->error_handler_saved_status;
1184 } else if (con->http_status == 404 || con->http_status == 403) {
1185 /* error-handler-404 is a 404 */
1186 con->http_status = -con->error_handler_saved_status;
1187 } else {
1188 /* error-handler-404 is back and has generated content */
1189 /* if Status: was set, take it otherwise use 200 */
1191 } else if (con->http_status >= 400) {
1192 buffer *error_handler = NULL;
1193 if (!buffer_string_is_empty(con->conf.error_handler)) {
1194 error_handler = con->conf.error_handler;
1195 } else if ((con->http_status == 404 || con->http_status == 403)
1196 && !buffer_string_is_empty(con->conf.error_handler_404)) {
1197 error_handler = con->conf.error_handler_404;
1200 if (error_handler) {
1201 /* call error-handler */
1203 /* set REDIRECT_STATUS to save current HTTP status code
1204 * for access by dynamic handlers
1205 * https://redmine.lighttpd.net/issues/1828 */
1206 data_string *ds;
1207 if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
1208 ds = data_string_init();
1210 buffer_copy_string_len(ds->key, CONST_STR_LEN("REDIRECT_STATUS"));
1211 buffer_append_int(ds->value, con->http_status);
1212 array_insert_unique(con->environment, (data_unset *)ds);
1214 if (error_handler == con->conf.error_handler) {
1215 plugins_call_connection_reset(srv, con);
1217 if (con->request.content_length) {
1218 if (con->request.content_length != con->request_content_queue->bytes_in) {
1219 con->keep_alive = 0;
1221 con->request.content_length = 0;
1222 chunkqueue_reset(con->request_content_queue);
1225 con->is_writable = 1;
1226 con->file_finished = 0;
1227 con->file_started = 0;
1228 con->parsed_response = 0;
1229 con->response.keep_alive = 0;
1230 con->response.content_length = -1;
1231 con->response.transfer_encoding = 0;
1233 con->error_handler_saved_status = con->http_status;
1234 con->error_handler_saved_method = con->request.http_method;
1236 con->request.http_method = HTTP_METHOD_GET;
1237 } else { /*(preserve behavior for server.error-handler-404)*/
1238 con->error_handler_saved_status = -con->http_status; /*(negative to flag old behavior)*/
1241 buffer_copy_buffer(con->request.uri, error_handler);
1242 connection_handle_errdoc_init(srv, con);
1243 con->http_status = 0; /*(after connection_handle_errdoc_init())*/
1245 done = -1;
1246 break;
1250 if (con->http_status == 0) con->http_status = 200;
1252 /* we have something to send, go on */
1253 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
1254 break;
1255 case HANDLER_WAIT_FOR_FD:
1256 srv->want_fds++;
1258 fdwaitqueue_append(srv, con);
1260 break;
1261 case HANDLER_COMEBACK:
1262 done = -1;
1263 break;
1264 case HANDLER_ERROR:
1265 /* something went wrong */
1266 connection_set_state(srv, con, CON_STATE_ERROR);
1267 break;
1268 default:
1269 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
1270 break;
1273 if (con->state == CON_STATE_HANDLE_REQUEST && ostate == CON_STATE_READ_POST) {
1274 ostate = CON_STATE_HANDLE_REQUEST;
1276 break;
1277 case CON_STATE_RESPONSE_START:
1279 * the decision is done
1280 * - create the HTTP-Response-Header
1284 if (-1 == connection_handle_write_prepare(srv, con)) {
1285 connection_set_state(srv, con, CON_STATE_ERROR);
1287 break;
1290 connection_set_state(srv, con, CON_STATE_WRITE);
1291 break;
1292 case CON_STATE_RESPONSE_END: /* transient */
1293 case CON_STATE_ERROR: /* transient */
1294 connection_handle_response_end_state(srv, con);
1295 break;
1296 case CON_STATE_CONNECT:
1297 chunkqueue_reset(con->read_queue);
1299 con->request_count = 0;
1301 break;
1302 case CON_STATE_CLOSE:
1303 connection_handle_close_state(srv, con);
1304 break;
1305 case CON_STATE_READ:
1306 connection_handle_read_state(srv, con);
1307 break;
1308 case CON_STATE_WRITE:
1309 do {
1310 /* only try to write if we have something in the queue */
1311 if (!chunkqueue_is_empty(con->write_queue)) {
1312 if (con->is_writable) {
1313 if (-1 == connection_handle_write(srv, con)) {
1314 log_error_write(srv, __FILE__, __LINE__, "ds",
1315 con->fd,
1316 "handle write failed.");
1317 connection_set_state(srv, con, CON_STATE_ERROR);
1318 break;
1320 if (con->state != CON_STATE_WRITE) break;
1322 } else if (con->file_finished) {
1323 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
1324 break;
1327 if (con->mode != DIRECT && !con->file_finished) {
1328 switch(r = plugins_call_handle_subrequest(srv, con)) {
1329 case HANDLER_WAIT_FOR_EVENT:
1330 case HANDLER_FINISHED:
1331 case HANDLER_GO_ON:
1332 break;
1333 case HANDLER_WAIT_FOR_FD:
1334 srv->want_fds++;
1335 fdwaitqueue_append(srv, con);
1336 break;
1337 case HANDLER_COMEBACK:
1338 default:
1339 log_error_write(srv, __FILE__, __LINE__, "sdd", "unexpected subrequest handler ret-value: ", con->fd, r);
1340 /* fall through */
1341 case HANDLER_ERROR:
1342 connection_set_state(srv, con, CON_STATE_ERROR);
1343 break;
1346 } while (con->state == CON_STATE_WRITE && (!chunkqueue_is_empty(con->write_queue) ? con->is_writable : con->file_finished));
1348 break;
1349 default:
1350 log_error_write(srv, __FILE__, __LINE__, "sdd",
1351 "unknown state:", con->fd, con->state);
1353 break;
1356 if (done == -1) {
1357 done = 0;
1358 } else if (ostate == con->state) {
1359 done = 1;
1363 if (srv->srvconf.log_state_handling) {
1364 log_error_write(srv, __FILE__, __LINE__, "sds",
1365 "state at exit:",
1366 con->fd,
1367 connection_get_state(con->state));
1370 r = 0;
1371 switch(con->state) {
1372 case CON_STATE_READ:
1373 case CON_STATE_CLOSE:
1374 r = FDEVENT_IN;
1375 break;
1376 case CON_STATE_WRITE:
1377 /* request write-fdevent only if we really need it
1378 * - if we have data to write
1379 * - if the socket is not writable yet
1381 if (!chunkqueue_is_empty(con->write_queue) &&
1382 (con->is_writable == 0) &&
1383 (con->traffic_limit_reached == 0)) {
1384 r |= FDEVENT_OUT;
1386 /* fall through */
1387 case CON_STATE_READ_POST:
1388 if (con->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) {
1389 r |= FDEVENT_IN;
1391 break;
1392 default:
1393 break;
1395 if (con->fd >= 0) {
1396 const int events = fdevent_event_get_interest(srv->ev, con->fd);
1397 if (con->is_readable < 0) {
1398 con->is_readable = 0;
1399 r |= FDEVENT_IN;
1401 if (con->is_writable < 0) {
1402 con->is_writable = 0;
1403 r |= FDEVENT_OUT;
1405 if (r != events) {
1406 /* update timestamps when enabling interest in events */
1407 if ((r & FDEVENT_IN) && !(events & FDEVENT_IN)) {
1408 con->read_idle_ts = srv->cur_ts;
1410 if ((r & FDEVENT_OUT) && !(events & FDEVENT_OUT)) {
1411 con->write_request_ts = srv->cur_ts;
1413 fdevent_event_set(srv->ev, &con->fde_ndx, con->fd, r);
1417 return 0;