xref: /lighttpd1.4/src/connections.c (revision 2e0edb85)
1 #include "first.h"
2 
3 #include "base.h"
4 #include "buffer.h"
5 #include "burl.h"       /* HTTP_PARSEOPT_HEADER_STRICT */
6 #include "chunk.h"
7 #include "log.h"
8 #include "connections.h"
9 #include "fdevent.h"
10 #include "h2.h"
11 #include "http_header.h"
12 
13 #include "reqpool.h"
14 #include "request.h"
15 #include "response.h"
16 #include "network.h"
17 #include "stat_cache.h"
18 
19 #include "plugin.h"
20 
21 #include "sock_addr_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 #include "sys-socket.h"
31 
32 #define HTTP_LINGER_TIMEOUT 5
33 
34 #define connection_set_state(r, n) ((r)->state = (n))
35 
36 __attribute_cold__
37 static void connection_set_state_error(request_st * const r, const request_state_t state) {
38     connection_set_state(r, state);
39 }
40 
41 __attribute_cold__
42 static connection *connection_init(server *srv);
43 
44 static void connection_reset(connection *con);
45 
46 static connection *connections_get_new_connection(server *srv) {
47     connection *con;
48     --srv->lim_conns;
49     if (srv->conns_pool) {
50         con = srv->conns_pool;
51         srv->conns_pool = con->next;
52     }
53     else {
54         con = connection_init(srv);
55         connection_reset(con);
56     }
57     /*con->prev = NULL;*//*(already set)*/
58     if ((con->next = srv->conns))
59         con->next->prev = con;
60     return (srv->conns = con);
61 }
62 
63 static void connection_del(server *srv, connection *con) {
64     if (con->next)
65         con->next->prev = con->prev;
66     if (con->prev)
67         con->prev->next = con->next;
68     else
69         srv->conns = con->next;
70     con->prev = NULL;
71     con->next = srv->conns_pool;
72     srv->conns_pool = con;
73     ++srv->lim_conns;
74 }
75 
76 static void connection_close(connection *con) {
77 	if (con->fd < 0) con->fd = -con->fd;
78 
79 	plugins_call_handle_connection_close(con);
80 
81 	server * const srv = con->srv;
82 	request_st * const r = &con->request;
83 	request_reset_ex(r); /*(r->conf.* is still valid below)*/
84 	connection_set_state(r, CON_STATE_CONNECT);
85 
86 	chunkqueue_reset(con->read_queue);
87 	con->request_count = 0;
88 	con->is_ssl_sock = 0;
89 	con->revents_err = 0;
90 
91 	fdevent_fdnode_event_del(srv->ev, con->fdn);
92 	fdevent_unregister(srv->ev, con->fd);
93 	con->fdn = NULL;
94 #ifdef __WIN32
95 	if (0 == closesocket(con->fd))
96 #else
97 	if (0 == close(con->fd))
98 #endif
99 		--srv->cur_fds;
100 	else
101 		log_perror(r->conf.errh, __FILE__, __LINE__,
102 		  "(warning) close: %d", con->fd);
103 
104 	if (r->conf.log_state_handling) {
105 		log_error(r->conf.errh, __FILE__, __LINE__,
106 		  "connection closed for fd %d", con->fd);
107 	}
108 	con->fd = -1;
109 
110 	connection_del(srv, con);
111 }
112 
113 static void connection_read_for_eos_plain(connection * const con) {
114 	/* we have to do the linger_on_close stuff regardless
115 	 * of r->keep_alive; even non-keepalive sockets
116 	 * may still have unread data, and closing before reading
117 	 * it will make the client not see all our output.
118 	 */
119 	ssize_t len;
120 	const int type = sock_addr_get_family(&con->dst_addr);
121 	char buf[16384];
122 	do {
123 		len = fdevent_socket_read_discard(con->fd, buf, sizeof(buf),
124 						  type, SOCK_STREAM);
125 	} while (len > 0 || (len < 0 && errno == EINTR));
126 
127 	if (len < 0 && errno == EAGAIN) return;
128       #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
129 	if (len < 0 && errno == EWOULDBLOCK) return;
130       #endif
131 
132 	/* 0 == len || (len < 0 && (errno is a non-recoverable error)) */
133 		con->close_timeout_ts = log_monotonic_secs - (HTTP_LINGER_TIMEOUT+1);
134 }
135 
136 static void connection_read_for_eos_ssl(connection * const con) {
137 	if (con->network_read(con, con->read_queue, MAX_READ_LIMIT) < 0)
138 		con->close_timeout_ts = log_monotonic_secs - (HTTP_LINGER_TIMEOUT+1);
139 	chunkqueue_reset(con->read_queue);
140 }
141 
142 static void connection_read_for_eos(connection * const con) {
143 	!con->is_ssl_sock
144 	  ? connection_read_for_eos_plain(con)
145 	  : connection_read_for_eos_ssl(con);
146 }
147 
148 static void connection_handle_close_state(connection *con) {
149 	connection_read_for_eos(con);
150 
151 	if (log_monotonic_secs - con->close_timeout_ts > HTTP_LINGER_TIMEOUT) {
152 		connection_close(con);
153 	}
154 }
155 
156 static void connection_handle_shutdown(connection *con) {
157 	plugins_call_handle_connection_shut_wr(con);
158 
159 	connection_reset(con);
160 	++con->srv->con_closed;
161 
162 	/* close the connection */
163 	if (con->fd >= 0
164 	    && (con->is_ssl_sock || 0 == shutdown(con->fd, SHUT_WR))) {
165 		con->close_timeout_ts = log_monotonic_secs;
166 
167 		request_st * const r = &con->request;
168 		connection_set_state(r, CON_STATE_CLOSE);
169 		if (r->conf.log_state_handling) {
170 			log_error(r->conf.errh, __FILE__, __LINE__,
171 			  "shutdown for fd %d", con->fd);
172 		}
173 	} else {
174 		connection_close(con);
175 	}
176 }
177 
178 
179 static void connection_handle_response_end_state(request_st * const r, connection * const con) {
180 	if (r->http_version > HTTP_VERSION_1_1) {
181 		h2_retire_con(r, con);
182 		r->keep_alive = 0;
183 		/* set a status so that mod_accesslog, mod_rrdtool hooks are called
184 		 * in plugins_call_handle_request_done() (XXX: or set to 0 to omit) */
185 		r->http_status = 100; /* XXX: what if con->state == CON_STATE_ERROR? */
186 	}
187 
188 	/* call request_done hook if http_status set (e.g. to log request) */
189 	/* (even if error, connection dropped, as long as http_status is set) */
190 	if (r->http_status) plugins_call_handle_request_done(r);
191 
192 	if (r->state != CON_STATE_ERROR) ++con->srv->con_written;
193 
194 	if (r->reqbody_length != r->reqbody_queue.bytes_in
195 	    || r->state == CON_STATE_ERROR) {
196 		/* request body may not have been read completely */
197 		r->keep_alive = 0;
198 		/* clean up failed partial write of 1xx intermediate responses*/
199 		if (&r->write_queue != con->write_queue) { /*(for HTTP/1.1)*/
200 			chunkqueue_free(con->write_queue);
201 			con->write_queue = &r->write_queue;
202 		}
203 	}
204 
205         if (r->keep_alive > 0) {
206 		request_reset(r);
207 		con->is_readable = 1; /* potentially trigger optimistic read */
208 		/*(accounting used by mod_accesslog for HTTP/1.0 and HTTP/1.1)*/
209 		r->bytes_read_ckpt = con->bytes_read;
210 		r->bytes_written_ckpt = con->bytes_written;
211 #if 0
212 		r->start_hp.tv_sec = log_epoch_secs;
213 		con->read_idle_ts = log_monotonic_secs;
214 #endif
215 		connection_set_state(r, CON_STATE_REQUEST_START);
216 	} else {
217 		connection_handle_shutdown(con);
218 	}
219 }
220 
221 
222 __attribute_pure__
223 static off_t
224 connection_write_throttled (const connection * const con, off_t max_bytes)
225 {
226     const request_config * const restrict rconf = &con->request.conf;
227     if (0 == rconf->global_bytes_per_second && 0 == rconf->bytes_per_second)
228         return max_bytes;
229 
230     if (rconf->global_bytes_per_second) {
231         off_t limit = (off_t)rconf->global_bytes_per_second
232                     - *(rconf->global_bytes_per_second_cnt_ptr);
233         if (max_bytes > limit)
234             max_bytes = limit;
235     }
236 
237     if (rconf->bytes_per_second) {
238         off_t limit = (off_t)rconf->bytes_per_second
239                     - con->bytes_written_cur_second;
240         if (max_bytes > limit)
241             max_bytes = limit;
242     }
243 
244     return max_bytes > 0 ? max_bytes : 0; /*(0 == reached traffic limit)*/
245 }
246 
247 
248 static off_t
249 connection_write_throttle (connection * const con, off_t max_bytes)
250 {
251     /*assert(max_bytes > 0);*/
252     max_bytes = connection_write_throttled(con, max_bytes);
253     if (0 == max_bytes) con->traffic_limit_reached = 1;
254     return max_bytes;
255 }
256 
257 
258 static int
259 connection_write_chunkqueue (connection * const con, chunkqueue * const restrict cq, off_t max_bytes)
260 {
261     /*assert(!chunkqueue_is_empty(cq));*//* checked by callers */
262 
263     con->write_request_ts = log_monotonic_secs;
264 
265     max_bytes = connection_write_throttle(con, max_bytes);
266     if (0 == max_bytes) return 1;
267 
268     off_t written = cq->bytes_out;
269     int ret;
270 
271   #ifdef TCP_CORK
272     int corked = 0;
273   #endif
274 
275     /* walk chunkqueue up to first FILE_CHUNK (if present)
276      * This may incur memory load misses for pointer chasing, but effectively
277      * preloads part of the chunkqueue, something which used to be a side effect
278      * of a previous (less efficient) version of chunkqueue_length() which
279      * walked the entire chunkqueue (on each and every call).  The loads here
280      * make a measurable difference in performance in underlying call to
281      * con->network_write() */
282     if (cq->first->next && cq->first->type == MEM_CHUNK) {
283         const chunk *c = cq->first;
284         do { c = c->next; } while (c && c->type == MEM_CHUNK);
285       #ifdef TCP_CORK
286         /* Linux: put a cork into socket as we want to combine write() calls
287          * but only if we really have multiple chunks including non-MEM_CHUNK
288          * (or if multiple chunks and TLS), and only if TCP socket */
289         if (NULL != c || (max_bytes > 16384 && con->is_ssl_sock)) {
290             const int sa_family = sock_addr_get_family(&con->srv_socket->addr);
291             if (sa_family == AF_INET || sa_family == AF_INET6) {
292                 corked = 1;
293                 (void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK,
294                                  &corked, sizeof(corked));
295             }
296         }
297       #endif
298     }
299 
300     ret = con->network_write(con, cq, max_bytes);
301     if (ret >= 0) {
302         ret = chunkqueue_is_empty(cq) ? 0 : 1;
303     }
304 
305   #ifdef TCP_CORK
306     if (corked) {
307         corked = 0;
308         (void)setsockopt(con->fd, IPPROTO_TCP, TCP_CORK,
309                          &corked, sizeof(corked));
310     }
311   #endif
312 
313     written = cq->bytes_out - written;
314     con->bytes_written += written;
315     con->bytes_written_cur_second += written;
316     request_st * const r = &con->request;
317     if (r->conf.global_bytes_per_second_cnt_ptr)
318         *(r->conf.global_bytes_per_second_cnt_ptr) += written;
319 
320     return ret;
321 }
322 
323 
324 static int
325 connection_write_1xx_info (request_st * const r, connection * const con)
326 {
327     /* (Note: prior 1xx intermediate responses may be present in cq) */
328     /* (Note: also choosing not to update con->write_request_ts
329      *  which differs from connection_write_chunkqueue()) */
330     chunkqueue * const cq = con->write_queue;
331     off_t written = cq->bytes_out;
332 
333     int rc = con->network_write(con, cq, MAX_WRITE_LIMIT);
334 
335     written = cq->bytes_out - written;
336     con->bytes_written += written;
337     con->bytes_written_cur_second += written;
338     if (r->conf.global_bytes_per_second_cnt_ptr)
339         *(r->conf.global_bytes_per_second_cnt_ptr) += written;
340 
341     if (rc < 0) {
342         connection_set_state_error(r, CON_STATE_ERROR);
343         return 0; /* error */
344     }
345 
346     if (!chunkqueue_is_empty(cq)) { /* partial write (unlikely) */
347         con->is_writable = 0;
348         if (cq == &r->write_queue) {
349             /* save partial write of 1xx in separate chunkqueue
350              * Note: sending of remainder of 1xx might be delayed
351              * until next set of response headers are sent */
352             con->write_queue = chunkqueue_init(NULL);
353             chunkqueue_append_chunkqueue(con->write_queue, cq);
354         }
355     }
356 
357   #if 0
358     /* XXX: accounting inconsistency
359      * 1xx is not currently included in r->resp_header_len,
360      * so mod_accesslog reporting of %b or %B (FORMAT_BYTES_OUT_NO_HEADER)
361      * reports all bytes out minus len of final response headers,
362      * but including 1xx intermediate responses.  If 1xx intermediate
363      * responses were included in r->resp_header_len, then there are a
364      * few places in the code which must be adjusted to use r->resp_header_done
365      * instead of (0 == r->resp_header_len) as flag that final response was set
366      * (Doing the following would "discard" the 1xx len from bytes_out)
367      */
368     r->write_queue.bytes_in = r->write_queue.bytes_out = 0;
369   #endif
370 
371     return 1; /* success */
372 }
373 
374 
375 int
376 connection_send_1xx (request_st * const r, connection * const con)
377 {
378     /* Make best effort to send HTTP/1.1 1xx intermediate */
379     /* (Note: if other modules set response headers *before* the
380      *  handle_response_start hook, and the backends subsequently sends 1xx,
381      *  then the response headers are sent here with 1xx and might be cleared
382      *  by caller (http_response_parse_headers() and http_response_check_1xx()),
383      *  instead of being sent with the final response.
384      *  (e.g. mod_magnet setting response headers, then backend sending 103)) */
385 
386     chunkqueue * const cq = con->write_queue; /*(bypass r->write_queue)*/
387 
388     buffer * const b = chunkqueue_append_buffer_open(cq);
389     buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 "));
390     http_status_append(b, r->http_status);
391     for (uint32_t i = 0; i < r->resp_headers.used; ++i) {
392         const data_string * const ds = (data_string *)r->resp_headers.data[i];
393         const uint32_t klen = buffer_clen(&ds->key);
394         const uint32_t vlen = buffer_clen(&ds->value);
395         if (0 == klen || 0 == vlen) continue;
396         buffer_append_str2(b, CONST_STR_LEN("\r\n"), ds->key.ptr, klen);
397         buffer_append_str2(b, CONST_STR_LEN(": "), ds->value.ptr, vlen);
398     }
399     buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
400     chunkqueue_append_buffer_commit(cq);
401 
402     if (con->traffic_limit_reached)
403         return 1; /* success; send later if throttled */
404 
405     return connection_write_1xx_info(r, con);
406 }
407 
408 
409 static int
410 connection_write_100_continue (request_st * const r, connection * const con)
411 {
412     /* Make best effort to send "HTTP/1.1 100 Continue" */
413     static const char http_100_continue[] = "HTTP/1.1 100 Continue\r\n\r\n";
414 
415     if (con->traffic_limit_reached)
416         return 1; /* success; skip sending if throttled */
417 
418     chunkqueue * const cq = con->write_queue; /*(bypass r->write_queue)*/
419     chunkqueue_append_mem(cq, http_100_continue, sizeof(http_100_continue)-1);
420     return connection_write_1xx_info(r, con);
421 }
422 
423 
424 static int connection_handle_write(request_st * const r, connection * const con) {
425 	/*assert(!chunkqueue_is_empty(cq));*//* checked by callers */
426 
427 	if (con->is_writable <= 0) return CON_STATE_WRITE;
428 	int rc = connection_write_chunkqueue(con, con->write_queue, MAX_WRITE_LIMIT);
429 	switch (rc) {
430 	case 0:
431 		if (r->resp_body_finished) {
432 			connection_set_state(r, CON_STATE_RESPONSE_END);
433 			return CON_STATE_RESPONSE_END;
434 		}
435 		break;
436 	case -1: /* error on our side */
437 		log_error(r->conf.errh, __FILE__, __LINE__,
438 		  "connection closed: write failed on fd %d", con->fd);
439 		connection_set_state_error(r, CON_STATE_ERROR);
440 		return CON_STATE_ERROR;
441 	case -2: /* remote close */
442 		connection_set_state_error(r, CON_STATE_ERROR);
443 		return CON_STATE_ERROR;
444 	case 1:
445 		/* do not spin trying to send HTTP/2 server Connection Preface
446 		 * while waiting for TLS negotiation to complete */
447 		if (con->write_queue->bytes_out)
448 			con->is_writable = 0;
449 
450 		/* not finished yet -> WRITE */
451 		break;
452 	}
453 
454 	return CON_STATE_WRITE; /*(state did not change)*/
455 }
456 
457 static int connection_handle_write_state(request_st * const r, connection * const con) {
458     do {
459         /* only try to write if we have something in the queue */
460         if (!chunkqueue_is_empty(&r->write_queue)) {
461             if (r->http_version <= HTTP_VERSION_1_1) {
462                 int rc = connection_handle_write(r, con);
463                 if (rc != CON_STATE_WRITE) return rc;
464             }
465         } else if (r->resp_body_finished) {
466             connection_set_state(r, CON_STATE_RESPONSE_END);
467             return CON_STATE_RESPONSE_END;
468         }
469 
470         if (r->handler_module && !r->resp_body_finished) {
471             const plugin * const p = r->handler_module;
472             int rc = p->handle_subrequest(r, p->data);
473             switch(rc) {
474             case HANDLER_WAIT_FOR_EVENT:
475             case HANDLER_FINISHED:
476             case HANDLER_GO_ON:
477                 break;
478             case HANDLER_COMEBACK:
479             default:
480                 log_error(r->conf.errh, __FILE__, __LINE__,
481                   "unexpected subrequest handler ret-value: %d %d",
482                   con->fd, rc);
483                 __attribute_fallthrough__
484             case HANDLER_ERROR:
485                 connection_set_state_error(r, CON_STATE_ERROR);
486                 return CON_STATE_ERROR;
487             }
488         }
489     } while (r->http_version <= HTTP_VERSION_1_1
490              && (!chunkqueue_is_empty(&r->write_queue)
491                  ? con->is_writable > 0 && 0 == con->traffic_limit_reached
492                  : r->resp_body_finished));
493 
494     return CON_STATE_WRITE;
495 }
496 
497 
498 __attribute_cold__
499 static connection *connection_init(server *srv) {
500 	connection * const con = calloc(1, sizeof(*con));
501 	force_assert(NULL != con);
502 
503 	con->srv = srv;
504 	con->plugin_slots = srv->plugin_slots;
505 	con->config_data_base = srv->config_data_base;
506 
507 	request_st * const r = &con->request;
508 	request_init_data(r, con, srv);
509 	con->write_queue = &r->write_queue;
510 	con->read_queue = &r->read_queue;
511 
512 	/* init plugin-specific per-connection structures */
513 	con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
514 	force_assert(NULL != con->plugin_ctx);
515 
516 	return con;
517 }
518 
519 
520 static void connection_free(connection * const con) {
521     request_st * const r = &con->request;
522 
523     connection_reset(con);
524     if (con->write_queue != &r->write_queue)
525         chunkqueue_free(con->write_queue);
526     if (con->read_queue != &r->read_queue)
527         chunkqueue_free(con->read_queue);
528     request_free_data(r);
529 
530     free(con->plugin_ctx);
531     free(con->dst_addr_buf.ptr);
532     free(con);
533 }
534 
535 void connections_pool_clear(server * const srv) {
536     connection *con;
537     while ((con = srv->conns_pool)) {
538         srv->conns_pool = con->next;
539         connection_free(con);
540     }
541 }
542 
543 void connections_free(server *srv) {
544     connections_pool_clear(srv);
545 
546     connection *con;
547     while ((con = srv->conns)) {
548         srv->conns = con->next;
549         connection_free(con);
550     }
551 }
552 
553 
554 static void connection_reset(connection *con) {
555 	request_st * const r = &con->request;
556 	request_reset(r);
557 	r->bytes_read_ckpt = 0;
558 	r->bytes_written_ckpt = 0;
559 	con->is_readable = 1;
560 
561 	con->bytes_written = 0;
562 	con->bytes_written_cur_second = 0;
563 	con->bytes_read = 0;
564 }
565 
566 
567 __attribute_cold__
568 static chunk *
569 connection_discard_blank_line (chunkqueue * const cq, uint32_t header_len)
570 {
571     /*(separate func only to be able to mark with compiler hint as cold)*/
572     chunkqueue_mark_written(cq, header_len);
573     return cq->first; /* refresh c after chunkqueue_mark_written() */
574 }
575 
576 
577 static chunk * connection_read_header_more(connection *con, chunkqueue *cq, chunk *c, const size_t olen) {
578     /*(should not be reached by HTTP/2 streams)*/
579     /*if (r->http_version == HTTP_VERSION_2) return NULL;*/
580     /*(However, new connections over TLS may become HTTP/2 connections via ALPN
581      * and return from this routine with r->http_version == HTTP_VERSION_2) */
582 
583     if ((NULL == c || NULL == c->next) && con->is_readable > 0) {
584         con->read_idle_ts = log_monotonic_secs;
585         if (0 != con->network_read(con, cq, MAX_READ_LIMIT)) {
586             request_st * const r = &con->request;
587             connection_set_state_error(r, CON_STATE_ERROR);
588         }
589         /* check if switched to HTTP/2 (ALPN "h2" during TLS negotiation) */
590         request_st * const r = &con->request;
591         if (r->http_version == HTTP_VERSION_2) return NULL;
592     }
593 
594     if (cq->first != cq->last && 0 != olen) {
595         const size_t clen = chunkqueue_length(cq);
596         size_t block = (olen + (16384-1)) & ~(16384-1);
597         block += (block - olen > 1024 ? 0 : 16384);
598         chunkqueue_compact_mem(cq, block > clen ? clen : block);
599     }
600 
601     /* detect if data is added to chunk */
602     c = cq->first;
603     return (c && (size_t)c->offset + olen < buffer_clen(c->mem))
604       ? c
605       : NULL;
606 }
607 
608 
609 static void
610 connection_transition_h2 (request_st * const h2r, connection * const con)
611 {
612     buffer_copy_string_len(&h2r->target,      CONST_STR_LEN("*"));
613     buffer_copy_string_len(&h2r->target_orig, CONST_STR_LEN("*"));
614     buffer_copy_string_len(&h2r->uri.path,    CONST_STR_LEN("*"));
615     h2r->http_method = HTTP_METHOD_PRI;
616     h2r->reqbody_length = -1; /*(unnecessary for h2r?)*/
617     h2r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN;
618 
619     /* (h2r->state == CON_STATE_READ) for transition by ALPN
620      *   or starting cleartext HTTP/2 with Prior Knowledge
621      *   (e.g. via HTTP Alternative Services)
622      * (h2r->state == CON_STATE_RESPONSE_END) for Upgrade: h2c */
623 
624     if (h2r->state != CON_STATE_ERROR)
625         connection_set_state(h2r, CON_STATE_WRITE);
626 
627   #if 0 /* ... if it turns out we need a separate fdevent handler for HTTP/2 */
628     con->fdn->handler = connection_handle_fdevent_h2;
629   #endif
630 
631     if (NULL == con->h2) /*(not yet transitioned to HTTP/2; not Upgrade: h2c)*/
632         h2_init_con(h2r, con, NULL);
633 }
634 
635 
636 /**
637  * handle request header read
638  *
639  * we get called by the state-engine and by the fdevent-handler
640  */
641 __attribute_noinline__
642 static int connection_handle_read_state(connection * const con)  {
643     /*(should not be reached by HTTP/2 streams)*/
644     chunkqueue * const cq = con->read_queue;
645     chunk *c = cq->first;
646     uint32_t clen = 0;
647     uint32_t header_len = 0;
648     request_st * const r = &con->request;
649     uint8_t keepalive_request_start = 0;
650     uint8_t pipelined_request_start = 0;
651     uint8_t discard_blank = 0;
652     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
653 
654     if (con->request_count > 1) {
655         discard_blank = 1;
656         if (con->bytes_read == r->bytes_read_ckpt) {
657             keepalive_request_start = 1;
658             if (NULL != c) { /* !chunkqueue_is_empty(cq)) */
659                 pipelined_request_start = 1;
660                 /* partial header of next request has already been read,
661                  * so optimistically check for more data received on
662                  * socket while processing the previous request */
663                 con->is_readable = 1;
664                 /*(if partially read next request and unable to read any bytes,
665                  * then will unnecessarily scan again before subsequent read)*/
666             }
667         }
668     }
669 
670     do {
671         if (NULL == c) continue;
672         clen = buffer_clen(c->mem) - c->offset;
673         if (0 == clen) continue;
674         if (__builtin_expect( (c->offset > USHRT_MAX), 0)) /*(highly unlikely)*/
675             chunkqueue_compact_mem_offset(cq);
676 
677         hoff[0] = 1;                         /* number of lines */
678         hoff[1] = (unsigned short)c->offset; /* base offset for all lines */
679         /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
680 
681         header_len = http_header_parse_hoff(c->mem->ptr + c->offset,clen,hoff);
682 
683         /* casting to (unsigned short) might truncate, and the hoff[]
684          * addition might overflow, but max_request_field_size is USHRT_MAX,
685          * so failure will be detected below */
686         const uint32_t max_request_field_size = r->conf.max_request_field_size;
687         if ((header_len ? header_len : clen) > max_request_field_size
688             || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1) {
689             log_error(r->conf.errh, __FILE__, __LINE__, "%s",
690                       "oversized request-header -> sending Status 431");
691             r->http_status = 431; /* Request Header Fields Too Large */
692             r->keep_alive = 0;
693             connection_set_state(r, CON_STATE_REQUEST_END);
694             return 1;
695         }
696 
697         if (__builtin_expect( (0 != header_len), 1)) {
698             if (__builtin_expect( (hoff[0] > 1), 1))
699                 break; /* common case; request headers complete */
700 
701             if (discard_blank) { /* skip one blank line e.g. following POST */
702                 if (header_len == clen) continue;
703                 const int ch = c->mem->ptr[c->offset+header_len];
704                 if (ch != '\r' && ch != '\n') {
705                     /* discard prior blank line if next line is not blank */
706                     discard_blank = 0;
707                     clen = 0;/*(for connection_read_header_more() to return c)*/
708                     c = connection_discard_blank_line(cq, header_len);/*cold*/
709                     continue;
710                 } /*(else fall through to error out in next block)*/
711             }
712         }
713 
714         if (((unsigned char *)c->mem->ptr)[c->offset] < 32) {
715             /* expecting ASCII method beginning with alpha char
716              * or HTTP/2 pseudo-header beginning with ':' */
717             /*(TLS handshake begins with SYN 0x16 (decimal 22))*/
718             log_error(r->conf.errh, __FILE__, __LINE__, "%s (%s)",
719                       c->mem->ptr[c->offset] == 0x16
720                       ? "unexpected TLS ClientHello on clear port"
721                       : "invalid request-line -> sending Status 400",
722                       con->dst_addr_buf.ptr);
723             r->http_status = 400; /* Bad Request */
724             r->keep_alive = 0;
725             connection_set_state(r, CON_STATE_REQUEST_END);
726             return 1;
727         }
728     } while ((c = connection_read_header_more(con, cq, c, clen)));
729 
730     if (keepalive_request_start) {
731         if (con->bytes_read > r->bytes_read_ckpt) {
732             /* update r->start_hp.tv_sec timestamp when first byte of
733              * next request is received on a keep-alive connection */
734             r->start_hp.tv_sec = log_epoch_secs;
735             if (r->conf.high_precision_timestamps)
736                 log_clock_gettime_realtime(&r->start_hp);
737         }
738         if (pipelined_request_start && c)
739             con->read_idle_ts = log_monotonic_secs;
740     }
741 
742     if (NULL == c) return 0; /* incomplete request headers */
743 
744   #ifdef __COVERITY__
745     if (buffer_clen(c->mem) < hoff[1]) {
746         return 1;
747     }
748   #endif
749 
750     char * const hdrs = c->mem->ptr + hoff[1];
751 
752     if (con->request_count > 1) {
753         /* clear buffers which may have been kept for reporting on keep-alive,
754          * (e.g. mod_status) */
755         request_reset_ex(r);
756     }
757     /* RFC7540 3.5 HTTP/2 Connection Preface
758      * "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
759      * (Connection Preface MUST be exact match)
760      * If ALT-SVC used to advertise HTTP/2, then client might start
761      * http connection (not TLS) sending HTTP/2 connection preface.
762      * (note: intentionally checking only on initial request) */
763     else if (!con->is_ssl_sock && r->conf.h2proto
764              && hoff[0] == 2 && hoff[2] == 16
765              && hdrs[0]=='P' && hdrs[1]=='R' && hdrs[2]=='I' && hdrs[3]==' ') {
766         r->http_version = HTTP_VERSION_2;
767         return 0;
768     }
769 
770     r->rqst_header_len = header_len;
771     if (r->conf.log_request_header)
772         log_error_multiline(r->conf.errh, __FILE__, __LINE__,
773                             hdrs, header_len, "fd:%d rqst: ", con->fd);
774     http_request_headers_process(r, hdrs, hoff, con->proto_default_port);
775     chunkqueue_mark_written(cq, r->rqst_header_len);
776     connection_set_state(r, CON_STATE_REQUEST_END);
777 
778     if (light_btst(r->rqst_htags, HTTP_HEADER_UPGRADE)
779         && 0 == r->http_status
780         && h2_check_con_upgrade_h2c(r)) {
781         /*(Upgrade: h2c over cleartext does not have SNI; no COMP_HTTP_HOST)*/
782         r->conditional_is_valid = (1 << COMP_SERVER_SOCKET)
783                                 | (1 << COMP_HTTP_REMOTE_IP);
784         /*connection_handle_write(r, con);*//* defer write to network */
785         return 0;
786     }
787 
788     return 1;
789 }
790 
791 
792 static handler_t connection_handle_fdevent(void * const context, const int revents) {
793     connection * restrict con = context;
794     const int is_ssl_sock = con->is_ssl_sock;
795 
796     joblist_append(con);
797 
798     if (revents & ~(FDEVENT_IN | FDEVENT_OUT))
799         con->revents_err |= (revents & ~(FDEVENT_IN | FDEVENT_OUT));
800 
801     if (revents & (FDEVENT_IN | FDEVENT_OUT)) {
802         if (is_ssl_sock) /*(ssl may read and write for both reads and writes)*/
803             con->is_readable = con->is_writable = 1;
804         else {
805             if (revents & FDEVENT_IN)
806                 con->is_readable = 1;
807             if (revents & FDEVENT_OUT)
808                 con->is_writable = 1;
809         }
810     }
811 
812     return HANDLER_FINISHED;
813 }
814 
815 
816 __attribute_cold__
817 static int connection_read_cq_err(connection *con) {
818     request_st * const r = &con->request;
819   #if defined(__WIN32)
820     int lastError = WSAGetLastError();
821     switch (lastError) {
822     case EAGAIN:
823         return 0;
824     case EINTR:
825         /* we have been interrupted before we could read */
826         con->is_readable = 1;
827         return 0;
828     case ECONNRESET:
829         /* suppress logging for this error, expected for keep-alive */
830         break;
831     default:
832         log_error(r->conf.errh, __FILE__, __LINE__,
833           "connection closed - recv failed: %d", lastError);
834         break;
835     }
836   #else /* __WIN32 */
837     switch (errno) {
838     case EAGAIN:
839         return 0;
840     case EINTR:
841         /* we have been interrupted before we could read */
842         con->is_readable = 1;
843         return 0;
844     case ECONNRESET:
845         /* suppress logging for this error, expected for keep-alive */
846         break;
847     default:
848         log_perror(r->conf.errh, __FILE__, __LINE__,
849           "connection closed - read failed");
850         break;
851     }
852   #endif /* __WIN32 */
853 
854     connection_set_state_error(r, CON_STATE_ERROR);
855     return -1;
856 }
857 
858 
859 /* 0: everything ok, -1: error, -2: con closed */
860 static int connection_read_cq(connection *con, chunkqueue *cq, off_t max_bytes) {
861     ssize_t len;
862     size_t mem_len = 0;
863 
864     do {
865         /* obtain chunk memory into which to read
866          * fill previous chunk if it has a reasonable amount of space available
867          * (use mem_len=0 to obtain large buffer at least half of chunk_buf_sz)
868          */
869         chunk *ckpt = cq->last;
870         char * const mem = chunkqueue_get_memory(cq, &mem_len);
871         if (mem_len > (size_t)max_bytes) mem_len = (size_t)max_bytes;
872 
873       #if defined(__WIN32)
874         len = recv(con->fd, mem, mem_len, 0);
875       #else
876         len = read(con->fd, mem, mem_len);
877       #endif
878 
879         chunkqueue_use_memory(cq, ckpt, len > 0 ? len : 0);
880 
881         if (len != (ssize_t)mem_len) {
882             /* we got less then expected, wait for the next fd-event */
883             con->is_readable = 0;
884 
885             if (len > 0) {
886                 con->bytes_read += len;
887                 return 0;
888             }
889             else if (0 == len) /* other end close connection -> KEEP-ALIVE */
890                 return -2;     /* (pipelining) */
891             else
892                 return connection_read_cq_err(con);
893         }
894 
895         con->bytes_read += len;
896         max_bytes -= len;
897 
898         int frd;
899         mem_len = (0 == fdevent_ioctl_fionread(con->fd, S_IFSOCK, &frd))
900           ? (frd < max_bytes) ? (size_t)frd : (size_t)max_bytes
901           : 0;
902     } while (max_bytes);
903     return 0;
904 }
905 
906 
907 static int connection_write_cq(connection *con, chunkqueue *cq, off_t max_bytes) {
908     request_st * const r = &con->request;
909     return con->srv->network_backend_write(con->fd,cq,max_bytes,r->conf.errh);
910 }
911 
912 
913 static handler_t connection_handle_read_post_state(request_st * const r);
914 
915 connection *connection_accepted(server *srv, const server_socket *srv_socket, sock_addr *cnt_addr, int cnt) {
916 		connection *con;
917 
918 		srv->cur_fds++;
919 
920 		/* ok, we have the connection, register it */
921 #if 0
922 		log_error(srv->errh, __FILE__, __LINE__, "accepted() %d", cnt);
923 #endif
924 		srv->con_opened++;
925 
926 		con = connections_get_new_connection(srv);
927 
928 		con->fd = cnt;
929 		con->fdn = fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
930 		con->network_read = connection_read_cq;
931 		con->network_write = connection_write_cq;
932 		con->reqbody_read = connection_handle_read_post_state;
933 
934 		request_st * const r = &con->request;
935 		connection_set_state(r, CON_STATE_REQUEST_START);
936 
937 		con->connection_start = log_monotonic_secs;
938 		con->dst_addr = *cnt_addr;
939 		sock_addr_cache_inet_ntop_copy_buffer(&con->dst_addr_buf,
940 		                                      &con->dst_addr);
941 		con->srv_socket = srv_socket;
942 		con->is_ssl_sock = srv_socket->is_ssl;
943 		con->proto_default_port = 80; /* "http" */
944 
945 		config_cond_cache_reset(r);
946 		r->conditional_is_valid = (1 << COMP_SERVER_SOCKET)
947 		                        | (1 << COMP_HTTP_REMOTE_IP);
948 
949 		if (HANDLER_GO_ON != plugins_call_handle_connection_accept(con)) {
950 			connection_reset(con);
951 			connection_close(con);
952 			return NULL;
953 		}
954 		if (r->http_status < 0) connection_set_state(r, CON_STATE_WRITE);
955 		return con;
956 }
957 
958 
959 __attribute_cold__
960 __attribute_noinline__
961 static const char *
962 connection_get_state (request_state_t state)
963 {
964     switch (state) {
965       case CON_STATE_CONNECT:        return "connect";
966       case CON_STATE_READ:           return "read";
967       case CON_STATE_READ_POST:      return "readpost";
968       case CON_STATE_WRITE:          return "write";
969       case CON_STATE_CLOSE:          return "close";
970       case CON_STATE_ERROR:          return "error";
971       case CON_STATE_HANDLE_REQUEST: return "handle-req";
972       case CON_STATE_REQUEST_START:  return "req-start";
973       case CON_STATE_REQUEST_END:    return "req-end";
974       case CON_STATE_RESPONSE_START: return "resp-start";
975       case CON_STATE_RESPONSE_END:   return "resp-end";
976       default:                       return "(unknown)";
977     }
978 }
979 
980 
981 static void connection_state_machine_h2 (request_st *h2r, connection *con);
982 
983 
984 static void
985 connection_state_machine_loop (request_st * const r, connection * const con)
986 {
987 	request_state_t ostate;
988 	do {
989 		if (r->conf.log_state_handling) {
990 			log_error(r->conf.errh, __FILE__, __LINE__,
991 			  "state for fd:%d id:%d %s", con->fd, r->h2id,
992 			  connection_get_state(r->state));
993 		}
994 
995 		switch ((ostate = r->state)) {
996 		case CON_STATE_REQUEST_START: /* transient */
997 			/*(should not be reached by HTTP/2 streams)*/
998 			r->start_hp.tv_sec = log_epoch_secs;
999 			con->read_idle_ts = log_monotonic_secs;
1000 			if (r->conf.high_precision_timestamps)
1001 				log_clock_gettime_realtime(&r->start_hp);
1002 
1003 			con->request_count++;
1004 			r->loops_per_request = 0;
1005 
1006 			connection_set_state(r, CON_STATE_READ);
1007 			__attribute_fallthrough__
1008 		case CON_STATE_READ:
1009 			/*(should not be reached by HTTP/2 streams)*/
1010 			if (!connection_handle_read_state(con)) {
1011 				if (r->http_version == HTTP_VERSION_2) {
1012 					connection_transition_h2(r, con);
1013 					connection_state_machine_h2(r, con);
1014 					return;
1015 				}
1016 				break;
1017 			}
1018 			/*if (r->state != CON_STATE_REQUEST_END) break;*/
1019 			__attribute_fallthrough__
1020 		case CON_STATE_REQUEST_END: /* transient */
1021 			ostate = (0 == r->reqbody_length)
1022 			  ? CON_STATE_HANDLE_REQUEST
1023 			  : CON_STATE_READ_POST;
1024 			connection_set_state(r, ostate);
1025 			__attribute_fallthrough__
1026 		case CON_STATE_READ_POST:
1027 		case CON_STATE_HANDLE_REQUEST:
1028 			switch (http_response_handler(r)) {
1029 			  case HANDLER_GO_ON:/*CON_STATE_RESPONSE_START occurred;transient*/
1030 			  case HANDLER_FINISHED:
1031 				break;
1032 			  case HANDLER_WAIT_FOR_EVENT:
1033 				return;
1034 			  case HANDLER_COMEBACK:
1035 				/* redo loop; will not match r->state */
1036 				ostate = CON_STATE_CONNECT;
1037 				continue;
1038 			  /*case HANDLER_ERROR:*/
1039 			  default:
1040 				connection_set_state_error(r, CON_STATE_ERROR);
1041 				continue;
1042 			}
1043 			/*__attribute_fallthrough__*/
1044 		/*case CON_STATE_RESPONSE_START:*//*occurred;transient*/
1045 			if (r->http_version > HTTP_VERSION_1_1)
1046 				h2_send_headers(r, con);
1047 			else
1048 				http_response_write_header(r);
1049 			connection_set_state(r, CON_STATE_WRITE);
1050 			__attribute_fallthrough__
1051 		case CON_STATE_WRITE:
1052 			if (connection_handle_write_state(r, con)
1053 			    != CON_STATE_RESPONSE_END)
1054 				break;
1055 			__attribute_fallthrough__
1056 		case CON_STATE_RESPONSE_END: /* transient */
1057 		case CON_STATE_ERROR:        /* transient */
1058 			if (r->http_version > HTTP_VERSION_1_1 && r != &con->request)
1059 				return;
1060 			connection_handle_response_end_state(r, con);
1061 			break;
1062 		case CON_STATE_CLOSE:
1063 			/*(should not be reached by HTTP/2 streams)*/
1064 			connection_handle_close_state(con);
1065 			break;
1066 		case CON_STATE_CONNECT:
1067 			break;
1068 		default:
1069 			log_error(r->conf.errh, __FILE__, __LINE__,
1070 			  "unknown state: %d %d", con->fd, r->state);
1071 			break;
1072 		}
1073 	} while (ostate != (request_state_t)r->state);
1074 }
1075 
1076 
1077 __attribute_cold__
1078 static void
1079 connection_revents_err (request_st * const r, connection * const con)
1080 {
1081     /* defer handling FDEVENT_HUP and FDEVENT_ERR to here in order to
1082      * first attempt (in callers) to read data in kernel socket buffers */
1083     /*assert(con->revents_err & ~(FDEVENT_IN | FDEVENT_OUT));*/
1084     const int revents = (int)con->revents_err;
1085     con->revents_err = 0;
1086 
1087     if (r->state == CON_STATE_CLOSE)
1088         con->close_timeout_ts = log_monotonic_secs - (HTTP_LINGER_TIMEOUT+1);
1089     else if (revents & FDEVENT_HUP)
1090         connection_set_state_error(r, CON_STATE_ERROR);
1091     else if (revents & FDEVENT_RDHUP) {
1092         int events = fdevent_fdnode_interest(con->fdn);
1093         events &= ~(FDEVENT_IN|FDEVENT_RDHUP);
1094         r->conf.stream_request_body &=
1095           ~(FDEVENT_STREAM_REQUEST_BUFMIN|FDEVENT_STREAM_REQUEST_POLLIN);
1096         r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLRDHUP;
1097         con->is_readable = 1; /*(can read 0 for end-of-stream)*/
1098         if (chunkqueue_is_empty(con->read_queue)) r->keep_alive = 0;
1099         if (r->reqbody_length < -1)/*(transparent proxy mode; no more rd data)*/
1100             r->reqbody_length = r->reqbody_queue.bytes_in;
1101         if (sock_addr_get_family(&con->dst_addr) == AF_UNIX) {
1102             /* future: will getpeername() on AF_UNIX check if still connected?*/
1103             fdevent_fdnode_event_set(con->srv->ev, con->fdn, events);
1104         }
1105         else if (fdevent_is_tcp_half_closed(con->fd)) {
1106             /* Success of fdevent_is_tcp_half_closed() after FDEVENT_RDHUP
1107              * indicates TCP FIN received, but does not distinguish between
1108              * client shutdown(fd, SHUT_WR) and client close(fd).  Remove
1109              * FDEVENT_RDHUP so that we do not spin on ready event.  However,
1110              * a later TCP RST will not be detected until next write to socket.
1111              * future: might getpeername() to check for TCP RST on half-closed
1112              * sockets (without FDEVENT_RDHUP interest) when checking for write
1113              * timeouts once a second in server.c, though getpeername() on
1114              * Windows might not indicate this */
1115             r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_TCP_FIN;
1116             fdevent_fdnode_event_set(con->srv->ev, con->fdn, events);
1117         }
1118         else {
1119             /* Failure of fdevent_is_tcp_half_closed() indicates TCP RST
1120              * (or unable to tell (unsupported OS), though should not
1121              * be setting FDEVENT_RDHUP in that case) */
1122             connection_set_state_error(r, CON_STATE_ERROR);
1123         }
1124     }
1125     else if (revents & FDEVENT_ERR)  /* error, connection reset */
1126         connection_set_state_error(r, CON_STATE_ERROR);
1127     else
1128         log_error(r->conf.errh, __FILE__, __LINE__,
1129           "connection closed: poll() -> ??? %d", revents);
1130 }
1131 
1132 
1133 static void
1134 connection_set_fdevent_interest (request_st * const r, connection * const con)
1135 {
1136     if (con->fd < 0) return;
1137 
1138     if (con->revents_err && r->state != CON_STATE_ERROR) {
1139         connection_revents_err(r, con); /* resets con->revents_err = 0 */
1140         connection_state_machine(con);
1141         return;
1142         /* connection_state_machine() will end up calling back into
1143          * connection_set_fdevent_interest(), but with 0 == con->revents_err */
1144     }
1145 
1146     int n = 0;
1147     switch(r->state) {
1148       case CON_STATE_READ:
1149         n = FDEVENT_IN;
1150         if (!(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLRDHUP))
1151             n |= FDEVENT_RDHUP;
1152         break;
1153       case CON_STATE_WRITE:
1154         if (!chunkqueue_is_empty(con->write_queue)
1155             && 0 == con->is_writable && 0 == con->traffic_limit_reached)
1156             n |= FDEVENT_OUT;
1157         __attribute_fallthrough__
1158       case CON_STATE_READ_POST:
1159         if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN)
1160             n |= FDEVENT_IN;
1161         if (!(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLRDHUP))
1162             n |= FDEVENT_RDHUP;
1163         break;
1164       case CON_STATE_CLOSE:
1165         n = FDEVENT_IN;
1166         break;
1167       case CON_STATE_CONNECT:
1168         return;
1169       default:
1170         break;
1171     }
1172 
1173     const int events = fdevent_fdnode_interest(con->fdn);
1174     if (con->is_readable < 0) {
1175         con->is_readable = 0;
1176         n |= FDEVENT_IN;
1177     }
1178     if (con->is_writable < 0) {
1179         con->is_writable = 0;
1180         n |= FDEVENT_OUT;
1181     }
1182     if (events & FDEVENT_RDHUP)
1183         n |= FDEVENT_RDHUP;
1184 
1185     if (n == events) return;
1186 
1187     /* update timestamps when enabling interest in events */
1188     if ((n & FDEVENT_IN) && !(events & FDEVENT_IN))
1189         con->read_idle_ts = log_monotonic_secs;
1190     if ((n & FDEVENT_OUT) && !(events & FDEVENT_OUT))
1191         con->write_request_ts = log_monotonic_secs;
1192     fdevent_fdnode_event_set(con->srv->ev, con->fdn, n);
1193 }
1194 
1195 
1196 __attribute_cold__
1197 static void
1198 connection_request_end_h2 (request_st * const h2r, connection * const con)
1199 {
1200     if (h2r->keep_alive >= 0) {
1201         h2r->keep_alive = -1;
1202         h2_send_goaway(con, H2_E_NO_ERROR);
1203     }
1204     else /*(abort connection upon second request to close h2 connection)*/
1205         h2_send_goaway(con, H2_E_ENHANCE_YOUR_CALM);
1206 }
1207 
1208 
1209 static void
1210 connection_state_machine_h2 (request_st * const h2r, connection * const con)
1211 {
1212     h2con * const h2c = con->h2;
1213 
1214     if (h2c->sent_goaway <= 0
1215         && (chunkqueue_is_empty(con->read_queue) || h2_parse_frames(con))
1216         && con->is_readable > 0) {
1217         chunkqueue * const cq = con->read_queue;
1218         const off_t mark = cq->bytes_in;
1219         if (0 == con->network_read(con, cq, MAX_READ_LIMIT)) {
1220             if (mark < cq->bytes_in)
1221                 h2_parse_frames(con);
1222         }
1223         else {
1224             /* network error; do not send GOAWAY, but pretend that we did */
1225             h2c->sent_goaway = H2_E_CONNECT_ERROR; /*any error (not NO_ERROR)*/
1226             connection_set_state_error(h2r, CON_STATE_ERROR);
1227         }
1228     }
1229 
1230     /* process requests on HTTP/2 streams */
1231     int resched = 0;
1232     if (h2c->sent_goaway <= 0 && h2c->rused) {
1233         /* coarse check for write throttling
1234          * (connection.kbytes-per-second, server.kbytes-per-second)
1235          * obtain an approximate limit, not refreshed per request_st,
1236          * even though we are not calculating response HEADERS frames
1237          * or frame overhead here */
1238         off_t max_bytes = con->is_writable > 0
1239           ? connection_write_throttle(con, MAX_WRITE_LIMIT)
1240           : 0;
1241         const off_t cqlen = chunkqueue_length(con->write_queue);
1242         if (cqlen > 8192 && max_bytes > 65536) max_bytes = 65536;
1243         max_bytes -= cqlen;
1244         if (max_bytes < 0) max_bytes = 0;
1245 
1246         /* XXX: to avoid buffer bloat due to staging too much data in
1247          * con->write_queue, consider setting limit on how much is staged
1248          * for sending on con->write_queue: adjusting max_bytes down */
1249 
1250         /* XXX: TODO: process requests in stream priority order */
1251         for (uint32_t i = 0; i < h2c->rused; ++i) {
1252             request_st * const r = h2c->r[i];
1253             /* future: might track read/write interest per request
1254              * to avoid iterating through all active requests */
1255 
1256           #if 0
1257             const int log_state_handling = r->conf.log_state_handling;
1258             if (log_state_handling)
1259                 log_error(r->conf.errh, __FILE__, __LINE__,
1260                   "state at enter %d %d %s", con->fd, r->h2id,
1261                   connection_get_state(r->state));
1262           #endif
1263 
1264             connection_state_machine_loop(r, con);
1265 
1266             if (r->resp_header_len && !chunkqueue_is_empty(&r->write_queue)
1267                 && max_bytes
1268                 && (r->resp_body_finished
1269                     || (r->conf.stream_response_body
1270                         & (FDEVENT_STREAM_RESPONSE
1271                           |FDEVENT_STREAM_RESPONSE_BUFMIN)))) {
1272 
1273                 uint32_t dlen = max_bytes > 32768 ? 32768 : (uint32_t)max_bytes;
1274                 dlen = h2_send_cqdata(r, con, &r->write_queue, dlen);
1275                 if (dlen) { /*(do not resched (spin) if swin empty window)*/
1276                     max_bytes -= (off_t)dlen;
1277                     if (!chunkqueue_is_empty(&r->write_queue))
1278                         resched |= 1;
1279                 }
1280             }
1281 
1282             {
1283                 if (chunkqueue_is_empty(&r->write_queue)) {
1284                     if (r->resp_body_finished && r->state == CON_STATE_WRITE) {
1285                         connection_set_state(r, CON_STATE_RESPONSE_END);
1286                         if (__builtin_expect( (r->conf.log_state_handling), 0))
1287                             connection_state_machine_loop(r, con);
1288                     }
1289                 }
1290             }
1291 
1292           #if 0
1293             if (log_state_handling)
1294                 log_error(r->conf.errh, __FILE__, __LINE__,
1295                   "state at exit %d %d %s", con->fd, r->h2id,
1296                   connection_get_state(r->state));
1297           #endif
1298 
1299             if (r->state==CON_STATE_RESPONSE_END || r->state==CON_STATE_ERROR) {
1300                 /*(trigger reschedule of con if frames pending)*/
1301                 if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r)
1302                     && !chunkqueue_is_empty(con->read_queue))
1303                     resched |= 2;
1304                 h2_send_end_stream(r, con);
1305                 const int alive = r->keep_alive;
1306                 h2_retire_stream(r, con);/*r invalidated;removed from h2c->r[]*/
1307                 --i;/* adjust loop i; h2c->rused was modified to retire r */
1308                 /*(special-case: allow *stream* to set r->keep_alive = -1 to
1309                  * trigger goaway on h2 connection, e.g. after mod_auth failure
1310                  * in attempt to mitigate brute force attacks by forcing a
1311                  * reconnect and (somewhat) slowing down retries)*/
1312                 if (alive < 0)
1313                     connection_request_end_h2(h2r, con);
1314             }
1315         }
1316 
1317         if (0 == max_bytes) resched |= 1;
1318     }
1319 
1320     if (h2c->sent_goaway > 0 && h2c->rused) {
1321         /* retire streams if an error has occurred
1322          * note: this is not done to other streams in the loop above
1323          * (besides the current stream in the loop) due to the specific
1324          * implementation above, where doing so would mess up the iterator */
1325         for (uint32_t i = 0; i < h2c->rused; ++i) {
1326             request_st * const r = h2c->r[i];
1327             /*assert(r->h2state == H2_STATE_CLOSED);*/
1328             h2_retire_stream(r, con);/*r invalidated;removed from h2c->r[]*/
1329             --i;/* adjust loop i; h2c->rused was modified to retire r */
1330         }
1331         /* XXX: ? should we discard con->write_queue
1332          *        and change h2r->state to CON_STATE_RESPONSE_END ? */
1333     }
1334 
1335     if (h2r->state == CON_STATE_WRITE) {
1336         /* write HTTP/2 frames to socket */
1337         if (!chunkqueue_is_empty(con->write_queue))
1338             connection_handle_write(h2r, con);
1339 
1340         if (chunkqueue_is_empty(con->write_queue)
1341             && 0 == h2c->rused && h2c->sent_goaway)
1342             connection_set_state(h2r, CON_STATE_RESPONSE_END);
1343     }
1344 
1345     if (h2r->state == CON_STATE_WRITE) {
1346         /* (resched & 1) more data is available to write, if still able to write
1347          * (resched & 2) resched to read deferred frames from con->read_queue */
1348         /*(con->is_writable set to 0 if !chunkqueue_is_empty(con->write_queue)
1349          * after trying to write in connection_handle_write() above)*/
1350         if (((resched & 1) && con->is_writable>0 && !con->traffic_limit_reached)
1351             || (resched & 2))
1352             joblist_append(con);
1353 
1354         if (h2_want_read(con))
1355             h2r->conf.stream_request_body |=  FDEVENT_STREAM_REQUEST_POLLIN;
1356         else
1357             h2r->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN;
1358     }
1359     else /* e.g. CON_STATE_RESPONSE_END or CON_STATE_ERROR */
1360         connection_state_machine_loop(h2r, con);
1361 
1362     connection_set_fdevent_interest(h2r, con);
1363 }
1364 
1365 
1366 static void
1367 connection_state_machine_h1 (request_st * const r, connection * const con)
1368 {
1369 	const int log_state_handling = r->conf.log_state_handling;
1370 	if (log_state_handling) {
1371 		log_error(r->conf.errh, __FILE__, __LINE__,
1372 		  "state at enter %d %s", con->fd, connection_get_state(r->state));
1373 	}
1374 
1375 	connection_state_machine_loop(r, con);
1376 
1377 	if (log_state_handling) {
1378 		log_error(r->conf.errh, __FILE__, __LINE__,
1379 		  "state at exit: %d %s", con->fd, connection_get_state(r->state));
1380 	}
1381 
1382 	connection_set_fdevent_interest(r, con);
1383 }
1384 
1385 
1386 void
1387 connection_state_machine (connection * const con)
1388 {
1389     request_st * const r = &con->request;
1390     if (r->http_version == HTTP_VERSION_2)
1391         connection_state_machine_h2(r, con);
1392     else /* if (r->http_version <= HTTP_VERSION_1_1) */
1393         connection_state_machine_h1(r, con);
1394 }
1395 
1396 
1397 static void connection_check_timeout (connection * const con, const unix_time64_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     }
1408     else if (con->h2 && r->state == CON_STATE_WRITE) {
1409         h2con * const h2c = con->h2;
1410         if (h2c->rused) {
1411             for (uint32_t i = 0; i < h2c->rused; ++i) {
1412                 request_st * const rr = h2c->r[i];
1413                 if (rr->state == CON_STATE_ERROR) { /*(should not happen)*/
1414                     changed = 1;
1415                     continue;
1416                 }
1417                 if (rr->reqbody_length != rr->reqbody_queue.bytes_in) {
1418                     /* XXX: should timeout apply if not trying to read on h2con?
1419                      * (still applying timeout to catch stuck connections) */
1420                     /* XXX: con->read_idle_ts is not per-request, so timeout
1421                      * will not occur if other read activity occurs on h2con
1422                      * (future: might keep separate timestamp per-request) */
1423                     if (cur_ts - con->read_idle_ts > rr->conf.max_read_idle) {
1424                         /* time - out */
1425                         if (rr->conf.log_request_handling) {
1426                             log_error(rr->conf.errh, __FILE__, __LINE__,
1427                               "request aborted - read timeout: %d", con->fd);
1428                         }
1429                         connection_set_state_error(r, CON_STATE_ERROR);
1430                         changed = 1;
1431                     }
1432                 }
1433 
1434                 if (rr->state != CON_STATE_READ_POST
1435                     && con->write_request_ts != 0) {
1436                     /* XXX: con->write_request_ts is not per-request, so timeout
1437                      * will not occur if other write activity occurs on h2con
1438                      * (future: might keep separate timestamp per-request) */
1439                     if (cur_ts - con->write_request_ts
1440                         > r->conf.max_write_idle) {
1441                         /*(see comment further down about max_write_idle)*/
1442                         /* time - out */
1443                         if (r->conf.log_timeouts) {
1444                             log_error(r->conf.errh, __FILE__, __LINE__,
1445                               "NOTE: a request from %s for %.*s timed out "
1446                               "after writing %lld bytes. We waited %d seconds. "
1447                               "If this is a problem, increase "
1448                               "server.max-write-idle",
1449                               con->dst_addr_buf.ptr,
1450                               BUFFER_INTLEN_PTR(&r->target),
1451                               (long long)r->write_queue.bytes_out,
1452                               (int)r->conf.max_write_idle);
1453                         }
1454                         connection_set_state_error(r, CON_STATE_ERROR);
1455                         changed = 1;
1456                     }
1457                 }
1458             }
1459         }
1460         else {
1461             if (cur_ts - con->read_idle_ts > con->keep_alive_idle) {
1462                 /* time - out */
1463                 if (r->conf.log_request_handling) {
1464                     log_error(r->conf.errh, __FILE__, __LINE__,
1465                               "connection closed - keep-alive timeout: %d",
1466                               con->fd);
1467                 }
1468                 connection_set_state(r, CON_STATE_RESPONSE_END);
1469                 changed = 1;
1470             }
1471         }
1472         /* process changes before optimistic read of additional HTTP/2 frames */
1473         if (changed)
1474             con->is_readable = 0;
1475     }
1476     else if (waitevents & FDEVENT_IN) {
1477         if (con->request_count == 1 || r->state != CON_STATE_READ) {
1478             /* e.g. CON_STATE_READ_POST || CON_STATE_WRITE */
1479             if (cur_ts - con->read_idle_ts > r->conf.max_read_idle) {
1480                 /* time - out */
1481                 if (r->conf.log_request_handling) {
1482                     log_error(r->conf.errh, __FILE__, __LINE__,
1483                               "connection closed - read timeout: %d", con->fd);
1484                 }
1485 
1486                 connection_set_state_error(r, CON_STATE_ERROR);
1487                 changed = 1;
1488             }
1489         } else {
1490             if (cur_ts - con->read_idle_ts > con->keep_alive_idle) {
1491                 /* time - out */
1492                 if (r->conf.log_request_handling) {
1493                     log_error(r->conf.errh, __FILE__, __LINE__,
1494                               "connection closed - keep-alive timeout: %d",
1495                               con->fd);
1496                 }
1497 
1498                 connection_set_state_error(r, CON_STATE_ERROR);
1499                 changed = 1;
1500             }
1501         }
1502     }
1503 
1504     /* max_write_idle timeout currently functions as backend timeout,
1505      * too, after response has been started.
1506      * Although backend timeouts now exist, there is no default for timeouts
1507      * to backends, so were this client timeout now to be changed to check
1508      * for write interest to the client, then timeout would not occur if the
1509      * backend hung and there was no backend read timeout set.  Therefore,
1510      * max_write_idle timeout remains timeout for both reading from backend
1511      * and writing to client, though this check here is only for HTTP/1.1.
1512      * In the future, if there were a quick way to detect that a backend
1513      * read timeout was in effect, then this timeout could check for write
1514      * interest to client.  (not a priority) */
1515     /*if (waitevents & FDEVENT_OUT)*/
1516     if (r->http_version <= HTTP_VERSION_1_1
1517         && r->state == CON_STATE_WRITE && con->write_request_ts != 0) {
1518       #if 0
1519         if (cur_ts - con->write_request_ts > 60) {
1520             log_error(r->conf.errh, __FILE__, __LINE__,
1521                       "connection closed - pre-write-request-timeout: %d %d",
1522                       con->fd, cur_ts - con->write_request_ts);
1523         }
1524       #endif
1525 
1526         if (cur_ts - con->write_request_ts > r->conf.max_write_idle) {
1527             /* time - out */
1528             if (r->conf.log_timeouts) {
1529                 log_error(r->conf.errh, __FILE__, __LINE__,
1530                   "NOTE: a request from %s for %.*s timed out after writing "
1531                   "%lld bytes. We waited %d seconds. If this is a problem, "
1532                   "increase server.max-write-idle",
1533                   con->dst_addr_buf.ptr,
1534                   BUFFER_INTLEN_PTR(&r->target),
1535                   (long long)con->bytes_written, (int)r->conf.max_write_idle);
1536             }
1537             connection_set_state_error(r, CON_STATE_ERROR);
1538             changed = 1;
1539         }
1540     }
1541 
1542     /* lighttpd HTTP/2 limitation: rate limit config r->conf.bytes_per_second
1543      * (currently) taken only from top-level config (socket), with host if SNI
1544      * used, but not any other config conditions, e.g. not per-file-type */
1545 
1546     if (0 == (t_diff = cur_ts - con->connection_start)) t_diff = 1;
1547 
1548     if (con->traffic_limit_reached &&
1549         (r->conf.bytes_per_second == 0 ||
1550          con->bytes_written < (off_t)r->conf.bytes_per_second * t_diff)) {
1551         /* enable connection again */
1552         con->traffic_limit_reached = 0;
1553 
1554         changed = 1;
1555     }
1556 
1557     con->bytes_written_cur_second = 0;
1558 
1559     if (changed) {
1560         connection_state_machine(con);
1561     }
1562 }
1563 
1564 void connection_periodic_maint (server * const srv, const unix_time64_t cur_ts) {
1565     /* check all connections for timeouts */
1566     for (connection *con = srv->conns, *tc; con; con = tc) {
1567         tc = con->next;
1568         connection_check_timeout(con, cur_ts);
1569     }
1570 }
1571 
1572 void connection_graceful_shutdown_maint (server *srv) {
1573     const int graceful_expire =
1574       (srv->graceful_expire_ts && srv->graceful_expire_ts < log_monotonic_secs);
1575     for (connection *con = srv->conns, *tc; con; con = tc) {
1576         tc = con->next;
1577         int changed = 0;
1578 
1579         request_st * const r = &con->request;
1580         if (r->state == CON_STATE_CLOSE) {
1581             /* reduce remaining linger timeout to be
1582              * (from zero) *up to* one more second, but no more */
1583             if (HTTP_LINGER_TIMEOUT > 1)
1584                 con->close_timeout_ts -= (HTTP_LINGER_TIMEOUT - 1);
1585             if (log_monotonic_secs - con->close_timeout_ts > HTTP_LINGER_TIMEOUT)
1586                 changed = 1;
1587         }
1588         else if (con->h2 && r->state == CON_STATE_WRITE) {
1589             h2_send_goaway(con, H2_E_NO_ERROR);
1590             if (0 == con->h2->rused && chunkqueue_is_empty(con->write_queue)) {
1591                 connection_set_state(r, CON_STATE_RESPONSE_END);
1592                 changed = 1;
1593             }
1594         }
1595         else if (r->state == CON_STATE_READ && con->request_count > 1
1596                  && chunkqueue_is_empty(con->read_queue)) {
1597             /* close connections in keep-alive waiting for next request */
1598             connection_set_state_error(r, CON_STATE_ERROR);
1599             changed = 1;
1600         }
1601 
1602         if (graceful_expire) {
1603             connection_set_state_error(r, CON_STATE_ERROR);
1604             changed = 1;
1605         }
1606 
1607         r->keep_alive = 0;            /* disable keep-alive */
1608 
1609         r->conf.bytes_per_second = 0;         /* disable rate limit */
1610         r->conf.global_bytes_per_second = 0;  /* disable rate limit */
1611         if (con->traffic_limit_reached) {
1612             con->traffic_limit_reached = 0;
1613             changed = 1;
1614         }
1615 
1616         if (changed) {
1617             connection_state_machine(con);
1618         }
1619     }
1620 }
1621 
1622 
1623 static int
1624 connection_handle_read_post_cq_compact (chunkqueue * const cq)
1625 {
1626     /* combine first mem chunk with next non-empty mem chunk
1627      * (loop if next chunk is empty) */
1628     chunk *c = cq->first;
1629     if (NULL == c) return 0;
1630     const uint32_t mlen = buffer_clen(c->mem) - (size_t)c->offset;
1631     while ((c = c->next)) {
1632         const uint32_t blen = buffer_clen(c->mem) - (size_t)c->offset;
1633         if (0 == blen) continue;
1634         chunkqueue_compact_mem(cq, mlen + blen);
1635         return 1;
1636     }
1637     return 0;
1638 }
1639 
1640 
1641 __attribute_pure__
1642 static int
1643 connection_handle_read_post_chunked_crlf (chunkqueue * const cq)
1644 {
1645     /* caller might check chunkqueue_length(cq) >= 2 before calling here
1646      * to limit return value to either 1 for good or -1 for error */
1647     chunk *c;
1648     buffer *b;
1649     char *p;
1650     size_t len;
1651 
1652     /* caller must have called chunkqueue_remove_finished_chunks(cq), so if
1653      * chunkqueue is not empty, it contains chunk with at least one char */
1654     if (chunkqueue_is_empty(cq)) return 0;
1655 
1656     c = cq->first;
1657     b = c->mem;
1658     p = b->ptr+c->offset;
1659     if (p[0] != '\r') return -1; /* error */
1660     if (p[1] == '\n') return 1;
1661     len = buffer_clen(b) - (size_t)c->offset;
1662     if (1 != len) return -1; /* error */
1663 
1664     while (NULL != (c = c->next)) {
1665         b = c->mem;
1666         len = buffer_clen(b) - (size_t)c->offset;
1667         if (0 == len) continue;
1668         p = b->ptr+c->offset;
1669         return (p[0] == '\n') ? 1 : -1; /* error if not '\n' */
1670     }
1671     return 0;
1672 }
1673 
1674 
1675 static handler_t
1676 connection_handle_read_post_chunked (request_st * const r, chunkqueue * const cq, chunkqueue * const dst_cq)
1677 {
1678     /* r->conf.max_request_size is in kBytes */
1679     const off_t max_request_size = (off_t)r->conf.max_request_size << 10;
1680     off_t te_chunked = r->te_chunked;
1681     do {
1682         off_t len = chunkqueue_length(cq);
1683 
1684         while (0 == te_chunked) {
1685             char *p;
1686             chunk *c = cq->first;
1687             if (NULL == c) break;
1688             force_assert(c->type == MEM_CHUNK);
1689             p = strchr(c->mem->ptr+c->offset, '\n');
1690             if (NULL != p) { /* found HTTP chunked header line */
1691                 off_t hsz = p + 1 - (c->mem->ptr+c->offset);
1692                 unsigned char *s = (unsigned char *)c->mem->ptr+c->offset;
1693                 for (unsigned char u;(u=(unsigned char)hex2int(*s))!=0xFF;++s) {
1694                     if (te_chunked > (off_t)(1uLL<<(8*sizeof(off_t)-5))-1-2) {
1695                         log_error(r->conf.errh, __FILE__, __LINE__,
1696                           "chunked data size too large -> 400");
1697                         /* 400 Bad Request */
1698                         return http_response_reqbody_read_error(r, 400);
1699                     }
1700                     te_chunked <<= 4;
1701                     te_chunked |= u;
1702                 }
1703                 if (s == (unsigned char *)c->mem->ptr+c->offset) { /*(no hex)*/
1704                     log_error(r->conf.errh, __FILE__, __LINE__,
1705                       "chunked header invalid chars -> 400");
1706                     /* 400 Bad Request */
1707                     return http_response_reqbody_read_error(r, 400);
1708                 }
1709                 while (*s == ' ' || *s == '\t') ++s;
1710                 if (*s != '\r' && *s != ';') {
1711                     log_error(r->conf.errh, __FILE__, __LINE__,
1712                       "chunked header invalid chars -> 400");
1713                     /* 400 Bad Request */
1714                     return http_response_reqbody_read_error(r, 400);
1715                 }
1716 
1717                 if (hsz >= 1024) {
1718                     /* prevent theoretical integer overflow
1719                      * casting to (size_t) and adding 2 (for "\r\n") */
1720                     log_error(r->conf.errh, __FILE__, __LINE__,
1721                       "chunked header line too long -> 400");
1722                     /* 400 Bad Request */
1723                     return http_response_reqbody_read_error(r, 400);
1724                 }
1725 
1726                 if (0 == te_chunked) {
1727                     /* do not consume final chunked header until
1728                      * (optional) trailers received along with
1729                      * request-ending blank line "\r\n" */
1730                     if (p[0] == '\r' && p[1] == '\n') {
1731                         /*(common case with no trailers; final \r\n received)*/
1732                         hsz += 2;
1733                     }
1734                     else {
1735                         /* trailers or final CRLF crosses into next cq chunk */
1736                         hsz -= 2;
1737                         do {
1738                             c = cq->first;
1739                             p = strstr(c->mem->ptr+c->offset+hsz, "\r\n\r\n");
1740                         } while (NULL == p
1741                                  && connection_handle_read_post_cq_compact(cq));
1742                         if (NULL == p) {
1743                             /*(effectively doubles max request field size
1744                              * potentially received by backend, if in the future
1745                              * these trailers are added to request headers)*/
1746                             if ((off_t)buffer_clen(c->mem) - c->offset
1747                                 < (off_t)r->conf.max_request_field_size) {
1748                                 break;
1749                             }
1750                             else {
1751                                 /* ignore excessively long trailers;
1752                                  * disable keep-alive on connection */
1753                                 r->keep_alive = 0;
1754                                 p = c->mem->ptr + buffer_clen(c->mem)
1755                                   - 4;
1756                             }
1757                         }
1758                         hsz = p + 4 - (c->mem->ptr+c->offset);
1759                         /* trailers currently ignored, but could be processed
1760                          * here if 0 == (r->conf.stream_request_body &
1761                          *               & (FDEVENT_STREAM_REQUEST
1762                          *                 |FDEVENT_STREAM_REQUEST_BUFMIN))
1763                          * taking care to reject fields forbidden in trailers,
1764                          * making trailers available to CGI and other backends*/
1765                     }
1766                     chunkqueue_mark_written(cq, (size_t)hsz);
1767                     r->reqbody_length = dst_cq->bytes_in;
1768                     break; /* done reading HTTP chunked request body */
1769                 }
1770 
1771                 /* consume HTTP chunked header */
1772                 chunkqueue_mark_written(cq, (size_t)hsz);
1773                 len = chunkqueue_length(cq);
1774 
1775                 if (0 !=max_request_size
1776                     && (max_request_size < te_chunked
1777                      || max_request_size - te_chunked < dst_cq->bytes_in)) {
1778                     log_error(r->conf.errh, __FILE__, __LINE__,
1779                       "request-size too long: %lld -> 413",
1780                       (long long)(dst_cq->bytes_in + te_chunked));
1781                     /* 413 Payload Too Large */
1782                     return http_response_reqbody_read_error(r, 413);
1783                 }
1784 
1785                 te_chunked += 2; /*(for trailing "\r\n" after chunked data)*/
1786 
1787                 break; /* read HTTP chunked header */
1788             }
1789 
1790             /*(likely better ways to handle chunked header crossing chunkqueue
1791              * chunks, but this situation is not expected to occur frequently)*/
1792             if ((off_t)buffer_clen(c->mem) - c->offset >= 1024) {
1793                 log_error(r->conf.errh, __FILE__, __LINE__,
1794                   "chunked header line too long -> 400");
1795                 /* 400 Bad Request */
1796                 return http_response_reqbody_read_error(r, 400);
1797             }
1798             else if (!connection_handle_read_post_cq_compact(cq)) {
1799                 break;
1800             }
1801         }
1802         if (0 == te_chunked) break;
1803 
1804         if (te_chunked > 2) {
1805             if (len > te_chunked-2) len = te_chunked-2;
1806             if (dst_cq->bytes_in + te_chunked <= 64*1024) {
1807                 /* avoid buffering request bodies <= 64k on disk */
1808                 chunkqueue_steal(dst_cq, cq, len);
1809             }
1810             else if (0 != chunkqueue_steal_with_tempfiles(dst_cq, cq, len,
1811                                                           r->conf.errh)) {
1812                 /* 500 Internal Server Error */
1813                 return http_response_reqbody_read_error(r, 500);
1814             }
1815             te_chunked -= len;
1816             len = chunkqueue_length(cq);
1817         }
1818 
1819         if (len < te_chunked) break;
1820 
1821         if (2 == te_chunked) {
1822             if (-1 == connection_handle_read_post_chunked_crlf(cq)) {
1823                 log_error(r->conf.errh, __FILE__, __LINE__,
1824                   "chunked data missing end CRLF -> 400");
1825                 /* 400 Bad Request */
1826                 return http_response_reqbody_read_error(r, 400);
1827             }
1828             chunkqueue_mark_written(cq, 2);/*consume \r\n at end of chunk data*/
1829             te_chunked -= 2;
1830         }
1831 
1832     } while (!chunkqueue_is_empty(cq));
1833 
1834     r->te_chunked = te_chunked;
1835     return HANDLER_GO_ON;
1836 }
1837 
1838 
1839 static handler_t
1840 connection_handle_read_body_unknown (request_st * const r, chunkqueue * const cq, chunkqueue * const dst_cq)
1841 {
1842     /* r->conf.max_request_size is in kBytes */
1843     const off_t max_request_size = (off_t)r->conf.max_request_size << 10;
1844     chunkqueue_append_chunkqueue(dst_cq, cq);
1845     if (0 != max_request_size && dst_cq->bytes_in > max_request_size) {
1846         log_error(r->conf.errh, __FILE__, __LINE__,
1847           "request-size too long: %lld -> 413", (long long)dst_cq->bytes_in);
1848         /* 413 Payload Too Large */
1849         return http_response_reqbody_read_error(r, 413);
1850     }
1851     return HANDLER_GO_ON;
1852 }
1853 
1854 
1855 __attribute_cold__
1856 static int
1857 connection_check_expect_100 (request_st * const r, connection * const con)
1858 {
1859     if (con->is_writable <= 0)
1860         return 1;
1861 
1862     const buffer * const vb =
1863       http_header_request_get(r, HTTP_HEADER_EXPECT,
1864                               CONST_STR_LEN("Expect"));
1865     if (NULL == vb)
1866         return 1;
1867 
1868     /* (always unset Expect header so that check is not repeated for request */
1869     int rc = buffer_eq_icase_slen(vb, CONST_STR_LEN("100-continue"));
1870     http_header_request_unset(r, HTTP_HEADER_EXPECT,
1871                               CONST_STR_LEN("Expect"));
1872     if (!rc
1873         || 0 != r->reqbody_queue.bytes_in
1874         || !chunkqueue_is_empty(&r->read_queue)
1875         || !chunkqueue_is_empty(&r->write_queue))
1876         return 1;
1877 
1878     /* send 100 Continue only if no request body data received yet
1879      * and response has not yet started (checked above) */
1880     if (r->http_version > HTTP_VERSION_1_1)
1881         h2_send_100_continue(r, con);
1882     else if (r->http_version == HTTP_VERSION_1_1)
1883         return connection_write_100_continue(r, con);
1884 
1885     return 1;
1886 }
1887 
1888 
1889 static handler_t
1890 connection_handle_read_post_state (request_st * const r)
1891 {
1892     connection * const con = r->con;
1893     chunkqueue * const cq = &r->read_queue;
1894     chunkqueue * const dst_cq = &r->reqbody_queue;
1895 
1896     int is_closed = 0;
1897 
1898     if (r->http_version > HTTP_VERSION_1_1) {
1899         /*(H2_STATE_HALF_CLOSED_REMOTE or H2_STATE_CLOSED)*/
1900         if (r->h2state >= H2_STATE_HALF_CLOSED_REMOTE)
1901             is_closed = 1;
1902     }
1903     else if (con->is_readable > 0) {
1904         con->read_idle_ts = log_monotonic_secs;
1905         const off_t max_per_read =
1906           !(r->conf.stream_request_body /*(if not streaming request body)*/
1907             & (FDEVENT_STREAM_REQUEST|FDEVENT_STREAM_REQUEST_BUFMIN))
1908             ? MAX_READ_LIMIT
1909             : (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN)
1910               ? 16384  /* FDEVENT_STREAM_REQUEST_BUFMIN */
1911               : 65536; /* FDEVENT_STREAM_REQUEST */
1912         switch(con->network_read(con, cq, max_per_read)) {
1913         case -1:
1914             connection_set_state_error(r, CON_STATE_ERROR);
1915             return HANDLER_ERROR;
1916         case -2:
1917             is_closed = 1;
1918             break;
1919         default:
1920             break;
1921         }
1922 
1923         chunkqueue_remove_finished_chunks(cq);
1924     }
1925 
1926     /* Check for Expect: 100-continue in request headers */
1927     if (light_btst(r->rqst_htags, HTTP_HEADER_EXPECT)
1928         && !connection_check_expect_100(r, con))
1929         return HANDLER_ERROR;
1930 
1931     if (r->http_version > HTTP_VERSION_1_1) {
1932         /* h2_recv_data() places frame payload directly into r->reqbody_queue */
1933     }
1934     else if (r->reqbody_length < 0) {
1935         /*(-1: Transfer-Encoding: chunked, -2: unspecified length)*/
1936         handler_t rc = (-1 == r->reqbody_length)
1937                      ? connection_handle_read_post_chunked(r, cq, dst_cq)
1938                      : connection_handle_read_body_unknown(r, cq, dst_cq);
1939         if (HANDLER_GO_ON != rc) return rc;
1940         chunkqueue_remove_finished_chunks(cq);
1941     }
1942     else {
1943         off_t len = (off_t)r->reqbody_length - dst_cq->bytes_in;
1944         if (r->reqbody_length <= 64*1024) {
1945             /* don't buffer request bodies <= 64k on disk */
1946             chunkqueue_steal(dst_cq, cq, len);
1947         }
1948         else if (0 !=
1949                  chunkqueue_steal_with_tempfiles(dst_cq,cq,len,r->conf.errh)) {
1950             /* writing to temp file failed */ /* Internal Server Error */
1951             return http_response_reqbody_read_error(r, 500);
1952         }
1953         chunkqueue_remove_finished_chunks(cq);
1954     }
1955 
1956     if (dst_cq->bytes_in == (off_t)r->reqbody_length) {
1957         /* Content is ready */
1958         r->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN;
1959         if (r->state == CON_STATE_READ_POST) {
1960             connection_set_state(r, CON_STATE_HANDLE_REQUEST);
1961         }
1962         return HANDLER_GO_ON;
1963     }
1964     else if (is_closed) {
1965       #if 0
1966         return http_response_reqbody_read_error(r, 400); /* Bad Request */
1967       #endif
1968         return HANDLER_ERROR;
1969     }
1970     else {
1971         r->conf.stream_request_body |= FDEVENT_STREAM_REQUEST_POLLIN;
1972         return (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST)
1973           ? HANDLER_GO_ON
1974           : HANDLER_WAIT_FOR_EVENT;
1975     }
1976 }
1977