Coverage Report

Created: 2025-07-11 06:25

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