xref: /lighttpd1.4/src/connections.c (revision 49e9f0ac)
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