Coverage Report

Created: 2025-07-11 06:24

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