Coverage Report

Created: 2025-07-11 06:26

/src/h2o/lib/common/http2client.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018 Ichito Nagata, 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 <arpa/inet.h>
23
#include <netdb.h>
24
#include <netinet/in.h>
25
#include <sys/socket.h>
26
#include <sys/types.h>
27
#include <sys/un.h>
28
#include "khash.h"
29
#include "h2o/hpack.h"
30
#include "h2o/httpclient.h"
31
#include "h2o/http2_common.h"
32
33
0
#define H2O_HTTP2_SETTINGS_CLIENT_CONNECTION_WINDOW_SIZE 16777216
34
0
#define H2O_HTTP2_SETTINGS_CLIENT_HEADER_TABLE_SIZE 4096
35
0
#define H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE 16384
36
37
enum enum_h2o_http2client_stream_state {
38
    STREAM_STATE_HEAD,
39
    STREAM_STATE_BODY,
40
    STREAM_STATE_CLOSED,
41
};
42
43
enum enum_h2o_http2client_conn_state {
44
    H2O_HTTP2CLIENT_CONN_STATE_OPEN,
45
    H2O_HTTP2CLIENT_CONN_STATE_HALF_CLOSED,
46
    H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING,
47
};
48
49
struct st_h2o_http2client_stream_t;
50
KHASH_MAP_INIT_INT64(stream, struct st_h2o_http2client_stream_t *)
51
52
struct st_h2o_http2client_conn_t {
53
    h2o_httpclient__h2_conn_t super;
54
    enum enum_h2o_http2client_conn_state state;
55
    khash_t(stream) * streams;
56
    h2o_http2_settings_t peer_settings;
57
    uint32_t max_open_stream_id;
58
    h2o_timer_t io_timeout;
59
    h2o_timer_t keepalive_timeout;
60
61
    struct {
62
        h2o_hpack_header_table_t header_table;
63
        h2o_http2_window_t window;
64
        h2o_buffer_t *buf;
65
        h2o_buffer_t *buf_in_flight;
66
        h2o_timer_t defer_timeout;
67
        h2o_linklist_t sending_streams;
68
        h2o_linklist_t sent_streams;
69
    } output;
70
71
    struct {
72
        h2o_hpack_header_table_t header_table;
73
        h2o_http2_window_t window;
74
        ssize_t (*read_frame)(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc);
75
        h2o_buffer_t *headers_unparsed;
76
    } input;
77
    h2o_mem_pool_t rst_streams_pool;
78
};
79
80
struct st_h2o_http2client_stream_t {
81
    h2o_httpclient_t super;
82
    struct st_h2o_http2client_conn_t *conn;
83
    uint32_t stream_id;
84
    struct {
85
        enum enum_h2o_http2client_stream_state req;
86
        enum enum_h2o_http2client_stream_state res;
87
    } state;
88
89
    struct {
90
        h2o_http2_window_t window;
91
        h2o_buffer_t *buf;
92
        h2o_linklist_t sending_link;
93
        h2o_httpclient_proceed_req_cb proceed_req; /* set to NULL once entire request body is provided to http2client */
94
    } output;
95
96
    struct {
97
        h2o_http2_window_t window;
98
        int status;
99
        h2o_headers_t headers;
100
        h2o_buffer_t *body;
101
        h2o_headers_t trailers;
102
        size_t remaining_content_length;
103
        unsigned message_body_forbidden : 1;
104
    } input;
105
106
    int *notify_destroyed;
107
    int send_own_expect;
108
};
109
110
static void do_emit_writereq(struct st_h2o_http2client_conn_t *conn);
111
112
static void request_write(struct st_h2o_http2client_conn_t *conn)
113
0
{
114
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING)
115
0
        return;
116
0
    if (!h2o_socket_is_writing(conn->super.sock) && !h2o_timer_is_linked(&conn->output.defer_timeout))
117
0
        h2o_timer_link(conn->super.ctx->loop, 0, &conn->output.defer_timeout);
118
0
}
119
120
static void enqueue_window_update(struct st_h2o_http2client_conn_t *conn, uint32_t stream_id, h2o_http2_window_t *window,
121
                                  size_t desired)
122
0
{
123
0
    assert(desired <= INT32_MAX);
124
0
    if (h2o_http2_window_get_avail(window) * 2 < desired) {
125
0
        int32_t delta = (int32_t)(desired - h2o_http2_window_get_avail(window));
126
0
        h2o_http2_encode_window_update_frame(&conn->output.buf, stream_id, delta);
127
0
        request_write(conn);
128
0
        h2o_http2_window_update(window, delta);
129
0
    }
130
0
}
131
132
static void stream_send_error(struct st_h2o_http2client_conn_t *conn, uint32_t stream_id, int errnum)
133
0
{
134
0
    assert(stream_id != 0);
135
0
    assert(conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING);
136
137
0
    h2o_http2_encode_rst_stream_frame(&conn->output.buf, stream_id, -errnum);
138
0
    request_write(conn);
139
0
}
140
141
static struct st_h2o_http2client_stream_t *get_stream(struct st_h2o_http2client_conn_t *conn, uint32_t stream_id)
142
0
{
143
0
    khiter_t iter = kh_get(stream, conn->streams, stream_id);
144
0
    if (iter != kh_end(conn->streams))
145
0
        return (struct st_h2o_http2client_stream_t *)kh_val(conn->streams, iter);
146
0
    return NULL;
147
0
}
148
149
static uint32_t get_max_buffer_size(h2o_httpclient_ctx_t *ctx)
150
0
{
151
0
    size_t sz = ctx->max_buffer_size;
152
0
    if (sz > INT32_MAX)
153
0
        sz = INT32_MAX;
154
0
    return (uint32_t)sz;
155
0
}
156
157
uint32_t h2o_httpclient__h2_get_max_concurrent_streams(h2o_httpclient__h2_conn_t *_conn)
158
0
{
159
0
    struct st_h2o_http2client_conn_t *conn = (void *)_conn;
160
0
    return conn->peer_settings.max_concurrent_streams < conn->super.ctx->http2.max_concurrent_streams
161
0
               ? conn->peer_settings.max_concurrent_streams
162
0
               : conn->super.ctx->http2.max_concurrent_streams;
163
0
}
164
165
static void adjust_conn_linkedlist(h2o_httpclient_connection_pool_t *connpool, struct st_h2o_http2client_conn_t *conn, int forward)
166
0
{
167
0
    if (connpool == NULL) {
168
0
        assert(!h2o_linklist_is_linked(&conn->super.link));
169
0
        return;
170
0
    }
171
0
    if (!h2o_linklist_is_linked(&conn->super.link))
172
0
        return;
173
174
0
    double ratio = (double)conn->super.num_streams / h2o_httpclient__h2_get_max_concurrent_streams(&conn->super);
175
176
    /* adjust connection linked list */
177
0
    h2o_linklist_t *node = forward ? conn->super.link.next : conn->super.link.prev;
178
0
    while (node != &connpool->http2.conns) {
179
0
        struct st_h2o_http2client_conn_t *cur = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, super.link, node);
180
0
        double cur_ratio = (double)cur->super.num_streams / h2o_httpclient__h2_get_max_concurrent_streams(&cur->super);
181
0
        if (forward ? (ratio <= cur_ratio) : (ratio >= cur_ratio))
182
0
            break;
183
0
        node = forward ? node->next : node->prev;
184
0
    }
185
0
    if (forward) {
186
0
        if (node == conn->super.link.next)
187
0
            return;
188
0
    } else {
189
0
        if (node == conn->super.link.prev)
190
0
            return;
191
0
        if (node != &connpool->http2.conns)
192
0
            node = node->next; /* do `insert after` rather than `insert before` */
193
0
    }
194
0
    h2o_linklist_unlink(&conn->super.link);
195
0
    h2o_linklist_insert(node, &conn->super.link);
196
0
}
197
198
static void register_stream(struct st_h2o_http2client_stream_t *stream, struct st_h2o_http2client_conn_t *conn)
199
0
{
200
0
    assert(stream->stream_id == 0);
201
202
0
    stream->conn = conn;
203
204
0
    stream->stream_id = conn->max_open_stream_id == 0 ? 1 : conn->max_open_stream_id + 2;
205
0
    conn->max_open_stream_id = stream->stream_id;
206
207
0
    int r;
208
0
    khiter_t iter = kh_put(stream, conn->streams, stream->stream_id, &r);
209
0
    assert(iter != kh_end(conn->streams));
210
0
    kh_val(conn->streams, iter) = stream;
211
212
0
    ++conn->super.num_streams;
213
214
0
    if (h2o_timer_is_linked(&conn->keepalive_timeout))
215
0
        h2o_timer_unlink(&conn->keepalive_timeout);
216
217
0
    adjust_conn_linkedlist(stream->super.connpool, conn, 1);
218
0
}
219
220
static void unregister_stream(struct st_h2o_http2client_stream_t *stream)
221
0
{
222
0
    khiter_t iter = kh_get(stream, stream->conn->streams, stream->stream_id);
223
0
    assert(iter != kh_end(stream->conn->streams));
224
0
    kh_del(stream, stream->conn->streams, iter);
225
226
0
    --stream->conn->super.num_streams;
227
228
0
    if (stream->conn->super.num_streams == 0)
229
0
        h2o_timer_link(stream->conn->super.ctx->loop, stream->conn->super.ctx->keepalive_timeout, &stream->conn->keepalive_timeout);
230
231
0
    adjust_conn_linkedlist(stream->super.connpool, stream->conn, 0);
232
0
}
233
234
static void close_stream(struct st_h2o_http2client_stream_t *stream)
235
0
{
236
0
    if (stream->conn != NULL) {
237
0
        unregister_stream(stream);
238
0
    }
239
240
0
    if (h2o_timer_is_linked(&stream->super._timeout))
241
0
        h2o_timer_unlink(&stream->super._timeout);
242
0
    if (h2o_linklist_is_linked(&stream->output.sending_link))
243
0
        h2o_linklist_unlink(&stream->output.sending_link);
244
245
0
    if (stream->output.buf != NULL)
246
0
        h2o_buffer_dispose(&stream->output.buf);
247
0
    h2o_buffer_dispose(&stream->input.body);
248
249
0
    if (stream->notify_destroyed != NULL)
250
0
        *stream->notify_destroyed = 1;
251
252
0
    free(stream);
253
0
}
254
255
static void close_response(struct st_h2o_http2client_stream_t *stream)
256
0
{
257
0
    assert(stream->state.res != STREAM_STATE_CLOSED);
258
0
    stream->state.res = STREAM_STATE_CLOSED;
259
0
    if (stream->state.req == STREAM_STATE_CLOSED) {
260
0
        close_stream(stream);
261
0
    }
262
0
}
263
264
static void call_callback_with_error(struct st_h2o_http2client_stream_t *stream, const char *errstr)
265
0
{
266
0
    assert(errstr != NULL);
267
0
    switch (stream->state.res) {
268
0
    case STREAM_STATE_HEAD: {
269
0
        h2o_httpclient_on_head_t on_head = {.version = 0x200};
270
0
        stream->super._cb.on_head(&stream->super, errstr, &on_head);
271
0
    } break;
272
0
    case STREAM_STATE_BODY:
273
0
        stream->super._cb.on_body(&stream->super, errstr, NULL, 0);
274
0
        break;
275
0
    case STREAM_STATE_CLOSED:
276
        /* proceed_req can be called to indicate error, regardless of write being inflight */
277
0
        if (stream->output.proceed_req != NULL) {
278
0
            h2o_httpclient_proceed_req_cb cb = stream->output.proceed_req;
279
0
            stream->output.proceed_req = NULL;
280
0
            cb(&stream->super, errstr);
281
0
        }
282
0
        break;
283
0
    }
284
0
}
285
286
static void call_stream_callbacks_with_error(struct st_h2o_http2client_conn_t *conn, const char *errstr)
287
0
{
288
0
    struct st_h2o_http2client_stream_t *stream;
289
0
    kh_foreach_value(conn->streams, stream, { call_callback_with_error(stream, errstr); });
290
0
}
291
292
static int extract_content_length(const h2o_headers_t *headers, size_t *content_length, const char **err_desc)
293
0
{
294
0
    *content_length = SIZE_MAX;
295
0
    for (size_t i = 0; i < headers->size; ++i) {
296
0
        if (headers->entries[i].name == &H2O_TOKEN_CONTENT_LENGTH->buf) {
297
0
            const h2o_iovec_t *value = &headers->entries[i].value;
298
0
            if (*content_length != SIZE_MAX) {
299
0
                *err_desc = "duplicate content-length";
300
0
                return 0;
301
0
            }
302
0
            *content_length = h2o_strtosize(value->base, value->len);
303
0
            if (*content_length == SIZE_MAX) {
304
0
                *err_desc = "malformed content-length";
305
0
                return 0;
306
0
            }
307
0
        }
308
0
    }
309
0
    return 1;
310
0
}
311
312
static int on_head(struct st_h2o_http2client_conn_t *conn, struct st_h2o_http2client_stream_t *stream, const uint8_t *src,
313
                   size_t len, const char **err_desc, int is_end_stream)
314
0
{
315
0
    int ret;
316
0
    h2o_mem_pool_t *pool;
317
0
    int *status;
318
0
    h2o_headers_t *headers;
319
0
    int dummy_status;
320
0
    h2o_headers_t dummy_headers = {0};
321
322
0
    if (stream != NULL) {
323
0
        pool = stream->super.pool;
324
0
        status = &stream->input.status;
325
0
        headers = &stream->input.headers;
326
0
    } else {
327
0
        pool = &conn->rst_streams_pool;
328
0
        status = &dummy_status;
329
0
        headers = &dummy_headers;
330
0
    }
331
332
0
    if ((ret = h2o_hpack_parse_response(pool, h2o_hpack_decode_header, &conn->input.header_table, status, headers, NULL, src, len,
333
0
                                        err_desc)) != 0) {
334
0
        if (ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR) {
335
0
            ret = H2O_HTTP2_ERROR_PROTOCOL;
336
0
            goto Failed;
337
0
        }
338
0
        return ret;
339
0
    }
340
341
0
    if (stream == NULL)
342
0
        return 0;
343
344
0
    if (100 <= stream->input.status && stream->input.status <= 199) {
345
0
        if (stream->input.status == 101) {
346
0
            ret = H2O_HTTP2_ERROR_PROTOCOL; // TODO is this alright?
347
0
            goto Failed;
348
0
        }
349
0
        if (stream->input.status == 100 && stream->send_own_expect) {
350
0
            stream->input.status = 0;
351
0
            stream->send_own_expect = 0;
352
0
            if (stream->output.buf != NULL && !h2o_linklist_is_linked(&stream->output.sending_link)) {
353
0
                h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
354
0
                request_write(stream->conn);
355
0
            }
356
357
0
            return 0;
358
0
        }
359
0
        if (stream->super.informational_cb != NULL &&
360
0
            stream->super.informational_cb(&stream->super, 0, stream->input.status, h2o_iovec_init(NULL, 0),
361
0
                                           stream->input.headers.entries, stream->input.headers.size) != 0) {
362
0
            ret = H2O_HTTP2_ERROR_INTERNAL;
363
0
            goto SendRSTStream;
364
0
        }
365
0
        return 0;
366
0
    }
367
368
0
    if ((100 <= stream->input.status && stream->input.status <= 199) ||
369
0
        (stream->input.status == 204 || stream->input.status == 304)) {
370
0
        stream->input.message_body_forbidden = 1;
371
0
    }
372
373
0
    if (!extract_content_length(&stream->input.headers, &stream->input.remaining_content_length, err_desc)) {
374
0
        ret = H2O_HTTP2_ERROR_PROTOCOL;
375
0
        goto Failed;
376
0
    }
377
378
0
    h2o_httpclient_on_head_t on_head = {.version = 0x200,
379
0
                                        .status = stream->input.status,
380
0
                                        .msg = h2o_iovec_init(NULL, 0),
381
0
                                        .headers = stream->input.headers.entries,
382
0
                                        .num_headers = stream->input.headers.size};
383
0
    stream->super._cb.on_body =
384
0
        stream->super._cb.on_head(&stream->super, is_end_stream ? h2o_httpclient_error_is_eos : NULL, &on_head);
385
386
0
    if (is_end_stream) {
387
0
        close_response(stream);
388
0
        return 0;
389
0
    }
390
0
    if (stream->super._cb.on_body == NULL) {
391
        /**
392
         * NOTE: if on_head returns NULL due to invalid response (e.g. invalid content-length header)
393
         * sending RST_STREAM with PROTOCOL_ERROR might be more suitable than CANCEL
394
         * (see: https://tools.ietf.org/html/rfc7540#section-8.1.2.6)
395
         * but sending CANCEL is not wrong, so we leave this as-is for now.
396
         */
397
0
        ret = H2O_HTTP2_ERROR_CANCEL;
398
0
        goto SendRSTStream;
399
0
    }
400
401
0
    stream->state.res = STREAM_STATE_BODY;
402
403
0
    return 0;
404
405
0
Failed:
406
0
    assert(ret == H2O_HTTP2_ERROR_PROTOCOL);
407
0
    call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
408
0
SendRSTStream:
409
0
    stream_send_error(conn, stream->stream_id, ret);
410
0
    close_stream(stream);
411
0
    return 0;
412
0
}
413
414
static int on_trailers(struct st_h2o_http2client_conn_t *conn, struct st_h2o_http2client_stream_t *stream, const uint8_t *src,
415
                       size_t len, const char **err_desc)
416
0
{
417
0
    int ret;
418
419
0
    assert(stream->state.res == STREAM_STATE_BODY);
420
421
0
    if ((ret = h2o_hpack_parse_response(stream->super.pool, h2o_hpack_decode_header, &conn->input.header_table, NULL,
422
0
                                        &stream->input.trailers, NULL, src, len, err_desc)) != 0) {
423
0
        if (ret == H2O_HTTP2_ERROR_INVALID_HEADER_CHAR) {
424
0
            ret = H2O_HTTP2_ERROR_PROTOCOL;
425
0
            goto Failed;
426
0
        }
427
0
        return ret;
428
0
    }
429
430
0
    if (stream->super._cb.on_body(&stream->super, h2o_httpclient_error_is_eos, stream->input.trailers.entries,
431
0
                                  stream->input.trailers.size) != 0) {
432
0
        ret = H2O_HTTP2_ERROR_INTERNAL;
433
0
        goto SendRSTStream;
434
0
    }
435
0
    close_response(stream);
436
0
    return 0;
437
438
0
Failed:
439
0
    assert(ret == H2O_HTTP2_ERROR_PROTOCOL);
440
0
    call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
441
0
SendRSTStream:
442
0
    stream_send_error(conn, stream->stream_id, ret);
443
0
    close_stream(stream);
444
0
    return 0;
445
0
}
446
447
ssize_t expect_default(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc);
448
static ssize_t expect_continuation_of_headers(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len,
449
                                              const char **err_desc)
450
0
{
451
0
    h2o_http2_frame_t frame;
452
0
    ssize_t ret;
453
0
    struct st_h2o_http2client_stream_t *stream;
454
0
    int hret;
455
456
0
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE, err_desc)) < 0)
457
0
        return ret;
458
0
    if (frame.type != H2O_HTTP2_FRAME_TYPE_CONTINUATION) {
459
0
        *err_desc = "expected CONTINUATION frame";
460
0
        return H2O_HTTP2_ERROR_PROTOCOL;
461
0
    }
462
463
0
    stream = get_stream(conn, frame.stream_id);
464
0
    if (stream != NULL && stream->state.res == STREAM_STATE_CLOSED) {
465
0
        *err_desc = "unexpected stream id in CONTINUATION frame";
466
0
        return H2O_HTTP2_ERROR_PROTOCOL;
467
0
    }
468
469
0
    h2o_buffer_reserve(&conn->input.headers_unparsed, frame.length);
470
0
    memcpy(conn->input.headers_unparsed->bytes + conn->input.headers_unparsed->size, frame.payload, frame.length);
471
0
    conn->input.headers_unparsed->size += frame.length;
472
473
0
    if ((frame.flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) != 0) {
474
0
        int is_end_stream = (frame.flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0;
475
0
        conn->input.read_frame = expect_default;
476
477
0
        if (stream != NULL && stream->state.res == STREAM_STATE_BODY) {
478
0
            hret = on_trailers(conn, stream, (const uint8_t *)conn->input.headers_unparsed->bytes,
479
0
                               conn->input.headers_unparsed->size, err_desc);
480
0
        } else {
481
0
            hret = on_head(conn, stream, (const uint8_t *)conn->input.headers_unparsed->bytes, conn->input.headers_unparsed->size,
482
0
                           err_desc, is_end_stream);
483
0
        }
484
0
        if (hret != 0)
485
0
            ret = hret;
486
487
0
        h2o_buffer_dispose(&conn->input.headers_unparsed);
488
0
        conn->input.headers_unparsed = NULL;
489
0
    }
490
491
0
    return ret;
492
0
}
493
494
static void do_update_window(h2o_httpclient_t *client);
495
static int handle_data_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
496
0
{
497
0
    h2o_http2_data_payload_t payload;
498
0
    struct st_h2o_http2client_stream_t *stream;
499
0
    int ret;
500
501
0
    if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
502
0
        return ret;
503
504
    /* save the input in the request body buffer, or send error (and close the stream) */
505
0
    if ((stream = get_stream(conn, frame->stream_id)) == NULL) {
506
0
        if (frame->stream_id <= conn->max_open_stream_id) {
507
0
            h2o_http2_window_consume_window(&conn->input.window, payload.length);
508
0
            enqueue_window_update(conn, 0, &conn->input.window, H2O_HTTP2_SETTINGS_CLIENT_CONNECTION_WINDOW_SIZE);
509
0
            return 0;
510
0
        } else {
511
0
            *err_desc = "invalid DATA frame";
512
0
            return H2O_HTTP2_ERROR_PROTOCOL;
513
0
        }
514
0
    }
515
516
0
    if (stream->state.res != STREAM_STATE_BODY) {
517
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
518
0
        call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
519
0
        close_stream(stream);
520
0
        return 0;
521
0
    }
522
523
    /**
524
     * RFC7230 Section 3.3.
525
     *
526
     *  Responses to the HEAD request method (Section 4.3.2 of [RFC7231]) never
527
     *  include a message body because the associated response header fields
528
     *  (e.g., Transfer-Encoding, Content-Length, etc.), if present, indicate
529
     *  only what their values would have been if the request method had been
530
     *  GET (Section 4.3.1 of [RFC7231]).
531
     *
532
     *  2xx (Successful) responses to a CONNECT request method (Section 4.3.6
533
     *  of [RFC7231]) switch to tunnel mode instead of having a message body.
534
     *
535
     *  All 1xx (Informational), 204 (No Content), and 304 (Not Modified)
536
     *  responses do not include a message body.
537
     *
538
     *  All other responses do include a message body, although the body might
539
     *  be of zero length.
540
     */
541
0
    if (stream->input.message_body_forbidden && payload.length != 0) {
542
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
543
0
        call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
544
0
        close_stream(stream);
545
0
        return 0;
546
0
    }
547
548
    /**
549
     * RFC 7540 Section 8.1.2.6.
550
     *  A request or response is also malformed if the value of
551
     *  a content-length header field does not equal the sum of the DATA frame
552
     *  payload lengths that form the body.
553
     */
554
0
    if (stream->input.remaining_content_length != SIZE_MAX) {
555
0
        if (payload.length > stream->input.remaining_content_length) {
556
0
            stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
557
0
            call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
558
0
            close_stream(stream);
559
0
            return 0;
560
0
        }
561
0
        stream->input.remaining_content_length -= payload.length;
562
0
    }
563
564
0
    size_t max_size = get_max_buffer_size(stream->super.ctx);
565
0
    if (stream->input.body->size + payload.length > max_size) {
566
0
        call_callback_with_error(stream, h2o_httpclient_error_flow_control);
567
0
        stream_send_error(stream->conn, stream->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
568
0
        close_stream(stream);
569
0
        return 0;
570
0
    }
571
572
0
    h2o_buffer_append(&stream->input.body, (void *)payload.data, payload.length);
573
574
0
    h2o_http2_window_consume_window(&conn->input.window, payload.length);
575
0
    h2o_http2_window_consume_window(&stream->input.window, payload.length);
576
577
0
    int is_final = (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0;
578
0
    if (stream->super._cb.on_body(&stream->super, is_final ? h2o_httpclient_error_is_eos : NULL, NULL, 0) != 0) {
579
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_INTERNAL);
580
0
        close_stream(stream);
581
0
        return 0;
582
0
    }
583
584
0
    if (is_final) {
585
0
        close_response(stream);
586
0
    } else {
587
        /* update connection-level window */
588
0
        enqueue_window_update(stream->conn, 0, &stream->conn->input.window, H2O_HTTP2_SETTINGS_CLIENT_CONNECTION_WINDOW_SIZE);
589
        /* update stream-level window */
590
0
        do_update_window(&stream->super);
591
0
    }
592
593
0
    return 0;
594
0
}
595
596
static int handle_headers_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
597
0
{
598
0
    h2o_http2_headers_payload_t payload;
599
0
    struct st_h2o_http2client_stream_t *stream;
600
0
    int ret;
601
602
    /* decode */
603
0
    if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
604
0
        return ret;
605
0
    if ((frame->stream_id & 1) == 0) {
606
0
        *err_desc = "invalid stream id in HEADERS frame";
607
0
        return H2O_HTTP2_ERROR_PROTOCOL;
608
0
    }
609
610
0
    if (frame->stream_id == payload.priority.dependency) {
611
0
        *err_desc = "stream cannot depend on itself";
612
0
        return H2O_HTTP2_ERROR_PROTOCOL;
613
0
    }
614
615
0
    if ((stream = get_stream(conn, frame->stream_id)) == NULL) {
616
0
        if (frame->stream_id > conn->max_open_stream_id) {
617
0
            *err_desc = "invalid stream id in HEADERS frame";
618
0
            return H2O_HTTP2_ERROR_PROTOCOL;
619
0
        }
620
0
    }
621
622
0
    int is_end_stream = (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0;
623
624
0
    if (stream != NULL) {
625
0
        h2o_timer_unlink(&stream->super._timeout);
626
627
0
        if (stream->state.res == STREAM_STATE_BODY && !is_end_stream) {
628
0
            *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
629
0
            return H2O_HTTP2_ERROR_PROTOCOL;
630
0
        }
631
0
    }
632
633
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0) {
634
        /* header is not complete, store in buffer */
635
0
        conn->input.read_frame = expect_continuation_of_headers;
636
0
        h2o_buffer_init(&conn->input.headers_unparsed, &h2o_socket_buffer_prototype);
637
0
        h2o_buffer_reserve(&conn->input.headers_unparsed, payload.headers_len);
638
0
        memcpy(conn->input.headers_unparsed->bytes, payload.headers, payload.headers_len);
639
0
        conn->input.headers_unparsed->size = payload.headers_len;
640
0
        return 0;
641
0
    }
642
643
    /* response header is complete, handle it */
644
0
    if (stream != NULL && stream->state.res == STREAM_STATE_BODY) {
645
0
        return on_trailers(conn, stream, payload.headers, payload.headers_len, err_desc);
646
0
    } else {
647
0
        return on_head(conn, stream, payload.headers, payload.headers_len, err_desc, is_end_stream);
648
0
    }
649
0
}
650
651
static int handle_priority_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
652
0
{
653
0
    h2o_http2_priority_t payload;
654
0
    int ret;
655
656
0
    if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
657
0
        return ret;
658
0
    if (frame->stream_id == payload.dependency) {
659
0
        *err_desc = "stream cannot depend on itself";
660
0
        return H2O_HTTP2_ERROR_PROTOCOL;
661
0
    }
662
663
    /* Ignore PRIORITY frames */
664
0
    return 0;
665
0
}
666
667
static int handle_rst_stream_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
668
0
{
669
0
    h2o_http2_rst_stream_payload_t payload;
670
0
    struct st_h2o_http2client_stream_t *stream;
671
0
    int ret;
672
673
0
    if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
674
0
        return ret;
675
0
    if (frame->stream_id > conn->max_open_stream_id) {
676
0
        *err_desc = "unexpected stream id in RST_STREAM frame";
677
0
        return H2O_HTTP2_ERROR_PROTOCOL;
678
0
    }
679
680
0
    stream = get_stream(conn, frame->stream_id);
681
0
    if (stream != NULL) {
682
        /* reset the stream */
683
0
        call_callback_with_error(stream, payload.error_code == -H2O_HTTP2_ERROR_REFUSED_STREAM ? h2o_httpclient_error_refused_stream
684
0
                                                                                               : h2o_httpclient_error_io);
685
0
        close_stream(stream);
686
0
    }
687
688
0
    return 0;
689
0
}
690
691
static int update_stream_output_window(struct st_h2o_http2client_stream_t *stream, ssize_t delta)
692
0
{
693
0
    if (h2o_http2_window_update(&stream->output.window, delta) != 0)
694
0
        return -1;
695
0
    ssize_t after = h2o_http2_window_get_avail(&stream->output.window);
696
0
    if (after > 0 && stream->output.buf != NULL && stream->output.buf->size != 0 &&
697
0
        !h2o_linklist_is_linked(&stream->output.sending_link))
698
0
        h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
699
0
    return 0;
700
0
}
701
702
static ssize_t conn_get_buffer_window(struct st_h2o_http2client_conn_t *conn)
703
0
{
704
0
    ssize_t ret, winsz;
705
0
    size_t capacity, cwnd_left;
706
707
0
    capacity = conn->output.buf->capacity;
708
0
    if ((cwnd_left = h2o_socket_prepare_for_latency_optimized_write(conn->super.sock,
709
0
                                                                    &conn->super.ctx->http2.latency_optimization)) < capacity) {
710
0
        capacity = cwnd_left;
711
0
        if (capacity < conn->output.buf->size)
712
0
            return 0;
713
0
    }
714
715
0
    ret = capacity - conn->output.buf->size;
716
0
    if (ret < H2O_HTTP2_FRAME_HEADER_SIZE)
717
0
        return 0;
718
0
    ret -= H2O_HTTP2_FRAME_HEADER_SIZE;
719
0
    winsz = h2o_http2_window_get_avail(&conn->output.window);
720
0
    if (winsz < ret)
721
0
        ret = winsz;
722
0
    return ret;
723
0
}
724
725
static int handle_settings_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
726
0
{
727
0
    if (frame->stream_id != 0) {
728
0
        *err_desc = "invalid stream id in SETTINGS frame";
729
0
        return H2O_HTTP2_ERROR_PROTOCOL;
730
0
    }
731
732
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
733
0
        if (frame->length != 0) {
734
0
            *err_desc = "invalid SETTINGS frame (+ACK)";
735
0
            return H2O_HTTP2_ERROR_FRAME_SIZE;
736
0
        }
737
0
    } else {
738
0
        uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
739
0
        int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
740
0
        if (ret != 0)
741
0
            return ret;
742
0
        { /* schedule ack */
743
0
            h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->output.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
744
0
            h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
745
0
            conn->output.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
746
0
            request_write(conn);
747
0
        }
748
        /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
749
0
        if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
750
0
            ssize_t delta = conn->peer_settings.initial_window_size - prev_initial_window_size;
751
0
            struct st_h2o_http2client_stream_t *stream;
752
0
            kh_foreach_value(conn->streams, stream, { update_stream_output_window((void *)stream, delta); });
753
754
0
            if (conn_get_buffer_window(conn) > 0)
755
0
                request_write(conn);
756
0
        }
757
0
    }
758
759
0
    return 0;
760
0
}
761
762
static int handle_push_promise_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
763
0
{
764
0
    *err_desc = "received PUSH_PROMISE frame";
765
0
    return H2O_HTTP2_ERROR_PROTOCOL;
766
0
}
767
768
static int handle_ping_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
769
0
{
770
0
    h2o_http2_ping_payload_t payload;
771
0
    int ret;
772
773
0
    if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
774
0
        return ret;
775
776
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
777
0
        h2o_http2_encode_ping_frame(&conn->output.buf, 1, payload.data);
778
0
        request_write(conn);
779
0
    }
780
781
0
    return 0;
782
0
}
783
784
static int handle_goaway_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
785
0
{
786
0
    h2o_http2_goaway_payload_t payload;
787
0
    int ret;
788
789
0
    if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
790
0
        return ret;
791
792
0
    struct st_h2o_http2client_stream_t *stream;
793
0
    kh_foreach_value(conn->streams, stream, {
794
0
        if (stream->stream_id > payload.last_stream_id) {
795
0
            call_callback_with_error(stream, h2o_httpclient_error_refused_stream);
796
0
            close_stream(stream);
797
0
        }
798
0
    });
799
800
    /* stop opening new streams */
801
0
    if (h2o_linklist_is_linked(&conn->super.link))
802
0
        h2o_linklist_unlink(&conn->super.link);
803
804
0
    return 0;
805
0
}
806
807
static int handle_window_update_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
808
0
{
809
0
    h2o_http2_window_update_payload_t payload;
810
0
    int ret, err_is_stream_level;
811
812
0
    if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
813
0
        if (err_is_stream_level) {
814
0
            stream_send_error(conn, frame->stream_id, ret);
815
0
            struct st_h2o_http2client_stream_t *stream = get_stream(conn, frame->stream_id);
816
0
            if (stream != NULL) {
817
0
                call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
818
0
                close_stream(stream);
819
0
            }
820
0
            return 0;
821
0
        } else {
822
0
            return ret;
823
0
        }
824
0
    }
825
826
0
    if (frame->stream_id == 0) {
827
0
        if (h2o_http2_window_update(&conn->output.window, payload.window_size_increment) != 0) {
828
0
            *err_desc = "flow control window overflow";
829
0
            return H2O_HTTP2_ERROR_FLOW_CONTROL;
830
0
        }
831
0
    } else if (frame->stream_id <= conn->max_open_stream_id) {
832
0
        struct st_h2o_http2client_stream_t *stream = get_stream(conn, frame->stream_id);
833
0
        if (stream != NULL) {
834
0
            if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
835
0
                stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
836
0
                call_callback_with_error(stream, h2o_httpclient_error_flow_control);
837
0
                close_stream(stream);
838
0
                return 0;
839
0
            }
840
0
        }
841
0
    } else {
842
0
        *err_desc = "invalid stream id in WINDOW_UPDATE frame";
843
0
        return H2O_HTTP2_ERROR_PROTOCOL;
844
0
    }
845
846
0
    if (conn_get_buffer_window(conn) > 0)
847
0
        request_write(conn);
848
849
0
    return 0;
850
0
}
851
852
static int handle_invalid_continuation_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame,
853
                                             const char **err_desc)
854
0
{
855
0
    *err_desc = "received invalid CONTINUATION frame";
856
0
    return H2O_HTTP2_ERROR_PROTOCOL;
857
0
}
858
859
ssize_t expect_default(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
860
0
{
861
0
    assert(conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING);
862
863
0
    h2o_http2_frame_t frame;
864
0
    ssize_t ret;
865
0
    static int (*FRAME_HANDLERS[])(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc) = {
866
0
        handle_data_frame,                /* DATA */
867
0
        handle_headers_frame,             /* HEADERS */
868
0
        handle_priority_frame,            /* PRIORITY */
869
0
        handle_rst_stream_frame,          /* RST_STREAM */
870
0
        handle_settings_frame,            /* SETTINGS */
871
0
        handle_push_promise_frame,        /* PUSH_PROMISE */
872
0
        handle_ping_frame,                /* PING */
873
0
        handle_goaway_frame,              /* GOAWAY */
874
0
        handle_window_update_frame,       /* WINDOW_UPDATE */
875
0
        handle_invalid_continuation_frame /* CONTINUATION */
876
0
    };
877
878
0
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE, err_desc)) < 0)
879
0
        return ret;
880
881
0
    if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
882
0
        int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
883
0
        if (hret != 0)
884
0
            ret = hret;
885
0
    } else {
886
0
        h2o_error_printf("skipping frame (type:%d)\n", frame.type);
887
0
    }
888
889
0
    return ret;
890
0
}
891
892
static ssize_t expect_settings(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
893
0
{
894
0
    assert(conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING);
895
896
0
    h2o_http2_frame_t frame;
897
0
    ssize_t ret;
898
899
0
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE, err_desc)) < 0)
900
0
        return ret;
901
902
0
    if (frame.type != H2O_HTTP2_FRAME_TYPE_SETTINGS)
903
0
        return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
904
905
0
    int hret = handle_settings_frame(conn, &frame, err_desc);
906
0
    if (hret != 0)
907
0
        return hret;
908
909
0
    conn->input.read_frame = expect_default;
910
0
    return ret;
911
0
}
912
913
static void close_connection_now(struct st_h2o_http2client_conn_t *conn)
914
0
{
915
0
    free(conn->super.origin_url.authority.base);
916
0
    free(conn->super.origin_url.host.base);
917
0
    free(conn->super.origin_url.path.base);
918
919
0
    h2o_socket_close(conn->super.sock);
920
921
0
    struct st_h2o_http2client_stream_t *stream;
922
0
    kh_foreach_value(conn->streams, stream, { close_stream(stream); });
923
0
    kh_destroy(stream, conn->streams);
924
925
0
    if (h2o_linklist_is_linked(&conn->super.link))
926
0
        h2o_linklist_unlink(&conn->super.link);
927
928
0
    if (h2o_timer_is_linked(&conn->io_timeout))
929
0
        h2o_timer_unlink(&conn->io_timeout);
930
0
    if (h2o_timer_is_linked(&conn->keepalive_timeout))
931
0
        h2o_timer_unlink(&conn->keepalive_timeout);
932
933
    /* output */
934
0
    h2o_hpack_dispose_header_table(&conn->output.header_table);
935
0
    h2o_buffer_dispose(&conn->output.buf);
936
0
    if (conn->output.buf_in_flight != NULL)
937
0
        h2o_buffer_dispose(&conn->output.buf_in_flight);
938
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout))
939
0
        h2o_timer_unlink(&conn->output.defer_timeout);
940
0
    assert(h2o_linklist_is_empty(&conn->output.sending_streams));
941
0
    assert(h2o_linklist_is_empty(&conn->output.sent_streams));
942
943
    /* input */
944
0
    h2o_hpack_dispose_header_table(&conn->input.header_table);
945
0
    if (conn->input.headers_unparsed != NULL)
946
0
        h2o_buffer_dispose(&conn->input.headers_unparsed);
947
948
0
    h2o_mem_clear_pool(&conn->rst_streams_pool);
949
0
    free(conn);
950
0
}
951
952
static int close_connection_if_necessary(struct st_h2o_http2client_conn_t *conn)
953
0
{
954
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_HALF_CLOSED && conn->super.num_streams == 0)
955
0
        conn->state = H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING;
956
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING) {
957
0
        close_connection_now(conn);
958
0
        return 1;
959
0
    }
960
0
    return 0;
961
0
}
962
963
static int close_connection(struct st_h2o_http2client_conn_t *conn)
964
0
{
965
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING;
966
0
    h2o_socket_read_stop(conn->super.sock);
967
968
0
    if (conn->output.buf_in_flight != NULL || h2o_timer_is_linked(&conn->output.defer_timeout)) {
969
        /* there is a pending write, let close_connection_if_necessary actually close the connection */
970
0
    } else {
971
0
        close_connection_now(conn);
972
0
        return -1;
973
0
    }
974
0
    return 0;
975
0
}
976
977
static void enqueue_goaway(struct st_h2o_http2client_conn_t *conn, int errnum, h2o_iovec_t additional_data)
978
0
{
979
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING)
980
0
        return;
981
982
0
    h2o_http2_encode_goaway_frame(&conn->output.buf, 0, errnum, additional_data);
983
0
    request_write(conn);
984
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_HALF_CLOSED;
985
986
    /* stop opening new streams */
987
0
    if (h2o_linklist_is_linked(&conn->super.link))
988
0
        h2o_linklist_unlink(&conn->super.link);
989
0
}
990
991
static void on_connect_error(struct st_h2o_http2client_stream_t *stream, const char *errstr)
992
0
{
993
0
    assert(errstr != NULL);
994
0
    stream->super._cb.on_connect(&stream->super, errstr, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL);
995
0
    close_stream(stream);
996
0
}
997
998
static void do_stream_timeout(struct st_h2o_http2client_stream_t *stream)
999
0
{
1000
0
    if (stream->conn == NULL) {
1001
0
        on_connect_error(stream, h2o_httpclient_error_connect_timeout);
1002
0
        return;
1003
0
    }
1004
0
    const char *errstr =
1005
0
        stream->state.res == STREAM_STATE_HEAD ? h2o_httpclient_error_first_byte_timeout : h2o_httpclient_error_io_timeout;
1006
0
    call_callback_with_error(stream, errstr);
1007
0
    close_stream(stream);
1008
0
}
1009
1010
static void on_stream_timeout(h2o_timer_t *entry)
1011
0
{
1012
0
    struct st_h2o_http2client_stream_t *stream = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, super._timeout, entry);
1013
0
    do_stream_timeout(stream);
1014
0
}
1015
1016
static void on_io_timeout(h2o_timer_t *entry)
1017
0
{
1018
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, io_timeout, entry);
1019
0
    struct st_h2o_http2client_stream_t *stream;
1020
0
    kh_foreach_value(conn->streams, stream, { do_stream_timeout(stream); });
1021
0
    close_connection_now(conn);
1022
0
}
1023
1024
static void on_keepalive_timeout(h2o_timer_t *entry)
1025
0
{
1026
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, keepalive_timeout, entry);
1027
0
    enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, h2o_iovec_init(NULL, 0));
1028
0
    request_write(conn);
1029
0
    close_connection(conn);
1030
0
}
1031
1032
static int parse_input(struct st_h2o_http2client_conn_t *conn)
1033
0
{
1034
    /* handle the input */
1035
0
    while (conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING && conn->super.sock->input->size != 0) {
1036
        /* process a frame */
1037
0
        const char *err_desc = NULL;
1038
0
        ssize_t ret =
1039
0
            conn->input.read_frame(conn, (uint8_t *)conn->super.sock->input->bytes, conn->super.sock->input->size, &err_desc);
1040
0
        if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
1041
0
            break;
1042
0
        } else if (ret < 0) {
1043
0
            if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
1044
0
                enqueue_goaway(conn, (int)ret,
1045
0
                               err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
1046
0
            }
1047
0
            call_stream_callbacks_with_error(conn, h2o_httpclient_error_protocol_violation);
1048
0
            return close_connection(conn);
1049
0
        }
1050
        /* advance to the next frame */
1051
0
        h2o_buffer_consume(&conn->super.sock->input, ret);
1052
0
    }
1053
0
    return 0;
1054
0
}
1055
1056
static void on_read(h2o_socket_t *sock, const char *err)
1057
0
{
1058
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1059
1060
0
    h2o_timer_unlink(&conn->io_timeout);
1061
1062
0
    if (err != NULL) {
1063
0
        call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1064
0
        close_connection(conn);
1065
0
        return;
1066
0
    }
1067
1068
0
    if (parse_input(conn) != 0)
1069
0
        return;
1070
1071
    /* write immediately, if pending write exists */
1072
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout)) {
1073
0
        h2o_timer_unlink(&conn->output.defer_timeout);
1074
0
        do_emit_writereq(conn);
1075
0
    }
1076
1077
0
    if (!h2o_timer_is_linked(&conn->io_timeout))
1078
0
        h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1079
0
}
1080
1081
static void on_connection_ready(struct st_h2o_http2client_stream_t *stream, struct st_h2o_http2client_conn_t *conn)
1082
0
{
1083
0
    h2o_iovec_t method;
1084
0
    h2o_url_t url;
1085
0
    h2o_header_t *headers;
1086
0
    size_t num_headers;
1087
0
    h2o_iovec_t body;
1088
0
    h2o_httpclient_properties_t props = (h2o_httpclient_properties_t){NULL};
1089
1090
0
    register_stream(stream, conn);
1091
1092
0
    stream->super._cb.on_head =
1093
0
        stream->super._cb.on_connect(&stream->super, NULL, &method, &url, (const h2o_header_t **)&headers, &num_headers, &body,
1094
0
                                     &stream->output.proceed_req, &props, &conn->super.origin_url);
1095
0
    if (stream->super._cb.on_head == NULL) {
1096
0
        close_stream(stream);
1097
0
        return;
1098
0
    }
1099
1100
0
    h2o_http2_window_init(&stream->output.window, conn->peer_settings.initial_window_size);
1101
1102
    /* forward request state */
1103
0
    if (stream->output.proceed_req != NULL) {
1104
0
        stream->state.req = STREAM_STATE_BODY;
1105
0
    } else if (body.base != NULL) {
1106
0
        stream->state.req = STREAM_STATE_BODY;
1107
0
    } else {
1108
0
        stream->state.req = STREAM_STATE_CLOSED;
1109
0
    }
1110
1111
0
    if (h2o_memis(method.base, method.len, H2O_STRLIT("HEAD"))) {
1112
0
        stream->input.message_body_forbidden = 1;
1113
0
    }
1114
1115
0
    if (props.send_own_expect && (stream->output.proceed_req != NULL || body.len != 0))
1116
0
        stream->send_own_expect = 1;
1117
1118
    /* send headers */
1119
0
    h2o_hpack_flatten_request(&conn->output.buf, &conn->output.header_table, conn->peer_settings.header_table_size,
1120
0
                              stream->stream_id, conn->peer_settings.max_frame_size, method, &url,
1121
0
                              stream->super.upgrade_to != NULL && stream->super.upgrade_to != h2o_httpclient_upgrade_to_connect
1122
0
                                  ? h2o_iovec_init(stream->super.upgrade_to, strlen(stream->super.upgrade_to))
1123
0
                                  : h2o_iovec_init(NULL, 0),
1124
0
                              headers, num_headers, stream->state.req == STREAM_STATE_CLOSED, stream->send_own_expect);
1125
1126
0
    if (stream->state.req == STREAM_STATE_BODY) {
1127
0
        h2o_buffer_init(&stream->output.buf, &h2o_socket_buffer_prototype);
1128
0
        h2o_buffer_append(&stream->output.buf, body.base, body.len);
1129
0
    }
1130
0
    h2o_linklist_insert(&conn->output.sending_streams, &stream->output.sending_link);
1131
0
    request_write(conn);
1132
0
}
1133
1134
static void on_notify_write(h2o_socket_t *sock, const char *err)
1135
0
{
1136
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1137
1138
0
    if (err != NULL) {
1139
0
        call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1140
0
        close_connection_now(conn);
1141
0
        return;
1142
0
    }
1143
0
    do_emit_writereq(conn);
1144
0
    close_connection_if_necessary(conn);
1145
0
}
1146
1147
static void on_write_complete(h2o_socket_t *sock, const char *err)
1148
0
{
1149
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1150
1151
0
    assert(conn->output.buf_in_flight != NULL);
1152
1153
0
    h2o_timer_unlink(&conn->io_timeout);
1154
1155
    /* close by error if necessary */
1156
0
    if (err != NULL) {
1157
0
        if (conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING)
1158
0
            call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1159
0
        close_connection_now(conn);
1160
0
        return;
1161
0
    }
1162
1163
0
    if (close_connection_if_necessary(conn))
1164
0
        return;
1165
1166
    /* unlink timeouts of streams that has finished sending requests */
1167
0
    while (!h2o_linklist_is_empty(&conn->output.sent_streams)) {
1168
0
        h2o_linklist_t *link = conn->output.sent_streams.next;
1169
0
        struct st_h2o_http2client_stream_t *stream =
1170
0
            H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, output.sending_link, link);
1171
0
        h2o_linklist_unlink(link);
1172
1173
0
        if (stream->send_own_expect && stream->state.req == STREAM_STATE_BODY) {
1174
0
            h2o_timer_link(stream->super.ctx->loop, stream->super.ctx->first_byte_timeout, &stream->super._timeout);
1175
0
            continue;
1176
0
        }
1177
1178
        /* request the app to send more, unless the stream is already closed (note: invocation of `proceed_req` might invoke
1179
         * `do_write_req` synchronously) */
1180
0
        int stream_destroyed = 0;
1181
0
        if (stream->output.proceed_req != NULL) {
1182
0
            stream->notify_destroyed = &stream_destroyed;
1183
0
            stream->output.proceed_req(&stream->super, NULL);
1184
0
            if (stream_destroyed)
1185
0
                continue;
1186
0
            stream->notify_destroyed = NULL;
1187
0
        }
1188
1189
0
        if (stream->output.proceed_req == NULL && !h2o_linklist_is_linked(&stream->output.sending_link)) {
1190
0
            stream->state.req = STREAM_STATE_CLOSED;
1191
0
            h2o_timer_link(stream->super.ctx->loop, stream->super.ctx->first_byte_timeout, &stream->super._timeout);
1192
0
        }
1193
0
    }
1194
1195
    /* reset the other buffer */
1196
0
    h2o_buffer_dispose(&conn->output.buf_in_flight);
1197
1198
    /* bail out if nothing can be written */
1199
0
    if (conn->output.buf->size == 0 && h2o_linklist_is_empty(&conn->output.sending_streams)) {
1200
0
        assert(!h2o_timer_is_linked(&conn->output.defer_timeout));
1201
0
        close_connection_if_necessary(conn);
1202
0
        return;
1203
0
    }
1204
1205
    /* run next write now instead of relying on the deferred timeout */
1206
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout))
1207
0
        h2o_timer_unlink(&conn->output.defer_timeout);
1208
0
#if !H2O_USE_LIBUV
1209
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_OPEN) {
1210
0
        h2o_socket_notify_write(sock, on_notify_write);
1211
0
        return;
1212
0
    }
1213
0
#endif
1214
0
    do_emit_writereq(conn);
1215
0
    close_connection_if_necessary(conn);
1216
0
}
1217
1218
static size_t sz_min(size_t x, size_t y)
1219
0
{
1220
0
    return x < y ? x : y;
1221
0
}
1222
1223
static size_t calc_max_payload_size(struct st_h2o_http2client_stream_t *stream)
1224
0
{
1225
0
    ssize_t conn_max, stream_max;
1226
1227
0
    if ((conn_max = conn_get_buffer_window(stream->conn)) <= 0)
1228
0
        return 0;
1229
0
    if ((stream_max = h2o_http2_window_get_avail(&stream->output.window)) <= 0)
1230
0
        return 0;
1231
0
    return sz_min(sz_min(conn_max, stream_max), stream->conn->peer_settings.max_frame_size);
1232
0
}
1233
1234
static void stream_emit_pending_data(struct st_h2o_http2client_stream_t *stream)
1235
0
{
1236
0
    size_t max_payload_size = calc_max_payload_size(stream);
1237
0
    size_t payload_size = sz_min(max_payload_size, stream->output.buf->size);
1238
0
    int end_stream = stream->output.proceed_req == NULL && payload_size == stream->output.buf->size;
1239
0
    if (payload_size == 0 && !end_stream)
1240
0
        return;
1241
0
    char *dst = h2o_buffer_reserve(&stream->conn->output.buf, H2O_HTTP2_FRAME_HEADER_SIZE + payload_size).base;
1242
0
    h2o_http2_encode_frame_header((void *)dst, payload_size, H2O_HTTP2_FRAME_TYPE_DATA,
1243
0
                                  end_stream ? H2O_HTTP2_FRAME_FLAG_END_STREAM : 0, stream->stream_id);
1244
0
    h2o_memcpy(dst + H2O_HTTP2_FRAME_HEADER_SIZE, stream->output.buf->bytes, payload_size);
1245
0
    stream->conn->output.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE + payload_size;
1246
0
    h2o_buffer_consume(&stream->output.buf, payload_size);
1247
1248
0
    h2o_http2_window_consume_window(&stream->conn->output.window, payload_size);
1249
0
    h2o_http2_window_consume_window(&stream->output.window, payload_size);
1250
0
}
1251
1252
static void do_emit_writereq(struct st_h2o_http2client_conn_t *conn)
1253
0
{
1254
0
    assert(conn->output.buf_in_flight == NULL);
1255
1256
    /* send DATA frames */
1257
0
    h2o_linklist_t pending;
1258
0
    h2o_linklist_init_anchor(&pending);
1259
0
    h2o_linklist_insert_list(&pending, &conn->output.sending_streams);
1260
0
    while (!h2o_linklist_is_empty(&pending)) {
1261
0
        struct st_h2o_http2client_stream_t *stream =
1262
0
            H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, output.sending_link, pending.next);
1263
0
        h2o_linklist_unlink(&stream->output.sending_link);
1264
1265
0
        if (stream->output.buf != NULL && !stream->send_own_expect)
1266
0
            stream_emit_pending_data(stream);
1267
1268
0
        if (stream->output.buf == NULL || stream->output.buf->size == 0) {
1269
0
            h2o_linklist_insert(&conn->output.sent_streams, &stream->output.sending_link);
1270
0
        } else if (h2o_http2_window_get_avail(&stream->output.window) > 0 && !stream->send_own_expect) {
1271
            /* re-insert to tail so that streams would be sent round-robin */
1272
0
            h2o_linklist_insert(&conn->output.sending_streams, &stream->output.sending_link);
1273
0
        } else {
1274
            /* stream is flow-control-blocked; is not linked until WINDOW_UPDATE frame is received */
1275
0
        }
1276
0
    }
1277
1278
0
    if (conn->output.buf->size != 0) {
1279
        /* write and wait for completion */
1280
0
        h2o_iovec_t buf = {conn->output.buf->bytes, conn->output.buf->size};
1281
0
        h2o_socket_write(conn->super.sock, &buf, 1, on_write_complete);
1282
0
        conn->output.buf_in_flight = conn->output.buf;
1283
0
        h2o_buffer_init(&conn->output.buf, &h2o_http2_wbuf_buffer_prototype);
1284
0
        if (!h2o_timer_is_linked(&conn->io_timeout))
1285
0
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1286
0
    }
1287
0
}
1288
1289
static void emit_writereq(h2o_timer_t *entry)
1290
0
{
1291
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, output.defer_timeout, entry);
1292
0
    do_emit_writereq(conn);
1293
0
}
1294
1295
static struct st_h2o_http2client_conn_t *create_connection(h2o_httpclient_ctx_t *ctx, h2o_socket_t *sock, h2o_url_t *origin_url,
1296
                                                           h2o_httpclient_connection_pool_t *connpool)
1297
0
{
1298
0
    struct st_h2o_http2client_conn_t *conn = h2o_mem_alloc(sizeof(*conn));
1299
1300
0
    memset(conn, 0, offsetof(struct st_h2o_http2client_conn_t, rst_streams_pool));
1301
0
    h2o_mem_init_pool(&conn->rst_streams_pool);
1302
1303
0
    conn->super.ctx = ctx;
1304
0
    conn->super.sock = sock;
1305
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_OPEN;
1306
0
    conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
1307
0
    conn->streams = kh_init(stream);
1308
0
    h2o_url_copy(NULL, &conn->super.origin_url, origin_url);
1309
0
    if (connpool != NULL)
1310
0
        h2o_linklist_insert(&connpool->http2.conns, &conn->super.link);
1311
0
    conn->io_timeout.cb = on_io_timeout;
1312
0
    conn->keepalive_timeout.cb = on_keepalive_timeout;
1313
1314
    /* output */
1315
0
    conn->output.header_table.hpack_capacity = H2O_HTTP2_SETTINGS_CLIENT_HEADER_TABLE_SIZE;
1316
0
    h2o_http2_window_init(&conn->output.window, conn->peer_settings.initial_window_size);
1317
0
    h2o_buffer_init(&conn->output.buf, &h2o_http2_wbuf_buffer_prototype);
1318
0
    conn->output.defer_timeout.cb = emit_writereq;
1319
0
    h2o_linklist_init_anchor(&conn->output.sending_streams);
1320
0
    h2o_linklist_init_anchor(&conn->output.sent_streams);
1321
1322
    /* input */
1323
0
    conn->input.header_table.hpack_capacity = conn->input.header_table.hpack_max_capacity =
1324
0
        H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1325
0
    h2o_http2_window_init(&conn->input.window, H2O_HTTP2_SETTINGS_DEFAULT.initial_window_size);
1326
0
    conn->input.read_frame = expect_settings;
1327
1328
0
    return conn;
1329
0
}
1330
1331
static void send_client_preface(struct st_h2o_http2client_conn_t *conn, h2o_httpclient_ctx_t *ctx)
1332
0
{
1333
0
#define PREFIX                                                                                                                     \
1334
0
    "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"                                                                                             \
1335
0
    "\x00\x00\x12"     /* frame size */                                                                                            \
1336
0
    "\x04"             /* settings frame */                                                                                        \
1337
0
    "\x00"             /* no flags */                                                                                              \
1338
0
    "\x00\x00\x00\x00" /* stream id */                                                                                             \
1339
0
    "\x00\x02"         /* enable_push */                                                                                           \
1340
0
    "\x00\x00\x00\x00" /* 0 */                                                                                                     \
1341
0
    "\x00\x03"         /* max_concurrent_streams */                                                                                \
1342
0
    "\x00\x00\x00\x64" /* 100 */                                                                                                   \
1343
0
    "\x00\x04"         /* initial_window_size */
1344
0
    static const size_t len = sizeof(PREFIX) - 1 + 4;
1345
1346
0
    uint32_t initial_window_size = get_max_buffer_size(ctx);
1347
1348
0
    h2o_iovec_t vec = h2o_buffer_reserve(&conn->output.buf, len);
1349
0
    memcpy(vec.base, PREFIX, sizeof(PREFIX) - 1);
1350
1351
    /* encode max_buffer_size */
1352
0
    vec.base[len - 4] = (char)((initial_window_size >> 24) & 0xff);
1353
0
    vec.base[len - 3] = (char)((initial_window_size >> 16) & 0xff);
1354
0
    vec.base[len - 2] = (char)((initial_window_size >> 8) & 0xff);
1355
0
    vec.base[len - 1] = (char)(initial_window_size & 0xff);
1356
1357
0
    conn->output.buf->size += len;
1358
0
    request_write(conn);
1359
0
#undef PREFIX
1360
0
}
1361
1362
static void do_cancel(h2o_httpclient_t *_client)
1363
0
{
1364
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1365
0
    stream_send_error(stream->conn, stream->stream_id, H2O_HTTP2_ERROR_CANCEL);
1366
0
    close_stream(stream);
1367
0
}
1368
1369
static void do_get_conn_properties(h2o_httpclient_t *_client, h2o_httpclient_conn_properties_t *properties)
1370
0
{
1371
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1372
0
    h2o_httpclient_set_conn_properties_of_socket(stream->conn->super.sock, properties);
1373
0
}
1374
1375
static void do_update_window(h2o_httpclient_t *_client)
1376
0
{
1377
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1378
0
    size_t max = get_max_buffer_size(stream->super.ctx);
1379
0
    size_t bufsize = stream->input.body->size;
1380
0
    assert(bufsize <= max);
1381
0
    enqueue_window_update(stream->conn, stream->stream_id, &stream->input.window, max - bufsize);
1382
0
}
1383
1384
static int do_write_req(h2o_httpclient_t *_client, h2o_iovec_t chunk, int is_end_stream)
1385
0
{
1386
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1387
0
    assert(stream->output.proceed_req != NULL);
1388
0
    assert(!h2o_linklist_is_linked(&stream->output.sending_link));
1389
1390
0
    if (is_end_stream)
1391
0
        stream->output.proceed_req = NULL;
1392
1393
0
    if (stream->output.buf == NULL)
1394
0
        h2o_buffer_init(&stream->output.buf, &h2o_socket_buffer_prototype);
1395
1396
0
    if (chunk.len != 0)
1397
0
        h2o_buffer_append(&stream->output.buf, chunk.base, chunk.len);
1398
1399
0
    h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
1400
0
    request_write(stream->conn);
1401
1402
0
    return 0;
1403
0
}
1404
1405
static void setup_stream(struct st_h2o_http2client_stream_t *stream)
1406
0
{
1407
0
    memset(&stream->conn, 0, sizeof(*stream) - offsetof(struct st_h2o_http2client_stream_t, conn));
1408
1409
0
    stream->super._timeout.cb = on_stream_timeout;
1410
0
    h2o_http2_window_init(&stream->input.window, get_max_buffer_size(stream->super.ctx));
1411
0
    h2o_buffer_init(&stream->input.body, &h2o_socket_buffer_prototype);
1412
0
    stream->input.remaining_content_length = SIZE_MAX;
1413
0
    stream->input.message_body_forbidden = 0;
1414
1415
0
    stream->super.buf = &stream->input.body;
1416
0
    stream->super.cancel = do_cancel;
1417
0
    stream->super.get_conn_properties = do_get_conn_properties;
1418
0
    stream->super.update_window = do_update_window;
1419
0
    stream->super.write_req = do_write_req;
1420
0
}
1421
1422
void h2o_httpclient__h2_on_connect(h2o_httpclient_t *_client, h2o_socket_t *sock, h2o_url_t *origin)
1423
0
{
1424
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1425
1426
0
    assert(!h2o_timer_is_linked(&stream->super._timeout));
1427
1428
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1429
0
    if (conn == NULL) {
1430
0
        conn = create_connection(stream->super.ctx, sock, origin, stream->super.connpool);
1431
0
        sock->data = conn;
1432
        /* send preface, settings, and connection-level window update */
1433
0
        send_client_preface(conn, stream->super.ctx);
1434
0
        h2o_socket_read_start(conn->super.sock, on_read);
1435
0
    }
1436
1437
0
    setup_stream(stream);
1438
1439
0
    if (!h2o_timer_is_linked(&conn->io_timeout))
1440
0
        h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1441
0
    on_connection_ready(stream, conn);
1442
0
}
1443
1444
const size_t h2o_httpclient__h2_size = sizeof(struct st_h2o_http2client_stream_t);