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