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