1 /*-
2 * Copyright (c) 2016-2019 Varnish Software AS
3 * All rights reserved.
4 *
5 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32 #include "config.h"
33
34 #include "cache/cache_varnishd.h"
35
36 #include <stdio.h>
37 #include <stdlib.h>
38
39 #include "cache/cache_transport.h"
40 #include "cache/cache_filter.h"
41 #include "http2/cache_http2.h"
42 #include "cache/cache_objhead.h"
43
44 #include "vend.h"
45 #include "vtcp.h"
46 #include "vtim.h"
47
48 #define H2EC1(U,v,r,d) const struct h2_error_s H2CE_##U[1] = {{#U,d,v,0,1,r}};
49 #define H2EC2(U,v,r,d) const struct h2_error_s H2SE_##U[1] = {{#U,d,v,1,0,r}};
50 #define H2EC3(U,v,r,d) H2EC1(U,v,r,d) H2EC2(U,v,r,d)
51 #define H2_ERROR(NAME, val, sc, reason, desc) H2EC##sc(NAME, val, reason, desc)
52 #include "tbl/h2_error.h"
53 #undef H2EC1
54 #undef H2EC2
55 #undef H2EC3
56
57 static const struct h2_error_s H2NN_ERROR[1] = {{
58 "UNKNOWN_ERROR",
59 "Unknown error number",
60 0xffffffff,
61 1,
62 1,
63 SC_RX_JUNK
64 }};
65
66 enum h2frame {
67 #define H2_FRAME(l,u,t,f,...) H2F_##u = t,
68 #include "tbl/h2_frames.h"
69 };
70
71 static const char *
h2_framename(enum h2frame h2f)72 h2_framename(enum h2frame h2f)
73 {
74
75 switch (h2f) {
76 #define H2_FRAME(l,u,t,f,...) case H2F_##u: return #u;
77 #include "tbl/h2_frames.h"
78 default:
79 return (NULL);
80 }
81 }
82
83 #define H2_FRAME_FLAGS(l,u,v) const uint8_t H2FF_##u = v;
84 #include "tbl/h2_frames.h"
85
86 /**********************************************************************
87 */
88
89 static const h2_error stream_errors[] = {
90 #define H2EC1(U,v,r,d)
91 #define H2EC2(U,v,r,d) [v] = H2SE_##U,
92 #define H2EC3(U,v,r,d) H2EC1(U,v,r,d) H2EC2(U,v,r,d)
93 #define H2_ERROR(NAME, val, sc, reason, desc) H2EC##sc(NAME, val, reason, desc)
94 #include "tbl/h2_error.h"
95 #undef H2EC1
96 #undef H2EC2
97 #undef H2EC3
98 };
99
100 #define NSTREAMERRORS (sizeof(stream_errors)/sizeof(stream_errors[0]))
101
102 static h2_error
h2_streamerror(uint32_t u)103 h2_streamerror(uint32_t u)
104 {
105 if (u < NSTREAMERRORS && stream_errors[u] != NULL)
106 return (stream_errors[u]);
107 else
108 return (H2NN_ERROR);
109 }
110
111 /**********************************************************************
112 */
113
114 static const h2_error conn_errors[] = {
115 #define H2EC1(U,v,r,d) [v] = H2CE_##U,
116 #define H2EC2(U,v,r,d)
117 #define H2EC3(U,v,r,d) H2EC1(U,v,r,d) H2EC2(U,v,r,d)
118 #define H2_ERROR(NAME, val, sc, reason, desc) H2EC##sc(NAME, val, reason, desc)
119 #include "tbl/h2_error.h"
120 #undef H2EC1
121 #undef H2EC2
122 #undef H2EC3
123 };
124
125 #define NCONNERRORS (sizeof(conn_errors)/sizeof(conn_errors[0]))
126
127 static h2_error
h2_connectionerror(uint32_t u)128 h2_connectionerror(uint32_t u)
129 {
130 if (u < NCONNERRORS && conn_errors[u] != NULL)
131 return (conn_errors[u]);
132 else
133 return (H2NN_ERROR);
134 }
135
136 /**********************************************************************/
137
138 struct h2_req *
h2_new_req(const struct worker * wrk,struct h2_sess * h2,unsigned stream,struct req * req)139 h2_new_req(const struct worker *wrk, struct h2_sess *h2,
140 unsigned stream, struct req *req)
141 {
142 struct h2_req *r2;
143
144 ASSERT_RXTHR(h2);
145 if (req == NULL)
146 req = Req_New(wrk, h2->sess);
147 CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
148
149 r2 = WS_Alloc(req->ws, sizeof *r2);
150 AN(r2);
151 INIT_OBJ(r2, H2_REQ_MAGIC);
152 r2->state = H2_S_IDLE;
153 r2->h2sess = h2;
154 r2->stream = stream;
155 r2->req = req;
156 if (stream)
157 r2->counted = 1;
158 r2->r_window = h2->local_settings.initial_window_size;
159 r2->t_window = h2->remote_settings.initial_window_size;
160 req->transport_priv = r2;
161 Lck_Lock(&h2->sess->mtx);
162 if (stream)
163 h2->open_streams++;
164 VTAILQ_INSERT_TAIL(&h2->streams, r2, list);
165 Lck_Unlock(&h2->sess->mtx);
166 h2->refcnt++;
167 return (r2);
168 }
169
170 void
h2_del_req(struct worker * wrk,const struct h2_req * r2)171 h2_del_req(struct worker *wrk, const struct h2_req *r2)
172 {
173 struct h2_sess *h2;
174 struct sess *sp;
175
176 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
177 AZ(r2->scheduled);
178 h2 = r2->h2sess;
179 CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
180 ASSERT_RXTHR(h2);
181 sp = h2->sess;
182 Lck_Lock(&sp->mtx);
183 assert(h2->refcnt > 0);
184 --h2->refcnt;
185 /* XXX: PRIORITY reshuffle */
186 VTAILQ_REMOVE(&h2->streams, r2, list);
187 Lck_Unlock(&sp->mtx);
188 assert(!WS_IsReserved(r2->req->ws));
189 Req_Cleanup(sp, wrk, r2->req);
190 Req_Release(r2->req);
191 }
192
193 void
h2_kill_req(struct worker * wrk,struct h2_sess * h2,struct h2_req * r2,h2_error h2e)194 h2_kill_req(struct worker *wrk, struct h2_sess *h2,
195 struct h2_req *r2, h2_error h2e)
196 {
197
198 ASSERT_RXTHR(h2);
199 AN(h2e);
200 Lck_Lock(&h2->sess->mtx);
201 VSLb(h2->vsl, SLT_Debug, "KILL st=%u state=%d sched=%d",
202 r2->stream, r2->state, r2->scheduled);
203 if (r2->counted) {
204 assert(h2->open_streams > 0);
205 h2->open_streams--;
206 r2->counted = 0;
207 }
208 if (r2->error == NULL)
209 r2->error = h2e;
210 if (r2->scheduled) {
211 if (r2->cond != NULL)
212 AZ(pthread_cond_signal(r2->cond));
213 r2 = NULL;
214 } else {
215 if (r2->state == H2_S_OPEN && h2->new_req == r2->req)
216 (void)h2h_decode_fini(h2);
217 }
218 Lck_Unlock(&h2->sess->mtx);
219 if (r2 != NULL)
220 h2_del_req(wrk, r2);
221 }
222
223 /**********************************************************************/
224
225 static void
h2_vsl_frame(const struct h2_sess * h2,const void * ptr,size_t len)226 h2_vsl_frame(const struct h2_sess *h2, const void *ptr, size_t len)
227 {
228 const uint8_t *b;
229 struct vsb *vsb;
230 const char *p;
231 unsigned u;
232
233 AN(ptr);
234 assert(len >= 9);
235 b = ptr;
236
237 vsb = VSB_new_auto();
238 AN(vsb);
239 p = h2_framename((enum h2frame)b[3]);
240 if (p != NULL)
241 VSB_cat(vsb, p);
242 else
243 VSB_quote(vsb, b + 3, 1, VSB_QUOTE_HEX);
244
245 u = vbe32dec(b) >> 8;
246 VSB_printf(vsb, "[%u] ", u);
247 VSB_quote(vsb, b + 4, 1, VSB_QUOTE_HEX);
248 VSB_putc(vsb, ' ');
249 VSB_quote(vsb, b + 5, 4, VSB_QUOTE_HEX);
250 if (u > 0) {
251 VSB_putc(vsb, ' ');
252 VSB_quote(vsb, b + 9, len - 9, VSB_QUOTE_HEX);
253 }
254 AZ(VSB_finish(vsb));
255 Lck_Lock(&h2->sess->mtx);
256 VSLb_bin(h2->vsl, SLT_H2RxHdr, 9, b);
257 if (len > 9)
258 VSLb_bin(h2->vsl, SLT_H2RxBody, len - 9, b + 9);
259
260 VSLb(h2->vsl, SLT_Debug, "H2RXF %s", VSB_data(vsb));
261 Lck_Unlock(&h2->sess->mtx);
262 VSB_destroy(&vsb);
263 }
264
265
266 /**********************************************************************
267 */
268
v_matchproto_(h2_rxframe_f)269 static h2_error v_matchproto_(h2_rxframe_f)
270 h2_rx_ping(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
271 {
272
273 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
274 ASSERT_RXTHR(h2);
275 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
276 assert(r2 == h2->req0);
277
278 if (h2->rxf_len != 8) // rfc7540,l,2364,2366
279 return (H2CE_FRAME_SIZE_ERROR);
280 AZ(h2->rxf_stream); // rfc7540,l,2359,2362
281 if (h2->rxf_flags != 0) // We never send pings
282 return (H2SE_PROTOCOL_ERROR);
283 H2_Send_Get(wrk, h2, r2);
284 H2_Send_Frame(wrk, h2,
285 H2_F_PING, H2FF_PING_ACK, 8, 0, h2->rxf_data);
286 H2_Send_Rel(h2, r2);
287 return (0);
288 }
289
290 /**********************************************************************
291 */
292
v_matchproto_(h2_rxframe_f)293 static h2_error v_matchproto_(h2_rxframe_f)
294 h2_rx_push_promise(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
295 {
296
297 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
298 ASSERT_RXTHR(h2);
299 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
300 // rfc7540,l,2262,2267
301 return (H2CE_PROTOCOL_ERROR);
302 }
303
304 /**********************************************************************
305 */
306
v_matchproto_(h2_rxframe_f)307 static h2_error v_matchproto_(h2_rxframe_f)
308 h2_rx_rst_stream(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
309 {
310
311 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
312 ASSERT_RXTHR(h2);
313 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
314
315 if (h2->rxf_len != 4) // rfc7540,l,2003,2004
316 return (H2CE_FRAME_SIZE_ERROR);
317 if (r2 == NULL)
318 return (0);
319 h2_kill_req(wrk, h2, r2, h2_streamerror(vbe32dec(h2->rxf_data)));
320 return (0);
321 }
322
323 /**********************************************************************
324 */
325
v_matchproto_(h2_rxframe_f)326 static h2_error v_matchproto_(h2_rxframe_f)
327 h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
328 {
329
330 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
331 ASSERT_RXTHR(h2);
332 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
333 assert(r2 == h2->req0);
334
335 h2->goaway_last_stream = vbe32dec(h2->rxf_data);
336 h2->error = h2_connectionerror(vbe32dec(h2->rxf_data + 4));
337 Lck_Lock(&h2->sess->mtx);
338 VSLb(h2->vsl, SLT_Debug, "GOAWAY %s", h2->error->name);
339 Lck_Unlock(&h2->sess->mtx);
340 return (h2->error);
341 }
342
343 /**********************************************************************
344 */
345
v_matchproto_(h2_rxframe_f)346 static h2_error v_matchproto_(h2_rxframe_f)
347 h2_rx_window_update(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
348 {
349 uint32_t wu;
350
351 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
352 ASSERT_RXTHR(h2);
353 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
354
355 if (h2->rxf_len != 4)
356 return (H2CE_FRAME_SIZE_ERROR);
357 wu = vbe32dec(h2->rxf_data) & ~(1LU<<31);
358 if (wu == 0)
359 return (H2SE_PROTOCOL_ERROR);
360 if (r2 == NULL)
361 return (0);
362 Lck_Lock(&h2->sess->mtx);
363 r2->t_window += wu;
364 if (r2 == h2->req0)
365 AZ(pthread_cond_broadcast(h2->winupd_cond));
366 else if (r2->cond != NULL)
367 AZ(pthread_cond_signal(r2->cond));
368 Lck_Unlock(&h2->sess->mtx);
369 if (r2->t_window >= (1LL << 31))
370 return (H2SE_FLOW_CONTROL_ERROR);
371 return (0);
372 }
373
374 /**********************************************************************
375 * Incoming PRIORITY, possibly an ACK of one we sent.
376 */
377
v_matchproto_(h2_rxframe_f)378 static h2_error v_matchproto_(h2_rxframe_f)
379 h2_rx_priority(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
380 {
381
382 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
383 ASSERT_RXTHR(h2);
384 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
385 return (0);
386 }
387
388 /**********************************************************************
389 * Incoming SETTINGS, possibly an ACK of one we sent.
390 */
391
392 #define H2_SETTING(U,l, ...) \
393 static void v_matchproto_(h2_setsetting_f) \
394 h2_setting_##l(struct h2_settings* s, uint32_t v) \
395 { \
396 s -> l = v; \
397 }
398 #include <tbl/h2_settings.h>
399
400 #define H2_SETTING(U, l, ...) \
401 const struct h2_setting_s H2_SET_##U[1] = {{ \
402 #l, \
403 h2_setting_##l, \
404 __VA_ARGS__ \
405 }};
406 #include <tbl/h2_settings.h>
407
408 static const struct h2_setting_s * const h2_setting_tbl[] = {
409 #define H2_SETTING(U,l,v, ...) [v] = H2_SET_##U,
410 #include <tbl/h2_settings.h>
411 };
412
413 #define H2_SETTING_TBL_LEN (sizeof(h2_setting_tbl)/sizeof(h2_setting_tbl[0]))
414
415 static void
h2_win_adjust(const struct h2_sess * h2,uint32_t oldval,uint32_t newval)416 h2_win_adjust(const struct h2_sess *h2, uint32_t oldval, uint32_t newval)
417 {
418 struct h2_req *r2;
419
420 Lck_AssertHeld(&h2->sess->mtx);
421 // rfc7540,l,2668,2674
422 VTAILQ_FOREACH(r2, &h2->streams, list) {
423 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
424 if (r2 == h2->req0)
425 continue; // rfc7540,l,2699,2699
426 switch (r2->state) {
427 case H2_S_IDLE:
428 case H2_S_OPEN:
429 case H2_S_CLOS_REM:
430 /*
431 * We allow a window to go negative, as per
432 * rfc7540,l,2676,2680
433 */
434 r2->t_window += (int64_t)newval - oldval;
435 break;
436 default:
437 break;
438 }
439 }
440 }
441
442 h2_error
h2_set_setting(struct h2_sess * h2,const uint8_t * d)443 h2_set_setting(struct h2_sess *h2, const uint8_t *d)
444 {
445 const struct h2_setting_s *s;
446 uint16_t x;
447 uint32_t y;
448
449 x = vbe16dec(d);
450 y = vbe32dec(d + 2);
451 if (x >= H2_SETTING_TBL_LEN || h2_setting_tbl[x] == NULL) {
452 // rfc7540,l,2181,2182
453 Lck_Lock(&h2->sess->mtx);
454 VSLb(h2->vsl, SLT_Debug,
455 "H2SETTING unknown setting 0x%04x=%08x (ignored)", x, y);
456 Lck_Unlock(&h2->sess->mtx);
457 return (0);
458 }
459 s = h2_setting_tbl[x];
460 AN(s);
461 if (y < s->minval || y > s->maxval) {
462 Lck_Lock(&h2->sess->mtx);
463 VSLb(h2->vsl, SLT_Debug, "H2SETTING invalid %s=0x%08x",
464 s->name, y);
465 Lck_Unlock(&h2->sess->mtx);
466 AN(s->range_error);
467 if (!DO_DEBUG(DBG_H2_NOCHECK))
468 return (s->range_error);
469 }
470 Lck_Lock(&h2->sess->mtx);
471 if (s == H2_SET_INITIAL_WINDOW_SIZE)
472 h2_win_adjust(h2, h2->remote_settings.initial_window_size, y);
473 VSLb(h2->vsl, SLT_Debug, "H2SETTING %s=0x%08x", s->name, y);
474 Lck_Unlock(&h2->sess->mtx);
475 AN(s->setfunc);
476 s->setfunc(&h2->remote_settings, y);
477 return (0);
478 }
479
v_matchproto_(h2_rxframe_f)480 static h2_error v_matchproto_(h2_rxframe_f)
481 h2_rx_settings(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
482 {
483 const uint8_t *p;
484 unsigned l;
485 h2_error retval = 0;
486
487 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
488 ASSERT_RXTHR(h2);
489 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
490 assert(r2 == h2->req0);
491 AZ(h2->rxf_stream);
492
493 if (h2->rxf_flags == H2FF_SETTINGS_ACK) {
494 if (h2->rxf_len > 0) // rfc7540,l,2047,2049
495 return (H2CE_FRAME_SIZE_ERROR);
496 return (0);
497 } else {
498 if (h2->rxf_len % 6) // rfc7540,l,2062,2064
499 return (H2CE_PROTOCOL_ERROR);
500 p = h2->rxf_data;
501 for (l = h2->rxf_len; l >= 6; l -= 6, p += 6) {
502 retval = h2_set_setting(h2, p);
503 if (retval)
504 return (retval);
505 }
506 H2_Send_Get(wrk, h2, r2);
507 H2_Send_Frame(wrk, h2,
508 H2_F_SETTINGS, H2FF_SETTINGS_ACK, 0, 0, NULL);
509 H2_Send_Rel(h2, r2);
510 }
511 return (0);
512 }
513
514 /**********************************************************************
515 * Incoming HEADERS, this is where the partys at...
516 */
517
v_matchproto_(task_func_t)518 void v_matchproto_(task_func_t)
519 h2_do_req(struct worker *wrk, void *priv)
520 {
521 struct req *req;
522 struct h2_req *r2;
523 struct h2_sess *h2;
524
525 CAST_OBJ_NOTNULL(req, priv, REQ_MAGIC);
526 CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
527 THR_SetRequest(req);
528 CNT_Embark(wrk, req);
529
530 wrk->stats->client_req++;
531 if (CNT_Request(req) != REQ_FSM_DISEMBARK) {
532 assert(!WS_IsReserved(req->ws));
533 AZ(req->top->vcl0);
534 h2 = r2->h2sess;
535 CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
536 Lck_Lock(&h2->sess->mtx);
537 r2->scheduled = 0;
538 r2->state = H2_S_CLOSED;
539 r2->h2sess->do_sweep = 1;
540 if (h2->mailcall == r2) {
541 h2->mailcall = NULL;
542 AZ(pthread_cond_signal(h2->cond));
543 }
544 Lck_Unlock(&h2->sess->mtx);
545 }
546 THR_SetRequest(NULL);
547 }
548
549 static h2_error
h2_end_headers(struct worker * wrk,struct h2_sess * h2,struct req * req,struct h2_req * r2)550 h2_end_headers(struct worker *wrk, struct h2_sess *h2,
551 struct req *req, struct h2_req *r2)
552 {
553 h2_error h2e;
554 ssize_t cl;
555
556 ASSERT_RXTHR(h2);
557 assert(r2->state == H2_S_OPEN);
558 h2e = h2h_decode_fini(h2);
559 h2->new_req = NULL;
560 if (h2e != NULL) {
561 Lck_Lock(&h2->sess->mtx);
562 VSLb(h2->vsl, SLT_Debug, "HPACK/FINI %s", h2e->name);
563 Lck_Unlock(&h2->sess->mtx);
564 assert(!WS_IsReserved(r2->req->ws));
565 h2_del_req(wrk, r2);
566 return (h2e);
567 }
568 VSLb_ts_req(req, "Req", req->t_req);
569
570 // XXX: Smarter to do this already at HPACK time into tail end of
571 // XXX: WS, then copy back once all headers received.
572 // XXX: Have I mentioned H/2 Is hodge-podge ?
573 http_CollectHdrSep(req->http, H_Cookie, "; "); // rfc7540,l,3114,3120
574
575 cl = http_GetContentLength(req->http);
576 assert(cl >= -2);
577 if (cl == -2) {
578 VSLb(h2->vsl, SLT_Debug, "Non-parseable Content-Length");
579 return (H2SE_PROTOCOL_ERROR);
580 }
581
582 if (req->req_body_status == NULL) {
583 if (cl == -1)
584 req->req_body_status = BS_EOF;
585 else
586 req->req_body_status = BS_LENGTH;
587 req->htc->content_length = cl;
588 } else {
589 /* A HEADER frame contained END_STREAM */
590 assert (req->req_body_status == BS_NONE);
591 r2->state = H2_S_CLOS_REM;
592 if (cl > 0)
593 return (H2CE_PROTOCOL_ERROR); //rfc7540,l,1838,1840
594 }
595
596 if (req->http->hd[HTTP_HDR_METHOD].b == NULL) {
597 VSLb(h2->vsl, SLT_Debug, "Missing :method");
598 return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
599 }
600 if (req->http->hd[HTTP_HDR_URL].b == NULL) {
601 VSLb(h2->vsl, SLT_Debug, "Missing :path");
602 return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
603 }
604 AN(req->http->hd[HTTP_HDR_PROTO].b);
605
606 assert(req->req_step == R_STP_TRANSPORT);
607 VCL_TaskEnter(req->privs);
608 VCL_TaskEnter(req->top->privs);
609 req->task->func = h2_do_req;
610 req->task->priv = req;
611 r2->scheduled = 1;
612 if (Pool_Task(wrk->pool, req->task, TASK_QUEUE_STR) != 0) {
613 r2->scheduled = 0;
614 r2->state = H2_S_CLOSED;
615 return (H2SE_REFUSED_STREAM); //rfc7540,l,3326,3329
616 }
617 return (0);
618 }
619
v_matchproto_(h2_rxframe_f)620 static h2_error v_matchproto_(h2_rxframe_f)
621 h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
622 {
623 struct req *req;
624 h2_error h2e;
625 const uint8_t *p;
626 size_t l;
627
628 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
629 ASSERT_RXTHR(h2);
630
631 if (r2 == NULL) {
632 if (h2->rxf_stream <= h2->highest_stream)
633 return (H2CE_PROTOCOL_ERROR); // rfc7540,l,1153,1158
634 /* NB: we don't need to guard the read of h2->open_streams
635 * because headers are handled sequentially so it cannot
636 * increase under our feet.
637 */
638 if (h2->open_streams >=
639 h2->local_settings.max_concurrent_streams) {
640 VSLb(h2->vsl, SLT_Debug,
641 "H2: stream %u: Hit maximum number of "
642 "concurrent streams", h2->rxf_stream);
643 return (H2SE_REFUSED_STREAM); // rfc7540,l,1200,1205
644 }
645 h2->highest_stream = h2->rxf_stream;
646 r2 = h2_new_req(wrk, h2, h2->rxf_stream, NULL);
647 }
648 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
649
650 if (r2->state != H2_S_IDLE)
651 return (H2CE_PROTOCOL_ERROR); // XXX spec ?
652 r2->state = H2_S_OPEN;
653
654 req = r2->req;
655 CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
656
657 req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER);
658 VSLb(req->vsl, SLT_Begin, "req %u rxreq", VXID(req->sp->vxid));
659 VSL(SLT_Link, req->sp->vxid, "req %u rxreq", VXID(req->vsl->wid));
660
661 h2->new_req = req;
662 req->sp = h2->sess;
663 req->transport = &H2_transport;
664
665 req->t_first = VTIM_real();
666 req->t_req = VTIM_real();
667 req->t_prev = req->t_first;
668 VSLb_ts_req(req, "Start", req->t_first);
669 req->acct.req_hdrbytes += h2->rxf_len;
670
671 HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
672 http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
673
674 h2h_decode_init(h2);
675
676 p = h2->rxf_data;
677 l = h2->rxf_len;
678 if (h2->rxf_flags & H2FF_HEADERS_PADDED) {
679 if (*p + 1 > l)
680 return (H2CE_PROTOCOL_ERROR); // rfc7540,l,1884,1887
681 l -= 1 + *p;
682 p += 1;
683 }
684 if (h2->rxf_flags & H2FF_HEADERS_PRIORITY) {
685 if (l < 5)
686 return (H2CE_PROTOCOL_ERROR);
687 l -= 5;
688 p += 5;
689 }
690 h2e = h2h_decode_bytes(h2, p, l);
691 if (h2e != NULL) {
692 Lck_Lock(&h2->sess->mtx);
693 VSLb(h2->vsl, SLT_Debug, "HPACK(hdr) %s", h2e->name);
694 Lck_Unlock(&h2->sess->mtx);
695 (void)h2h_decode_fini(h2);
696 assert(!WS_IsReserved(r2->req->ws));
697 h2_del_req(wrk, r2);
698 return (h2e);
699 }
700
701 if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
702 req->req_body_status = BS_NONE;
703
704 if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
705 return (h2_end_headers(wrk, h2, req, r2));
706 return (0);
707 }
708
709 /**********************************************************************/
710
v_matchproto_(h2_rxframe_f)711 static h2_error v_matchproto_(h2_rxframe_f)
712 h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
713 {
714 struct req *req;
715 h2_error h2e;
716
717 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
718 ASSERT_RXTHR(h2);
719 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
720
721 if (r2 == NULL || r2->state != H2_S_OPEN || r2->req != h2->new_req)
722 return (H2CE_PROTOCOL_ERROR); // XXX spec ?
723 req = r2->req;
724 h2e = h2h_decode_bytes(h2, h2->rxf_data, h2->rxf_len);
725 r2->req->acct.req_hdrbytes += h2->rxf_len;
726 if (h2e != NULL) {
727 Lck_Lock(&h2->sess->mtx);
728 VSLb(h2->vsl, SLT_Debug, "HPACK(cont) %s", h2e->name);
729 Lck_Unlock(&h2->sess->mtx);
730 (void)h2h_decode_fini(h2);
731 assert(!WS_IsReserved(r2->req->ws));
732 h2_del_req(wrk, r2);
733 return (h2e);
734 }
735 if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
736 return (h2_end_headers(wrk, h2, req, r2));
737 return (0);
738 }
739
740 /**********************************************************************/
741
v_matchproto_(h2_rxframe_f)742 static h2_error v_matchproto_(h2_rxframe_f)
743 h2_rx_data(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
744 {
745 int w1 = 0, w2 = 0;
746 char buf[4];
747 unsigned wi;
748 ssize_t cl;
749
750 CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
751 ASSERT_RXTHR(h2);
752 CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
753
754 if (r2 == NULL || !r2->scheduled)
755 return (0);
756 if (r2->state >= H2_S_CLOS_REM) {
757 r2->error = H2SE_STREAM_CLOSED;
758 return (H2SE_STREAM_CLOSED); // rfc7540,l,1766,1769
759 }
760 Lck_Lock(&h2->sess->mtx);
761 while (h2->mailcall != NULL && h2->error == 0 && r2->error == 0)
762 AZ(Lck_CondWait(h2->cond, &h2->sess->mtx, 0));
763 if (h2->error || r2->error) {
764 Lck_Unlock(&h2->sess->mtx);
765 return (h2->error ? h2->error : r2->error);
766 }
767
768 r2->reqbody_bytes += h2->rxf_len;
769 if (h2->rxf_flags & H2FF_DATA_END_STREAM)
770 r2->state = H2_S_CLOS_REM;
771 cl = r2->req->htc->content_length;
772 if (cl >= 0 && (r2->reqbody_bytes > cl ||
773 (r2->state >= H2_S_CLOS_REM && r2->reqbody_bytes != cl))) {
774 VSLb(h2->vsl, SLT_Debug,
775 "H2: stream %u: Received data and Content-Length"
776 " mismatch", h2->rxf_stream);
777 r2->error = H2SE_PROTOCOL_ERROR; // rfc7540,l,3150,3163
778 if (r2->cond)
779 AZ(pthread_cond_signal(r2->cond));
780 Lck_Unlock(&h2->sess->mtx);
781 return (H2SE_PROTOCOL_ERROR);
782 }
783
784 AZ(h2->mailcall);
785 h2->mailcall = r2;
786 h2->req0->r_window -= h2->rxf_len;
787 r2->r_window -= h2->rxf_len;
788 // req_bodybytes accounted in CNT code.
789 if (r2->cond)
790 AZ(pthread_cond_signal(r2->cond));
791 while (h2->mailcall != NULL && h2->error == 0 && r2->error == 0)
792 AZ(Lck_CondWait(h2->cond, &h2->sess->mtx, 0));
793 wi = cache_param->h2_rx_window_increment;
794 if (h2->req0->r_window < cache_param->h2_rx_window_low_water) {
795 h2->req0->r_window += wi;
796 w1 = 1;
797 }
798 if (r2->r_window < cache_param->h2_rx_window_low_water) {
799 r2->r_window += wi;
800 w2 = 1;
801 }
802
803
804 Lck_Unlock(&h2->sess->mtx);
805
806 if (w1 || w2) {
807 vbe32enc(buf, wi);
808 H2_Send_Get(wrk, h2, h2->req0);
809 if (w1)
810 H2_Send_Frame(wrk, h2, H2_F_WINDOW_UPDATE, 0,
811 4, 0, buf);
812 if (w2)
813 H2_Send_Frame(wrk, h2, H2_F_WINDOW_UPDATE, 0,
814 4, r2->stream, buf);
815 H2_Send_Rel(h2, h2->req0);
816 }
817 return (0);
818 }
819
v_matchproto_(vfp_pull_f)820 static enum vfp_status v_matchproto_(vfp_pull_f)
821 h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
822 {
823 struct h2_req *r2;
824 struct h2_sess *h2;
825 unsigned l;
826 enum vfp_status retval;
827
828 CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
829 CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
830 CAST_OBJ_NOTNULL(r2, vfe->priv1, H2_REQ_MAGIC);
831 h2 = r2->h2sess;
832
833 AN(ptr);
834 AN(lp);
835 l = *lp;
836 *lp = 0;
837
838 Lck_Lock(&h2->sess->mtx);
839 r2->cond = &vc->wrk->cond;
840 while (h2->mailcall != r2 && h2->error == 0 && r2->error == 0)
841 AZ(Lck_CondWait(r2->cond, &h2->sess->mtx, 0));
842 r2->cond = NULL;
843 if (h2->error || r2->error) {
844 retval = VFP_ERROR;
845 } else {
846 assert(h2->mailcall == r2);
847 if (l > h2->rxf_len)
848 l = h2->rxf_len;
849 if (l > 0) {
850 memcpy(ptr, h2->rxf_data, l);
851 h2->rxf_data += l;
852 h2->rxf_len -= l;
853 }
854 *lp = l;
855 if (h2->rxf_len > 0) {
856 /* We ran out of storage: Have VFP call us
857 * again with a fresh buffer */
858 Lck_Unlock(&h2->sess->mtx);
859 return (VFP_OK);
860 }
861 if (h2->rxf_len == 0 && r2->state >= H2_S_CLOS_REM)
862 retval = VFP_END;
863 else
864 retval = VFP_OK;
865 h2->mailcall = NULL;
866 AZ(pthread_cond_signal(h2->cond));
867 }
868 Lck_Unlock(&h2->sess->mtx);
869 return (retval);
870 }
871
872 static void
h2_vfp_body_fini(struct vfp_ctx * vc,struct vfp_entry * vfe)873 h2_vfp_body_fini(struct vfp_ctx *vc, struct vfp_entry *vfe)
874 {
875 struct h2_req *r2;
876 struct h2_sess *h2;
877
878 CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
879 CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
880 CAST_OBJ_NOTNULL(r2, vfe->priv1, H2_REQ_MAGIC);
881 CHECK_OBJ_NOTNULL(r2->req, REQ_MAGIC);
882 h2 = r2->h2sess;
883
884 if (vc->failed) {
885 CHECK_OBJ_NOTNULL(r2->req->wrk, WORKER_MAGIC);
886 H2_Send_Get(r2->req->wrk, h2, r2);
887 H2_Send_RST(r2->req->wrk, h2, r2, r2->stream,
888 H2SE_REFUSED_STREAM);
889 H2_Send_Rel(h2, r2);
890 Lck_Lock(&h2->sess->mtx);
891 r2->error = H2SE_REFUSED_STREAM;
892 if (h2->mailcall == r2) {
893 h2->mailcall = NULL;
894 AZ(pthread_cond_signal(h2->cond));
895 }
896 Lck_Unlock(&h2->sess->mtx);
897 }
898 }
899
900 static const struct vfp h2_body = {
901 .name = "H2_BODY",
902 .pull = h2_vfp_body,
903 .fini = h2_vfp_body_fini
904 };
905
v_matchproto_(vtr_req_body_t)906 void v_matchproto_(vtr_req_body_t)
907 h2_req_body(struct req *req)
908 {
909 struct h2_req *r2;
910 struct vfp_entry *vfe;
911
912 CHECK_OBJ(req, REQ_MAGIC);
913 CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
914 vfe = VFP_Push(req->vfc, &h2_body);
915 AN(vfe);
916 vfe->priv1 = r2;
917 }
918
919 /**********************************************************************/
920
v_matchproto_(vtr_req_fail_f)921 void v_matchproto_(vtr_req_fail_f)
922 h2_req_fail(struct req *req, enum sess_close reason)
923 {
924 assert(reason > 0);
925 assert(req->sp->fd != 0);
926 VSLb(req->vsl, SLT_Debug, "H2FAILREQ");
927 }
928
929 /**********************************************************************/
930
v_matchproto_(htc_complete_f)931 static enum htc_status_e v_matchproto_(htc_complete_f)
932 h2_frame_complete(struct http_conn *htc)
933 {
934 struct h2_sess *h2;
935
936 CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
937 CAST_OBJ_NOTNULL(h2, htc->priv, H2_SESS_MAGIC);
938 if (htc->rxbuf_b + 9 > htc->rxbuf_e ||
939 htc->rxbuf_b + 9 + (vbe32dec(htc->rxbuf_b) >> 8) > htc->rxbuf_e)
940 return (HTC_S_MORE);
941 return (HTC_S_COMPLETE);
942 }
943
944 /**********************************************************************/
945
946 static h2_error
h2_procframe(struct worker * wrk,struct h2_sess * h2,h2_frame h2f)947 h2_procframe(struct worker *wrk, struct h2_sess *h2, h2_frame h2f)
948 {
949 struct h2_req *r2;
950 h2_error h2e;
951
952 ASSERT_RXTHR(h2);
953 if (h2->rxf_stream == 0 && h2f->act_szero != 0)
954 return (h2f->act_szero);
955
956 if (h2->rxf_stream != 0 && h2f->act_snonzero != 0)
957 return (h2f->act_snonzero);
958
959 if (h2->rxf_stream > h2->highest_stream && h2f->act_sidle != 0)
960 return (h2f->act_sidle);
961
962 if (h2->rxf_stream != 0 && !(h2->rxf_stream & 1)) {
963 // rfc7540,l,1140,1145
964 // rfc7540,l,1153,1158
965 /* No even streams, we don't do PUSH_PROMISE */
966 Lck_Lock(&h2->sess->mtx);
967 VSLb(h2->vsl, SLT_Debug, "H2: illegal stream (=%u)",
968 h2->rxf_stream);
969 Lck_Unlock(&h2->sess->mtx);
970 return (H2CE_PROTOCOL_ERROR);
971 }
972
973 VTAILQ_FOREACH(r2, &h2->streams, list)
974 if (r2->stream == h2->rxf_stream)
975 break;
976
977 if (h2->new_req != NULL &&
978 !(r2 && h2->new_req == r2->req && h2f == H2_F_CONTINUATION))
979 return (H2CE_PROTOCOL_ERROR); // rfc7540,l,1859,1863
980
981 h2e = h2f->rxfunc(wrk, h2, r2);
982 if (h2e == 0)
983 return (0);
984 if (h2->rxf_stream == 0 || h2e->connection)
985 return (h2e); // Connection errors one level up
986
987 H2_Send_Get(wrk, h2, h2->req0);
988 H2_Send_RST(wrk, h2, h2->req0, h2->rxf_stream, h2e);
989 H2_Send_Rel(h2, h2->req0);
990 return (0);
991 }
992
993 int
h2_stream_tmo(struct h2_sess * h2,const struct h2_req * r2,vtim_real now)994 h2_stream_tmo(struct h2_sess *h2, const struct h2_req *r2, vtim_real now)
995 {
996 int r = 0;
997
998 CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
999 CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
1000 Lck_AssertHeld(&h2->sess->mtx);
1001
1002 /* NB: when now is NAN, it means that idle_send_timeout was hit
1003 * on a lock condwait operation.
1004 */
1005 if (isnan(now))
1006 AN(r2->t_winupd);
1007
1008 if (r2->t_winupd == 0 && r2->t_send == 0)
1009 return (0);
1010
1011 if (isnan(now) || (r2->t_winupd != 0 &&
1012 now - r2->t_winupd > SESS_TMO(h2->sess, idle_send_timeout))) {
1013 VSLb(h2->vsl, SLT_Debug,
1014 "H2: stream %u: Hit idle_send_timeout waiting for"
1015 " WINDOW_UPDATE", r2->stream);
1016 r = 1;
1017 }
1018
1019 if (r == 0 && r2->t_send != 0 &&
1020 now - r2->t_send > SESS_TMO(h2->sess, send_timeout)) {
1021 VSLb(h2->vsl, SLT_Debug,
1022 "H2: stream %u: Hit send_timeout", r2->stream);
1023 r = 1;
1024 }
1025
1026 return (r);
1027 }
1028
1029 static int
h2_stream_tmo_unlocked(struct h2_sess * h2,const struct h2_req * r2)1030 h2_stream_tmo_unlocked(struct h2_sess *h2, const struct h2_req *r2)
1031 {
1032 int r;
1033
1034 Lck_Lock(&h2->sess->mtx);
1035 r = h2_stream_tmo(h2, r2, h2->sess->t_idle);
1036 Lck_Unlock(&h2->sess->mtx);
1037
1038 return (r);
1039 }
1040
1041 /*
1042 * This is the janitorial task of cleaning up any closed & refused
1043 * streams, and checking if the session is timed out.
1044 */
1045 static int
h2_sweep(struct worker * wrk,struct h2_sess * h2)1046 h2_sweep(struct worker *wrk, struct h2_sess *h2)
1047 {
1048 int tmo = 0;
1049 struct h2_req *r2, *r22;
1050
1051 ASSERT_RXTHR(h2);
1052
1053 h2->do_sweep = 0;
1054 VTAILQ_FOREACH_SAFE(r2, &h2->streams, list, r22) {
1055 if (r2 == h2->req0) {
1056 assert (r2->state == H2_S_IDLE);
1057 continue;
1058 }
1059 switch (r2->state) {
1060 case H2_S_CLOSED:
1061 if (!r2->scheduled)
1062 h2_del_req(wrk, r2);
1063 break;
1064 case H2_S_CLOS_REM:
1065 if (!r2->scheduled) {
1066 H2_Send_Get(wrk, h2, h2->req0);
1067 H2_Send_RST(wrk, h2, h2->req0, r2->stream,
1068 H2SE_REFUSED_STREAM);
1069 H2_Send_Rel(h2, h2->req0);
1070 h2_del_req(wrk, r2);
1071 continue;
1072 }
1073 /* FALLTHROUGH */
1074 case H2_S_CLOS_LOC:
1075 case H2_S_OPEN:
1076 if (h2_stream_tmo_unlocked(h2, r2)) {
1077 tmo = 1;
1078 continue;
1079 }
1080 break;
1081 case H2_S_IDLE:
1082 /* Current code make this unreachable: h2_new_req is
1083 * only called inside h2_rx_headers, which immediately
1084 * sets the new stream state to H2_S_OPEN */
1085 /* FALLTHROUGH */
1086 default:
1087 WRONG("Wrong h2 stream state");
1088 break;
1089 }
1090 }
1091 if (tmo)
1092 return (0);
1093 return (h2->refcnt > 1);
1094 }
1095
1096
1097 /***********************************************************************
1098 * Called in loop from h2_new_session()
1099 */
1100
1101 #define H2_FRAME(l,U,...) const struct h2_frame_s H2_F_##U[1] = \
1102 {{ #U, h2_rx_##l, __VA_ARGS__ }};
1103 #include "tbl/h2_frames.h"
1104
1105 static const h2_frame h2flist[] = {
1106 #define H2_FRAME(l,U,t,...) [t] = H2_F_##U,
1107 #include "tbl/h2_frames.h"
1108 };
1109
1110 #define H2FMAX (sizeof(h2flist) / sizeof(h2flist[0]))
1111
1112 int
h2_rxframe(struct worker * wrk,struct h2_sess * h2)1113 h2_rxframe(struct worker *wrk, struct h2_sess *h2)
1114 {
1115 enum htc_status_e hs;
1116 h2_frame h2f;
1117 h2_error h2e;
1118 char b[8];
1119
1120 ASSERT_RXTHR(h2);
1121 VTCP_blocking(*h2->htc->rfd);
1122 h2->sess->t_idle = VTIM_real();
1123 hs = HTC_RxStuff(h2->htc, h2_frame_complete,
1124 NULL, NULL, NAN,
1125 h2->sess->t_idle + SESS_TMO(h2->sess, timeout_idle),
1126 NAN, h2->local_settings.max_frame_size + 9);
1127 switch (hs) {
1128 case HTC_S_COMPLETE:
1129 break;
1130 case HTC_S_TIMEOUT:
1131 if (h2_sweep(wrk, h2))
1132 return (1);
1133
1134 /* FALLTHROUGH */
1135 default:
1136 /* XXX: HTC_S_OVERFLOW / FRAME_SIZE_ERROR handling */
1137 Lck_Lock(&h2->sess->mtx);
1138 VSLb(h2->vsl, SLT_Debug, "H2: No frame (hs=%d)", hs);
1139 h2->error = H2CE_NO_ERROR;
1140 Lck_Unlock(&h2->sess->mtx);
1141 return (0);
1142 }
1143
1144 if (h2->do_sweep)
1145 (void)h2_sweep(wrk, h2);
1146
1147 h2->rxf_len = vbe32dec(h2->htc->rxbuf_b) >> 8;
1148 h2->rxf_type = h2->htc->rxbuf_b[3];
1149 h2->rxf_flags = h2->htc->rxbuf_b[4];
1150 h2->rxf_stream = vbe32dec(h2->htc->rxbuf_b + 5);
1151 h2->rxf_stream &= ~(1LU<<31); // rfc7540,l,690,692
1152 h2->rxf_data = (void*)(h2->htc->rxbuf_b + 9);
1153 /* XXX: later full DATA will not be rx'ed yet. */
1154 HTC_RxPipeline(h2->htc, h2->htc->rxbuf_b + h2->rxf_len + 9);
1155
1156 h2_vsl_frame(h2, h2->htc->rxbuf_b, 9L + h2->rxf_len);
1157 h2->srq->acct.req_hdrbytes += 9;
1158
1159 if (h2->rxf_type >= H2FMAX) {
1160 // rfc7540,l,679,681
1161 // XXX: later, drain rest of frame
1162 h2->bogosity++;
1163 Lck_Lock(&h2->sess->mtx);
1164 VSLb(h2->vsl, SLT_Debug,
1165 "H2: Unknown frame type 0x%02x (ignored)",
1166 (uint8_t)h2->rxf_type);
1167 Lck_Unlock(&h2->sess->mtx);
1168 h2->srq->acct.req_bodybytes += h2->rxf_len;
1169 return (1);
1170 }
1171 h2f = h2flist[h2->rxf_type];
1172
1173 AN(h2f->name);
1174 AN(h2f->rxfunc);
1175 if (h2f->overhead)
1176 h2->srq->acct.req_bodybytes += h2->rxf_len;
1177
1178 if (h2->rxf_flags & ~h2f->flags) {
1179 // rfc7540,l,687,688
1180 h2->bogosity++;
1181 Lck_Lock(&h2->sess->mtx);
1182 VSLb(h2->vsl, SLT_Debug,
1183 "H2: Unknown flags 0x%02x on %s (ignored)",
1184 (uint8_t)h2->rxf_flags & ~h2f->flags, h2f->name);
1185 Lck_Unlock(&h2->sess->mtx);
1186 h2->rxf_flags &= h2f->flags;
1187 }
1188
1189 h2e = h2_procframe(wrk, h2, h2f);
1190 if (h2->error == 0 && h2e) {
1191 h2->error = h2e;
1192 vbe32enc(b, h2->highest_stream);
1193 vbe32enc(b + 4, h2e->val);
1194 H2_Send_Get(wrk, h2, h2->req0);
1195 H2_Send_Frame(wrk, h2, H2_F_GOAWAY, 0, 8, 0, b);
1196 H2_Send_Rel(h2, h2->req0);
1197 }
1198 return (h2->error ? 0 : 1);
1199 }
1200