Coverage Report

Created: 2026-10-17 07:02

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