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