Coverage Report

Created: 2025-12-03 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2o/lib/http2/connection.c
Line
Count
Source
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
4.39k
{
51
4.39k
    return (h2o_http2_stream_is_push(stream_id) ? conn->push_stream_ids.max_open : conn->pull_stream_ids.max_open) < stream_id;
52
4.39k
}
53
54
static void enqueue_goaway(h2o_http2_conn_t *conn, int errnum, h2o_iovec_t additional_data)
55
6.24k
{
56
6.24k
    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
6.24k
        h2o_http2_encode_goaway_frame(&conn->_write.buf, conn->pull_stream_ids.max_open, errnum, additional_data);
59
6.24k
        h2o_http2_conn_request_write(conn);
60
6.24k
        conn->state = H2O_HTTP2_CONN_STATE_HALF_CLOSED;
61
6.24k
    }
62
6.24k
}
63
64
static void enqueue_server_preface(h2o_http2_conn_t *conn)
65
11.5k
{
66
    /* Send settings and initial window update */
67
11.5k
    h2o_http2_settings_kvpair_t settings[] = {
68
11.5k
        {H2O_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, conn->super.ctx->globalconf->http2.max_streams},
69
11.5k
        {H2O_HTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL, 1}};
70
11.5k
    h2o_http2_encode_settings_frame(&conn->_write.buf, settings, PTLS_ELEMENTSOF(settings));
71
11.5k
    h2o_http2_encode_window_update_frame(
72
11.5k
        &conn->_write.buf, 0, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE - H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
73
11.5k
}
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
78.7k
{
143
    /* do nothing touch anything if write is in progress */
144
78.7k
    if (conn->_write.buf_in_flight != NULL) {
145
10
        assert(h2o_timer_is_linked(&conn->_timeout_entry));
146
10
        return;
147
10
    }
148
149
78.7k
    h2o_timer_unlink(&conn->_timeout_entry);
150
151
    /* always set idle timeout if TLS handshake is in progress */
152
78.7k
    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
78.7k
    if (conn->num_streams.blocked_by_server != 0)
157
5.75k
        return;
158
159
72.9k
SetTimeout:
160
72.9k
    conn->_timeout_entry.cb = on_idle_timeout;
161
72.9k
    h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.idle_timeout, &conn->_timeout_entry);
162
72.9k
}
163
164
static int can_run_requests(h2o_http2_conn_t *conn)
165
6.20k
{
166
6.20k
    return conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed <
167
6.20k
           conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
168
6.20k
}
169
170
static void process_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
171
5.19k
{
172
5.19k
    if (stream->req.proceed_req != NULL) {
173
408
        assert(
174
408
            !(stream->req_body.state == H2O_HTTP2_REQ_BODY_NONE || stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED));
175
408
        conn->num_streams._req_streaming_in_progress++;
176
408
        conn->super.ctx->http2.events.streaming_requests++;
177
408
        stream->req_body.streamed = 1;
178
408
        if (stream->req.is_tunnel_req)
179
22
            conn->num_streams.tunnel++;
180
408
        update_stream_input_window(conn, stream,
181
408
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
182
408
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
183
4.78k
    } else {
184
4.78k
        if (stream->state < H2O_HTTP2_STREAM_STATE_SEND_HEADERS) {
185
4.78k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
186
4.78k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
187
4.78k
        }
188
4.78k
    }
189
190
5.19k
    if (!h2o_http2_stream_is_push(stream->stream_id) && conn->pull_stream_ids.max_processed < stream->stream_id)
191
5.08k
        conn->pull_stream_ids.max_processed = stream->stream_id;
192
193
5.19k
    h2o_process_request(&stream->req);
194
5.19k
}
195
196
static void run_pending_requests(h2o_http2_conn_t *conn)
197
37.0k
{
198
37.0k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
199
4.78k
        return;
200
201
32.2k
    h2o_linklist_t *link, *lnext;
202
32.2k
    int ran_one_request;
203
204
32.2k
    do {
205
32.2k
        ran_one_request = 0;
206
207
38.4k
        for (link = conn->_pending_reqs.next; link != &conn->_pending_reqs && can_run_requests(conn); link = lnext) {
208
            /* fetch and detach a pending stream */
209
6.20k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, link);
210
211
6.20k
            lnext = link->next;
212
213
            /* handle no more than specified number of streaming requests at a time */
214
6.20k
            if (stream->req.proceed_req != NULL &&
215
1.41k
                conn->num_streams._req_streaming_in_progress - conn->num_streams.tunnel >=
216
1.41k
                    conn->super.ctx->globalconf->http2.max_concurrent_streaming_requests_per_connection)
217
1.02k
                continue;
218
219
            /* handle it */
220
5.17k
            h2o_linklist_unlink(&stream->_link);
221
5.17k
            ran_one_request = 1;
222
5.17k
            process_request(conn, stream);
223
5.17k
        }
224
225
32.2k
    } while (ran_one_request && !h2o_linklist_is_empty(&conn->_pending_reqs));
226
32.2k
}
227
228
static int reset_stream_if_disregarded(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
229
7.55k
{
230
7.55k
    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
7.55k
    return 0;
236
7.55k
}
237
238
static void execute_or_enqueue_request_core(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
239
5.26k
{
240
    /* TODO schedule the pending reqs using the scheduler */
241
5.26k
    h2o_linklist_insert(&conn->_pending_reqs, &stream->_link);
242
243
5.26k
    run_pending_requests(conn);
244
5.26k
    update_idle_timeout(conn);
245
5.26k
}
246
247
static void execute_or_enqueue_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
248
4.80k
{
249
4.80k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_REQ_PENDING);
250
251
4.80k
    if (reset_stream_if_disregarded(conn, stream))
252
0
        return;
253
254
4.80k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
255
4.80k
    if (!stream->blocked_by_server)
256
4.64k
        h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
257
4.80k
    execute_or_enqueue_request_core(conn, stream);
258
4.80k
}
259
260
void h2o_http2_conn_register_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
261
49.3k
{
262
49.3k
    khiter_t iter;
263
49.3k
    int r;
264
265
49.3k
    iter = kh_put(h2o_http2_stream_t, conn->streams, stream->stream_id, &r);
266
49.3k
    assert(iter != kh_end(conn->streams));
267
49.3k
    kh_val(conn->streams, iter) = stream;
268
49.3k
}
269
270
void h2o_http2_conn_preserve_stream_scheduler(h2o_http2_conn_t *conn, h2o_http2_stream_t *src)
271
49.3k
{
272
49.3k
    assert(h2o_http2_scheduler_is_open(&src->_scheduler));
273
274
49.3k
    h2o_http2_stream_t **dst = conn->_recently_closed_streams.streams + conn->_recently_closed_streams.next_slot;
275
49.3k
    if (++conn->_recently_closed_streams.next_slot == HTTP2_CLOSED_STREAM_PRIORITIES)
276
2.97k
        conn->_recently_closed_streams.next_slot = 0;
277
278
49.3k
    if (*dst != NULL) {
279
24.0k
        assert(h2o_http2_scheduler_is_open(&(*dst)->_scheduler));
280
24.0k
        h2o_http2_scheduler_close(&(*dst)->_scheduler);
281
25.2k
    } else {
282
25.2k
        *dst = h2o_mem_alloc(offsetof(h2o_http2_stream_t, _scheduler) + sizeof((*dst)->_scheduler));
283
25.2k
    }
284
285
49.3k
    (*dst)->stream_id = src->stream_id;
286
49.3k
    h2o_http2_scheduler_relocate(&(*dst)->_scheduler, &src->_scheduler);
287
49.3k
    h2o_http2_scheduler_deactivate(&(*dst)->_scheduler);
288
49.3k
}
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
2.99k
{
292
2.99k
    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
2.99k
    switch (new_state) {
295
0
    case H2O_HTTP2_REQ_BODY_NONE:
296
0
        h2o_fatal("invalid state");
297
0
        break;
298
1.04k
    case H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED:
299
1.04k
        assert(stream->req.proceed_req == NULL);
300
1.04k
        if (stream->req_body.streamed) {
301
408
            conn->num_streams._req_streaming_in_progress--;
302
408
            if (stream->req.is_tunnel_req)
303
22
                conn->num_streams.tunnel--;
304
408
        }
305
1.04k
        break;
306
1.94k
    default:
307
1.94k
        break;
308
2.99k
    }
309
2.99k
    stream->req_body.state = new_state;
310
2.99k
}
311
312
void h2o_http2_conn_unregister_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
313
49.3k
{
314
49.3k
    h2o_http2_conn_preserve_stream_scheduler(conn, stream);
315
316
49.3k
    khiter_t iter = kh_get(h2o_http2_stream_t, conn->streams, stream->stream_id);
317
49.3k
    assert(iter != kh_end(conn->streams));
318
49.3k
    kh_del(h2o_http2_stream_t, conn->streams, iter);
319
320
49.3k
    if (stream->req_body.state != H2O_HTTP2_REQ_BODY_NONE && stream->req_body.state < H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED) {
321
734
        stream->req.proceed_req = NULL;
322
734
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
323
734
    }
324
325
49.3k
    if (stream->blocked_by_server)
326
524
        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
49.3k
    if (stream->reset_by_peer || stream->reset_by_peer_action) {
331
26.9k
        if (conn->dos_mitigation.reset_budget > 0)
332
22.3k
            --conn->dos_mitigation.reset_budget;
333
334
        /* setup process delay if we've just ran out of reset budget */
335
26.9k
        if (conn->dos_mitigation.reset_budget == 0 && conn->super.ctx->globalconf->http2.dos_delay != 0 &&
336
4.70k
            !h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
337
121
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.dos_delay, &conn->dos_mitigation.process_delay);
338
339
26.9k
    } else {
340
22.4k
        if (conn->dos_mitigation.reset_budget < conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection)
341
3.36k
            ++conn->dos_mitigation.reset_budget;
342
22.4k
    }
343
344
49.3k
    switch (stream->state) {
345
566
    case H2O_HTTP2_STREAM_STATE_RECV_BODY:
346
566
        if (h2o_linklist_is_linked(&stream->_link))
347
69
            h2o_linklist_unlink(&stream->_link);
348
    /* fallthru */
349
32.5k
    case H2O_HTTP2_STREAM_STATE_IDLE:
350
41.0k
    case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
351
41.0k
        assert(!h2o_linklist_is_linked(&stream->_link));
352
41.0k
        break;
353
41.0k
    case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
354
27
        assert(h2o_linklist_is_linked(&stream->_link));
355
27
        h2o_linklist_unlink(&stream->_link);
356
27
        break;
357
218
    case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
358
290
    case H2O_HTTP2_STREAM_STATE_SEND_BODY:
359
3.19k
    case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
360
8.19k
    case H2O_HTTP2_STREAM_STATE_END_STREAM:
361
8.19k
        if (h2o_linklist_is_linked(&stream->_link))
362
25
            h2o_linklist_unlink(&stream->_link);
363
8.19k
        break;
364
49.3k
    }
365
49.3k
    if (stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
366
44.3k
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
367
368
49.3k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
369
31.7k
        run_pending_requests(conn);
370
31.7k
        update_idle_timeout(conn);
371
31.7k
    }
372
49.3k
}
373
374
void close_connection_now(h2o_http2_conn_t *conn)
375
11.7k
{
376
    /* mark as is_closing here to prevent sending any more frames */
377
11.7k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
378
379
11.7k
    h2o_http2_stream_t *stream;
380
381
11.7k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
382
383
11.7k
    kh_foreach_value(conn->streams, stream, { h2o_http2_stream_close(conn, stream); });
384
385
11.7k
    assert(conn->num_streams.pull.open == 0);
386
11.7k
    assert(conn->num_streams.pull.half_closed == 0);
387
11.7k
    assert(conn->num_streams.pull.send_body == 0);
388
11.7k
    assert(conn->num_streams.push.half_closed == 0);
389
11.7k
    assert(conn->num_streams.push.send_body == 0);
390
11.7k
    assert(conn->num_streams.priority.open == 0);
391
11.7k
    assert(conn->num_streams.blocked_by_server == 0);
392
11.7k
    assert(conn->num_streams._req_streaming_in_progress == 0);
393
11.7k
    assert(conn->num_streams.tunnel == 0);
394
11.7k
    kh_destroy(h2o_http2_stream_t, conn->streams);
395
11.7k
    assert(conn->_http1_req_input == NULL);
396
11.7k
    h2o_hpack_dispose_header_table(&conn->_input_header_table);
397
11.7k
    h2o_hpack_dispose_header_table(&conn->_output_header_table);
398
11.7k
    assert(h2o_linklist_is_empty(&conn->_pending_reqs));
399
11.7k
    h2o_timer_unlink(&conn->_timeout_entry);
400
401
11.7k
    if (h2o_timer_is_linked(&conn->_graceful_shutdown_timeout))
402
0
        h2o_timer_unlink(&conn->_graceful_shutdown_timeout);
403
404
11.7k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
405
81
        h2o_timer_unlink(&conn->dos_mitigation.process_delay);
406
407
11.7k
    h2o_buffer_dispose(&conn->_write.buf);
408
11.7k
    if (conn->_write.buf_in_flight != NULL)
409
8
        h2o_buffer_dispose(&conn->_write.buf_in_flight);
410
11.7k
    {
411
11.7k
        size_t i;
412
37.0k
        for (i = 0; i < sizeof(conn->_recently_closed_streams.streams) / sizeof(conn->_recently_closed_streams.streams[0]); ++i) {
413
36.1k
            h2o_http2_stream_t *closed_stream = conn->_recently_closed_streams.streams[i];
414
36.1k
            if (closed_stream == NULL)
415
10.9k
                break;
416
36.1k
            assert(h2o_http2_scheduler_is_open(&closed_stream->_scheduler));
417
25.2k
            h2o_http2_scheduler_close(&closed_stream->_scheduler);
418
25.2k
            free(closed_stream);
419
25.2k
        }
420
11.7k
    }
421
11.7k
    h2o_http2_scheduler_dispose(&conn->scheduler);
422
11.7k
    assert(h2o_linklist_is_empty(&conn->_write.streams_to_proceed));
423
11.7k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
424
11.7k
    if (conn->_headers_unparsed != NULL)
425
261
        h2o_buffer_dispose(&conn->_headers_unparsed);
426
11.7k
    if (conn->push_memo != NULL)
427
0
        h2o_cache_destroy(conn->push_memo);
428
11.7k
    if (conn->casper != NULL)
429
0
        h2o_http2_casper_destroy(conn->casper);
430
431
11.7k
    if (conn->sock != NULL)
432
11.7k
        h2o_socket_close(conn->sock);
433
434
11.7k
    h2o_destroy_connection(&conn->super);
435
11.7k
}
436
437
int close_connection(h2o_http2_conn_t *conn)
438
24.3k
{
439
24.3k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
440
441
24.3k
    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
12.5k
    } else {
444
11.7k
        close_connection_now(conn);
445
11.7k
        return -1;
446
11.7k
    }
447
12.5k
    return 0;
448
24.3k
}
449
450
static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum)
451
30.8k
{
452
30.8k
    assert(stream_id != 0);
453
30.8k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
454
455
30.8k
    conn->super.ctx->http2.events.protocol_level_errors[-errnum]++;
456
457
30.8k
    h2o_http2_encode_rst_stream_frame(&conn->_write.buf, stream_id, -errnum);
458
30.8k
    h2o_http2_conn_request_write(conn);
459
30.8k
}
460
461
static void request_gathered_write(h2o_http2_conn_t *conn)
462
85.1k
{
463
85.1k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
464
85.1k
    if (!h2o_socket_is_writing(conn->sock) && !h2o_timer_is_linked(&conn->_write.timeout_entry)) {
465
14.6k
        h2o_timer_link(conn->super.ctx->loop, 0, &conn->_write.timeout_entry);
466
14.6k
    }
467
85.1k
}
468
469
static int update_stream_output_window(h2o_http2_stream_t *stream, ssize_t delta)
470
10.7k
{
471
10.7k
    ssize_t cur = h2o_http2_window_get_avail(&stream->output_window);
472
10.7k
    if (h2o_http2_window_update(&stream->output_window, delta) != 0)
473
727
        return -1;
474
9.97k
    if (cur <= 0 && h2o_http2_window_get_avail(&stream->output_window) > 0 &&
475
1.46k
        (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL)) {
476
1.08k
        assert(!h2o_linklist_is_linked(&stream->_link));
477
1.08k
        h2o_http2_scheduler_activate(&stream->_scheduler);
478
1.08k
    }
479
9.97k
    return 0;
480
9.97k
}
481
482
static void write_streaming_body(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
483
221
{
484
221
    int is_end_stream = 0;
485
486
221
    assert(stream->req.entity.base == NULL);
487
488
    /* check state as well as update */
489
221
    switch (stream->req_body.state) {
490
0
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
491
144
    case H2O_HTTP2_REQ_BODY_OPEN:
492
144
        assert(stream->req_body.buf->size != 0);
493
144
        break;
494
144
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
495
77
        stream->req.proceed_req = NULL;
496
77
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
497
77
        is_end_stream = 1;
498
77
        break;
499
0
    default:
500
0
        h2o_fatal("unexpected req_body.state");
501
0
        break;
502
221
    }
503
504
    /* invoke write_req */
505
221
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
506
221
    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
221
    if (stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED && stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM)
514
12
        h2o_http2_stream_close(conn, stream);
515
221
}
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
2.81k
{
519
2.81k
    int is_first = 0;
520
521
2.81k
    switch (stream->req_body.state) {
522
816
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
523
816
        is_first = 1;
524
816
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
525
816
        break;
526
1.99k
    case H2O_HTTP2_REQ_BODY_OPEN:
527
1.99k
        break;
528
0
    default:
529
0
        h2o_fatal("unexpected req_body.state");
530
0
        break;
531
2.81k
    }
532
533
2.81k
    stream->req.req_body_bytes_received += payload.len;
534
535
    /* check size */
536
2.81k
    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
2.81k
    if (stream->req.content_length != SIZE_MAX) {
542
494
        size_t received = stream->req.req_body_bytes_received, cl = stream->req.content_length;
543
494
        if (is_end_stream ? (received != cl) : (received > cl)) {
544
53
            stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
545
53
            h2o_http2_stream_reset(conn, stream);
546
53
            return;
547
53
        }
548
494
    }
549
550
    /* update timer */
551
2.75k
    if (!stream->blocked_by_server)
552
970
        h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
553
554
    /* just reset the stream if the request is to be disregarded */
555
2.75k
    if (reset_stream_if_disregarded(conn, stream))
556
0
        return;
557
558
    /* update state, buffer the data */
559
2.75k
    int req_queued = stream->req.proceed_req != NULL;
560
2.75k
    if (is_end_stream) {
561
264
        if (stream->state < H2O_HTTP2_STREAM_STATE_REQ_PENDING) {
562
241
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
563
241
            if (stream->req.process_called)
564
68
                h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
565
241
        }
566
264
        if (stream->req.write_req.cb != NULL) {
567
81
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_QUEUED);
568
183
        } else {
569
183
            stream->req.proceed_req = NULL;
570
183
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
571
183
        }
572
264
    }
573
2.75k
    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
2.75k
    if (stream->req_body.streamed) {
577
1.17k
        if (stream->req.write_req.cb != NULL) {
578
763
            if (stream->req.entity.base == NULL)
579
205
                write_streaming_body(conn, stream);
580
763
        } else {
581
408
            stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
582
408
        }
583
1.17k
        return;
584
1.17k
    }
585
586
    /* not (yet) in streaming mode */
587
1.58k
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
588
589
    /* when receiving first DATA frame... */
590
1.58k
    if (is_first && !is_end_stream) {
591
        /* trigger request streaming mode if possible */
592
629
        if (h2o_req_can_stream_request(&stream->req)) {
593
467
            stream->req.proceed_req = proceed_request;
594
467
            execute_or_enqueue_request_core(conn, stream);
595
467
            return;
596
467
        }
597
        /* or, run in non-streaming mode (TODO elect input streams one by one for non-streaming case as well?) */
598
162
        update_stream_input_window(conn, stream,
599
162
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
600
162
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
601
162
    }
602
603
    /* run or queue the request when all input is available (and if the request has not been queued for streaming processing) */
604
1.11k
    if (is_end_stream && !req_queued)
605
161
        execute_or_enqueue_request(conn, stream);
606
1.11k
}
607
608
static int send_invalid_request_error(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const char *err_desc)
609
2.67k
{
610
    /* fast forward the stream's state so that we can start sending the response */
611
2.67k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
612
2.67k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
613
2.67k
    h2o_send_error_400(&stream->req, "Invalid Request", err_desc, 0);
614
2.67k
    return 0;
615
2.67k
}
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
16.9k
{
620
16.9k
    int ret, header_exists_map = 0;
621
16.9k
    h2o_iovec_t expect = h2o_iovec_init(NULL, 0);
622
623
16.9k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS);
624
625
16.9k
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table,
626
16.9k
                                       &stream->req.input.method, &stream->req.input.scheme, &stream->req.input.authority,
627
16.9k
                                       &stream->req.input.path, &stream->req.upgrade, &stream->req.headers, &header_exists_map,
628
16.9k
                                       &stream->req.content_length, &expect, &stream->cache_digests, NULL, src, len, err_desc)) !=
629
16.9k
        0) {
630
        /* all errors except invalid-header-char are connection errors */
631
7.21k
        if (ret != H2O_HTTP2_ERROR_INVALID_HEADER_CHAR)
632
4.15k
            return ret;
633
7.21k
    }
634
635
12.7k
    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
12.7k
    if (stream->req.input.scheme == NULL)
639
4.03k
        stream->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP;
640
641
12.7k
    int is_connect, must_exist_map, may_exist_map;
642
12.7k
    if (h2o_memis(stream->req.input.method.base, stream->req.input.method.len, H2O_STRLIT("CONNECT"))) {
643
26
        is_connect = 1;
644
26
        must_exist_map = H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
645
26
        may_exist_map = 0;
646
        /* extended connect looks like an ordinary request plus an upgrade token (:protocol) */
647
26
        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
12.7k
    } 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
3
        if (!((header_exists_map & H2O_HPACK_PARSE_HEADERS_PROTOCOL_EXISTS) == 0 &&
655
3
              h2o_memis(stream->req.input.path.base, stream->req.input.path.len, H2O_STRLIT("/")))) {
656
2
            ret = H2O_HTTP2_ERROR_PROTOCOL;
657
2
            goto SendRSTStream;
658
2
        }
659
3
        assert(stream->req.upgrade.base == NULL); /* otherwise PROTOCOL_EXISTS will be set */
660
1
        is_connect = 1;
661
1
        must_exist_map = H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS |
662
1
                         H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
663
1
        may_exist_map = 0;
664
12.7k
    } else {
665
        /* normal request */
666
12.7k
        is_connect = 0;
667
12.7k
        must_exist_map =
668
12.7k
            H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
669
12.7k
        may_exist_map = H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
670
12.7k
    }
671
672
    /* check that all MUST pseudo headers exist, and that there are no other pseudo headers than MUST or MAY */
673
12.7k
    if (!((header_exists_map & must_exist_map) == must_exist_map && (header_exists_map & ~(must_exist_map | may_exist_map)) == 0)) {
674
4.09k
        ret = H2O_HTTP2_ERROR_PROTOCOL;
675
4.09k
        goto SendRSTStream;
676
4.09k
    }
677
678
8.68k
    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
8.68k
    if (ret != 0) {
685
2.67k
        assert(ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR);
686
2.67k
        return send_invalid_request_error(conn, stream, *err_desc);
687
2.67k
    }
688
689
    /* special handling of CONNECT method */
690
6.01k
    if (is_connect) {
691
        /* reject the request if content-length is specified or if the stream has been closed */
692
25
        if (stream->req.content_length != SIZE_MAX || stream->req_body.buf == NULL)
693
3
            return send_invalid_request_error(conn, stream, "Invalid CONNECT request");
694
        /* handle the request */
695
22
        stream->req.is_tunnel_req = 1;
696
22
        goto ProcessImmediately;
697
0
        return 0;
698
25
    }
699
700
    /* handle expect: 100-continue */
701
5.98k
    if (expect.base != NULL) {
702
420
        if (!h2o_lcstris(expect.base, expect.len, H2O_STRLIT("100-continue"))) {
703
420
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
704
420
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
705
420
            h2o_send_error_417(&stream->req, "Expectation Failed", "unknown expectation", 0);
706
420
            return 0;
707
420
        }
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
5.56k
    if (stream->req_body.buf == NULL) {
719
4.54k
        execute_or_enqueue_request(conn, stream);
720
4.54k
    } else {
721
1.02k
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
722
1.02k
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME);
723
1.02k
    }
724
5.56k
    return 0;
725
726
4.09k
SendRSTStream:
727
4.09k
    stream->reset_by_peer_action = 1;
728
4.09k
    stream_send_error(conn, stream->stream_id, ret);
729
4.09k
    h2o_http2_stream_reset(conn, stream);
730
4.09k
    return 0;
731
732
22
ProcessImmediately:
733
22
    stream->req.entity = h2o_iovec_init("", 0); /* setting to non-NULL pointer indicates the presence of HTTP payload */
734
22
    stream->req.proceed_req = proceed_request;
735
22
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
736
22
    set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
737
22
    process_request(conn, stream);
738
22
    return 0;
739
5.98k
}
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
64
{
744
64
    size_t dummy_content_length;
745
64
    h2o_iovec_t dummy_expect = h2o_iovec_init(NULL, 0);
746
64
    int ret;
747
748
64
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table, NULL, NULL, NULL,
749
64
                                       NULL, NULL, &stream->req.headers, NULL, &dummy_content_length, &dummy_expect, NULL, NULL,
750
64
                                       src, len, err_desc)) != 0)
751
14
        return ret;
752
50
    handle_request_body_chunk(conn, stream, h2o_iovec_init(NULL, 0), 1);
753
50
    return 0;
754
64
}
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
1.54k
{
758
1.54k
    h2o_http2_frame_t frame;
759
1.54k
    ssize_t ret;
760
1.54k
    h2o_http2_stream_t *stream;
761
1.54k
    int hret;
762
763
1.54k
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
764
164
        return ret;
765
1.37k
    if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
766
19
        *err_desc = "expected CONTINUATION frame";
767
19
        return H2O_HTTP2_ERROR_PROTOCOL;
768
19
    }
769
770
1.35k
    if ((stream = h2o_http2_conn_get_stream(conn, frame.stream_id)) == NULL ||
771
1.27k
        !(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY)) {
772
90
        *err_desc = "unexpected stream id in CONTINUATION frame";
773
90
        return H2O_HTTP2_ERROR_PROTOCOL;
774
90
    }
775
776
1.26k
    if (conn->_headers_unparsed->size + frame.length <= H2O_MAX_REQLEN) {
777
1.26k
        h2o_buffer_reserve(&conn->_headers_unparsed, frame.length);
778
1.26k
        memcpy(conn->_headers_unparsed->bytes + conn->_headers_unparsed->size, frame.payload, frame.length);
779
1.26k
        conn->_headers_unparsed->size += frame.length;
780
781
1.26k
        if ((frame.flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
782
21
            conn->_read_expect = expect_default;
783
21
            if (stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS) {
784
11
                hret = handle_incoming_request(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
785
11
                                               conn->_headers_unparsed->size, err_desc);
786
11
            } else {
787
10
                hret = handle_trailing_headers(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
788
10
                                               conn->_headers_unparsed->size, err_desc);
789
10
            }
790
21
            if (hret != 0)
791
9
                ret = hret;
792
21
            h2o_buffer_dispose(&conn->_headers_unparsed);
793
21
            conn->_headers_unparsed = NULL;
794
21
        }
795
1.26k
    } 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
1.26k
    return ret;
802
1.35k
}
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
570
{
806
570
    assert(delta <= INT32_MAX);
807
570
    h2o_http2_encode_window_update_frame(&conn->_write.buf, stream_id, (int32_t)delta);
808
570
    h2o_http2_conn_request_write(conn);
809
570
    h2o_http2_window_update(window, delta);
810
570
}
811
812
void update_stream_input_window(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, size_t delta)
813
2.06k
{
814
2.06k
    stream->input_window.bytes_unnotified += delta;
815
2.06k
    if (stream->input_window.bytes_unnotified >= h2o_http2_window_get_avail(&stream->input_window.window)) {
816
570
        send_window_update(conn, stream->stream_id, &stream->input_window.window, stream->input_window.bytes_unnotified);
817
570
        stream->input_window.bytes_unnotified = 0;
818
570
    }
819
2.06k
}
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
64.6k
{
824
64.6k
    h2o_http2_scheduler_node_t *parent_sched = NULL;
825
826
    /* determine the parent */
827
64.6k
    if (priority->dependency != 0) {
828
52.5k
        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
499k
        for (i = 0; i < HTTP2_CLOSED_STREAM_PRIORITIES; i++) {
835
456k
            if (conn->_recently_closed_streams.streams[i] &&
836
246k
                conn->_recently_closed_streams.streams[i]->stream_id == priority->dependency) {
837
10.2k
                parent_sched = &conn->_recently_closed_streams.streams[i]->_scheduler.node;
838
10.2k
                break;
839
10.2k
            }
840
456k
        }
841
52.5k
        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
42.3k
            h2o_http2_stream_t *parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
847
42.3k
            if (parent_stream != NULL) {
848
4.72k
                parent_sched = &parent_stream->_scheduler.node;
849
37.6k
            } 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
37.6k
                parent_sched = &conn->scheduler;
857
37.6k
                priority = &h2o_http2_default_priority;
858
37.6k
            }
859
42.3k
        } 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
4.59k
            h2o_http2_scheduler_openref_t *orig_parent_ref =
870
4.59k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched);
871
4.59k
            if (orig_parent_ref->weight < priority->weight || !priority->exclusive) {
872
                /* Turns out the client's dependency tree does not look like Chromium's */
873
13
                conn->is_chromium_dependency_tree = 0;
874
4.57k
            } else {
875
4.57k
                h2o_http2_stream_t *current_parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
876
4.57k
                if (current_parent_stream != NULL && orig_parent_ref->weight > current_parent_stream->_scheduler.weight &&
877
2.93k
                    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
2.93k
                    parent_sched = h2o_http2_scheduler_find_parent_by_weight(&conn->scheduler, priority->weight);
884
2.93k
                    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
1.02k
                        parent_sched = &current_parent_stream->_scheduler.node;
888
1.02k
                    }
889
2.93k
                }
890
4.57k
            }
891
4.59k
        }
892
52.5k
    } else {
893
12.0k
        parent_sched = &conn->scheduler;
894
12.0k
    }
895
896
    /* Verify if the client's dependency tree looks like Chromium's */
897
64.6k
    if (priority->exclusive && conn->is_chromium_dependency_tree) {
898
7.44k
        int parent_weight = 256;
899
7.44k
        if (parent_sched->_parent != NULL && parent_sched->_parent->_parent != NULL) {
900
3.46k
            h2o_http2_scheduler_openref_t *parent_ref =
901
3.46k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched->_parent);
902
3.46k
            parent_weight = parent_ref->weight;
903
3.46k
        }
904
7.44k
        if (parent_weight < priority->weight) {
905
            /* Child's weight is bigger than parent's -- not Chromium */
906
4
            conn->is_chromium_dependency_tree = 0;
907
4
        }
908
57.2k
    } else {
909
        /* Stream doesn't have the exclusive flag -- not Chromium */
910
57.2k
        conn->is_chromium_dependency_tree = 0;
911
57.2k
    }
912
913
    /* setup the scheduler */
914
64.6k
    if (!scheduler_is_open) {
915
49.2k
        h2o_http2_scheduler_open(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
916
49.2k
    } else {
917
15.4k
        h2o_http2_scheduler_rebind(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
918
15.4k
    }
919
64.6k
}
920
921
void proceed_request(h2o_req_t *req, const char *errstr)
922
484
{
923
484
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
924
484
    h2o_http2_conn_t *conn = (h2o_http2_conn_t *)stream->req.conn;
925
926
484
    assert(stream->req_body.streamed);
927
928
    /* consume bytes */
929
484
    size_t written = stream->req.entity.len;
930
484
    h2o_buffer_consume(&stream->req_body.buf, written);
931
484
    stream->req.entity = h2o_iovec_init(NULL, 0);
932
933
    /* handle error */
934
484
    if (errstr != NULL) {
935
54
        stream->req.proceed_req = NULL;
936
54
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
937
54
        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
54
            stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
941
54
            h2o_http2_scheduler_deactivate(&stream->_scheduler);
942
54
            if (!h2o_linklist_is_linked(&stream->_link))
943
54
                h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
944
54
            h2o_http2_stream_reset(conn, stream);
945
54
        }
946
54
        return;
947
54
    }
948
949
430
    switch (stream->req_body.state) {
950
426
    case H2O_HTTP2_REQ_BODY_OPEN:
951
426
        update_stream_input_window(conn, stream, written);
952
426
        if (stream->blocked_by_server && h2o_http2_window_get_avail(&stream->input_window.window) > 0) {
953
415
            h2o_http2_stream_set_blocked_by_server(conn, stream, 0);
954
415
            update_idle_timeout(conn);
955
415
        }
956
426
        if (stream->req_body.buf->size != 0)
957
12
            write_streaming_body(conn, stream);
958
426
        break;
959
4
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
960
4
        assert(written != 0);
961
4
        write_streaming_body(conn, stream);
962
4
        break;
963
0
    default:
964
0
        h2o_fatal("unexpected req_body_state");
965
430
    }
966
430
}
967
968
static int handle_data_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
969
22.8k
{
970
22.8k
    h2o_http2_data_payload_t payload;
971
22.8k
    h2o_http2_stream_t *stream;
972
22.8k
    int ret;
973
974
22.8k
    if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
975
73
        return ret;
976
977
    /* update connection-level window */
978
22.8k
    h2o_http2_window_consume_window(&conn->_input_window, frame->length);
979
22.8k
    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
22.8k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
985
2.67k
        if (frame->stream_id <= conn->pull_stream_ids.max_open) {
986
2.39k
            stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
987
2.39k
            return 0;
988
2.39k
        } else {
989
275
            *err_desc = "invalid DATA frame";
990
275
            return H2O_HTTP2_ERROR_PROTOCOL;
991
275
        }
992
2.67k
    }
993
20.1k
    if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
994
19.1k
          stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN)) {
995
17.0k
        stream->reset_by_peer_action = 1;
996
17.0k
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
997
17.0k
        h2o_http2_stream_reset(conn, stream);
998
17.0k
        return 0;
999
17.0k
    }
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
3.07k
    h2o_http2_window_consume_window(&stream->input_window.window, frame->length);
1004
3.07k
    if (frame->length != payload.length)
1005
1.06k
        update_stream_input_window(conn, stream, frame->length - payload.length);
1006
1007
    /* actually handle the input */
1008
3.07k
    if (payload.length != 0 || (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0)
1009
2.76k
        handle_request_body_chunk(conn, stream, h2o_iovec_init(payload.data, payload.length),
1010
2.76k
                                  (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0);
1011
1012
3.07k
    return 0;
1013
20.1k
}
1014
1015
static int handle_headers_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1016
17.3k
{
1017
17.3k
    h2o_http2_headers_payload_t payload;
1018
17.3k
    h2o_http2_stream_t *stream;
1019
17.3k
    int ret;
1020
1021
    /* decode */
1022
17.3k
    if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
1023
32
        return ret;
1024
17.3k
    if ((frame->stream_id & 1) == 0) {
1025
17
        *err_desc = "invalid stream id in HEADERS frame";
1026
17
        return H2O_HTTP2_ERROR_PROTOCOL;
1027
17
    }
1028
17.3k
    if (frame->stream_id <= conn->pull_stream_ids.max_open) {
1029
121
        if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
1030
47
            *err_desc = "closed stream id in HEADERS frame";
1031
47
            return H2O_HTTP2_ERROR_STREAM_CLOSED;
1032
47
        }
1033
74
        if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
1034
17
              stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN)) {
1035
12
            *err_desc = "invalid stream id in HEADERS frame";
1036
12
            return H2O_HTTP2_ERROR_PROTOCOL;
1037
12
        }
1038
1039
        /* is a trailer */
1040
62
        if (stream->req.is_tunnel_req) {
1041
1
            *err_desc = "trailer cannot be used in a CONNECT request";
1042
1
            return H2O_HTTP2_ERROR_PROTOCOL;
1043
1
        }
1044
61
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0) {
1045
5
            *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
1046
5
            return H2O_HTTP2_ERROR_PROTOCOL;
1047
5
        }
1048
56
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0)
1049
2
            goto PREPARE_FOR_CONTINUATION;
1050
54
        return handle_trailing_headers(conn, stream, payload.headers, payload.headers_len, err_desc);
1051
56
    }
1052
17.2k
    if (frame->stream_id == payload.priority.dependency) {
1053
4
        *err_desc = "stream cannot depend on itself";
1054
4
        return H2O_HTTP2_ERROR_PROTOCOL;
1055
4
    }
1056
1057
    /* open or determine the stream and prepare */
1058
17.2k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1059
46
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_PRIORITY) != 0) {
1060
43
            set_priority(conn, stream, &payload.priority, 1);
1061
43
            stream->received_priority = payload.priority;
1062
43
        }
1063
17.1k
    } else {
1064
17.1k
        conn->received_any_request = 1;
1065
17.1k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload.priority);
1066
17.1k
        set_priority(conn, stream, &payload.priority, 0);
1067
17.1k
    }
1068
17.2k
    h2o_http2_stream_prepare_for_request(conn, stream);
1069
1070
    /* setup container for request body if it is expected to arrive */
1071
17.2k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0)
1072
6.02k
        h2o_buffer_init(&stream->req_body.buf, &h2o_socket_buffer_prototype);
1073
1074
17.2k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
1075
        /* request headers are complete, handle it */
1076
16.9k
        return handle_incoming_request(conn, stream, payload.headers, payload.headers_len, err_desc);
1077
16.9k
    }
1078
1079
282
PREPARE_FOR_CONTINUATION:
1080
    /* request is not complete, store in buffer */
1081
282
    conn->_read_expect = expect_continuation_of_headers;
1082
282
    h2o_buffer_init(&conn->_headers_unparsed, &h2o_socket_buffer_prototype);
1083
282
    h2o_buffer_reserve(&conn->_headers_unparsed, payload.headers_len);
1084
282
    memcpy(conn->_headers_unparsed->bytes, payload.headers, payload.headers_len);
1085
282
    conn->_headers_unparsed->size = payload.headers_len;
1086
282
    return 0;
1087
17.2k
}
1088
1089
static int handle_priority_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1090
49.5k
{
1091
49.5k
    h2o_http2_priority_t payload;
1092
49.5k
    h2o_http2_stream_t *stream;
1093
49.5k
    int ret;
1094
1095
49.5k
    if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
1096
64
        return ret;
1097
49.5k
    if (frame->stream_id == payload.dependency) {
1098
4
        *err_desc = "stream cannot depend on itself";
1099
4
        return H2O_HTTP2_ERROR_PROTOCOL;
1100
4
    }
1101
1102
49.5k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1103
15.4k
        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
15.4k
        if (h2o_http2_scheduler_get_weight(&stream->_scheduler) != 257)
1108
15.4k
            set_priority(conn, stream, &payload, 1);
1109
34.1k
    } else {
1110
34.1k
        if (h2o_http2_stream_is_push(frame->stream_id)) {
1111
            /* Ignore PRIORITY frames for closed or idle pushed streams */
1112
1.12k
            return 0;
1113
32.9k
        } else {
1114
            /* Ignore PRIORITY frames for closed pull streams */
1115
32.9k
            if (frame->stream_id <= conn->pull_stream_ids.max_open)
1116
934
                return 0;
1117
32.9k
        }
1118
32.0k
        if (conn->num_streams.priority.open >= conn->super.ctx->globalconf->http2.max_streams_for_priority) {
1119
7
            *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
7
            return H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM;
1124
7
        }
1125
32.0k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload);
1126
32.0k
        set_priority(conn, stream, &payload, 0);
1127
32.0k
    }
1128
1129
47.4k
    return 0;
1130
49.5k
}
1131
1132
static void resume_send(h2o_http2_conn_t *conn)
1133
10.0k
{
1134
10.0k
    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
10.0k
    request_gathered_write(conn);
1141
10.0k
}
1142
1143
static int handle_settings_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1144
9.90k
{
1145
9.90k
    if (frame->stream_id != 0) {
1146
104
        *err_desc = "invalid stream id in SETTINGS frame";
1147
104
        return H2O_HTTP2_ERROR_PROTOCOL;
1148
104
    }
1149
1150
9.79k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
1151
443
        if (frame->length != 0) {
1152
5
            *err_desc = "invalid SETTINGS frame (+ACK)";
1153
5
            return H2O_HTTP2_ERROR_FRAME_SIZE;
1154
5
        }
1155
438
        if (h2o_timeval_is_null(&conn->timestamps.settings_acked_at) && !h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1156
206
            conn->timestamps.settings_acked_at = h2o_gettimeofday(conn->super.ctx->loop);
1157
206
        }
1158
9.35k
    } else {
1159
9.35k
        uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
1160
9.35k
        int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
1161
9.35k
        if (ret != 0)
1162
184
            return ret;
1163
9.17k
        { /* schedule ack */
1164
9.17k
            h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
1165
9.17k
            h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
1166
9.17k
            conn->_write.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
1167
9.17k
            h2o_http2_conn_request_write(conn);
1168
9.17k
        }
1169
        /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
1170
9.17k
        if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
1171
6.31k
            ssize_t delta = (int32_t)conn->peer_settings.initial_window_size - (int32_t)prev_initial_window_size;
1172
6.31k
            h2o_http2_stream_t *stream;
1173
6.31k
            kh_foreach_value(conn->streams, stream, { update_stream_output_window(stream, delta); });
1174
6.31k
            resume_send(conn);
1175
6.31k
        }
1176
9.17k
    }
1177
1178
9.61k
    return 0;
1179
9.79k
}
1180
1181
static int handle_window_update_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1182
11.0k
{
1183
11.0k
    h2o_http2_window_update_payload_t payload;
1184
11.0k
    int ret, err_is_stream_level;
1185
1186
11.0k
    if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
1187
7.18k
        if (err_is_stream_level) {
1188
7.15k
            h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1189
7.15k
            if (stream != NULL) {
1190
5.72k
                stream->reset_by_peer_action = 1;
1191
5.72k
                h2o_http2_stream_reset(conn, stream);
1192
5.72k
            }
1193
7.15k
            stream_send_error(conn, frame->stream_id, ret);
1194
7.15k
            return 0;
1195
7.15k
        } else {
1196
25
            return ret;
1197
25
        }
1198
7.18k
    }
1199
1200
3.88k
    if (frame->stream_id == 0) {
1201
715
        if (h2o_http2_window_update(&conn->_write.window, payload.window_size_increment) != 0) {
1202
6
            *err_desc = "flow control window overflow";
1203
6
            return H2O_HTTP2_ERROR_FLOW_CONTROL;
1204
6
        }
1205
3.16k
    } else if (!is_idle_stream_id(conn, frame->stream_id)) {
1206
3.07k
        h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1207
3.07k
        if (stream != NULL) {
1208
1.51k
            if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
1209
15
                stream->reset_by_peer_action = 1;
1210
15
                h2o_http2_stream_reset(conn, stream);
1211
15
                stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
1212
15
                return 0;
1213
15
            }
1214
1.51k
        }
1215
3.07k
    } else {
1216
94
        *err_desc = "invalid stream id in WINDOW_UPDATE frame";
1217
94
        return H2O_HTTP2_ERROR_PROTOCOL;
1218
94
    }
1219
1220
3.76k
    resume_send(conn);
1221
1222
3.76k
    return 0;
1223
3.88k
}
1224
1225
static int handle_goaway_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1226
316
{
1227
316
    h2o_http2_goaway_payload_t payload;
1228
316
    int ret;
1229
1230
316
    if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
1231
51
        return ret;
1232
1233
    /* stop opening new push streams hereafter */
1234
265
    conn->push_stream_ids.max_open = 0x7ffffffe;
1235
1236
265
    return 0;
1237
316
}
1238
1239
static int handle_ping_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1240
807
{
1241
807
    h2o_http2_ping_payload_t payload;
1242
807
    int ret;
1243
1244
807
    if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
1245
54
        return ret;
1246
1247
753
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
1248
233
        h2o_http2_encode_ping_frame(&conn->_write.buf, 1, payload.data);
1249
233
        h2o_http2_conn_request_write(conn);
1250
233
    }
1251
1252
753
    return 0;
1253
807
}
1254
1255
static int handle_rst_stream_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1256
1.26k
{
1257
1.26k
    h2o_http2_rst_stream_payload_t payload;
1258
1.26k
    h2o_http2_stream_t *stream;
1259
1.26k
    int ret;
1260
1261
1.26k
    if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
1262
40
        return ret;
1263
1.22k
    if (is_idle_stream_id(conn, frame->stream_id)) {
1264
59
        *err_desc = "unexpected stream id in RST_STREAM frame";
1265
59
        return H2O_HTTP2_ERROR_PROTOCOL;
1266
59
    }
1267
1268
1.16k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL)
1269
1.15k
        return 0;
1270
1271
    /* reset the stream */
1272
9
    stream->reset_by_peer = 1;
1273
9
    h2o_http2_stream_reset(conn, stream);
1274
1275
    /* TODO log */
1276
1277
9
    return 0;
1278
1.16k
}
1279
1280
static int handle_push_promise_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1281
26
{
1282
26
    *err_desc = "received PUSH_PROMISE frame";
1283
26
    return H2O_HTTP2_ERROR_PROTOCOL;
1284
26
}
1285
1286
static int handle_invalid_continuation_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1287
10
{
1288
10
    *err_desc = "received invalid CONTINUATION frame";
1289
10
    return H2O_HTTP2_ERROR_PROTOCOL;
1290
10
}
1291
1292
ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1293
122k
{
1294
122k
    h2o_http2_frame_t frame;
1295
122k
    ssize_t ret;
1296
122k
    static int (*FRAME_HANDLERS[])(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc) = {
1297
122k
        handle_data_frame,                /* DATA */
1298
122k
        handle_headers_frame,             /* HEADERS */
1299
122k
        handle_priority_frame,            /* PRIORITY */
1300
122k
        handle_rst_stream_frame,          /* RST_STREAM */
1301
122k
        handle_settings_frame,            /* SETTINGS */
1302
122k
        handle_push_promise_frame,        /* PUSH_PROMISE */
1303
122k
        handle_ping_frame,                /* PING */
1304
122k
        handle_goaway_frame,              /* GOAWAY */
1305
122k
        handle_window_update_frame,       /* WINDOW_UPDATE */
1306
122k
        handle_invalid_continuation_frame /* CONTINUATION */
1307
122k
    };
1308
1309
122k
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
1310
5.50k
        return ret;
1311
1312
116k
    if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
1313
113k
        int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
1314
113k
        if (hret != 0)
1315
5.36k
            ret = hret;
1316
113k
    } else {
1317
3.28k
        H2O_PROBE_CONN(H2_UNKNOWN_FRAME_TYPE, &conn->super, frame.type);
1318
3.28k
    }
1319
1320
116k
    return ret;
1321
122k
}
1322
1323
static ssize_t expect_preface(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1324
11.9k
{
1325
11.9k
    if (len < CONNECTION_PREFACE.len) {
1326
264
        return H2O_HTTP2_ERROR_INCOMPLETE;
1327
264
    }
1328
11.6k
    if (memcmp(src, CONNECTION_PREFACE.base, CONNECTION_PREFACE.len) != 0) {
1329
171
        return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
1330
171
    }
1331
1332
11.4k
    {
1333
11.4k
        enqueue_server_preface(conn);
1334
11.4k
        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
11.4k
        if (h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1339
11.4k
            conn->timestamps.settings_sent_at = h2o_gettimeofday(conn->super.ctx->loop);
1340
11.4k
        }
1341
11.4k
        h2o_http2_conn_request_write(conn);
1342
11.4k
    }
1343
1344
11.4k
    conn->_read_expect = expect_default;
1345
11.4k
    return CONNECTION_PREFACE.len;
1346
11.6k
}
1347
1348
static int parse_input(h2o_http2_conn_t *conn)
1349
15.3k
{
1350
    /* handle the input */
1351
139k
    while (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && conn->sock->input->size != 0) {
1352
        /* process a frame */
1353
135k
        const char *err_desc = NULL;
1354
135k
        ssize_t ret = conn->_read_expect(conn, (uint8_t *)conn->sock->input->bytes, conn->sock->input->size, &err_desc);
1355
135k
        if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
1356
5.16k
            break;
1357
130k
        } else if (ret < 0) {
1358
6.41k
            if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
1359
6.24k
                enqueue_goaway(conn, (int)ret,
1360
6.24k
                               err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
1361
6.24k
            }
1362
6.41k
            return close_connection(conn);
1363
6.41k
        }
1364
        /* advance to the next frame */
1365
123k
        h2o_buffer_consume(&conn->sock->input, ret);
1366
123k
    }
1367
8.96k
    return 0;
1368
15.3k
}
1369
1370
static void on_read(h2o_socket_t *sock, const char *err)
1371
20.7k
{
1372
20.7k
    h2o_http2_conn_t *conn = sock->data;
1373
1374
20.7k
    if (err != NULL) {
1375
5.37k
        conn->super.ctx->http2.events.read_closed++;
1376
5.37k
        h2o_socket_read_stop(conn->sock);
1377
5.37k
        close_connection(conn);
1378
5.37k
        return;
1379
5.37k
    }
1380
1381
    /* dispatch requests blocked by 425 when TLS handshake is complete */
1382
15.3k
    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
15.3k
    if (parse_input(conn) != 0)
1397
180
        return;
1398
15.2k
    update_idle_timeout(conn);
1399
1400
    /* write immediately, if there is no write in flight and if pending write exists */
1401
15.2k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry)) {
1402
13.5k
        h2o_timer_unlink(&conn->_write.timeout_entry);
1403
13.5k
        do_emit_writereq(conn);
1404
13.5k
    }
1405
15.2k
}
1406
1407
static void on_upgrade_complete(void *_conn, h2o_socket_t *sock, size_t reqsize)
1408
100
{
1409
100
    h2o_http2_conn_t *conn = _conn;
1410
1411
100
    if (sock == NULL) {
1412
0
        close_connection(conn);
1413
0
        return;
1414
0
    }
1415
1416
100
    conn->sock = sock;
1417
100
    sock->data = conn;
1418
100
    conn->_http1_req_input = sock->input;
1419
100
    h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype);
1420
1421
100
    enqueue_server_preface(conn);
1422
100
    h2o_http2_conn_request_write(conn);
1423
1424
    /* setup inbound */
1425
100
    h2o_socket_read_start(conn->sock, on_read);
1426
1427
    /* handle the request */
1428
100
    execute_or_enqueue_request(conn, h2o_http2_conn_get_stream(conn, 1));
1429
1430
100
    if (conn->_http1_req_input->size > reqsize) {
1431
45
        size_t remaining_bytes = conn->_http1_req_input->size - reqsize;
1432
45
        h2o_buffer_reserve(&sock->input, remaining_bytes);
1433
45
        memcpy(sock->input->bytes, conn->_http1_req_input->bytes + reqsize, remaining_bytes);
1434
45
        sock->input->size += remaining_bytes;
1435
45
        on_read(conn->sock, NULL);
1436
45
    }
1437
100
}
1438
1439
static size_t bytes_in_buf(h2o_http2_conn_t *conn)
1440
74.9k
{
1441
74.9k
    size_t size = conn->_write.buf->size;
1442
74.9k
    if (conn->_write.buf_in_flight != 0)
1443
22
        size += conn->_write.buf_in_flight->size;
1444
74.9k
    return size;
1445
74.9k
}
1446
1447
void h2o_http2_conn_request_write(h2o_http2_conn_t *conn)
1448
75.0k
{
1449
75.0k
    if (conn->state == H2O_HTTP2_CONN_STATE_IS_CLOSING)
1450
0
        return;
1451
75.0k
    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
75.0k
    request_gathered_write(conn);
1454
75.0k
}
1455
1456
void h2o_http2_conn_register_for_proceed_callback(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
1457
8.47k
{
1458
8.47k
    h2o_http2_conn_request_write(conn);
1459
1460
8.47k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1461
8.47k
        if (h2o_http2_window_get_avail(&stream->output_window) > 0) {
1462
8.24k
            assert(!h2o_linklist_is_linked(&stream->_link));
1463
8.24k
            h2o_http2_scheduler_activate(&stream->_scheduler);
1464
8.24k
        }
1465
8.47k
    } else {
1466
0
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1467
0
    }
1468
8.47k
}
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
69
{
1481
69
    h2o_http2_conn_t *conn = sock->data;
1482
1483
69
    if (err != NULL) {
1484
0
        close_connection_now(conn);
1485
0
        return;
1486
0
    }
1487
69
    do_emit_writereq(conn);
1488
69
}
1489
1490
static void on_write_complete(h2o_socket_t *sock, const char *err)
1491
14.3k
{
1492
14.3k
    h2o_http2_conn_t *conn = sock->data;
1493
1494
14.3k
    assert(conn->_write.buf_in_flight != NULL);
1495
1496
    /* close by error if necessary */
1497
14.3k
    if (err != NULL) {
1498
8
        conn->super.ctx->http2.events.write_closed++;
1499
8
        close_connection_now(conn);
1500
8
        return;
1501
8
    }
1502
1503
    /* reset the other memory pool */
1504
14.3k
    h2o_buffer_dispose(&conn->_write.buf_in_flight);
1505
14.3k
    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
14.3k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1509
13.6k
        while (!h2o_linklist_is_empty(&conn->_write.streams_to_proceed)) {
1510
5.49k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, conn->_write.streams_to_proceed.next);
1511
5.49k
            assert(!h2o_http2_stream_has_pending_data(stream));
1512
5.49k
            h2o_linklist_unlink(&stream->_link);
1513
5.49k
            h2o_http2_stream_proceed(conn, stream);
1514
5.49k
        }
1515
8.11k
    }
1516
1517
    /* update the timeout now that the states have been updated */
1518
14.3k
    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
14.3k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry))
1522
85
        h2o_timer_unlink(&conn->_write.timeout_entry);
1523
1524
14.3k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1525
8.11k
        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
8.11k
    }
1528
1529
14.3k
#if !H2O_USE_LIBUV
1530
14.3k
    if (conn->state == H2O_HTTP2_CONN_STATE_OPEN) {
1531
8.11k
        if (conn->_write.buf->size != 0 || h2o_http2_scheduler_is_active(&conn->scheduler))
1532
93
            h2o_socket_notify_write(sock, on_notify_write);
1533
8.11k
        return;
1534
8.11k
    }
1535
6.26k
#endif
1536
1537
    /* write more, if possible */
1538
6.26k
    do_emit_writereq(conn);
1539
6.26k
}
1540
1541
static int emit_writereq_of_openref(h2o_http2_scheduler_openref_t *ref, int *still_is_active, void *cb_arg)
1542
6.38k
{
1543
6.38k
    h2o_http2_conn_t *conn = cb_arg;
1544
6.38k
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _scheduler, ref);
1545
1546
6.38k
    assert(h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL);
1547
1548
6.38k
    *still_is_active = 0;
1549
1550
6.38k
    h2o_http2_stream_send_pending_data(conn, stream);
1551
6.38k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1552
921
        if (h2o_http2_window_get_avail(&stream->output_window) <= 0) {
1553
            /* is blocked */
1554
921
        } else {
1555
0
            *still_is_active = 1;
1556
0
        }
1557
5.46k
    } else {
1558
5.46k
        if (stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM) {
1559
4.92k
            h2o_iovec_t server_timing;
1560
4.92k
            if (stream->req.send_server_timing &&
1561
0
                (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
4.92k
            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
4.92k
        }
1573
5.46k
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1574
5.46k
    }
1575
1576
6.38k
    return h2o_http2_conn_get_buffer_window(conn) > 0 ? 0 : -1;
1577
6.38k
}
1578
1579
void do_emit_writereq(h2o_http2_conn_t *conn)
1580
20.8k
{
1581
20.8k
    assert(conn->_write.buf_in_flight == NULL);
1582
1583
    /* push DATA frames */
1584
20.8k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && h2o_http2_conn_get_buffer_window(conn) > 0)
1585
8.34k
        h2o_http2_scheduler_run(&conn->scheduler, emit_writereq_of_openref, conn);
1586
1587
20.8k
    if (conn->_write.buf->size != 0) {
1588
        /* write and wait for completion */
1589
14.3k
        h2o_iovec_t buf = {conn->_write.buf->bytes, conn->_write.buf->size};
1590
14.3k
        h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
1591
14.3k
        conn->_write.buf_in_flight = conn->_write.buf;
1592
14.3k
        h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1593
14.3k
        h2o_timer_unlink(&conn->_timeout_entry);
1594
14.3k
        h2o_timer_link(conn->super.ctx->loop, H2O_HTTP2_DEFAULT_OUTBUF_WRITE_TIMEOUT, &conn->_timeout_entry);
1595
14.3k
    }
1596
1597
    /* close the connection if necessary */
1598
20.8k
    switch (conn->state) {
1599
8.34k
    case H2O_HTTP2_CONN_STATE_OPEN:
1600
8.34k
        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
12.5k
    case H2O_HTTP2_CONN_STATE_IS_CLOSING:
1607
12.5k
        close_connection(conn);
1608
12.5k
        break;
1609
20.8k
    }
1610
20.8k
}
1611
1612
static void emit_writereq(h2o_timer_t *entry)
1613
987
{
1614
987
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _write.timeout_entry, entry);
1615
1616
987
    do_emit_writereq(conn);
1617
987
}
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
869
{
1627
869
    h2o_http2_conn_t *conn = (void *)_conn;
1628
869
    return h2o_socket_getpeername(conn->sock, sa);
1629
869
}
1630
1631
static ptls_t *get_ptls(h2o_conn_t *_conn)
1632
869
{
1633
869
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1634
869
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1635
869
    return h2o_socket_get_ptls(conn->sock);
1636
869
}
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
40
{
1768
40
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, dos_mitigation.process_delay, timer);
1769
1770
40
    assert(!h2o_timer_is_linked(&conn->dos_mitigation.process_delay));
1771
40
    run_pending_requests(conn);
1772
40
}
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
12.2k
{
1776
12.2k
    static const h2o_conn_callbacks_t callbacks = {
1777
12.2k
        .get_sockname = get_sockname,
1778
12.2k
        .get_peername = get_peername,
1779
12.2k
        .get_ptls = get_ptls,
1780
12.2k
        .get_ssl_server_name = get_ssl_server_name,
1781
12.2k
        .log_state = log_state,
1782
12.2k
        .get_req_id = get_req_id,
1783
12.2k
        .push_path = push_path,
1784
12.2k
        .get_debug_state = h2o_http2_get_debug_state,
1785
12.2k
        .close_idle_connection = close_idle_connection,
1786
12.2k
        .foreach_request = foreach_request,
1787
12.2k
        .request_shutdown = initiate_graceful_shutdown,
1788
12.2k
        .get_rtt = get_rtt,
1789
12.2k
        .log_ = {{
1790
12.2k
            .transport =
1791
12.2k
                {
1792
12.2k
                    .cc_name = log_tcp_congestion_controller,
1793
12.2k
                    .delivery_rate = log_tcp_delivery_rate,
1794
12.2k
                },
1795
12.2k
            .ssl =
1796
12.2k
                {
1797
12.2k
                    .protocol_version = log_ssl_protocol_version,
1798
12.2k
                    .session_reused = log_ssl_session_reused,
1799
12.2k
                    .cipher = log_ssl_cipher,
1800
12.2k
                    .cipher_bits = log_ssl_cipher_bits,
1801
12.2k
                    .session_id = log_ssl_session_id,
1802
12.2k
                    .negotiated_protocol = log_ssl_negotiated_protocol,
1803
12.2k
                    .ech_config_id = log_ssl_ech_config_id,
1804
12.2k
                    .ech_kem = log_ssl_ech_kem,
1805
12.2k
                    .ech_cipher = log_ssl_ech_cipher,
1806
12.2k
                    .ech_cipher_bits = log_ssl_ech_cipher_bits,
1807
12.2k
                    .backend = log_ssl_backend,
1808
12.2k
                },
1809
12.2k
            .http2 =
1810
12.2k
                {
1811
12.2k
                    .stream_id = log_stream_id,
1812
12.2k
                    .priority_received = log_priority_received,
1813
12.2k
                    .priority_received_exclusive = log_priority_received_exclusive,
1814
12.2k
                    .priority_received_parent = log_priority_received_parent,
1815
12.2k
                    .priority_received_weight = log_priority_received_weight,
1816
12.2k
                    .priority_actual = log_priority_actual,
1817
12.2k
                    .priority_actual_parent = log_priority_actual_parent,
1818
12.2k
                    .priority_actual_weight = log_priority_actual_weight,
1819
12.2k
                },
1820
12.2k
        }},
1821
12.2k
    };
1822
1823
12.2k
    h2o_http2_conn_t *conn = (void *)h2o_create_connection(sizeof(*conn), ctx, hosts, connected_at, &callbacks);
1824
1825
12.2k
    memset((char *)conn + sizeof(conn->super), 0, sizeof(*conn) - sizeof(conn->super));
1826
12.2k
    conn->sock = sock;
1827
12.2k
    conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
1828
12.2k
    conn->streams = kh_init(h2o_http2_stream_t);
1829
12.2k
    h2o_http2_scheduler_init(&conn->scheduler);
1830
12.2k
    conn->state = H2O_HTTP2_CONN_STATE_OPEN;
1831
12.2k
    conn->_read_expect = expect_preface;
1832
12.2k
    conn->_input_header_table.hpack_capacity = conn->_input_header_table.hpack_max_capacity =
1833
12.2k
        H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1834
12.2k
    h2o_http2_window_init(&conn->_input_window, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE);
1835
12.2k
    conn->_output_header_table.hpack_capacity = H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1836
12.2k
    h2o_linklist_init_anchor(&conn->_pending_reqs);
1837
12.2k
    h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1838
12.2k
    h2o_linklist_init_anchor(&conn->_write.streams_to_proceed);
1839
12.2k
    conn->_write.timeout_entry.cb = emit_writereq;
1840
12.2k
    h2o_http2_window_init(&conn->_write.window, conn->peer_settings.initial_window_size);
1841
12.2k
    h2o_linklist_init_anchor(&conn->early_data.blocked_streams);
1842
12.2k
    conn->is_chromium_dependency_tree = 1; /* initially assume the client is Chromium until proven otherwise */
1843
12.2k
    conn->received_any_request = 0;
1844
12.2k
    conn->dos_mitigation.process_delay.cb = on_dos_process_delay;
1845
12.2k
    conn->dos_mitigation.reset_budget = conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
1846
1847
12.2k
    return conn;
1848
12.2k
}
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
11.6k
{
1968
11.6k
    h2o_http2_conn_t *conn = create_conn(ctx->ctx, ctx->hosts, sock, connected_at);
1969
11.6k
    conn->http2_origin_frame = ctx->http2_origin_frame;
1970
11.6k
    sock->data = conn;
1971
11.6k
    h2o_socket_read_start(conn->sock, on_read);
1972
11.6k
    update_idle_timeout(conn);
1973
11.6k
    if (sock->input->size != 0)
1974
4.41k
        on_read(sock, 0);
1975
11.6k
}
1976
1977
int h2o_http2_handle_upgrade(h2o_req_t *req, struct timeval connected_at)
1978
521
{
1979
521
    h2o_http2_conn_t *http2conn = create_conn(req->conn->ctx, req->conn->hosts, NULL, connected_at);
1980
521
    h2o_http2_stream_t *stream;
1981
521
    ssize_t connection_index, settings_index;
1982
521
    h2o_iovec_t settings_decoded;
1983
521
    const char *err_desc;
1984
1985
521
    assert(req->version < 0x200); /* from HTTP/1.x */
1986
1987
    /* check that "HTTP2-Settings" is declared in the connection header */
1988
521
    connection_index = h2o_find_header(&req->headers, H2O_TOKEN_CONNECTION, -1);
1989
521
    assert(connection_index != -1);
1990
521
    if (!h2o_contains_token(req->headers.entries[connection_index].value.base, req->headers.entries[connection_index].value.len,
1991
521
                            H2O_STRLIT("http2-settings"), ',')) {
1992
192
        goto Error;
1993
192
    }
1994
1995
    /* decode the settings */
1996
329
    if ((settings_index = h2o_find_header(&req->headers, H2O_TOKEN_HTTP2_SETTINGS, -1)) == -1) {
1997
68
        goto Error;
1998
68
    }
1999
261
    if ((settings_decoded = h2o_decode_base64url(&req->pool, req->headers.entries[settings_index].value.base,
2000
261
                                                 req->headers.entries[settings_index].value.len))
2001
261
            .base == NULL) {
2002
43
        goto Error;
2003
43
    }
2004
218
    if (h2o_http2_update_peer_settings(&http2conn->peer_settings, (uint8_t *)settings_decoded.base, settings_decoded.len,
2005
218
                                       &err_desc) != 0) {
2006
118
        goto Error;
2007
118
    }
2008
2009
    /* open the stream, now that the function is guaranteed to succeed */
2010
100
    stream = h2o_http2_stream_open(http2conn, 1, req, &h2o_http2_default_priority);
2011
100
    h2o_http2_scheduler_open(&stream->_scheduler, &http2conn->scheduler, h2o_http2_default_priority.weight, 0);
2012
100
    h2o_http2_stream_prepare_for_request(http2conn, stream);
2013
2014
    /* send response */
2015
100
    req->res.status = 101;
2016
100
    req->res.reason = "Switching Protocols";
2017
100
    h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("h2c"));
2018
100
    h2o_http1_upgrade(req, NULL, 0, on_upgrade_complete, http2conn);
2019
2020
100
    return 0;
2021
421
Error:
2022
421
    kh_destroy(h2o_http2_stream_t, http2conn->streams);
2023
421
    h2o_destroy_connection(&http2conn->super);
2024
421
    return -1;
2025
218
}