vinyl-cache/bin/vinyld/http2/cache_http2_proto.c
0
/*-
1
 * Copyright (c) 2016-2019 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 */
30
31
#include "config.h"
32
33
#include "cache/cache_int.h"
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
38
#include "cache/cache_transport.h"
39
#include "cache/cache_filter.h"
40
#include "http2/cache_http2.h"
41
#include "cache/cache_objhead.h"
42
#include "storage/storage.h"
43
44
#include "vend.h"
45
#include "vtcp.h"
46
#include "vtim.h"
47
48
#define H2_CUSTOM_ERRORS
49
#define H2EC1(U,v,g,r,d)        \
50
        const struct h2_error_s H2CE_##U[1] = {{"H2CE_" #U,d,v,0,1,g,r}};
51
#define H2EC2(U,v,g,r,d)        \
52
        const struct h2_error_s H2SE_##U[1] = {{"H2SE_" #U,d,v,1,0,g,r}};
53
#define H2EC3(U,v,g,r,d) H2EC1(U,v,g,r,d) H2EC2(U,v,g,r,d)
54
#define H2_ERROR(NAME, val, sc, goaway, reason, desc)   \
55
        H2EC##sc(NAME, val, goaway, reason, desc)
56
#include "tbl/h2_error.h"
57
#undef H2EC1
58
#undef H2EC2
59
#undef H2EC3
60
61
static const struct h2_error_s H2NN_ERROR[1] = {{
62
        "UNKNOWN_ERROR",
63
        "Unknown error number",
64
        0xffffffff,
65
        1,
66
        1,
67
        0,
68
        SC_RX_JUNK
69
}};
70
71
enum h2frame {
72
#define H2_FRAME(l,u,t,f,...)   H2F_##u = t,
73
#include "tbl/h2_frames.h"
74
};
75
76
static const char *
77 18459
h2_framename(enum h2frame h2f)
78
{
79
80 18459
        switch (h2f) {
81
#define H2_FRAME(l,u,t,f,...)   case H2F_##u: return (#u);
82
#include "tbl/h2_frames.h"
83
        default:
84
                return (NULL);
85
        }
86 18459
}
87
88
#define H2_FRAME_FLAGS(l,u,v)   const uint8_t H2FF_##u = v;
89
#include "tbl/h2_frames.h"
90
91
/**********************************************************************
92
 */
93
94
static const h2_error stream_errors[] = {
95
#define H2EC1(U,v,g,r,d)
96
#define H2EC2(U,v,g,r,d) [v] = H2SE_##U,
97
#define H2EC3(U,v,g,r,d) H2EC1(U,v,g,r,d) H2EC2(U,v,g,r,d)
98
#define H2_ERROR(NAME, val, sc, goaway, reason, desc)   \
99
        H2EC##sc(NAME, val, goaway, reason, desc)
100
#include "tbl/h2_error.h"
101
#undef H2EC1
102
#undef H2EC2
103
#undef H2EC3
104
};
105
106
#define NSTREAMERRORS vcountof(stream_errors)
107
108
static h2_error
109 315
h2_streamerror(uint32_t u)
110
{
111 315
        if (u < NSTREAMERRORS && stream_errors[u] != NULL)
112 273
                return (stream_errors[u]);
113
        else
114 42
                return (H2NN_ERROR);
115 315
}
116
117
/**********************************************************************
118
 */
119
120
static const h2_error conn_errors[] = {
121
#define H2EC1(U,v,g,r,d) [v] = H2CE_##U,
122
#define H2EC2(U,v,g,r,d)
123
#define H2EC3(U,v,g,r,d) H2EC1(U,v,g,r,d) H2EC2(U,v,g,r,d)
124
#define H2_ERROR(NAME, val, sc, goaway, reason, desc)   \
125
        H2EC##sc(NAME, val, goaway, reason, desc)
126
#include "tbl/h2_error.h"
127
#undef H2EC1
128
#undef H2EC2
129
#undef H2EC3
130
};
131
132
#define NCONNERRORS vcountof(conn_errors)
133
134
static h2_error
135 63
h2_connectionerror(uint32_t u)
136
{
137 63
        if (u < NCONNERRORS && conn_errors[u] != NULL)
138 42
                return (conn_errors[u]);
139
        else
140 21
                return (H2NN_ERROR);
141 63
}
142
143
/**********************************************************************/
144
145
struct h2_req *
146 7329
h2_new_req(struct h2_sess *h2, unsigned stream, struct req *req)
147
{
148
        struct h2_req *r2;
149
150 7329
        ASSERT_RXTHR(h2);
151 7329
        if (req == NULL)
152 7224
                req = Req_New(h2->sess, NULL);
153 7329
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
154
155 7329
        req->http0->protover = 20;
156
157 7329
        r2 = WS_Alloc(req->ws, sizeof *r2);
158 7329
        AN(r2);
159 7329
        INIT_OBJ(r2, H2_REQ_MAGIC);
160 7329
        r2->state = H2_S_IDLE;
161 7329
        r2->h2sess = h2;
162 7329
        r2->stream = stream;
163 7329
        r2->req = req;
164 7329
        if (stream)
165 4074
                r2->counted = 1;
166 7329
        r2->r_window = h2->local_settings.initial_window_size;
167 7329
        r2->t_window = h2->remote_settings.initial_window_size;
168 7329
        req->transport_priv = r2;
169 7329
        Lck_Lock(&h2->sess->mtx);
170 7329
        if (stream)
171 4074
                h2->open_streams++;
172 7329
        VTAILQ_INSERT_TAIL(&h2->streams, r2, list);
173 7329
        Lck_Unlock(&h2->sess->mtx);
174 7329
        h2->refcnt++;
175 7329
        return (r2);
176
}
177
178
void
179 7287
h2_del_req(struct worker *wrk, struct h2_req *r2)
180
{
181
        struct h2_sess *h2;
182
        struct sess *sp;
183
        struct stv_buffer *stvbuf;
184
185 7287
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
186 7287
        AZ(r2->scheduled);
187 7287
        h2 = r2->h2sess;
188 7287
        CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
189 7287
        ASSERT_RXTHR(h2);
190 7287
        sp = h2->sess;
191 7287
        Lck_Lock(&sp->mtx);
192 7287
        assert(h2->refcnt > 0);
193 7287
        --h2->refcnt;
194
        /* XXX: PRIORITY reshuffle */
195 7287
        VTAILQ_REMOVE(&h2->streams, r2, list);
196 7287
        if (r2->req == h2->new_req)
197 861
                h2->new_req = NULL;
198 7287
        Lck_Unlock(&sp->mtx);
199
200 7287
        assert(!WS_IsReserved(r2->req->ws));
201 7287
        AZ(r2->req->ws->r);
202
203 7287
        CHECK_OBJ_ORNULL(r2->rxbuf, H2_RXBUF_MAGIC);
204 7287
        if (r2->rxbuf) {
205 84
                stvbuf = r2->rxbuf->stvbuf;
206 84
                r2->rxbuf = NULL;
207 84
                STV_FreeBuf(wrk, &stvbuf);
208 84
                AZ(stvbuf);
209 84
        }
210
211 7287
        Req_Cleanup(sp, wrk, r2->req);
212 7287
        if (FEATURE(FEATURE_BUSY_STATS_RATE))
213 0
                WRK_AddStat(wrk);
214 7287
        Req_Release(r2->req);
215 7287
}
216
217
void
218 3653
h2_kill_req(struct worker *wrk, struct h2_sess *h2,
219
    struct h2_req *r2, h2_error h2e)
220
{
221
222 3653
        ASSERT_RXTHR(h2);
223 3653
        AN(h2e);
224 3653
        Lck_Lock(&h2->sess->mtx);
225 7306
        VSLb(h2->vsl, SLT_Debug, "KILL st=%u state=%d sched=%d",
226 3653
            r2->stream, r2->state, r2->scheduled);
227 3653
        if (r2->counted) {
228 943
                assert(h2->open_streams > 0);
229 943
                h2->open_streams--;
230 943
                r2->counted = 0;
231 943
        }
232 3653
        if (r2->error == NULL)
233 315
                r2->error = h2e;
234 3653
        if (r2->scheduled) {
235 1301
                if (r2->cond != NULL)
236 127
                        PTOK(pthread_cond_signal(r2->cond));
237 1301
                r2 = NULL;
238 1301
                Lck_Unlock(&h2->sess->mtx);
239 1301
        } else {
240 2352
                Lck_Unlock(&h2->sess->mtx);
241 2352
                if (r2->state == H2_S_OPEN && h2->new_req == r2->req)
242 105
                        (void)h2h_decode_hdr_fini(h2);
243
        }
244 3653
        if (r2 != NULL)
245 2352
                h2_del_req(wrk, r2);
246 3653
}
247
248
/**********************************************************************/
249
250
static void
251 18774
h2_vsl_frame(const struct h2_sess *h2, const void *ptr, size_t len)
252
{
253
        const uint8_t *b;
254
        struct vsb *vsb;
255
        const char *p;
256
        unsigned u;
257
258 18774
        if (VSL_tag_is_masked(SLT_H2RxHdr) &&
259 315
            VSL_tag_is_masked(SLT_H2RxBody))
260 315
                return;
261
262 18459
        AN(ptr);
263 18459
        assert(len >= 9);
264 18459
        b = ptr;
265
266 18459
        vsb = VSB_new_auto();
267 18459
        AN(vsb);
268 18459
        p = h2_framename((enum h2frame)b[3]);
269 18459
        if (p != NULL)
270 18438
                VSB_cat(vsb, p);
271
        else
272 21
                VSB_quote(vsb, b + 3, 1, VSB_QUOTE_HEX);
273
274 18459
        u = vbe32dec(b) >> 8;
275 18459
        VSB_printf(vsb, "[%u] ", u);
276 18459
        VSB_quote(vsb, b + 4, 1, VSB_QUOTE_HEX);
277 18459
        VSB_putc(vsb, ' ');
278 18459
        VSB_quote(vsb, b + 5, 4, VSB_QUOTE_HEX);
279 18459
        if (u > 0) {
280 12369
                VSB_putc(vsb, ' ');
281 12369
                VSB_quote(vsb, b + 9, len - 9, VSB_QUOTE_HEX);
282 12369
        }
283 18459
        AZ(VSB_finish(vsb));
284 18459
        Lck_Lock(&h2->sess->mtx);
285 18459
        VSLb_bin(h2->vsl, SLT_H2RxHdr, 9, b);
286 18459
        if (len > 9)
287 12369
                VSLb_bin(h2->vsl, SLT_H2RxBody, len - 9, b + 9);
288
289 18459
        VSLb(h2->vsl, SLT_Debug, "H2RXF %s", VSB_data(vsb));
290 18459
        Lck_Unlock(&h2->sess->mtx);
291 18459
        VSB_destroy(&vsb);
292 18774
}
293
294
295
/**********************************************************************
296
 */
297
298
static h2_error v_matchproto_(h2_rxframe_f)
299 126
h2_rx_ping(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
300
{
301
302 126
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
303 126
        ASSERT_RXTHR(h2);
304 126
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
305 126
        assert(r2 == h2->req0);
306
307 126
        if (h2->rxf_len != 8) {                         // rfc7540,l,2364,2366
308 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx ping with (len != 8)");
309 21
                return (H2CE_FRAME_SIZE_ERROR);
310
        }
311 105
        AZ(h2->rxf_stream);                             // rfc7540,l,2359,2362
312 105
        if (h2->rxf_flags != 0) {                       // We never send pings
313 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx ping ack");
314 21
                return (H2SE_PROTOCOL_ERROR);
315
        }
316 84
        H2_Send_Get(wrk, h2, r2);
317 168
        H2_Send_Frame(wrk, h2,
318 84
            H2_F_PING, H2FF_PING_ACK, 8, 0, h2->rxf_data);
319 84
        H2_Send_Rel(h2, r2);
320 84
        return (0);
321 126
}
322
323
/**********************************************************************
324
 */
325
326
static h2_error v_matchproto_(h2_rxframe_f)
327 42
h2_rx_push_promise(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
328
{
329
330 42
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
331 42
        ASSERT_RXTHR(h2);
332 42
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
333
334
        // rfc7540,l,2262,2267
335 42
        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx push promise");
336 42
        return (H2CE_PROTOCOL_ERROR);
337
}
338
339
/**********************************************************************
340
 */
341
342
int
343 1703
h2_rapid_reset_check(struct worker *wrk, struct h2_sess *h2,
344
    const struct h2_req *r2)
345
{
346
        vtim_real now;
347
348 1703
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
349 1703
        CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
350 1703
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
351
352 1703
        if (h2->rapid_reset_limit == 0)
353 0
                return (0);
354
355 1703
        now = VTIM_real();
356 1703
        CHECK_OBJ_NOTNULL(r2->req, REQ_MAGIC);
357 1703
        AN(r2->req->t_first);
358 1703
        if (now - r2->req->t_first > h2->rapid_reset)
359 170
                return (0);
360
361 1533
        return (1);
362 1703
}
363
364
h2_error
365 1533
h2_rapid_reset_charge(struct worker *wrk, struct h2_sess *h2,
366
    const struct h2_req *r2)
367
{
368
        vtim_real now;
369
        vtim_dur d;
370 1533
        h2_error h2e = NULL;
371
372 1533
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
373 1533
        AN(H2_SEND_HELD(h2, r2));
374 1533
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
375
376 1533
        now = VTIM_real();
377
378 1533
        d = now - h2->last_rst;
379 3066
        h2->rst_budget += h2->rapid_reset_limit * d /
380 1533
            h2->rapid_reset_period;
381 1533
        h2->rst_budget = vmin_t(double, h2->rst_budget,
382
            h2->rapid_reset_limit);
383 1533
        h2->last_rst = now;
384
385 1533
        h2->rst_budget -= 1.0;
386
387 1533
        if (h2->rst_budget < 0) {
388 63
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: Hit RST limit. Closing session.");
389 63
                h2e = H2CE_RAPID_RESET;
390 63
                H2_Send_GOAWAY(wrk, h2, r2, h2e);
391 63
        }
392
393 1533
        return (h2e);
394
}
395
396
static h2_error v_matchproto_(h2_rxframe_f)
397 399
h2_rx_rst_stream(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
398
{
399 399
        h2_error h2e = NULL;
400
401 399
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
402 399
        ASSERT_RXTHR(h2);
403 399
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
404
405 399
        if (h2->rxf_len != 4) {                 // rfc7540,l,2003,2004
406 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx rst with (len != 4)");
407 21
                return (H2CE_FRAME_SIZE_ERROR);
408
        }
409 378
        if (r2 == NULL)
410 63
                return (0);
411 315
        if (h2_rapid_reset_check(wrk, h2, r2)) {
412 273
                H2_Send_Get(wrk, h2, h2->req0);
413 273
                h2e = h2_rapid_reset_charge(wrk, h2, h2->req0);
414 273
                H2_Send_Rel(h2, h2->req0);
415 273
        }
416 315
        h2_kill_req(wrk, h2, r2, h2_streamerror(vbe32dec(h2->rxf_data)));
417 315
        return (h2e);
418 399
}
419
420
/**********************************************************************
421
 */
422
423
static h2_error v_matchproto_(h2_rxframe_f)
424 63
h2_rx_goaway(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
425
{
426
427 63
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
428 63
        ASSERT_RXTHR(h2);
429 63
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
430 63
        assert(r2 == h2->req0);
431
432 63
        h2->goaway = 1;
433 63
        h2->goaway_last_stream = vbe32dec(h2->rxf_data);
434 63
        h2->error = h2_connectionerror(vbe32dec(h2->rxf_data + 4));
435 63
        H2S_Lock_VSLb(h2, SLT_Debug, "GOAWAY %s", h2->error->name);
436 63
        return (h2->error);
437
}
438
439
static void
440 3066
h2_tx_goaway(struct worker *wrk, struct h2_sess *h2, h2_error h2e)
441
{
442 3066
        ASSERT_RXTHR(h2);
443 3066
        AN(h2e);
444
445 3066
        if (h2->goaway || !h2e->send_goaway)
446 42
                return;
447
448 3024
        H2_Send_Get(wrk, h2, h2->req0);
449 3024
        H2_Send_GOAWAY(wrk, h2, h2->req0, h2e);
450 3024
        H2_Send_Rel(h2, h2->req0);
451 3066
}
452
453
/**********************************************************************
454
 */
455
456
static h2_error v_matchproto_(h2_rxframe_f)
457 546
h2_rx_window_update(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
458
{
459
        uint32_t wu;
460
461 546
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
462 546
        ASSERT_RXTHR(h2);
463 546
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
464
465 546
        if (h2->rxf_len != 4) {
466 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx winup with (len != 4)");
467 21
                return (H2CE_FRAME_SIZE_ERROR);
468
        }
469 525
        wu = vbe32dec(h2->rxf_data) & ~(1LU<<31);
470 525
        if (wu == 0)
471 105
                return (H2SE_PROTOCOL_ERROR);
472 420
        if (r2 == NULL)
473 21
                return (0);
474 399
        Lck_Lock(&h2->sess->mtx);
475 399
        r2->t_window += wu;
476 399
        if (r2 == h2->req0)
477 168
                PTOK(pthread_cond_broadcast(h2->winupd_cond));
478 231
        else if (r2->cond != NULL)
479 168
                PTOK(pthread_cond_signal(r2->cond));
480 399
        Lck_Unlock(&h2->sess->mtx);
481 399
        if (r2->t_window >= (1LL << 31))
482 42
                return (H2SE_FLOW_CONTROL_ERROR);
483 357
        return (0);
484 546
}
485
486
/**********************************************************************
487
 * Incoming PRIORITY, possibly an ACK of one we sent.
488
 *
489
 * deprecated, rfc9113,l,1103,1104
490
 */
491
492
static h2_error v_matchproto_(h2_rxframe_f)
493 189
h2_rx_priority(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
494
{
495
496 189
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
497 189
        ASSERT_RXTHR(h2);
498 189
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
499 189
        return (0);
500
}
501
502
/**********************************************************************
503
 * Incoming SETTINGS, possibly an ACK of one we sent.
504
 */
505
506
#define H2_SETTING(U,l, ...)                                    \
507
static void v_matchproto_(h2_setsetting_f)                      \
508
h2_setting_##l(struct h2_settings* s, uint32_t v)               \
509
{                                                               \
510
        s -> l = v;                                             \
511
}
512
#include <tbl/h2_settings.h>
513
514
#define H2_SETTING(U, l, ...)                                   \
515
const struct h2_setting_s H2_SET_##U[1] = {{                    \
516
        #l,                                                     \
517
        h2_setting_##l,                                         \
518
        __VA_ARGS__                                             \
519
}};
520
#include <tbl/h2_settings.h>
521
522
static const struct h2_setting_s * const h2_setting_tbl[] = {
523
#define H2_SETTING(U,l,v, ...) [v] = H2_SET_##U,
524
#include <tbl/h2_settings.h>
525
};
526
527
#define H2_SETTING_TBL_LEN vcountof(h2_setting_tbl)
528
529
static void
530 189
h2_win_adjust(const struct h2_sess *h2, uint32_t oldval, uint32_t newval)
531
{
532
        struct h2_req *r2;
533
534 189
        Lck_AssertHeld(&h2->sess->mtx);
535
        // rfc7540,l,2668,2674
536 378
        VTAILQ_FOREACH(r2, &h2->streams, list) {
537 189
                CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
538 189
                if (r2 == h2->req0)
539 189
                        continue; // rfc7540,l,2699,2699
540 0
                switch (r2->state) {
541
                case H2_S_IDLE:
542
                case H2_S_OPEN:
543
                case H2_S_CLOS_REM:
544
                        /*
545
                         * We allow a window to go negative, as per
546
                         * rfc7540,l,2676,2680
547
                         */
548 0
                        r2->t_window += (int64_t)newval - oldval;
549 0
                        break;
550
                default:
551 0
                        break;
552
                }
553 0
        }
554 189
}
555
556
h2_error
557 378
h2_set_setting(struct h2_sess *h2, const uint8_t *d)
558
{
559
        const struct h2_setting_s *s;
560
        uint16_t x;
561
        uint32_t y;
562
563 378
        x = vbe16dec(d);
564 378
        y = vbe32dec(d + 2);
565 378
        if (x >= H2_SETTING_TBL_LEN || h2_setting_tbl[x] == NULL) {
566
                // rfc7540,l,2181,2182
567 42
                H2S_Lock_VSLb(h2, SLT_Debug,
568 21
                    "H2SETTING unknown setting 0x%04x=%08x (ignored)", x, y);
569 21
                return (0);
570
        }
571 357
        s = h2_setting_tbl[x];
572 357
        AN(s);
573 357
        if (y < s->minval || y > s->maxval) {
574 126
                H2S_Lock_VSLb(h2, SLT_Debug, "H2SETTING invalid %s=0x%08x",
575 63
                    s->name, y);
576 63
                AN(s->range_error);
577 63
                if (!DO_DEBUG(DBG_H2_NOCHECK))
578 21
                        return (s->range_error);
579 42
        }
580 336
        Lck_Lock(&h2->sess->mtx);
581 336
        if (s == H2_SET_INITIAL_WINDOW_SIZE)
582 189
                h2_win_adjust(h2, h2->remote_settings.initial_window_size, y);
583 336
        VSLb(h2->vsl, SLT_Debug, "H2SETTING %s=0x%08x", s->name, y);
584 336
        Lck_Unlock(&h2->sess->mtx);
585 336
        AN(s->setfunc);
586 336
        s->setfunc(&h2->remote_settings, y);
587 336
        return (0);
588 378
}
589
590
static h2_error v_matchproto_(h2_rxframe_f)
591 6216
h2_rx_settings(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
592
{
593
        const uint8_t *p;
594
        unsigned l;
595 6216
        h2_error retval = 0;
596
597 6216
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
598 6216
        ASSERT_RXTHR(h2);
599 6216
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
600 6216
        assert(r2 == h2->req0);
601 6216
        AZ(h2->rxf_stream);
602
603 6216
        if (h2->rxf_flags == H2FF_SETTINGS_ACK) {
604 3066
                if (h2->rxf_len > 0) {                  // rfc7540,l,2047,2049
605 21
                        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx settings ack with "
606
                            "(len > 0)");
607 21
                        return (H2CE_FRAME_SIZE_ERROR);
608
                }
609 3045
                return (0);
610
        } else {
611 3150
                if (h2->rxf_len % 6) {                  // rfc7540,l,2062,2064
612 21
                        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx settings with "
613
                            "((len %% 6) != 0)");
614 21
                        return (H2CE_PROTOCOL_ERROR);
615
                }
616 3129
                p = h2->rxf_data;
617 3276
                for (l = h2->rxf_len; l >= 6; l -= 6, p += 6) {
618 168
                        retval = h2_set_setting(h2, p);
619 168
                        if (retval)
620 21
                                return (retval);
621 147
                }
622 3108
                H2_Send_Get(wrk, h2, r2);
623 3108
                H2_Send_Frame(wrk, h2,
624
                    H2_F_SETTINGS, H2FF_SETTINGS_ACK, 0, 0, NULL);
625 3108
                H2_Send_Rel(h2, r2);
626
        }
627 3108
        return (0);
628 6216
}
629
630
/**********************************************************************
631
 * Incoming HEADERS, this is where the party's at...
632
 */
633
634
void v_matchproto_(task_func_t)
635 3169
h2_do_req(struct worker *wrk, void *priv)
636
{
637
        struct req *req;
638
        struct h2_req *r2;
639
        struct h2_sess *h2;
640
641 3169
        CAST_OBJ_NOTNULL(req, priv, REQ_MAGIC);
642 3169
        CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
643 3169
        THR_SetRequest(req);
644 3169
        CNT_Embark(wrk, req);
645
646 3169
        if (CNT_Request(req) != REQ_FSM_DISEMBARK) {
647 2898
                wrk->stats->client_req++;
648 2898
                assert(!WS_IsReserved(req->ws));
649 2898
                AZ(req->top->vcl0);
650 2898
                h2 = r2->h2sess;
651 2898
                CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
652 2898
                Lck_Lock(&h2->sess->mtx);
653 2898
                r2->scheduled = 0;
654 2898
                r2->state = H2_S_CLOSED;
655 2898
                r2->h2sess->do_sweep = 1;
656 2898
                Lck_Unlock(&h2->sess->mtx);
657 2898
        }
658 3169
        THR_SetRequest(NULL);
659 3169
}
660
661
static h2_error
662 3108
h2_end_headers(struct worker *wrk, struct h2_sess *h2,
663
    struct req *req, struct h2_req *r2)
664
{
665
        h2_error h2e;
666
        ssize_t cl;
667
668 3108
        ASSERT_RXTHR(h2);
669 3108
        assert(r2->state == H2_S_OPEN);
670 3108
        h2e = h2h_decode_hdr_fini(h2);
671 3108
        h2->new_req = NULL;
672 3108
        if (h2e != NULL) {
673 105
                H2S_Lock_VSLb(h2, SLT_Debug, "HPACK/FINI %s", h2e->name);
674 105
                assert(!WS_IsReserved(r2->req->ws));
675 105
                h2_del_req(wrk, r2);
676 105
                return (h2e);
677
        }
678 3003
        req->t_req = VTIM_real();
679 3003
        VSLb_ts_req(req, "Req", req->t_req);
680
681
        // XXX: Smarter to do this already at HPACK time into tail end of
682
        // XXX: WS, then copy back once all headers received.
683
        // XXX: Have I mentioned H/2 Is hodge-podge ?
684 3003
        http_CollectHdrSep(req->http, H_Cookie, "; ");  // rfc7540,l,3114,3120
685
686 3003
        cl = http_GetContentLength(req->http);
687 3003
        assert(cl >= -2);
688 3003
        if (cl == -2) {
689 0
                H2S_Lock_VSLb(h2, SLT_Debug, "Non-parseable Content-Length");
690 0
                return (H2SE_PROTOCOL_ERROR);
691
        }
692
693 3003
        if (req->req_body_status == NULL) {
694 756
                if (cl == -1)
695 399
                        req->req_body_status = BS_EOF;
696
                else {
697
                        /* Note: If cl==0 here, we still need to have
698
                         * req_body_status==BS_LENGTH, so that there will
699
                         * be a wait for the stream to reach H2_S_CLOS_REM
700
                         * while dealing with the request body. */
701 357
                        req->req_body_status = BS_LENGTH;
702
                }
703
                /* Set req->htc->content_length because this is used as
704
                 * the hint in vrb_pull() for how large the storage
705
                 * buffers need to be */
706 756
                req->htc->content_length = cl;
707 756
        } else {
708
                /* A HEADER frame contained END_STREAM */
709 2247
                assert (req->req_body_status == BS_NONE);
710 2247
                r2->state = H2_S_CLOS_REM;
711 2247
                if (cl > 0) {
712 21
                        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx header with END_STREAM "
713
                            "and content-length > 0");
714 21
                        return (H2CE_PROTOCOL_ERROR); //rfc7540,l,1838,1840
715
                }
716
        }
717
718 2982
        if (req->http->hd[HTTP_HDR_METHOD].b == NULL) {
719 21
                H2S_Lock_VSLb(h2, SLT_Debug, "Missing :method");
720 21
                return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
721
        }
722
723 2961
        http_SetWellKnownMethod(req->http);
724
725 2961
        if (req->http->hd[HTTP_HDR_URL].b == NULL) {
726 21
                H2S_Lock_VSLb(h2, SLT_Debug, "Missing :path");
727 21
                return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3087,3090
728
        }
729
730 2940
        AN(req->http->hd[HTTP_HDR_PROTO].b);
731
732 2940
        if (*req->http->hd[HTTP_HDR_URL].b == '*' &&
733 84
            ! http_method_eq(req->http->wkm, WKM_OPTIONS)) {
734 63
                H2S_Lock_VSLb(h2, SLT_BogoHeader, "Illegal :path pseudo-header");
735 63
                return (H2SE_PROTOCOL_ERROR); //rfc7540,l,3068,3071
736
        }
737
738 2877
        assert(req->req_step == R_STP_TRANSPORT);
739 2877
        VCL_TaskEnter(req->privs);
740 2877
        VCL_TaskEnter(req->top->privs);
741 2877
        req->task->func = h2_do_req;
742 2877
        req->task->priv = req;
743 2877
        r2->scheduled = 1;
744 2877
        if (Pool_Task(wrk->pool, req->task, TASK_QUEUE_STR) != 0) {
745 21
                r2->scheduled = 0;
746 21
                r2->state = H2_S_CLOSED;
747 21
                return (H2SE_REFUSED_STREAM); //rfc7540,l,3326,3329
748
        }
749 2856
        return (0);
750 3108
}
751
752
static h2_error v_matchproto_(h2_rxframe_f)
753 4032
h2_rx_headers(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
754
{
755
        struct req *req;
756
        h2_error h2e;
757
        const uint8_t *p;
758
        size_t l;
759
760 4032
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
761 4032
        ASSERT_RXTHR(h2);
762
763 4032
        if (r2 != NULL) {
764 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx headers on non-idle stream");
765 21
                return (H2CE_PROTOCOL_ERROR);   // rfc9113,l,887,891
766
        }
767
768 4011
        if (h2->rxf_stream <= h2->highest_stream) {
769 21
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: new stream ID < highest stream");
770 21
                return (H2CE_PROTOCOL_ERROR);   // rfc7540,l,1153,1158
771
        }
772
        /* NB: we don't need to guard the read of h2->open_streams
773
         * because headers are handled sequentially so it cannot
774
         * increase under our feet.
775
         */
776 7980
        if (h2->open_streams >=
777 3990
            (int)h2->local_settings.max_concurrent_streams) {
778 42
                H2S_Lock_VSLb(h2, SLT_Debug,
779
                    "H2: stream %u: Hit maximum number of "
780 21
                    "concurrent streams", h2->rxf_stream);
781 21
                return (H2SE_REFUSED_STREAM);   // rfc7540,l,1200,1205
782
        }
783 3969
        h2->highest_stream = h2->rxf_stream;
784 3969
        r2 = h2_new_req(h2, h2->rxf_stream, NULL);
785 3969
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
786 3969
        assert(r2->state == H2_S_IDLE);
787 3969
        r2->state = H2_S_OPEN;
788
789 3969
        req = r2->req;
790 3969
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
791
792 3969
        req->vsl->wid = VXID_Get(wrk, VSL_CLIENTMARKER);
793 3969
        VSLb(req->vsl, SLT_Begin, "req %ju rxreq", VXID(req->sp->vxid));
794 3969
        VSL(SLT_Link, req->sp->vxid, "req %ju rxreq", VXID(req->vsl->wid));
795
796 3969
        h2->new_req = req;
797 3969
        req->sp = h2->sess;
798 3969
        req->transport = &HTTP2_transport;
799
800 3969
        req->t_first = h2->t1;
801 3969
        req->t_prev = req->t_first;
802 3969
        VSLb_ts_req(req, "Start", req->t_first);
803 3969
        req->acct.req_hdrbytes += h2->rxf_len;
804
805 3969
        HTTP_Setup(req->http, req->ws, req->vsl, SLT_ReqMethod);
806 3969
        http_SetH(req->http, HTTP_HDR_PROTO, "HTTP/2.0");
807
808 3969
        h2h_decode_hdr_init(h2);
809
810 3969
        p = h2->rxf_data;
811 3969
        l = h2->rxf_len;
812 3969
        if (h2->rxf_flags & H2FF_HEADERS_PADDED) {
813 147
                if (*p + 1 > l) {
814 42
                        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx headers with pad length > frame len");
815 42
                        return (H2CE_PROTOCOL_ERROR);   // rfc7540,l,1884,1887
816
                }
817 105
                l -= 1 + *p;
818 105
                p += 1;
819 105
        }
820 3927
        if (h2->rxf_flags & H2FF_HEADERS_PRIORITY) {
821 63
                if (l < 5) {
822 21
                        H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx headers with incorrect "
823
                            "priority data");
824 21
                        return (H2CE_PROTOCOL_ERROR);
825
                }
826 42
                l -= 5;
827 42
                p += 5;
828 42
        }
829 3906
        h2e = h2h_decode_bytes(h2, p, l);
830 3906
        if (h2e != NULL) {
831 714
                H2S_Lock_VSLb(h2, SLT_Debug, "HPACK(hdr) %s", h2e->name);
832 714
                (void)h2h_decode_hdr_fini(h2);
833 714
                assert(!WS_IsReserved(r2->req->ws));
834 714
                h2_del_req(wrk, r2);
835 714
                return (h2e);
836
        }
837
838 3192
        if (h2->rxf_flags & H2FF_HEADERS_END_STREAM)
839 2436
                req->req_body_status = BS_NONE;
840
841 3192
        if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
842 3045
                return (h2_end_headers(wrk, h2, req, r2));
843 147
        return (0);
844 4032
}
845
846
/**********************************************************************/
847
848
static h2_error v_matchproto_(h2_rxframe_f)
849 399
h2_rx_continuation(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
850
{
851
        struct req *req;
852
        h2_error h2e;
853
854 399
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
855 399
        ASSERT_RXTHR(h2);
856 399
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
857
858 399
        if (r2 == NULL || r2->state != H2_S_OPEN || r2->req != h2->new_req) {
859 84
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: rx unexpected CONT frame"
860 42
                    " on stream %d", h2->rxf_stream);
861 42
                return (H2CE_PROTOCOL_ERROR);   // XXX spec ?
862
        }
863 357
        req = r2->req;
864 357
        h2e = h2h_decode_bytes(h2, h2->rxf_data, h2->rxf_len);
865 357
        r2->req->acct.req_hdrbytes += h2->rxf_len;
866 357
        if (h2e != NULL) {
867 42
                H2S_Lock_VSLb(h2, SLT_Debug, "HPACK(cont) %s", h2e->name);
868 42
                (void)h2h_decode_hdr_fini(h2);
869 42
                assert(!WS_IsReserved(r2->req->ws));
870 42
                h2_del_req(wrk, r2);
871 42
                return (h2e);
872
        }
873 315
        if (h2->rxf_flags & H2FF_HEADERS_END_HEADERS)
874 63
                return (h2_end_headers(wrk, h2, req, r2));
875 252
        return (0);
876 399
}
877
878
/**********************************************************************/
879
880
static h2_error v_matchproto_(h2_rxframe_f)
881 6615
h2_rx_data(struct worker *wrk, struct h2_sess *h2, struct h2_req *r2)
882
{
883
        char buf[4];
884
        ssize_t l;
885
        uint64_t l2, head;
886
        const uint8_t *src;
887
        unsigned len;
888
889
        /* XXX: Shouldn't error handling, setting of r2->error and
890
         * r2->cond signalling be handled more generally at the end of
891
         * procframe()??? */
892
893 6615
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
894 6615
        ASSERT_RXTHR(h2);
895 6615
        CHECK_OBJ_ORNULL(r2, H2_REQ_MAGIC);
896
897 6615
        if (r2 == NULL)
898 21
                return (0);
899
900 6594
        if (r2->state >= H2_S_CLOS_REM) {
901 42
                r2->error = H2SE_STREAM_CLOSED;
902 42
                return (H2SE_STREAM_CLOSED); // rfc7540,l,1766,1769
903
        }
904
905 6552
        Lck_Lock(&h2->sess->mtx);
906 6552
        CHECK_OBJ_ORNULL(r2->rxbuf, H2_RXBUF_MAGIC);
907
908 6552
        if (h2->error != NULL || r2->error != NULL) {
909 21
                if (r2->cond)
910 0
                        PTOK(pthread_cond_signal(r2->cond));
911 21
                Lck_Unlock(&h2->sess->mtx);
912 21
                return (h2->error != NULL ? h2->error : r2->error);
913
        }
914
915
        /* Check padding if present */
916 6531
        src = h2->rxf_data;
917 6531
        len = h2->rxf_len;
918 6531
        if (h2->rxf_flags & H2FF_DATA_PADDED) {
919 5586
                if (*src >= len) {
920 0
                        VSLb(h2->vsl, SLT_SessError,
921
                            "H2: stream %u: Padding larger than frame length",
922 0
                            h2->rxf_stream);
923 0
                        r2->error = H2CE_PROTOCOL_ERROR;
924 0
                        if (r2->cond)
925 0
                                PTOK(pthread_cond_signal(r2->cond));
926 0
                        Lck_Unlock(&h2->sess->mtx);
927 0
                        return (H2CE_PROTOCOL_ERROR);
928
                }
929 5586
                len -= 1 + *src;
930 5586
                src += 1;
931 5586
        }
932
933
        /* Check against the Content-Length header if given */
934 6531
        if (r2->req->htc->content_length >= 0) {
935 6321
                if (r2->rxbuf)
936 588
                        l = r2->rxbuf->head;
937
                else
938 5733
                        l = 0;
939 6321
                l += len;
940 6615
                if (l > r2->req->htc->content_length ||
941 6258
                    ((h2->rxf_flags & H2FF_DATA_END_STREAM) &&
942 294
                     l != r2->req->htc->content_length)) {
943 126
                        VSLb(h2->vsl, SLT_Debug,
944
                            "H2: stream %u: Received data and Content-Length"
945 63
                            " mismatch", h2->rxf_stream);
946 63
                        r2->error = H2SE_PROTOCOL_ERROR;
947 63
                        if (r2->cond)
948 21
                                PTOK(pthread_cond_signal(r2->cond));
949 63
                        Lck_Unlock(&h2->sess->mtx);
950 63
                        return (H2SE_PROTOCOL_ERROR);
951
                }
952 6258
        }
953
954
        /* Check and charge connection window. The entire frame including
955
         * padding (h2->rxf_len) counts towards the window. */
956 6468
        if (h2->rxf_len > h2->req0->r_window) {
957 0
                VSLb(h2->vsl, SLT_SessError,
958
                    "H2: stream %u: Exceeded connection receive window",
959 0
                    h2->rxf_stream);
960 0
                r2->error = H2CE_FLOW_CONTROL_ERROR;
961 0
                if (r2->cond)
962 0
                        PTOK(pthread_cond_signal(r2->cond));
963 0
                Lck_Unlock(&h2->sess->mtx);
964 0
                return (H2CE_FLOW_CONTROL_ERROR);
965
        }
966 6468
        h2->req0->r_window -= h2->rxf_len;
967 6468
        if (h2->req0->r_window < cache_param->h2_rx_window_low_water) {
968 903
                h2->req0->r_window += cache_param->h2_rx_window_increment;
969 903
                vbe32enc(buf, cache_param->h2_rx_window_increment);
970 903
                Lck_Unlock(&h2->sess->mtx);
971 903
                H2_Send_Get(wrk, h2, h2->req0);
972 903
                H2_Send_Frame(wrk, h2, H2_F_WINDOW_UPDATE, 0, 4, 0, buf);
973 903
                H2_Send_Rel(h2, h2->req0);
974 903
                Lck_Lock(&h2->sess->mtx);
975 903
        }
976
977
        /* Check stream window. The entire frame including padding
978
         * (h2->rxf_len) counts towards the window. */
979 6468
        if (h2->rxf_len > r2->r_window) {
980 0
                VSLb(h2->vsl, SLT_Debug,
981
                    "H2: stream %u: Exceeded stream receive window",
982 0
                    h2->rxf_stream);
983 0
                r2->error = H2SE_FLOW_CONTROL_ERROR;
984 0
                if (r2->cond)
985 0
                        PTOK(pthread_cond_signal(r2->cond));
986 0
                Lck_Unlock(&h2->sess->mtx);
987 0
                return (H2SE_FLOW_CONTROL_ERROR);
988
        }
989
990
        /* Handle zero size frame before starting to allocate buffers */
991 6468
        if (len == 0) {
992 5439
                r2->r_window -= h2->rxf_len;
993
994
                /* Handle the specific corner case where the entire window
995
                 * has been exhausted using nothing but padding
996
                 * bytes. Since no bytes have been buffered, no bytes
997
                 * would be consumed by the request thread and no stream
998
                 * window updates sent. Unpaint ourselves from this corner
999
                 * by sending a stream window update here. */
1000 5439
                CHECK_OBJ_ORNULL(r2->rxbuf, H2_RXBUF_MAGIC);
1001 5439
                if (r2->r_window == 0 &&
1002 21
                    (r2->rxbuf == NULL || r2->rxbuf->tail == r2->rxbuf->head)) {
1003 21
                        if (r2->rxbuf)
1004 0
                                l = r2->rxbuf->size;
1005
                        else
1006 21
                                l = h2->local_settings.initial_window_size;
1007 21
                        r2->r_window += l;
1008 21
                        Lck_Unlock(&h2->sess->mtx);
1009 21
                        vbe32enc(buf, l);
1010 21
                        H2_Send_Get(wrk, h2, h2->req0);
1011 42
                        H2_Send_Frame(wrk, h2, H2_F_WINDOW_UPDATE, 0, 4,
1012 21
                            r2->stream, buf);
1013 21
                        H2_Send_Rel(h2, h2->req0);
1014 21
                        Lck_Lock(&h2->sess->mtx);
1015 21
                }
1016
1017 5439
                if (h2->rxf_flags & H2FF_DATA_END_STREAM)
1018 63
                        r2->state = H2_S_CLOS_REM;
1019 5439
                if (r2->cond)
1020 5282
                        PTOK(pthread_cond_signal(r2->cond));
1021 5439
                Lck_Unlock(&h2->sess->mtx);
1022 5439
                return (0);
1023
        }
1024
1025
        /* Make the buffer on demand */
1026 1029
        if (r2->rxbuf == NULL) {
1027
                unsigned bufsize;
1028
                size_t bstest;
1029
                struct stv_buffer *stvbuf;
1030
                struct h2_rxbuf *rxbuf;
1031
1032 462
                Lck_Unlock(&h2->sess->mtx);
1033
1034 462
                bufsize = h2->local_settings.initial_window_size;
1035 462
                if (bufsize < r2->r_window) {
1036
                        /* This will not happen because we do not have any
1037
                         * mechanism to change the initial window size on
1038
                         * a running session. But if we gain that ability,
1039
                         * this future proofs it. */
1040 0
                        bufsize = r2->r_window;
1041 0
                }
1042 462
                assert(bufsize > 0);
1043 462
                if ((h2->rxf_flags & H2FF_DATA_END_STREAM) &&
1044 252
                    bufsize > len)
1045
                        /* Cap the buffer size when we know this is the
1046
                         * single data frame. */
1047 252
                        bufsize = len;
1048 462
                CHECK_OBJ_NOTNULL(stv_h2_rxbuf, STEVEDORE_MAGIC);
1049 924
                stvbuf = STV_AllocBuf(wrk, stv_h2_rxbuf,
1050 462
                    bufsize + sizeof *rxbuf);
1051 462
                if (stvbuf == NULL) {
1052 0
                        Lck_Lock(&h2->sess->mtx);
1053 0
                        VSLb(h2->vsl, SLT_Debug,
1054
                            "H2: stream %u: Failed to allocate request body"
1055
                            " buffer",
1056 0
                            h2->rxf_stream);
1057 0
                        r2->error = H2SE_INTERNAL_ERROR;
1058 0
                        if (r2->cond)
1059 0
                                PTOK(pthread_cond_signal(r2->cond));
1060 0
                        Lck_Unlock(&h2->sess->mtx);
1061 0
                        return (H2SE_INTERNAL_ERROR);
1062
                }
1063 462
                rxbuf = STV_GetBufPtr(stvbuf, &bstest);
1064 462
                AN(rxbuf);
1065 462
                assert(bstest >= bufsize + sizeof *rxbuf);
1066 462
                assert(PAOK(rxbuf));
1067 462
                INIT_OBJ(rxbuf, H2_RXBUF_MAGIC);
1068 462
                rxbuf->size = bufsize;
1069 462
                rxbuf->stvbuf = stvbuf;
1070
1071 462
                r2->rxbuf = rxbuf;
1072
1073 462
                Lck_Lock(&h2->sess->mtx);
1074 462
        }
1075
1076 1029
        CHECK_OBJ_NOTNULL(r2->rxbuf, H2_RXBUF_MAGIC);
1077 1029
        assert(r2->rxbuf->tail <= r2->rxbuf->head);
1078 1029
        l = r2->rxbuf->head - r2->rxbuf->tail;
1079 1029
        assert(l <= r2->rxbuf->size);
1080 1029
        l = r2->rxbuf->size - l;
1081 1029
        assert(len <= l); /* Stream window handling ensures this */
1082
1083 1029
        Lck_Unlock(&h2->sess->mtx);
1084
1085 1029
        l = len;
1086 1029
        head = r2->rxbuf->head;
1087 1029
        do {
1088 1134
                l2 = l;
1089 1134
                if ((head % r2->rxbuf->size) + l2 > r2->rxbuf->size)
1090 105
                        l2 = r2->rxbuf->size - (head % r2->rxbuf->size);
1091 1134
                assert(l2 > 0);
1092 1134
                vmemcpy(&r2->rxbuf->data[head % r2->rxbuf->size], src, l2);
1093 1134
                src += l2;
1094 1134
                head += l2;
1095 1134
                l -= l2;
1096 1134
        } while (l > 0);
1097
1098 1029
        Lck_Lock(&h2->sess->mtx);
1099
1100
        /* Charge stream window. The entire frame including padding
1101
         * (h2->rxf_len) counts towards the window. The used padding
1102
         * bytes will be included in the next connection window update
1103
         * sent when the buffer bytes are consumed because that is
1104
         * calculated against the available buffer space. */
1105 1029
        r2->r_window -= h2->rxf_len;
1106 1029
        r2->rxbuf->head += len;
1107 1029
        assert(r2->rxbuf->tail <= r2->rxbuf->head);
1108 1029
        if (h2->rxf_flags & H2FF_DATA_END_STREAM)
1109 378
                r2->state = H2_S_CLOS_REM;
1110 1029
        if (r2->cond)
1111 606
                PTOK(pthread_cond_signal(r2->cond));
1112 1029
        Lck_Unlock(&h2->sess->mtx);
1113
1114 1029
        return (0);
1115 6615
}
1116
1117
static enum vfp_status v_matchproto_(vfp_pull_f)
1118 1070
h2_vfp_body(struct vfp_ctx *vc, struct vfp_entry *vfe, void *ptr, ssize_t *lp)
1119
{
1120
        struct h2_req *r2;
1121
        struct h2_sess *h2;
1122
        enum vfp_status retval;
1123
        ssize_t l, l2;
1124
        uint64_t tail;
1125
        uint8_t *dst;
1126
        char buf[4];
1127
        int i;
1128
1129 1070
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
1130 1070
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
1131 1070
        CAST_OBJ_NOTNULL(r2, vfe->priv1, H2_REQ_MAGIC);
1132 1070
        h2 = r2->h2sess;
1133
1134 1070
        AN(ptr);
1135 1070
        AN(lp);
1136 1070
        assert(*lp >= 0);
1137
1138 1070
        Lck_Lock(&h2->sess->mtx);
1139
1140 1070
        r2->cond = &vc->wrk->cond;
1141 7084
        while (1) {
1142 7084
                CHECK_OBJ_ORNULL(r2->rxbuf, H2_RXBUF_MAGIC);
1143 7084
                if (r2->rxbuf) {
1144 1469
                        assert(r2->rxbuf->tail <= r2->rxbuf->head);
1145 1469
                        l = r2->rxbuf->head - r2->rxbuf->tail;
1146 1469
                } else
1147 5615
                        l = 0;
1148
1149 7084
                if (h2->error != NULL || r2->error != NULL)
1150 136
                        retval = VFP_ERROR;
1151 6948
                else if (r2->state >= H2_S_CLOS_REM && l <= *lp)
1152 410
                        retval = VFP_END;
1153
                else {
1154 6538
                        if (l > *lp)
1155 0
                                l = *lp;
1156 6538
                        retval = VFP_OK;
1157
                }
1158
1159 7084
                if (retval != VFP_OK || l > 0)
1160 1070
                        break;
1161
1162 12028
                i = Lck_CondWaitTimeout(r2->cond, &h2->sess->mtx,
1163 6014
                    SESS_TMO(h2->sess, timeout_idle));
1164 6014
                if (i == ETIMEDOUT) {
1165 0
                        retval = VFP_ERROR;
1166 0
                        break;
1167
                }
1168
        }
1169 1070
        r2->cond = NULL;
1170
1171 1070
        Lck_Unlock(&h2->sess->mtx);
1172
1173 1070
        if (l == 0 || retval == VFP_ERROR) {
1174 188
                *lp = 0;
1175 188
                return (retval);
1176
        }
1177
1178 882
        *lp = l;
1179 882
        dst = ptr;
1180 882
        tail = r2->rxbuf->tail;
1181 882
        do {
1182 987
                l2 = l;
1183 987
                if ((tail % r2->rxbuf->size) + l2 > r2->rxbuf->size)
1184 105
                        l2 = r2->rxbuf->size - (tail % r2->rxbuf->size);
1185 987
                assert(l2 > 0);
1186 987
                vmemcpy(dst, &r2->rxbuf->data[tail % r2->rxbuf->size], l2);
1187 987
                dst += l2;
1188 987
                tail += l2;
1189 987
                l -= l2;
1190 987
        } while (l > 0);
1191
1192 882
        Lck_Lock(&h2->sess->mtx);
1193
1194 882
        CHECK_OBJ_NOTNULL(r2->rxbuf, H2_RXBUF_MAGIC);
1195 882
        r2->rxbuf->tail = tail;
1196 882
        assert(r2->rxbuf->tail <= r2->rxbuf->head);
1197
1198 882
        if (r2->r_window < cache_param->h2_rx_window_low_water &&
1199 609
            r2->state < H2_S_CLOS_REM) {
1200
                /* l is free buffer space */
1201
                /* l2 is calculated window increment */
1202 399
                l = r2->rxbuf->size - (r2->rxbuf->head - r2->rxbuf->tail);
1203 399
                assert(r2->r_window <= l);
1204 399
                l2 = cache_param->h2_rx_window_increment;
1205 399
                if (r2->r_window + l2 > l)
1206 399
                        l2 = l - r2->r_window;
1207 399
                r2->r_window += l2;
1208 399
        } else
1209 483
                l2 = 0;
1210
1211 882
        Lck_Unlock(&h2->sess->mtx);
1212
1213 882
        if (l2 > 0) {
1214 399
                vbe32enc(buf, l2);
1215 399
                H2_Send_Get(vc->wrk, h2, r2);
1216 798
                H2_Send_Frame(vc->wrk, h2, H2_F_WINDOW_UPDATE, 0, 4,
1217 399
                    r2->stream, buf);
1218 399
                H2_Send_Rel(h2, r2);
1219 399
        }
1220
1221 882
        return (retval);
1222 1070
}
1223
1224
static void
1225 546
h2_vfp_body_fini(struct vfp_ctx *vc, struct vfp_entry *vfe)
1226
{
1227
        struct h2_req *r2;
1228
        struct h2_sess *h2;
1229 546
        struct stv_buffer *stvbuf = NULL;
1230
1231 546
        CHECK_OBJ_NOTNULL(vc, VFP_CTX_MAGIC);
1232 546
        CHECK_OBJ_NOTNULL(vfe, VFP_ENTRY_MAGIC);
1233 546
        CAST_OBJ_NOTNULL(r2, vfe->priv1, H2_REQ_MAGIC);
1234 546
        CHECK_OBJ_NOTNULL(r2->req, REQ_MAGIC);
1235 546
        h2 = r2->h2sess;
1236
1237 546
        if (vc->failed) {
1238 0
                CHECK_OBJ_NOTNULL(r2->req->wrk, WORKER_MAGIC);
1239 0
                H2_Send_Get(r2->req->wrk, h2, r2);
1240 0
                H2_Send_RST(r2->req->wrk, h2, r2, r2->stream,
1241
                    H2SE_REFUSED_STREAM);
1242 0
                H2_Send_Rel(h2, r2);
1243 0
                Lck_Lock(&h2->sess->mtx);
1244 0
                r2->error = H2SE_REFUSED_STREAM;
1245 0
                Lck_Unlock(&h2->sess->mtx);
1246 0
        }
1247
1248 546
        if (r2->state >= H2_S_CLOS_REM && r2->rxbuf != NULL) {
1249 378
                Lck_Lock(&h2->sess->mtx);
1250 378
                CHECK_OBJ_ORNULL(r2->rxbuf, H2_RXBUF_MAGIC);
1251 378
                if (r2->rxbuf != NULL) {
1252 378
                        stvbuf = r2->rxbuf->stvbuf;
1253 378
                        r2->rxbuf = NULL;
1254 378
                }
1255 378
                Lck_Unlock(&h2->sess->mtx);
1256 378
                if (stvbuf != NULL) {
1257 378
                        STV_FreeBuf(vc->wrk, &stvbuf);
1258 378
                        AZ(stvbuf);
1259 378
                }
1260 378
        }
1261 546
}
1262
1263
static const struct vfp h2_body = {
1264
        .name = "H2_BODY",
1265
        .pull = h2_vfp_body,
1266
        .fini = h2_vfp_body_fini
1267
};
1268
1269
void v_matchproto_(vtr_req_body_t)
1270 756
h2_req_body(struct req *req)
1271
{
1272
        struct h2_req *r2;
1273
        struct vfp_entry *vfe;
1274
1275 756
        CHECK_OBJ(req, REQ_MAGIC);
1276 756
        CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
1277 756
        vfe = VFP_Push(req->vfc, &h2_body);
1278 756
        AN(vfe);
1279 756
        vfe->priv1 = r2;
1280 756
}
1281
1282
/**********************************************************************/
1283
1284
void v_matchproto_(vtr_req_fail_f)
1285 21
h2_req_fail(struct req *req, stream_close_t reason)
1286
{
1287 21
        assert(reason != SC_NULL);
1288 21
        assert(req->sp->fd != 0);
1289 21
        VSLb(req->vsl, SLT_Debug, "H2FAILREQ");
1290 21
}
1291
1292
/**********************************************************************/
1293
1294
static enum htc_status_e v_matchproto_(htc_complete_f)
1295 35045
h2_frame_complete(struct http_conn *htc)
1296
{
1297
        struct h2_sess *h2;
1298
1299 35045
        CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
1300 35045
        CAST_OBJ_NOTNULL(h2, htc->priv, H2_SESS_MAGIC);
1301 35045
        if (htc->rxbuf_b + 9 > htc->rxbuf_e ||
1302 19238
            htc->rxbuf_b + 9 + (vbe32dec(htc->rxbuf_b) >> 8) > htc->rxbuf_e)
1303 16271
                return (HTC_S_MORE);
1304 18774
        return (HTC_S_COMPLETE);
1305 35045
}
1306
1307
/**********************************************************************/
1308
1309
static h2_error
1310 18753
h2_procframe(struct worker *wrk, struct h2_sess *h2, h2_frame h2f)
1311
{
1312
        struct h2_req *r2;
1313
        h2_error h2e;
1314
1315 18753
        ASSERT_RXTHR(h2);
1316 18753
        if (h2->rxf_stream == 0 && h2f->act_szero != 0) {
1317 42
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: unexpected %s frame on stream 0",
1318 21
                    h2f->name);
1319 21
                return (h2f->act_szero);
1320
        }
1321
1322 18732
        if (h2->rxf_stream != 0 && h2f->act_snonzero != 0) {
1323 42
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: unexpected %s frame on stream %d",
1324 21
                    h2f->name, h2->rxf_stream);
1325 21
                return (h2f->act_snonzero);
1326
        }
1327
1328 18711
        if (h2->rxf_stream > h2->highest_stream && h2f->act_sidle != 0) {
1329 84
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: unexpected %s frame on idle stream "
1330 42
                    "%d", h2f->name, h2->rxf_stream);
1331 42
                return (h2f->act_sidle);
1332
        }
1333
1334 18669
        if (h2->rxf_stream != 0 && !(h2->rxf_stream & 1)) {
1335
                // rfc7540,l,1140,1145
1336
                // rfc7540,l,1153,1158
1337
                /* No even streams, we don't do PUSH_PROMISE */
1338 42
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: illegal stream (=%u)",
1339 21
                    h2->rxf_stream);
1340 21
                return (H2CE_PROTOCOL_ERROR);
1341
        }
1342
1343 32282
        VTAILQ_FOREACH(r2, &h2->streams, list)
1344 27914
                if (r2->stream == h2->rxf_stream)
1345 14280
                        break;
1346
1347 18648
        if (h2->new_req != NULL && h2f != H2_F_CONTINUATION) {
1348 42
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: expected continuation but "
1349 21
                    " received %s on stream %d", h2f->name, h2->rxf_stream);
1350 21
                return (H2CE_PROTOCOL_ERROR);   // rfc7540,l,1859,1863
1351
        }
1352
1353 18627
        h2e = h2f->rxfunc(wrk, h2, r2);
1354 18627
        if (h2e == NULL)
1355 16884
                return (NULL);
1356 1743
        if (h2->rxf_stream == 0 || h2e->connection)
1357 588
                return (h2e);   // Connection errors one level up
1358
1359 1155
        H2_Send_Get(wrk, h2, h2->req0);
1360 1155
        H2_Send_RST(wrk, h2, h2->req0, h2->rxf_stream, h2e);
1361 1155
        H2_Send_Rel(h2, h2->req0);
1362 1155
        return (NULL);
1363 18753
}
1364
1365
h2_error
1366 12551
h2_stream_tmo(struct h2_sess *h2, const struct h2_req *r2, vtim_real now, vtim_real *due)
1367
{
1368
        vtim_real t;
1369
1370 12551
        CHECK_OBJ_NOTNULL(h2, H2_SESS_MAGIC);
1371 12551
        CHECK_OBJ_NOTNULL(r2, H2_REQ_MAGIC);
1372 12551
        Lck_AssertHeld(&h2->sess->mtx);
1373
1374
        /* NB: when now is NAN, it means that h2_window_timeout was hit
1375
         * on a lock condwait operation.
1376
         */
1377 12551
        if (isnan(now))
1378 21
                AN(r2->t_winupd);
1379
1380 12551
        if (h2->error != NULL && h2->error->connection &&
1381 0
            !h2->error->send_goaway)
1382 0
                return (h2->error);
1383
1384 12551
        if (r2->t_winupd == 0 && r2->t_send == 0)
1385 11890
                return (NULL);
1386
1387 661
        if (isnan(now) || (r2->t_winupd != 0 &&
1388 577
            now > r2->t_winupd + cache_param->h2_window_timeout)) {
1389 84
                VSLb(h2->vsl, SLT_Debug,
1390 42
                     "H2: stream %u: Hit h2_window_timeout", r2->stream);
1391 42
                return (H2SE_BROKE_WINDOW);
1392
        }
1393
1394 1238
        if (r2->t_send != 0 &&
1395 619
            now > r2->t_send + SESS_TMO(h2->sess, send_timeout)) {
1396 84
                VSLb(h2->vsl, SLT_Debug,
1397 42
                     "H2: stream %u: Hit send_timeout", r2->stream);
1398 42
                return (H2SE_CANCEL);
1399
        }
1400
1401 577
        if (due == NULL)
1402 220
                return (NULL);
1403
1404
#define deadline(ref, var, add)                         \
1405
        if ((var) != 0 && ((t = (var) + (add)) < ref))  \
1406
                ref = t
1407
1408 357
        deadline(*due, r2->t_winupd, cache_param->h2_window_timeout);
1409 357
        deadline(*due, r2->t_send, SESS_TMO(h2->sess, send_timeout));
1410
1411
#undef deadline
1412
1413 357
        return (NULL);
1414 12551
}
1415
1416
static h2_error
1417 12289
h2_stream_tmo_unlocked(struct h2_sess *h2, const struct h2_req *r2, vtim_real *due)
1418
{
1419
        h2_error h2e;
1420
1421 12289
        Lck_Lock(&h2->sess->mtx);
1422 12289
        h2e = h2_stream_tmo(h2, r2, h2->sess->t_idle, due);
1423 12289
        Lck_Unlock(&h2->sess->mtx);
1424
1425 12289
        return (h2e);
1426
}
1427
1428
/*
1429
 * This is the janitorial task of cleaning up any closed & refused
1430
 * streams, and checking if the session is timed out.
1431
 */
1432
static h2_error
1433 21963
h2_sweep(struct worker *wrk, struct h2_sess *h2, vtim_real *due)
1434
{
1435
        struct h2_req *r2, *r22;
1436
        h2_error h2e, tmo;
1437
1438 21963
        ASSERT_RXTHR(h2);
1439
1440 21963
        h2e = h2->error;
1441
1442 21963
        h2->do_sweep = 0;
1443 57013
        VTAILQ_FOREACH_SAFE(r2, &h2->streams, list, r22) {
1444 35050
                if (r2 == h2->req0) {
1445 21963
                        assert (r2->state == H2_S_IDLE);
1446 21963
                        continue;
1447
                }
1448 13087
                switch (r2->state) {
1449
                case H2_S_CLOSED:
1450 693
                        AZ(r2->scheduled);
1451 693
                        h2_del_req(wrk, r2);
1452 693
                        break;
1453
                case H2_S_CLOS_REM:
1454 4767
                        if (!r2->scheduled) {
1455 105
                                H2_Send_Get(wrk, h2, h2->req0);
1456 105
                                H2_Send_RST(wrk, h2, h2->req0, r2->stream,
1457
                                    H2SE_REFUSED_STREAM);
1458 105
                                H2_Send_Rel(h2, h2->req0);
1459 105
                                h2_del_req(wrk, r2);
1460 105
                                continue;
1461
                        }
1462
                        /* FALLTHROUGH */
1463
                case H2_S_CLOS_LOC:
1464
                case H2_S_OPEN:
1465 12289
                        tmo = h2_stream_tmo_unlocked(h2, r2, due);
1466 12289
                        if (h2e == NULL)
1467 12289
                                h2e = tmo;
1468 12289
                        break;
1469 0
                case H2_S_IDLE:
1470
                        /* Current code make this unreachable: h2_new_req is
1471
                         * only called inside h2_rx_headers, which immediately
1472
                         * sets the new stream state to H2_S_OPEN */
1473
                        /* FALLTHROUGH */
1474
                default:
1475 0
                        WRONG("Wrong h2 stream state");
1476 0
                        break;
1477
                }
1478 12982
        }
1479 21963
        return (h2e);
1480
}
1481
1482
/*
1483
 * if we have received end_headers, the new request is started
1484
 * if we have not received end_stream, DATA frames are expected later
1485
 *
1486
 * neither of these make much sense to output here
1487
 *
1488
 * goaway currently is always 0, see #4285
1489
 */
1490
static void
1491 2352
h2_htc_debug(enum htc_status_e hs, struct h2_sess *h2)
1492
{
1493
        const char *s, *r;
1494
1495 2352
        if (LIKELY(VSL_tag_is_masked(SLT_Debug)))
1496 0
                return;
1497
1498 2352
        HTC_Status(hs, &s, &r);
1499 4704
        H2S_Lock_VSLb(h2, SLT_Debug, "H2: HTC %s (%s) frame=%s goaway=%d",
1500 2352
            s, r, h2->htc->rxbuf_b == h2->htc->rxbuf_e ? "complete" : "partial",
1501 2352
            h2->goaway);
1502 2352
}
1503
1504
/***********************************************************************
1505
 * Called in loop from h2_new_session()
1506
 */
1507
1508
#define H2_FRAME(l,U,...) const struct h2_frame_s H2_F_##U[1] = \
1509
    {{ #U, h2_rx_##l, __VA_ARGS__ }};
1510
#include "tbl/h2_frames.h"
1511
1512
static const h2_frame h2flist[] = {
1513
#define H2_FRAME(l,U,t,...) [t] = H2_F_##U,
1514
#include "tbl/h2_frames.h"
1515
};
1516
1517
#define H2FMAX vcountof(h2flist)
1518
1519
int
1520 21231
h2_rxframe(struct worker *wrk, struct h2_sess *h2)
1521
{
1522
        enum htc_status_e hs;
1523
        vtim_real due;
1524
        h2_frame h2f;
1525
        h2_error h2e;
1526
        const char *s, *r;
1527
1528 21231
        ASSERT_RXTHR(h2);
1529
1530 21231
        if (h2->goaway && h2->open_streams == 0) {
1531
                // h2 WS must always be released before returning
1532 0
                WS_ReleaseP(h2->ws, h2->htc->rxbuf_b);
1533 0
                return (0);
1534
        }
1535
1536 21231
        due = h2->sess->t_idle + SESS_TMO(h2->sess, timeout_idle);
1537 21231
        h2e = h2_sweep(wrk, h2, &due);
1538
1539
        /*
1540
         * due is now the next expiry of: timeout_idle, h2_window_timeout,
1541
         * send_timeout
1542
         *
1543
         * we add 2ms to ensure the read does not return too early for the
1544
         * HTC_S_MORE sweep to hit the same expiring timeout, becuase
1545
         * HTC_RxStuff uses poll(), which has a granularity of 1ms.
1546
         */
1547 21231
        due += 0.002;
1548
1549 21231
        if (h2e != NULL && h2e->connection) {
1550 0
                h2->error = h2e;
1551 0
                h2_tx_goaway(wrk, h2, h2e);
1552 0
                WS_ReleaseP(h2->ws, h2->htc->rxbuf_b);
1553 0
                return (0);
1554
        }
1555
1556 21231
        h2->t1 = NAN;
1557 21231
        VTCP_blocking(*h2->htc->rfd);
1558 42462
        hs = HTC_RxStuff(h2->htc, h2_frame_complete, &h2->t1, NULL, NAN,
1559 21231
            due, NAN, h2->local_settings.max_frame_size + 9);
1560
1561 21231
        h2e = NULL;
1562 21231
        switch (hs) {
1563
        case HTC_S_EOF:
1564 2352
                h2_htc_debug(hs, h2);
1565 2352
                h2e = H2CE_NO_ERROR;
1566 2352
                break;
1567
        case HTC_S_COMPLETE:
1568 18774
                h2->sess->t_idle = VTIM_real();
1569 18774
                if (h2->do_sweep)
1570 606
                        h2e = h2_sweep(wrk, h2, NULL);
1571 18774
                break;
1572
        case HTC_S_MORE:
1573 105
                h2->sess->t_idle = VTIM_real();
1574 105
                h2e = h2_sweep(wrk, h2, NULL);
1575
1576 105
                if (h2e == NULL && h2->open_streams == 0)
1577 63
                        h2e = H2CE_NO_ERROR;
1578 105
                break;
1579
        default:
1580 0
                HTC_Status(hs, &s, &r);
1581 0
                H2S_Lock_VSLb(h2, SLT_SessError, "H2: HTC %s (%s)", s, r);
1582 0
                h2e = H2CE_ENHANCE_YOUR_CALM;
1583 0
        }
1584
1585 21231
        if (h2e != NULL && h2e->connection) {
1586 2415
                h2->error = h2e;
1587 2415
                h2_tx_goaway(wrk, h2, h2e);
1588 2415
                return (0);
1589
        }
1590
1591 18816
        if (hs != HTC_S_COMPLETE) {
1592 42
                HTC_RxPipeline(h2->htc, h2->htc->rxbuf_b);
1593 42
                return (1);
1594
        }
1595
1596 18774
        h2->rxf_len = vbe32dec(h2->htc->rxbuf_b) >> 8;
1597 18774
        h2->rxf_type = h2->htc->rxbuf_b[3];
1598 18774
        h2->rxf_flags = h2->htc->rxbuf_b[4];
1599 18774
        h2->rxf_stream = vbe32dec(h2->htc->rxbuf_b + 5);
1600 18774
        h2->rxf_stream &= ~(1LU<<31);                   // rfc7540,l,690,692
1601 18774
        h2->rxf_data = (void*)(h2->htc->rxbuf_b + 9);
1602
        /* XXX: later full DATA will not be rx'ed yet. */
1603 18774
        HTC_RxPipeline(h2->htc, h2->htc->rxbuf_b + h2->rxf_len + 9);
1604
1605 18774
        h2_vsl_frame(h2, h2->htc->rxbuf_b, 9L + h2->rxf_len);
1606 18774
        h2->srq->acct.req_hdrbytes += 9;
1607
1608 18774
        if (h2->rxf_type >= H2FMAX) {
1609
                // rfc7540,l,679,681
1610
                // XXX: later, drain rest of frame
1611 21
                h2->bogosity++;
1612 42
                H2S_Lock_VSLb(h2, SLT_Debug,
1613
                    "H2: Unknown frame type 0x%02x (ignored)",
1614 21
                    (uint8_t)h2->rxf_type);
1615 21
                h2->srq->acct.req_bodybytes += h2->rxf_len;
1616 21
                return (1);
1617
        }
1618 18753
        h2f = h2flist[h2->rxf_type];
1619
1620 18753
        AN(h2f->name);
1621 18753
        AN(h2f->rxfunc);
1622 18753
        if (h2f->overhead)
1623 7665
                h2->srq->acct.req_bodybytes += h2->rxf_len;
1624
1625 18753
        if (h2->rxf_flags & ~h2f->flags) {
1626
                // rfc7540,l,687,688
1627 42
                h2->bogosity++;
1628 84
                H2S_Lock_VSLb(h2, SLT_Debug,
1629
                    "H2: Unknown flags 0x%02x on %s (ignored)",
1630 42
                    (uint8_t)h2->rxf_flags & ~h2f->flags, h2f->name);
1631 42
                h2->rxf_flags &= h2f->flags;
1632 42
        }
1633
1634 18753
        h2e = h2_procframe(wrk, h2, h2f);
1635 18753
        if (h2->error == NULL && h2e != NULL) {
1636 651
                h2->error = h2e;
1637 651
                h2_tx_goaway(wrk, h2, h2e);
1638 651
        }
1639
1640 18753
        return (h2->error != NULL ? 0 : 1);
1641 21231
}