Coverage Report

Created: 2026-09-04 06:56

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.56k
{
51
5.56k
    return (h2o_http2_stream_is_push(stream_id) ? conn->push_stream_ids.max_open : conn->pull_stream_ids.max_open) < stream_id;
52
5.56k
}
53
54
static void enqueue_goaway(h2o_http2_conn_t *conn, int errnum, h2o_iovec_t additional_data)
55
6.53k
{
56
6.53k
    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.53k
        h2o_http2_encode_goaway_frame(&conn->_write.buf, conn->pull_stream_ids.max_open, errnum, additional_data);
59
6.53k
        h2o_http2_conn_request_write(conn);
60
6.53k
        conn->state = H2O_HTTP2_CONN_STATE_HALF_CLOSED;
61
6.53k
    }
62
6.53k
}
63
64
static void enqueue_server_preface(h2o_http2_conn_t *conn)
65
12.2k
{
66
    /* Send settings and initial window update */
67
12.2k
    h2o_http2_settings_kvpair_t settings[] = {
68
12.2k
        {H2O_HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, conn->super.ctx->globalconf->http2.max_streams},
69
12.2k
        {H2O_HTTP2_SETTINGS_ENABLE_CONNECT_PROTOCOL, 1}};
70
12.2k
    h2o_http2_encode_settings_frame(&conn->_write.buf, settings, PTLS_ELEMENTSOF(settings));
71
12.2k
    h2o_http2_encode_window_update_frame(
72
12.2k
        &conn->_write.buf, 0, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE - H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
73
12.2k
}
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
85.2k
{
143
    /* do nothing touch anything if write is in progress */
144
85.2k
    if (conn->_write.buf_in_flight != NULL) {
145
15
        assert(h2o_timer_is_linked(&conn->_timeout_entry));
146
15
        return;
147
15
    }
148
149
85.1k
    h2o_timer_unlink(&conn->_timeout_entry);
150
151
    /* always set idle timeout if TLS handshake is in progress */
152
85.1k
    if (conn->sock->ssl != NULL && h2o_socket_ssl_is_early_data(conn->sock))
153
0
        goto SetTimeout;
154
155
    /* no need to set timeout if pending requests exist */
156
85.1k
    if (conn->num_streams.blocked_by_server != 0)
157
7.52k
        return;
158
159
77.6k
SetTimeout:
160
77.6k
    conn->_timeout_entry.cb = on_idle_timeout;
161
77.6k
    h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.idle_timeout, &conn->_timeout_entry);
162
77.6k
}
163
164
static int can_run_requests(h2o_http2_conn_t *conn)
165
6.71k
{
166
6.71k
    return conn->num_streams.pull.half_closed + conn->num_streams.push.half_closed <
167
6.71k
           conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
168
6.71k
}
169
170
static void process_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
171
6.22k
{
172
6.22k
    if (stream->req.proceed_req != NULL) {
173
562
        assert(
174
562
            !(stream->req_body.state == H2O_HTTP2_REQ_BODY_NONE || stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED));
175
562
        conn->num_streams._req_streaming_in_progress++;
176
562
        conn->super.ctx->http2.events.streaming_requests++;
177
562
        stream->req_body.streamed = 1;
178
562
        if (stream->req.is_tunnel_req)
179
39
            conn->num_streams.tunnel++;
180
562
        update_stream_input_window(conn, stream,
181
562
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
182
562
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
183
5.66k
    } else {
184
5.66k
        if (stream->state < H2O_HTTP2_STREAM_STATE_SEND_HEADERS) {
185
5.66k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
186
5.66k
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
187
5.66k
        }
188
5.66k
    }
189
190
6.22k
    if (!h2o_http2_stream_is_push(stream->stream_id) && conn->pull_stream_ids.max_processed < stream->stream_id)
191
6.10k
        conn->pull_stream_ids.max_processed = stream->stream_id;
192
193
6.22k
    h2o_process_request(&stream->req);
194
6.22k
}
195
196
static void run_pending_requests(h2o_http2_conn_t *conn)
197
41.1k
{
198
41.1k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
199
4.83k
        return;
200
201
36.2k
    h2o_linklist_t *link, *lnext;
202
36.2k
    int ran_one_request;
203
204
36.2k
    do {
205
36.2k
        ran_one_request = 0;
206
207
43.0k
        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.71k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, link);
210
211
6.71k
            lnext = link->next;
212
213
            /* handle no more than specified number of streaming requests at a time */
214
6.71k
            if (stream->req.proceed_req != NULL &&
215
1.05k
                conn->num_streams._req_streaming_in_progress - conn->num_streams.tunnel >=
216
1.05k
                    conn->super.ctx->globalconf->http2.max_concurrent_streaming_requests_per_connection)
217
529
                continue;
218
219
            /* handle it */
220
6.18k
            h2o_linklist_unlink(&stream->_link);
221
6.18k
            ran_one_request = 1;
222
6.18k
            process_request(conn, stream);
223
6.18k
        }
224
225
36.2k
    } while (ran_one_request && !h2o_linklist_is_empty(&conn->_pending_reqs));
226
36.2k
}
227
228
static int reset_stream_if_disregarded(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
229
9.33k
{
230
9.33k
    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.33k
    return 0;
236
9.33k
}
237
238
static void execute_or_enqueue_request_core(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
239
6.38k
{
240
    /* TODO schedule the pending reqs using the scheduler */
241
6.38k
    h2o_linklist_insert(&conn->_pending_reqs, &stream->_link);
242
243
6.38k
    run_pending_requests(conn);
244
6.38k
    update_idle_timeout(conn);
245
6.38k
}
246
247
static void execute_or_enqueue_request(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
248
5.79k
{
249
5.79k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_REQ_PENDING);
250
251
5.79k
    if (reset_stream_if_disregarded(conn, stream))
252
0
        return;
253
254
5.79k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
255
5.79k
    if (!stream->blocked_by_server)
256
5.58k
        h2o_http2_stream_set_blocked_by_server(conn, stream, 1);
257
5.79k
    execute_or_enqueue_request_core(conn, stream);
258
5.79k
}
259
260
void h2o_http2_conn_register_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
261
53.8k
{
262
53.8k
    khiter_t iter;
263
53.8k
    int r;
264
265
53.8k
    iter = kh_put(h2o_http2_stream_t, conn->streams, stream->stream_id, &r);
266
53.8k
    assert(iter != kh_end(conn->streams));
267
53.8k
    kh_val(conn->streams, iter) = stream;
268
53.8k
}
269
270
void h2o_http2_conn_preserve_stream_scheduler(h2o_http2_conn_t *conn, h2o_http2_stream_t *src)
271
53.8k
{
272
53.8k
    assert(h2o_http2_scheduler_is_open(&src->_scheduler));
273
274
53.8k
    h2o_http2_stream_t **dst = conn->_recently_closed_streams.streams + conn->_recently_closed_streams.next_slot;
275
53.8k
    if (++conn->_recently_closed_streams.next_slot == HTTP2_CLOSED_STREAM_PRIORITIES)
276
3.32k
        conn->_recently_closed_streams.next_slot = 0;
277
278
53.8k
    if (*dst != NULL) {
279
27.1k
        assert(h2o_http2_scheduler_is_open(&(*dst)->_scheduler));
280
27.1k
        h2o_http2_scheduler_close(&(*dst)->_scheduler);
281
27.1k
    } else {
282
26.6k
        *dst = h2o_mem_alloc(offsetof(h2o_http2_stream_t, _scheduler) + sizeof((*dst)->_scheduler));
283
26.6k
    }
284
285
53.8k
    (*dst)->stream_id = src->stream_id;
286
53.8k
    h2o_http2_scheduler_relocate(&(*dst)->_scheduler, &src->_scheduler);
287
53.8k
    h2o_http2_scheduler_deactivate(&(*dst)->_scheduler);
288
53.8k
}
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.70k
{
292
3.70k
    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.70k
    switch (new_state) {
295
0
    case H2O_HTTP2_REQ_BODY_NONE:
296
0
        h2o_fatal("invalid state");
297
0
        break;
298
1.29k
    case H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED:
299
1.29k
        assert(stream->req.proceed_req == NULL);
300
1.29k
        if (stream->req_body.streamed) {
301
562
            conn->num_streams._req_streaming_in_progress--;
302
562
            if (stream->req.is_tunnel_req)
303
39
                conn->num_streams.tunnel--;
304
562
        }
305
1.29k
        break;
306
2.41k
    default:
307
2.41k
        break;
308
3.70k
    }
309
3.70k
    stream->req_body.state = new_state;
310
3.70k
}
311
312
void h2o_http2_conn_unregister_stream(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
313
53.8k
{
314
53.8k
    h2o_http2_conn_preserve_stream_scheduler(conn, stream);
315
316
53.8k
    khiter_t iter = kh_get(h2o_http2_stream_t, conn->streams, stream->stream_id);
317
53.8k
    assert(iter != kh_end(conn->streams));
318
53.8k
    kh_del(h2o_http2_stream_t, conn->streams, iter);
319
320
53.8k
    if (stream->req_body.state != H2O_HTTP2_REQ_BODY_NONE && stream->req_body.state < H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED) {
321
864
        stream->req.proceed_req = NULL;
322
864
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
323
864
    }
324
325
53.8k
    if (stream->blocked_by_server)
326
752
        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
53.8k
    if (stream->reset_by_peer || stream->reset_by_peer_action) {
331
29.3k
        if (conn->dos_mitigation.reset_budget > 0)
332
25.0k
            --conn->dos_mitigation.reset_budget;
333
334
        /* setup process delay if we've just ran out of reset budget */
335
29.3k
        if (conn->dos_mitigation.reset_budget == 0 && conn->super.ctx->globalconf->http2.dos_delay != 0 &&
336
4.45k
            !h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
337
143
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->globalconf->http2.dos_delay,
338
143
                           &conn->dos_mitigation.process_delay);
339
340
29.3k
    } else {
341
24.4k
        if (conn->dos_mitigation.reset_budget < conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection)
342
3.90k
            ++conn->dos_mitigation.reset_budget;
343
24.4k
    }
344
345
53.8k
    switch (stream->state) {
346
644
    case H2O_HTTP2_STREAM_STATE_RECV_BODY:
347
644
        if (h2o_linklist_is_linked(&stream->_link))
348
53
            h2o_linklist_unlink(&stream->_link);
349
    /* fallthru */
350
35.0k
    case H2O_HTTP2_STREAM_STATE_IDLE:
351
44.0k
    case H2O_HTTP2_STREAM_STATE_RECV_HEADERS:
352
44.0k
        assert(!h2o_linklist_is_linked(&stream->_link));
353
44.0k
        break;
354
44.0k
    case H2O_HTTP2_STREAM_STATE_REQ_PENDING:
355
148
        assert(h2o_linklist_is_linked(&stream->_link));
356
148
        h2o_linklist_unlink(&stream->_link);
357
148
        break;
358
283
    case H2O_HTTP2_STREAM_STATE_SEND_HEADERS:
359
373
    case H2O_HTTP2_STREAM_STATE_SEND_BODY:
360
4.14k
    case H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL:
361
9.63k
    case H2O_HTTP2_STREAM_STATE_END_STREAM:
362
9.63k
        if (h2o_linklist_is_linked(&stream->_link))
363
9
            h2o_linklist_unlink(&stream->_link);
364
9.63k
        break;
365
53.8k
    }
366
53.8k
    if (stream->state != H2O_HTTP2_STREAM_STATE_END_STREAM)
367
48.3k
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_END_STREAM);
368
369
53.8k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
370
34.6k
        run_pending_requests(conn);
371
34.6k
        update_idle_timeout(conn);
372
34.6k
    }
373
53.8k
}
374
375
void close_connection_now(h2o_http2_conn_t *conn)
376
12.4k
{
377
    /* mark as is_closing here to prevent sending any more frames */
378
12.4k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
379
380
12.4k
    h2o_http2_stream_t *stream;
381
382
12.4k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
383
384
12.4k
    kh_foreach_value(conn->streams, stream, { h2o_http2_stream_close(conn, stream); });
385
386
12.4k
    assert(conn->num_streams.pull.open == 0);
387
12.4k
    assert(conn->num_streams.pull.half_closed == 0);
388
12.4k
    assert(conn->num_streams.pull.send_body == 0);
389
12.4k
    assert(conn->num_streams.push.half_closed == 0);
390
12.4k
    assert(conn->num_streams.push.send_body == 0);
391
12.4k
    assert(conn->num_streams.priority.open == 0);
392
12.4k
    assert(conn->num_streams.blocked_by_server == 0);
393
12.4k
    assert(conn->num_streams._req_streaming_in_progress == 0);
394
12.4k
    assert(conn->num_streams.tunnel == 0);
395
12.4k
    kh_destroy(h2o_http2_stream_t, conn->streams);
396
12.4k
    assert(conn->_http1_req_input == NULL);
397
12.4k
    h2o_hpack_dispose_header_table(&conn->_input_header_table);
398
12.4k
    h2o_hpack_dispose_header_table(&conn->_output_header_table);
399
12.4k
    assert(h2o_linklist_is_empty(&conn->_pending_reqs));
400
12.4k
    h2o_timer_unlink(&conn->_timeout_entry);
401
402
12.4k
    if (h2o_timer_is_linked(&conn->_graceful_shutdown_timeout))
403
0
        h2o_timer_unlink(&conn->_graceful_shutdown_timeout);
404
405
12.4k
    if (h2o_timer_is_linked(&conn->dos_mitigation.process_delay))
406
85
        h2o_timer_unlink(&conn->dos_mitigation.process_delay);
407
408
12.4k
    h2o_buffer_dispose(&conn->_write.buf);
409
12.4k
    if (conn->_write.buf_in_flight != NULL)
410
4
        h2o_buffer_dispose(&conn->_write.buf_in_flight);
411
12.4k
    {
412
12.4k
        size_t i;
413
39.1k
        for (i = 0; i < sizeof(conn->_recently_closed_streams.streams) / sizeof(conn->_recently_closed_streams.streams[0]); ++i) {
414
38.2k
            h2o_http2_stream_t *closed_stream = conn->_recently_closed_streams.streams[i];
415
38.2k
            if (closed_stream == NULL)
416
11.5k
                break;
417
38.2k
            assert(h2o_http2_scheduler_is_open(&closed_stream->_scheduler));
418
26.6k
            h2o_http2_scheduler_close(&closed_stream->_scheduler);
419
26.6k
            free(closed_stream);
420
26.6k
        }
421
12.4k
    }
422
12.4k
    h2o_http2_scheduler_dispose(&conn->scheduler);
423
12.4k
    assert(h2o_linklist_is_empty(&conn->_write.streams_to_proceed));
424
12.4k
    assert(!h2o_timer_is_linked(&conn->_write.timeout_entry));
425
12.4k
    if (conn->_headers_unparsed != NULL)
426
281
        h2o_buffer_dispose(&conn->_headers_unparsed);
427
12.4k
    if (conn->push_memo != NULL)
428
0
        h2o_cache_destroy(conn->push_memo);
429
12.4k
    if (conn->casper != NULL)
430
0
        h2o_http2_casper_destroy(conn->casper);
431
432
12.4k
    if (conn->sock != NULL)
433
12.4k
        h2o_socket_close(conn->sock);
434
435
12.4k
    h2o_destroy_connection(&conn->super);
436
12.4k
}
437
438
int close_connection(h2o_http2_conn_t *conn)
439
25.6k
{
440
25.6k
    conn->state = H2O_HTTP2_CONN_STATE_IS_CLOSING;
441
442
25.6k
    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
12.4k
        close_connection_now(conn);
446
12.4k
        return -1;
447
12.4k
    }
448
13.1k
    return 0;
449
25.6k
}
450
451
static void stream_send_error(h2o_http2_conn_t *conn, uint32_t stream_id, int errnum)
452
34.5k
{
453
34.5k
    assert(stream_id != 0);
454
34.5k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
455
456
34.5k
    conn->super.ctx->http2.events.protocol_level_errors[-errnum]++;
457
458
34.5k
    h2o_http2_encode_rst_stream_frame(&conn->_write.buf, stream_id, -errnum);
459
34.5k
    h2o_http2_conn_request_write(conn);
460
34.5k
}
461
462
static void request_gathered_write(h2o_http2_conn_t *conn)
463
100k
{
464
100k
    assert(conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING);
465
100k
    if (!h2o_socket_is_writing(conn->sock) && !h2o_timer_is_linked(&conn->_write.timeout_entry)) {
466
15.5k
        h2o_timer_link(conn->super.ctx->loop, 0, &conn->_write.timeout_entry);
467
15.5k
    }
468
100k
}
469
470
static int update_stream_output_window(h2o_http2_stream_t *stream, ssize_t delta)
471
14.3k
{
472
14.3k
    ssize_t cur = h2o_http2_window_get_avail(&stream->output_window);
473
14.3k
    if (h2o_http2_window_update(&stream->output_window, delta) != 0)
474
1.06k
        return -1;
475
13.3k
    if (cur <= 0 && h2o_http2_window_get_avail(&stream->output_window) > 0 &&
476
3.98k
        (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL)) {
477
3.02k
        assert(!h2o_linklist_is_linked(&stream->_link));
478
3.02k
        h2o_http2_scheduler_activate(&stream->_scheduler);
479
3.02k
    }
480
13.3k
    return 0;
481
13.3k
}
482
483
static void write_streaming_body(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
484
288
{
485
288
    int is_end_stream = 0;
486
487
288
    assert(stream->req.entity.base == NULL);
488
489
    /* check state as well as update */
490
288
    switch (stream->req_body.state) {
491
0
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
492
189
    case H2O_HTTP2_REQ_BODY_OPEN:
493
189
        assert(stream->req_body.buf->size != 0);
494
189
        break;
495
189
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
496
99
        stream->req.proceed_req = NULL;
497
99
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
498
99
        is_end_stream = 1;
499
99
        break;
500
0
    default:
501
0
        h2o_fatal("unexpected req_body.state");
502
0
        break;
503
288
    }
504
505
    /* invoke write_req */
506
288
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
507
288
    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
288
    if (stream->req_body.state == H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED && stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM)
515
11
        h2o_http2_stream_close(conn, stream);
516
288
}
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.59k
{
520
3.59k
    int is_first = 0;
521
522
3.59k
    switch (stream->req_body.state) {
523
1.02k
    case H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME:
524
1.02k
        is_first = 1;
525
1.02k
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
526
1.02k
        break;
527
2.56k
    case H2O_HTTP2_REQ_BODY_OPEN:
528
2.56k
        break;
529
0
    default:
530
0
        h2o_fatal("unexpected req_body.state");
531
0
        break;
532
3.59k
    }
533
534
3.59k
    stream->req.req_body_bytes_received += payload.len;
535
536
    /* check size */
537
3.59k
    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.59k
    if (stream->req.content_length != SIZE_MAX) {
543
549
        size_t received = stream->req.req_body_bytes_received, cl = stream->req.content_length;
544
549
        if (is_end_stream ? (received != cl) : (received > cl)) {
545
53
            stream_send_error(conn, stream->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
546
53
            h2o_http2_stream_reset(conn, stream);
547
53
            return;
548
53
        }
549
549
    }
550
551
    /* update timer */
552
3.54k
    if (!stream->blocked_by_server)
553
1.23k
        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.54k
    if (reset_stream_if_disregarded(conn, stream))
557
0
        return;
558
559
    /* update state, buffer the data */
560
3.54k
    int req_queued = stream->req.proceed_req != NULL;
561
3.54k
    if (is_end_stream) {
562
346
        if (stream->state < H2O_HTTP2_STREAM_STATE_REQ_PENDING) {
563
319
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
564
319
            if (stream->req.process_called)
565
94
                h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
566
319
        }
567
346
        if (stream->req.write_req.cb != NULL) {
568
102
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_QUEUED);
569
244
        } else {
570
244
            stream->req.proceed_req = NULL;
571
244
            set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
572
244
        }
573
346
    }
574
3.54k
    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.54k
    if (stream->req_body.streamed) {
578
1.50k
        if (stream->req.write_req.cb != NULL) {
579
808
            if (stream->req.entity.base == NULL)
580
262
                write_streaming_body(conn, stream);
581
808
        } else {
582
697
            stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
583
697
        }
584
1.50k
        return;
585
1.50k
    }
586
587
    /* not (yet) in streaming mode */
588
2.03k
    stream->req.entity = h2o_iovec_init(stream->req_body.buf->bytes, stream->req_body.buf->size);
589
590
    /* when receiving first DATA frame... */
591
2.03k
    if (is_first && !is_end_stream) {
592
        /* trigger request streaming mode if possible */
593
784
        if (h2o_req_can_stream_request(&stream->req)) {
594
590
            stream->req.proceed_req = proceed_request;
595
590
            execute_or_enqueue_request_core(conn, stream);
596
590
            return;
597
590
        }
598
        /* or, run in non-streaming mode (TODO elect input streams one by one for non-streaming case as well?) */
599
194
        update_stream_input_window(conn, stream,
600
194
                                   conn->super.ctx->globalconf->http2.active_stream_window_size -
601
194
                                       H2O_HTTP2_SETTINGS_HOST_STREAM_INITIAL_WINDOW_SIZE);
602
194
    }
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.44k
    if (is_end_stream && !req_queued)
606
211
        execute_or_enqueue_request(conn, stream);
607
1.44k
}
608
609
static int send_invalid_request_error(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, const char *err_desc)
610
3.04k
{
611
    /* fast forward the stream's state so that we can start sending the response */
612
3.04k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
613
3.04k
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
614
3.04k
    h2o_send_error_400(&stream->req, "Invalid Request", err_desc, 0);
615
3.04k
    return 0;
616
3.04k
}
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
19.0k
{
621
19.0k
    int ret, header_exists_map = 0;
622
19.0k
    h2o_iovec_t expect = h2o_iovec_init(NULL, 0);
623
624
19.0k
    assert(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS);
625
626
19.0k
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table,
627
19.0k
                                       &stream->req.input.method, &stream->req.input.scheme, &stream->req.input.authority,
628
19.0k
                                       &stream->req.input.path, &stream->req.upgrade, &stream->req.headers, &header_exists_map,
629
19.0k
                                       &stream->req.content_length, &expect, &stream->cache_digests, NULL, src, len, err_desc)) !=
630
19.0k
        0) {
631
        /* all errors except invalid-header-char are connection errors */
632
7.80k
        if (ret != H2O_HTTP2_ERROR_INVALID_HEADER_CHAR)
633
4.35k
            return ret;
634
7.80k
    }
635
636
14.6k
    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
14.6k
    if (stream->req.input.scheme == NULL)
640
4.26k
        stream->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP;
641
642
14.6k
    int is_connect, must_exist_map, may_exist_map;
643
14.6k
    if (h2o_memis(stream->req.input.method.base, stream->req.input.method.len, H2O_STRLIT("CONNECT"))) {
644
51
        is_connect = 1;
645
51
        must_exist_map = H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
646
51
        may_exist_map = 0;
647
        /* extended connect looks like an ordinary request plus an upgrade token (:protocol) */
648
51
        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
14.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
8
        if (!((header_exists_map & H2O_HPACK_PARSE_HEADERS_PROTOCOL_EXISTS) == 0 &&
656
8
              h2o_memis(stream->req.input.path.base, stream->req.input.path.len, H2O_STRLIT("/")))) {
657
7
            ret = H2O_HTTP2_ERROR_PROTOCOL;
658
7
            goto SendRSTStream;
659
7
        }
660
8
        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
14.6k
    } else {
666
        /* normal request */
667
14.6k
        is_connect = 0;
668
14.6k
        must_exist_map =
669
14.6k
            H2O_HPACK_PARSE_HEADERS_METHOD_EXISTS | H2O_HPACK_PARSE_HEADERS_SCHEME_EXISTS | H2O_HPACK_PARSE_HEADERS_PATH_EXISTS;
670
14.6k
        may_exist_map = H2O_HPACK_PARSE_HEADERS_AUTHORITY_EXISTS;
671
14.6k
    }
672
673
    /* check that all MUST pseudo headers exist, and that there are no other pseudo headers than MUST or MAY */
674
14.6k
    if (!((header_exists_map & must_exist_map) == must_exist_map && (header_exists_map & ~(must_exist_map | may_exist_map)) == 0)) {
675
4.33k
        ret = H2O_HTTP2_ERROR_PROTOCOL;
676
4.33k
        goto SendRSTStream;
677
4.33k
    }
678
679
10.3k
    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.3k
    if (ret != 0) {
686
3.03k
        assert(ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR);
687
3.03k
        return send_invalid_request_error(conn, stream, *err_desc);
688
3.03k
    }
689
690
    /* special handling of CONNECT method */
691
7.29k
    if (is_connect) {
692
        /* reject the request if content-length is specified or if the stream has been closed */
693
50
        if (stream->req.content_length != SIZE_MAX || stream->req_body.buf == NULL)
694
11
            return send_invalid_request_error(conn, stream, "Invalid CONNECT request");
695
        /* handle the request */
696
39
        stream->req.is_tunnel_req = 1;
697
39
        goto ProcessImmediately;
698
0
        return 0;
699
50
    }
700
701
    /* handle expect: 100-continue */
702
7.24k
    if (expect.base != NULL) {
703
500
        if (!h2o_lcstris(expect.base, expect.len, H2O_STRLIT("100-continue"))) {
704
500
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_REQ_PENDING);
705
500
            h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_SEND_HEADERS);
706
500
            h2o_send_error_417(&stream->req, "Expectation Failed", "unknown expectation", 0);
707
500
            return 0;
708
500
        }
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.74k
    if (stream->req_body.buf == NULL) {
720
5.48k
        execute_or_enqueue_request(conn, stream);
721
5.48k
    } else {
722
1.25k
        h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
723
1.25k
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME);
724
1.25k
    }
725
6.74k
    return 0;
726
727
4.34k
SendRSTStream:
728
4.34k
    stream->reset_by_peer_action = 1;
729
4.34k
    stream_send_error(conn, stream->stream_id, ret);
730
4.34k
    h2o_http2_stream_reset(conn, stream);
731
4.34k
    return 0;
732
733
39
ProcessImmediately:
734
39
    stream->req.entity = h2o_iovec_init("", 0); /* setting to non-NULL pointer indicates the presence of HTTP payload */
735
39
    stream->req.proceed_req = proceed_request;
736
39
    h2o_http2_stream_set_state(conn, stream, H2O_HTTP2_STREAM_STATE_RECV_BODY);
737
39
    set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_OPEN);
738
39
    process_request(conn, stream);
739
39
    return 0;
740
7.24k
}
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
84
{
745
84
    size_t dummy_content_length;
746
84
    h2o_iovec_t dummy_expect = h2o_iovec_init(NULL, 0);
747
84
    int ret;
748
749
84
    if ((ret = h2o_hpack_parse_request(&stream->req.pool, h2o_hpack_decode_header, &conn->_input_header_table, NULL, NULL, NULL,
750
84
                                       NULL, NULL, &stream->req.headers, NULL, &dummy_content_length, &dummy_expect, NULL, NULL,
751
84
                                       src, len, err_desc)) != 0)
752
13
        return ret;
753
71
    handle_request_body_chunk(conn, stream, h2o_iovec_init(NULL, 0), 1);
754
71
    return 0;
755
84
}
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.39k
{
759
1.39k
    h2o_http2_frame_t frame;
760
1.39k
    ssize_t ret;
761
1.39k
    h2o_http2_stream_t *stream;
762
1.39k
    int hret;
763
764
1.39k
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
765
189
        return ret;
766
1.20k
    if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
767
28
        *err_desc = "expected CONTINUATION frame";
768
28
        return H2O_HTTP2_ERROR_PROTOCOL;
769
28
    }
770
771
1.17k
    if ((stream = h2o_http2_conn_get_stream(conn, frame.stream_id)) == NULL ||
772
1.07k
        !(stream->state == H2O_HTTP2_STREAM_STATE_RECV_HEADERS || stream->state == H2O_HTTP2_STREAM_STATE_RECV_BODY)) {
773
105
        *err_desc = "unexpected stream id in CONTINUATION frame";
774
105
        return H2O_HTTP2_ERROR_PROTOCOL;
775
105
    }
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
25
            conn->_read_expect = expect_default;
784
25
            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
13
            } else {
788
13
                hret = handle_trailing_headers(conn, stream, (const uint8_t *)conn->_headers_unparsed->bytes,
789
13
                                               conn->_headers_unparsed->size, err_desc);
790
13
            }
791
25
            if (hret != 0)
792
9
                ret = hret;
793
25
            h2o_buffer_dispose(&conn->_headers_unparsed);
794
25
            conn->_headers_unparsed = NULL;
795
25
        }
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.17k
}
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
756
{
807
756
    assert(delta <= INT32_MAX);
808
756
    h2o_http2_encode_window_update_frame(&conn->_write.buf, stream_id, (int32_t)delta);
809
756
    h2o_http2_conn_request_write(conn);
810
756
    h2o_http2_window_update(window, delta);
811
756
}
812
813
void update_stream_input_window(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream, size_t delta)
814
2.70k
{
815
2.70k
    stream->input_window.bytes_unnotified += delta;
816
2.70k
    if (stream->input_window.bytes_unnotified >= h2o_http2_window_get_avail(&stream->input_window.window)) {
817
756
        send_window_update(conn, stream->stream_id, &stream->input_window.window, stream->input_window.bytes_unnotified);
818
756
        stream->input_window.bytes_unnotified = 0;
819
756
    }
820
2.70k
}
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
68.5k
{
825
68.5k
    h2o_http2_scheduler_node_t *parent_sched = NULL;
826
827
    /* determine the parent */
828
68.5k
    if (priority->dependency != 0) {
829
56.5k
        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
542k
        for (i = 0; i < HTTP2_CLOSED_STREAM_PRIORITIES; i++) {
836
496k
            if (conn->_recently_closed_streams.streams[i] &&
837
276k
                conn->_recently_closed_streams.streams[i]->stream_id == priority->dependency) {
838
10.5k
                parent_sched = &conn->_recently_closed_streams.streams[i]->_scheduler.node;
839
10.5k
                break;
840
10.5k
            }
841
496k
        }
842
56.5k
        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
45.9k
            h2o_http2_stream_t *parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
848
45.9k
            if (parent_stream != NULL) {
849
5.98k
                parent_sched = &parent_stream->_scheduler.node;
850
40.0k
            } 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
40.0k
                parent_sched = &conn->scheduler;
858
40.0k
                priority = &h2o_http2_default_priority;
859
40.0k
            }
860
45.9k
        } 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.93k
            h2o_http2_scheduler_openref_t *orig_parent_ref =
871
4.93k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched);
872
4.93k
            if (orig_parent_ref->weight < priority->weight || !priority->exclusive) {
873
                /* Turns out the client's dependency tree does not look like Chromium's */
874
20
                conn->is_chromium_dependency_tree = 0;
875
4.91k
            } else {
876
4.91k
                h2o_http2_stream_t *current_parent_stream = h2o_http2_conn_get_stream(conn, priority->dependency);
877
4.91k
                if (current_parent_stream != NULL && orig_parent_ref->weight > current_parent_stream->_scheduler.weight &&
878
3.07k
                    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.07k
                    parent_sched = h2o_http2_scheduler_find_parent_by_weight(&conn->scheduler, priority->weight);
885
3.07k
                    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.01k
                        parent_sched = &current_parent_stream->_scheduler.node;
889
1.01k
                    }
890
3.07k
                }
891
4.91k
            }
892
4.93k
        }
893
56.5k
    } 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
68.5k
    if (priority->exclusive && conn->is_chromium_dependency_tree) {
899
6.88k
        int parent_weight = 256;
900
6.88k
        if (parent_sched->_parent != NULL && parent_sched->_parent->_parent != NULL) {
901
3.56k
            h2o_http2_scheduler_openref_t *parent_ref =
902
3.56k
                H2O_STRUCT_FROM_MEMBER(h2o_http2_scheduler_openref_t, node, parent_sched->_parent);
903
3.56k
            parent_weight = parent_ref->weight;
904
3.56k
        }
905
6.88k
        if (parent_weight < priority->weight) {
906
            /* Child's weight is bigger than parent's -- not Chromium */
907
17
            conn->is_chromium_dependency_tree = 0;
908
17
        }
909
61.6k
    } else {
910
        /* Stream doesn't have the exclusive flag -- not Chromium */
911
61.6k
        conn->is_chromium_dependency_tree = 0;
912
61.6k
    }
913
914
    /* setup the scheduler */
915
68.5k
    if (!scheduler_is_open) {
916
53.7k
        h2o_http2_scheduler_open(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
917
53.7k
    } else {
918
14.8k
        h2o_http2_scheduler_rebind(&stream->_scheduler, parent_sched, priority->weight, priority->exclusive);
919
14.8k
    }
920
68.5k
}
921
922
void proceed_request(h2o_req_t *req, const char *errstr)
923
650
{
924
650
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, req, req);
925
650
    h2o_http2_conn_t *conn = (h2o_http2_conn_t *)stream->req.conn;
926
927
650
    assert(stream->req_body.streamed);
928
929
    /* consume bytes */
930
650
    size_t written = stream->req.entity.len;
931
650
    h2o_buffer_consume(&stream->req_body.buf, written);
932
650
    stream->req.entity = h2o_iovec_init(NULL, 0);
933
934
    /* handle error */
935
650
    if (errstr != NULL) {
936
84
        stream->req.proceed_req = NULL;
937
84
        set_req_body_state(conn, stream, H2O_HTTP2_REQ_BODY_CLOSE_DELIVERED);
938
84
        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
84
            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
84
            stream_send_error(conn, stream->stream_id,
948
84
                              errstr == h2o_httpclient_error_is_eos ? H2O_HTTP2_ERROR_NONE : H2O_HTTP2_ERROR_STREAM_CLOSED);
949
84
            h2o_http2_scheduler_deactivate(&stream->_scheduler);
950
84
            if (!h2o_linklist_is_linked(&stream->_link))
951
83
                h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
952
84
            h2o_http2_stream_reset(conn, stream);
953
84
        }
954
84
        return;
955
84
    }
956
957
566
    switch (stream->req_body.state) {
958
558
    case H2O_HTTP2_REQ_BODY_OPEN:
959
558
        update_stream_input_window(conn, stream, written);
960
558
        if (stream->blocked_by_server && h2o_http2_window_get_avail(&stream->input_window.window) > 0) {
961
543
            h2o_http2_stream_set_blocked_by_server(conn, stream, 0);
962
543
            update_idle_timeout(conn);
963
543
        }
964
558
        if (stream->req_body.buf->size != 0)
965
18
            write_streaming_body(conn, stream);
966
558
        break;
967
8
    case H2O_HTTP2_REQ_BODY_CLOSE_QUEUED:
968
8
        assert(written != 0);
969
8
        write_streaming_body(conn, stream);
970
8
        break;
971
0
    default:
972
0
        h2o_fatal("unexpected req_body_state");
973
566
    }
974
566
}
975
976
static int handle_data_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
977
26.8k
{
978
26.8k
    h2o_http2_data_payload_t payload;
979
26.8k
    h2o_http2_stream_t *stream;
980
26.8k
    int ret;
981
982
26.8k
    if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
983
54
        return ret;
984
985
    /* update connection-level window */
986
26.7k
    h2o_http2_window_consume_window(&conn->_input_window, frame->length);
987
26.7k
    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.7k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
993
3.54k
        if (frame->stream_id <= conn->pull_stream_ids.max_open) {
994
3.23k
            stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_STREAM_CLOSED);
995
3.23k
            return 0;
996
3.23k
        } else {
997
304
            *err_desc = "invalid DATA frame";
998
304
            return H2O_HTTP2_ERROR_PROTOCOL;
999
304
        }
1000
3.54k
    }
1001
23.2k
    if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
1002
22.0k
          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
4.15k
    h2o_http2_window_consume_window(&stream->input_window.window, frame->length);
1012
4.15k
    if (frame->length != payload.length)
1013
1.38k
        update_stream_input_window(conn, stream, frame->length - payload.length);
1014
1015
    /* actually handle the input */
1016
4.15k
    if (payload.length != 0 || (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0)
1017
3.52k
        handle_request_body_chunk(conn, stream, h2o_iovec_init(payload.data, payload.length),
1018
3.52k
                                  (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0);
1019
1020
4.15k
    return 0;
1021
23.2k
}
1022
1023
static int handle_headers_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1024
19.5k
{
1025
19.5k
    h2o_http2_headers_payload_t payload;
1026
19.5k
    h2o_http2_stream_t *stream;
1027
19.5k
    int ret;
1028
1029
    /* decode */
1030
19.5k
    if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
1031
41
        return ret;
1032
19.5k
    if ((frame->stream_id & 1) == 0) {
1033
18
        *err_desc = "invalid stream id in HEADERS frame";
1034
18
        return H2O_HTTP2_ERROR_PROTOCOL;
1035
18
    }
1036
19.5k
    if (frame->stream_id <= conn->pull_stream_ids.max_open) {
1037
217
        if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL) {
1038
127
            *err_desc = "closed stream id in HEADERS frame";
1039
127
            return H2O_HTTP2_ERROR_STREAM_CLOSED;
1040
127
        }
1041
90
        if (!(stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN_BEFORE_FIRST_FRAME ||
1042
17
              stream->req_body.state == H2O_HTTP2_REQ_BODY_OPEN)) {
1043
12
            *err_desc = "invalid stream id in HEADERS frame";
1044
12
            return H2O_HTTP2_ERROR_PROTOCOL;
1045
12
        }
1046
1047
        /* is a trailer */
1048
78
        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
77
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0) {
1053
3
            *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
1054
3
            return H2O_HTTP2_ERROR_PROTOCOL;
1055
3
        }
1056
74
        if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0)
1057
3
            goto PREPARE_FOR_CONTINUATION;
1058
71
        return handle_trailing_headers(conn, stream, payload.headers, payload.headers_len, err_desc);
1059
74
    }
1060
19.3k
    if (frame->stream_id == payload.priority.dependency) {
1061
6
        *err_desc = "stream cannot depend on itself";
1062
6
        return H2O_HTTP2_ERROR_PROTOCOL;
1063
6
    }
1064
1065
    /* open or determine the stream and prepare */
1066
19.3k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1067
35
        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
19.2k
    } else {
1072
19.2k
        conn->received_any_request = 1;
1073
19.2k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload.priority);
1074
19.2k
        set_priority(conn, stream, &payload.priority, 0);
1075
19.2k
    }
1076
19.3k
    h2o_http2_stream_prepare_for_request(conn, stream);
1077
1078
    /* setup container for request body if it is expected to arrive */
1079
19.3k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) == 0)
1080
6.53k
        h2o_buffer_init(&stream->req_body.buf, &h2o_socket_buffer_prototype);
1081
1082
19.3k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
1083
        /* request headers are complete, handle it */
1084
19.0k
        return handle_incoming_request(conn, stream, payload.headers, payload.headers_len, err_desc);
1085
19.0k
    }
1086
1087
306
PREPARE_FOR_CONTINUATION:
1088
    /* request is not complete, store in buffer */
1089
306
    conn->_read_expect = expect_continuation_of_headers;
1090
306
    h2o_buffer_init(&conn->_headers_unparsed, &h2o_socket_buffer_prototype);
1091
306
    h2o_buffer_reserve(&conn->_headers_unparsed, payload.headers_len);
1092
306
    memcpy(conn->_headers_unparsed->bytes, payload.headers, payload.headers_len);
1093
306
    conn->_headers_unparsed->size = payload.headers_len;
1094
306
    return 0;
1095
19.3k
}
1096
1097
static int handle_priority_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1098
51.6k
{
1099
51.6k
    h2o_http2_priority_t payload;
1100
51.6k
    h2o_http2_stream_t *stream;
1101
51.6k
    int ret;
1102
1103
51.6k
    if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
1104
54
        return ret;
1105
51.6k
    if (frame->stream_id == payload.dependency) {
1106
4
        *err_desc = "stream cannot depend on itself";
1107
4
        return H2O_HTTP2_ERROR_PROTOCOL;
1108
4
    }
1109
1110
51.6k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) != NULL) {
1111
14.8k
        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
14.8k
        if (h2o_http2_scheduler_get_weight(&stream->_scheduler) != 257)
1116
14.8k
            set_priority(conn, stream, &payload, 1);
1117
36.7k
    } else {
1118
36.7k
        if (h2o_http2_stream_is_push(frame->stream_id)) {
1119
            /* Ignore PRIORITY frames for closed or idle pushed streams */
1120
1.28k
            return 0;
1121
35.5k
        } else {
1122
            /* Ignore PRIORITY frames for closed pull streams */
1123
35.5k
            if (frame->stream_id <= conn->pull_stream_ids.max_open)
1124
1.06k
                return 0;
1125
35.5k
        }
1126
34.4k
        if (conn->num_streams.priority.open >= conn->super.ctx->globalconf->http2.max_streams_for_priority) {
1127
8
            *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
8
            return H2O_HTTP2_ERROR_ENHANCE_YOUR_CALM;
1132
8
        }
1133
34.4k
        stream = h2o_http2_stream_open(conn, frame->stream_id, NULL, &payload);
1134
34.4k
        set_priority(conn, stream, &payload, 0);
1135
34.4k
    }
1136
1137
49.2k
    return 0;
1138
51.6k
}
1139
1140
static void resume_send(h2o_http2_conn_t *conn)
1141
13.7k
{
1142
13.7k
    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
13.7k
    request_gathered_write(conn);
1149
13.7k
}
1150
1151
static int handle_settings_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1152
13.3k
{
1153
13.3k
    if (frame->stream_id != 0) {
1154
86
        *err_desc = "invalid stream id in SETTINGS frame";
1155
86
        return H2O_HTTP2_ERROR_PROTOCOL;
1156
86
    }
1157
1158
13.2k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
1159
868
        if (frame->length != 0) {
1160
12
            *err_desc = "invalid SETTINGS frame (+ACK)";
1161
12
            return H2O_HTTP2_ERROR_FRAME_SIZE;
1162
12
        }
1163
856
        if (h2o_timeval_is_null(&conn->timestamps.settings_acked_at) && !h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1164
223
            conn->timestamps.settings_acked_at = h2o_gettimeofday(conn->super.ctx->loop);
1165
223
        }
1166
12.3k
    } else {
1167
12.3k
        uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
1168
12.3k
        int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
1169
12.3k
        if (ret != 0)
1170
203
            return ret;
1171
12.1k
        { /* schedule ack */
1172
12.1k
            h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->_write.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
1173
12.1k
            h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
1174
12.1k
            conn->_write.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
1175
12.1k
            h2o_http2_conn_request_write(conn);
1176
12.1k
        }
1177
        /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
1178
12.1k
        if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
1179
8.57k
            ssize_t delta = (int32_t)conn->peer_settings.initial_window_size - (int32_t)prev_initial_window_size;
1180
8.57k
            h2o_http2_stream_t *stream;
1181
8.57k
            kh_foreach_value(conn->streams, stream, { update_stream_output_window(stream, delta); });
1182
8.57k
            resume_send(conn);
1183
8.57k
        }
1184
12.1k
    }
1185
1186
13.0k
    return 0;
1187
13.2k
}
1188
1189
static int handle_window_update_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1190
13.0k
{
1191
13.0k
    h2o_http2_window_update_payload_t payload;
1192
13.0k
    int ret, err_is_stream_level;
1193
1194
13.0k
    if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
1195
7.75k
        if (err_is_stream_level) {
1196
7.72k
            h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1197
7.72k
            if (stream != NULL) {
1198
5.91k
                stream->reset_by_peer_action = 1;
1199
5.91k
                h2o_http2_stream_reset(conn, stream);
1200
5.91k
            }
1201
7.72k
            stream_send_error(conn, frame->stream_id, ret);
1202
7.72k
            return 0;
1203
7.72k
        } else {
1204
29
            return ret;
1205
29
        }
1206
7.75k
    }
1207
1208
5.26k
    if (frame->stream_id == 0) {
1209
1.23k
        if (h2o_http2_window_update(&conn->_write.window, payload.window_size_increment) != 0) {
1210
9
            *err_desc = "flow control window overflow";
1211
9
            return H2O_HTTP2_ERROR_FLOW_CONTROL;
1212
9
        }
1213
4.02k
    } else if (!is_idle_stream_id(conn, frame->stream_id)) {
1214
3.95k
        h2o_http2_stream_t *stream = h2o_http2_conn_get_stream(conn, frame->stream_id);
1215
3.95k
        if (stream != NULL) {
1216
2.06k
            if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
1217
26
                stream->reset_by_peer_action = 1;
1218
26
                h2o_http2_stream_reset(conn, stream);
1219
26
                stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
1220
26
                return 0;
1221
26
            }
1222
2.06k
        }
1223
3.95k
    } else {
1224
72
        *err_desc = "invalid stream id in WINDOW_UPDATE frame";
1225
72
        return H2O_HTTP2_ERROR_PROTOCOL;
1226
72
    }
1227
1228
5.15k
    resume_send(conn);
1229
1230
5.15k
    return 0;
1231
5.26k
}
1232
1233
static int handle_goaway_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1234
655
{
1235
655
    h2o_http2_goaway_payload_t payload;
1236
655
    int ret;
1237
1238
655
    if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
1239
69
        return ret;
1240
1241
    /* stop opening new push streams hereafter */
1242
586
    conn->push_stream_ids.max_open = 0x7ffffffe;
1243
1244
586
    return 0;
1245
655
}
1246
1247
static int handle_ping_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1248
1.84k
{
1249
1.84k
    h2o_http2_ping_payload_t payload;
1250
1.84k
    int ret;
1251
1252
1.84k
    if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
1253
82
        return ret;
1254
1255
1.76k
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
1256
1.23k
        h2o_http2_encode_ping_frame(&conn->_write.buf, 1, payload.data);
1257
1.23k
        h2o_http2_conn_request_write(conn);
1258
1.23k
    }
1259
1260
1.76k
    return 0;
1261
1.84k
}
1262
1263
static int handle_rst_stream_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1264
1.59k
{
1265
1.59k
    h2o_http2_rst_stream_payload_t payload;
1266
1.59k
    h2o_http2_stream_t *stream;
1267
1.59k
    int ret;
1268
1269
1.59k
    if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
1270
55
        return ret;
1271
1.53k
    if (is_idle_stream_id(conn, frame->stream_id)) {
1272
52
        *err_desc = "unexpected stream id in RST_STREAM frame";
1273
52
        return H2O_HTTP2_ERROR_PROTOCOL;
1274
52
    }
1275
1276
1.48k
    if ((stream = h2o_http2_conn_get_stream(conn, frame->stream_id)) == NULL)
1277
1.47k
        return 0;
1278
1279
    /* reset the stream */
1280
14
    stream->reset_by_peer = 1;
1281
14
    h2o_http2_stream_reset(conn, stream);
1282
1283
    /* TODO log */
1284
1285
14
    return 0;
1286
1.48k
}
1287
1288
static int handle_push_promise_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1289
22
{
1290
22
    *err_desc = "received PUSH_PROMISE frame";
1291
22
    return H2O_HTTP2_ERROR_PROTOCOL;
1292
22
}
1293
1294
static int handle_invalid_continuation_frame(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
1295
7
{
1296
7
    *err_desc = "received invalid CONTINUATION frame";
1297
7
    return H2O_HTTP2_ERROR_PROTOCOL;
1298
7
}
1299
1300
ssize_t expect_default(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1301
137k
{
1302
137k
    h2o_http2_frame_t frame;
1303
137k
    ssize_t ret;
1304
137k
    static int (*FRAME_HANDLERS[])(h2o_http2_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc) = {
1305
137k
        handle_data_frame,                /* DATA */
1306
137k
        handle_headers_frame,             /* HEADERS */
1307
137k
        handle_priority_frame,            /* PRIORITY */
1308
137k
        handle_rst_stream_frame,          /* RST_STREAM */
1309
137k
        handle_settings_frame,            /* SETTINGS */
1310
137k
        handle_push_promise_frame,        /* PUSH_PROMISE */
1311
137k
        handle_ping_frame,                /* PING */
1312
137k
        handle_goaway_frame,              /* GOAWAY */
1313
137k
        handle_window_update_frame,       /* WINDOW_UPDATE */
1314
137k
        handle_invalid_continuation_frame /* CONTINUATION */
1315
137k
    };
1316
1317
137k
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_HOST_MAX_FRAME_SIZE, err_desc)) < 0)
1318
5.70k
        return ret;
1319
1320
131k
    if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
1321
128k
        int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
1322
128k
        if (hret != 0)
1323
5.68k
            ret = hret;
1324
128k
    } else {
1325
3.31k
        H2O_PROBE_CONN(H2_UNKNOWN_FRAME_TYPE, &conn->super, frame.type);
1326
3.31k
    }
1327
1328
131k
    return ret;
1329
137k
}
1330
1331
static ssize_t expect_preface(h2o_http2_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
1332
12.6k
{
1333
12.6k
    if (len < CONNECTION_PREFACE.len) {
1334
284
        return H2O_HTTP2_ERROR_INCOMPLETE;
1335
284
    }
1336
12.3k
    if (memcmp(src, CONNECTION_PREFACE.base, CONNECTION_PREFACE.len) != 0) {
1337
166
        return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
1338
166
    }
1339
1340
12.1k
    {
1341
12.1k
        enqueue_server_preface(conn);
1342
12.1k
        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.1k
        if (h2o_timeval_is_null(&conn->timestamps.settings_sent_at)) {
1347
12.1k
            conn->timestamps.settings_sent_at = h2o_gettimeofday(conn->super.ctx->loop);
1348
12.1k
        }
1349
12.1k
        h2o_http2_conn_request_write(conn);
1350
12.1k
    }
1351
1352
12.1k
    conn->_read_expect = expect_default;
1353
12.1k
    return CONNECTION_PREFACE.len;
1354
12.3k
}
1355
1356
static int parse_input(h2o_http2_conn_t *conn)
1357
16.0k
{
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
151k
        const char *err_desc = NULL;
1362
151k
        ssize_t ret = conn->_read_expect(conn, (uint8_t *)conn->sock->input->bytes, conn->sock->input->size, &err_desc);
1363
151k
        if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
1364
5.47k
            break;
1365
146k
        } else if (ret < 0) {
1366
6.70k
            if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
1367
6.53k
                enqueue_goaway(conn, (int)ret,
1368
6.53k
                               err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
1369
6.53k
            }
1370
6.70k
            return close_connection(conn);
1371
6.70k
        }
1372
        /* advance to the next frame */
1373
139k
        h2o_buffer_consume(&conn->sock->input, ret);
1374
139k
    }
1375
9.36k
    return 0;
1376
16.0k
}
1377
1378
static void on_read(h2o_socket_t *sock, const char *err)
1379
21.8k
{
1380
21.8k
    h2o_http2_conn_t *conn = sock->data;
1381
1382
21.8k
    if (err != NULL) {
1383
5.76k
        conn->super.ctx->http2.events.read_closed++;
1384
5.76k
        h2o_socket_read_stop(conn->sock);
1385
5.76k
        close_connection(conn);
1386
5.76k
        return;
1387
5.76k
    }
1388
1389
    /* dispatch requests blocked by 425 when TLS handshake is complete */
1390
16.0k
    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.0k
    if (parse_input(conn) != 0)
1405
170
        return;
1406
15.9k
    update_idle_timeout(conn);
1407
1408
    /* write immediately, if there is no write in flight and if pending write exists */
1409
15.9k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry)) {
1410
14.3k
        h2o_timer_unlink(&conn->_write.timeout_entry);
1411
14.3k
        do_emit_writereq(conn);
1412
14.3k
    }
1413
15.9k
}
1414
1415
static void on_upgrade_complete(void *_conn, h2o_socket_t *sock, size_t reqsize)
1416
99
{
1417
99
    h2o_http2_conn_t *conn = _conn;
1418
1419
99
    if (sock == NULL) {
1420
0
        close_connection(conn);
1421
0
        return;
1422
0
    }
1423
1424
99
    conn->sock = sock;
1425
99
    sock->data = conn;
1426
99
    conn->_http1_req_input = sock->input;
1427
99
    h2o_buffer_init(&sock->input, &h2o_socket_buffer_prototype);
1428
1429
99
    enqueue_server_preface(conn);
1430
99
    h2o_http2_conn_request_write(conn);
1431
1432
    /* setup inbound */
1433
99
    h2o_socket_read_start(conn->sock, on_read);
1434
1435
    /* handle the request */
1436
99
    execute_or_enqueue_request(conn, h2o_http2_conn_get_stream(conn, 1));
1437
1438
99
    if (conn->_http1_req_input->size > reqsize) {
1439
35
        size_t remaining_bytes = conn->_http1_req_input->size - reqsize;
1440
35
        h2o_buffer_reserve(&sock->input, remaining_bytes);
1441
35
        memcpy(sock->input->bytes, conn->_http1_req_input->bytes + reqsize, remaining_bytes);
1442
35
        sock->input->size += remaining_bytes;
1443
35
        on_read(conn->sock, NULL);
1444
35
    }
1445
99
}
1446
1447
static size_t bytes_in_buf(h2o_http2_conn_t *conn)
1448
86.6k
{
1449
86.6k
    size_t size = conn->_write.buf->size;
1450
86.6k
    if (conn->_write.buf_in_flight != 0)
1451
35
        size += conn->_write.buf_in_flight->size;
1452
86.6k
    return size;
1453
86.6k
}
1454
1455
void h2o_http2_conn_request_write(h2o_http2_conn_t *conn)
1456
86.7k
{
1457
86.7k
    if (conn->state == H2O_HTTP2_CONN_STATE_IS_CLOSING)
1458
0
        return;
1459
86.7k
    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.7k
    request_gathered_write(conn);
1462
86.7k
}
1463
1464
void h2o_http2_conn_register_for_proceed_callback(h2o_http2_conn_t *conn, h2o_http2_stream_t *stream)
1465
9.93k
{
1466
9.93k
    h2o_http2_conn_request_write(conn);
1467
1468
9.93k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1469
9.93k
        if (h2o_http2_window_get_avail(&stream->output_window) > 0) {
1470
9.57k
            assert(!h2o_linklist_is_linked(&stream->_link));
1471
9.57k
            h2o_http2_scheduler_activate(&stream->_scheduler);
1472
9.57k
        }
1473
9.93k
    } else {
1474
0
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1475
0
    }
1476
9.93k
}
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
100
{
1489
100
    h2o_http2_conn_t *conn = sock->data;
1490
1491
100
    if (err != NULL) {
1492
0
        close_connection_now(conn);
1493
0
        return;
1494
0
    }
1495
100
    do_emit_writereq(conn);
1496
100
}
1497
1498
static void on_write_complete(h2o_socket_t *sock, const char *err)
1499
15.3k
{
1500
15.3k
    h2o_http2_conn_t *conn = sock->data;
1501
1502
15.3k
    assert(conn->_write.buf_in_flight != NULL);
1503
1504
    /* close by error if necessary */
1505
15.3k
    if (err != NULL) {
1506
4
        conn->super.ctx->http2.events.write_closed++;
1507
4
        close_connection_now(conn);
1508
4
        return;
1509
4
    }
1510
1511
    /* reset the other memory pool */
1512
15.3k
    h2o_buffer_dispose(&conn->_write.buf_in_flight);
1513
15.3k
    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
15.3k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1517
14.8k
        while (!h2o_linklist_is_empty(&conn->_write.streams_to_proceed)) {
1518
6.08k
            h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _link, conn->_write.streams_to_proceed.next);
1519
6.08k
            assert(!h2o_http2_stream_has_pending_data(stream));
1520
6.08k
            h2o_linklist_unlink(&stream->_link);
1521
6.08k
            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.08k
            h2o_http2_stream_proceed(conn, stream);
1526
6.08k
        }
1527
8.78k
    }
1528
1529
    /* update the timeout now that the states have been updated */
1530
15.3k
    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
15.3k
    if (h2o_timer_is_linked(&conn->_write.timeout_entry))
1534
109
        h2o_timer_unlink(&conn->_write.timeout_entry);
1535
1536
15.3k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING) {
1537
8.78k
        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
8.78k
    }
1540
1541
15.3k
#if !H2O_USE_LIBUV
1542
15.3k
    if (conn->state == H2O_HTTP2_CONN_STATE_OPEN) {
1543
8.78k
        if (conn->_write.buf->size != 0 || h2o_http2_scheduler_is_active(&conn->scheduler))
1544
119
            h2o_socket_notify_write(sock, on_notify_write);
1545
8.78k
        return;
1546
8.78k
    }
1547
6.55k
#endif
1548
1549
    /* write more, if possible */
1550
6.55k
    do_emit_writereq(conn);
1551
6.55k
}
1552
1553
static int emit_writereq_of_openref(h2o_http2_scheduler_openref_t *ref, int *still_is_active, void *cb_arg)
1554
7.57k
{
1555
7.57k
    h2o_http2_conn_t *conn = cb_arg;
1556
7.57k
    h2o_http2_stream_t *stream = H2O_STRUCT_FROM_MEMBER(h2o_http2_stream_t, _scheduler, ref);
1557
1558
7.57k
    assert(h2o_http2_stream_has_pending_data(stream) || stream->state >= H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL);
1559
1560
7.57k
    *still_is_active = 0;
1561
1562
7.57k
    h2o_http2_stream_send_pending_data(conn, stream);
1563
7.57k
    if (h2o_http2_stream_has_pending_data(stream) || stream->state == H2O_HTTP2_STREAM_STATE_SEND_BODY_IS_FINAL) {
1564
1.57k
        if (h2o_http2_window_get_avail(&stream->output_window) <= 0) {
1565
            /* is blocked */
1566
1.57k
        } else {
1567
0
            *still_is_active = 1;
1568
0
        }
1569
6.00k
    } else {
1570
6.00k
        if (stream->state == H2O_HTTP2_STREAM_STATE_END_STREAM) {
1571
5.37k
            h2o_iovec_t server_timing;
1572
5.37k
            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.37k
            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.37k
        }
1585
6.00k
        h2o_linklist_insert(&conn->_write.streams_to_proceed, &stream->_link);
1586
6.00k
    }
1587
1588
7.57k
    return h2o_http2_conn_get_buffer_window(conn) > 0 ? 0 : -1;
1589
7.57k
}
1590
1591
void do_emit_writereq(h2o_http2_conn_t *conn)
1592
22.1k
{
1593
22.1k
    assert(conn->_write.buf_in_flight == NULL);
1594
1595
    /* push DATA frames */
1596
22.1k
    if (conn->state < H2O_HTTP2_CONN_STATE_IS_CLOSING && h2o_http2_conn_get_buffer_window(conn) > 0)
1597
8.97k
        h2o_http2_scheduler_run(&conn->scheduler, emit_writereq_of_openref, conn);
1598
1599
22.1k
    if (conn->_write.buf->size != 0) {
1600
        /* write and wait for completion */
1601
15.3k
        h2o_iovec_t buf = {conn->_write.buf->bytes, conn->_write.buf->size};
1602
15.3k
        h2o_socket_write(conn->sock, &buf, 1, on_write_complete);
1603
15.3k
        conn->_write.buf_in_flight = conn->_write.buf;
1604
15.3k
        h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1605
15.3k
        h2o_timer_unlink(&conn->_timeout_entry);
1606
15.3k
        h2o_timer_link(conn->super.ctx->loop, H2O_HTTP2_DEFAULT_OUTBUF_WRITE_TIMEOUT, &conn->_timeout_entry);
1607
15.3k
    }
1608
1609
    /* close the connection if necessary */
1610
22.1k
    switch (conn->state) {
1611
8.97k
    case H2O_HTTP2_CONN_STATE_OPEN:
1612
8.97k
        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
13.1k
    case H2O_HTTP2_CONN_STATE_IS_CLOSING:
1619
13.1k
        close_connection(conn);
1620
13.1k
        break;
1621
22.1k
    }
1622
22.1k
}
1623
1624
static void emit_writereq(h2o_timer_t *entry)
1625
1.11k
{
1626
1.11k
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, _write.timeout_entry, entry);
1627
1628
1.11k
    do_emit_writereq(conn);
1629
1.11k
}
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.09k
{
1639
1.09k
    h2o_http2_conn_t *conn = (void *)_conn;
1640
1.09k
    return h2o_socket_getpeername(conn->sock, sa);
1641
1.09k
}
1642
1643
static ptls_t *get_ptls(h2o_conn_t *_conn)
1644
1.09k
{
1645
1.09k
    struct st_h2o_http2_conn_t *conn = (void *)_conn;
1646
1.09k
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1647
1.09k
    return h2o_socket_get_ptls(conn->sock);
1648
1.09k
}
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
58
{
1780
58
    h2o_http2_conn_t *conn = H2O_STRUCT_FROM_MEMBER(h2o_http2_conn_t, dos_mitigation.process_delay, timer);
1781
1782
58
    assert(!h2o_timer_is_linked(&conn->dos_mitigation.process_delay));
1783
58
    run_pending_requests(conn);
1784
58
}
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.0k
{
1788
13.0k
    static const h2o_conn_callbacks_t callbacks = {
1789
13.0k
        .get_sockname = get_sockname,
1790
13.0k
        .get_peername = get_peername,
1791
13.0k
        .get_ptls = get_ptls,
1792
13.0k
        .get_ssl_server_name = get_ssl_server_name,
1793
13.0k
        .log_state = log_state,
1794
13.0k
        .get_req_id = get_req_id,
1795
13.0k
        .push_path = push_path,
1796
13.0k
        .get_debug_state = h2o_http2_get_debug_state,
1797
13.0k
        .close_idle_connection = close_idle_connection,
1798
13.0k
        .foreach_request = foreach_request,
1799
13.0k
        .request_shutdown = initiate_graceful_shutdown,
1800
13.0k
        .get_rtt = get_rtt,
1801
13.0k
        .log_ = {{
1802
13.0k
            .transport =
1803
13.0k
                {
1804
13.0k
                    .cc_name = log_tcp_congestion_controller,
1805
13.0k
                    .delivery_rate = log_tcp_delivery_rate,
1806
13.0k
                },
1807
13.0k
            .ssl =
1808
13.0k
                {
1809
13.0k
                    .protocol_version = log_ssl_protocol_version,
1810
13.0k
                    .session_reused = log_ssl_session_reused,
1811
13.0k
                    .cipher = log_ssl_cipher,
1812
13.0k
                    .cipher_bits = log_ssl_cipher_bits,
1813
13.0k
                    .session_id = log_ssl_session_id,
1814
13.0k
                    .negotiated_protocol = log_ssl_negotiated_protocol,
1815
13.0k
                    .ech_config_id = log_ssl_ech_config_id,
1816
13.0k
                    .ech_kem = log_ssl_ech_kem,
1817
13.0k
                    .ech_cipher = log_ssl_ech_cipher,
1818
13.0k
                    .ech_cipher_bits = log_ssl_ech_cipher_bits,
1819
13.0k
                    .backend = log_ssl_backend,
1820
13.0k
                },
1821
13.0k
            .http2 =
1822
13.0k
                {
1823
13.0k
                    .stream_id = log_stream_id,
1824
13.0k
                    .priority_received = log_priority_received,
1825
13.0k
                    .priority_received_exclusive = log_priority_received_exclusive,
1826
13.0k
                    .priority_received_parent = log_priority_received_parent,
1827
13.0k
                    .priority_received_weight = log_priority_received_weight,
1828
13.0k
                    .priority_actual = log_priority_actual,
1829
13.0k
                    .priority_actual_parent = log_priority_actual_parent,
1830
13.0k
                    .priority_actual_weight = log_priority_actual_weight,
1831
13.0k
                },
1832
13.0k
        }},
1833
13.0k
    };
1834
1835
13.0k
    h2o_http2_conn_t *conn = (void *)h2o_create_connection(sizeof(*conn), ctx, hosts, connected_at, &callbacks);
1836
1837
13.0k
    memset((char *)conn + sizeof(conn->super), 0, sizeof(*conn) - sizeof(conn->super));
1838
13.0k
    conn->sock = sock;
1839
13.0k
    conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
1840
13.0k
    conn->streams = kh_init(h2o_http2_stream_t);
1841
13.0k
    h2o_http2_scheduler_init(&conn->scheduler);
1842
13.0k
    conn->state = H2O_HTTP2_CONN_STATE_OPEN;
1843
13.0k
    conn->_read_expect = expect_preface;
1844
13.0k
    conn->_input_header_table.hpack_capacity = conn->_input_header_table.hpack_max_capacity =
1845
13.0k
        H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1846
13.0k
    h2o_http2_window_init(&conn->_input_window, H2O_HTTP2_SETTINGS_HOST_CONNECTION_WINDOW_SIZE);
1847
13.0k
    conn->_output_header_table.hpack_capacity = H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1848
13.0k
    h2o_linklist_init_anchor(&conn->_pending_reqs);
1849
13.0k
    h2o_buffer_init(&conn->_write.buf, &h2o_http2_wbuf_buffer_prototype);
1850
13.0k
    h2o_linklist_init_anchor(&conn->_write.streams_to_proceed);
1851
13.0k
    conn->_write.timeout_entry.cb = emit_writereq;
1852
13.0k
    h2o_http2_window_init(&conn->_write.window, conn->peer_settings.initial_window_size);
1853
13.0k
    h2o_linklist_init_anchor(&conn->early_data.blocked_streams);
1854
13.0k
    conn->is_chromium_dependency_tree = 1; /* initially assume the client is Chromium until proven otherwise */
1855
13.0k
    conn->received_any_request = 0;
1856
13.0k
    conn->dos_mitigation.process_delay.cb = on_dos_process_delay;
1857
13.0k
    conn->dos_mitigation.reset_budget = conn->super.ctx->globalconf->http2.max_concurrent_requests_per_connection;
1858
1859
13.0k
    return conn;
1860
13.0k
}
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
12.3k
{
1980
12.3k
    h2o_http2_conn_t *conn = create_conn(ctx->ctx, ctx->hosts, sock, connected_at);
1981
12.3k
    conn->http2_origin_frame = ctx->http2_origin_frame;
1982
12.3k
    sock->data = conn;
1983
12.3k
    h2o_socket_read_start(conn->sock, on_read);
1984
12.3k
    update_idle_timeout(conn);
1985
12.3k
    if (sock->input->size != 0)
1986
4.56k
        on_read(sock, 0);
1987
12.3k
}
1988
1989
int h2o_http2_handle_upgrade(h2o_req_t *req, struct timeval connected_at)
1990
633
{
1991
633
    h2o_http2_conn_t *http2conn = create_conn(req->conn->ctx, req->conn->hosts, NULL, connected_at);
1992
633
    h2o_http2_stream_t *stream;
1993
633
    ssize_t connection_index, settings_index;
1994
633
    h2o_iovec_t settings_decoded;
1995
633
    const char *err_desc;
1996
1997
633
    assert(req->version < 0x200); /* from HTTP/1.x */
1998
1999
    /* check that "HTTP2-Settings" is declared in the connection header */
2000
633
    connection_index = h2o_find_header(&req->headers, H2O_TOKEN_CONNECTION, -1);
2001
633
    assert(connection_index != -1);
2002
633
    if (!h2o_contains_token(req->headers.entries[connection_index].value.base, req->headers.entries[connection_index].value.len,
2003
633
                            H2O_STRLIT("http2-settings"), ',')) {
2004
245
        goto Error;
2005
245
    }
2006
2007
    /* decode the settings */
2008
388
    if ((settings_index = h2o_find_header(&req->headers, H2O_TOKEN_HTTP2_SETTINGS, -1)) == -1) {
2009
114
        goto Error;
2010
114
    }
2011
274
    if ((settings_decoded = h2o_decode_base64url(&req->pool, req->headers.entries[settings_index].value.base,
2012
274
                                                 req->headers.entries[settings_index].value.len))
2013
274
            .base == NULL) {
2014
39
        goto Error;
2015
39
    }
2016
235
    if (h2o_http2_update_peer_settings(&http2conn->peer_settings, (uint8_t *)settings_decoded.base, settings_decoded.len,
2017
235
                                       &err_desc) != 0) {
2018
136
        goto Error;
2019
136
    }
2020
2021
    /* open the stream, now that the function is guaranteed to succeed */
2022
99
    stream = h2o_http2_stream_open(http2conn, 1, req, &h2o_http2_default_priority);
2023
99
    h2o_http2_scheduler_open(&stream->_scheduler, &http2conn->scheduler, h2o_http2_default_priority.weight, 0);
2024
99
    h2o_http2_stream_prepare_for_request(http2conn, stream);
2025
2026
    /* send response */
2027
99
    req->res.status = 101;
2028
99
    req->res.reason = "Switching Protocols";
2029
99
    h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_UPGRADE, NULL, H2O_STRLIT("h2c"));
2030
99
    h2o_http1_upgrade(req, NULL, 0, on_upgrade_complete, http2conn);
2031
2032
99
    return 0;
2033
534
Error:
2034
534
    kh_destroy(h2o_http2_stream_t, http2conn->streams);
2035
534
    h2o_destroy_connection(&http2conn->super);
2036
534
    return -1;
2037
235
}