xref: /lighttpd1.4/src/h2.c (revision 3392e8fb)
1 /*
2  * h2 - HTTP/2 protocol layer
3  *
4  * Copyright(c) 2020 Glenn Strauss gstrauss()gluelogic.com  All rights reserved
5  * License: BSD 3-clause (same as lighttpd)
6  */
7 #include "first.h"
8 #include "h2.h"
9 
10 #include <arpa/inet.h>  /* htonl() */
11 #include <stdint.h>     /* INT32_MAX INT32_MIN */
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "base.h"
16 #include "buffer.h"
17 #include "chunk.h"
18 #include "fdevent.h"    /* FDEVENT_STREAM_REQUEST_BUFMIN */
19 #include "http_date.h"
20 #include "http_header.h"
21 #include "log.h"
22 #include "request.h"
23 #include "response.h"   /* http_response_omit_header() */
24 
25 
26 /* lowercased field-names
27  * (32-byte record (power-2) and single block of memory for memory locality) */
28 static const char http_header_lc[][32] = {
29   [HTTP_HEADER_OTHER]                     = ""
30  ,[HTTP_HEADER_ACCEPT]                    = "accept"
31  ,[HTTP_HEADER_ACCEPT_ENCODING]           = "accept-encoding"
32  ,[HTTP_HEADER_ACCEPT_LANGUAGE]           = "accept-language"
33  ,[HTTP_HEADER_ACCEPT_RANGES]             = "accept-ranges"
34  ,[HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN]="access-control-allow-origin"
35  ,[HTTP_HEADER_AGE]                       = "age"
36  ,[HTTP_HEADER_ALLOW]                     = "allow"
37  ,[HTTP_HEADER_ALT_SVC]                   = "alt-svc"
38  ,[HTTP_HEADER_ALT_USED]                  = "alt-used"
39  ,[HTTP_HEADER_AUTHORIZATION]             = "authorization"
40  ,[HTTP_HEADER_CACHE_CONTROL]             = "cache-control"
41  ,[HTTP_HEADER_CONNECTION]                = "connection"
42  ,[HTTP_HEADER_CONTENT_ENCODING]          = "content-encoding"
43  ,[HTTP_HEADER_CONTENT_LENGTH]            = "content-length"
44  ,[HTTP_HEADER_CONTENT_LOCATION]          = "content-location"
45  ,[HTTP_HEADER_CONTENT_RANGE]             = "content-range"
46  ,[HTTP_HEADER_CONTENT_SECURITY_POLICY]   = "content-security-policy"
47  ,[HTTP_HEADER_CONTENT_TYPE]              = "content-type"
48  ,[HTTP_HEADER_COOKIE]                    = "cookie"
49  ,[HTTP_HEADER_DATE]                      = "date"
50  ,[HTTP_HEADER_DNT]                       = "dnt"
51  ,[HTTP_HEADER_ETAG]                      = "etag"
52  ,[HTTP_HEADER_EXPECT]                    = "expect"
53  ,[HTTP_HEADER_EXPECT_CT]                 = "expect-ct"
54  ,[HTTP_HEADER_EXPIRES]                   = "expires"
55  ,[HTTP_HEADER_FORWARDED]                 = "forwarded"
56  ,[HTTP_HEADER_HOST]                      = "host"
57  ,[HTTP_HEADER_HTTP2_SETTINGS]            = "http2-settings"
58  ,[HTTP_HEADER_IF_MATCH]                  = "if-match"
59  ,[HTTP_HEADER_IF_MODIFIED_SINCE]         = "if-modified-since"
60  ,[HTTP_HEADER_IF_NONE_MATCH]             = "if-none-match"
61  ,[HTTP_HEADER_IF_RANGE]                  = "if-range"
62  ,[HTTP_HEADER_IF_UNMODIFIED_SINCE]       = "if-unmodified-since"
63  ,[HTTP_HEADER_LAST_MODIFIED]             = "last-modified"
64  ,[HTTP_HEADER_LINK]                      = "link"
65  ,[HTTP_HEADER_LOCATION]                  = "location"
66  ,[HTTP_HEADER_ONION_LOCATION]            = "onion-location"
67  ,[HTTP_HEADER_P3P]                       = "p3p"
68  ,[HTTP_HEADER_PRAGMA]                    = "pragma"
69  ,[HTTP_HEADER_RANGE]                     = "range"
70  ,[HTTP_HEADER_REFERER]                   = "referer"
71  ,[HTTP_HEADER_REFERRER_POLICY]           = "referrer-policy"
72  ,[HTTP_HEADER_SERVER]                    = "server"
73  ,[HTTP_HEADER_SET_COOKIE]                = "set-cookie"
74  ,[HTTP_HEADER_STATUS]                    = "status"
75  ,[HTTP_HEADER_STRICT_TRANSPORT_SECURITY] = "strict-transport-security"
76  ,[HTTP_HEADER_TE]                        = "te"
77  ,[HTTP_HEADER_TRANSFER_ENCODING]         = "transfer-encoding"
78  ,[HTTP_HEADER_UPGRADE]                   = "upgrade"
79  ,[HTTP_HEADER_UPGRADE_INSECURE_REQUESTS] = "upgrade-insecure-requests"
80  ,[HTTP_HEADER_USER_AGENT]                = "user-agent"
81  ,[HTTP_HEADER_VARY]                      = "vary"
82  ,[HTTP_HEADER_WWW_AUTHENTICATE]          = "www-authenticate"
83  ,[HTTP_HEADER_X_CONTENT_TYPE_OPTIONS]    = "x-content-type-options"
84  ,[HTTP_HEADER_X_FORWARDED_FOR]           = "x-forwarded-for"
85  ,[HTTP_HEADER_X_FORWARDED_PROTO]         = "x-forwarded-proto"
86  ,[HTTP_HEADER_X_FRAME_OPTIONS]           = "x-frame-options"
87  ,[HTTP_HEADER_X_XSS_PROTECTION]          = "x-xss-protection"
88 };
89 
90 
91 /* future optimization: could conceivably store static XXH32() hash values for
92  * field-name (e.g. for benefit of entries marked LSHPACK_HDR_UNKNOWN) to
93  * incrementally reduce cost of calculating hash values for field-name on each
94  * request where those headers are used.  Might also store single element
95  * static caches for "date:" value (updated each time static buffer is updated)
96  * and for "server:" value (often global to server), keyed on r->conf.server_tag
97  * pointer addr.  HTTP_HEADER_STATUS could be overloaded for ":status", since
98  * lighttpd should not send "Status:" response header (should not happen) */
99 
100 static const uint8_t http_header_lshpack_idx[] = {
101   [HTTP_HEADER_OTHER]                     = LSHPACK_HDR_UNKNOWN
102  ,[HTTP_HEADER_ACCEPT_ENCODING]           = LSHPACK_HDR_ACCEPT_ENCODING
103  ,[HTTP_HEADER_AUTHORIZATION]             = LSHPACK_HDR_AUTHORIZATION
104  ,[HTTP_HEADER_CACHE_CONTROL]             = LSHPACK_HDR_CACHE_CONTROL
105  ,[HTTP_HEADER_CONNECTION]                = LSHPACK_HDR_UNKNOWN
106  ,[HTTP_HEADER_CONTENT_ENCODING]          = LSHPACK_HDR_CONTENT_ENCODING
107  ,[HTTP_HEADER_CONTENT_LENGTH]            = LSHPACK_HDR_CONTENT_LENGTH
108  ,[HTTP_HEADER_CONTENT_LOCATION]          = LSHPACK_HDR_CONTENT_LOCATION
109  ,[HTTP_HEADER_CONTENT_TYPE]              = LSHPACK_HDR_CONTENT_TYPE
110  ,[HTTP_HEADER_COOKIE]                    = LSHPACK_HDR_COOKIE
111  ,[HTTP_HEADER_DATE]                      = LSHPACK_HDR_DATE
112  ,[HTTP_HEADER_ETAG]                      = LSHPACK_HDR_ETAG
113  ,[HTTP_HEADER_EXPECT]                    = LSHPACK_HDR_EXPECT
114  ,[HTTP_HEADER_FORWARDED]                 = LSHPACK_HDR_UNKNOWN
115  ,[HTTP_HEADER_HOST]                      = LSHPACK_HDR_HOST
116  ,[HTTP_HEADER_IF_MODIFIED_SINCE]         = LSHPACK_HDR_IF_MODIFIED_SINCE
117  ,[HTTP_HEADER_IF_NONE_MATCH]             = LSHPACK_HDR_IF_NONE_MATCH
118  ,[HTTP_HEADER_LAST_MODIFIED]             = LSHPACK_HDR_LAST_MODIFIED
119  ,[HTTP_HEADER_LOCATION]                  = LSHPACK_HDR_LOCATION
120  ,[HTTP_HEADER_RANGE]                     = LSHPACK_HDR_RANGE
121  ,[HTTP_HEADER_SERVER]                    = LSHPACK_HDR_SERVER
122  ,[HTTP_HEADER_SET_COOKIE]                = LSHPACK_HDR_SET_COOKIE
123  ,[HTTP_HEADER_STATUS]                    = LSHPACK_HDR_UNKNOWN
124  ,[HTTP_HEADER_TRANSFER_ENCODING]         = LSHPACK_HDR_TRANSFER_ENCODING
125  ,[HTTP_HEADER_UPGRADE]                   = LSHPACK_HDR_UNKNOWN
126  ,[HTTP_HEADER_USER_AGENT]                = LSHPACK_HDR_USER_AGENT
127  ,[HTTP_HEADER_VARY]                      = LSHPACK_HDR_VARY
128  ,[HTTP_HEADER_X_FORWARDED_FOR]           = LSHPACK_HDR_UNKNOWN
129  ,[HTTP_HEADER_X_FORWARDED_PROTO]         = LSHPACK_HDR_UNKNOWN
130  ,[HTTP_HEADER_HTTP2_SETTINGS]            = LSHPACK_HDR_UNKNOWN
131  ,[HTTP_HEADER_ACCEPT]                    = LSHPACK_HDR_ACCEPT
132  ,[HTTP_HEADER_ACCEPT_LANGUAGE]           = LSHPACK_HDR_ACCEPT_LANGUAGE
133  ,[HTTP_HEADER_ACCEPT_RANGES]             = LSHPACK_HDR_ACCEPT_RANGES
134  ,[HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN]=LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN
135  ,[HTTP_HEADER_AGE]                       = LSHPACK_HDR_AGE
136  ,[HTTP_HEADER_ALLOW]                     = LSHPACK_HDR_ALLOW
137  ,[HTTP_HEADER_ALT_SVC]                   = LSHPACK_HDR_UNKNOWN
138  ,[HTTP_HEADER_ALT_USED]                  = LSHPACK_HDR_UNKNOWN
139  ,[HTTP_HEADER_CONTENT_RANGE]             = LSHPACK_HDR_CONTENT_RANGE
140  ,[HTTP_HEADER_CONTENT_SECURITY_POLICY]   = LSHPACK_HDR_UNKNOWN
141  ,[HTTP_HEADER_DNT]                       = LSHPACK_HDR_UNKNOWN
142  ,[HTTP_HEADER_EXPECT_CT]                 = LSHPACK_HDR_UNKNOWN
143  ,[HTTP_HEADER_EXPIRES]                   = LSHPACK_HDR_EXPIRES
144  ,[HTTP_HEADER_IF_MATCH]                  = LSHPACK_HDR_IF_MATCH
145  ,[HTTP_HEADER_IF_RANGE]                  = LSHPACK_HDR_IF_RANGE
146  ,[HTTP_HEADER_IF_UNMODIFIED_SINCE]       = LSHPACK_HDR_IF_UNMODIFIED_SINCE
147  ,[HTTP_HEADER_LINK]                      = LSHPACK_HDR_LINK
148  ,[HTTP_HEADER_ONION_LOCATION]            = LSHPACK_HDR_UNKNOWN
149  ,[HTTP_HEADER_P3P]                       = LSHPACK_HDR_UNKNOWN
150  ,[HTTP_HEADER_PRAGMA]                    = LSHPACK_HDR_UNKNOWN
151  ,[HTTP_HEADER_REFERER]                   = LSHPACK_HDR_REFERER
152  ,[HTTP_HEADER_REFERRER_POLICY]           = LSHPACK_HDR_UNKNOWN
153  ,[HTTP_HEADER_STRICT_TRANSPORT_SECURITY] = LSHPACK_HDR_STRICT_TRANSPORT_SECURITY
154  ,[HTTP_HEADER_TE]                        = LSHPACK_HDR_UNKNOWN
155  ,[HTTP_HEADER_UPGRADE_INSECURE_REQUESTS] = LSHPACK_HDR_UNKNOWN
156  ,[HTTP_HEADER_WWW_AUTHENTICATE]          = LSHPACK_HDR_WWW_AUTHENTICATE
157  ,[HTTP_HEADER_X_CONTENT_TYPE_OPTIONS]    = LSHPACK_HDR_UNKNOWN
158  ,[HTTP_HEADER_X_FRAME_OPTIONS]           = LSHPACK_HDR_UNKNOWN
159  ,[HTTP_HEADER_X_XSS_PROTECTION]          = LSHPACK_HDR_UNKNOWN
160 };
161 
162 
163 /* Note: must be kept in sync with ls-hpack/lshpack.h:lshpack_static_hdr_idx[]*/
164 static const uint8_t lshpack_idx_http_header[] = {
165   [LSHPACK_HDR_UNKNOWN]                   = HTTP_HEADER_OTHER
166  ,[LSHPACK_HDR_AUTHORITY]                 = HTTP_HEADER_OTHER
167  ,[LSHPACK_HDR_METHOD_GET]                = HTTP_HEADER_OTHER
168  ,[LSHPACK_HDR_METHOD_POST]               = HTTP_HEADER_OTHER
169  ,[LSHPACK_HDR_PATH]                      = HTTP_HEADER_OTHER
170  ,[LSHPACK_HDR_PATH_INDEX_HTML]           = HTTP_HEADER_OTHER
171  ,[LSHPACK_HDR_SCHEME_HTTP]               = HTTP_HEADER_OTHER
172  ,[LSHPACK_HDR_SCHEME_HTTPS]              = HTTP_HEADER_OTHER
173  ,[LSHPACK_HDR_STATUS_200]                = HTTP_HEADER_OTHER
174  ,[LSHPACK_HDR_STATUS_204]                = HTTP_HEADER_OTHER
175  ,[LSHPACK_HDR_STATUS_206]                = HTTP_HEADER_OTHER
176  ,[LSHPACK_HDR_STATUS_304]                = HTTP_HEADER_OTHER
177  ,[LSHPACK_HDR_STATUS_400]                = HTTP_HEADER_OTHER
178  ,[LSHPACK_HDR_STATUS_404]                = HTTP_HEADER_OTHER
179  ,[LSHPACK_HDR_STATUS_500]                = HTTP_HEADER_OTHER
180  ,[LSHPACK_HDR_ACCEPT_CHARSET]            = HTTP_HEADER_OTHER
181  ,[LSHPACK_HDR_ACCEPT_ENCODING]           = HTTP_HEADER_ACCEPT_ENCODING
182  ,[LSHPACK_HDR_ACCEPT_LANGUAGE]           = HTTP_HEADER_ACCEPT_LANGUAGE
183  ,[LSHPACK_HDR_ACCEPT_RANGES]             = HTTP_HEADER_ACCEPT_RANGES
184  ,[LSHPACK_HDR_ACCEPT]                    = HTTP_HEADER_ACCEPT
185  ,[LSHPACK_HDR_ACCESS_CONTROL_ALLOW_ORIGIN]=HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN
186  ,[LSHPACK_HDR_AGE]                       = HTTP_HEADER_AGE
187  ,[LSHPACK_HDR_ALLOW]                     = HTTP_HEADER_ALLOW
188  ,[LSHPACK_HDR_AUTHORIZATION]             = HTTP_HEADER_AUTHORIZATION
189  ,[LSHPACK_HDR_CACHE_CONTROL]             = HTTP_HEADER_CACHE_CONTROL
190  ,[LSHPACK_HDR_CONTENT_DISPOSITION]       = HTTP_HEADER_OTHER
191  ,[LSHPACK_HDR_CONTENT_ENCODING]          = HTTP_HEADER_CONTENT_ENCODING
192  ,[LSHPACK_HDR_CONTENT_LANGUAGE]          = HTTP_HEADER_OTHER
193  ,[LSHPACK_HDR_CONTENT_LENGTH]            = HTTP_HEADER_CONTENT_LENGTH
194  ,[LSHPACK_HDR_CONTENT_LOCATION]          = HTTP_HEADER_CONTENT_LOCATION
195  ,[LSHPACK_HDR_CONTENT_RANGE]             = HTTP_HEADER_CONTENT_RANGE
196  ,[LSHPACK_HDR_CONTENT_TYPE]              = HTTP_HEADER_CONTENT_TYPE
197  ,[LSHPACK_HDR_COOKIE]                    = HTTP_HEADER_COOKIE
198  ,[LSHPACK_HDR_DATE]                      = HTTP_HEADER_DATE
199  ,[LSHPACK_HDR_ETAG]                      = HTTP_HEADER_ETAG
200  ,[LSHPACK_HDR_EXPECT]                    = HTTP_HEADER_EXPECT
201  ,[LSHPACK_HDR_EXPIRES]                   = HTTP_HEADER_EXPIRES
202  ,[LSHPACK_HDR_FROM]                      = HTTP_HEADER_OTHER
203  ,[LSHPACK_HDR_HOST]                      = HTTP_HEADER_HOST
204  ,[LSHPACK_HDR_IF_MATCH]                  = HTTP_HEADER_IF_MATCH
205  ,[LSHPACK_HDR_IF_MODIFIED_SINCE]         = HTTP_HEADER_IF_MODIFIED_SINCE
206  ,[LSHPACK_HDR_IF_NONE_MATCH]             = HTTP_HEADER_IF_NONE_MATCH
207  ,[LSHPACK_HDR_IF_RANGE]                  = HTTP_HEADER_IF_RANGE
208  ,[LSHPACK_HDR_IF_UNMODIFIED_SINCE]       = HTTP_HEADER_IF_UNMODIFIED_SINCE
209  ,[LSHPACK_HDR_LAST_MODIFIED]             = HTTP_HEADER_LAST_MODIFIED
210  ,[LSHPACK_HDR_LINK]                      = HTTP_HEADER_LINK
211  ,[LSHPACK_HDR_LOCATION]                  = HTTP_HEADER_LOCATION
212  ,[LSHPACK_HDR_MAX_FORWARDS]              = HTTP_HEADER_OTHER
213  ,[LSHPACK_HDR_PROXY_AUTHENTICATE]        = HTTP_HEADER_OTHER
214  ,[LSHPACK_HDR_PROXY_AUTHORIZATION]       = HTTP_HEADER_OTHER
215  ,[LSHPACK_HDR_RANGE]                     = HTTP_HEADER_RANGE
216  ,[LSHPACK_HDR_REFERER]                   = HTTP_HEADER_REFERER
217  ,[LSHPACK_HDR_REFRESH]                   = HTTP_HEADER_OTHER
218  ,[LSHPACK_HDR_RETRY_AFTER]               = HTTP_HEADER_OTHER
219  ,[LSHPACK_HDR_SERVER]                    = HTTP_HEADER_SERVER
220  ,[LSHPACK_HDR_SET_COOKIE]                = HTTP_HEADER_SET_COOKIE
221  ,[LSHPACK_HDR_STRICT_TRANSPORT_SECURITY] = HTTP_HEADER_STRICT_TRANSPORT_SECURITY
222  ,[LSHPACK_HDR_TRANSFER_ENCODING]         = HTTP_HEADER_TRANSFER_ENCODING
223  ,[LSHPACK_HDR_USER_AGENT]                = HTTP_HEADER_USER_AGENT
224  ,[LSHPACK_HDR_VARY]                      = HTTP_HEADER_VARY
225  ,[LSHPACK_HDR_VIA]                       = HTTP_HEADER_OTHER
226  ,[LSHPACK_HDR_WWW_AUTHENTICATE]          = HTTP_HEADER_WWW_AUTHENTICATE
227 };
228 
229 
230 static request_st * h2_init_stream (request_st * const h2r, connection * const con);
231 
232 
233 __attribute_pure__
234 static inline uint32_t
235 h2_u32 (const uint8_t * const s)
236 {
237     return ((uint32_t)s[0] << 24)
238          | ((uint32_t)s[1] << 16)
239          | ((uint32_t)s[2] <<  8)
240          |  (uint32_t)s[3];
241 }
242 
243 
244 __attribute_pure__
245 static inline uint32_t
246 h2_u31 (const uint8_t * const s)
247 {
248     return h2_u32(s) & ~0x80000000u;
249 }
250 
251 
252 __attribute_pure__
253 static inline uint32_t
254 h2_u24 (const uint8_t * const s)
255 {
256   #if 1
257     /* XXX: optimization is valid only for how this is used in h2.c
258      * where we have checked that frame header received is at least
259      * 9 chars, and where s containing frame length (3-bytes) is
260      * followed by at least 1 additional char. */
261     return h2_u32(s) >> 8;
262   #else
263     return ((uint32_t)s[0] << 16)
264          | ((uint32_t)s[1] <<  8)
265          |  (uint32_t)s[2];
266   #endif
267 }
268 
269 
270 __attribute_pure__
271 static inline uint16_t
272 h2_u16 (const uint8_t * const s)
273 {
274     return ((uint16_t)s[0] << 8)
275          |  (uint16_t)s[1];
276 }
277 
278 
279 static void
280 h2_send_settings_ack (connection * const con)
281 {
282     static const uint8_t settings_ack[] = {
283       /* SETTINGS w/ ACK */
284       0x00, 0x00, 0x00        /* frame length */
285      ,H2_FTYPE_SETTINGS       /* frame type */
286      ,H2_FLAG_ACK             /* frame flags */
287      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
288     };
289 
290     chunkqueue_append_mem(con->write_queue,
291                           (const char *)settings_ack, sizeof(settings_ack));
292 }
293 
294 
295 __attribute_cold__
296 static void
297 h2_send_rst_stream_id (uint32_t h2id, connection * const con, const request_h2error_t e)
298 {
299     union {
300       uint8_t c[16];
301       uint32_t u[4];          /*(alignment)*/
302     } rst_stream = { {        /*(big-endian numbers)*/
303       0x00, 0x00, 0x00        /* padding for alignment; do not send */
304       /* RST_STREAM */
305      ,0x00, 0x00, 0x04        /* frame length */
306      ,H2_FTYPE_RST_STREAM     /* frame type */
307      ,0x00                    /* frame flags */
308      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
309      ,0x00, 0x00, 0x00, 0x00  /* error code;       (fill in below) */
310     } };
311 
312     rst_stream.u[2] = htonl(h2id);
313     rst_stream.u[3] = htonl(e);
314     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
315                           (const char *)rst_stream.c+3, sizeof(rst_stream)-3);
316 }
317 
318 
319 __attribute_cold__
320 static void
321 h2_send_rst_stream (request_st * const r, connection * const con, const request_h2error_t e)
322 {
323     r->state = CON_STATE_ERROR;
324     r->h2state = H2_STATE_CLOSED;
325     h2_send_rst_stream_id(r->h2id, con, e);
326 }
327 
328 
329 __attribute_cold__
330 static void
331 h2_send_goaway_rst_stream (connection * const con)
332 {
333     h2con * const h2c = con->h2;
334     const int sent_goaway = h2c->sent_goaway;
335     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
336         request_st * const r = h2c->r[i];
337         if (r->h2state == H2_STATE_CLOSED) continue;
338         /*(XXX: might consider always sending RST_STREAM)*/
339         if (!sent_goaway) {
340             r->state = CON_STATE_ERROR;
341             r->h2state = H2_STATE_CLOSED;
342         }
343         else /*(also sets r->h2state = H2_STATE_CLOSED)*/
344             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
345     }
346 }
347 
348 
349 void
350 h2_send_goaway (connection * const con, const request_h2error_t e)
351 {
352     /* future: RFC 7540 Section 6.8 notes that server initiating graceful
353      * connection shutdown SHOULD send GOAWAY with stream id 2^31-1 and a
354      * NO_ERROR code, and later send another GOAWAY with an updated last
355      * stream identifier.  (This is not done here, but doing so would be
356      * friendlier to clients that send streaming requests which the client
357      * is unable to retry.) */
358 
359     if (e != H2_E_NO_ERROR)
360         h2_send_goaway_rst_stream(con);
361     /*XXX: else should send RST_STREAM w/ CANCEL for any active PUSH_PROMISE */
362 
363     h2con * const h2c = con->h2;
364     if (h2c->sent_goaway && (h2c->sent_goaway > 0 || e == H2_E_NO_ERROR))
365         return;
366     h2c->sent_goaway = (e == H2_E_NO_ERROR) ? -1 : (int32_t)e;
367 
368     union {
369       uint8_t c[20];
370       uint32_t u[5];          /*(alignment)*/
371     } goaway = { {            /*(big-endian numbers)*/
372       0x00, 0x00, 0x00        /* padding for alignment; do not send */
373       /* GOAWAY */
374      ,0x00, 0x00, 0x08        /* frame length */
375      ,H2_FTYPE_GOAWAY         /* frame type */
376      ,0x00                    /* frame flags */
377      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
378      ,0x00, 0x00, 0x00, 0x00  /* last-stream-id (fill in below) */
379      ,0x00, 0x00, 0x00, 0x00  /* error code     (fill in below) */
380                               /* additional debug data (*); (optional)
381                                * adjust frame length if any additional
382                                * debug data is sent */
383     } };
384 
385     goaway.u[3] = htonl(h2c->h2_cid); /* last-stream-id */
386     goaway.u[4] = htonl(e);
387     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
388                           (const char *)goaway.c+3, sizeof(goaway)-3);
389 }
390 
391 
392 __attribute_cold__
393 static void
394 h2_send_goaway_e (connection * const con, const request_h2error_t e)
395 {
396     h2_send_goaway(con, e);
397 }
398 
399 
400 static int
401 h2_recv_goaway (connection * const con, const uint8_t * const s, uint32_t len)
402 {
403     /*(s must be entire GOAWAY frame and len the frame length field)*/
404     /*assert(s[3] == H2_FTYPE_GOAWAY);*/
405     UNUSED(len);
406     if (0 != h2_u31(s+5)) { /*(GOAWAY stream id must be 0)*/
407         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
408         return 0;
409     }
410     const uint32_t e = h2_u32(s+13);
411   #if 0
412     /* XXX: debug: could log error code sent by peer */
413   #endif
414   #if 0
415     /* XXX: debug: could log additional debug info (if any) sent by peer */
416     if (len > 8) {
417     }
418   #endif
419   #if 0
420     /* XXX: could validate/use Last-Stream-ID sent by peer */
421     const uint32_t last_id = h2_u31(s+9);
422   #endif
423 
424     /* send PROTOCOL_ERROR back to peer if peer sent an error code
425      * (i.e. not NO_ERROR) in order to terminate connection more quickly */
426     h2_send_goaway(con, e==H2_E_NO_ERROR ? H2_E_NO_ERROR : H2_E_PROTOCOL_ERROR);
427     h2con * const h2c = con->h2;
428     if (0 == h2c->rused) return 0;
429     return 1;
430 }
431 
432 
433 static void
434 h2_recv_rst_stream (connection * const con, const uint8_t * const s, const uint32_t len)
435 {
436     /*(s must be entire RST_STREAM frame and len the frame length field)*/
437     /*assert(s[3] == H2_FTYPE_RST_STREAM);*/
438     if (4 != len) {                  /*(RST_STREAM frame length must be 4)*/
439         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
440         return;
441     }
442     const uint32_t id = h2_u31(s+5);
443     if (0 == id) {                   /*(RST_STREAM id must not be 0)*/
444         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
445         return;
446     }
447     h2con * const h2c = con->h2;
448     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
449         request_st * const r = h2c->r[i];
450         if (r->h2id != id) continue;
451         if (r->h2state == H2_STATE_IDLE) {
452             /*(RST_STREAM must not be for stream in "idle" state)*/
453             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
454             return;
455         }
456         /* XXX: ? add debug trace including error code from RST_STREAM ? */
457         r->state = CON_STATE_ERROR;
458         r->h2state = H2_STATE_CLOSED;
459         return;
460     }
461     /* unknown/inactive stream id
462      * XXX: how should we handle RST_STREAM for unknown/inactive stream id?
463      * (stream id may have been closed recently and server forgot about it,
464      *  but client (peer) sent RST_STREAM prior to receiving stream end from
465      *  server)*/
466   #if 0
467     if (h2c->sent_goaway && h2c->h2_cid < id) return;
468     h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
469   #else
470     if (h2c->h2_cid < id) {
471         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
472         return;
473     }
474   #endif
475 }
476 
477 
478 static void
479 h2_recv_ping (connection * const con, uint8_t * const s, const uint32_t len)
480 {
481   #if 0
482     union {
483       uint8_t c[20];
484       uint32_t u[5];          /*(alignment)*/
485     } ping = { {              /*(big-endian numbers)*/
486       0x00, 0x00, 0x00        /* padding for alignment; do not send */
487       /* PING */
488      ,0x00, 0x00, 0x08        /* frame length */
489      ,H2_FTYPE_PING           /* frame type */
490      ,H2_FLAG_ACK             /* frame flags */
491      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
492      ,0x00, 0x00, 0x00, 0x00  /* opaque            (fill in below) */
493      ,0x00, 0x00, 0x00, 0x00
494     } };
495   #endif
496 
497     /*(s must be entire PING frame and len the frame length field)*/
498     /*assert(s[3] == H2_FTYPE_PING);*/
499     if (8 != len) {                  /*(PING frame length must be 8)*/
500         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
501         return;
502     }
503     s[5] &= ~0x80; /* reserved bit must be ignored */
504     if (0 != h2_u31(s+5)) { /*(PING stream id must be 0)*/
505         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
506         return;
507     }
508     if (s[4] & H2_FLAG_ACK) /*(ignore; unexpected if we did not send PING)*/
509         return;
510     /* reflect PING back to peer with frame flag ACK */
511     /* (9 byte frame header plus 8 byte PING payload = 17 bytes)*/
512     s[4] = H2_FLAG_ACK;
513     chunkqueue_append_mem(con->write_queue, (const char *)s, 17);
514 }
515 
516 
517 static void
518 h2_recv_priority (connection * const con, const uint8_t * const s, const uint32_t len)
519 {
520     /*(s must be entire PRIORITY frame and len the frame length field)*/
521     /*assert(s[3] == H2_FTYPE_PRIORITY);*/
522     if (5 != len) {                  /*(PRIORITY frame length must be 5)*/
523         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
524         return;
525     }
526     const uint32_t id = h2_u31(s+5);
527     if (0 == id) {                   /*(PRIORITY id must not be 0)*/
528         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
529         return;
530     }
531     const uint32_t prio = h2_u31(s+9);
532   #if 0
533     uint32_t exclusive_dependency = (s[9] & 0x80) ? 1 : 0;
534     uint32_t weight = s[13];
535   #endif
536     h2con * const h2c = con->h2;
537     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
538         request_st * const r = h2c->r[i];
539         if (r->h2id != id) continue;
540         /* XXX: TODO: update priority info */
541         if (prio == id) {
542             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
543             return;
544         }
545         return;
546     }
547     /* XXX: TODO: update priority info for unknown/inactive stream */
548     /*if (h2c->sent_goaway && h2c->h2_cid < id) return;*/
549     if (prio == id) {
550         h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
551         return;
552     }
553 }
554 
555 
556 static void
557 h2_recv_window_update (connection * const con, const uint8_t * const s, const uint32_t len)
558 {
559     /*(s must be entire WINDOW_UPDATE frame and len the frame length field)*/
560     /*assert(s[3] == H2_FTYPE_WINDOW_UPDATE);*/
561     if (4 != len) {                  /*(WINDOW_UPDATE frame length must be 4)*/
562         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
563         return;
564     }
565     const uint32_t id = h2_u31(s+5);
566     const int32_t v = (int32_t)h2_u31(s+9);
567     request_st *r = NULL;
568     if (0 == id)
569         r = &con->request;
570     else {
571         h2con * const h2c = con->h2;
572         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
573             request_st * const rr = h2c->r[i];
574             if (rr->h2id != id) continue;
575             r = rr;
576             break;
577         }
578         /* peer should not send WINDOW_UPDATE for an inactive stream,
579          * but RFC 7540 does not explicitly call this out.  On the other hand,
580          * since there may be a temporary mismatch in stream state between
581          * peers, ignore window update if stream id is unknown/inactive.
582          * Also, it is not an error if GOAWAY sent and h2c->h2_cid < id */
583         if (NULL == r) {
584             if (h2c->h2_cid < id && 0 == h2c->sent_goaway)
585                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
586           #if 0
587             /*(needed for h2spec if testing with response < 16k+1 over TLS
588              * or response <= socket send buffer size over cleartext, due to
589              * completing response too quickly for the test frame sequence) */
590             if (v == 0)        /* h2spec: 6.9-2   (after we retired id 1) */
591                 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
592             if (v == INT32_MAX)/* h2spec: 6.9.1-3 (after we retired id 1) */
593                 h2_send_rst_stream_id(id, con, H2_E_FLOW_CONTROL_ERROR);
594           #endif
595             return;
596         }
597         /* MUST NOT be treated as error if stream is in closed state; ignore */
598         if (r->h2state == H2_STATE_CLOSED
599             || r->h2state == H2_STATE_HALF_CLOSED_LOCAL) return;
600     }
601     if (0 == v || r->h2_swin > INT32_MAX - v) {
602         request_h2error_t e = (0 == v)
603           ? H2_E_PROTOCOL_ERROR
604           : H2_E_FLOW_CONTROL_ERROR;
605         if (0 == id)
606             h2_send_goaway_e(con, e);
607         else
608             h2_send_rst_stream(r, con, e);
609         return;
610     }
611     r->h2_swin += v;
612 }
613 
614 
615 static void
616 h2_send_window_update (connection * const con, uint32_t h2id, const uint32_t len)
617 {
618     if (0 == len) return;
619     union {
620       uint8_t c[16];
621       uint32_t u[4];          /*(alignment)*/
622     } window_upd = { {        /*(big-endian numbers)*/
623       0x00, 0x00, 0x00        /* padding for alignment; do not send */
624       /* WINDOW_UPDATE */
625      ,0x00, 0x00, 0x04        /* frame length */
626      ,H2_FTYPE_WINDOW_UPDATE  /* frame type */
627      ,0x00                    /* frame flags */
628      ,0x00, 0x00, 0x00, 0x00  /* stream identifier      (fill in below) */
629      ,0x00, 0x00, 0x00, 0x00  /* window update increase (fill in below) */
630     } };
631 
632     window_upd.u[2] = htonl(h2id);
633     window_upd.u[3] = htonl(len);
634     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
635                           (const char *)window_upd.c+3, sizeof(window_upd)-3);
636 }
637 
638 
639 static void
640 h2_parse_frame_settings (connection * const con, const uint8_t *s, uint32_t len)
641 {
642     /*(s and len must be SETTINGS frame payload)*/
643     /*(caller must validate frame len, frame type == 0x04, frame id == 0)*/
644     h2con * const h2c = con->h2;
645     for (; len >= 6; len -= 6, s += 6) {
646         uint32_t v = h2_u32(s+2);
647         switch (h2_u16(s)) {
648           case H2_SETTINGS_HEADER_TABLE_SIZE:
649             /* encoder may use any table size <= value sent by peer */
650             /* For simple compliance with RFC and constrained memory use,
651              * choose to not increase table size beyond the default 4096,
652              * but allow smaller sizes to be set and then reset up to 4096,
653              * e.g. set to 0 to evict all dynamic table entries,
654              * and then set to 4096 to restore dynamic table use */
655             if (v > 4096) v = 4096;
656             if (v == h2c->s_header_table_size) break;
657             h2c->s_header_table_size = v;
658             lshpack_enc_set_max_capacity(&h2c->encoder, v);
659             break;
660           case H2_SETTINGS_ENABLE_PUSH:
661             if ((v|1) != 1) { /*(v == 0 || v == 1)*/
662                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
663                 return;
664             }
665             h2c->s_enable_push = v;
666             break;
667           case H2_SETTINGS_MAX_CONCURRENT_STREAMS:
668             h2c->s_max_concurrent_streams = v;
669             break;
670           case H2_SETTINGS_INITIAL_WINDOW_SIZE:
671             if (v > INT32_MAX) { /*(2^31 - 1)*/
672                 h2_send_goaway_e(con, H2_E_FLOW_CONTROL_ERROR);
673                 return;
674             }
675             else if (h2c->rused) { /*(update existing streams)*/
676                 /*(underflow is ok; unsigned integer math)*/
677                 /*(h2c->s_initial_window_size is >= 0)*/
678                 int32_t diff =
679                   (int32_t)((uint32_t)v - (uint32_t)h2c->s_initial_window_size);
680                 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
681                     request_st * const r = h2c->r[i];
682                     const int32_t swin = r->h2_swin;
683                     if (r->h2state == H2_STATE_HALF_CLOSED_LOCAL
684                         || r->h2state == H2_STATE_CLOSED) continue;
685                     if (diff >= 0
686                         ? swin > INT32_MAX - diff
687                         : swin < INT32_MIN - diff) {
688                         h2_send_rst_stream(r, con, H2_E_FLOW_CONTROL_ERROR);
689                         continue;
690                     }
691                     r->h2_swin += diff;
692                 }
693             }
694             h2c->s_initial_window_size = (int32_t)v;
695             break;
696           case H2_SETTINGS_MAX_FRAME_SIZE:
697             if (v < 16384 || v > 16777215) { /*[(2^14),(2^24-1)]*/
698                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
699                 return;
700             }
701             h2c->s_max_frame_size = v;
702             break;
703           case H2_SETTINGS_MAX_HEADER_LIST_SIZE:
704             h2c->s_max_header_list_size = v;
705             break;
706           default:
707             break;
708         }
709     }
710 
711     if (len) {
712         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
713         return;
714     }
715 
716     /* caller must send SETTINGS frame with ACK flag,
717      * if appropriate, and if h2c->sent_goaway is not set
718      * (Do not send ACK for Upgrade: h2c and HTTP2-Settings header) */
719 }
720 
721 
722 static void
723 h2_recv_settings (connection * const con, const uint8_t * const s, const uint32_t len)
724 {
725     /*(s must be entire SETTINGS frame, len must be the frame length field)*/
726     /*assert(s[3] == H2_FTYPE_SETTINGS);*/
727     if (0 != h2_u31(s+5)) {/*(SETTINGS stream id must be 0)*/
728         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
729         return;
730     }
731 
732     h2con * const h2c = con->h2;
733     if (!(s[4] & H2_FLAG_ACK)) {
734         h2_parse_frame_settings(con, s+9, len);
735         if (h2c->sent_goaway <= 0)
736             h2_send_settings_ack(con);
737     }
738     else {
739         /* lighttpd currently sends SETTINGS in server preface, and not again,
740          * so this does not have to handle another SETTINGS frame being sent
741          * before receiving an ACK from prior SETTINGS frame.  (If it does,
742          * then we will need some sort of counter.) */
743         if (0 != len)
744             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
745         else if (h2c->sent_settings)
746             h2c->sent_settings = 0;
747         else /* SETTINGS with ACK for SETTINGS frame we did not send */
748             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
749     }
750 }
751 
752 
753 static int
754 h2_recv_end_data (request_st * const r, connection * const con, const uint32_t alen)
755 {
756     chunkqueue * const reqbody_queue = &r->reqbody_queue;
757     r->h2state = (r->h2state == H2_STATE_OPEN)
758       ? H2_STATE_HALF_CLOSED_REMOTE
759       : H2_STATE_CLOSED;
760     if (r->reqbody_length == -1)
761         r->reqbody_length = reqbody_queue->bytes_in + (off_t)alen;
762     else if (r->reqbody_length != reqbody_queue->bytes_in + (off_t)alen) {
763         if (0 == reqbody_queue->bytes_out) {
764             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
765             return 0;
766         } /* else let reqbody streaming consumer handle truncated reqbody */
767     }
768 
769     return 1;
770 }
771 
772 
773 static int
774 h2_recv_data (connection * const con, const uint8_t * const s, const uint32_t len)
775 {
776     /*(s must be entire DATA frame, len must be the frame length field)*/
777     /*assert(s[3] == H2_FTYPE_DATA);*/
778 
779     /* future: consider string refs rather than copying DATA from chunkqueue
780      * or try to consume entire chunk, or to split chunks with less copying */
781 
782     h2con * const h2c = con->h2;
783     const uint32_t id = h2_u31(s+5);
784     if (0 == id || h2c->h2_cid < id) { /*(RST_STREAM id must not be 0)*/
785         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
786         return 0;
787     }
788 
789     uint32_t alen = len; /* actual data len, minus padding */
790     uint32_t pad = 0;
791     if (s[4] & H2_FLAG_PADDED) {
792         pad = s[9];
793         if (pad >= len) {
794             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
795             return 0;
796         }
797         alen -= (1 + pad);
798     }
799 
800     request_st * const h2r = &con->request;
801     if (h2r->h2_rwin <= 0 && 0 != alen) { /*(always proceed if 0 == alen)*/
802         /*(connection_state_machine_h2() must ensure con is rescheduled,
803          * when backends consume data if con->read_queue is not empty,
804          * whether or not con->fd has data to read from the network)*/
805         /*(leave frame in cq to be re-read later)*/
806         return 0;
807     }
808     /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/
809     /*(not worried about underflow while
810      * SETTINGS_MAX_FRAME_SIZE is small (e.g. 16k or 32k) and
811      * SETTINGS_MAX_CONCURRENT_STREAMS is small (h2c->r[8]))*/
812     /*h2r->h2_rwin -= (int32_t)len;*//* update connection recv window (below) */
813 
814     request_st *r = NULL;
815     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
816         request_st * const rr = h2c->r[i];
817         if (rr->h2id != id) continue;
818         r = rr;
819         break;
820     }
821     chunkqueue * const cq = con->read_queue;
822     if (NULL == r) {
823         /* XXX: TODO: might need to keep a list of recently retired streams
824          * for a few seconds so that if we send RST_STREAM, then we ignore
825          * further DATA and do not send connection error, though recv windows
826          * still must be updated. */
827         if (h2c->h2_cid < id || (!h2c->sent_goaway && 0 != alen))
828             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
829         chunkqueue_mark_written(cq, 9+len);
830         return 0;
831     }
832 
833     if (r->h2state == H2_STATE_CLOSED
834         || r->h2state == H2_STATE_HALF_CLOSED_REMOTE) {
835         h2_send_rst_stream_id(id, con, H2_E_STREAM_CLOSED);
836         chunkqueue_mark_written(cq, 9+len);
837         h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/
838         return 1;
839     }
840 
841     if (r->h2_rwin <= 0 && 0 != alen) {/*(always proceed if 0==alen)*/
842         if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN) {
843             /*(connection_state_machine_h2() must ensure con is rescheduled,
844              * when backends consume data if con->read_queue is not empty,
845              * whether or not con->fd has data to read from the network)*/
846             /*(leave frame in cq to be re-read later)*/
847             return 0;
848         }
849     }
850     /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/
851     /*(undeflow will not occur (with reasonable SETTINGS_MAX_FRAME_SIZE used)
852      * since windows updated elsewhere and data is streamed to temp files if
853      * not FDEVENT_STREAM_REQUEST_BUFMIN)*/
854     /*r->h2_rwin -= (int32_t)len;*/
855     h2_send_window_update(con, r->h2id, len); /*(r->h2_rwin)*/
856     h2_send_window_update(con, 0, len);       /*(h2r->h2_rwin)*/
857 
858     chunkqueue * const dst = &r->reqbody_queue;
859 
860     if (r->reqbody_length >= 0 && r->reqbody_length < dst->bytes_in + alen) {
861         /* data exceeds Content-Length specified (client mistake) */
862       #if 0 /* truncate */
863         alen = r->reqbody_length - dst->bytes_in;
864         /*(END_STREAM may follow in 0-length DATA frame or HEADERS (trailers))*/
865       #else /* reject */
866         h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
867         chunkqueue_mark_written(cq, 9+len);
868         return 1;
869       #endif
870     }
871 
872     /*(accounting for mod_accesslog and mod_rrdtool)*/
873     chunkqueue * const rq = &r->read_queue;
874     rq->bytes_in  += (off_t)alen;
875     rq->bytes_out += (off_t)alen;
876 
877     /* r->conf.max_request_size is in kBytes */
878     const off_t max_request_size = (off_t)r->conf.max_request_size << 10;
879     if (0 != max_request_size
880         && dst->bytes_in + (off_t)alen > max_request_size) {
881         if (0 == r->http_status) {
882             r->http_status = 413; /* Payload Too Large */
883             log_error(r->conf.errh, __FILE__, __LINE__,
884               "request-size too long: %lld -> 413",
885               (long long) (dst->bytes_in + (off_t)alen));
886         }
887         chunkqueue_mark_written(cq, 9+len);
888         return 1;
889     }
890 
891     if ((s[4] & H2_FLAG_END_STREAM) && !h2_recv_end_data(r, con, alen)) {
892         chunkqueue_mark_written(cq, 9+len);
893         return 1;
894     }
895 
896     chunkqueue_mark_written(cq, 9 + ((s[4] & H2_FLAG_PADDED) ? 1 : 0));
897 
898   #if 0
899     if (pad) {
900         /* XXX: future optimization: if data is at end of chunk, then adjust
901          * size of chunk by reducing c->mem->used to avoid copying chunk
902          * when it is split (below) since the split would be due to padding
903          * (also adjust cq->bytes_out)*/
904         /*(might quickly check 9+len == cqlen if cqlen passed in as param)*/
905         /*(then check if cq->last contains all of padding, or leave alone)*/
906         /*(if handled here, then set pad = 0 here)*/
907     }
908   #endif
909 
910     /*(similar decision logic to that in http_chunk_uses_tempfile())*/
911     const chunk * const c = dst->last;
912     if ((c && c->type == FILE_CHUNK && c->file.is_temp)
913         || chunkqueue_length(dst) + alen > 65536) {
914         log_error_st * const errh = r->conf.errh;
915         if (0 != chunkqueue_steal_with_tempfiles(dst, cq, (off_t)alen, errh)) {
916             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
917             return 0;
918         }
919     }
920     else
921         chunkqueue_steal(dst, cq, (off_t)alen);
922 
923     if (pad)
924         chunkqueue_mark_written(cq, pad);
925     return 1;
926 }
927 
928 
929 __attribute_cold__
930 static uint32_t
931 h2_frame_cq_compact (chunkqueue * const cq, uint32_t len)
932 {
933     /*(marked cold since most frames not expect to cross chunk boundary)*/
934 
935     /* caller must guarantee that chunks in chunkqueue are all MEM_CHUNK */
936     /* caller should check (chunkqueue_length(cq) >= len) before calling,
937      * or should check that returned value >= len */
938 
939     chunkqueue_compact_mem(cq, len);
940     return buffer_string_length(cq->first->mem) - (uint32_t)cq->first->offset;
941 }
942 
943 
944 __attribute_cold__
945 static uint32_t
946 h2_recv_continuation (uint32_t n, uint32_t clen, const off_t cqlen, chunkqueue * const cq, connection * const con)
947 {
948     chunk *c = cq->first;
949     uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
950     uint32_t m = n;
951     uint32_t flags;
952     h2con * const h2c = con->h2;
953     const uint32_t fsize = h2c->s_max_frame_size;
954     const uint32_t id = h2_u31(s+5);
955     do {
956         if (cqlen < n+9) return n+9; /* incomplete frame; go on */
957         if (clen < n+9) {
958             clen = h2_frame_cq_compact(cq, n+9);
959             c = cq->first; /*(reload after h2_frame_cq_compact())*/
960             s = (uint8_t *)(c->mem->ptr + c->offset);
961         }
962         if (s[n+3] != H2_FTYPE_CONTINUATION) {
963             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
964             return 0;
965         }
966         flags = s[n+4];
967         const uint32_t flen = h2_u24(s+n);
968         if (id != h2_u32(s+n+5)) {
969             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
970             return 0;
971         }
972         if (flen > fsize) {
973             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
974             return 0;
975         }
976         n += 9+flen;
977         if (n >= 65536) { /*(very oversized for hpack)*/
978             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
979             return 0;
980         }
981         if (clen < n) {
982             clen = h2_frame_cq_compact(cq, n);
983             if (clen < n) return n; /* incomplete frame; go on */
984             c = cq->first; /*(reload after h2_frame_cq_compact())*/
985             s = (uint8_t *)(c->mem->ptr + c->offset);
986         }
987     } while (!(flags & H2_FLAG_END_HEADERS));
988 
989     /* If some CONTINUATION frames were concatenated to earlier frames while
990      * processing above, but END_HEADERS were not received, then the next time
991      * data was read, initial frame size might exceed SETTINGS_MAX_FRAME_SIZE.
992      * (This describes the current lighttpd implementation in h2_parse_frames())
993      * While a flag could be set and checked to avoid this, such situations of
994      * large HEADERS (and CONTINUATION) across multiple network reads is
995      * expected to be rare.  Reparse and concatenate below.
996      *
997      * Aside: why would the authors of RFC 7540 go through the trouble of
998      * creating a CONTINUATION frame that must be special-cased when use of
999      * CONTINUATION is so restricted e.g. no other intervening frames and
1000      * that HEADERS and PUSH_PROMISE HPACK must be parsed as a single block?
1001      * IMHO, it would have been simpler to avoid CONTINUATION entirely, and have
1002      * a special-case for HEADERS and PUSH_PROMISE to be allowed to exceed
1003      * SETTINGS_MAX_FRAME_SIZE with implementations providing a different limit.
1004      * While intermediates would not know such a limit of origin servers,
1005      * there could have been a reasonable default set with a different SETTINGS
1006      * parameter aimed just at HEADERS and PUSH_PROMISE.  The parameter
1007      * SETTINGS_MAX_HEADER_LIST_SIZE could even have been (re)used, had it been
1008      * given a reasonable initial value instead of "unlimited", since HPACK
1009      * encoded headers are smaller than the HPACK decoded headers to which the
1010      * limit SETTINGS_MAX_HEADER_LIST_SIZE applies. */
1011 
1012     n = m; /* reset n to beginning of first CONTINUATION frame */
1013 
1014     /* Eliminate padding from first frame (HEADERS or PUSH_PROMISE) if PADDED */
1015     if (s[4] & H2_FLAG_PADDED) {
1016         const uint32_t plen = s[9];
1017         /* validate padding */
1018         const uint32_t flen = h2_u24(s);
1019         if (flen < 1 + plen + ((s[n+4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
1020             /* Padding that exceeds the size remaining for the header block
1021              * fragment MUST be treated as a PROTOCOL_ERROR. */
1022             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1023             return 0;
1024         }
1025         /* set padding to 0 since we will overwrite padding in merge below */
1026         /* (alternatively, could memmove() 9 bytes of frame header over the
1027          *  pad length octet, remove PADDED flag, add 1 to c->offset,
1028          *  add 1 to s, subtract 1 from clen and substract 1 from cqlen,
1029          *  substract 1 from n, add 1 to cq->bytes_out) */
1030         s[9] = 0;
1031         /* set offset to beginning of padding at end of first frame */
1032         m -= plen;
1033         /* XXX: layer violation; adjusts chunk.c internal accounting */
1034         cq->bytes_out += plen;
1035     }
1036 
1037   #ifdef __COVERITY__
1038     /* Coverity does not notice that values used in s are checked.
1039      * Although silencing here, would prefer not to do so since doing so
1040      * disables Coverity from reporting questionable modifications which
1041      * might be made to the code in the future. */
1042     __coverity_tainted_data_sink__(s);
1043   #endif
1044 
1045     do {
1046         const uint32_t flen = h2_u24(s+n);
1047       #ifdef __COVERITY__ /*flen values were checked in do {} while loop above*/
1048         if (clen < n+9+flen) {
1049             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1050             return 0;
1051         }
1052       #endif
1053         flags = s[n+4];
1054         memmove(s+m, s+n+9, flen);
1055         m += flen;
1056         n += 9+flen;
1057         /* XXX: layer violation; adjusts chunk.c internal accounting */
1058         cq->bytes_out += 9;
1059     } while (!(flags & H2_FLAG_END_HEADERS));
1060     /* overwrite frame size */
1061     m -= 9; /*(temporarily remove frame header from len)*/
1062     s[0] = (m >> 16) & 0xFF;
1063     s[1] = (m >>  8) & 0xFF;
1064     s[2] = (m      ) & 0xFF;
1065     m += 9;
1066     /* adjust chunk c->mem */
1067     if (n < clen) { /*(additional frames after CONTINUATION)*/
1068         memmove(s+m, s+n, clen-n);
1069         n = m + (clen-n);
1070     }
1071     else
1072         n = m;
1073     buffer_string_set_length(c->mem, n + (uint32_t)c->offset);
1074 
1075     return m;
1076 }
1077 
1078 
1079 __attribute_cold__
1080 static request_st *
1081 h2_recv_trailers_r (connection * const con, h2con * const h2c, const uint32_t id, const uint32_t flags)
1082 {
1083     /* rant: RFC 7230 HTTP/1.1 trailer-part would have been much simpler
1084      * to support in RFC 7540 HTTP/2 as a distinct frame type rather than
1085      * HEADERS.  As trailers are not known at the time the request is made,
1086      * reuse of such trailers is limited and so a theoretical TRAILERS frame
1087      * could have been implemented without HPACK encoding, and would have
1088      * been more straightforward to implement than overloading and having to
1089      * handle multiple cases for HEADERS.  TRAILERS support could then also
1090      * be optional, like in HTTP/1.1 */
1091     request_st *r = NULL;
1092     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
1093         request_st * const rr = h2c->r[i];
1094         if (rr->h2id != id) continue;
1095         r = rr;
1096         break;
1097     }
1098     if (NULL == r) {
1099         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1100         return NULL;
1101     }
1102     if (r->h2state != H2_STATE_OPEN
1103         && r->h2state != H2_STATE_HALF_CLOSED_LOCAL) {
1104         h2_send_rst_stream(r, con, H2_E_STREAM_CLOSED);
1105         return NULL;
1106     }
1107     /* RFC 7540 is not explicit in restricting HEADERS (trailers) following
1108      * (optional) DATA frames, but in following HTTP/1.1, we limit to single
1109      * (optional) HEADERS (+ CONTINUATIONs) after (optional) DATA frame(s)
1110      * and require that the HEADERS frame set END_STREAM flag. */
1111     if (!(flags & H2_FLAG_END_STREAM)) {
1112         h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1113         return NULL;
1114     }
1115 
1116     return h2_recv_end_data(r, con, 0) ? r : NULL;
1117 }
1118 
1119 
1120 static void
1121 h2_parse_headers_frame (request_st * const restrict r, const unsigned char *psrc, const uint32_t plen, const int trailers)
1122 {
1123     h2con * const h2c = r->con->h2;
1124     struct lshpack_dec * const restrict decoder = &h2c->decoder;
1125     const unsigned char * const endp = psrc + plen;
1126     http_header_parse_ctx hpctx;
1127     hpctx.hlen     = 0;
1128     hpctx.pseudo   = 1;
1129     hpctx.scheme   = 0;
1130     hpctx.trailers = trailers;
1131     hpctx.max_request_field_size = r->conf.max_request_field_size;
1132     hpctx.http_parseopts = r->conf.http_parseopts;
1133     const int log_request_header = r->conf.log_request_header;
1134     int rc = LSHPACK_OK;
1135     /*buffer_clear(&r->target);*//*(initial state)*/
1136 
1137     /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
1138     buffer * const tb = r->tmp_buf;
1139     force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
1140     const lsxpack_strlen_t tbsz = (tb->size <= LSXPACK_MAX_STRLEN)
1141       ? tb->size
1142       : LSXPACK_MAX_STRLEN;
1143 
1144     /* note: #define LSHPACK_DEC_HTTP1X_OUTPUT 1 (default) configures
1145      * decoder to produce output in format: "field-name: value\r\n"
1146      * future: modify build system to define value to 0 in lshpack.h
1147      * against which lighttpd builds (or define value in build systems)
1148      * Then adjust code below to not use the HTTP/1.x compatibility,
1149      * as it is less efficient to copy into HTTP/1.1 request and reparse
1150      * than it is to directly parse each decoded header line. */
1151     lsxpack_header_t lsx;
1152     while (psrc < endp) {
1153         memset(&lsx, 0, sizeof(lsxpack_header_t));
1154         lsx.buf = tb->ptr;
1155         lsx.val_len = tbsz;
1156         rc = lshpack_dec_decode(decoder, &psrc, endp, &lsx);
1157         if (0 == lsx.name_len)
1158             rc = LSHPACK_ERR_BAD_DATA;
1159         if (rc == LSHPACK_OK) {
1160             hpctx.k = lsx.buf+lsx.name_offset;
1161             hpctx.v = lsx.buf+lsx.val_offset;
1162             hpctx.klen = lsx.name_len;
1163             hpctx.vlen = lsx.val_len;
1164             /*assert(lsx.hpack_index < sizeof(lshpack_idx_http_header));*/
1165             hpctx.id = lshpack_idx_http_header[lsx.hpack_index];
1166 
1167             if (log_request_header)
1168                 log_error(r->conf.errh, __FILE__, __LINE__,
1169                   "fd:%d id:%u rqst: %.*s: %.*s", r->con->fd, r->h2id,
1170                   (int)hpctx.klen, hpctx.k, (int)hpctx.vlen, hpctx.v);
1171 
1172           #if 0
1173             /* might not be worth special-casing pseudo headers here and
1174              * repeating the code in http_request_parse_header() to avoid
1175              * memcmp() for pseudo headers (request.c does not know ls-hpack)*/
1176             if (hpctx.pseudo && lsx.hpack_index
1177                 && lsx.hpack_index < LSHPACK_HDR_STATUS_200 && !trailers) {
1178                 /* lsx.hpack_index:
1179                  *   LSHPACK_HDR_AUTHORITY
1180                  *   LSHPACK_HDR_METHOD_GET
1181                  *   LSHPACK_HDR_METHOD_POST
1182                  *   LSHPACK_HDR_PATH
1183                  *   LSHPACK_HDR_PATH_INDEX_HTML
1184                  *   LSHPACK_HDR_SCHEME_HTTP
1185                  *   LSHPACK_HDR_SCHEME_HTTPS
1186                  */
1187             }
1188           #endif
1189 
1190             r->http_status = http_request_parse_header(r, &hpctx);
1191             if (0 != r->http_status)
1192                 break;
1193         }
1194       #if 0 /*(see catch-all below)*/
1195         /* Send GOAWAY (further below) (decoder state not maintained on error)
1196          * (see comments above why decoder state must be maintained) */
1197         /* XXX: future: could try to send :status 431 here
1198          * and reset other active streams in H2_STATE_OPEN */
1199         else if (rc == LSHPACK_ERR_MORE_BUF) {
1200             /* XXX: TODO if (r->conf.log_request_header_on_error) */
1201             r->http_status = 431; /* Request Header Fields Too Large */
1202             /*(try to avoid reading/buffering more data for this request)*/
1203             r->h2_rwin = 0; /*(out-of-sync with peer, but is error case)*/
1204             /*r->h2state = H2_STATE_HALF_CLOSED_REMOTE*/
1205             /* psrc was not advanced if LSHPACK_ERR_MORE_BUF;
1206              * processing must stop (since not retrying w/ larger buf)*/
1207             break;
1208         }
1209       #endif
1210         else { /* LSHPACK_ERR_BAD_DATA */
1211             /* GOAWAY with H2_E_PROTOCOL_ERROR is not specific enough
1212              * to tell peer to not retry request, so send RST_STREAM
1213              * (slightly more specific, but not by much) before GOAWAY*/
1214             /* LSHPACK_ERR_MORE_BUF is treated as an attack, send GOAWAY
1215              * (h2r->tmp_buf was resized to 64k in h2_init_con()) */
1216             request_h2error_t err = H2_E_COMPRESSION_ERROR;
1217             if (rc != LSHPACK_ERR_BAD_DATA) {
1218                 /* LSHPACK_ERR_TOO_LARGE, LSHPACK_ERR_MORE_BUF */
1219                 err = H2_E_PROTOCOL_ERROR;
1220                 h2_send_rst_stream(r, r->con, err);
1221             }
1222             if (!h2c->sent_goaway && !trailers)
1223                 h2c->h2_cid = r->h2id;
1224             h2_send_goaway_e(r->con, err);
1225             if (!trailers) {
1226                 h2_retire_stream(r, r->con);
1227                 return;
1228             }
1229             else {
1230                 r->state = CON_STATE_ERROR;
1231                 r->h2state = H2_STATE_CLOSED;
1232             }
1233             break;
1234         }
1235     }
1236 
1237     hpctx.hlen += 2;
1238     r->rqst_header_len += hpctx.hlen;
1239     /*(accounting for mod_accesslog and mod_rrdtool)*/
1240     chunkqueue * const rq = &r->read_queue;
1241     rq->bytes_in  += (off_t)hpctx.hlen;
1242     rq->bytes_out += (off_t)hpctx.hlen;
1243 
1244     if (0 == r->http_status && LSHPACK_OK == rc) {
1245         if (hpctx.pseudo)
1246             r->http_status =
1247               http_request_validate_pseudohdrs(r, hpctx.scheme,
1248                                                hpctx.http_parseopts);
1249         if (0 == r->http_status)
1250             http_request_headers_process_h2(r, r->con->proto_default_port);
1251     }
1252 }
1253 
1254 
1255 static int
1256 h2_recv_headers (connection * const con, uint8_t * const s, uint32_t flen)
1257 {
1258   #ifdef __COVERITY__
1259     /* Coverity does not notice that values used in s are checked.
1260      * Although silencing here, would prefer not to do so since doing so
1261      * disables Coverity from reporting questionable modifications which
1262      * might be made to the code in the future. */
1263     __coverity_tainted_data_sink__(s);
1264   #endif
1265     request_st *r = NULL;
1266     h2con * const h2c = con->h2;
1267     const uint32_t id = h2_u31(s+5);
1268     if (0 == id) { /* HEADERS, PUSH_PROMISE stream id must != 0 */
1269         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1270         return 0;
1271     }
1272     if (!(id & 1)) { /* stream id from client must be odd */
1273         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1274         return 0;
1275     }
1276 
1277     request_st * const h2r = &con->request;
1278     int trailers = 0;
1279 
1280     if (id > h2c->h2_cid) {
1281         if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r)) {
1282             if (0 == h2c->sent_settings) { /*(see h2_recv_settings() comments)*/
1283                 /* too many active streams; refuse new stream */
1284                 h2c->h2_cid = id;
1285                 h2_send_rst_stream_id(id, con, H2_E_REFUSED_STREAM);
1286                 return 1;
1287             }
1288             else {
1289                 /* alternative: stop processing frames and defer processing this
1290                  * HEADERS frame until num active streams drops below limit.
1291                  * lighttpd sends SETTINGS_MAX_CONCURRENT_STREAMS <limit> with
1292                  * server Connection Preface, so a well-behaved client will
1293                  * adjust after it sends its initial requests.
1294                  * (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)*/
1295                 return -1;
1296             }
1297         }
1298         /* Note: MUST process HPACK decode even if already sent GOAWAY.
1299          * This is necessary since there may be active streams not in
1300          * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly
1301          * receiving DATA and, more relevantly, still might receive HEADERS
1302          * frame with trailers, for which the decoder state is required.
1303          * XXX: future might try to reduce other processing done if sent
1304          *      GOAWAY, e.g. might avoid allocating (request_st *r) */
1305         r = h2_init_stream(h2r, con);
1306         r->h2id = id;
1307         r->h2state = (s[4] & H2_FLAG_END_STREAM)
1308           ? H2_STATE_HALF_CLOSED_REMOTE
1309           : H2_STATE_OPEN;
1310         r->state = CON_STATE_REQUEST_END;
1311         /* Note: timestamps here are updated only after receipt of entire header
1312          * (HEADERS frame might have been sent in multiple packets
1313          *  and CONTINUATION frames may have been sent in multiple packets)
1314          * (affects high precision timestamp, if enabled)
1315          * (large sets of headers are not typical, and even when they do
1316          *  occur, they will typically be sent within the same second)
1317          * (future: might keep high precision timestamp in h2con when first
1318          *  packet of HEADERS or PUSH_PROMISE is received, and clear that
1319          *  timestamp when frame + CONTINUATION(s) are complete (so that
1320          *  re-read of initial frame does not overwrite the timestamp))
1321          */
1322         r->start_hp.tv_sec = log_epoch_secs;
1323         if (r->conf.high_precision_timestamps)
1324             log_clock_gettime_realtime(&r->start_hp);
1325     }
1326     else {
1327         r = h2_recv_trailers_r(con, h2c, id, s[4]); /* (cold code path) */
1328         if (NULL == r)
1329             return (h2c->sent_goaway > 0) ? 0 : 1;
1330         trailers = 1;
1331     }
1332 
1333     const unsigned char *psrc = s + 9;
1334     uint32_t alen = flen;
1335     if (s[4] & H2_FLAG_PADDED) {
1336         ++psrc;
1337         const uint32_t pad = s[9];
1338         if (flen < 1 + pad + ((s[4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
1339             /* Padding that exceeds the size remaining for the header block
1340              * fragment MUST be treated as a PROTOCOL_ERROR. */
1341             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1342             if (!trailers)
1343                 h2_retire_stream(r, con);
1344             else {
1345                 r->state = CON_STATE_ERROR;
1346                 r->h2state = H2_STATE_CLOSED;
1347             }
1348             return 0;
1349         }
1350         alen -= (1 + pad); /*(alen is adjusted for PRIORITY below)*/
1351     }
1352     if (s[4] & H2_FLAG_PRIORITY) {
1353         /* XXX: TODO: handle PRIORITY (prio fields start at *psrc) */
1354         const uint32_t prio = h2_u31(psrc);
1355         if (prio == id) {
1356             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1357             if (!trailers)
1358                 h2_retire_stream(r, con);
1359             return 1;
1360         }
1361       #if 0
1362         uint32_t exclusive_dependency = (psrc[0] & 0x80) ? 1 : 0;
1363         uint32_t weight = psrc[4];
1364       #endif
1365         psrc += 5;
1366         alen -= 5;
1367     }
1368 
1369     h2_parse_headers_frame(r, psrc, alen, trailers);
1370 
1371   #if 0 /*(handled in h2_parse_frames() as a connection error)*/
1372     /* not handled here:
1373      * r is invalid if h2_parse_headers_frame() HPACK decode error */
1374     if (s[3] == H2_FTYPE_PUSH_PROMISE && !trailers) {
1375         /* Had to process HPACK to keep HPACK tables sync'd with peer but now
1376          * discard the request if PUSH_PROMISE, since not expected, as this code
1377          * is running as a server, not as a client.
1378          * XXX: future might try to reduce other processing done if
1379          * discarding, e.g. might avoid allocating (request_st *r) */
1380         /* rant: PUSH_PROMISE could have been a flag on HEADERS frame
1381          *       instead of an independent frame type */
1382         r->http_status = 0;
1383         h2_retire_stream(r, con);
1384     }
1385   #endif
1386 
1387     if (!h2c->sent_goaway) {
1388         h2c->h2_cid = id;
1389         if (!light_btst(r->rqst_htags, HTTP_HEADER_CONTENT_LENGTH))
1390             r->reqbody_length = (s[4] & H2_FLAG_END_STREAM) ? 0 : -1;
1391       #if 0
1392         else if (r->reqbody_length > 0 && (s[4] & H2_FLAG_END_STREAM)) {
1393             /*(handled in connection_handle_read_post_state())*/
1394             /* XXX: TODO if (r->conf.log_request_header_on_error) */
1395             r->http_status = 400; /* Bad Request */
1396         }
1397       #endif
1398 
1399         /* RFC 7540 Section 8. HTTP Message Exchanges
1400          * 8.1.2.6. Malformed Requests and Responses
1401          *   For malformed requests, a server MAY send an HTTP
1402          *   response prior to closing or resetting the stream.
1403          * However, h2spec expects stream PROTOCOL_ERROR.
1404          * (This is unfortunate, since we would rather send
1405          *  400 Bad Request which tells client *do not* retry
1406          *  the bad request without modification)
1407          * https://github.com/summerwind/h2spec/issues/120
1408          * https://github.com/summerwind/h2spec/issues/121
1409          * https://github.com/summerwind/h2spec/issues/122
1410          */
1411       #if 0
1412         if (400 == r->http_status && !trailers) {
1413             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1414             h2_retire_stream(r, con);
1415         }
1416       #endif
1417     }
1418     else if (h2c->h2_cid < id) {
1419         /* Had to process HPACK to keep HPACK tables sync'd with peer
1420          * but now discard the request if id is after id sent in GOAWAY.
1421          * XXX: future might try to reduce other processing done if
1422          * discarding, e.g. might avoid allocating (request_st *r) */
1423         r->http_status = 0;
1424         h2_retire_stream(r, con);
1425     }
1426 
1427     return 1;
1428 }
1429 
1430 
1431 int
1432 h2_parse_frames (connection * const con)
1433 {
1434     /* read and process HTTP/2 frames from socket */
1435     h2con * const h2c = con->h2;
1436     chunkqueue * const cq = con->read_queue;
1437     /* initial max frame size is the minimum: 16k
1438      * (lighttpd does not currently increase max frame size)
1439      * (lighttpd does not currently decrease max frame size)
1440      * (XXX: If SETTINGS_MAX_FRAME_SIZE were increased and then decreased,
1441      *       should accept the larger frame size until SETTINGS is ACK'd) */
1442     const uint32_t fsize = h2c->s_max_frame_size;
1443     for (off_t cqlen = chunkqueue_length(cq); cqlen >= 9; ) {
1444         chunk *c = cq->first;
1445         /*assert(c->type == MEM_CHUNK);*/
1446         /* copy data if frame header crosses chunk boundary
1447          * future: be more efficient than blind full chunk copy */
1448         uint32_t clen = buffer_string_length(c->mem) - c->offset;
1449         if (clen < 9) {
1450             clen = h2_frame_cq_compact(cq, 9);
1451             c = cq->first; /*(reload after h2_frame_cq_compact())*/
1452         }
1453         uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1454         uint32_t flen = h2_u24(s);
1455         if (flen > fsize) {
1456             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1457             return 0;
1458         }
1459 
1460         /*(handle PUSH_PROMISE as connection error further below)*/
1461         /*if (s[3] == H2_FTYPE_HEADERS || s[3] == H2_FTYPE_PUSH_PROMISE)*/
1462 
1463         if (s[3] == H2_FTYPE_HEADERS) {
1464             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1465             if (clen < 9+flen) {
1466                 clen = h2_frame_cq_compact(cq, 9+flen);
1467                 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1468                 s = (uint8_t *)(c->mem->ptr + c->offset);
1469             }
1470 
1471             if (!(s[4] & H2_FLAG_END_HEADERS)) {
1472                 /* collect CONTINUATION frames (cold code path) */
1473                 /* note: h2_recv_continuation() return value is overloaded
1474                  * and the resulting clen is 9+flen of *concatenated* frames */
1475                 clen = h2_recv_continuation(9+flen, clen, cqlen, cq, con);
1476                 if (0 == clen)    return 0;
1477                 if (cqlen < clen) return 1; /* incomplete frames; go on */
1478                 c = cq->first; /*(reload after h2_recv_continuation())*/
1479                 s = (uint8_t *)(c->mem->ptr + c->offset);
1480                 /* frame size was also updated and might (legitimately)
1481                  * exceed SETTINGS_MAX_FRAME_SIZE, so do not test fsize again */
1482                 flen = h2_u24(s);
1483                 /* recalculate after CONTINUATION removed */
1484                 cqlen = chunkqueue_length(cq);
1485             }
1486 
1487           #ifdef __COVERITY__
1488             /* Coverity does not notice that values used in s are checked.
1489              * Although silencing here, would prefer not to do so since doing so
1490              * disables Coverity from reporting questionable modifications which
1491              * might be made to the code in the future. */
1492             __coverity_tainted_data_sink__(s);
1493           #endif
1494 
1495             int rc = h2_recv_headers(con, s, flen);
1496             cqlen -= (9+flen);
1497             if (rc >= 0)
1498                 chunkqueue_mark_written(cq, 9+flen);
1499             if (rc <= 0)
1500                 return 0;
1501             con->read_idle_ts = log_monotonic_secs;
1502         }
1503         else if (s[3] == H2_FTYPE_DATA) {
1504             /* future: might try to stream data for incomplete frames,
1505              * but that would require keeping additional state for partially
1506              * read frames, including cleaning up if errors occur.
1507              * Since well-behaved clients do not intentionally send partial
1508              * frames, and try to resend if socket buffers are full, this is
1509              * probably not a big concern in practice. */
1510             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1511             con->read_idle_ts = log_monotonic_secs;
1512             /*(h2_recv_data() must consume frame from cq or else return 0)*/
1513             if (!h2_recv_data(con, s, flen))
1514                 return 0;
1515             cqlen -= (9+flen);
1516         }
1517         else {
1518             /* frame types below are expected to be small
1519              * most frame types below have fixed (small) size
1520              *   4 bytes - WINDOW_UPDATE
1521              *   5 bytes - PRIORITY
1522              *   8 bytes - PING
1523              *   4 bytes - RST_STREAM
1524              * some are variable size
1525              *     SETTINGS (6 * #settings; 6 defined in RFC 7540 Section 6.5)
1526              *     GOAWAY   (8 + optional additional debug data (variable))
1527              * XXX: might add sanity check for a max flen here,
1528              *      before waiting to read partial frame
1529              *      (fsize limit is still enforced above for all frames)
1530              */
1531             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1532             if (clen < 9+flen) {
1533                 clen = h2_frame_cq_compact(cq, 9+flen); UNUSED(clen);
1534                 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1535                 s = (uint8_t *)(c->mem->ptr + c->offset);
1536             }
1537             switch (s[3]) { /* frame type */
1538               case H2_FTYPE_WINDOW_UPDATE:
1539                 h2_recv_window_update(con, s, flen);
1540                 break;
1541               case H2_FTYPE_PRIORITY:
1542                 h2_recv_priority(con, s, flen);
1543                 break;
1544               case H2_FTYPE_SETTINGS:
1545                 h2_recv_settings(con, s, flen);
1546                 break;
1547               case H2_FTYPE_PING:
1548                 h2_recv_ping(con, s, flen);
1549                 break;
1550               case H2_FTYPE_RST_STREAM:
1551                 h2_recv_rst_stream(con, s, flen);
1552                 break;
1553               case H2_FTYPE_GOAWAY:
1554                 if (!h2_recv_goaway(con, s, flen)) return 0;
1555                 break;
1556               case H2_FTYPE_PUSH_PROMISE: /*not expected from client*/
1557               case H2_FTYPE_CONTINUATION: /*handled with HEADERS*/
1558                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1559                 return 0;
1560               default: /* ignore unknown frame types */
1561                 break;
1562             }
1563             cqlen -= (9+flen);
1564             chunkqueue_mark_written(cq, 9+flen);
1565         }
1566 
1567         if (h2c->sent_goaway > 0) return 0;
1568     }
1569 
1570     return 1;
1571 }
1572 
1573 
1574 int
1575 h2_want_read (connection * const con)
1576 {
1577     chunkqueue * const cq = con->read_queue;
1578     if (chunkqueue_is_empty(cq)) return 1;
1579 
1580     /* check for partial frame */
1581     const off_t cqlen = chunkqueue_length(cq);
1582     if (cqlen < 9) return 1;
1583     chunk *c = cq->first;
1584     uint32_t clen = buffer_string_length(c->mem) - c->offset;
1585     if (clen < 9) {
1586         clen = h2_frame_cq_compact(cq, 9);
1587         c = cq->first; /*(reload after h2_frame_cq_compact())*/
1588     }
1589     uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1590     uint32_t flen = h2_u24(s);
1591     if (clen < 9+flen) return 1;
1592 
1593     /* check if not HEADERS, or if HEADERS has END_HEADERS flag */
1594     if (s[3] != H2_FTYPE_HEADERS || (s[4] & H2_FLAG_END_HEADERS))
1595         return 0;
1596 
1597     /* check for partial CONTINUATION frames */
1598     for (uint32_t n = 9+flen; cqlen >= n+9; n += 9+flen) {
1599         if (clen < n+9) {
1600             clen = h2_frame_cq_compact(cq, n+9);
1601             c = cq->first; /*(reload after h2_frame_cq_compact())*/
1602             s = (uint8_t *)(c->mem->ptr + c->offset);
1603         }
1604         flen = h2_u24(s+n);
1605         if (cqlen < n+9+flen) return 1; /* incomplete frame; go on */
1606         if (s[4] & H2_FLAG_END_HEADERS) return 0;
1607     }
1608 
1609     return 1;
1610 }
1611 
1612 
1613 static int
1614 h2_recv_client_connection_preface (connection * const con)
1615 {
1616     /* check if the client Connection Preface (24 bytes) has been received
1617      * (initial SETTINGS frame should immediately follow, but is not checked) */
1618     chunkqueue * const cq = con->read_queue;
1619     if (chunkqueue_length(cq) < 24) {
1620         chunk * const c = cq->first;
1621         if (c && buffer_string_length(c->mem) - c->offset >= 4) {
1622             const char * const s = c->mem->ptr + c->offset;
1623             if (s[0]!='P'||s[1]!='R'||s[2]!='I'||s[3]!=' ') {
1624                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1625                 return 1; /* error; done receiving connection preface */
1626             }
1627         }
1628         return 0; /*(not ready yet)*/
1629     }
1630 
1631     static const char h2preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1632     chunk *c = cq->first;
1633     const uint32_t clen = buffer_string_length(c->mem) - c->offset;
1634     if (clen < 24) h2_frame_cq_compact(cq, 24);
1635     c = cq->first; /*(reload after h2_frame_cq_compact())*/
1636     const uint8_t * const s = (uint8_t *)(c->mem->ptr + c->offset);
1637     if (0 == memcmp(s, h2preface, 24)) /* sizeof(h2preface)-1) */
1638         chunkqueue_mark_written(cq, 24);
1639     else
1640         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1641     return 1; /* done receiving connection preface (even if error occurred) */
1642 }
1643 
1644 
1645 __attribute_cold__
1646 static int
1647 h2_read_client_connection_preface (struct connection * const con, chunkqueue * const cq, off_t max_bytes)
1648 {
1649     /* temporary con->network_read() filter until connection preface received */
1650 
1651     /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1652     void ** const hctx = con->plugin_ctx+0; /*(0 idx used for h2)*/
1653     int(* const network_read)(struct connection *, chunkqueue *, off_t) =
1654       (int(*)(struct connection *, chunkqueue *, off_t))(uintptr_t)(*hctx);
1655     if (max_bytes < 24) max_bytes = 24; /*(should not happen)*/
1656     int rc = (network_read)(con, cq, max_bytes);
1657     if (NULL == con->h2) return rc; /*(unexpected; already cleaned up)*/
1658     if (-1 != rc && h2_recv_client_connection_preface(con)) {
1659         con->network_read = network_read;
1660         *hctx = NULL;
1661         /*(intentionally update timestamp only after reading preface complete)*/
1662         con->read_idle_ts = log_monotonic_secs;
1663     }
1664     return rc;
1665 }
1666 
1667 
1668 void
1669 h2_init_con (request_st * const restrict h2r, connection * const restrict con, const buffer * const restrict http2_settings)
1670 {
1671     h2con * const h2c = calloc(1, sizeof(h2con));
1672     force_assert(h2c);
1673     con->h2 = h2c;
1674     con->read_idle_ts = log_monotonic_secs;
1675     con->keep_alive_idle = h2r->conf.max_keep_alive_idle;
1676 
1677     h2r->h2_rwin = 65535;                 /* h2 connection recv window */
1678     h2r->h2_swin = 65535;                 /* h2 connection send window */
1679     /* settings sent from peer */         /* initial values */
1680     h2c->s_header_table_size     = 4096;  /* SETTINGS_HEADER_TABLE_SIZE      */
1681     h2c->s_enable_push           = 1;     /* SETTINGS_ENABLE_PUSH            */
1682     h2c->s_max_concurrent_streams= ~0u;   /* SETTINGS_MAX_CONCURRENT_STREAMS */
1683     h2c->s_initial_window_size   = 65535; /* SETTINGS_INITIAL_WINDOW_SIZE    */
1684     h2c->s_max_frame_size        = 16384; /* SETTINGS_MAX_FRAME_SIZE         */
1685     h2c->s_max_header_list_size  = ~0u;   /* SETTINGS_MAX_HEADER_LIST_SIZE   */
1686     h2c->sent_settings           = log_monotonic_secs;/*(send SETTINGS below)*/
1687 
1688     lshpack_dec_init(&h2c->decoder);
1689     lshpack_enc_init(&h2c->encoder);
1690     lshpack_enc_use_hist(&h2c->encoder, 1);
1691 
1692     if (http2_settings) /*(if Upgrade: h2c)*/
1693         h2_parse_frame_settings(con, (uint8_t *)CONST_BUF_LEN(http2_settings));
1694 
1695     static const uint8_t h2settings[] = { /*(big-endian numbers)*/
1696       /* SETTINGS */
1697       0x00, 0x00, 0x0c        /* frame length */ /* 6 * 2 for two settings */
1698      ,H2_FTYPE_SETTINGS       /* frame type */
1699      ,0x00                    /* frame flags */
1700      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
1701      ,0x00, H2_SETTINGS_MAX_CONCURRENT_STREAMS
1702      ,0x00, 0x00, 0x00, 0x08  /* 8 */
1703      #if 0  /* ? explicitly disable dynamic table ? (and adjust frame length) */
1704             /* If this is sent, must wait until peer sends SETTINGS with ACK
1705              * before disabling dynamic table in HPACK decoder */
1706             /*(before calling lshpack_dec_set_max_capacity(&h2c->decoder, 0))*/
1707      ,0x00, H2_SETTINGS_HEADER_TABLE_SIZE
1708      ,0x00, 0x00, 0x00, 0x00  /* 0 */
1709      #endif
1710      #if 0  /* ? explicitly disable push ?       (and adjust frame length) */
1711      ,0x00, H2_SETTINGS_ENABLE_PUSH
1712      ,0x00, 0x00, 0x00, 0x00  /* 0 */
1713      #endif
1714      #if 0  /* ? increase from default (65535) ? (and adjust frame length) */
1715      ,0x00, H2_SETTINGS_INITIAL_WINDOW_SIZE
1716      ,0x00, 0x02, 0x00, 0x00  /* 131072 */
1717      #endif
1718      #if 0  /* ? increase from default (16384) ? (and adjust frame length) */
1719      ,0x00, H2_SETTINGS_MAX_FRAME_SIZE
1720      ,0x00, 0x00, 0x80, 0x00  /* 32768 */
1721      #endif
1722      ,0x00, H2_SETTINGS_MAX_HEADER_LIST_SIZE
1723      ,0x00, 0x00, 0xFF, 0xFF  /* 65535 */
1724 
1725      #if 0
1726       /* WINDOW_UPDATE */
1727      ,0x00, 0x00, 0x04        /* frame length */
1728      ,H2_FTYPE_WINDOW_UPDATE  /* frame type */
1729      ,0x00                    /* frame flags */
1730      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
1731      ,0x00, 0x01, 0x00, 0x01  /* 65537 */ /* increase connection rwin to 128k */
1732      #endif
1733     };
1734 
1735     /*h2r->h2_rwin += 65537;*//*(enable if WINDOWS_UPDATE is sent above)*/
1736     chunkqueue_append_mem(con->write_queue,
1737                           (const char *)h2settings, sizeof(h2settings));
1738 
1739     if (!h2_recv_client_connection_preface(con)) {
1740         /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1741         con->plugin_ctx[0] = (void *)(uintptr_t)con->network_read;
1742         con->network_read = h2_read_client_connection_preface;
1743         /* note: no steps taken to reset con->network_read() on error
1744          * as con->network_read() is always set in connection_accepted() */
1745     }
1746 
1747     buffer_string_prepare_copy(h2r->tmp_buf, 65535);
1748 }
1749 
1750 
1751 static void
1752 h2_send_hpack (request_st * const r, connection * const con, const char *data, uint32_t dlen, const uint32_t flags)
1753 {
1754     union {
1755       uint8_t c[12];
1756       uint32_t u[3];          /*(alignment)*/
1757     } headers = { {           /*(big-endian numbers)*/
1758       0x00, 0x00, 0x00        /* padding for alignment; do not send */
1759       /* HEADERS */
1760      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
1761      ,H2_FTYPE_HEADERS        /* frame type */
1762      ,(uint8_t)flags          /* frame flags (e.g. END_STREAM for trailers) */
1763      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
1764     } };
1765 
1766     headers.u[2] = htonl(r->h2id);
1767 
1768     /* similar to h2_send_data(), but unlike DATA frames there is a HEADERS
1769      * frame potentially followed by CONTINUATION frame(s) here, and the final
1770      * HEADERS or CONTINUATION frame here has END_HEADERS flag set.
1771      * For trailers, END_STREAM flag is set on HEADERS frame. */
1772 
1773     /*(approximate space needed for frames (header + payload)
1774      * with slight over-estimate of 16 bytes per frame header (> 9)
1775      * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
1776      * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
1777      *  per frame can be appoximated with (dlen>>10) + 9)*/
1778     buffer * const b =
1779       chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
1780     char * restrict ptr = b->ptr;
1781     h2con * const h2c = con->h2;
1782     const uint32_t fsize = h2c->s_max_frame_size;
1783     do {
1784         const uint32_t len = dlen < fsize ? dlen : fsize;
1785         headers.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
1786         headers.c[4] = (len >>  8) & 0xFF;
1787         headers.c[5] = (len      ) & 0xFF;
1788         if (len == dlen)
1789             headers.c[7] |= H2_FLAG_END_HEADERS;
1790       #if 0
1791         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
1792                               (const char *)headers.c+3, sizeof(headers)-3);
1793         chunkqueue_append_mem(con->write_queue, data, len);
1794       #else
1795         memcpy(ptr, headers.c+3, sizeof(headers)-3);
1796         memcpy(ptr+sizeof(headers)-3, data, len);
1797         ptr  += len + sizeof(headers)-3;
1798       #endif
1799         data += len;
1800         dlen -= len;
1801         /*(include H2_FLAG_END_STREAM in HEADERS frame, not CONTINUATION)*/
1802         headers.c[6] = H2_FTYPE_CONTINUATION; /*(if additional frames needed)*/
1803         headers.c[7] = 0x00; /*(off +3 to skip over align pad)*/
1804     } while (dlen);
1805     buffer_string_set_length(b, (uint32_t)(ptr - b->ptr));
1806     chunkqueue_append_buffer_commit(con->write_queue);
1807 }
1808 
1809 
1810 __attribute_cold__
1811 static void
1812 h2_log_response_header_lsx(request_st * const r, const lsxpack_header_t * const lsx)
1813 {
1814     log_error(r->conf.errh, __FILE__, __LINE__,
1815       "fd:%d id:%u resp: %.*s: %.*s", r->con->fd, r->h2id,
1816       (int)lsx->name_len, lsx->buf + lsx->name_offset,
1817       (int)lsx->val_len,  lsx->buf + lsx->val_offset);
1818 }
1819 
1820 
1821 __attribute_cold__
1822 static void
1823 h2_log_response_header(request_st * const r, const int len, const char * const hdr)
1824 {
1825     log_error(r->conf.errh, __FILE__, __LINE__,
1826       "fd:%d id:%u resp: %.*s", r->con->fd, r->h2id, len, hdr);
1827 }
1828 
1829 
1830 void
1831 h2_send_headers (request_st * const r, connection * const con)
1832 {
1833     /*(set keep_alive_idle; out-of-place and non-event for most configs,
1834      * but small attempt to (maybe) preserve behavior for specific configs)*/
1835     con->keep_alive_idle = r->conf.max_keep_alive_idle;
1836 
1837     /* specialized version of http_response_write_header(); send headers
1838      * directly to HPACK encoder, rather than double-buffering in chunkqueue */
1839 
1840     if (304 == r->http_status
1841         && light_btst(r->resp_htags, HTTP_HEADER_CONTENT_ENCODING))
1842         http_header_response_unset(r, HTTP_HEADER_CONTENT_ENCODING,
1843                                    CONST_STR_LEN("Content-Encoding"));
1844 
1845     /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
1846     buffer * const tb = r->tmp_buf;
1847     force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
1848     unsigned char *dst = (unsigned char *)tb->ptr;
1849     unsigned char * const dst_end = (unsigned char *)tb->ptr + tb->size;
1850 
1851     h2con * const h2c = con->h2;
1852     struct lshpack_enc * const encoder = &h2c->encoder;
1853     lsxpack_header_t lsx;
1854     uint32_t alen = 7+3+4; /* ":status: xxx\r\n" */
1855     const int log_response_header = r->conf.log_response_header;
1856     const int resp_header_repeated = r->resp_header_repeated;
1857 
1858     char status[12] = ":status: ";
1859     int x = r->http_status; /*(expect status < 1000; should be [100-599])*/
1860     status[11] = (x % 10) + '0';
1861     status[10] = (x / 10 % 10) + '0';
1862     status[9]  = (x / 100) + '0';
1863 
1864     if (log_response_header)
1865         h2_log_response_header(r, 12, status);
1866 
1867     memset(&lsx, 0, sizeof(lsxpack_header_t));
1868     lsx.buf = status;
1869     lsx.name_offset = 0;
1870     lsx.name_len = 7;
1871     lsx.val_offset = 9;
1872     lsx.val_len = 3;
1873     switch (r->http_status) {
1874       case 200: lsx.hpack_index = LSHPACK_HDR_STATUS_200; break;
1875       case 204: lsx.hpack_index = LSHPACK_HDR_STATUS_204; break;
1876       case 206: lsx.hpack_index = LSHPACK_HDR_STATUS_206; break;
1877       case 304: lsx.hpack_index = LSHPACK_HDR_STATUS_304; break;
1878       case 400: lsx.hpack_index = LSHPACK_HDR_STATUS_400; break;
1879       case 404: lsx.hpack_index = LSHPACK_HDR_STATUS_404; break;
1880       case 500: lsx.hpack_index = LSHPACK_HDR_STATUS_500; break;
1881       default:
1882         break;
1883     }
1884     dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
1885     if (dst == (unsigned char *)tb->ptr) {
1886         h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1887         return;
1888     }
1889 
1890     /* add all headers */
1891     for (uint32_t i = 0, used = r->resp_headers.used; i < used; ++i) {
1892         data_string * const restrict ds =(data_string *)r->resp_headers.data[i];
1893         const uint32_t klen = buffer_string_length(&ds->key);
1894         const uint32_t vlen = buffer_string_length(&ds->value);
1895         const char * const restrict k = ds->key.ptr;
1896         if (0 == vlen || 0 == klen) continue;
1897         alen += klen + vlen + 4;
1898 
1899         if (alen > LSXPACK_MAX_STRLEN) {
1900             /* ls-hpack default limit (UINT16_MAX) is per-line, due to field
1901              * sizes of lsx.name_offset,lsx.name_len,lsx.val_offset,lsx.val_len
1902              * However, similar to elsewhere, limit total size of expanded
1903              * headers to (very generous) 64k - 1.  Peers might allow less. */
1904             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1905             return;
1906         }
1907 
1908         /* HTTP/2 requires lowercase keys
1909          * ls-hpack requires key and value be in same buffer
1910          * Since keys are typically short, append (and lowercase) key onto
1911          * end of value buffer */
1912         char * const v = buffer_string_prepare_append(&ds->value, klen);
1913         if (ds->ext != HTTP_HEADER_OTHER) {
1914             memcpy(v, http_header_lc[ds->ext], klen);
1915         }
1916         else {
1917             if ((k[0] & 0xdf) == 'X' && http_response_omit_header(r, ds)) {
1918                 alen -= klen + vlen + 4;
1919                 continue;
1920             }
1921             for (uint32_t j = 0; j < klen; ++j)
1922                 v[j] = !light_isupper(k[j]) ? k[j] : (k[j] | 0x20);
1923         }
1924         /*buffer_commit(&ds->value, klen);*//*(not necessary; truncated below)*/
1925 
1926         uint32_t voff = 0;
1927         const char *n;
1928         lsx.buf = ds->value.ptr;
1929         do {
1930             n = !resp_header_repeated
1931               ? NULL
1932               : memchr(lsx.buf+voff, '\n', vlen - voff);
1933 
1934             memset(&lsx, 0, sizeof(lsxpack_header_t));
1935             lsx.hpack_index = http_header_lshpack_idx[ds->ext];
1936             lsx.buf = ds->value.ptr;
1937             lsx.name_offset = vlen;
1938             lsx.name_len = klen;
1939             lsx.val_offset = voff;
1940             if (NULL == n)
1941                 lsx.val_len = vlen - voff;
1942             else {
1943                 /* multiple headers (same field-name) separated by "\r\n"
1944                  * and then "field-name: " (see http_header_response_insert())*/
1945                 voff = (uint32_t)(n + 1 - lsx.buf);
1946                 lsx.val_len = voff - 2 - lsx.val_offset; /*(-2 for "\r\n")*/
1947                 voff += klen + 2;
1948             }
1949 
1950             if (log_response_header)
1951                 h2_log_response_header_lsx(r, &lsx);
1952 
1953             unsigned char * const dst_in = dst;
1954             dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
1955             if (dst == dst_in) {
1956                 buffer_string_set_length(&ds->value, vlen); /*(restore prior value)*/
1957                 h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1958                 return;
1959             }
1960         } while (n);
1961         buffer_string_set_length(&ds->value, vlen); /*(restore prior value)*/
1962     }
1963 
1964     if (!light_btst(r->resp_htags, HTTP_HEADER_DATE)) {
1965         /* HTTP/1.1 and later requires a Date: header */
1966         /* "date: " 6-chars + 30-chars for "%a, %d %b %Y %T GMT" + '\0' */
1967         static time_t tlast = 0;
1968         static char tstr[36] = "date: ";
1969 
1970         memset(&lsx, 0, sizeof(lsxpack_header_t));
1971         lsx.buf = tstr;
1972         lsx.name_offset = 0;
1973         lsx.name_len = 4;
1974         lsx.val_offset = 6;
1975         lsx.val_len = 29;
1976         lsx.hpack_index = LSHPACK_HDR_DATE;
1977 
1978         /* cache the generated timestamp */
1979         const time_t cur_ts = log_epoch_secs;
1980         if (__builtin_expect ( (tlast != cur_ts), 0))
1981             http_date_time_to_str(tstr+6, sizeof(tstr)-6, (tlast = cur_ts));
1982 
1983         alen += 35+2;
1984 
1985         if (log_response_header)
1986             h2_log_response_header(r, 35, tstr);
1987 
1988         unsigned char * const dst_in = dst;
1989         dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
1990         if (dst == dst_in) {
1991             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1992             return;
1993         }
1994     }
1995 
1996     if (!light_btst(r->resp_htags, HTTP_HEADER_SERVER)
1997         && !buffer_string_is_empty(r->conf.server_tag)) {
1998         buffer * const b = chunk_buffer_acquire();
1999         const uint32_t vlen = buffer_string_length(r->conf.server_tag);
2000         buffer_append_str2(b, CONST_STR_LEN("server: "),
2001                               r->conf.server_tag->ptr, vlen);
2002 
2003         alen += 6+vlen+4;
2004 
2005         if (log_response_header)
2006             h2_log_response_header(r, (int)6+vlen+2, b->ptr);
2007 
2008         memset(&lsx, 0, sizeof(lsxpack_header_t));
2009         lsx.buf = b->ptr;
2010         lsx.name_offset = 0;
2011         lsx.name_len = 6;
2012         lsx.val_offset = 8;
2013         lsx.val_len = vlen;
2014         lsx.hpack_index = LSHPACK_HDR_SERVER;
2015         unsigned char * const dst_in = dst;
2016         dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2017         chunk_buffer_release(b);
2018         if (dst == dst_in) {
2019             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2020             return;
2021         }
2022     }
2023 
2024     alen += 2; /* "virtual" blank line ("\r\n") ending headers */
2025     r->resp_header_len = alen;
2026     /*(accounting for mod_accesslog and mod_rrdtool)*/
2027     chunkqueue * const wq = &r->write_queue;
2028     wq->bytes_in  += (off_t)alen;
2029     wq->bytes_out += (off_t)alen;
2030 
2031     const uint32_t dlen = (uint32_t)((char *)dst - tb->ptr);
2032     const uint32_t flags =
2033       (r->resp_body_finished && chunkqueue_is_empty(&r->write_queue))
2034         ? H2_FLAG_END_STREAM
2035         : 0;
2036     h2_send_hpack(r, con, tb->ptr, dlen, flags);
2037 }
2038 
2039 
2040 __attribute_cold__
2041 __attribute_noinline__
2042 static void
2043 h2_send_headers_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen, uint32_t flags)
2044 {
2045     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
2046     hoff[0] = 1;                         /* number of lines */
2047     hoff[1] = 0;                         /* base offset for all lines */
2048     /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
2049     uint32_t rc = http_header_parse_hoff(hdrs, hlen, hoff);
2050     if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
2051         || 1 == hoff[0]) { /*(initial blank line (should not happen))*/
2052         /* error if headers incomplete or too many header fields */
2053         log_error(r->conf.errh, __FILE__, __LINE__,
2054                   "oversized response-header");
2055         hoff[0] = 1;
2056         hoff[1] = 0;
2057         http_header_parse_hoff(CONST_STR_LEN(":status: 500\r\n\r\n"), hoff);
2058     }
2059 
2060     /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
2061     buffer * const tb = r->tmp_buf;
2062     force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
2063     unsigned char *dst = (unsigned char *)tb->ptr;
2064     unsigned char * const dst_end = (unsigned char *)tb->ptr + tb->size;
2065 
2066     h2con * const h2c = con->h2;
2067     struct lshpack_enc * const encoder = &h2c->encoder;
2068     lsxpack_header_t lsx;
2069 
2070     int i = 1;
2071     if (hdrs[0] == ':') {
2072         i = 2;
2073         /* expect first line to contain ":status: ..." if pseudo-header,
2074          * and expecting single pseudo-header for headers, zero for trailers */
2075         /*assert(0 == memcmp(hdrs, ":status: ", sizeof(":status: ")-1));*/
2076         memset(&lsx, 0, sizeof(lsxpack_header_t));
2077         *(const char **)&lsx.buf = hdrs;
2078         lsx.name_offset = 0;
2079         lsx.name_len = sizeof(":status")-1;
2080         lsx.val_offset = lsx.name_len + 2;
2081         lsx.val_len = 3;
2082         dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2083         if (dst == (unsigned char *)tb->ptr) {
2084             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2085             return;
2086         }
2087     }
2088 
2089     /*(note: not expecting any other pseudo-headers)*/
2090 
2091     /* note: expects field-names are lowercased (http_response_write_header())*/
2092 
2093     for (; i < hoff[0]; ++i) {
2094         const char *k = hdrs + ((i > 1) ? hoff[i] : 0);
2095         const char *end = hdrs + hoff[i+1];
2096         const char *v = memchr(k, ':', end-k);
2097         /* XXX: DOES NOT handle line wrapping (which is deprecated by RFCs)
2098          * (not expecting line wrapping; not produced internally by lighttpd,
2099          *  though possible from backends or with custom lua code)*/
2100         if (NULL == v || k == v) continue;
2101         uint32_t klen = v - k;
2102         if (0 == klen) continue;
2103         do { ++v; } while (*v == ' ' || *v == '\t'); /*(expect single ' ')*/
2104       #ifdef __COVERITY__
2105         /*(k has at least .:\n by now, so end[-2] valid)*/
2106         force_assert(end >= k + 2);
2107       #endif
2108         if (end[-2] != '\r') /*(header line must end "\r\n")*/
2109             continue;
2110         end -= 2;
2111         uint32_t vlen = end - v;
2112         if (0 == vlen) continue;
2113         memset(&lsx, 0, sizeof(lsxpack_header_t));
2114         *(const char **)&lsx.buf = hdrs;
2115         lsx.name_offset = k - hdrs;
2116         lsx.name_len = klen;
2117         lsx.val_offset = v - hdrs;
2118         lsx.val_len = vlen;
2119         unsigned char * const dst_in = dst;
2120         dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
2121         if (dst == dst_in) {
2122             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2123             return;
2124         }
2125     }
2126     uint32_t dlen = (uint32_t)((char *)dst - tb->ptr);
2127     h2_send_hpack(r, con, tb->ptr, dlen, flags);
2128 }
2129 
2130 
2131 static void
2132 h2_send_1xx_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen)
2133 {
2134     h2_send_headers_block(r, con, hdrs, hlen, 0);
2135 }
2136 
2137 
2138 int
2139 h2_send_1xx (request_st * const r, connection * const con)
2140 {
2141     buffer * const b = chunk_buffer_acquire();
2142 
2143     buffer_copy_string_len(b, CONST_STR_LEN(":status: "));
2144     buffer_append_int(b, r->http_status);
2145     for (uint32_t i = 0; i < r->resp_headers.used; ++i) {
2146         const data_string * const ds = (data_string *)r->resp_headers.data[i];
2147         const uint32_t klen = buffer_string_length(&ds->key);
2148         const uint32_t vlen = buffer_string_length(&ds->value);
2149         if (0 == klen || 0 == vlen) continue;
2150         buffer_append_str2(b, CONST_STR_LEN("\r\n"), ds->key.ptr, klen);
2151         buffer_append_str2(b, CONST_STR_LEN(": "), ds->value.ptr, vlen);
2152     }
2153     buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
2154 
2155     h2_send_1xx_block(r, con, CONST_BUF_LEN(b));
2156 
2157     chunk_buffer_release(b);
2158     return 1; /* for http_response_send_1xx_cb */
2159 }
2160 
2161 
2162 void
2163 h2_send_100_continue (request_st * const r, connection * const con)
2164 {
2165     /* 100 Continue is small and will always fit in SETTING_MAX_FRAME_SIZE;
2166      * i.e. there will not be any CONTINUATION frames here */
2167 
2168     /* XXX: need to update hpack dynamic table,
2169      * or else could hard-code header block fragment
2170      * { 0x48, 0x03, 0x31, 0x30, 0x30 }
2171      */
2172 
2173     /* short header block, so reuse shared code used for trailers
2174      * rather than adding something specific for ls-hpack here */
2175 
2176     h2_send_1xx_block(r, con, CONST_STR_LEN(":status: 100\r\n\r\n"));
2177 }
2178 
2179 
2180 static void
2181 h2_send_end_stream_data (request_st * const r, connection * const con);
2182 
2183 __attribute_cold__
2184 __attribute_noinline__
2185 static void
2186 h2_send_end_stream_trailers (request_st * const r, connection * const con, const buffer * const trailers)
2187 {
2188     /*(trailers are merged into response headers if trailers are received before
2189      * sending response headers to client.  However, if streaming response, then
2190      * trailers might need handling here)*/
2191 
2192     /* parse and lowercase field-names in trailers */
2193     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
2194     hoff[0] = 1;                         /* number of lines */
2195     hoff[1] = 0;                         /* base offset for all lines */
2196     /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
2197     uint32_t rc = http_header_parse_hoff(CONST_BUF_LEN(trailers), hoff);
2198     if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
2199         || 1 == hoff[0]) { /*(initial blank line)*/
2200         /* skip trailers if incomplete, too many fields, or too long (> 64k-1)*/
2201         h2_send_end_stream_data(r, con);
2202         return;
2203     }
2204 
2205     char * const ptr = trailers->ptr;
2206     for (int i = 1; i < hoff[0]; ++i) {
2207         char *k = ptr + ((i > 1) ? hoff[i] : 0);
2208         if (*k == ':') {
2209             /*(pseudo-header should not appear in trailers)*/
2210             h2_send_end_stream_data(r, con);
2211             return;
2212         }
2213         const char * const colon = memchr(k, ':', ptr+hoff[i+1]-k);
2214         if (NULL == colon) continue;
2215         do {
2216             if (light_isupper(*k)) *k |= 0x20;
2217         } while (++k != colon);
2218     }
2219 
2220     h2_send_headers_block(r, con, CONST_BUF_LEN(trailers), H2_FLAG_END_STREAM);
2221 }
2222 
2223 
2224 #if 0 /*(replaced by h2_send_headers())*/
2225 void
2226 h2_send_cqheaders (request_st * const r, connection * const con)
2227 {
2228     /*(assumes HTTP/1.1 response headers have been prepended as first chunk)
2229      *(future: if r->write_queue is bypassed for headers, adjust
2230      * r->write_queue bytes counts (bytes_in, bytes_out) with header len)*/
2231     /* note: expects field-names are lowercased (http_response_write_header())*/
2232     chunk * const c = r->write_queue.first;
2233     const uint32_t len = buffer_string_length(c->mem) - (uint32_t)c->offset;
2234     uint32_t flags = (r->resp_body_finished && NULL == c->next)
2235       ? H2_FLAG_END_STREAM
2236       : 0;
2237     h2_send_headers_block(r, con, c->mem->ptr + c->offset, len, flags);
2238     chunkqueue_mark_written(&r->write_queue, len);
2239 }
2240 #endif
2241 
2242 
2243 #if 0
2244 
2245 void
2246 h2_send_data (request_st * const r, connection * const con, const char *data, uint32_t dlen)
2247 {
2248     /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
2249 
2250     union {
2251       uint8_t c[12];
2252       uint32_t u[3];          /*(alignment)*/
2253     } dataframe = { {         /*(big-endian numbers)*/
2254       0x00, 0x00, 0x00        /* padding for alignment; do not send */
2255       /* DATA */
2256      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
2257      ,H2_FTYPE_DATA           /* frame type */
2258      ,0x00                    /* frame flags */
2259      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
2260     } };
2261 
2262     dataframe.u[2] = htonl(r->h2id);
2263 
2264     /* XXX: does not provide an optimization to send final set of data with
2265      *      END_STREAM flag; see h2_send_end_stream_data() to end stream */
2266 
2267     /* adjust stream and connection windows */
2268     /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
2269     request_st * const h2r = &con->request;
2270     if (r->h2_swin   < 0) return;
2271     if (h2r->h2_swin < 0) return;
2272     if ((int32_t)dlen > r->h2_swin)   dlen = (uint32_t)r->h2_swin;
2273     if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
2274     if (0 == dlen) return;
2275     r->h2_swin   -= (int32_t)dlen;
2276     h2r->h2_swin -= (int32_t)dlen;
2277 
2278     /* XXX: future: should have an interface which processes chunkqueue
2279      * and takes string refs to mmap FILE_CHUNK to avoid extra copying
2280      * since the result is likely to be consumed by TLS modules */
2281 
2282     /*(approximate space needed for frames (header + payload)
2283      * with slight over-estimate of 16 bytes per frame header (> 9)
2284      * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
2285      * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
2286      *  per frame can be appoximated with (dlen>>10) + 9)*/
2287     buffer * const b =
2288       chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
2289     char * restrict ptr = b->ptr;
2290     h2con * const h2c = con->h2;
2291     const uint32_t fsize = h2c->s_max_frame_size;
2292     do {
2293         const uint32_t len = dlen < fsize ? dlen : fsize;
2294         dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
2295         dataframe.c[4] = (len >>  8) & 0xFF;
2296         dataframe.c[5] = (len      ) & 0xFF;
2297       #if 0
2298         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
2299                               (const char *)dataframe.c+3, sizeof(dataframe)-3);
2300         chunkqueue_append_mem(con->write_queue, data, len);
2301       #else
2302         memcpy(ptr, dataframe.c+3, sizeof(dataframe)-3);
2303         memcpy(ptr+sizeof(dataframe)-3, data, len);
2304         ptr  += len + sizeof(dataframe)-3;
2305       #endif
2306         data += len;
2307         dlen -= len;
2308     } while (dlen);
2309     buffer_string_set_length(b, (uint32_t)(ptr - b->ptr));
2310     chunkqueue_append_buffer_commit(con->write_queue);
2311 }
2312 
2313 #endif
2314 
2315 
2316 void
2317 h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const cq, uint32_t dlen)
2318 {
2319     /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
2320 
2321     union {
2322       uint8_t c[12];
2323       uint32_t u[3];          /*(alignment)*/
2324     } dataframe = { {         /*(big-endian numbers)*/
2325       0x00, 0x00, 0x00        /* padding for alignment; do not send */
2326       /* DATA */
2327      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
2328      ,H2_FTYPE_DATA           /* frame type */
2329      ,0x00                    /* frame flags */
2330      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
2331     } };
2332 
2333     dataframe.u[2] = htonl(r->h2id);
2334 
2335     /* XXX: does not provide an optimization to send final set of data with
2336      *      END_STREAM flag; see h2_send_end_stream_data() to end stream */
2337 
2338     /* adjust stream and connection windows */
2339     /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
2340     request_st * const h2r = &con->request;
2341     if (r->h2_swin   < 0) return;
2342     if (h2r->h2_swin < 0) return;
2343     if ((int32_t)dlen > r->h2_swin)   dlen = (uint32_t)r->h2_swin;
2344     if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
2345     if (0 == dlen) return;
2346     r->h2_swin   -= (int32_t)dlen;
2347     h2r->h2_swin -= (int32_t)dlen;
2348 
2349     /* XXX: future: should have an interface which processes chunkqueue
2350      * and takes string refs to mmap FILE_CHUNK to avoid extra copying
2351      * since the result is likely to be consumed by TLS modules */
2352 
2353     h2con * const h2c = con->h2;
2354     const uint32_t fsize = h2c->s_max_frame_size;
2355     do {
2356         const uint32_t len = dlen < fsize ? dlen : fsize;
2357         dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
2358         dataframe.c[4] = (len >>  8) & 0xFF;
2359         dataframe.c[5] = (len      ) & 0xFF;
2360         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
2361                               (const char *)dataframe.c+3, sizeof(dataframe)-3);
2362         chunkqueue_steal(con->write_queue, cq, (off_t)dlen);
2363         dlen -= len;
2364     } while (dlen);
2365 }
2366 
2367 
2368 static void
2369 h2_send_end_stream_data (request_st * const r, connection * const con)
2370 {
2371     union {
2372       uint8_t c[12];
2373       uint32_t u[3];          /*(alignment)*/
2374     } dataframe = { {         /*(big-endian numbers)*/
2375       0x00, 0x00, 0x00        /* padding for alignment; do not send */
2376       /* DATA */
2377      ,0x00, 0x00, 0x00        /* frame length */
2378      ,H2_FTYPE_DATA           /* frame type */
2379      ,H2_FLAG_END_STREAM      /* frame flags */
2380      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
2381     } };
2382 
2383     dataframe.u[2] = htonl(r->h2id);
2384     r->h2state = H2_STATE_CLOSED;
2385     /*(ignore window updates when sending 0-length DATA frame with END_STREAM)*/
2386     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
2387                           (const char *)dataframe.c+3, sizeof(dataframe)-3);
2388 }
2389 
2390 
2391 void
2392 h2_send_end_stream (request_st * const r, connection * const con)
2393 {
2394     if (r->state != CON_STATE_ERROR && r->resp_body_finished) {
2395         /* CON_STATE_RESPONSE_END */
2396         if (r->gw_dechunk && r->gw_dechunk->done
2397             && !buffer_is_empty(&r->gw_dechunk->b))
2398             h2_send_end_stream_trailers(r, con, &r->gw_dechunk->b);
2399         else
2400             h2_send_end_stream_data(r, con);
2401     }
2402     else { /* CON_STATE_ERROR */
2403         h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2404     }
2405 }
2406 
2407 
2408 /*
2409  * (XXX: might move below to separate file)
2410  */
2411 #include "base64.h"
2412 #include "chunk.h"
2413 #include "plugin.h"
2414 #include "plugin_config.h"
2415 #include "reqpool.h"
2416 
2417 
2418 static request_st *
2419 h2_init_stream (request_st * const h2r, connection * const con)
2420 {
2421     h2con * const h2c = con->h2;
2422     ++con->request_count;
2423     force_assert(h2c->rused < sizeof(h2c->r)/sizeof(*h2c->r));
2424     /* initialize stream as subrequest (request_st *) */
2425     request_st * const r = request_acquire(con);
2426     /* XXX: TODO: assign default priority, etc.
2427      *      Perhaps store stream id and priority in separate table */
2428     h2c->r[h2c->rused++] = r;
2429     r->h2_rwin = h2c->s_initial_window_size;
2430     r->h2_swin = h2c->s_initial_window_size;
2431     r->http_version = HTTP_VERSION_2;
2432 
2433     /* copy config state from h2r */
2434     server * const srv = con->srv;
2435     const uint32_t used = srv->config_context->used;
2436     r->conditional_is_valid = h2r->conditional_is_valid;
2437     memcpy(r->cond_cache, h2r->cond_cache, used * sizeof(cond_cache_t));
2438   #ifdef HAVE_PCRE_H
2439     if (used > 1) /*(save 128b per con if no conditions)*/
2440         memcpy(r->cond_match, h2r->cond_match, used * sizeof(cond_match_t));
2441   #endif
2442     /*(see config_reset_config())*/
2443     r->server_name = h2r->server_name;
2444     memcpy(&r->conf, &h2r->conf, sizeof(request_config));
2445 
2446     /* stream id must be assigned by caller */
2447     return r;
2448 }
2449 
2450 
2451 static void
2452 h2_release_stream (request_st * const r, connection * const con)
2453 {
2454     if (r->http_status) {
2455         /* (see comment in connection_handle_response_end_state()) */
2456         plugins_call_handle_request_done(r);
2457 
2458       #if 0
2459         /* (fuzzy accounting for mod_accesslog, mod_rrdtool to avoid
2460          *  double counting, but HTTP/2 framing and HPACK-encoded headers in
2461          *  con->read_queue and con->write_queue are not equivalent to the
2462          *  HPACK-decoded headers and request and response bodies in stream
2463          *  r->read_queue and r->write_queue) */
2464         /* DISABLED since mismatches invalidate the relationship between
2465          * con->bytes_in and con->bytes_out */
2466         con->read_queue->bytes_in   -= r->read_queue.bytes_in;
2467         con->write_queue->bytes_out -= r->write_queue.bytes_out;
2468       #else
2469         UNUSED(con);
2470       #endif
2471     }
2472 
2473     request_release(r);
2474 }
2475 
2476 
2477 void
2478 h2_retire_stream (request_st *r, connection * const con)
2479 {
2480     if (r == NULL) return; /*(should not happen)*/
2481     h2con * const h2c = con->h2;
2482     request_st ** const ar = h2c->r;
2483     uint32_t i = 0, rused = h2c->rused;
2484     while (i < rused && ar[i] != r) ++i;
2485     if (i != rused) {
2486         /* swap with last element; might need to revisit if ordered by priority */
2487         /*if (i != --rused) ar[i] = ar[rused];*/
2488         /* shift elements; currently choosing to preserve order requested */
2489         if (i != --rused) memmove(ar+i, ar+i+1, (rused-i)*sizeof(*ar));
2490         h2c->r[(h2c->rused = rused)] = NULL;
2491         h2_release_stream(r, con);
2492     }
2493     /*else ... should not happen*/
2494 }
2495 
2496 
2497 void
2498 h2_retire_con (request_st * const h2r, connection * const con)
2499 {
2500     h2con * const h2c = con->h2;
2501     if (NULL == h2c) return;
2502 
2503     if (h2r->state != CON_STATE_ERROR) { /*(CON_STATE_RESPONSE_END)*/
2504         h2_send_goaway(con, H2_E_NO_ERROR);
2505         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
2506             /*(unexpected if CON_STATE_RESPONSE_END)*/
2507             request_st * const r = h2c->r[i];
2508             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
2509             h2_release_stream(r, con);
2510         }
2511         if (!chunkqueue_is_empty(con->write_queue)) {
2512             /* similar to connection_handle_write() but without error checks,
2513              * without MAX_WRITE_LIMIT, and without connection throttling */
2514             /*h2r->conf.bytes_per_second = 0;*/         /* disable rate limit */
2515             /*h2r->conf.global_bytes_per_second = 0;*/  /* disable rate limit */
2516             /*con->traffic_limit_reached = 0;*/
2517             chunkqueue * const cq = con->write_queue;
2518             const off_t len = chunkqueue_length(cq);
2519             off_t written = cq->bytes_out;
2520             con->network_write(con, cq, len);
2521             /*(optional accounting)*/
2522             written = cq->bytes_out - written;
2523             con->bytes_written += written;
2524             con->bytes_written_cur_second += written;
2525             if (h2r->conf.global_bytes_per_second_cnt_ptr)
2526                 *(h2r->conf.global_bytes_per_second_cnt_ptr) += written;
2527         }
2528     }
2529     else { /* CON_STATE_ERROR */
2530         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
2531             request_st * const r = h2c->r[i];
2532             h2_release_stream(r, con);
2533         }
2534         /* XXX: perhaps attempt to send GOAWAY?  Not when CON_STATE_ERROR */
2535     }
2536 
2537     con->h2 = NULL;
2538 
2539     /* future: might keep a pool of reusable (h2con *) */
2540     lshpack_enc_cleanup(&h2c->encoder);
2541     lshpack_dec_cleanup(&h2c->decoder);
2542     free(h2c);
2543 }
2544 
2545 
2546 static void
2547 h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings)
2548 {
2549     /* status: (h2r->state == CON_STATE_REQUEST_END) for Upgrade: h2c */
2550 
2551     /* HTTP/1.1 101 Switching Protocols
2552      * Connection: Upgrade
2553      * Upgrade: h2c
2554      */
2555   #if 1
2556     static const char switch_proto[] = "HTTP/1.1 101 Switching Protocols\r\n"
2557                                        "Connection: Upgrade\r\n"
2558                                        "Upgrade: h2c\r\n\r\n";
2559     chunkqueue_append_mem(&h2r->write_queue,
2560                           CONST_STR_LEN(switch_proto));
2561     h2r->resp_header_len = sizeof(switch_proto)-1;
2562   #else
2563     h2r->http_status = 101;
2564     http_header_response_set(h2r, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"),
2565                                                        CONST_STR_LEN("h2c"));
2566     http_response_write_header(h2r);
2567     http_response_reset(h2r);
2568     h2r->http_status = 0;
2569   #endif
2570 
2571     connection * const con = h2r->con;
2572     h2_init_con(h2r, con, http2_settings);
2573     if (con->h2->sent_goaway) return;
2574 
2575     con->h2->h2_cid = 1; /* stream id 1 is assigned to h2c upgrade */
2576 
2577     /* copy request state from &con->request to subrequest r
2578      * XXX: would be nice if there were a cleaner way to do this
2579      * (This is fragile and must be kept in-sync with request_st in request.h)*/
2580 
2581     request_st * const r = h2_init_stream(h2r, con);
2582     /*(undo double-count; already incremented in CON_STATE_REQUEST_START)*/
2583     --con->request_count;
2584     r->state = h2r->state; /* CON_STATE_REQUEST_END */
2585     r->http_status = 0;
2586     r->http_method = h2r->http_method;
2587     r->h2state = H2_STATE_HALF_CLOSED_REMOTE;
2588     r->h2id = 1;
2589     r->rqst_htags = h2r->rqst_htags;
2590     h2r->rqst_htags = 0;
2591     r->rqst_header_len = h2r->rqst_header_len;
2592     h2r->rqst_header_len = 0;
2593     r->rqst_headers = h2r->rqst_headers;        /* copy struct */
2594     memset(&h2r->rqst_headers, 0, sizeof(array));
2595     r->uri = h2r->uri;                          /* copy struct */
2596   #if 0
2597     r->physical = h2r->physical;                /* copy struct */
2598     r->env = h2r->env;                          /* copy struct */
2599   #endif
2600     memset(&h2r->rqst_headers, 0, sizeof(array));
2601     memset(&h2r->uri, 0, sizeof(request_uri));
2602   #if 0
2603     memset(&h2r->physical, 0, sizeof(physical));
2604     memset(&h2r->env, 0, sizeof(array));
2605   #endif
2606   #if 0 /* expect empty request body */
2607     r->reqbody_length = h2r->reqbody_length; /* currently always 0 */
2608     r->te_chunked = h2r->te_chunked;         /* must be 0 */
2609     r->resp_body_scratchpad = h2r->resp_body_scratchpad; /*(not started yet)*/
2610     swap(&r->reqbody_queue,&h2r->reqbody_queue);/*currently always empty queue*/
2611   #endif
2612     r->http_host = h2r->http_host;
2613     h2r->http_host = NULL;
2614   #if 0
2615     r->server_name = h2r->server_name;
2616     h2r->server_name = NULL;
2617   #endif
2618     r->target = h2r->target;                    /* copy struct */
2619     r->target_orig = h2r->target_orig;          /* copy struct */
2620   #if 0
2621     r->pathinfo = h2r->pathinfo;                /* copy struct */
2622     r->server_name_buf = h2r->server_name_buf;  /* copy struct */
2623   #endif
2624     memset(&h2r->target, 0, sizeof(buffer));
2625     memset(&h2r->target_orig, 0, sizeof(buffer));
2626   #if 0
2627     memset(&h2r->pathinfo, 0, sizeof(buffer));
2628     memset(&h2r->server_name_buf, 0, sizeof(buffer));
2629   #endif
2630   #if 0
2631     /* skip copying response structures, other state not yet modified in h2r */
2632     /* r write_queue and read_queue are intentionally separate from h2r */
2633     /* r->gw_dechunk must be NULL for HTTP/2 */
2634     /* bytes_written_ckpt and bytes_read_ckpt are for HTTP/1.1 */
2635     /* error handlers have not yet been set */
2636   #endif
2637   #if 0
2638     r->loops_per_request = h2r->loops_per_request;
2639     r->async_callback = h2r->async_callback;
2640   #endif
2641     r->keep_alive = h2r->keep_alive;
2642     r->tmp_buf = h2r->tmp_buf;                /* shared; same as srv->tmp_buf */
2643     r->start_hp = h2r->start_hp;                /* copy struct */
2644 
2645     /* Note: HTTP/1.1 101 Switching Protocols is not immediately written to
2646      * the network here.  As this is called from cleartext Upgrade: h2c,
2647      * we choose to delay sending the status until the beginning of the response
2648      * to the HTTP/1.1 request which included Upgrade: h2c */
2649 }
2650 
2651 
2652 int
2653 h2_check_con_upgrade_h2c (request_st * const r)
2654 {
2655     /* RFC7540 3.2 Starting HTTP/2 for "http" URIs */
2656 
2657     buffer *http_connection, *http2_settings;
2658     buffer *upgrade = http_header_request_get(r, HTTP_HEADER_UPGRADE,
2659                                               CONST_STR_LEN("Upgrade"));
2660     if (NULL == upgrade) return 0;
2661     http_connection = http_header_request_get(r, HTTP_HEADER_CONNECTION,
2662                                               CONST_STR_LEN("Connection"));
2663     if (NULL == http_connection) {
2664         http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2665                                   CONST_STR_LEN("Upgrade"));
2666         return 0;
2667     }
2668     if (r->http_version != HTTP_VERSION_1_1) {
2669         http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2670                                   CONST_STR_LEN("Upgrade"));
2671         http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2672         return 0;
2673     }
2674 
2675     if (!http_header_str_contains_token(CONST_BUF_LEN(upgrade),
2676                                         CONST_STR_LEN("h2c")))
2677         return 0;
2678 
2679     http2_settings = http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS,
2680                                              CONST_STR_LEN("HTTP2-Settings"));
2681     if (NULL != http2_settings) {
2682         if (0 == r->reqbody_length) {
2683             buffer * const b = r->tmp_buf;
2684             buffer_clear(b);
2685             if (r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/
2686                 &&
2687                 http_header_str_contains_token(CONST_BUF_LEN(http_connection),
2688                                                CONST_STR_LEN("HTTP2-Settings"))
2689                 && buffer_append_base64_decode(b, CONST_BUF_LEN(http2_settings),
2690                                                BASE64_URL)) {
2691                 h2_con_upgrade_h2c(r, b);
2692                 r->http_version = HTTP_VERSION_2;
2693             } /* else ignore if invalid base64 */
2694         }
2695         else {
2696             /* ignore Upgrade: h2c if request body present since we do not
2697              * (currently) handle request body before transition to h2c */
2698             /* RFC7540 3.2 Requests that contain a payload body MUST be sent
2699              * in their entirety before the client can send HTTP/2 frames. */
2700         }
2701         http_header_request_unset(r, HTTP_HEADER_HTTP2_SETTINGS,
2702                                   CONST_STR_LEN("HTTP2-Settings"));
2703         http_header_remove_token(http_connection, CONST_STR_LEN("HTTP2-Settings"));
2704     } /* else ignore Upgrade: h2c; HTTP2-Settings required for Upgrade: h2c */
2705     http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2706                               CONST_STR_LEN("Upgrade"));
2707     http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2708     return (r->http_version == HTTP_VERSION_2);
2709 }
2710