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