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