Coverage Report

Created: 2025-08-26 06:35

/src/h2o/lib/http2/connection.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Fastly, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a copy
5
 * of this software and associated documentation files (the "Software"), to
6
 * deal in the Software without restriction, including without limitation the
7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8
 * sell copies of the Software, and to permit persons to whom the Software is
9
 * furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in
12
 * all copies or substantial portions of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20
 * IN THE SOFTWARE.
21
 */
22
#include <inttypes.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include "h2o.h"
26
#include "h2o/hpack.h"
27
#include "h2o/http1.h"
28
#include "h2o/http2.h"
29
#include "h2o/http2_internal.h"
30
#include "h2o/absprio.h"
31
#include "../probes_.h"
32
33
static const h2o_iovec_t CONNECTION_PREFACE = {H2O_STRLIT("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")};
34
35
h2o_buffer_prototype_t h2o_http2_wbuf_buffer_prototype = {{H2O_HTTP2_DEFAULT_OUTBUF_SIZE}};
36
37
static void update_stream_input_window(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, size_t bytes);
38
static void proceed_request(h2o_req_t *req, const char *errstr);
39
static void initiate_graceful_shutdown(h2o_conn_t *_conn);
40
static void close_connection_now(h2o_http2_conn_t *conn);
41
static int close_connection(h2o_http2_conn_t *conn);
42
static ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc);
43
static void do_emit_writereq(h2o_http2_conn_t *conn);
44
static void on_read(h2o_socket_t *sock, const char *err);
45
static void push_path(h2o_req_t *src_req, const char *abspath, size_t abspath_len, int is_critical);
46
static int foreach_request(h2o_conn_t *_conn, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata);
47
static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum);
48
49
static int is_idle_stream_id(h2o_http2_conn_t *conn, uint32_t stream_id)
50
2.10k
{
51
2.10k
    return (h2o_http2_stream_is_push(stream_id) ? conn->push_stream_ids.max_open : conn->pull_stream_ids.max_open) < stream_id;
52
2.10k
}
53
54
static void enqueue_goaway(h2o_http2_conn_t *conn, int errnum, h2o_iovec_t additional_data)
55
2.35k
{
56
2.35k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
57
        /* http2 spec allows sending GOAWAY more than once (for one reason since errors may arise after sending the first one) */
58
2.35k
        h2o_http2_encode_goaway_frame(&conn->_write.buf, conn->pull_stream_ids.max_open, errnum, additional_data);
59
2.35k
        h2o_http2_conn_request_write(conn);
60
2.35k
        conn->state = H2O_HTTP2_CONN_STATE_HALF_CLOSED;
61
2.35k
    }
62
2.35k
}
63
64
static void enqueue_server_preface(h2o_http2_conn_t *conn)
65
4.98k
{
66
    /* Send settings and initial window update */
67
4.98k
    h2o_http2_settings_kvpair_t settings[] = {
68
4.98k
        {H2O_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, conn->super.ctx->globalconf->http2.max_streams},
69
4.98k
        {H2O_HTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL, 1}};
70
4.98k
    h2o_http2_encode_settings_frame(&conn->_write.buf, settings, PTLS_ELEMENTSOF(settings));
71
4.98k
    h2o_http2_encode_window_update_frame(
72
4.98k
        &conn->_write.buf, 0, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE - H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
73
4.98k
}
74
75
static void graceful_shutdown_close_straggler(h2o_timer_t *entry)
76
0
{
77
0
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _graceful_shutdown_timeout, entry);
78
    /* We've sent two GOAWAY frames, close the remaining connections */
79
0
    close_connection(conn);
80
0
}
81
82
static void graceful_shutdown_resend_goaway(h2o_timer_t *entry)
83
0
{
84
0
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _graceful_shutdown_timeout, entry);
85
86
0
    if (conn->state < H2O_HTTP2_CONN_STATE_HALF_CLOSED) {
87
0
        enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, (h2o_iovec_t){NULL});
88
89
        /* After waiting a second, we still have an active connection. If configured, wait one
90
         * final timeout before closing the connection */
91
0
        if (conn->super.ctx->globalconf->http2.graceful_shutdown_timeout > 0) {
92
0
            conn->_graceful_shutdown_timeout.cb = graceful_shutdown_close_straggler;
93
0
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.graceful_shutdown_timeout,
94
0
                           &conn->_graceful_shutdown_timeout);
95
0
        }
96
0
    }
97
0
}
98
99
static void close_idle_connection(h2o_conn_t *_conn)
100
0
{
101
0
    initiate_graceful_shutdown(_conn);
102
0
}
103
104
static void initiate_graceful_shutdown(h2o_conn_t *_conn)
105
0
{
106
0
    h2o_conn_set_state(_conn, H2O_CONN_STATE_SHUTDOWN);
107
108
    /* draft-16 6.8
109
     * A server that is attempting to gracefully shut down a connection SHOULD send an initial GOAWAY frame with the last stream
110
     * identifier set to 231-1 and a NO_ERROR code. This signals to the client that a shutdown is imminent and that no further
111
     * requests can be initiated. After waiting at least one round trip time, the server can send another GOAWAY frame with an
112
     * updated last stream identifier. This ensures that a connection can be cleanly shut down without losing requests.
113
     */
114
115
0
    h2o_http2_conn_t *conn = (void *)_conn;
116
0
    assert(conn->_graceful_shutdown_timeout.cb == NULL);
117
0
    conn->_graceful_shutdown_timeout.cb = graceful_shutdown_resend_goaway;
118
119
0
    if (conn->state < H2O_HTTP2_CONN_STATE_HALF_CLOSED) {
120
0
        h2o_http2_encode_goaway_frame(&conn->_write.buf, INT32_MAX, H2O_HTTP2_ERROR_NONE,
121
0
                                      (h2o_iovec_t){H2O_STRLIT("graceful shutdown")});
122
0
        h2o_http2_conn_request_write(conn);
123
0
    }
124
125
0
    h2o_timer_link(conn->super.ctx->loop, 1000, &conn->_graceful_shutdown_timeout);
126
0
}
127
128
static void on_idle_timeout(h2o_timer_t *entry)
129
0
{
130
0
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _timeout_entry, entry);
131
0
    conn->super.ctx->http2.events.idle_timeouts++;
132
133
0
    if (conn->_write.buf_in_flight != NULL) {
134
0
        close_connection_now(conn);
135
0
    } else {
136
0
        enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, h2o_iovec_init(H2O_STRLIT("idle timeout")));
137
0
        close_connection(conn);
138
0
    }
139
0
}
140
141
static void update_idle_timeout(h2o_http2_conn_t *conn)
142
34.1k
{
143
    /* do nothing touch anything if write is in progress */
144
34.1k
    if (conn->_write.buf_in_flight != NULL) {
145
6
        assert(h2o_timer_is_linked(&conn->_timeout_entry));
146
6
        return;
147
6
    }
148
149
34.1k
    h2o_timer_unlink(&conn->_timeout_entry);
150
151
    /* always set idle timeout if TLS handshake is in progress */
152
34.1k
    if (conn->sock->ssl != NULL && h2o_socket_ssl_is_early_data(conn->sock))
153
0
        goto SetTimeout;
154
155
    /* no need to set timeout if pending requests exist */
156
34.1k
    if (conn->num_streams.blocked_by_server != 0)
157
2.41k
        return;
158
159
31.7k
SetTimeout:
160
31.7k
    conn->_timeout_entry.cb = on_idle_timeout;
161
31.7k
    h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.idle_timeout, &conn->_timeout_entry);
162
31.7k
}
163
164
static int can_run_requests(h2o_http2_conn_t *conn)
165
3.93k
{
166
3.93k
    return conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed <
167
3.93k
           conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
168
3.93k
}
169
170
static void process_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
171
3.89k
{
172
3.89k
    if (stream->req.proceed_req != NULL) {
173
139
        assert(
174
139
            !(stream->req_body.state == H2O_HTTP2_REQ_BODY_NONE || stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED));
175
139
        conn->num_streams._req_streaming_in_progress++;
176
139
        conn->super.ctx->http2.events.streaming_requests++;
177
139
        stream->req_body.streamed = 1;
178
139
        if (stream->req.is_tunnel_req)
179
0
            conn->num_streams.tunnel++;
180
139
        update_stream_input_window(conn, stream,
181
139
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
182
139
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
183
3.75k
    } else {
184
3.75k
        if (stream->state < H2O_HTTP2_STREAM_STATE_SEND_HEADERS) {
185
3.75k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
186
3.75k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
187
3.75k
        }
188
3.75k
    }
189
190
3.89k
    if (!h2o_http2_stream_is_push(stream->stream_id) && conn->pull_stream_ids.max_processed < stream->stream_id)
191
3.85k
        conn->pull_stream_ids.max_processed = stream->stream_id;
192
193
3.89k
    h2o_process_request(&stream->req);
194
3.89k
}
195
196
static void run_pending_requests(h2o_http2_conn_t *conn)
197
16.9k
{
198
16.9k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
199
1.40k
        return;
200
201
15.5k
    h2o_linklist_t *link, *lnext;
202
15.5k
    int ran_one_request;
203
204
15.5k
    do {
205
15.5k
        ran_one_request = 0;
206
207
19.5k
        for (link = conn->_pending_reqs.next; link != &conn->_pending_reqs && can_run_requests(conn); link = lnext) {
208
            /* fetch and detach a pending stream */
209
3.93k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, link);
210
211
3.93k
            lnext = link->next;
212
213
            /* handle no more than specified number of streaming requests at a time */
214
3.93k
            if (stream->req.proceed_req != NULL &&
215
3.93k
                conn->num_streams._req_streaming_in_progress - conn->num_streams.tunnel >=
216
178
                    conn->super.ctx->globalconf->http2.max_concurrent_streaming_requests_per_connection)
217
39
                continue;
218
219
            /* handle it */
220
3.89k
            h2o_linklist_unlink(&stream->_link);
221
3.89k
            ran_one_request = 1;
222
3.89k
            process_request(conn, stream);
223
3.89k
        }
224
225
15.5k
    } while (ran_one_request && !h2o_linklist_is_empty(&conn->_pending_reqs));
226
15.5k
}
227
228
static int reset_stream_if_disregarded(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
229
4.78k
{
230
4.78k
    if (!h2o_http2_stream_is_push(stream->stream_id) && stream->stream_id > conn->pull_stream_ids.max_open) {
231
        /* this stream is opened after sending GOAWAY, so ignore it */
232
0
        h2o_http2_stream_reset(conn, stream);
233
0
        return 1;
234
0
    }
235
4.78k
    return 0;
236
4.78k
}
237
238
static void execute_or_enqueue_request_core(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
239
3.91k
{
240
    /* TODO schedule the pending reqs using the scheduler */
241
3.91k
    h2o_linklist_insert(&conn->_pending_reqs, &stream->_link);
242
243
3.91k
    run_pending_requests(conn);
244
3.91k
    update_idle_timeout(conn);
245
3.91k
}
246
247
static void execute_or_enqueue_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
248
3.75k
{
249
3.75k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_REQ_PENDING);
250
251
3.75k
    if (reset_stream_if_disregarded(conn, stream))
252
0
        return;
253
254
3.75k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
255
3.75k
    if (!stream->blocked_by_server)
256
3.70k
        h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
257
3.75k
    execute_or_enqueue_request_core(conn, stream);
258
3.75k
}
259
260
void h2o_http2_conn_register_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
261
22.2k
{
262
22.2k
    khiter_t iter;
263
22.2k
    int r;
264
265
22.2k
    iter = kh_put(h2o_http2_stream_t, conn->streams, stream->stream_id, &r);
266
22.2k
    assert(iter != kh_end(conn->streams));
267
22.2k
    kh_val(conn->streams, iter) = stream;
268
22.2k
}
269
270
void h2o_http2_conn_preserve_stream_scheduler(h2o_http2_conn_t *conn, h2o_http2_stream_t *src)
271
22.2k
{
272
22.2k
    assert(h2o_http2_scheduler_is_open(&src->_scheduler));
273
274
22.2k
    h2o_http2_stream_t **dst = conn->_recently_closed_streams.streams + conn->_recently_closed_streams.next_slot;
275
22.2k
    if (++conn->_recently_closed_streams.next_slot == HTTP2_CLOSED_STREAM_PRIORITIES)
276
1.33k
        conn->_recently_closed_streams.next_slot = 0;
277
278
22.2k
    if (*dst != NULL) {
279
10.1k
        assert(h2o_http2_scheduler_is_open(&(*dst)->_scheduler));
280
10.1k
        h2o_http2_scheduler_close(&(*dst)->_scheduler);
281
12.1k
    } else {
282
12.1k
        *dst = h2o_mem_alloc(offsetof(h2o_http2_stream_t, _scheduler) + sizeof((*dst)->_scheduler));
283
12.1k
    }
284
285
22.2k
    (*dst)->stream_id = src->stream_id;
286
22.2k
    h2o_http2_scheduler_relocate(&(*dst)->_scheduler, &src->_scheduler);
287
22.2k
    h2o_http2_scheduler_deactivate(&(*dst)->_scheduler);
288
22.2k
}
289
290
static void set_req_body_state(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, enum en_h2o_req_body_state_t new_state)
291
1.00k
{
292
1.00k
    assert(stream->req_body.state < new_state); /* use `<` instead of `<=` as we think we only use the function that way, and
293
                                                 * setting CLOSE_DELIVERED twice causes unnecessary decrements */
294
1.00k
    switch (new_state) {
295
0
    case H2O_HTTP2_REQ_BODY_NONE:
296
0
        h2o_fatal("invalid state");
297
0
        break;
298
350
    case H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED:
299
350
        assert(stream->req.proceed_req == NULL);
300
350
        if (stream->req_body.streamed) {
301
139
            conn->num_streams._req_streaming_in_progress--;
302
139
            if (stream->req.is_tunnel_req)
303
0
                conn->num_streams.tunnel--;
304
139
        }
305
350
        break;
306
656
    default:
307
656
        break;
308
1.00k
    }
309
1.00k
    stream->req_body.state = new_state;
310
1.00k
}
311
312
void h2o_http2_conn_unregister_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
313
22.2k
{
314
22.2k
    h2o_http2_conn_preserve_stream_scheduler(conn, stream);
315
316
22.2k
    khiter_t iter = kh_get(h2o_http2_stream_t, conn->streams, stream->stream_id);
317
22.2k
    assert(iter != kh_end(conn->streams));
318
22.2k
    kh_del(h2o_http2_stream_t, conn->streams, iter);
319
320
22.2k
    if (stream->req_body.state != H2O_HTTP2_REQ_BODY_NONE && stream->req_body.state < H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED) {
321
255
        stream->req.proceed_req = NULL;
322
255
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
323
255
    }
324
325
22.2k
    if (stream->blocked_by_server)
326
151
        h2o_http2_stream_set_blocked_by_server(conn, stream, 0);
327
328
    /* Decrement reset_budget if the stream was reset by peer or by peer's invalid action, otherwise increment. By doing so, we
329
     * penalize connections that generate resets for >50% of requests. */
330
22.2k
    if (stream->reset_by_peer || stream->reset_by_peer_action) {
331
10.2k
        if (conn->dos_mitigation.reset_budget > 0)
332
8.84k
            --conn->dos_mitigation.reset_budget;
333
334
        /* setup process delay if we've just ran out of reset budget */
335
10.2k
        if (conn->dos_mitigation.reset_budget == 0 && conn->super.ctx->globalconf->http2.dos_delay != 0 &&
336
10.2k
            !h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
337
32
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.dos_delay, &conn->dos_mitigation.process_delay);
338
339
12.0k
    } else {
340
12.0k
        if (conn->dos_mitigation.reset_budget < conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection)
341
1.78k
            ++conn->dos_mitigation.reset_budget;
342
12.0k
    }
343
344
22.2k
    switch (stream->state) {
345
188
    case H2O_HTTP2_STREAM_STATE_RECV_BODY:
346
188
        if (h2o_linklist_is_linked(&stream->_link))
347
12
            h2o_linklist_unlink(&stream->_link);
348
    /* fallthru */
349
13.5k
    case H2O_HTTP2_STREAM_STATE_IDLE:
350
16.8k
    case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
351
16.8k
        assert(!h2o_linklist_is_linked(&stream->_link));
352
16.8k
        break;
353
16.8k
    case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
354
3
        assert(h2o_linklist_is_linked(&stream->_link));
355
3
        h2o_linklist_unlink(&stream->_link);
356
3
        break;
357
44
    case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
358
68
    case H2O_HTTP2_STREAM_STATE_SEND_BODY:
359
2.45k
    case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
360
5.40k
    case H2O_HTTP2_STREAM_STATE_END_STREAM:
361
5.40k
        if (h2o_linklist_is_linked(&stream->_link))
362
20
            h2o_linklist_unlink(&stream->_link);
363
5.40k
        break;
364
22.2k
    }
365
22.2k
    if (stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
366
19.2k
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
367
368
22.2k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
369
13.0k
        run_pending_requests(conn);
370
13.0k
        update_idle_timeout(conn);
371
13.0k
    }
372
22.2k
}
373
374
void close_connection_now(h2o_http2_conn_t *conn)
375
4.97k
{
376
    /* mark as is_closing here to prevent sending any more frames */
377
4.97k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
378
379
4.97k
    h2o_http2_stream_t *stream;
380
381
4.97k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
382
383
4.97k
    kh_foreach_value(conn->streams, stream, { h2o_http2_stream_close(conn, stream); });
384
385
4.97k
    assert(conn->num_streams.pull.open == 0);
386
4.97k
    assert(conn->num_streams.pull.half_closed == 0);
387
4.97k
    assert(conn->num_streams.pull.send_body == 0);
388
4.97k
    assert(conn->num_streams.push.half_closed == 0);
389
4.97k
    assert(conn->num_streams.push.send_body == 0);
390
4.97k
    assert(conn->num_streams.priority.open == 0);
391
4.97k
    assert(conn->num_streams.blocked_by_server == 0);
392
4.97k
    assert(conn->num_streams._req_streaming_in_progress == 0);
393
4.97k
    assert(conn->num_streams.tunnel == 0);
394
4.97k
    kh_destroy(h2o_http2_stream_t, conn->streams);
395
4.97k
    assert(conn->_http1_req_input == NULL);
396
4.97k
    h2o_hpack_dispose_header_table(&conn->_input_header_table);
397
4.97k
    h2o_hpack_dispose_header_table(&conn->_output_header_table);
398
4.97k
    assert(h2o_linklist_is_empty(&conn->_pending_reqs));
399
4.97k
    h2o_timer_unlink(&conn->_timeout_entry);
400
401
4.97k
    if (h2o_timer_is_linked(&conn->_graceful_shutdown_timeout))
402
0
        h2o_timer_unlink(&conn->_graceful_shutdown_timeout);
403
404
4.97k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
405
30
        h2o_timer_unlink(&conn->dos_mitigation.process_delay);
406
407
4.97k
    h2o_buffer_dispose(&conn->_write.buf);
408
4.97k
    if (conn->_write.buf_in_flight != NULL)
409
5
        h2o_buffer_dispose(&conn->_write.buf_in_flight);
410
4.97k
    {
411
4.97k
        size_t i;
412
17.1k
        for (i = 0; i < sizeof(conn->_recently_closed_streams.streams) / sizeof(conn->_recently_closed_streams.streams[0]); ++i) {
413
16.6k
            h2o_http2_stream_t *closed_stream = conn->_recently_closed_streams.streams[i];
414
16.6k
            if (closed_stream == NULL)
415
4.48k
                break;
416
12.1k
            assert(h2o_http2_scheduler_is_open(&closed_stream->_scheduler));
417
12.1k
            h2o_http2_scheduler_close(&closed_stream->_scheduler);
418
12.1k
            free(closed_stream);
419
12.1k
        }
420
4.97k
    }
421
4.97k
    h2o_http2_scheduler_dispose(&conn->scheduler);
422
4.97k
    assert(h2o_linklist_is_empty(&conn->_write.streams_to_proceed));
423
4.97k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
424
4.97k
    if (conn->_headers_unparsed != NULL)
425
136
        h2o_buffer_dispose(&conn->_headers_unparsed);
426
4.97k
    if (conn->push_memo != NULL)
427
0
        h2o_cache_destroy(conn->push_memo);
428
4.97k
    if (conn->casper != NULL)
429
0
        h2o_http2_casper_destroy(conn->casper);
430
431
4.97k
    if (conn->sock != NULL)
432
4.97k
        h2o_socket_close(conn->sock);
433
434
4.97k
    h2o_destroy_connection(&conn->super);
435
4.97k
}
436
437
int close_connection(h2o_http2_conn_t *conn)
438
9.71k
{
439
9.71k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
440
441
9.71k
    if (conn->_write.buf_in_flight != NULL || h2o_timer_is_linked(&conn->_write.timeout_entry)) {
442
        /* there is a pending write, let on_write_complete actually close the connection */
443
4.96k
    } else {
444
4.96k
        close_connection_now(conn);
445
4.96k
        return -1;
446
4.96k
    }
447
4.74k
    return 0;
448
9.71k
}
449
450
static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum)
451
12.4k
{
452
12.4k
    assert(stream_id != 0);
453
12.4k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
454
455
12.4k
    conn->super.ctx->http2.events.protocol_level_errors[-errnum]++;
456
457
12.4k
    h2o_http2_encode_rst_stream_frame(&conn->_write.buf, stream_id, -errnum);
458
12.4k
    h2o_http2_conn_request_write(conn);
459
12.4k
}
460
461
static void request_gathered_write(h2o_http2_conn_t *conn)
462
37.6k
{
463
37.6k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
464
37.6k
    if (!h2o_socket_is_writing(conn->sock) && !h2o_timer_is_linked(&conn->_write.timeout_entry)) {
465
6.09k
        h2o_timer_link(conn->super.ctx->loop, 0, &conn->_write.timeout_entry);
466
6.09k
    }
467
37.6k
}
468
469
static int update_stream_output_window(h2o_http2_stream_t *stream, ssize_t delta)
470
3.37k
{
471
3.37k
    ssize_t cur = h2o_http2_window_get_avail(&stream->output_window);
472
3.37k
    if (h2o_http2_window_update(&stream->output_window, delta) != 0)
473
13
        return -1;
474
3.36k
    if (cur <= 0 && h2o_http2_window_get_avail(&stream->output_window) > 0 &&
475
3.36k
        (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL)) {
476
457
        assert(!h2o_linklist_is_linked(&stream->_link));
477
457
        h2o_http2_scheduler_activate(&stream->_scheduler);
478
457
    }
479
3.36k
    return 0;
480
3.36k
}
481
482
static void write_streaming_body(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
483
71
{
484
71
    int is_end_stream = 0;
485
486
71
    assert(stream->req.entity.base == NULL);
487
488
    /* check state as well as update */
489
71
    switch (stream->req_body.state) {
490
0
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
491
50
    case H2O_HTTP2_REQ_BODY_OPEN:
492
50
        assert(stream->req_body.buf->size != 0);
493
50
        break;
494
50
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
495
21
        stream->req.proceed_req = NULL;
496
21
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
497
21
        is_end_stream = 1;
498
21
        break;
499
0
    default:
500
0
        h2o_fatal("unexpected req_body.state");
501
0
        break;
502
71
    }
503
504
    /* invoke write_req */
505
71
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
506
71
    if (stream->req.write_req.cb(stream->req.write_req.ctx, is_end_stream) != 0) {
507
0
        stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
508
0
        h2o_http2_stream_reset(conn, stream);
509
0
        return;
510
0
    }
511
512
    /* close the H2 stream if both sides are done */
513
71
    if (stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED && stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM)
514
1
        h2o_http2_stream_close(conn, stream);
515
71
}
516
517
static void handle_request_body_chunk(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, h2o_iovec_t payload, int is_end_stream)
518
1.03k
{
519
1.03k
    int is_first = 0;
520
521
1.03k
    switch (stream->req_body.state) {
522
283
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
523
283
        is_first = 1;
524
283
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
525
283
        break;
526
751
    case H2O_HTTP2_REQ_BODY_OPEN:
527
751
        break;
528
0
    default:
529
0
        h2o_fatal("unexpected req_body.state");
530
0
        break;
531
1.03k
    }
532
533
1.03k
    stream->req.req_body_bytes_received += payload.len;
534
535
    /* check size */
536
1.03k
    if (stream->req.req_body_bytes_received > conn->super.ctx->globalconf->max_request_entity_size) {
537
0
        stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_REFUSED_STREAM);
538
0
        h2o_http2_stream_reset(conn, stream);
539
0
        return;
540
0
    }
541
1.03k
    if (stream->req.content_length != SIZE_MAX) {
542
31
        size_t received = stream->req.req_body_bytes_received, cl = stream->req.content_length;
543
31
        if (is_end_stream ? (received != cl) : (received > cl)) {
544
8
            stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
545
8
            h2o_http2_stream_reset(conn, stream);
546
8
            return;
547
8
        }
548
31
    }
549
550
    /* update timer */
551
1.02k
    if (!stream->blocked_by_server)
552
341
        h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
553
554
    /* just reset the stream if the request is to be disregarded */
555
1.02k
    if (reset_stream_if_disregarded(conn, stream))
556
0
        return;
557
558
    /* update state, buffer the data */
559
1.02k
    int req_queued = stream->req.proceed_req != NULL;
560
1.02k
    if (is_end_stream) {
561
83
        if (stream->state < H2O_HTTP2_STREAM_STATE_REQ_PENDING) {
562
76
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
563
76
            if (stream->req.process_called)
564
22
                h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
565
76
        }
566
83
        if (stream->req.write_req.cb != NULL) {
567
23
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_QUEUED);
568
60
        } else {
569
60
            stream->req.proceed_req = NULL;
570
60
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
571
60
        }
572
83
    }
573
1.02k
    h2o_buffer_append(&stream->req_body.buf, payload.base, payload.len);
574
575
    /* if in request streaming mode: either submit the chunk or just keep it, and return */
576
1.02k
    if (stream->req_body.streamed) {
577
398
        if (stream->req.write_req.cb != NULL) {
578
267
            if (stream->req.entity.base == NULL)
579
64
                write_streaming_body(conn, stream);
580
267
        } else {
581
131
            stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
582
131
        }
583
398
        return;
584
398
    }
585
586
    /* not (yet) in streaming mode */
587
628
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
588
589
    /* when receiving first DATA frame... */
590
628
    if (is_first && !is_end_stream) {
591
        /* trigger request streaming mode if possible */
592
230
        if (h2o_req_can_stream_request(&stream->req)) {
593
154
            stream->req.proceed_req = proceed_request;
594
154
            execute_or_enqueue_request_core(conn, stream);
595
154
            return;
596
154
        }
597
        /* or, run in non-streaming mode (TODO elect input streams one by one for non-streaming case as well?) */
598
76
        update_stream_input_window(conn, stream,
599
76
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
600
76
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
601
76
    }
602
603
    /* run or queue the request when all input is available (and if the request has not been queued for streaming processing) */
604
474
    if (is_end_stream && !req_queued)
605
51
        execute_or_enqueue_request(conn, stream);
606
474
}
607
608
static int send_invalid_request_error(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const char *err_desc)
609
1.44k
{
610
    /* fast forward the stream's state so that we can start sending the response */
611
1.44k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
612
1.44k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
613
1.44k
    h2o_send_error_400(&stream->req, "Invalid Request", err_desc, 0);
614
1.44k
    return 0;
615
1.44k
}
616
617
static int handle_incoming_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const uint8_t *src, size_t len,
618
                                   const char **err_desc)
619
8.65k
{
620
8.65k
    int ret, header_exists_map = 0;
621
8.65k
    h2o_iovec_t expect = h2o_iovec_init(NULL, 0);
622
623
8.65k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS);
624
625
8.65k
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table,
626
8.65k
                                       &stream->req.input.method, &stream->req.input.scheme, &stream->req.input.authority,
627
8.65k
                                       &stream->req.input.path, &stream->req.upgrade, &stream->req.headers, &header_exists_map,
628
8.65k
                                       &stream->req.content_length, &expect, &stream->cache_digests, NULL, src, len, err_desc)) !=
629
8.65k
        0) {
630
        /* all errors except invalid-header-char are connection errors */
631
2.87k
        if (ret != H2O_HTTP2_ERROR_INVALID_HEADER_CHAR)
632
1.30k
            return ret;
633
2.87k
    }
634
635
7.34k
    h2o_probe_log_request(&stream->req, stream->stream_id);
636
637
    /* fixup the scheme so that it would never be a NULL pointer (note: checks below are done using `header_exists_map`) */
638
7.34k
    if (stream->req.input.scheme == NULL)
639
1.81k
        stream->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP;
640
641
7.34k
    int is_connect, must_exist_map, may_exist_map;
642
7.34k
    if (h2o_memis(stream->req.input.method.base, stream->req.input.method.len, H2O_STRLIT("CONNECT"))) {
643
0
        is_connect = 1;
644
0
        must_exist_map = H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
645
0
        may_exist_map = 0;
646
        /* extended connect looks like an ordinary request plus an upgrade token (:protocol) */
647
0
        if ((header_exists_map & H2O_HPACK_PARSE_HEADERS_PROTOCOL_EXISTS) != 0)
648
0
            must_exist_map |= H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS |
649
0
                              H2O_HPACK_PARSE_HEADERS_PROTOCOL_EXISTS;
650
7.34k
    } else if (h2o_memis(stream->req.input.method.base, stream->req.input.method.len, H2O_STRLIT("CONNECT-UDP"))) {
651
        /* Handling of masque draft-03. Method is CONNECT-UDP and :protocol is not used, so we set `:protocol` to "connect-udp" to
652
         * make it look like an upgrade. The method is preserved and can be used to distinguish between RFC 9298 version which uses
653
         * "CONNECT". The draft requires "masque" in `:scheme` but we need to support clients that put "https" there instead. */
654
0
        if (!((header_exists_map & H2O_HPACK_PARSE_HEADERS_PROTOCOL_EXISTS) == 0 &&
655
0
              h2o_memis(stream->req.input.path.base, stream->req.input.path.len, H2O_STRLIT("/")))) {
656
0
            ret = H2O_HTTP2_ERROR_PROTOCOL;
657
0
            goto SendRSTStream;
658
0
        }
659
0
        assert(stream->req.upgrade.base == NULL); /* otherwise PROTOCOL_EXISTS will be set */
660
0
        is_connect = 1;
661
0
        must_exist_map = H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS |
662
0
                         H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
663
0
        may_exist_map = 0;
664
7.34k
    } else {
665
        /* normal request */
666
7.34k
        is_connect = 0;
667
7.34k
        must_exist_map =
668
7.34k
            H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
669
7.34k
        may_exist_map = H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
670
7.34k
    }
671
672
    /* check that all MUST pseudo headers exist, and that there are no other pseudo headers than MUST or MAY */
673
7.34k
    if (!((header_exists_map & must_exist_map) == must_exist_map && (header_exists_map & ~(must_exist_map | may_exist_map)) == 0)) {
674
1.86k
        ret = H2O_HTTP2_ERROR_PROTOCOL;
675
1.86k
        goto SendRSTStream;
676
1.86k
    }
677
678
5.48k
    if (conn->num_streams.pull.open > conn->super.ctx->globalconf->http2.max_streams) {
679
0
        ret = H2O_HTTP2_ERROR_REFUSED_STREAM;
680
0
        goto SendRSTStream;
681
0
    }
682
683
    /* send 400 if the request contains invalid header characters */
684
5.48k
    if (ret != 0) {
685
1.44k
        assert(ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR);
686
1.44k
        return send_invalid_request_error(conn, stream, *err_desc);
687
1.44k
    }
688
689
    /* special handling of CONNECT method */
690
4.03k
    if (is_connect) {
691
        /* reject the request if content-length is specified or if the stream has been closed */
692
0
        if (stream->req.content_length != SIZE_MAX || stream->req_body.buf == NULL)
693
0
            return send_invalid_request_error(conn, stream, "Invalid CONNECT request");
694
        /* handle the request */
695
0
        stream->req.is_tunnel_req = 1;
696
0
        goto ProcessImmediately;
697
0
        return 0;
698
0
    }
699
700
    /* handle expect: 100-continue */
701
4.03k
    if (expect.base != NULL) {
702
99
        if (!h2o_lcstris(expect.base, expect.len, H2O_STRLIT("100-continue"))) {
703
99
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
704
99
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
705
99
            h2o_send_error_417(&stream->req, "Expectation Failed", "unknown expectation", 0);
706
99
            return 0;
707
99
        }
708
0
        if (h2o_req_should_forward_expect(&stream->req)) {
709
0
            h2o_add_header(&stream->req.pool, &stream->req.headers, H2O_TOKEN_EXPECT, NULL, expect.base, expect.len);
710
0
            goto ProcessImmediately;
711
0
        } else {
712
0
            stream->req.res.status = 100;
713
0
            h2o_send_informational(&stream->req);
714
0
        }
715
0
    }
716
717
    /* handle the request */
718
3.94k
    if (stream->req_body.buf == NULL) {
719
3.59k
        execute_or_enqueue_request(conn, stream);
720
3.59k
    } else {
721
350
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
722
350
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME);
723
350
    }
724
3.94k
    return 0;
725
726
1.86k
SendRSTStream:
727
1.86k
    stream->reset_by_peer_action = 1;
728
1.86k
    stream_send_error(conn, stream->stream_id, ret);
729
1.86k
    h2o_http2_stream_reset(conn, stream);
730
1.86k
    return 0;
731
732
0
ProcessImmediately:
733
0
    stream->req.entity = h2o_iovec_init("", 0); /* setting to non-NULL pointer indicates the presence of HTTP payload */
734
0
    stream->req.proceed_req = proceed_request;
735
0
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
736
0
    set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
737
0
    process_request(conn, stream);
738
0
    return 0;
739
4.03k
}
740
741
static int handle_trailing_headers(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const uint8_t *src, size_t len,
742
                                   const char **err_desc)
743
30
{
744
30
    size_t dummy_content_length;
745
30
    h2o_iovec_t dummy_expect = h2o_iovec_init(NULL, 0);
746
30
    int ret;
747
748
30
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table, NULL, NULL, NULL,
749
30
                                       NULL, NULL, &stream->req.headers, NULL, &dummy_content_length, &dummy_expect, NULL, NULL,
750
30
                                       src, len, err_desc)) != 0)
751
4
        return ret;
752
26
    handle_request_body_chunk(conn, stream, h2o_iovec_init(NULL, 0), 1);
753
26
    return 0;
754
30
}
755
756
static ssize_t expect_continuation_of_headers(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
757
758
{
758
758
    h2o_http2_frame_t frame;
759
758
    ssize_t ret;
760
758
    h2o_http2_stream_t *stream;
761
758
    int hret;
762
763
758
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
764
97
        return ret;
765
661
    if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
766
13
        *err_desc = "expected CONTINUATION frame";
767
13
        return H2O_HTTP2_ERROR_PROTOCOL;
768
13
    }
769
770
648
    if ((stream = h2o_http2_conn_get_stream(conn, frame.stream_id)) == NULL ||
771
648
        !(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY)) {
772
41
        *err_desc = "unexpected stream id in CONTINUATION frame";
773
41
        return H2O_HTTP2_ERROR_PROTOCOL;
774
41
    }
775
776
607
    if (conn->_headers_unparsed->size + frame.length <= H2O_MAX_REQLEN) {
777
607
        h2o_buffer_reserve(&conn->_headers_unparsed, frame.length);
778
607
        memcpy(conn->_headers_unparsed->bytes + conn->_headers_unparsed->size, frame.payload, frame.length);
779
607
        conn->_headers_unparsed->size += frame.length;
780
781
607
        if ((frame.flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
782
5
            conn->_read_expect = expect_default;
783
5
            if (stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS) {
784
4
                hret = handle_incoming_request(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
785
4
                                               conn->_headers_unparsed->size, err_desc);
786
4
            } else {
787
1
                hret = handle_trailing_headers(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
788
1
                                               conn->_headers_unparsed->size, err_desc);
789
1
            }
790
5
            if (hret != 0)
791
3
                ret = hret;
792
5
            h2o_buffer_dispose(&conn->_headers_unparsed);
793
5
            conn->_headers_unparsed = NULL;
794
5
        }
795
607
    } else {
796
        /* request is too large (TODO log) */
797
0
        stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_REFUSED_STREAM);
798
0
        h2o_http2_stream_reset(conn, stream);
799
0
    }
800
801
607
    return ret;
802
648
}
803
804
static void send_window_update(h2o_http2_conn_t *conn, uint32_t stream_id, h2o_http2_window_t *window, size_t delta)
805
215
{
806
215
    assert(delta <= INT32_MAX);
807
215
    h2o_http2_encode_window_update_frame(&conn->_write.buf, stream_id, (int32_t)delta);
808
215
    h2o_http2_conn_request_write(conn);
809
215
    h2o_http2_window_update(window, delta);
810
215
}
811
812
void update_stream_input_window(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, size_t delta)
813
997
{
814
997
    stream->input_window.bytes_unnotified += delta;
815
997
    if (stream->input_window.bytes_unnotified >= h2o_http2_window_get_avail(&stream->input_window.window)) {
816
215
        send_window_update(conn, stream->stream_id, &stream->input_window.window, stream->input_window.bytes_unnotified);
817
215
        stream->input_window.bytes_unnotified = 0;
818
215
    }
819
997
}
820
821
static void set_priority(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const h2o_http2_priority_t *priority,
822
                         int scheduler_is_open)
823
29.9k
{
824
29.9k
    h2o_http2_scheduler_node_t *parent_sched = NULL;
825
826
    /* determine the parent */
827
29.9k
    if (priority->dependency != 0) {
828
23.8k
        size_t i;
829
        /* First look for "recently closed" stream priorities.
830
         * This includes not only actually closed streams but also streams whose priority was modified
831
         * by H2O (e.g. through priority header).
832
         * By searching this list first, priority of a newly arrived stream can correctly refer to a priority
833
         * specified by client before. */
834
226k
        for (i = 0; i < HTTP2_CLOSED_STREAM_PRIORITIES; i++) {
835
207k
            if (conn->_recently_closed_streams.streams[i] &&
836
207k
                conn->_recently_closed_streams.streams[i]->stream_id == priority->dependency) {
837
4.82k
                parent_sched = &conn->_recently_closed_streams.streams[i]->_scheduler.node;
838
4.82k
                break;
839
4.82k
            }
840
207k
        }
841
23.8k
        if (parent_sched == NULL) {
842
            /* If the above search for recently closed streams did not succeed (either the parent was not closed
843
             * recently or modified priority), get the priority scheduler currently associated with the parent
844
             * stream.
845
             */
846
18.9k
            h2o_http2_stream_t *parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
847
18.9k
            if (parent_stream != NULL) {
848
3.56k
                parent_sched = &parent_stream->_scheduler.node;
849
15.4k
            } else {
850
                /* A dependency on a stream that is not currently in the tree - such as a stream in the "idle" state - results in
851
                 * that stream being given a default priority. (RFC 7540 5.3.1) It is possible for a stream to become closed while
852
                 * prioritization information that creates a dependency on that stream is in transit. If a stream identified in a
853
                 * dependency has no associated priority information, then the dependent stream is instead assigned a default
854
                 * priority. (RFC 7540 5.3.4)
855
                 */
856
15.4k
                parent_sched = &conn->scheduler;
857
15.4k
                priority = &h2o_http2_default_priority;
858
15.4k
            }
859
18.9k
        } else if (conn->is_chromium_dependency_tree) {
860
            /* Parent stream was found in the recently closed streams.
861
             * There are two possible cases for this.
862
             * 1) the parent stream was actually closed recently
863
             * 2) the parent stream's priority was modified by H2O (e.g. priority headers)
864
             * In case of 2), we might need to ignore the original dependency specified by the client,
865
             * if such a modification was a demotion (decreasing urgency/weight).
866
             *
867
             * This block handles case 2).
868
             */
869
2.05k
            h2o_http2_scheduler_openref_t *orig_parent_ref =
870
2.05k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched);
871
2.05k
            if (orig_parent_ref->weight < priority->weight || !priority->exclusive) {
872
                /* Turns out the client's dependency tree does not look like Chromium's */
873
5
                conn->is_chromium_dependency_tree = 0;
874
2.04k
            } else {
875
2.04k
                h2o_http2_stream_t *current_parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
876
2.04k
                if (current_parent_stream != NULL && orig_parent_ref->weight > current_parent_stream->_scheduler.weight &&
877
2.04k
                    priority->exclusive) {
878
                    /* Parent stream was demoted as a result of reprioritization via priority header.
879
                     * In this case, search the new parent from the root so that this stream is handled before
880
                     * the parent originally specified by the client.
881
                     * This entire logic assumes Chromium-type dependency tree, thus guarded by
882
                     * `chromium_dependency_tree` */
883
1.25k
                    parent_sched = h2o_http2_scheduler_find_parent_by_weight(&conn->scheduler, priority->weight);
884
1.25k
                    if (parent_sched == &stream->_scheduler.node) {
885
                        /* h2o_http2_scheduler_find_parent_by_weight may return the current node itself.
886
                         * In such a case, correct parent should be the parent of the current node. */
887
369
                        parent_sched = &current_parent_stream->_scheduler.node;
888
369
                    }
889
1.25k
                }
890
2.04k
            }
891
2.05k
        }
892
23.8k
    } else {
893
6.09k
        parent_sched = &conn->scheduler;
894
6.09k
    }
895
896
    /* Verify if the client's dependency tree looks like Chromium's */
897
29.9k
    if (priority->exclusive && conn->is_chromium_dependency_tree) {
898
4.01k
        int parent_weight = 256;
899
4.01k
        if (parent_sched->_parent != NULL && parent_sched->_parent->_parent != NULL) {
900
1.70k
            h2o_http2_scheduler_openref_t *parent_ref =
901
1.70k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched->_parent);
902
1.70k
            parent_weight = parent_ref->weight;
903
1.70k
        }
904
4.01k
        if (parent_weight < priority->weight) {
905
            /* Child's weight is bigger than parent's -- not Chromium */
906
10
            conn->is_chromium_dependency_tree = 0;
907
10
        }
908
25.8k
    } else {
909
        /* Stream doesn't have the exclusive flag -- not Chromium */
910
25.8k
        conn->is_chromium_dependency_tree = 0;
911
25.8k
    }
912
913
    /* setup the scheduler */
914
29.9k
    if (!scheduler_is_open) {
915
22.1k
        h2o_http2_scheduler_open(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
916
22.1k
    } else {
917
7.77k
        h2o_http2_scheduler_rebind(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
918
7.77k
    }
919
29.9k
}
920
921
void proceed_request(h2o_req_t *req, const char *errstr)
922
169
{
923
169
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
924
169
    h2o_http2_conn_t *conn = (h2o_http2_conn_t *)stream->req.conn;
925
926
169
    assert(stream->req_body.streamed);
927
928
    /* consume bytes */
929
169
    size_t written = stream->req.entity.len;
930
169
    h2o_buffer_consume(&stream->req_body.buf, written);
931
169
    stream->req.entity = h2o_iovec_init(NULL, 0);
932
933
    /* handle error */
934
169
    if (errstr != NULL) {
935
14
        stream->req.proceed_req = NULL;
936
14
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
937
14
        if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
938
            /* Send error and close. State disposal is delayed so as to avoid freeing `req` within this function, which might
939
             * trigger the destruction of the generator being the caller. */
940
14
            stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
941
14
            h2o_http2_scheduler_deactivate(&stream->_scheduler);
942
14
            if (!h2o_linklist_is_linked(&stream->_link))
943
14
                h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
944
14
            h2o_http2_stream_reset(conn, stream);
945
14
        }
946
14
        return;
947
14
    }
948
949
155
    switch (stream->req_body.state) {
950
153
    case H2O_HTTP2_REQ_BODY_OPEN:
951
153
        update_stream_input_window(conn, stream, written);
952
153
        if (stream->blocked_by_server && h2o_http2_window_get_avail(&stream->input_window.window) > 0) {
953
148
            h2o_http2_stream_set_blocked_by_server(conn, stream, 0);
954
148
            update_idle_timeout(conn);
955
148
        }
956
153
        if (stream->req_body.buf->size != 0)
957
5
            write_streaming_body(conn, stream);
958
153
        break;
959
2
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
960
2
        assert(written != 0);
961
2
        write_streaming_body(conn, stream);
962
2
        break;
963
0
    default:
964
0
        h2o_fatal("unexpected req_body_state");
965
155
    }
966
155
}
967
968
static int handle_data_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
969
8.70k
{
970
8.70k
    h2o_http2_data_payload_t payload;
971
8.70k
    h2o_http2_stream_t *stream;
972
8.70k
    int ret;
973
974
8.70k
    if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
975
32
        return ret;
976
977
    /* update connection-level window */
978
8.67k
    h2o_http2_window_consume_window(&conn->_input_window, frame->length);
979
8.67k
    if (h2o_http2_window_get_avail(&conn->_input_window) <= H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE / 2)
980
0
        send_window_update(conn, 0, &conn->_input_window,
981
0
                           H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE - h2o_http2_window_get_avail(&conn->_input_window));
982
983
    /* check state */
984
8.67k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
985
1.17k
        if (frame->stream_id <= conn->pull_stream_ids.max_open) {
986
1.03k
            stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
987
1.03k
            return 0;
988
1.03k
        } else {
989
147
            *err_desc = "invalid DATA frame";
990
147
            return H2O_HTTP2_ERROR_PROTOCOL;
991
147
        }
992
1.17k
    }
993
7.49k
    if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
994
7.49k
          stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN)) {
995
6.13k
        stream->reset_by_peer_action = 1;
996
6.13k
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
997
6.13k
        h2o_http2_stream_reset(conn, stream);
998
6.13k
        return 0;
999
6.13k
    }
1000
1001
    /* update stream-level window (doing it here could end up in sending multiple WINDOW_UPDATE frames if the receive window is
1002
     * fully-used, but no need to worry; in such case we'd be sending ACKs at a very fast rate anyways) */
1003
1.35k
    h2o_http2_window_consume_window(&stream->input_window.window, frame->length);
1004
1.35k
    if (frame->length != payload.length)
1005
629
        update_stream_input_window(conn, stream, frame->length - payload.length);
1006
1007
    /* actually handle the input */
1008
1.35k
    if (payload.length != 0 || (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0)
1009
1.00k
        handle_request_body_chunk(conn, stream, h2o_iovec_init(payload.data, payload.length),
1010
1.00k
                                  (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0);
1011
1012
1.35k
    return 0;
1013
7.49k
}
1014
1015
static int handle_headers_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1016
8.89k
{
1017
8.89k
    h2o_http2_headers_payload_t payload;
1018
8.89k
    h2o_http2_stream_t *stream;
1019
8.89k
    int ret;
1020
1021
    /* decode */
1022
8.89k
    if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
1023
17
        return ret;
1024
8.88k
    if ((frame->stream_id & 1) == 0) {
1025
14
        *err_desc = "invalid stream id in HEADERS frame";
1026
14
        return H2O_HTTP2_ERROR_PROTOCOL;
1027
14
    }
1028
8.86k
    if (frame->stream_id <= conn->pull_stream_ids.max_open) {
1029
79
        if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
1030
41
            *err_desc = "closed stream id in HEADERS frame";
1031
41
            return H2O_HTTP2_ERROR_STREAM_CLOSED;
1032
41
        }
1033
38
        if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
1034
38
              stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN)) {
1035
4
            *err_desc = "invalid stream id in HEADERS frame";
1036
4
            return H2O_HTTP2_ERROR_PROTOCOL;
1037
4
        }
1038
1039
        /* is a trailer */
1040
34
        if (stream->req.is_tunnel_req) {
1041
0
            *err_desc = "trailer cannot be used in a CONNECT request";
1042
0
            return H2O_HTTP2_ERROR_PROTOCOL;
1043
0
        }
1044
34
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0) {
1045
2
            *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
1046
2
            return H2O_HTTP2_ERROR_PROTOCOL;
1047
2
        }
1048
32
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0)
1049
3
            goto PREPARE_FOR_CONTINUATION;
1050
29
        return handle_trailing_headers(conn, stream, payload.headers, payload.headers_len, err_desc);
1051
32
    }
1052
8.78k
    if (frame->stream_id == payload.priority.dependency) {
1053
3
        *err_desc = "stream cannot depend on itself";
1054
3
        return H2O_HTTP2_ERROR_PROTOCOL;
1055
3
    }
1056
1057
    /* open or determine the stream and prepare */
1058
8.78k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1059
20
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PRIORITY) != 0) {
1060
17
            set_priority(conn, stream, &payload.priority, 1);
1061
17
            stream->received_priority = payload.priority;
1062
17
        }
1063
8.76k
    } else {
1064
8.76k
        conn->received_any_request = 1;
1065
8.76k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload.priority);
1066
8.76k
        set_priority(conn, stream, &payload.priority, 0);
1067
8.76k
    }
1068
8.78k
    h2o_http2_stream_prepare_for_request(conn, stream);
1069
1070
    /* setup container for request body if it is expected to arrive */
1071
8.78k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0)
1072
2.19k
        h2o_buffer_init(&stream->req_body.buf, &h2o_socket_buffer_prototype);
1073
1074
8.78k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
1075
        /* request headers are complete, handle it */
1076
8.64k
        return handle_incoming_request(conn, stream, payload.headers, payload.headers_len, err_desc);
1077
8.64k
    }
1078
1079
141
PREPARE_FOR_CONTINUATION:
1080
    /* request is not complete, store in buffer */
1081
141
    conn->_read_expect = expect_continuation_of_headers;
1082
141
    h2o_buffer_init(&conn->_headers_unparsed, &h2o_socket_buffer_prototype);
1083
141
    h2o_buffer_reserve(&conn->_headers_unparsed, payload.headers_len);
1084
141
    memcpy(conn->_headers_unparsed->bytes, payload.headers, payload.headers_len);
1085
141
    conn->_headers_unparsed->size = payload.headers_len;
1086
141
    return 0;
1087
8.78k
}
1088
1089
static int handle_priority_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1090
22.5k
{
1091
22.5k
    h2o_http2_priority_t payload;
1092
22.5k
    h2o_http2_stream_t *stream;
1093
22.5k
    int ret;
1094
1095
22.5k
    if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
1096
19
        return ret;
1097
22.5k
    if (frame->stream_id == payload.dependency) {
1098
3
        *err_desc = "stream cannot depend on itself";
1099
3
        return H2O_HTTP2_ERROR_PROTOCOL;
1100
3
    }
1101
1102
22.5k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1103
7.75k
        stream->received_priority = payload;
1104
        /* ignore priority changes to pushed streams with weight=257, since that is where we are trying to be smarter than the web
1105
         * browsers
1106
         */
1107
7.75k
        if (h2o_http2_scheduler_get_weight(&stream->_scheduler) != 257)
1108
7.75k
            set_priority(conn, stream, &payload, 1);
1109
14.7k
    } else {
1110
14.7k
        if (h2o_http2_stream_is_push(frame->stream_id)) {
1111
            /* Ignore PRIORITY frames for closed or idle pushed streams */
1112
959
            return 0;
1113
13.8k
        } else {
1114
            /* Ignore PRIORITY frames for closed pull streams */
1115
13.8k
            if (frame->stream_id <= conn->pull_stream_ids.max_open)
1116
437
                return 0;
1117
13.8k
        }
1118
13.3k
        if (conn->num_streams.priority.open >= conn->super.ctx->globalconf->http2.max_streams_for_priority) {
1119
2
            *err_desc = "too many streams in idle/closed state";
1120
            /* RFC 7540 10.5: An endpoint MAY treat activity that is suspicious as a connection error (Section 5.4.1) of type
1121
             * ENHANCE_YOUR_CALM.
1122
             */
1123
2
            return H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM;
1124
2
        }
1125
13.3k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload);
1126
13.3k
        set_priority(conn, stream, &payload, 0);
1127
13.3k
    }
1128
1129
21.1k
    return 0;
1130
22.5k
}
1131
1132
static void resume_send(h2o_http2_conn_t *conn)
1133
3.30k
{
1134
3.30k
    if (h2o_http2_conn_get_buffer_window(conn) <= 0)
1135
0
        return;
1136
#if 0 /* TODO reenable this check for performance? */
1137
    if (conn->scheduler.list.size == 0)
1138
        return;
1139
#endif
1140
3.30k
    request_gathered_write(conn);
1141
3.30k
}
1142
1143
static int handle_settings_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1144
3.96k
{
1145
3.96k
    if (frame->stream_id != 0) {
1146
35
        *err_desc = "invalid stream id in SETTINGS frame";
1147
35
        return H2O_HTTP2_ERROR_PROTOCOL;
1148
35
    }
1149
1150
3.92k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
1151
617
        if (frame->length != 0) {
1152
3
            *err_desc = "invalid SETTINGS frame (+ACK)";
1153
3
            return H2O_HTTP2_ERROR_FRAME_SIZE;
1154
3
        }
1155
614
        if (h2o_timeval_is_null(&conn->timestamps.settings_acked_at) && !h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1156
207
            conn->timestamps.settings_acked_at = h2o_gettimeofday(conn->super.ctx->loop);
1157
207
        }
1158
3.30k
    } else {
1159
3.30k
        uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
1160
3.30k
        int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
1161
3.30k
        if (ret != 0)
1162
120
            return ret;
1163
3.18k
        { /* schedule ack */
1164
3.18k
            h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
1165
3.18k
            h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
1166
3.18k
            conn->_write.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
1167
3.18k
            h2o_http2_conn_request_write(conn);
1168
3.18k
        }
1169
        /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
1170
3.18k
        if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
1171
1.70k
            ssize_t delta = (int32_t)conn->peer_settings.initial_window_size - (int32_t)prev_initial_window_size;
1172
1.70k
            h2o_http2_stream_t *stream;
1173
1.70k
            kh_foreach_value(conn->streams, stream, { update_stream_output_window(stream, delta); });
1174
1.70k
            resume_send(conn);
1175
1.70k
        }
1176
3.18k
    }
1177
1178
3.80k
    return 0;
1179
3.92k
}
1180
1181
static int handle_window_update_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1182
5.05k
{
1183
5.05k
    h2o_http2_window_update_payload_t payload;
1184
5.05k
    int ret, err_is_stream_level;
1185
1186
5.05k
    if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
1187
3.41k
        if (err_is_stream_level) {
1188
3.40k
            h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1189
3.40k
            if (stream != NULL) {
1190
2.20k
                stream->reset_by_peer_action = 1;
1191
2.20k
                h2o_http2_stream_reset(conn, stream);
1192
2.20k
            }
1193
3.40k
            stream_send_error(conn, frame->stream_id, ret);
1194
3.40k
            return 0;
1195
3.40k
        } else {
1196
10
            return ret;
1197
10
        }
1198
3.41k
    }
1199
1200
1.64k
    if (frame->stream_id == 0) {
1201
358
        if (h2o_http2_window_update(&conn->_write.window, payload.window_size_increment) != 0) {
1202
1
            *err_desc = "flow control window overflow";
1203
1
            return H2O_HTTP2_ERROR_FLOW_CONTROL;
1204
1
        }
1205
1.28k
    } else if (!is_idle_stream_id(conn, frame->stream_id)) {
1206
1.25k
        h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1207
1.25k
        if (stream != NULL) {
1208
304
            if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
1209
3
                stream->reset_by_peer_action = 1;
1210
3
                h2o_http2_stream_reset(conn, stream);
1211
3
                stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
1212
3
                return 0;
1213
3
            }
1214
304
        }
1215
1.25k
    } else {
1216
35
        *err_desc = "invalid stream id in WINDOW_UPDATE frame";
1217
35
        return H2O_HTTP2_ERROR_PROTOCOL;
1218
35
    }
1219
1220
1.60k
    resume_send(conn);
1221
1222
1.60k
    return 0;
1223
1.64k
}
1224
1225
static int handle_goaway_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1226
305
{
1227
305
    h2o_http2_goaway_payload_t payload;
1228
305
    int ret;
1229
1230
305
    if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
1231
37
        return ret;
1232
1233
    /* stop opening new push streams hereafter */
1234
268
    conn->push_stream_ids.max_open = 0x7ffffffe;
1235
1236
268
    return 0;
1237
305
}
1238
1239
static int handle_ping_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1240
487
{
1241
487
    h2o_http2_ping_payload_t payload;
1242
487
    int ret;
1243
1244
487
    if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
1245
32
        return ret;
1246
1247
455
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
1248
258
        h2o_http2_encode_ping_frame(&conn->_write.buf, 1, payload.data);
1249
258
        h2o_http2_conn_request_write(conn);
1250
258
    }
1251
1252
455
    return 0;
1253
487
}
1254
1255
static int handle_rst_stream_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1256
833
{
1257
833
    h2o_http2_rst_stream_payload_t payload;
1258
833
    h2o_http2_stream_t *stream;
1259
833
    int ret;
1260
1261
833
    if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
1262
14
        return ret;
1263
819
    if (is_idle_stream_id(conn, frame->stream_id)) {
1264
23
        *err_desc = "unexpected stream id in RST_STREAM frame";
1265
23
        return H2O_HTTP2_ERROR_PROTOCOL;
1266
23
    }
1267
1268
796
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL)
1269
792
        return 0;
1270
1271
    /* reset the stream */
1272
4
    stream->reset_by_peer = 1;
1273
4
    h2o_http2_stream_reset(conn, stream);
1274
1275
    /* TODO log */
1276
1277
4
    return 0;
1278
796
}
1279
1280
static int handle_push_promise_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1281
9
{
1282
9
    *err_desc = "received PUSH_PROMISE frame";
1283
9
    return H2O_HTTP2_ERROR_PROTOCOL;
1284
9
}
1285
1286
static int handle_invalid_continuation_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1287
2
{
1288
2
    *err_desc = "received invalid CONTINUATION frame";
1289
2
    return H2O_HTTP2_ERROR_PROTOCOL;
1290
2
}
1291
1292
ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1293
54.7k
{
1294
54.7k
    h2o_http2_frame_t frame;
1295
54.7k
    ssize_t ret;
1296
54.7k
    static int (*FRAME_HANDLERS[])(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc) = {
1297
54.7k
        handle_data_frame,                /* DATA */
1298
54.7k
        handle_headers_frame,             /* HEADERS */
1299
54.7k
        handle_priority_frame,            /* PRIORITY */
1300
54.7k
        handle_rst_stream_frame,          /* RST_STREAM */
1301
54.7k
        handle_settings_frame,            /* SETTINGS */
1302
54.7k
        handle_push_promise_frame,        /* PUSH_PROMISE */
1303
54.7k
        handle_ping_frame,                /* PING */
1304
54.7k
        handle_goaway_frame,              /* GOAWAY */
1305
54.7k
        handle_window_update_frame,       /* WINDOW_UPDATE */
1306
54.7k
        handle_invalid_continuation_frame /* CONTINUATION */
1307
54.7k
    };
1308
1309
54.7k
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
1310
2.34k
        return ret;
1311
1312
52.3k
    if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
1313
50.7k
        int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
1314
50.7k
        if (hret != 0)
1315
1.91k
            ret = hret;
1316
50.7k
    } else {
1317
1.59k
        H2O_PROBE_CONN(H2_UNKNOWN_FRAME_TYPE, &conn->super, frame.type);
1318
1.59k
    }
1319
1320
52.3k
    return ret;
1321
54.7k
}
1322
1323
static ssize_t expect_preface(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1324
4.98k
{
1325
4.98k
    if (len < CONNECTION_PREFACE.len) {
1326
59
        return H2O_HTTP2_ERROR_INCOMPLETE;
1327
59
    }
1328
4.92k
    if (memcmp(src, CONNECTION_PREFACE.base, CONNECTION_PREFACE.len) != 0) {
1329
54
        return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
1330
54
    }
1331
1332
4.87k
    {
1333
4.87k
        enqueue_server_preface(conn);
1334
4.87k
        if (conn->http2_origin_frame) {
1335
            /* write origin frame */
1336
0
            h2o_http2_encode_origin_frame(&conn->_write.buf, *conn->http2_origin_frame);
1337
0
        }
1338
4.87k
        if (h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1339
4.87k
            conn->timestamps.settings_sent_at = h2o_gettimeofday(conn->super.ctx->loop);
1340
4.87k
        }
1341
4.87k
        h2o_http2_conn_request_write(conn);
1342
4.87k
    }
1343
1344
4.87k
    conn->_read_expect = expect_default;
1345
4.87k
    return CONNECTION_PREFACE.len;
1346
4.92k
}
1347
1348
static int parse_input(h2o_http2_conn_t *conn)
1349
6.20k
{
1350
    /* handle the input */
1351
62.1k
    while (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && conn->sock->input->size != 0) {
1352
        /* process a frame */
1353
60.4k
        const char *err_desc = NULL;
1354
60.4k
        ssize_t ret = conn->_read_expect(conn, (uint8_t *)conn->sock->input->bytes, conn->sock->input->size, &err_desc);
1355
60.4k
        if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
1356
2.11k
            break;
1357
58.3k
        } else if (ret < 0) {
1358
2.40k
            if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
1359
2.35k
                enqueue_goaway(conn, (int)ret,
1360
2.35k
                               err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
1361
2.35k
            }
1362
2.40k
            return close_connection(conn);
1363
2.40k
        }
1364
        /* advance to the next frame */
1365
55.9k
        h2o_buffer_consume(&conn->sock->input, ret);
1366
55.9k
    }
1367
3.80k
    return 0;
1368
6.20k
}
1369
1370
static void on_read(h2o_socket_t *sock, const char *err)
1371
8.76k
{
1372
8.76k
    h2o_http2_conn_t *conn = sock->data;
1373
1374
8.76k
    if (err != NULL) {
1375
2.56k
        conn->super.ctx->http2.events.read_closed++;
1376
2.56k
        h2o_socket_read_stop(conn->sock);
1377
2.56k
        close_connection(conn);
1378
2.56k
        return;
1379
2.56k
    }
1380
1381
    /* dispatch requests blocked by 425 when TLS handshake is complete */
1382
6.20k
    if (!h2o_linklist_is_empty(&conn->early_data.blocked_streams)) {
1383
0
        assert(conn->sock->ssl != NULL);
1384
0
        if (!h2o_socket_ssl_is_early_data(conn->sock)) {
1385
0
            while (conn->early_data.blocked_streams.next != &conn->early_data.blocked_streams) {
1386
0
                h2o_http2_stream_t *stream =
1387
0
                    H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, conn->early_data.blocked_streams.next);
1388
0
                h2o_linklist_unlink(&stream->_link);
1389
0
                if (!stream->blocked_by_server)
1390
0
                    h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
1391
0
                h2o_replay_request(&stream->req);
1392
0
            }
1393
0
        }
1394
0
    }
1395
1396
6.20k
    if (parse_input(conn) != 0)
1397
42
        return;
1398
6.16k
    update_idle_timeout(conn);
1399
1400
    /* write immediately, if there is no write in flight and if pending write exists */
1401
6.16k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry)) {
1402
5.69k
        h2o_timer_unlink(&conn->_write.timeout_entry);
1403
5.69k
        do_emit_writereq(conn);
1404
5.69k
    }
1405
6.16k
}
1406
1407
static void on_upgrade_complete(void *_conn, h2o_socket_t *sock, size_t reqsize)
1408
116
{
1409
116
    h2o_http2_conn_t *conn = _conn;
1410
1411
116
    if (sock == NULL) {
1412
0
        close_connection(conn);
1413
0
        return;
1414
0
    }
1415
1416
116
    conn->sock = sock;
1417
116
    sock->data = conn;
1418
116
    conn->_http1_req_input = sock->input;
1419
116
    h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype);
1420
1421
116
    enqueue_server_preface(conn);
1422
116
    h2o_http2_conn_request_write(conn);
1423
1424
    /* setup inbound */
1425
116
    h2o_socket_read_start(conn->sock, on_read);
1426
1427
    /* handle the request */
1428
116
    execute_or_enqueue_request(conn, h2o_http2_conn_get_stream(conn, 1));
1429
1430
116
    if (conn->_http1_req_input->size > reqsize) {
1431
59
        size_t remaining_bytes = conn->_http1_req_input->size - reqsize;
1432
59
        h2o_buffer_reserve(&sock->input, remaining_bytes);
1433
59
        memcpy(sock->input->bytes, conn->_http1_req_input->bytes + reqsize, remaining_bytes);
1434
59
        sock->input->size += remaining_bytes;
1435
59
        on_read(conn->sock, NULL);
1436
59
    }
1437
116
}
1438
1439
static size_t bytes_in_buf(h2o_http2_conn_t *conn)
1440
34.2k
{
1441
34.2k
    size_t size = conn->_write.buf->size;
1442
34.2k
    if (conn->_write.buf_in_flight != 0)
1443
0
        size += conn->_write.buf_in_flight->size;
1444
34.2k
    return size;
1445
34.2k
}
1446
1447
void h2o_http2_conn_request_write(h2o_http2_conn_t *conn)
1448
34.3k
{
1449
34.3k
    if (conn->state == H2O_HTTP2_CONN_STATE_IS_CLOSING)
1450
0
        return;
1451
34.3k
    if (h2o_socket_is_reading(conn->sock) && bytes_in_buf(conn) >= H2O_HTTP2_DEFAULT_OUTBUF_SOFT_MAX_SIZE)
1452
0
        h2o_socket_read_stop(conn->sock);
1453
34.3k
    request_gathered_write(conn);
1454
34.3k
}
1455
1456
void h2o_http2_conn_register_for_proceed_callback(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
1457
5.51k
{
1458
5.51k
    h2o_http2_conn_request_write(conn);
1459
1460
5.51k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1461
5.51k
        if (h2o_http2_window_get_avail(&stream->output_window) > 0) {
1462
5.38k
            assert(!h2o_linklist_is_linked(&stream->_link));
1463
5.38k
            h2o_http2_scheduler_activate(&stream->_scheduler);
1464
5.38k
        }
1465
5.51k
    } else {
1466
0
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1467
0
    }
1468
5.51k
}
1469
1470
void h2o_http2_conn_register_for_replay(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
1471
0
{
1472
0
    if (conn->sock->ssl != NULL && h2o_socket_ssl_is_early_data(conn->sock)) {
1473
0
        h2o_linklist_insert(&conn->early_data.blocked_streams, &stream->_link);
1474
0
    } else {
1475
0
        h2o_replay_request_deferred(&stream->req);
1476
0
    }
1477
0
}
1478
1479
static void on_notify_write(h2o_socket_t *sock, const char *err)
1480
23
{
1481
23
    h2o_http2_conn_t *conn = sock->data;
1482
1483
23
    if (err != NULL) {
1484
0
        close_connection_now(conn);
1485
0
        return;
1486
0
    }
1487
23
    do_emit_writereq(conn);
1488
23
}
1489
1490
static void on_write_complete(h2o_socket_t *sock, const char *err)
1491
5.98k
{
1492
5.98k
    h2o_http2_conn_t *conn = sock->data;
1493
1494
5.98k
    assert(conn->_write.buf_in_flight != NULL);
1495
1496
    /* close by error if necessary */
1497
5.98k
    if (err != NULL) {
1498
5
        conn->super.ctx->http2.events.write_closed++;
1499
5
        close_connection_now(conn);
1500
5
        return;
1501
5
    }
1502
1503
    /* reset the other memory pool */
1504
5.98k
    h2o_buffer_dispose(&conn->_write.buf_in_flight);
1505
5.98k
    assert(conn->_write.buf_in_flight == NULL);
1506
1507
    /* call the proceed callback of the streams that have been flushed (while unlinking them from the list) */
1508
5.98k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1509
6.69k
        while (!h2o_linklist_is_empty(&conn->_write.streams_to_proceed)) {
1510
3.08k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, conn->_write.streams_to_proceed.next);
1511
3.08k
            assert(!h2o_http2_stream_has_pending_data(stream));
1512
3.08k
            h2o_linklist_unlink(&stream->_link);
1513
3.08k
            h2o_http2_stream_proceed(conn, stream);
1514
3.08k
        }
1515
3.61k
    }
1516
1517
    /* update the timeout now that the states have been updated */
1518
5.98k
    update_idle_timeout(conn);
1519
1520
    /* cancel the write callback if scheduled (as the generator may have scheduled a write just before this function gets called) */
1521
5.98k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry))
1522
26
        h2o_timer_unlink(&conn->_write.timeout_entry);
1523
1524
5.98k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1525
3.61k
        if (!h2o_socket_is_reading(conn->sock) && bytes_in_buf(conn) < H2O_HTTP2_DEFAULT_OUTBUF_SOFT_MAX_SIZE)
1526
0
            h2o_socket_read_start(conn->sock, on_read);
1527
3.61k
    }
1528
1529
5.98k
#if !H2O_USE_LIBUV
1530
5.98k
    if (conn->state == H2O_HTTP2_CONN_STATE_OPEN) {
1531
3.61k
        if (conn->_write.buf->size != 0 || h2o_http2_scheduler_is_active(&conn->scheduler))
1532
26
            h2o_socket_notify_write(sock, on_notify_write);
1533
3.61k
        return;
1534
3.61k
    }
1535
2.37k
#endif
1536
1537
    /* write more, if possible */
1538
2.37k
    do_emit_writereq(conn);
1539
2.37k
}
1540
1541
static int emit_writereq_of_openref(h2o_http2_scheduler_openref_t *ref, int *still_is_active, void *cb_arg)
1542
3.59k
{
1543
3.59k
    h2o_http2_conn_t *conn = cb_arg;
1544
3.59k
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _scheduler, ref);
1545
1546
3.59k
    assert(h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL);
1547
1548
3.59k
    *still_is_active = 0;
1549
1550
3.59k
    h2o_http2_stream_send_pending_data(conn, stream);
1551
3.59k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1552
507
        if (h2o_http2_window_get_avail(&stream->output_window) <= 0) {
1553
            /* is blocked */
1554
507
        } else {
1555
0
            *still_is_active = 1;
1556
0
        }
1557
3.08k
    } else {
1558
3.08k
        if (stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM) {
1559
2.91k
            h2o_iovec_t server_timing;
1560
2.91k
            if (stream->req.send_server_timing &&
1561
2.91k
                (server_timing = h2o_build_server_timing_trailer(&stream->req, NULL, 0, NULL, 0)).len != 0) {
1562
0
                static const h2o_iovec_t name = {H2O_STRLIT("server-timing")};
1563
0
                h2o_vector_reserve(&stream->req.pool, &stream->req.res.trailers, stream->req.res.trailers.size + 1);
1564
0
                stream->req.res.trailers.entries[stream->req.res.trailers.size++] =
1565
0
                    (h2o_header_t){(h2o_iovec_t *)&name, NULL, server_timing};
1566
0
            }
1567
2.91k
            if (stream->req.res.trailers.size != 0) {
1568
0
                h2o_hpack_flatten_trailers(&conn->_write.buf, &conn->_output_header_table, conn->peer_settings.header_table_size,
1569
0
                                           stream->stream_id, conn->peer_settings.max_frame_size, stream->req.res.trailers.entries,
1570
0
                                           stream->req.res.trailers.size);
1571
0
            }
1572
2.91k
        }
1573
3.08k
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1574
3.08k
    }
1575
1576
3.59k
    return h2o_http2_conn_get_buffer_window(conn) > 0 ? 0 : -1;
1577
3.59k
}
1578
1579
void do_emit_writereq(h2o_http2_conn_t *conn)
1580
8.46k
{
1581
8.46k
    assert(conn->_write.buf_in_flight == NULL);
1582
1583
    /* push DATA frames */
1584
8.46k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && h2o_http2_conn_get_buffer_window(conn) > 0)
1585
3.71k
        h2o_http2_scheduler_run(&conn->scheduler, emit_writereq_of_openref, conn);
1586
1587
8.46k
    if (conn->_write.buf->size != 0) {
1588
        /* write and wait for completion */
1589
5.98k
        h2o_iovec_t buf = {conn->_write.buf->bytes, conn->_write.buf->size};
1590
5.98k
        h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
1591
5.98k
        conn->_write.buf_in_flight = conn->_write.buf;
1592
5.98k
        h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1593
5.98k
        h2o_timer_unlink(&conn->_timeout_entry);
1594
5.98k
        h2o_timer_link(conn->super.ctx->loop, H2O_HTTP2_DEFAULT_OUTBUF_WRITE_TIMEOUT, &conn->_timeout_entry);
1595
5.98k
    }
1596
1597
    /* close the connection if necessary */
1598
8.46k
    switch (conn->state) {
1599
3.71k
    case H2O_HTTP2_CONN_STATE_OPEN:
1600
3.71k
        break;
1601
0
    case H2O_HTTP2_CONN_STATE_HALF_CLOSED:
1602
0
        if (conn->num_streams.pull.open + conn->num_streams.push.open != 0)
1603
0
            break;
1604
0
        conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
1605
    /* fall-thru */
1606
4.74k
    case H2O_HTTP2_CONN_STATE_IS_CLOSING:
1607
4.74k
        close_connection(conn);
1608
4.74k
        break;
1609
8.46k
    }
1610
8.46k
}
1611
1612
static void emit_writereq(h2o_timer_t *entry)
1613
377
{
1614
377
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _write.timeout_entry, entry);
1615
1616
377
    do_emit_writereq(conn);
1617
377
}
1618
1619
static socklen_t get_sockname(h2o_conn_t *_conn, struct sockaddr *sa)
1620
0
{
1621
0
    h2o_http2_conn_t *conn = (void *)_conn;
1622
0
    return h2o_socket_getsockname(conn->sock, sa);
1623
0
}
1624
1625
static socklen_t get_peername(h2o_conn_t *_conn, struct sockaddr *sa)
1626
255
{
1627
255
    h2o_http2_conn_t *conn = (void *)_conn;
1628
255
    return h2o_socket_getpeername(conn->sock, sa);
1629
255
}
1630
1631
static ptls_t *get_ptls(h2o_conn_t *_conn)
1632
255
{
1633
255
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1634
255
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1635
255
    return h2o_socket_get_ptls(conn->sock);
1636
255
}
1637
1638
static const char *get_ssl_server_name(h2o_conn_t *_conn)
1639
0
{
1640
0
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1641
0
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1642
0
    return h2o_socket_get_ssl_server_name(conn->sock);
1643
0
}
1644
1645
static ptls_log_conn_state_t *log_state(h2o_conn_t *_conn)
1646
0
{
1647
0
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1648
0
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1649
0
    return h2o_socket_log_state(conn->sock);
1650
0
}
1651
1652
static uint64_t get_req_id(h2o_req_t *req)
1653
0
{
1654
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1655
0
    return stream->stream_id;
1656
0
}
1657
1658
static int64_t get_rtt(h2o_conn_t *_conn)
1659
0
{
1660
0
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1661
0
    if (!h2o_timeval_is_null(&conn->timestamps.settings_sent_at) && !h2o_timeval_is_null(&conn->timestamps.settings_acked_at)) {
1662
0
        return h2o_timeval_subtract(&conn->timestamps.settings_sent_at, &conn->timestamps.settings_acked_at);
1663
0
    } else {
1664
0
        return -1;
1665
0
    }
1666
0
}
1667
1668
#define DEFINE_LOGGER(name)                                                                                                        \
1669
    static h2o_iovec_t log_##name(h2o_req_t *req)                                                                                  \
1670
0
    {                                                                                                                              \
1671
0
        h2o_http2_conn_t *conn = (void *)req->conn;                                                                                \
1672
0
        return h2o_socket_log_##name(conn->sock, &req->pool);                                                                      \
1673
0
    }
Unexecuted instantiation: connection.c:log_tcp_congestion_controller
Unexecuted instantiation: connection.c:log_tcp_delivery_rate
Unexecuted instantiation: connection.c:log_ssl_protocol_version
Unexecuted instantiation: connection.c:log_ssl_session_reused
Unexecuted instantiation: connection.c:log_ssl_cipher
Unexecuted instantiation: connection.c:log_ssl_cipher_bits
Unexecuted instantiation: connection.c:log_ssl_session_id
Unexecuted instantiation: connection.c:log_ssl_negotiated_protocol
Unexecuted instantiation: connection.c:log_ssl_ech_config_id
Unexecuted instantiation: connection.c:log_ssl_ech_kem
Unexecuted instantiation: connection.c:log_ssl_ech_cipher
Unexecuted instantiation: connection.c:log_ssl_ech_cipher_bits
Unexecuted instantiation: connection.c:log_ssl_backend
1674
DEFINE_LOGGER(tcp_congestion_controller)
1675
DEFINE_LOGGER(tcp_delivery_rate)
1676
DEFINE_LOGGER(ssl_protocol_version)
1677
DEFINE_LOGGER(ssl_session_reused)
1678
DEFINE_LOGGER(ssl_cipher)
1679
DEFINE_LOGGER(ssl_cipher_bits)
1680
DEFINE_LOGGER(ssl_session_id)
1681
DEFINE_LOGGER(ssl_negotiated_protocol)
1682
DEFINE_LOGGER(ssl_ech_config_id)
1683
DEFINE_LOGGER(ssl_ech_kem)
1684
DEFINE_LOGGER(ssl_ech_cipher)
1685
DEFINE_LOGGER(ssl_ech_cipher_bits)
1686
DEFINE_LOGGER(ssl_backend)
1687
#undef DEFINE_LOGGER
1688
1689
static h2o_iovec_t log_stream_id(h2o_req_t *req)
1690
0
{
1691
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1692
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT32_LONGEST_STR));
1693
0
    size_t len = (size_t)sprintf(s, "%" PRIu32, stream->stream_id);
1694
0
    return h2o_iovec_init(s, len);
1695
0
}
1696
1697
static h2o_iovec_t log_priority_received(h2o_req_t *req)
1698
0
{
1699
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1700
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof("1:" H2O_UINT32_LONGEST_STR ":" H2O_UINT16_LONGEST_STR));
1701
0
    size_t len = (size_t)sprintf(s, "%c:%" PRIu32 ":%" PRIu16, stream->received_priority.exclusive ? '1' : '0',
1702
0
                                 stream->received_priority.dependency, stream->received_priority.weight);
1703
0
    return h2o_iovec_init(s, len);
1704
0
}
1705
1706
static h2o_iovec_t log_priority_received_exclusive(h2o_req_t *req)
1707
0
{
1708
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1709
0
    return h2o_iovec_init(stream->received_priority.exclusive ? "1" : "0", 1);
1710
0
}
1711
1712
static h2o_iovec_t log_priority_received_parent(h2o_req_t *req)
1713
0
{
1714
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1715
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT32_LONGEST_STR));
1716
0
    size_t len = sprintf(s, "%" PRIu32, stream->received_priority.dependency);
1717
0
    return h2o_iovec_init(s, len);
1718
0
}
1719
1720
static h2o_iovec_t log_priority_received_weight(h2o_req_t *req)
1721
0
{
1722
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1723
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT16_LONGEST_STR));
1724
0
    size_t len = sprintf(s, "%" PRIu16, stream->received_priority.weight);
1725
0
    return h2o_iovec_init(s, len);
1726
0
}
1727
1728
static uint32_t get_parent_stream_id(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
1729
0
{
1730
0
    h2o_http2_scheduler_node_t *parent_sched = h2o_http2_scheduler_get_parent(&stream->_scheduler);
1731
0
    if (parent_sched == &conn->scheduler) {
1732
0
        return 0;
1733
0
    } else {
1734
0
        h2o_http2_stream_t *parent_stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _scheduler, parent_sched);
1735
0
        return parent_stream->stream_id;
1736
0
    }
1737
0
}
1738
1739
static h2o_iovec_t log_priority_actual(h2o_req_t *req)
1740
0
{
1741
0
    h2o_http2_conn_t *conn = (void *)req->conn;
1742
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1743
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT32_LONGEST_STR ":" H2O_UINT16_LONGEST_STR));
1744
0
    size_t len = (size_t)sprintf(s, "%" PRIu32 ":%" PRIu16, get_parent_stream_id(conn, stream),
1745
0
                                 h2o_http2_scheduler_get_weight(&stream->_scheduler));
1746
0
    return h2o_iovec_init(s, len);
1747
0
}
1748
1749
static h2o_iovec_t log_priority_actual_parent(h2o_req_t *req)
1750
0
{
1751
0
    h2o_http2_conn_t *conn = (void *)req->conn;
1752
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1753
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT32_LONGEST_STR));
1754
0
    size_t len = (size_t)sprintf(s, "%" PRIu32, get_parent_stream_id(conn, stream));
1755
0
    return h2o_iovec_init(s, len);
1756
0
}
1757
1758
static h2o_iovec_t log_priority_actual_weight(h2o_req_t *req)
1759
0
{
1760
0
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
1761
0
    char *s = h2o_mem_alloc_pool(&stream->req.pool, *s, sizeof(H2O_UINT16_LONGEST_STR));
1762
0
    size_t len = (size_t)sprintf(s, "%" PRIu16, h2o_http2_scheduler_get_weight(&stream->_scheduler));
1763
0
    return h2o_iovec_init(s, len);
1764
0
}
1765
1766
static void on_dos_process_delay(h2o_timer_t *timer)
1767
2
{
1768
2
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, dos_mitigation.process_delay, timer);
1769
1770
2
    assert(!h2o_timer_is_linked(&conn->dos_mitigation.process_delay));
1771
2
    run_pending_requests(conn);
1772
2
}
1773
1774
static h2o_http2_conn_t *create_conn(h2o_context_t *ctx, h2o_hostconf_t **hosts, h2o_socket_t *sock, struct timeval connected_at)
1775
5.33k
{
1776
5.33k
    static const h2o_conn_callbacks_t callbacks = {
1777
5.33k
        .get_sockname = get_sockname,
1778
5.33k
        .get_peername = get_peername,
1779
5.33k
        .get_ptls = get_ptls,
1780
5.33k
        .get_ssl_server_name = get_ssl_server_name,
1781
5.33k
        .log_state = log_state,
1782
5.33k
        .get_req_id = get_req_id,
1783
5.33k
        .push_path = push_path,
1784
5.33k
        .get_debug_state = h2o_http2_get_debug_state,
1785
5.33k
        .close_idle_connection = close_idle_connection,
1786
5.33k
        .foreach_request = foreach_request,
1787
5.33k
        .request_shutdown = initiate_graceful_shutdown,
1788
5.33k
        .get_rtt = get_rtt,
1789
5.33k
        .log_ = {{
1790
5.33k
            .transport =
1791
5.33k
                {
1792
5.33k
                    .cc_name = log_tcp_congestion_controller,
1793
5.33k
                    .delivery_rate = log_tcp_delivery_rate,
1794
5.33k
                },
1795
5.33k
            .ssl =
1796
5.33k
                {
1797
5.33k
                    .protocol_version = log_ssl_protocol_version,
1798
5.33k
                    .session_reused = log_ssl_session_reused,
1799
5.33k
                    .cipher = log_ssl_cipher,
1800
5.33k
                    .cipher_bits = log_ssl_cipher_bits,
1801
5.33k
                    .session_id = log_ssl_session_id,
1802
5.33k
                    .negotiated_protocol = log_ssl_negotiated_protocol,
1803
5.33k
                    .ech_config_id = log_ssl_ech_config_id,
1804
5.33k
                    .ech_kem = log_ssl_ech_kem,
1805
5.33k
                    .ech_cipher = log_ssl_ech_cipher,
1806
5.33k
                    .ech_cipher_bits = log_ssl_ech_cipher_bits,
1807
5.33k
                    .backend = log_ssl_backend,
1808
5.33k
                },
1809
5.33k
            .http2 =
1810
5.33k
                {
1811
5.33k
                    .stream_id = log_stream_id,
1812
5.33k
                    .priority_received = log_priority_received,
1813
5.33k
                    .priority_received_exclusive = log_priority_received_exclusive,
1814
5.33k
                    .priority_received_parent = log_priority_received_parent,
1815
5.33k
                    .priority_received_weight = log_priority_received_weight,
1816
5.33k
                    .priority_actual = log_priority_actual,
1817
5.33k
                    .priority_actual_parent = log_priority_actual_parent,
1818
5.33k
                    .priority_actual_weight = log_priority_actual_weight,
1819
5.33k
                },
1820
5.33k
        }},
1821
5.33k
    };
1822
1823
5.33k
    h2o_http2_conn_t *conn = (void *)h2o_create_connection(sizeof(*conn), ctx, hosts, connected_at, &callbacks);
1824
1825
5.33k
    memset((char *)conn + sizeof(conn->super), 0, sizeof(*conn) - sizeof(conn->super));
1826
5.33k
    conn->sock = sock;
1827
5.33k
    conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
1828
5.33k
    conn->streams = kh_init(h2o_http2_stream_t);
1829
5.33k
    h2o_http2_scheduler_init(&conn->scheduler);
1830
5.33k
    conn->state = H2O_HTTP2_CONN_STATE_OPEN;
1831
5.33k
    conn->_read_expect = expect_preface;
1832
5.33k
    conn->_input_header_table.hpack_capacity = conn->_input_header_table.hpack_max_capacity =
1833
5.33k
        H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1834
5.33k
    h2o_http2_window_init(&conn->_input_window, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE);
1835
5.33k
    conn->_output_header_table.hpack_capacity = H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1836
5.33k
    h2o_linklist_init_anchor(&conn->_pending_reqs);
1837
5.33k
    h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1838
5.33k
    h2o_linklist_init_anchor(&conn->_write.streams_to_proceed);
1839
5.33k
    conn->_write.timeout_entry.cb = emit_writereq;
1840
5.33k
    h2o_http2_window_init(&conn->_write.window, conn->peer_settings.initial_window_size);
1841
5.33k
    h2o_linklist_init_anchor(&conn->early_data.blocked_streams);
1842
5.33k
    conn->is_chromium_dependency_tree = 1; /* initially assume the client is Chromium until proven otherwise */
1843
5.33k
    conn->received_any_request = 0;
1844
5.33k
    conn->dos_mitigation.process_delay.cb = on_dos_process_delay;
1845
5.33k
    conn->dos_mitigation.reset_budget = conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
1846
1847
5.33k
    return conn;
1848
5.33k
}
1849
1850
static int update_push_memo(h2o_http2_conn_t *conn, h2o_req_t *src_req, const char *abspath, size_t abspath_len)
1851
0
{
1852
1853
0
    if (conn->push_memo == NULL)
1854
0
        conn->push_memo = h2o_cache_create(0, 1024, 1, NULL);
1855
1856
    /* uses the hash as the key */
1857
0
    h2o_cache_hashcode_t url_hash = h2o_cache_calchash(src_req->input.scheme->name.base, src_req->input.scheme->name.len) ^
1858
0
                                    h2o_cache_calchash(src_req->input.authority.base, src_req->input.authority.len) ^
1859
0
                                    h2o_cache_calchash(abspath, abspath_len);
1860
0
    return h2o_cache_set(conn->push_memo, 0, h2o_iovec_init(&url_hash, sizeof(url_hash)), url_hash, h2o_iovec_init(NULL, 0));
1861
0
}
1862
1863
static void push_path(h2o_req_t *src_req, const char *abspath, size_t abspath_len, int is_critical)
1864
0
{
1865
0
    h2o_http2_conn_t *conn = (void *)src_req->conn;
1866
0
    h2o_http2_stream_t *src_stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, src_req);
1867
1868
    /* RFC 7540 8.2.1: PUSH_PROMISE frames can be sent by the server in response to any client-initiated stream */
1869
0
    if (h2o_http2_stream_is_push(src_stream->stream_id))
1870
0
        return;
1871
1872
0
    if (!src_stream->req.hostconf->http2.push_preload || !conn->peer_settings.enable_push ||
1873
0
        conn->num_streams.push.open >= conn->peer_settings.max_concurrent_streams)
1874
0
        return;
1875
1876
0
    if (conn->state >= H2O_HTTP2_CONN_STATE_IS_CLOSING)
1877
0
        return;
1878
0
    if (conn->push_stream_ids.max_open >= 0x7ffffff0)
1879
0
        return;
1880
0
    if (!(h2o_linklist_is_empty(&conn->_pending_reqs) && can_run_requests(conn)))
1881
0
        return;
1882
1883
0
    if (h2o_find_header(&src_stream->req.headers, H2O_TOKEN_X_FORWARDED_FOR, -1) != -1)
1884
0
        return;
1885
1886
0
    if (src_stream->cache_digests != NULL) {
1887
0
        h2o_iovec_t url = h2o_concat(&src_stream->req.pool, src_stream->req.input.scheme->name, h2o_iovec_init(H2O_STRLIT("://")),
1888
0
                                     src_stream->req.input.authority, h2o_iovec_init(abspath, abspath_len));
1889
0
        if (h2o_cache_digests_lookup_by_url(src_stream->cache_digests, url.base, url.len) == H2O_CACHE_DIGESTS_STATE_FRESH)
1890
0
            return;
1891
0
    }
1892
1893
    /* delayed initialization of casper (cookie-based), that MAY be used together to cache-digests */
1894
0
    if (src_stream->req.hostconf->http2.casper.capacity_bits != 0) {
1895
0
        if (!src_stream->pull.casper_is_ready) {
1896
0
            src_stream->pull.casper_is_ready = 1;
1897
0
            if (conn->casper == NULL)
1898
0
                h2o_http2_conn_init_casper(conn, src_stream->req.hostconf->http2.casper.capacity_bits);
1899
0
            ssize_t header_index;
1900
0
            for (header_index = -1;
1901
0
                 (header_index = h2o_find_header(&src_stream->req.headers, H2O_TOKEN_COOKIE, header_index)) != -1;) {
1902
0
                h2o_header_t *header = src_stream->req.headers.entries + header_index;
1903
0
                h2o_http2_casper_consume_cookie(conn->casper, header->value.base, header->value.len);
1904
0
            }
1905
0
        }
1906
0
    }
1907
1908
    /* update the push memo, and if it already pushed on the same connection, return */
1909
0
    if (update_push_memo(conn, &src_stream->req, abspath, abspath_len))
1910
0
        return;
1911
1912
    /* open the stream */
1913
0
    h2o_http2_stream_t *stream = h2o_http2_stream_open(conn, conn->push_stream_ids.max_open + 2, NULL, &h2o_http2_default_priority);
1914
0
    stream->received_priority.dependency = src_stream->stream_id;
1915
0
    stream->push.parent_stream_id = src_stream->stream_id;
1916
0
    if (is_critical) {
1917
0
        h2o_http2_scheduler_open(&stream->_scheduler, &conn->scheduler, 257, 0);
1918
0
    } else {
1919
0
        h2o_http2_scheduler_open(&stream->_scheduler, &src_stream->_scheduler.node, 16, 0);
1920
0
    }
1921
0
    h2o_http2_stream_prepare_for_request(conn, stream);
1922
1923
    /* setup request */
1924
0
    stream->req.input.method = (h2o_iovec_t){H2O_STRLIT("GET")};
1925
0
    stream->req.input.scheme = src_stream->req.input.scheme;
1926
0
    stream->req.input.authority =
1927
0
        h2o_strdup(&stream->req.pool, src_stream->req.input.authority.base, src_stream->req.input.authority.len);
1928
0
    stream->req.input.path = h2o_strdup(&stream->req.pool, abspath, abspath_len);
1929
0
    stream->req.version = 0x200;
1930
1931
0
    { /* copy headers that may affect the response (of a cacheable response) */
1932
0
        size_t i;
1933
0
        for (i = 0; i != src_stream->req.headers.size; ++i) {
1934
0
            h2o_header_t *src_header = src_stream->req.headers.entries + i;
1935
            /* currently only predefined headers are copiable */
1936
0
            if (h2o_iovec_is_token(src_header->name)) {
1937
0
                h2o_token_t *token = H2O_STRUCT_FROM_MEMBER(h2o_token_t, buf, src_header->name);
1938
0
                if (token->flags.copy_for_push_request)
1939
0
                    h2o_add_header(&stream->req.pool, &stream->req.headers, token, NULL,
1940
0
                                   h2o_strdup(&stream->req.pool, src_header->value.base, src_header->value.len).base,
1941
0
                                   src_header->value.len);
1942
0
            }
1943
0
        }
1944
0
    }
1945
1946
0
    execute_or_enqueue_request(conn, stream);
1947
1948
    /* send push-promise ASAP (before the parent stream gets closed), even if execute_or_enqueue_request did not trigger the
1949
     * invocation of send_headers */
1950
0
    if (!stream->push.promise_sent && stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
1951
0
        h2o_http2_stream_send_push_promise(conn, stream);
1952
0
}
1953
1954
static int foreach_request(h2o_conn_t *_conn, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata)
1955
0
{
1956
0
    h2o_http2_conn_t *conn = (void *)_conn;
1957
0
    h2o_http2_stream_t *stream;
1958
0
    kh_foreach_value(conn->streams, stream, {
1959
0
        int ret = cb(&stream->req, cbdata);
1960
0
        if (ret != 0)
1961
0
            return ret;
1962
0
    });
1963
0
    return 0;
1964
0
}
1965
1966
void h2o_http2_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
1967
4.85k
{
1968
4.85k
    h2o_http2_conn_t *conn = create_conn(ctx->ctx, ctx->hosts, sock, connected_at);
1969
4.85k
    conn->http2_origin_frame = ctx->http2_origin_frame;
1970
4.85k
    sock->data = conn;
1971
4.85k
    h2o_socket_read_start(conn->sock, on_read);
1972
4.85k
    update_idle_timeout(conn);
1973
4.85k
    if (sock->input->size != 0)
1974
4.85k
        on_read(sock, 0);
1975
4.85k
}
1976
1977
int h2o_http2_handle_upgrade(h2o_req_t *req, struct timeval connected_at)
1978
475
{
1979
475
    h2o_http2_conn_t *http2conn = create_conn(req->conn->ctx, req->conn->hosts, NULL, connected_at);
1980
475
    h2o_http2_stream_t *stream;
1981
475
    ssize_t connection_index, settings_index;
1982
475
    h2o_iovec_t settings_decoded;
1983
475
    const char *err_desc;
1984
1985
475
    assert(req->version < 0x200); /* from HTTP/1.x */
1986
1987
    /* check that "HTTP2-Settings" is declared in the connection header */
1988
475
    connection_index = h2o_find_header(&req->headers, H2O_TOKEN_CONNECTION, -1);
1989
475
    assert(connection_index != -1);
1990
475
    if (!h2o_contains_token(req->headers.entries[connection_index].value.base, req->headers.entries[connection_index].value.len,
1991
475
                            H2O_STRLIT("http2-settings"), ',')) {
1992
178
        goto Error;
1993
178
    }
1994
1995
    /* decode the settings */
1996
297
    if ((settings_index = h2o_find_header(&req->headers, H2O_TOKEN_HTTP2_SETTINGS, -1)) == -1) {
1997
64
        goto Error;
1998
64
    }
1999
233
    if ((settings_decoded = h2o_decode_base64url(&req->pool, req->headers.entries[settings_index].value.base,
2000
233
                                                 req->headers.entries[settings_index].value.len))
2001
233
            .base == NULL) {
2002
26
        goto Error;
2003
26
    }
2004
207
    if (h2o_http2_update_peer_settings(&http2conn->peer_settings, (uint8_t *)settings_decoded.base, settings_decoded.len,
2005
207
                                       &err_desc) != 0) {
2006
91
        goto Error;
2007
91
    }
2008
2009
    /* open the stream, now that the function is guaranteed to succeed */
2010
116
    stream = h2o_http2_stream_open(http2conn, 1, req, &h2o_http2_default_priority);
2011
116
    h2o_http2_scheduler_open(&stream->_scheduler, &http2conn->scheduler, h2o_http2_default_priority.weight, 0);
2012
116
    h2o_http2_stream_prepare_for_request(http2conn, stream);
2013
2014
    /* send response */
2015
116
    req->res.status = 101;
2016
116
    req->res.reason = "Switching Protocols";
2017
116
    h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("h2c"));
2018
116
    h2o_http1_upgrade(req, NULL, 0, on_upgrade_complete, http2conn);
2019
2020
116
    return 0;
2021
359
Error:
2022
359
    kh_destroy(h2o_http2_stream_t, http2conn->streams);
2023
359
    h2o_destroy_connection(&http2conn->super);
2024
359
    return -1;
2025
207
}