xref: /lighttpd1.4/src/h2.c (revision 70b1af06)
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_header.h"
20 #include "log.h"
21 #include "request.h"
22 
23 
24 static request_st * h2_init_stream (request_st * const h2r, connection * const con);
25 
26 
27 static void
28 h2_send_settings_ack (connection * const con)
29 {
30     static const uint8_t settings_ack[] = {
31       /* SETTINGS w/ ACK */
32       0x00, 0x00, 0x00        /* frame length */
33      ,H2_FTYPE_SETTINGS       /* frame type */
34      ,H2_FLAG_ACK             /* frame flags */
35      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
36     };
37 
38     chunkqueue_append_mem(con->write_queue,
39                           (const char *)settings_ack, sizeof(settings_ack));
40 }
41 
42 
43 __attribute_cold__
44 static void
45 h2_send_rst_stream_id (uint32_t h2id, connection * const con, const request_h2error_t e)
46 {
47     union {
48       uint8_t c[16];
49       uint32_t u[4];          /*(alignment)*/
50     } rst_stream = { {        /*(big-endian numbers)*/
51       0x00, 0x00, 0x00        /* padding for alignment; do not send */
52       /* RST_STREAM */
53      ,0x00, 0x00, 0x04        /* frame length */
54      ,H2_FTYPE_RST_STREAM     /* frame type */
55      ,0x00                    /* frame flags */
56      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
57      ,0x00, 0x00, 0x00, 0x00  /* error code;       (fill in below) */
58     } };
59 
60     rst_stream.u[2] = htonl(h2id);
61     rst_stream.u[3] = htonl(e);
62     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
63                           (const char *)rst_stream.c+3, sizeof(rst_stream)-3);
64 }
65 
66 
67 __attribute_cold__
68 static void
69 h2_send_rst_stream (request_st * const r, connection * const con, const request_h2error_t e)
70 {
71     r->h2state = H2_STATE_CLOSED;
72     h2_send_rst_stream_id(r->h2id, con, e);
73 }
74 
75 
76 __attribute_cold__
77 static void
78 h2_send_goaway_rst_stream (connection * const con)
79 {
80     h2con * const h2c = con->h2;
81     const int sent_goaway = h2c->sent_goaway;
82     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
83         request_st * const r = h2c->r[i];
84         if (r->h2state == H2_STATE_CLOSED) continue;
85         /*(XXX: might consider always sending RST_STREAM)*/
86         if (!sent_goaway)
87             r->h2state = H2_STATE_CLOSED;
88         else /*(also sets r->h2state = H2_STATE_CLOSED)*/
89             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
90     }
91 }
92 
93 
94 void
95 h2_send_goaway (connection * const con, const request_h2error_t e)
96 {
97     /* future: RFC 7540 Section 6.8 notes that server initiating graceful
98      * connection shutdown SHOULD send GOAWAY with stream id 2^31-1 and a
99      * NO_ERROR code, and later send another GOAWAY with an updated last
100      * stream identifier.  (This is not done here, but doing so would be
101      * friendlier to clients that send streaming requests which the client
102      * is unable to retry.) */
103 
104     if (e != H2_E_NO_ERROR)
105         h2_send_goaway_rst_stream(con);
106     /*XXX: else should send RST_STREAM w/ CANCEL for any active PUSH_PROMISE */
107 
108     h2con * const h2c = con->h2;
109     if (h2c->sent_goaway && (h2c->sent_goaway > 0 || e == H2_E_NO_ERROR))
110         return;
111     h2c->sent_goaway = (e == H2_E_NO_ERROR) ? -1 : (int32_t)e;
112 
113     union {
114       uint8_t c[20];
115       uint32_t u[5];          /*(alignment)*/
116     } goaway = { {            /*(big-endian numbers)*/
117       0x00, 0x00, 0x00        /* padding for alignment; do not send */
118       /* GOAWAY */
119      ,0x00, 0x00, 0x08        /* frame length */
120      ,H2_FTYPE_GOAWAY         /* frame type */
121      ,0x00                    /* frame flags */
122      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
123      ,0x00, 0x00, 0x00, 0x00  /* last-stream-id (fill in below) */
124      ,0x00, 0x00, 0x00, 0x00  /* error code     (fill in below) */
125                               /* additional debug data (*); (optional)
126                                * adjust frame length if any additional
127                                * debug data is sent */
128     } };
129 
130     goaway.u[3] = htonl(h2c->h2_cid); /* last-stream-id */
131     goaway.u[4] = htonl(e);
132     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
133                           (const char *)goaway.c+3, sizeof(goaway)-3);
134 }
135 
136 
137 __attribute_cold__
138 static void
139 h2_send_goaway_e (connection * const con, const request_h2error_t e)
140 {
141     h2_send_goaway(con, e);
142 }
143 
144 
145 static int
146 h2_recv_goaway (connection * const con, const uint8_t * const s, uint32_t len)
147 {
148     /*(s must be entire GOAWAY frame and len the frame length field)*/
149     /*assert(s[3] == H2_FTYPE_GOAWAY);*/
150     UNUSED(len);
151     if ((s[5] & ~0x80) | s[6] | s[7] | s[8]) { /*(GOAWAY stream id must be 0)*/
152         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
153         return 0;
154     }
155     const uint32_t e = (s[13]<< 24) | (s[14]<< 16) | (s[15]<< 8) | s[16];
156   #if 0
157     /* XXX: debug: could log error code sent by peer */
158   #endif
159   #if 0
160     /* XXX: debug: could log additional debug info (if any) sent by peer */
161     if (len > 8) {
162     }
163   #endif
164   #if 0
165     /* XXX: could validate/use Last-Stream-ID sent by peer */
166     const uint32_t last_id = (s[9] << 24) | (s[10]<< 16) | (s[11]<< 8) | s[12];
167   #endif
168 
169     /* send PROTOCOL_ERROR back to peer if peer sent an error code
170      * (i.e. not NO_ERROR) in order to terminate connection more quickly */
171     h2_send_goaway(con, e==H2_E_NO_ERROR ? H2_E_NO_ERROR : H2_E_PROTOCOL_ERROR);
172     h2con * const h2c = con->h2;
173     if (0 == h2c->rused) return 0;
174     return 1;
175 }
176 
177 
178 static void
179 h2_recv_rst_stream (connection * const con, const uint8_t * const s, const uint32_t len)
180 {
181     /*(s must be entire RST_STREAM frame and len the frame length field)*/
182     /*assert(s[3] == H2_FTYPE_RST_STREAM);*/
183     if (4 != len) {                  /*(RST_STREAM frame length must be 4)*/
184         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
185         return;
186     }
187     const uint32_t id =
188       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
189     if (0 == id) {                   /*(RST_STREAM id must not be 0)*/
190         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
191         return;
192     }
193     h2con * const h2c = con->h2;
194     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
195         request_st * const r = h2c->r[i];
196         if (r->h2id != id) continue;
197         if (r->h2state == H2_STATE_IDLE) {
198             /*(RST_STREAM must not be for stream in "idle" state)*/
199             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
200             return;
201         }
202         /* XXX: ? add debug trace including error code from RST_STREAM ? */
203         r->h2state = H2_STATE_CLOSED;
204         return;
205     }
206     /* unknown/inactive stream id
207      * XXX: how should we handle RST_STREAM for unknown/inactive stream id?
208      * (stream id may have been closed recently and server forgot about it,
209      *  but client (peer) sent RST_STREAM prior to receiving stream end from
210      *  server)*/
211   #if 0
212     if (h2c->sent_goaway && h2c->h2_cid < id) return;
213     h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
214   #else
215     if (h2c->h2_cid < id) {
216         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
217         return;
218     }
219   #endif
220 }
221 
222 
223 static void
224 h2_recv_ping (connection * const con, uint8_t * const s, const uint32_t len)
225 {
226   #if 0
227     union {
228       uint8_t c[20];
229       uint32_t u[5];          /*(alignment)*/
230     } ping = { {              /*(big-endian numbers)*/
231       0x00, 0x00, 0x00        /* padding for alignment; do not send */
232       /* PING */
233      ,0x00, 0x00, 0x08        /* frame length */
234      ,H2_FTYPE_PING           /* frame type */
235      ,H2_FLAG_ACK             /* frame flags */
236      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
237      ,0x00, 0x00, 0x00, 0x00  /* opaque            (fill in below) */
238      ,0x00, 0x00, 0x00, 0x00
239     } };
240   #endif
241 
242     /*(s must be entire PING frame and len the frame length field)*/
243     /*assert(s[3] == H2_FTYPE_PING);*/
244     if (8 != len) {                  /*(PING frame length must be 8)*/
245         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
246         return;
247     }
248     s[5] &= ~0x80; /* reserved bit must be ignored */
249     if (s[5] | s[6] | s[7] | s[8]) { /*(PING stream id must be 0)*/
250         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
251         return;
252     }
253     if (s[4] & H2_FLAG_ACK) /*(ignore; unexpected if we did not send PING)*/
254         return;
255     /* reflect PING back to peer with frame flag ACK */
256     /* (9 byte frame header plus 8 byte PING payload = 17 bytes)*/
257     s[4] = H2_FLAG_ACK;
258     chunkqueue_append_mem(con->write_queue, (const char *)s, 17);
259 }
260 
261 
262 static void
263 h2_recv_priority (connection * const con, const uint8_t * const s, const uint32_t len)
264 {
265     /*(s must be entire PRIORITY frame and len the frame length field)*/
266     /*assert(s[3] == H2_FTYPE_PRIORITY);*/
267     if (5 != len) {                  /*(PRIORITY frame length must be 5)*/
268         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
269         return;
270     }
271     const uint32_t id =
272       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
273     if (0 == id) {                   /*(PRIORITY id must not be 0)*/
274         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
275         return;
276     }
277     const uint32_t prio =
278       ((s[9] << 24) | (s[10] << 16) | (s[11] << 8) | s[12]) & ~0x80000000u;
279   #if 0
280     uint32_t exclusive_dependency = (s[9] & 0x80) ? 1 : 0;
281     uint32_t weight = s[13];
282   #endif
283     h2con * const h2c = con->h2;
284     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
285         request_st * const r = h2c->r[i];
286         if (r->h2id != id) continue;
287         /* XXX: TODO: update priority info */
288         if (prio == id) {
289             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
290             return;
291         }
292         return;
293     }
294     /* XXX: TODO: update priority info for unknown/inactive stream */
295     /*if (h2c->sent_goaway && h2c->h2_cid < id) return;*/
296     if (prio == id) {
297         h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
298         return;
299     }
300 }
301 
302 
303 static void
304 h2_recv_window_update (connection * const con, const uint8_t * const s, const uint32_t len)
305 {
306     /*(s must be entire WINDOW_UPDATE frame and len the frame length field)*/
307     /*assert(s[3] == H2_FTYPE_WINDOW_UPDATE);*/
308     if (4 != len) {                  /*(WINDOW_UPDATE frame length must be 4)*/
309         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
310         return;
311     }
312     const uint32_t id =
313       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
314     const int32_t v =
315       (int32_t)(((s[9] << 24)|(s[10] << 16)|(s[11] << 8)|s[12]) & ~0x80000000);
316     request_st *r = NULL;
317     if (0 == id)
318         r = &con->request;
319     else {
320         h2con * const h2c = con->h2;
321         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
322             request_st * const rr = h2c->r[i];
323             if (rr->h2id != id) continue;
324             r = rr;
325             break;
326         }
327         /* peer should not send WINDOW_UPDATE for an inactive stream,
328          * but RFC 7540 does not explicitly call this out.  On the other hand,
329          * since there may be a temporary mismatch in stream state between
330          * peers, ignore window update if stream id is unknown/inactive.
331          * Also, it is not an error if GOAWAY sent and h2c->h2_cid < id */
332         if (NULL == r) {
333             if (h2c->h2_cid < id && 0 == h2c->sent_goaway)
334                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
335           #if 0
336             /*(needed for h2spec if testing with response < 16k+1 over TLS
337              * or response <= socket send buffer size over cleartext, due to
338              * completing response too quickly for the test frame sequence) */
339             if (v == 0)        /* h2spec: 6.9-2   (after we retired id 1) */
340                 h2_send_rst_stream_id(id, con, H2_E_PROTOCOL_ERROR);
341             if (v == INT32_MAX)/* h2spec: 6.9.1-3 (after we retired id 1) */
342                 h2_send_rst_stream_id(id, con, H2_E_FLOW_CONTROL_ERROR);
343           #endif
344             return;
345         }
346         /* MUST NOT be treated as error if stream is in closed state; ignore */
347         if (r->h2state == H2_STATE_CLOSED
348             || r->h2state == H2_STATE_HALF_CLOSED_LOCAL) return;
349     }
350     if (0 == v || r->h2_swin > INT32_MAX - v) {
351         request_h2error_t e = (0 == v)
352           ? H2_E_PROTOCOL_ERROR
353           : H2_E_FLOW_CONTROL_ERROR;
354         if (0 == id)
355             h2_send_goaway_e(con, e);
356         else
357             h2_send_rst_stream(r, con, e);
358         return;
359     }
360     r->h2_swin += v;
361 }
362 
363 
364 static void
365 h2_send_window_update (connection * const con, uint32_t h2id, const uint32_t len)
366 {
367     if (0 == len) return;
368     union {
369       uint8_t c[16];
370       uint32_t u[4];          /*(alignment)*/
371     } window_upd = { {        /*(big-endian numbers)*/
372       0x00, 0x00, 0x00        /* padding for alignment; do not send */
373       /* WINDOW_UPDATE */
374      ,0x00, 0x00, 0x04        /* frame length */
375      ,H2_FTYPE_WINDOW_UPDATE  /* frame type */
376      ,0x00                    /* frame flags */
377      ,0x00, 0x00, 0x00, 0x00  /* stream identifier      (fill in below) */
378      ,0x00, 0x00, 0x00, 0x00  /* window update increase (fill in below) */
379     } };
380 
381     window_upd.u[2] = htonl(h2id);
382     window_upd.u[3] = htonl(len);
383     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align padding)*/
384                           (const char *)window_upd.c+3, sizeof(window_upd)-3);
385 }
386 
387 
388 static void
389 h2_parse_frame_settings (connection * const con, const uint8_t *s, uint32_t len)
390 {
391     /*(s and len must be SETTINGS frame payload)*/
392     /*(caller must validate frame len, frame type == 0x04, frame id == 0)*/
393     h2con * const h2c = con->h2;
394     for (; len >= 6; len -= 6, s += 6) {
395         uint32_t v = (s[2] << 24) | (s[3] << 16) | (s[4] << 8) | s[5];
396         switch (((s[0] << 8) | s[1])) {
397           case H2_SETTINGS_HEADER_TABLE_SIZE:
398             /* encoder may use any table size <= value sent by peer */
399             /* For simple compliance with RFC and constrained memory use,
400              * choose to not increase table size beyond the default 4096,
401              * but allow smaller sizes to be set and then reset up to 4096,
402              * e.g. set to 0 to evict all dynamic table entries,
403              * and then set to 4096 to restore dynamic table use */
404             if (v > 4096) v = 4096;
405             if (v == h2c->s_header_table_size) break;
406             h2c->s_header_table_size = v;
407             /* FIXME: TODO: configure HPACK encoder */
408             break;
409           case H2_SETTINGS_ENABLE_PUSH:
410             if ((v|1) != 1) { /*(v == 0 || v == 1)*/
411                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
412                 return;
413             }
414             h2c->s_enable_push = v;
415             break;
416           case H2_SETTINGS_MAX_CONCURRENT_STREAMS:
417             h2c->s_max_concurrent_streams = v;
418             break;
419           case H2_SETTINGS_INITIAL_WINDOW_SIZE:
420             if (v > INT32_MAX) { /*(2^31 - 1)*/
421                 h2_send_goaway_e(con, H2_E_FLOW_CONTROL_ERROR);
422                 return;
423             }
424             else if (h2c->rused) { /*(update existing streams)*/
425                 /*(underflow is ok; unsigned integer math)*/
426                 /*(h2c->s_initial_window_size is >= 0)*/
427                 int32_t diff =
428                   (int32_t)((uint32_t)v - (uint32_t)h2c->s_initial_window_size);
429                 for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
430                     request_st * const r = h2c->r[i];
431                     const int32_t swin = r->h2_swin;
432                     if (r->h2state == H2_STATE_HALF_CLOSED_LOCAL
433                         || r->h2state == H2_STATE_CLOSED) continue;
434                     if (diff >= 0
435                         ? swin > INT32_MAX - diff
436                         : swin < INT32_MIN - diff) {
437                         h2_send_rst_stream(r, con, H2_E_FLOW_CONTROL_ERROR);
438                         continue;
439                     }
440                     r->h2_swin += diff;
441                 }
442             }
443             h2c->s_initial_window_size = (int32_t)v;
444             break;
445           case H2_SETTINGS_MAX_FRAME_SIZE:
446             if (v < 16384 || v > 16777215) { /*[(2^14),(2^24-1)]*/
447                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
448                 return;
449             }
450             h2c->s_max_frame_size = v;
451             break;
452           case H2_SETTINGS_MAX_HEADER_LIST_SIZE:
453             h2c->s_max_header_list_size = v;
454             break;
455           default:
456             break;
457         }
458     }
459 
460     if (len) {
461         h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
462         return;
463     }
464 
465     /* caller must send SETTINGS frame with ACK flag,
466      * if appropriate, and if h2c->sent_goaway is not set
467      * (Do not send ACK for Upgrade: h2c and HTTP2-Settings header) */
468 }
469 
470 
471 static void
472 h2_recv_settings (connection * const con, const uint8_t * const s, const uint32_t len)
473 {
474     /*(s must be entire SETTINGS frame, len must be the frame length field)*/
475     /*assert(s[3] == H2_FTYPE_SETTINGS);*/
476     if ((s[5] & ~0x80) | s[6] | s[7] | s[8]) {/*(SETTINGS stream id must be 0)*/
477         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
478         return;
479     }
480 
481     h2con * const h2c = con->h2;
482     if (!(s[4] & H2_FLAG_ACK)) {
483         h2_parse_frame_settings(con, s+9, len);
484         if (h2c->sent_goaway <= 0)
485             h2_send_settings_ack(con);
486     }
487     else {
488         /* lighttpd currently sends SETTINGS in server preface, and not again,
489          * so this does not have to handle another SETTINGS frame being sent
490          * before receiving an ACK from prior SETTINGS frame.  (If it does,
491          * then we will need some sort of counter.) */
492         if (0 != len)
493             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
494         else if (h2c->sent_settings)
495             h2c->sent_settings = 0;
496         else /* SETTINGS with ACK for SETTINGS frame we did not send */
497             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
498     }
499 }
500 
501 
502 static int
503 h2_recv_end_data (request_st * const r, connection * const con, const uint32_t alen)
504 {
505     chunkqueue * const reqbody_queue = r->reqbody_queue;
506     r->h2state = (r->h2state == H2_STATE_OPEN)
507       ? H2_STATE_HALF_CLOSED_REMOTE
508       : H2_STATE_CLOSED;
509     if (r->reqbody_length == -1)
510         r->reqbody_length = reqbody_queue->bytes_in + (off_t)alen;
511     else if (r->reqbody_length != reqbody_queue->bytes_in + (off_t)alen) {
512         if (0 == reqbody_queue->bytes_out) {
513             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
514             return 0;
515         } /* else let reqbody streaming consumer handle truncated reqbody */
516     }
517 
518     return 1;
519 }
520 
521 
522 static int
523 h2_recv_data (connection * const con, const uint8_t * const s, const uint32_t len)
524 {
525     /*(s must be entire DATA frame, len must be the frame length field)*/
526     /*assert(s[3] == H2_FTYPE_DATA);*/
527 
528     /* future: consider string refs rather than copying DATA from chunkqueue
529      * or try to consume entire chunk, or to split chunks with less copying */
530 
531     h2con * const h2c = con->h2;
532     const uint32_t id =
533       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
534     if (0 == id || h2c->h2_cid < id) { /*(RST_STREAM id must not be 0)*/
535         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
536         return 0;
537     }
538 
539     uint32_t alen = len; /* actual data len, minus padding */
540     uint32_t pad = 0;
541     if (s[4] & H2_FLAG_PADDED) {
542         pad = s[9];
543         if (pad >= len) {
544             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
545             return 0;
546         }
547         alen -= (1 + pad);
548     }
549 
550     request_st * const h2r = &con->request;
551     if (h2r->h2_rwin <= 0 && 0 != alen) { /*(always proceed if 0 == alen)*/
552         /*(connection_state_machine_h2() must ensure con is rescheduled,
553          * when backends consume data if con->read_queue is not empty,
554          * whether or not con->fd has data to read from the network)*/
555         /*(leave frame in cq to be re-read later)*/
556         return 0;
557     }
558     /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/
559     /*(not worried about underflow while
560      * SETTINGS_MAX_FRAME_SIZE is small (e.g. 16k or 32k) and
561      * SETTINGS_MAX_CONCURRENT_STREAMS is small (h2c->r[8]))*/
562     /*h2r->h2_rwin -= (int32_t)len;*//* update connection recv window (below) */
563 
564     request_st *r = NULL;
565     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
566         request_st * const rr = h2c->r[i];
567         if (rr->h2id != id) continue;
568         r = rr;
569         break;
570     }
571     chunkqueue * const cq = con->read_queue;
572     if (NULL == r) {
573         /* XXX: TODO: might need to keep a list of recently retired streams
574          * for a few seconds so that if we send RST_STREAM, then we ignore
575          * further DATA and do not send connection error, though recv windows
576          * still must be updated. */
577         if (h2c->h2_cid < id || (!h2c->sent_goaway && 0 != alen))
578             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
579         chunkqueue_mark_written(cq, 9+len);
580         return 0;
581     }
582 
583     if (r->h2state == H2_STATE_CLOSED
584         || r->h2state == H2_STATE_HALF_CLOSED_REMOTE) {
585         h2_send_rst_stream_id(id, con, H2_E_STREAM_CLOSED);
586         chunkqueue_mark_written(cq, 9+len);
587         h2_send_window_update(con, 0, len); /*(h2r->h2_rwin)*/
588         return 1;
589     }
590 
591     if (r->h2_rwin <= 0 && 0 != alen) {/*(always proceed if 0==alen)*/
592         if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_BUFMIN) {
593             /*(connection_state_machine_h2() must ensure con is rescheduled,
594              * when backends consume data if con->read_queue is not empty,
595              * whether or not con->fd has data to read from the network)*/
596             /*(leave frame in cq to be re-read later)*/
597             return 0;
598         }
599     }
600     /*(allow h2r->h2_rwin to dip below 0 so that entire frame is processed)*/
601     /*(undeflow will not occur (with reasonable SETTINGS_MAX_FRAME_SIZE used)
602      * since windows updated elsewhere and data is streamed to temp files if
603      * not FDEVENT_STREAM_REQUEST_BUFMIN)*/
604     /*r->h2_rwin -= (int32_t)len;*/
605     h2_send_window_update(con, r->h2id, len); /*(r->h2_rwin)*/
606     h2_send_window_update(con, 0, len);       /*(h2r->h2_rwin)*/
607 
608     chunkqueue * const dst = r->reqbody_queue;
609 
610     if (r->reqbody_length >= 0 && r->reqbody_length < dst->bytes_in + alen) {
611         /* data exceeds Content-Length specified (client mistake) */
612       #if 0 /* truncate */
613         alen = r->reqbody_length - dst->bytes_in;
614         /*(END_STREAM may follow in 0-length DATA frame or HEADERS (trailers))*/
615       #else /* reject */
616         h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
617         chunkqueue_mark_written(cq, 9+len);
618         return 1;
619       #endif
620     }
621 
622     /*(accounting for mod_accesslog and mod_rrdtool)*/
623     chunkqueue * const rq = r->read_queue;
624     rq->bytes_in  += (off_t)alen;
625     rq->bytes_out += (off_t)alen;
626 
627     /* r->conf.max_request_size is in kBytes */
628     const off_t max_request_size = (off_t)r->conf.max_request_size << 10;
629     if (0 != max_request_size
630         && dst->bytes_in + (off_t)alen > max_request_size) {
631         if (0 == r->http_status) {
632             r->http_status = 413; /* Payload Too Large */
633             log_error(r->conf.errh, __FILE__, __LINE__,
634               "request-size too long: %lld -> 413",
635               (long long) (dst->bytes_in + (off_t)alen));
636         }
637         chunkqueue_mark_written(cq, 9+len);
638         return 1;
639     }
640 
641     if ((s[4] & H2_FLAG_END_STREAM) && !h2_recv_end_data(r, con, alen)) {
642         chunkqueue_mark_written(cq, 9+len);
643         return 1;
644     }
645 
646     chunkqueue_mark_written(cq, 9 + ((s[4] & H2_FLAG_PADDED) ? 1 : 0));
647 
648   #if 0
649     if (pad) {
650         /* XXX: future optimization: if data is at end of chunk, then adjust
651          * size of chunk by reducing c->mem->used to avoid copying chunk
652          * when it is split (below) since the split would be due to padding
653          * (also adjust cq->bytes_out)*/
654         /*(might quickly check 9+len == cqlen if cqlen passed in as param)*/
655         /*(then check if cq->last contains all of padding, or leave alone)*/
656         /*(if handled here, then set pad = 0 here)*/
657     }
658   #endif
659 
660     /*(similar decision logic to that in http_chunk_uses_tempfile())*/
661     const chunk * const c = dst->last;
662     if ((c && c->type == FILE_CHUNK && c->file.is_temp)
663         || dst->bytes_in - dst->bytes_out + alen > 65536) {
664         log_error_st * const errh = r->conf.errh;
665         if (0 != chunkqueue_steal_with_tempfiles(dst, cq, (off_t)alen, errh)) {
666             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
667             return 0;
668         }
669     }
670     else
671         chunkqueue_steal(dst, cq, (off_t)alen);
672 
673     if (pad)
674         chunkqueue_mark_written(cq, pad);
675     return 1;
676 }
677 
678 
679 __attribute_cold__
680 static uint32_t
681 h2_frame_cq_compact (chunkqueue * const cq, uint32_t len)
682 {
683     /*(marked cold since most frames not expect to cross chunk boundary)*/
684 
685     /*(must be guaranteed by caller)*/
686         /*assert(chunkqueue_length(cq) >= len);*/
687         /*assert(cq->first != cq->last);*//*(multiple chunks)*/
688     /* caller must guarantee that chunks in chunkqueue are all MEM_CHUNK */
689 
690     /* move data to beginning of buffer if offset is large or data is short */
691     chunk *c = cq->first;
692     uint32_t mlen = buffer_string_length(c->mem);
693     if (mlen < c->offset) {
694         memmove(c->mem->ptr, c->mem->ptr + c->offset, mlen);
695         buffer_string_set_length(c->mem, mlen);
696         c->offset = 0;
697     }
698 
699     /* combine first mem chunk with next non-empty mem chunks up to len
700      * (loop if next chunk is empty) */
701     /* (modified from connection_handle_read_post_cq_compact()) */
702     uint32_t clen = mlen;
703     do {
704         buffer * const mem = c->next->mem;
705         const off_t offset = c->next->offset;
706         mlen = buffer_string_length(mem) - (uint32_t)offset;
707         force_assert(c->type == MEM_CHUNK);
708         force_assert(c->next->type == MEM_CHUNK);
709         if (mlen > clen - len) {
710             mlen = clen - len;
711             buffer_append_string_len(c->mem, mem->ptr+offset, mlen);
712             c->next->offset += mlen;
713             return len;
714         }
715 
716         buffer_append_string_len(c->mem, mem->ptr+offset, mlen);
717         clen += mlen;
718         /*(swap first and second chunk, then remove first chunk)*/
719         c->next->offset = c->offset;
720         c->next->mem = c->mem;
721         c->mem = mem;
722         c->offset = offset + (off_t)mlen;
723         chunkqueue_remove_finished_chunks(cq);
724     } while ((c = cq->first)); /*(need to re-read cq->first)*/
725     return clen;
726 }
727 
728 
729 __attribute_cold__
730 static uint32_t
731 h2_recv_continuation (uint32_t n, uint32_t clen, const off_t cqlen, chunkqueue * const cq, connection * const con)
732 {
733     chunk *c = cq->first;
734     uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
735     uint32_t m = n;
736     uint32_t flags;
737     h2con * const h2c = con->h2;
738     const uint32_t fsize = h2c->s_max_frame_size;
739     const uint32_t id =
740       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
741     do {
742         if (cqlen < n+9) return n+9; /* incomplete frame; go on */
743         if (clen < n+9) {
744             clen = h2_frame_cq_compact(cq, n+9);
745             c = cq->first; /*(reload after h2_frame_cq_compact())*/
746             s = (uint8_t *)(c->mem->ptr + c->offset);
747         }
748         if (s[n+3] != H2_FTYPE_CONTINUATION) {
749             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
750             return 0;
751         }
752         flags = s[n+4];
753         const uint32_t flen = (s[n+0]<<16)|(s[n+1]<<8)|s[n+2];
754         if (id != (uint32_t)((s[n+5]<<24)|(s[n+6]<<16)|(s[n+7]<<8)|s[n+8])) {
755             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
756             return 0;
757         }
758         if (flen > fsize) {
759             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
760             return 0;
761         }
762         n += 9+flen;
763         if (n >= 65536) { /*(very oversized for hpack)*/
764             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
765             return 0;
766         }
767         if (clen < n) {
768             clen = h2_frame_cq_compact(cq, n);
769             c = cq->first; /*(reload after h2_frame_cq_compact())*/
770             s = (uint8_t *)(c->mem->ptr + c->offset);
771         }
772     } while (!(flags & H2_FLAG_END_HEADERS));
773 
774     /* If some CONTINUATION frames were concatenated to earlier frames while
775      * processing above, but END_HEADERS were not received, then the next time
776      * data was read, initial frame size might exceed SETTINGS_MAX_FRAME_SIZE.
777      * (This describes the current lighttpd implementation in h2_parse_frames())
778      * While a flag could be set and checked to avoid this, such situations of
779      * large HEADERS (and CONTINUATION) across multiple network reads is
780      * expected to be rare.  Reparse and concatenate below.
781      *
782      * Aside: why would the authors of RFC 7540 go through the trouble of
783      * creating a CONTINUATION frame that must be special-cased when use of
784      * CONTINUATION is so restricted e.g. no other intervening frames and
785      * that HEADERS and PUSH_PROMISE HPACK must be parsed as a single block?
786      * IMHO, it would have been simpler to avoid CONTINUATION entirely, and have
787      * a special-case for HEADERS and PUSH_PROMISE to be allowed to exceed
788      * SETTINGS_MAX_FRAME_SIZE with implementations providing a different limit.
789      * While intermediates would not know such a limit of origin servers,
790      * there could have been a reasonable default set with a different SETTINGS
791      * parameter aimed just at HEADERS and PUSH_PROMISE.  The parameter
792      * SETTINGS_MAX_HEADER_LIST_SIZE could even have been (re)used, had it been
793      * given a reasonable initial value instead of "unlimited", since HPACK
794      * encoded headers are smaller than the HPACK decoded headers to which the
795      * limit SETTINGS_MAX_HEADER_LIST_SIZE applies. */
796 
797     n = m; /* reset n to beginning of first CONTINUATION frame */
798 
799     /* Eliminate padding from first frame (HEADERS or PUSH_PROMISE) if PADDED */
800     if (s[4] & H2_FLAG_PADDED) {
801         const uint32_t plen = s[9];
802         /* validate padding */
803         const uint32_t flen = (s[0]<<16)|(s[1]<<8)|s[2];
804         if (flen < 1 + plen + ((s[n+4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
805             /* Padding that exceeds the size remaining for the header block
806              * fragment MUST be treated as a PROTOCOL_ERROR. */
807             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
808             return 0;
809         }
810         /* set padding to 0 since we will overwrite padding in merge below */
811         /* (alternatively, could memmove() 9 bytes of frame header over the
812          *  pad length octet, remove PADDED flag, add 1 to c->offset,
813          *  add 1 to s, subtract 1 from clen and substract 1 from cqlen,
814          *  substract 1 from n) */
815         s[9] = 0;
816         /* set offset to beginning of padding at end of first frame */
817         m -= plen;
818     }
819 
820     do {
821         const uint32_t flen = (s[n+0]<<16)|(s[n+1]<<8)|s[n+2];
822         flags = s[n+4];
823         memmove(s+m, s+n+9, flen);
824         m += flen;
825         n += 9+flen;
826     } while (!(flags & H2_FLAG_END_HEADERS));
827     /* overwrite frame size */
828     m -= 9; /*(temporarily remove frame header from len)*/
829     s[0] = (m >> 16) & 0xFF;
830     s[1] = (m >>  8) & 0xFF;
831     s[2] = (m      ) & 0xFF;
832     m += 9;
833     /* adjust chunk c->mem */
834     if (n < clen) { /*(additional frames after CONTINUATION)*/
835         memmove(s+m, s+n, clen-n);
836         n = m + (clen-n);
837     }
838     else
839         n = m;
840     buffer_string_set_length(c->mem, n + (uint32_t)c->offset);
841 
842     return m;
843 }
844 
845 
846 __attribute_cold__
847 static request_st *
848 h2_recv_trailers_r (connection * const con, h2con * const h2c, const uint32_t id, const uint32_t flags)
849 {
850     /* rant: RFC 7230 HTTP/1.1 trailer-part would have been much simpler
851      * to support in RFC 7540 HTTP/2 as a distinct frame type rather than
852      * HEADERS.  As trailers are not known at the time the request is made,
853      * reuse of such trailers is limited and so a theoretical TRAILERS frame
854      * could have been implemented without HPACK encoding, and would have
855      * been more straightforward to implement than overloading and having to
856      * handle multiple cases for HEADERS.  TRAILERS support could then also
857      * be optional, like in HTTP/1.1 */
858     request_st *r = NULL;
859     for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
860         request_st * const rr = h2c->r[i];
861         if (rr->h2id != id) continue;
862         r = rr;
863         break;
864     }
865     if (NULL == r) {
866         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
867         return NULL;
868     }
869     if (r->h2state != H2_STATE_OPEN
870         && r->h2state != H2_STATE_HALF_CLOSED_LOCAL) {
871         h2_send_rst_stream(r, con, H2_E_STREAM_CLOSED);
872         return NULL;
873     }
874     /* RFC 7540 is not explicit in restricting HEADERS (trailers) following
875      * (optional) DATA frames, but in following HTTP/1.1, we limit to single
876      * (optional) HEADERS (+ CONTINUATIONs) after (optional) DATA frame(s)
877      * and require that the HEADERS frame set END_STREAM flag. */
878     if (!(flags & H2_FLAG_END_STREAM)) {
879         h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
880         return NULL;
881     }
882 
883     return h2_recv_end_data(r, con, 0) ? r : NULL;
884 }
885 
886 
887 /* prototype if HPACK-decoded HEADERS reconstituted
888  * into HTTP/1.1 request format in r->read_queue */
889 
890 /* Note: similar to connection_handle_read_state(), except operates on single
891  * buf since HTTP/2 headers delivered in a single buffer and are complete or err
892  */
893 __attribute_noinline__
894 static void
895 h2_parse_request_headers (request_st * const r, char * const hdrs, const uint32_t header_len)
896 {
897     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
898     hoff[0] = 1;                         /* number of lines */
899     hoff[1] = 0;                         /* base offset for all lines */
900     /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
901     r->rqst_header_len = http_header_parse_hoff(hdrs, header_len, hoff);
902     if (0 == r->rqst_header_len || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1) {
903         /* error if headers incomplete or too many header fields */
904         r->http_status = 431; /* Request Header Fields Too Large */
905         log_error(r->conf.errh, __FILE__, __LINE__,
906                   "oversized request-header -> sending Status 431");
907         return;
908     }
909     if (r->conf.log_request_header)
910         log_error(r->conf.errh, __FILE__, __LINE__,
911           "fd: %d request-len: %d\n%.*s", r->con->fd,
912           (int)r->rqst_header_len, (int)r->rqst_header_len, hdrs);
913     http_request_headers_process(r, hdrs, hoff, r->con->proto_default_port);
914 }
915 
916 
917 static void
918 h2_parse_request (request_st * const r)
919 {
920     chunk * const c = r->read_queue->first;
921     r->rqst_header_len = buffer_string_length(c->mem) - (uint32_t)c->offset;
922     h2_parse_request_headers(r, c->mem->ptr + c->offset, r->rqst_header_len);
923     chunkqueue_mark_written(r->read_queue, r->rqst_header_len);
924 
925     if (0 != r->http_status) {
926         if (431 == r->http_status) /*(e.g. too many header lines)*/
927             log_error(r->conf.errh, __FILE__, __LINE__,
928                       "oversized request-header -> sending Status 431");
929     }
930 
931     /* ignore Upgrade if using HTTP/2 */
932     if (r->rqst_htags & HTTP_HEADER_UPGRADE) {
933         http_header_request_unset(r, HTTP_HEADER_UPGRADE,
934                                   CONST_STR_LEN("upgrade"));
935         buffer * const connhdr =
936           http_header_request_get(r, HTTP_HEADER_CONNECTION,
937                                   CONST_STR_LEN("connection"));
938         if (connhdr)
939             http_header_remove_token(connhdr, CONST_STR_LEN("upgrade"));
940     }
941     /* XXX: should filter out other hop-by-hop connection headers, too */
942 }
943 
944 
945 static int
946 h2_parse_headers_frame (connection * const con, const unsigned char *psrc, const uint32_t plen, request_st * const restrict r, const int trailers)
947 {
948     uint32_t hlen = 0;
949 
950 
951 
952     /* XXX: TODO: HPACK decode frame; fill in (request_st *r) */
953 
954 
955 
956   #if 1
957     /* terminate reconstituted HTTP/1.1 request
958      * (along with HTTP/2 pseudo-headers) */
959     chunkqueue_append_mem(r->read_queue, CONST_STR_LEN("\r\n"));
960     if (r->read_queue->first->next) {
961         hlen += 2;
962         h2_frame_cq_compact(r->read_queue, hlen);
963     }
964     h2_parse_request(r);
965   #else
966     /* future: adjust counts if bypassing HTTP/1.x compatibility
967      * (avoiding reconsitituting HTTP/1.1 request in r->read_queue) */
968     r->rqst_header_len += hlen;
969     /*(accounting for mod_accesslog and mod_rrdtool)*/
970     chunkqueue * const rq = r->read_queue;
971     rq->bytes_in  += (off_t)hlen;
972     rq->bytes_out += (off_t)hlen;
973   #endif
974 
975     return 1;
976 }
977 
978 
979 static int
980 h2_recv_headers (connection * const con, uint8_t * const s, uint32_t flen)
981 {
982     request_st *r = NULL;
983     h2con * const h2c = con->h2;
984     const uint32_t id =
985       ((s[5] << 24) | (s[6] << 16) | (s[7] << 8) | s[8]) & ~0x80000000u;
986     if (0 == id) { /* HEADERS, PUSH_PROMISE stream id must != 0 */
987         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
988         return 0;
989     }
990     if (!(id & 1)) { /* stream id from client must be odd */
991         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
992         return 0;
993     }
994 
995     request_st * const h2r = &con->request;
996     int trailers = 0;
997 
998     if (id > h2c->h2_cid) {
999         if (h2c->rused == sizeof(h2c->r)/sizeof(*h2c->r)) {
1000             if (0 == h2c->sent_settings) { /*(see h2_recv_settings() comments)*/
1001                 /* too many active streams; refuse new stream */
1002                 h2c->h2_cid = id;
1003                 h2_send_rst_stream_id(id, con, H2_E_REFUSED_STREAM);
1004                 return 1;
1005             }
1006             else {
1007                 /* alternative: stop processing frames and defer processing this
1008                  * HEADERS frame until num active streams drops below limit.
1009                  * lighttpd sends SETTINGS_MAX_CONCURRENT_STREAMS <limit> with
1010                  * server Connection Preface, so a well-behaved client will
1011                  * adjust after it sends its initial requests.
1012                  * (e.g. h2load -n 100 -m 100 sends 100 requests upon connect)*/
1013                 return -1;
1014             }
1015         }
1016         /* Note: MUST process HPACK decode even if already sent GOAWAY.
1017          * This is necessary since there may be active streams not in
1018          * H2_STATE_HALF_CLOSED_REMOTE, e.g. H2_STATE_OPEN, still possibly
1019          * receiving DATA and, more relevantly, still might receive HEADERS
1020          * frame with trailers, for which the decoder state is required.
1021          * XXX: future might try to reduce other processing done if sent
1022          *      GOAWAY, e.g. might avoid allocating (request_st *r) */
1023         r = h2_init_stream(h2r, con);
1024         r->h2id = id;
1025         r->h2state = (s[4] & H2_FLAG_END_STREAM)
1026           ? H2_STATE_HALF_CLOSED_REMOTE
1027           : H2_STATE_OPEN;
1028         /* Note: timestamps here are updated only after receipt of entire header
1029          * (HEADERS frame might have been sent in multiple packets
1030          *  and CONTINUATION frames may have been sent in multiple packets)
1031          * (affects high precision timestamp, if enabled)
1032          * (large sets of headers are not typical, and even when they do
1033          *  occur, they will typically be sent within the same second)
1034          * (future: might keep high precision timestamp in h2con when first
1035          *  packet of HEADERS or PUSH_PROMISE is received, and clear that
1036          *  timestamp when frame + CONTINUATION(s) are complete (so that
1037          *  re-read of initial frame does not overwrite the timestamp))
1038          */
1039         r->start_ts = log_epoch_secs;
1040         if (r->conf.high_precision_timestamps)
1041             log_clock_gettime_realtime(&r->start_hp);
1042     }
1043     else {
1044         r = h2_recv_trailers_r(con, h2c, id, s[4]); /* (cold code path) */
1045         if (NULL == r)
1046             return (h2c->sent_goaway > 0) ? 0 : 1;
1047         trailers = 1;
1048     }
1049 
1050     const unsigned char *psrc = s + 9;
1051     uint32_t alen = flen;
1052     if (s[4] & H2_FLAG_PADDED) {
1053         ++psrc;
1054         const uint32_t pad = s[9];
1055         if (flen < 1 + pad + ((s[4] & H2_FLAG_PRIORITY) ? 5 : 0)) {
1056             /* Padding that exceeds the size remaining for the header block
1057              * fragment MUST be treated as a PROTOCOL_ERROR. */
1058             h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1059             h2_retire_stream(r, con);
1060             return 0;
1061         }
1062         alen -= (1 + pad); /*(alen is adjusted for PRIORITY below)*/
1063     }
1064     if (s[4] & H2_FLAG_PRIORITY) {
1065         /* XXX: TODO: handle PRIORITY (prio fields start at *psrc) */
1066         const uint32_t prio =
1067           ((psrc[0]<<24)|(psrc[1]<<16)|(psrc[2]<<8)|psrc[3]) & ~0x80000000u;
1068         if (prio == id) {
1069             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1070             h2_retire_stream(r, con);
1071             return 1;
1072         }
1073       #if 0
1074         uint32_t exclusive_dependency = (psrc[0] & 0x80) ? 1 : 0;
1075         uint32_t weight = psrc[4];
1076       #endif
1077         psrc += 5;
1078         alen -= 5;
1079     }
1080 
1081     if (!h2_parse_headers_frame(con, psrc, alen, r, trailers))
1082         return 0;
1083 
1084   #if 0 /*(handled in h2_parse_frames() as a connection error)*/
1085     if (s[3] == H2_FTYPE_PUSH_PROMISE) {
1086         /* Had to process HPACK to keep HPACK tables sync'd with peer but now
1087          * discard the request if PUSH_PROMISE, since not expected, as this code
1088          * is running as a server, not as a client.
1089          * XXX: future might try to reduce other processing done if
1090          * discarding, e.g. might avoid allocating (request_st *r) */
1091         /* rant: PUSH_PROMISE could have been a flag on HEADERS frame
1092          *       instead of an independent frame type */
1093         r->http_status = 0;
1094         h2_retire_stream(r, con);
1095     }
1096   #endif
1097 
1098     if (!h2c->sent_goaway) {
1099         h2c->h2_cid = id;
1100         if (!(r->rqst_htags & HTTP_HEADER_CONTENT_LENGTH))
1101             r->reqbody_length = (s[4] & H2_FLAG_END_STREAM) ? 0 : -1;
1102       #if 0
1103         else if (r->reqbody_length > 0 && (s[4] & H2_FLAG_END_STREAM)) {
1104             /*(handled in connection_handle_read_post_state())*/
1105             /* XXX: TODO if (r->conf.log_request_header_on_error) */
1106             r->http_status = 400; /* Bad Request */
1107         }
1108       #endif
1109 
1110         /* RFC 7540 Section 8. HTTP Message Exchanges
1111          * 8.1.2.6. Malformed Requests and Responses
1112          *   For malformed requests, a server MAY send an HTTP
1113          *   response prior to closing or resetting the stream.
1114          * However, h2spec expects stream PROTOCOL_ERROR.
1115          * (This is unfortunate, since we would rather send
1116          *  400 Bad Request which tells client *do not* retry
1117          *  the bad request without modification)
1118          * https://github.com/summerwind/h2spec/issues/120
1119          * https://github.com/summerwind/h2spec/issues/121
1120          * https://github.com/summerwind/h2spec/issues/122
1121          */
1122       #if 0
1123         if (400 == r->http_status) {
1124             h2_send_rst_stream(r, con, H2_E_PROTOCOL_ERROR);
1125             h2_retire_stream(r, con);
1126         }
1127       #endif
1128     }
1129     else if (h2c->h2_cid < id) {
1130         /* Had to process HPACK to keep HPACK tables sync'd with peer
1131          * but now discard the request if id is after id sent in GOAWAY.
1132          * XXX: future might try to reduce other processing done if
1133          * discarding, e.g. might avoid allocating (request_st *r) */
1134         r->http_status = 0;
1135         h2_retire_stream(r, con);
1136     }
1137 
1138     return 1;
1139 }
1140 
1141 
1142 int
1143 h2_parse_frames (connection * const con)
1144 {
1145     /* read and process HTTP/2 frames from socket */
1146     h2con * const h2c = con->h2;
1147     chunkqueue * const cq = con->read_queue;
1148     /* initial max frame size is the minimum: 16k
1149      * (lighttpd does not currently increase max frame size)
1150      * (lighttpd does not currently decrease max frame size)
1151      * (XXX: If SETTINGS_MAX_FRAME_SIZE were increased and then decreased,
1152      *       should accept the larger frame size until SETTINGS is ACK'd) */
1153     const uint32_t fsize = h2c->s_max_frame_size;
1154     for (off_t cqlen = chunkqueue_length(cq); cqlen >= 9; ) {
1155         chunk *c = cq->first;
1156         /*assert(c->type == MEM_CHUNK);*/
1157         /* copy data if frame header crosses chunk boundary
1158          * future: be more efficient than blind full chunk copy */
1159         uint32_t clen = buffer_string_length(c->mem) - c->offset;
1160         if (clen < 9) {
1161             clen = h2_frame_cq_compact(cq, 9);
1162             c = cq->first; /*(reload after h2_frame_cq_compact())*/
1163         }
1164         uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1165         uint32_t flen = (s[0] << 16) | (s[1] << 8) | s[2];
1166         if (flen > fsize) {
1167             h2_send_goaway_e(con, H2_E_FRAME_SIZE_ERROR);
1168             return 0;
1169         }
1170 
1171         /*(handle PUSH_PROMISE as connection error further below)*/
1172         /*if (s[3] == H2_FTYPE_HEADERS || s[3] == H2_FTYPE_PUSH_PROMISE)*/
1173 
1174         if (s[3] == H2_FTYPE_HEADERS) {
1175             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1176             if (clen < 9+flen) {
1177                 clen = h2_frame_cq_compact(cq, 9+flen);
1178                 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1179                 s = (uint8_t *)(c->mem->ptr + c->offset);
1180             }
1181 
1182             if (!(s[4] & H2_FLAG_END_HEADERS)) {
1183                 /* collect CONTINUATION frames (cold code path) */
1184                 /* note: h2_recv_continuation() return value is overloaded
1185                  * and the resulting clen is 9+flen of *concatenated* frames */
1186                 clen = h2_recv_continuation(9+flen, clen, cqlen, cq, con);
1187                 if (0 == clen)    return 0;
1188                 if (cqlen < clen) return 1; /* incomplete frames; go on */
1189                 c = cq->first; /*(reload after h2_recv_continuation())*/
1190                 s = (uint8_t *)(c->mem->ptr + c->offset);
1191                 /* frame size was also updated and might (legitimately)
1192                  * exceed SETTINGS_MAX_FRAME_SIZE, so do not test fsize again */
1193                 flen = (s[0]<<16)|(s[1]<<8)|s[2];
1194                 /* recalculate after CONTINUATION removed */
1195                 cqlen = chunkqueue_length(cq);
1196             }
1197 
1198             int rc = h2_recv_headers(con, s, flen);
1199             cqlen -= (9+flen);
1200             if (rc >= 0)
1201                 chunkqueue_mark_written(cq, 9+flen);
1202             if (rc <= 0)
1203                 return 0;
1204             con->read_idle_ts = log_epoch_secs;
1205         }
1206         else if (s[3] == H2_FTYPE_DATA) {
1207             /* future: might try to stream data for incomplete frames,
1208              * but that would require keeping additional state for partially
1209              * read frames, including cleaning up if errors occur.
1210              * Since well-behaved clients do not intentionally send partial
1211              * frames, and try to resend if socket buffers are full, this is
1212              * probably not a big concern in practice. */
1213             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1214             con->read_idle_ts = log_epoch_secs;
1215             /*(h2_recv_data() must consume frame from cq or else return 0)*/
1216             if (!h2_recv_data(con, s, flen))
1217                 return 0;
1218             cqlen -= (9+flen);
1219         }
1220         else {
1221             /* frame types below are expected to be small
1222              * most frame types below have fixed (small) size
1223              *   4 bytes - WINDOW_UPDATE
1224              *   5 bytes - PRIORITY
1225              *   8 bytes - PING
1226              *   4 bytes - RST_STREAM
1227              * some are variable size
1228              *     SETTINGS (6 * #settings; 6 defined in RFC 7540 Section 6.5)
1229              *     GOAWAY   (8 + optional additional debug data (variable))
1230              * XXX: might add sanity check for a max flen here,
1231              *      before waiting to read partial frame
1232              *      (fsize limit is still enforced above for all frames)
1233              */
1234             if (cqlen < 9+flen) return 1; /* incomplete frame; go on */
1235             if (clen < 9+flen) {
1236                 clen = h2_frame_cq_compact(cq, 9+flen);
1237                 c = cq->first; /*(reload after h2_frame_cq_compact())*/
1238                 s = (uint8_t *)(c->mem->ptr + c->offset);
1239             }
1240             switch (s[3]) { /* frame type */
1241               case H2_FTYPE_WINDOW_UPDATE:
1242                 h2_recv_window_update(con, s, flen);
1243                 break;
1244               case H2_FTYPE_PRIORITY:
1245                 h2_recv_priority(con, s, flen);
1246                 break;
1247               case H2_FTYPE_SETTINGS:
1248                 h2_recv_settings(con, s, flen);
1249                 break;
1250               case H2_FTYPE_PING:
1251                 h2_recv_ping(con, s, flen);
1252                 break;
1253               case H2_FTYPE_RST_STREAM:
1254                 h2_recv_rst_stream(con, s, flen);
1255                 break;
1256               case H2_FTYPE_GOAWAY:
1257                 if (!h2_recv_goaway(con, s, flen)) return 0;
1258                 break;
1259               case H2_FTYPE_PUSH_PROMISE: /*not expected from client*/
1260               case H2_FTYPE_CONTINUATION: /*handled with HEADERS*/
1261                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1262                 return 0;
1263               default: /* ignore unknown frame types */
1264                 break;
1265             }
1266             cqlen -= (9+flen);
1267             chunkqueue_mark_written(cq, 9+flen);
1268         }
1269 
1270         if (h2c->sent_goaway > 0) return 0;
1271     }
1272 
1273     return 1;
1274 }
1275 
1276 
1277 int
1278 h2_want_read (connection * const con)
1279 {
1280     chunkqueue * const cq = con->read_queue;
1281     if (chunkqueue_is_empty(cq)) return 1;
1282 
1283     /* check for partial frame */
1284     const off_t cqlen = cq->bytes_in - cq->bytes_out; /*chunkqueue_length(cq);*/
1285     if (cqlen < 9) return 1;
1286     chunk *c = cq->first;
1287     uint32_t clen = buffer_string_length(c->mem) - c->offset;
1288     if (clen < 9) {
1289         clen = h2_frame_cq_compact(cq, 9);
1290         c = cq->first; /*(reload after h2_frame_cq_compact())*/
1291     }
1292     uint8_t *s = (uint8_t *)(c->mem->ptr + c->offset);
1293     uint32_t flen = (s[0] << 16) | (s[1] << 8) | s[2];
1294     if (clen < 9+flen) return 1;
1295 
1296     /* check if not HEADERS, or if HEADERS has END_HEADERS flag */
1297     if (s[3] != H2_FTYPE_HEADERS || (s[4] & H2_FLAG_END_HEADERS))
1298         return 0;
1299 
1300     /* check for partial CONTINUATION frames */
1301     for (uint32_t n = 9+flen; cqlen >= n+9; n += 9+flen) {
1302         if (clen < n+9) {
1303             clen = h2_frame_cq_compact(cq, n+9);
1304             c = cq->first; /*(reload after h2_frame_cq_compact())*/
1305             s = (uint8_t *)(c->mem->ptr + c->offset);
1306         }
1307         flen = (s[n+0] << 16) | (s[n+1] << 8) | s[n+2];
1308         if (cqlen < n+9+flen) return 1; /* incomplete frame; go on */
1309         if (s[4] & H2_FLAG_END_HEADERS) return 0;
1310     }
1311 
1312     return 1;
1313 }
1314 
1315 
1316 static int
1317 h2_recv_client_connection_preface (connection * const con)
1318 {
1319     /* check if the client Connection Preface (24 bytes) has been received
1320      * (initial SETTINGS frame should immediately follow, but is not checked) */
1321     chunkqueue * const cq = con->read_queue;
1322     if (chunkqueue_length(cq) < 24) {
1323         chunk * const c = cq->first;
1324         if (c && buffer_string_length(c->mem) - c->offset >= 4) {
1325             const char * const s = c->mem->ptr + c->offset;
1326             if (s[0]!='P'||s[1]!='R'||s[2]!='I'||s[3]!=' ') {
1327                 h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1328                 return 1; /* error; done receiving connection preface */
1329             }
1330         }
1331         return 0; /*(not ready yet)*/
1332     }
1333 
1334     static const char h2preface[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
1335     chunk *c = cq->first;
1336     const uint32_t clen = buffer_string_length(c->mem) - c->offset;
1337     if (clen < 24) h2_frame_cq_compact(cq, 24);
1338     c = cq->first; /*(reload after h2_frame_cq_compact())*/
1339     const uint8_t * const s = (uint8_t *)(c->mem->ptr + c->offset);
1340     if (0 == memcmp(s, h2preface, 24)) /* sizeof(h2preface)-1) */
1341         chunkqueue_mark_written(cq, 24);
1342     else
1343         h2_send_goaway_e(con, H2_E_PROTOCOL_ERROR);
1344     return 1; /* done receiving connection preface (even if error occurred) */
1345 }
1346 
1347 
1348 __attribute_cold__
1349 static int
1350 h2_read_client_connection_preface (struct connection * const con, chunkqueue * const cq, off_t max_bytes)
1351 {
1352     /* temporary con->network_read() filter until connection preface received */
1353 
1354     /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1355     void ** const hctx = con->plugin_ctx+0; /*(0 idx used for h2)*/
1356     int(* const network_read)(struct connection *, chunkqueue *, off_t) =
1357       (int(*)(struct connection *, chunkqueue *, off_t))(uintptr_t)(*hctx);
1358     if (max_bytes < 24) max_bytes = 24; /*(should not happen)*/
1359     int rc = (network_read)(con, cq, max_bytes);
1360     if (NULL == con->h2) return rc; /*(unexpected; already cleaned up)*/
1361     if (-1 != rc && h2_recv_client_connection_preface(con)) {
1362         con->network_read = network_read;
1363         *hctx = NULL;
1364         /*(intentionally update timestamp only after reading preface complete)*/
1365         con->read_idle_ts = log_epoch_secs;
1366     }
1367     return rc;
1368 }
1369 
1370 
1371 void
1372 h2_init_con (request_st * const restrict h2r, connection * const restrict con, const buffer * const restrict http2_settings)
1373 {
1374     h2con * const h2c = calloc(1, sizeof(h2con));
1375     force_assert(h2c);
1376     con->h2 = h2c;
1377     con->read_idle_ts = log_epoch_secs;
1378     con->keep_alive_idle = h2r->conf.max_keep_alive_idle;
1379 
1380     h2r->h2_rwin = 65535;                 /* h2 connection recv window */
1381     h2r->h2_swin = 65535;                 /* h2 connection send window */
1382     /* settings sent from peer */         /* initial values */
1383     h2c->s_header_table_size     = 4096;  /* SETTINGS_HEADER_TABLE_SIZE      */
1384     h2c->s_enable_push           = 1;     /* SETTINGS_ENABLE_PUSH            */
1385     h2c->s_max_concurrent_streams= ~0u;   /* SETTINGS_MAX_CONCURRENT_STREAMS */
1386     h2c->s_initial_window_size   = 65535; /* SETTINGS_INITIAL_WINDOW_SIZE    */
1387     h2c->s_max_frame_size        = 16384; /* SETTINGS_MAX_FRAME_SIZE         */
1388     h2c->s_max_header_list_size  = ~0u;   /* SETTINGS_MAX_HEADER_LIST_SIZE   */
1389     h2c->sent_settings           = log_epoch_secs; /*(send SETTINGS below)*/
1390 
1391     if (http2_settings) /*(if Upgrade: h2c)*/
1392         h2_parse_frame_settings(con, (uint8_t *)CONST_BUF_LEN(http2_settings));
1393 
1394     static const uint8_t h2settings[] = { /*(big-endian numbers)*/
1395       /* SETTINGS */
1396       0x00, 0x00, 0x0c        /* frame length */ /* 6 * 2 for two settings */
1397      ,H2_FTYPE_SETTINGS       /* frame type */
1398      ,0x00                    /* frame flags */
1399      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
1400      ,0x00, H2_SETTINGS_MAX_CONCURRENT_STREAMS
1401      ,0x00, 0x00, 0x00, 0x08  /* 8 */
1402      #if 0  /* ? explicitly disable dynamic table ? (and adjust frame length) */
1403             /* If this is sent, must wait until peer sends SETTINGS with ACK
1404              * before disabling dynamic table in HPACK decoder */
1405      ,0x00, H2_SETTINGS_HEADER_TABLE_SIZE
1406      ,0x00, 0x00, 0x00, 0x00  /* 0 */
1407      #endif
1408      #if 0  /* ? explicitly disable push ?       (and adjust frame length) */
1409      ,0x00, H2_SETTINGS_ENABLE_PUSH
1410      ,0x00, 0x00, 0x00, 0x00  /* 0 */
1411      #endif
1412      #if 0  /* ? increase from default (65535) ? (and adjust frame length) */
1413      ,0x00, H2_SETTINGS_INITIAL_WINDOW_SIZE
1414      ,0x00, 0x02, 0x00, 0x00  /* 131072 */
1415      #endif
1416      #if 0  /* ? increase from default (16384) ? (and adjust frame length) */
1417      ,0x00, H2_SETTINGS_MAX_FRAME_SIZE
1418      ,0x00, 0x00, 0x80, 0x00  /* 32768 */
1419      #endif
1420      ,0x00, H2_SETTINGS_MAX_HEADER_LIST_SIZE
1421      ,0x00, 0x00, 0xFF, 0xFF  /* 65535 */
1422 
1423      #if 0
1424       /* WINDOW_UPDATE */
1425      ,0x00, 0x00, 0x04        /* frame length */
1426      ,H2_FTYPE_WINDOW_UPDATE  /* frame type */
1427      ,0x00                    /* frame flags */
1428      ,0x00, 0x00, 0x00, 0x00  /* stream identifier */
1429      ,0x00, 0x01, 0x00, 0x01  /* 65537 */ /* increase connection rwin to 128k */
1430      #endif
1431     };
1432 
1433     /*h2r->h2_rwin += 65537;*//*(enable if WINDOWS_UPDATE is sent above)*/
1434     chunkqueue_append_mem(con->write_queue,
1435                           (const char *)h2settings, sizeof(h2settings));
1436 
1437     if (!h2_recv_client_connection_preface(con)) {
1438         /*(alternatively, func ptr could be saved in an element in (h2con *))*/
1439         con->plugin_ctx[0] = (void *)(uintptr_t)con->network_read;
1440         con->network_read = h2_read_client_connection_preface;
1441         /* note: no steps taken to reset con->network_read() on error
1442          * as con->network_read() is always set in connection_accepted() */
1443     }
1444 
1445     buffer_string_prepare_copy(h2r->tmp_buf, 65535);
1446 }
1447 
1448 
1449 static void
1450 h2_send_hpack (request_st * const r, connection * const con, const char *data, uint32_t dlen, const uint32_t flags)
1451 {
1452     union {
1453       uint8_t c[12];
1454       uint32_t u[3];          /*(alignment)*/
1455     } headers = { {           /*(big-endian numbers)*/
1456       0x00, 0x00, 0x00        /* padding for alignment; do not send */
1457       /* HEADERS */
1458      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
1459      ,H2_FTYPE_HEADERS        /* frame type */
1460      ,(uint8_t)flags          /* frame flags (e.g. END_STREAM for trailers) */
1461      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
1462     } };
1463 
1464     headers.u[2] = htonl(r->h2id);
1465 
1466     /* similar to h2_send_data(), but unlike DATA frames there is a HEADERS
1467      * frame potentially followed by CONTINUATION frame(s) here, and the final
1468      * HEADERS or CONTINUATION frame here has END_HEADERS flag set.
1469      * For trailers, END_STREAM flag is set on HEADERS frame. */
1470 
1471     /*(approximate space needed for frames (header + payload)
1472      * with slight over-estimate of 16 bytes per frame header (> 9)
1473      * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
1474      * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
1475      *  per frame can be appoximated with (dlen>>10) + 9)*/
1476     buffer * const b =
1477       chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
1478     char * restrict ptr = b->ptr;
1479     h2con * const h2c = con->h2;
1480     const uint32_t fsize = h2c->s_max_frame_size;
1481     do {
1482         const uint32_t len = dlen < fsize ? dlen : fsize;
1483         headers.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
1484         headers.c[4] = (len >>  8) & 0xFF;
1485         headers.c[5] = (len      ) & 0xFF;
1486         if (len == dlen)
1487             headers.c[7] |= H2_FLAG_END_HEADERS;
1488       #if 0
1489         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
1490                               (const char *)headers.c+3, sizeof(headers)-3);
1491         chunkqueue_append_mem(con->write_queue, data, len);
1492       #else
1493         memcpy(ptr, headers.c+3, sizeof(headers)-3);
1494         memcpy(ptr+sizeof(headers)-3, data, len);
1495         ptr  += len + sizeof(headers)-3;
1496       #endif
1497         data += len;
1498         dlen -= len;
1499         /*(include H2_FLAG_END_STREAM in HEADERS frame, not CONTINUATION)*/
1500         headers.c[6] = H2_FTYPE_CONTINUATION; /*(if additional frames needed)*/
1501         headers.c[7] = 0x00; /*(off +3 to skip over align pad)*/
1502     } while (dlen);
1503     buffer_string_set_length(b, (uint32_t)(ptr - b->ptr));
1504     chunkqueue_append_buffer_commit(con->write_queue);
1505 }
1506 
1507 
1508 __attribute_noinline__
1509 static void
1510 h2_send_headers_block (request_st * const r, connection * const con, const char * const hdrs, const uint32_t hlen, uint32_t flags)
1511 {
1512     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
1513     hoff[0] = 1;                         /* number of lines */
1514     hoff[1] = 0;                         /* base offset for all lines */
1515     /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
1516     uint32_t rc = http_header_parse_hoff(hdrs, hlen, hoff);
1517     if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
1518         || 1 == hoff[0]) { /*(initial blank line (should not happen))*/
1519         /* error if headers incomplete or too many header fields */
1520         log_error(r->conf.errh, __FILE__, __LINE__,
1521                   "oversized response-header");
1522         hoff[0] = 1;
1523         hoff[1] = 0;
1524         http_header_parse_hoff(CONST_STR_LEN(":status: 500\r\n\r\n"), hoff);
1525     }
1526 
1527     /*(h2_init_con() resized h2r->tmp_buf to 64k; shared with r->tmp_buf)*/
1528     buffer * const tb = r->tmp_buf;
1529     force_assert(tb->size >= 65536);/*(sanity check; remove in future)*/
1530 
1531     /* FIXME: TODO: hpack-encode headers */
1532     uint32_t dlen = 0; /* TODO: hpack-encoded len */
1533     char *data = tb->ptr; /* TODO: hpack-encoded data */
1534 
1535     h2_send_hpack(r, con, tb->ptr, dlen, flags);
1536 }
1537 
1538 
1539 void
1540 h2_send_100_continue (request_st * const r, connection * const con)
1541 {
1542     /* place frame directly in con->write_queue for accounting to be part of
1543      * HTTP/2 protocol overhead, and not part of response header or body len */
1544     /* 100 Continue is small and will always fit in SETTING_MAX_FRAME_SIZE;
1545      * i.e. there will not be any CONTINUATION frames here */
1546 
1547     /* XXX: need to update hpack dynamic table,
1548      * or else could hard-code header block fragment
1549      * { 0x48, 0x03, 0x31, 0x30, 0x30 }
1550      */
1551 
1552     h2_send_headers_block(r, con, CONST_STR_LEN(":status: 100\r\n\r\n"), 0);
1553 }
1554 
1555 
1556 static void
1557 h2_send_end_stream_data (request_st * const r, connection * const con);
1558 
1559 __attribute_cold__
1560 __attribute_noinline__
1561 static void
1562 h2_send_end_stream_trailers (request_st * const r, connection * const con, const buffer * const trailers)
1563 {
1564     /*(trailers are merged into response headers if trailers are received before
1565      * sending response headers to client.  However, if streaming response, then
1566      * trailers might need handling here)*/
1567 
1568     /* parse and lowercase field-names in trailers */
1569     unsigned short hoff[8192]; /* max num header lines + 3; 16k on stack */
1570     hoff[0] = 1;                         /* number of lines */
1571     hoff[1] = 0;                         /* base offset for all lines */
1572     /*hoff[2] = ...;*/                   /* offset from base for 2nd line */
1573     uint32_t rc = http_header_parse_hoff(CONST_BUF_LEN(trailers), hoff);
1574     if (0 == rc || rc > USHRT_MAX || hoff[0] >= sizeof(hoff)/sizeof(hoff[0])-1
1575         || 1 == hoff[0]) { /*(initial blank line (should not happen))*/
1576         /* skip trailers if incomplete, too many fields, or too long (> 64k-1)*/
1577         h2_send_end_stream_data(r, con);
1578         return;
1579     }
1580 
1581     char * const ptr = trailers->ptr;
1582     for (int i = 1; i < hoff[0]; ++i) {
1583         char *k = ptr + ((i > 1) ? hoff[i] : 0);
1584         if (*k == ':') {
1585             /*(pseudo-header should not appear in trailers)*/
1586             h2_send_end_stream_data(r, con);
1587             return;
1588         }
1589         const char * const colon = memchr(k, ':', ptr+hoff[i+1]-k);
1590         if (NULL == colon) continue;
1591         do {
1592             if (*k >= 'A' && *k <= 'Z') *k |= 0x20;
1593         } while (++k != colon);
1594     }
1595 
1596     h2_send_headers_block(r, con, CONST_BUF_LEN(trailers), H2_FLAG_END_STREAM);
1597 }
1598 
1599 
1600 void
1601 h2_send_cqheaders (request_st * const r, connection * const con)
1602 {
1603     /*(assumes HTTP/1.1 response headers have been prepended as first chunk)
1604      *(future: if r->write_queue is bypassed for headers, adjust
1605      * r->write_queue bytes counts (bytes_in, bytes_out) with header len)*/
1606     /* note: expects field-names are lowercased (http_response_write_header())*/
1607     chunk * const c = r->write_queue->first;
1608     const uint32_t len = buffer_string_length(c->mem) - (uint32_t)c->offset;
1609     uint32_t flags = (r->resp_body_finished && NULL == c->next)
1610       ? H2_FLAG_END_STREAM
1611       : 0;
1612     h2_send_headers_block(r, con, c->mem->ptr + c->offset, len, flags);
1613     chunkqueue_mark_written(r->write_queue, len);
1614 }
1615 
1616 
1617 #if 0
1618 
1619 void
1620 h2_send_data (request_st * const r, connection * const con, const char *data, uint32_t dlen)
1621 {
1622     /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
1623 
1624     union {
1625       uint8_t c[12];
1626       uint32_t u[3];          /*(alignment)*/
1627     } dataframe = { {         /*(big-endian numbers)*/
1628       0x00, 0x00, 0x00        /* padding for alignment; do not send */
1629       /* DATA */
1630      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
1631      ,H2_FTYPE_DATA           /* frame type */
1632      ,0x00                    /* frame flags */
1633      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
1634     } };
1635 
1636     dataframe.u[2] = htonl(r->h2id);
1637 
1638     /* XXX: does not provide an optimization to send final set of data with
1639      *      END_STREAM flag; see h2_send_end_stream_data() to end stream */
1640 
1641     /* adjust stream and connection windows */
1642     /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
1643     request_st * const h2r = &con->request;
1644     if (r->h2_swin   < 0) return;
1645     if (h2r->h2_swin < 0) return;
1646     if ((int32_t)dlen > r->h2_swin)   dlen = (uint32_t)r->h2_swin;
1647     if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
1648     if (0 == dlen) return;
1649     r->h2_swin   -= (int32_t)dlen;
1650     h2r->h2_swin -= (int32_t)dlen;
1651 
1652     /* XXX: future: should have an interface which processes chunkqueue
1653      * and takes string refs to mmap FILE_CHUNK to avoid extra copying
1654      * since the result is likely to be consumed by TLS modules */
1655 
1656     /*(approximate space needed for frames (header + payload)
1657      * with slight over-estimate of 16 bytes per frame header (> 9)
1658      * and minimum SETTING_MAX_FRAME_SIZE of 16k (could be larger)
1659      * (dlen >> 14)+1 is num 16k frames needed, multipled by 16 bytes
1660      *  per frame can be appoximated with (dlen>>10) + 9)*/
1661     buffer * const b =
1662       chunkqueue_append_buffer_open_sz(con->write_queue, dlen + (dlen>>10) + 9);
1663     char * restrict ptr = b->ptr;
1664     h2con * const h2c = con->h2;
1665     const uint32_t fsize = h2c->s_max_frame_size;
1666     do {
1667         const uint32_t len = dlen < fsize ? dlen : fsize;
1668         dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
1669         dataframe.c[4] = (len >>  8) & 0xFF;
1670         dataframe.c[5] = (len      ) & 0xFF;
1671       #if 0
1672         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
1673                               (const char *)dataframe.c+3, sizeof(dataframe)-3);
1674         chunkqueue_append_mem(con->write_queue, data, len);
1675       #else
1676         memcpy(ptr, dataframe.c+3, sizeof(dataframe)-3);
1677         memcpy(ptr+sizeof(dataframe)-3, data, len);
1678         ptr  += len + sizeof(dataframe)-3;
1679       #endif
1680         data += len;
1681         dlen -= len;
1682     } while (dlen);
1683     buffer_string_set_length(b, (uint32_t)(ptr - b->ptr));
1684     chunkqueue_append_buffer_commit(con->write_queue);
1685 }
1686 
1687 #endif
1688 
1689 
1690 void
1691 h2_send_cqdata (request_st * const r, connection * const con, chunkqueue * const cq, uint32_t dlen)
1692 {
1693     /* Note: dlen should be <= MAX_WRITE_LIMIT in order to share resources */
1694 
1695     union {
1696       uint8_t c[12];
1697       uint32_t u[3];          /*(alignment)*/
1698     } dataframe = { {         /*(big-endian numbers)*/
1699       0x00, 0x00, 0x00        /* padding for alignment; do not send */
1700       /* DATA */
1701      ,0x00, 0x00, 0x00        /* frame length      (fill in below) */
1702      ,H2_FTYPE_DATA           /* frame type */
1703      ,0x00                    /* frame flags */
1704      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
1705     } };
1706 
1707     dataframe.u[2] = htonl(r->h2id);
1708 
1709     /* XXX: does not provide an optimization to send final set of data with
1710      *      END_STREAM flag; see h2_send_end_stream_data() to end stream */
1711 
1712     /* adjust stream and connection windows */
1713     /*assert(dlen <= INT32_MAX);*//* dlen should be <= MAX_WRITE_LIMIT */
1714     request_st * const h2r = &con->request;
1715     if (r->h2_swin   < 0) return;
1716     if (h2r->h2_swin < 0) return;
1717     if ((int32_t)dlen > r->h2_swin)   dlen = (uint32_t)r->h2_swin;
1718     if ((int32_t)dlen > h2r->h2_swin) dlen = (uint32_t)h2r->h2_swin;
1719     if (0 == dlen) return;
1720     r->h2_swin   -= (int32_t)dlen;
1721     h2r->h2_swin -= (int32_t)dlen;
1722 
1723     /* XXX: future: should have an interface which processes chunkqueue
1724      * and takes string refs to mmap FILE_CHUNK to avoid extra copying
1725      * since the result is likely to be consumed by TLS modules */
1726 
1727     h2con * const h2c = con->h2;
1728     const uint32_t fsize = h2c->s_max_frame_size;
1729     do {
1730         const uint32_t len = dlen < fsize ? dlen : fsize;
1731         dataframe.c[3] = (len >> 16) & 0xFF; /*(off +3 to skip over align pad)*/
1732         dataframe.c[4] = (len >>  8) & 0xFF;
1733         dataframe.c[5] = (len      ) & 0xFF;
1734         chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
1735                               (const char *)dataframe.c+3, sizeof(dataframe)-3);
1736         chunkqueue_steal(con->write_queue, cq, (off_t)dlen);
1737         dlen -= len;
1738     } while (dlen);
1739 }
1740 
1741 
1742 static void
1743 h2_send_end_stream_data (request_st * const r, connection * const con)
1744 {
1745     union {
1746       uint8_t c[12];
1747       uint32_t u[3];          /*(alignment)*/
1748     } dataframe = { {         /*(big-endian numbers)*/
1749       0x00, 0x00, 0x00        /* padding for alignment; do not send */
1750       /* DATA */
1751      ,0x00, 0x00, 0x00        /* frame length */
1752      ,H2_FTYPE_DATA           /* frame type */
1753      ,H2_FLAG_END_STREAM      /* frame flags */
1754      ,0x00, 0x00, 0x00, 0x00  /* stream identifier (fill in below) */
1755     } };
1756 
1757     dataframe.u[2] = htonl(r->h2id);
1758     r->h2state = H2_STATE_CLOSED;
1759     /*(ignore window updates when sending 0-length DATA frame with END_STREAM)*/
1760     chunkqueue_append_mem(con->write_queue,  /*(+3 to skip over align pad)*/
1761                           (const char *)dataframe.c+3, sizeof(dataframe)-3);
1762 }
1763 
1764 
1765 void
1766 h2_send_end_stream (request_st * const r, connection * const con)
1767 {
1768     if (r->state != CON_STATE_ERROR && r->resp_body_finished) {
1769         /* CON_STATE_RESPONSE_END */
1770         if (r->gw_dechunk && r->gw_dechunk->done
1771             && !buffer_is_empty(&r->gw_dechunk->b))
1772             h2_send_end_stream_trailers(r, con, &r->gw_dechunk->b);
1773         else
1774             h2_send_end_stream_data(r, con);
1775     }
1776     else { /* CON_STATE_ERROR */
1777         h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1778     }
1779 }
1780 
1781 
1782 /*
1783  * (XXX: might move below to separate file)
1784  */
1785 #include "base64.h"
1786 #include "chunk.h"
1787 #include "plugin.h"
1788 #include "plugin_config.h"
1789 #include "reqpool.h"
1790 
1791 
1792 static request_st *
1793 h2_init_stream (request_st * const h2r, connection * const con)
1794 {
1795     h2con * const h2c = con->h2;
1796     ++con->request_count;
1797     force_assert(h2c->rused < sizeof(h2c->r)/sizeof(*h2c->r));
1798     /* initialize stream as subrequest (request_st *) */
1799     request_st * const r = calloc(1, sizeof(request_st));
1800     force_assert(r);
1801     /* XXX: TODO: assign default priority, etc.
1802      *      Perhaps store stream id and priority in separate table */
1803     h2c->r[h2c->rused++] = r;
1804     server * const srv = con->srv;
1805     request_init(r, con, srv);
1806     r->h2_rwin = h2c->s_initial_window_size;
1807     r->h2_swin = h2c->s_initial_window_size;
1808     r->http_version = HTTP_VERSION_2;
1809 
1810     /* copy config state from h2r */
1811     const uint32_t used = srv->config_context->used;
1812     r->conditional_is_valid = h2r->conditional_is_valid;
1813     memcpy(r->cond_cache, h2r->cond_cache, used * sizeof(cond_cache_t));
1814   #ifdef HAVE_PCRE_H
1815     if (used > 1) /*(save 128b per con if no conditions)*/
1816         memcpy(r->cond_match, h2r->cond_match, used * sizeof(cond_match_t));
1817   #endif
1818     r->server_name = h2r->server_name;
1819     memcpy(&r->conf, &h2r->conf, sizeof(request_config));
1820 
1821     /* stream id must be assigned by caller */
1822     return r;
1823 }
1824 
1825 
1826 static void
1827 h2_release_stream (request_st * const r, connection * const con)
1828 {
1829     if (r->http_status) {
1830         /* (see comment in connection_handle_response_end_state()) */
1831         plugins_call_handle_request_done(r);
1832 
1833       #if 0
1834         /* (fuzzy accounting for mod_accesslog, mod_rrdtool to avoid
1835          *  double counting, but HTTP/2 framing and HPACK-encoded headers in
1836          *  con->read_queue and con->write_queue are not equivalent to the
1837          *  HPACK-decoded headers and request and response bodies in stream
1838          *  r->read_queue and r->write_queue) */
1839         /* DISABLED since mismatches invalidate the relationship between
1840          * con->bytes_in and con->bytes_out */
1841         con->read_queue->bytes_in   -= r->read_queue->bytes_in;
1842         con->write_queue->bytes_out -= r->write_queue->bytes_out;
1843       #else
1844         UNUSED(con);
1845       #endif
1846     }
1847 
1848     request_reset(r);
1849     /* future: might keep a pool of reusable (request_st *) */
1850     request_free(r);
1851     free(r);
1852 }
1853 
1854 
1855 void
1856 h2_retire_stream (request_st *r, connection * const con)
1857 {
1858     if (r == NULL) return; /*(should not happen)*/
1859     h2con * const h2c = con->h2;
1860     request_st ** const ar = h2c->r;
1861     for (uint32_t i = 0, j = 0, rused = h2c->rused; i < rused; ++i) {
1862         if (ar[i] != r)
1863             ar[j++] = ar[i];
1864         else {
1865             h2_release_stream(r, con);
1866             r = NULL;
1867         }
1868     }
1869     if (r == NULL) /* found */
1870         h2c->r[--h2c->rused] = NULL;
1871     /*else ... should not happen*/
1872 }
1873 
1874 
1875 void
1876 h2_retire_con (request_st * const h2r, connection * const con)
1877 {
1878     h2con * const h2c = con->h2;
1879     if (NULL == h2c) return;
1880 
1881     if (h2r->state != CON_STATE_ERROR) { /*(CON_STATE_RESPONSE_END)*/
1882         h2_send_goaway(con, H2_E_NO_ERROR);
1883         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
1884             /*(unexpected if CON_STATE_RESPONSE_END)*/
1885             request_st * const r = h2c->r[i];
1886             h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
1887             h2_release_stream(r, con);
1888         }
1889         if (!chunkqueue_is_empty(con->write_queue)) {
1890             /* similar to connection_handle_write() but without error checks,
1891              * without MAX_WRITE_LIMIT, and without connection throttling */
1892             /*h2r->conf.bytes_per_second = 0;*/         /* disable rate limit */
1893             /*h2r->conf.global_bytes_per_second = 0;*/  /* disable rate limit */
1894             /*con->traffic_limit_reached = 0;*/
1895             chunkqueue * const cq = con->write_queue;
1896             const off_t len = chunkqueue_length(cq);
1897             off_t written = cq->bytes_out;
1898             con->network_write(con, cq, len);
1899             /*(optional accounting)*/
1900             written = cq->bytes_out - written;
1901             con->bytes_written += written;
1902             con->bytes_written_cur_second += written;
1903             if (h2r->conf.global_bytes_per_second_cnt_ptr)
1904                 *(h2r->conf.global_bytes_per_second_cnt_ptr) += written;
1905         }
1906     }
1907     else { /* CON_STATE_ERROR */
1908         for (uint32_t i = 0, rused = h2c->rused; i < rused; ++i) {
1909             request_st * const r = h2c->r[i];
1910             h2_release_stream(r, con);
1911         }
1912         /* XXX: perhaps attempt to send GOAWAY?  Not when CON_STATE_ERROR */
1913     }
1914 
1915     con->h2 = NULL;
1916 
1917     /* future: might keep a pool of reusable (h2con *) */
1918     free(h2c);
1919 }
1920 
1921 
1922 static void
1923 h2_con_upgrade_h2c (request_st * const h2r, const buffer * const http2_settings)
1924 {
1925     /* status: (h2r->state == CON_STATE_REQUEST_END) for Upgrade: h2c */
1926 
1927     /* HTTP/1.1 101 Switching Protocols
1928      * Connection: Upgrade
1929      * Upgrade: h2c
1930      */
1931   #if 1
1932     static const char switch_proto[] = "HTTP/1.1 101 Switching Protocols\r\n"
1933                                        "Connection: Upgrade\r\n"
1934                                        "Upgrade: h2c\r\n\r\n";
1935     chunkqueue_append_mem(h2r->write_queue,
1936                           CONST_STR_LEN(switch_proto));
1937     h2r->resp_header_len = sizeof(switch_proto)-1;
1938   #else
1939     h2r->http_status = 101;
1940     http_header_response_set(h2r, HTTP_HEADER_UPGRADE, CONST_STR_LEN("Upgrade"),
1941                                                        CONST_STR_LEN("h2c"));
1942     http_response_write_header(h2r);
1943     http_response_reset(h2r);
1944     h2r->http_status = 0;
1945   #endif
1946 
1947     connection * const con = h2r->con;
1948     h2_init_con(h2r, con, http2_settings);
1949     if (con->h2->sent_goaway) return;
1950 
1951     con->h2->h2_cid = 1; /* stream id 1 is assigned to h2c upgrade */
1952 
1953     /* copy request state from &con->request to subrequest r
1954      * XXX: would be nice if there were a cleaner way to do this
1955      * (This is fragile and must be kept in-sync with request_st in request.h)*/
1956 
1957     request_st * const r = h2_init_stream(h2r, con);
1958     /*(undo double-count; already incremented in CON_STATE_REQUEST_START)*/
1959     --con->request_count;
1960     r->state = h2r->state; /* CON_STATE_REQUEST_END */
1961     r->http_status = 0;
1962     r->http_method = h2r->http_method;
1963     r->h2state = H2_STATE_HALF_CLOSED_REMOTE;
1964     r->h2id = 1;
1965     r->rqst_htags = h2r->rqst_htags;
1966     h2r->rqst_htags = 0;
1967     r->rqst_header_len = h2r->rqst_header_len;
1968     h2r->rqst_header_len = 0;
1969     r->rqst_headers = h2r->rqst_headers;        /* copy struct */
1970     memset(&h2r->rqst_headers, 0, sizeof(array));
1971     r->uri = h2r->uri;                          /* copy struct */
1972   #if 0
1973     r->physical = h2r->physical;                /* copy struct */
1974     r->env = h2r->env;                          /* copy struct */
1975   #endif
1976     memset(&h2r->rqst_headers, 0, sizeof(array));
1977     memset(&h2r->uri, 0, sizeof(request_uri));
1978   #if 0
1979     memset(&h2r->physical, 0, sizeof(physical));
1980     memset(&h2r->env, 0, sizeof(array));
1981   #endif
1982   #if 0 /* expect empty request body */
1983     r->reqbody_length = h2r->reqbody_length; /* currently always 0 */
1984     r->te_chunked = h2r->te_chunked;         /* must be 0 */
1985     swap(r->reqbody_queue, h2r->reqbody_queue); /*currently always empty queue*/
1986   #endif
1987     r->http_host = h2r->http_host;
1988     h2r->http_host = NULL;
1989   #if 0
1990     r->server_name = h2r->server_name;
1991     h2r->server_name = NULL;
1992   #endif
1993     r->target = h2r->target;                    /* copy struct */
1994     r->target_orig = h2r->target_orig;          /* copy struct */
1995   #if 0
1996     r->pathinfo = h2r->pathinfo;                /* copy struct */
1997     r->server_name_buf = h2r->server_name_buf;  /* copy struct */
1998   #endif
1999     memset(&h2r->target, 0, sizeof(buffer));
2000     memset(&h2r->target_orig, 0, sizeof(buffer));
2001   #if 0
2002     memset(&h2r->pathinfo, 0, sizeof(buffer));
2003     memset(&h2r->server_name_buf, 0, sizeof(buffer));
2004   #endif
2005   #if 0
2006     /* skip copying response structures, other state not yet modified in h2r */
2007     /* r write_queue and read_queue are intentionally separate from h2r */
2008     /* r->gw_dechunk must be NULL for HTTP/2 */
2009     /* bytes_written_ckpt and bytes_read_ckpt are for HTTP/1.1 */
2010     /* error handlers have not yet been set */
2011   #endif
2012   #if 0
2013     r->loops_per_request = h2r->loops_per_request;
2014     r->async_callback = h2r->async_callback;
2015   #endif
2016     r->keep_alive = h2r->keep_alive;
2017     r->tmp_buf = h2r->tmp_buf;                /* shared; same as srv->tmp_buf */
2018     r->start_hp = h2r->start_hp;                /* copy struct */
2019     r->start_ts = h2r->start_ts;
2020 
2021     /* Note: HTTP/1.1 101 Switching Protocols is not immediately written to
2022      * the network here.  As this is called from cleartext Upgrade: h2c,
2023      * we choose to delay sending the status until the beginning of the response
2024      * to the HTTP/1.1 request which included Upgrade: h2c */
2025 }
2026 
2027 
2028 int
2029 h2_check_con_upgrade_h2c (request_st * const r)
2030 {
2031     /* RFC7540 3.2 Starting HTTP/2 for "http" URIs */
2032 
2033     buffer *http_connection, *http2_settings;
2034     buffer *upgrade = http_header_request_get(r, HTTP_HEADER_UPGRADE,
2035                                               CONST_STR_LEN("Upgrade"));
2036     if (NULL == upgrade) return 0;
2037     http_connection = http_header_request_get(r, HTTP_HEADER_CONNECTION,
2038                                               CONST_STR_LEN("Connection"));
2039     if (NULL == http_connection) {
2040         http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2041                                   CONST_STR_LEN("Upgrade"));
2042         return 0;
2043     }
2044     if (r->http_version != HTTP_VERSION_1_1) {
2045         http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2046                                   CONST_STR_LEN("Upgrade"));
2047         http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2048         return 0;
2049     }
2050 
2051     if (!http_header_str_contains_token(CONST_BUF_LEN(upgrade),
2052                                         CONST_STR_LEN("h2c")))
2053         return 0;
2054 
2055     http2_settings = http_header_request_get(r, HTTP_HEADER_HTTP2_SETTINGS,
2056                                              CONST_STR_LEN("HTTP2-Settings"));
2057     if (NULL != http2_settings) {
2058         if (0 == r->reqbody_length) {
2059             buffer * const b = r->tmp_buf;
2060             buffer_clear(b);
2061             if (r->conf.h2proto > 1/*(must be enabled with server.h2c feature)*/
2062                 &&
2063                 http_header_str_contains_token(CONST_BUF_LEN(http_connection),
2064                                                CONST_STR_LEN("HTTP2-Settings"))
2065                 && buffer_append_base64_decode(b, CONST_BUF_LEN(http2_settings),
2066                                                BASE64_URL)) {
2067                 h2_con_upgrade_h2c(r, b);
2068                 r->http_version = HTTP_VERSION_2;
2069             } /* else ignore if invalid base64 */
2070         }
2071         else {
2072             /* ignore Upgrade: h2c if request body present since we do not
2073              * (currently) handle request body before transition to h2c */
2074             /* RFC7540 3.2 Requests that contain a payload body MUST be sent
2075              * in their entirety before the client can send HTTP/2 frames. */
2076         }
2077         http_header_request_unset(r, HTTP_HEADER_HTTP2_SETTINGS,
2078                                   CONST_STR_LEN("HTTP2-Settings"));
2079         http_header_remove_token(http_connection, CONST_STR_LEN("HTTP2-Settings"));
2080     } /* else ignore Upgrade: h2c; HTTP2-Settings required for Upgrade: h2c */
2081     http_header_request_unset(r, HTTP_HEADER_UPGRADE,
2082                               CONST_STR_LEN("Upgrade"));
2083     http_header_remove_token(http_connection, CONST_STR_LEN("Upgrade"));
2084     return (r->http_version == HTTP_VERSION_2);
2085 }
2086