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