Coverage Report

Created: 2025-08-26 06:33

/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, int headers_had_end_stream)
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
        conn->input.read_frame = expect_default;
475
476
0
        if (stream != NULL && stream->state.res == STREAM_STATE_BODY) {
477
0
            hret = on_trailers(conn, stream, (const uint8_t *)conn->input.headers_unparsed->bytes,
478
0
                               conn->input.headers_unparsed->size, err_desc);
479
0
        } else {
480
0
            hret = on_head(conn, stream, (const uint8_t *)conn->input.headers_unparsed->bytes, conn->input.headers_unparsed->size,
481
0
                           err_desc, headers_had_end_stream);
482
0
        }
483
0
        if (hret != 0)
484
0
            ret = hret;
485
486
0
        h2o_buffer_dispose(&conn->input.headers_unparsed);
487
0
        conn->input.headers_unparsed = NULL;
488
0
    }
489
490
0
    return ret;
491
0
}
492
493
static ssize_t expect_continuation_of_headers_eos(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len,
494
                                                  const char **err_desc)
495
0
{
496
0
    return expect_continuation_of_headers(conn, src, len, err_desc, 1);
497
0
}
498
499
static ssize_t expect_continuation_of_headers_no_eos(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len,
500
        const char **err_desc)
501
0
{
502
0
    return expect_continuation_of_headers(conn, src, len, err_desc, 0);
503
0
}
504
505
static void do_update_window(h2o_httpclient_t *client);
506
static int handle_data_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
507
0
{
508
0
    h2o_http2_data_payload_t payload;
509
0
    struct st_h2o_http2client_stream_t *stream;
510
0
    int ret;
511
512
0
    if ((ret = h2o_http2_decode_data_payload(&payload, frame, err_desc)) != 0)
513
0
        return ret;
514
515
    /* save the input in the request body buffer, or send error (and close the stream) */
516
0
    if ((stream = get_stream(conn, frame->stream_id)) == NULL) {
517
0
        if (frame->stream_id <= conn->max_open_stream_id) {
518
0
            h2o_http2_window_consume_window(&conn->input.window, payload.length);
519
0
            enqueue_window_update(conn, 0, &conn->input.window, H2O_HTTP2_SETTINGS_CLIENT_CONNECTION_WINDOW_SIZE);
520
0
            return 0;
521
0
        } else {
522
0
            *err_desc = "invalid DATA frame";
523
0
            return H2O_HTTP2_ERROR_PROTOCOL;
524
0
        }
525
0
    }
526
527
0
    if (stream->state.res != STREAM_STATE_BODY) {
528
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
529
0
        call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
530
0
        close_stream(stream);
531
0
        return 0;
532
0
    }
533
534
    /**
535
     * RFC7230 Section 3.3.
536
     *
537
     *  Responses to the HEAD request method (Section 4.3.2 of [RFC7231]) never
538
     *  include a message body because the associated response header fields
539
     *  (e.g., Transfer-Encoding, Content-Length, etc.), if present, indicate
540
     *  only what their values would have been if the request method had been
541
     *  GET (Section 4.3.1 of [RFC7231]).
542
     *
543
     *  2xx (Successful) responses to a CONNECT request method (Section 4.3.6
544
     *  of [RFC7231]) switch to tunnel mode instead of having a message body.
545
     *
546
     *  All 1xx (Informational), 204 (No Content), and 304 (Not Modified)
547
     *  responses do not include a message body.
548
     *
549
     *  All other responses do include a message body, although the body might
550
     *  be of zero length.
551
     */
552
0
    if (stream->input.message_body_forbidden && payload.length != 0) {
553
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
554
0
        call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
555
0
        close_stream(stream);
556
0
        return 0;
557
0
    }
558
559
    /**
560
     * RFC 7540 Section 8.1.2.6.
561
     *  A request or response is also malformed if the value of
562
     *  a content-length header field does not equal the sum of the DATA frame
563
     *  payload lengths that form the body.
564
     */
565
0
    if (stream->input.remaining_content_length != SIZE_MAX) {
566
0
        if (payload.length > stream->input.remaining_content_length) {
567
0
            stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_PROTOCOL);
568
0
            call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
569
0
            close_stream(stream);
570
0
            return 0;
571
0
        }
572
0
        stream->input.remaining_content_length -= payload.length;
573
0
    }
574
575
0
    size_t max_size = get_max_buffer_size(stream->super.ctx);
576
0
    if (stream->input.body->size + payload.length > max_size) {
577
0
        call_callback_with_error(stream, h2o_httpclient_error_flow_control);
578
0
        stream_send_error(stream->conn, stream->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
579
0
        close_stream(stream);
580
0
        return 0;
581
0
    }
582
583
0
    h2o_buffer_append(&stream->input.body, (void *)payload.data, payload.length);
584
585
0
    h2o_http2_window_consume_window(&conn->input.window, payload.length);
586
0
    h2o_http2_window_consume_window(&stream->input.window, payload.length);
587
588
0
    int is_final = (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0;
589
0
    if (stream->super._cb.on_body(&stream->super, is_final ? h2o_httpclient_error_is_eos : NULL, NULL, 0) != 0) {
590
0
        stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_INTERNAL);
591
0
        close_stream(stream);
592
0
        return 0;
593
0
    }
594
595
0
    if (is_final) {
596
0
        close_response(stream);
597
0
    } else {
598
        /* update connection-level window */
599
0
        enqueue_window_update(stream->conn, 0, &stream->conn->input.window, H2O_HTTP2_SETTINGS_CLIENT_CONNECTION_WINDOW_SIZE);
600
        /* update stream-level window */
601
0
        do_update_window(&stream->super);
602
0
    }
603
604
0
    return 0;
605
0
}
606
607
static int handle_headers_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
608
0
{
609
0
    h2o_http2_headers_payload_t payload;
610
0
    struct st_h2o_http2client_stream_t *stream;
611
0
    int ret;
612
613
    /* decode */
614
0
    if ((ret = h2o_http2_decode_headers_payload(&payload, frame, err_desc)) != 0)
615
0
        return ret;
616
0
    if ((frame->stream_id & 1) == 0) {
617
0
        *err_desc = "invalid stream id in HEADERS frame";
618
0
        return H2O_HTTP2_ERROR_PROTOCOL;
619
0
    }
620
621
0
    if (frame->stream_id == payload.priority.dependency) {
622
0
        *err_desc = "stream cannot depend on itself";
623
0
        return H2O_HTTP2_ERROR_PROTOCOL;
624
0
    }
625
626
0
    if ((stream = get_stream(conn, frame->stream_id)) == NULL) {
627
0
        if (frame->stream_id > conn->max_open_stream_id) {
628
0
            *err_desc = "invalid stream id in HEADERS frame";
629
0
            return H2O_HTTP2_ERROR_PROTOCOL;
630
0
        }
631
0
    }
632
633
0
    int is_end_stream = (frame->flags & H2O_HTTP2_FRAME_FLAG_END_STREAM) != 0;
634
635
0
    if (stream != NULL) {
636
0
        h2o_timer_unlink(&stream->super._timeout);
637
638
0
        if (stream->state.res == STREAM_STATE_BODY && !is_end_stream) {
639
0
            *err_desc = "trailing HEADERS frame MUST have END_STREAM flag set";
640
0
            return H2O_HTTP2_ERROR_PROTOCOL;
641
0
        }
642
0
    }
643
644
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_END_HEADERS) == 0) {
645
        /* header is not complete, store in buffer */
646
0
        conn->input.read_frame = is_end_stream ? expect_continuation_of_headers_eos : expect_continuation_of_headers_no_eos;
647
0
        h2o_buffer_init(&conn->input.headers_unparsed, &h2o_socket_buffer_prototype);
648
0
        h2o_buffer_reserve(&conn->input.headers_unparsed, payload.headers_len);
649
0
        memcpy(conn->input.headers_unparsed->bytes, payload.headers, payload.headers_len);
650
0
        conn->input.headers_unparsed->size = payload.headers_len;
651
0
        return 0;
652
0
    }
653
654
    /* response header is complete, handle it */
655
0
    if (stream != NULL && stream->state.res == STREAM_STATE_BODY) {
656
0
        return on_trailers(conn, stream, payload.headers, payload.headers_len, err_desc);
657
0
    } else {
658
0
        return on_head(conn, stream, payload.headers, payload.headers_len, err_desc, is_end_stream);
659
0
    }
660
0
}
661
662
static int handle_priority_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
663
0
{
664
0
    h2o_http2_priority_t payload;
665
0
    int ret;
666
667
0
    if ((ret = h2o_http2_decode_priority_payload(&payload, frame, err_desc)) != 0)
668
0
        return ret;
669
0
    if (frame->stream_id == payload.dependency) {
670
0
        *err_desc = "stream cannot depend on itself";
671
0
        return H2O_HTTP2_ERROR_PROTOCOL;
672
0
    }
673
674
    /* Ignore PRIORITY frames */
675
0
    return 0;
676
0
}
677
678
static int handle_rst_stream_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
679
0
{
680
0
    h2o_http2_rst_stream_payload_t payload;
681
0
    struct st_h2o_http2client_stream_t *stream;
682
0
    int ret;
683
684
0
    if ((ret = h2o_http2_decode_rst_stream_payload(&payload, frame, err_desc)) != 0)
685
0
        return ret;
686
0
    if (frame->stream_id > conn->max_open_stream_id) {
687
0
        *err_desc = "unexpected stream id in RST_STREAM frame";
688
0
        return H2O_HTTP2_ERROR_PROTOCOL;
689
0
    }
690
691
0
    stream = get_stream(conn, frame->stream_id);
692
0
    if (stream != NULL) {
693
        /* reset the stream */
694
0
        call_callback_with_error(stream, payload.error_code == -H2O_HTTP2_ERROR_REFUSED_STREAM ? h2o_httpclient_error_refused_stream
695
0
                                                                                               : h2o_httpclient_error_io);
696
0
        close_stream(stream);
697
0
    }
698
699
0
    return 0;
700
0
}
701
702
static int update_stream_output_window(struct st_h2o_http2client_stream_t *stream, ssize_t delta)
703
0
{
704
0
    if (h2o_http2_window_update(&stream->output.window, delta) != 0)
705
0
        return -1;
706
0
    ssize_t after = h2o_http2_window_get_avail(&stream->output.window);
707
0
    if (after > 0 && stream->output.buf != NULL && stream->output.buf->size != 0 &&
708
0
        !h2o_linklist_is_linked(&stream->output.sending_link))
709
0
        h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
710
0
    return 0;
711
0
}
712
713
static ssize_t conn_get_buffer_window(struct st_h2o_http2client_conn_t *conn)
714
0
{
715
0
    ssize_t ret, winsz;
716
0
    size_t capacity, cwnd_left;
717
718
0
    capacity = conn->output.buf->capacity;
719
0
    if ((cwnd_left = h2o_socket_prepare_for_latency_optimized_write(conn->super.sock,
720
0
                                                                    &conn->super.ctx->http2.latency_optimization)) < capacity) {
721
0
        capacity = cwnd_left;
722
0
        if (capacity < conn->output.buf->size)
723
0
            return 0;
724
0
    }
725
726
0
    ret = capacity - conn->output.buf->size;
727
0
    if (ret < H2O_HTTP2_FRAME_HEADER_SIZE)
728
0
        return 0;
729
0
    ret -= H2O_HTTP2_FRAME_HEADER_SIZE;
730
0
    winsz = h2o_http2_window_get_avail(&conn->output.window);
731
0
    if (winsz < ret)
732
0
        ret = winsz;
733
0
    return ret;
734
0
}
735
736
static int handle_settings_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
737
0
{
738
0
    if (frame->stream_id != 0) {
739
0
        *err_desc = "invalid stream id in SETTINGS frame";
740
0
        return H2O_HTTP2_ERROR_PROTOCOL;
741
0
    }
742
743
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) != 0) {
744
0
        if (frame->length != 0) {
745
0
            *err_desc = "invalid SETTINGS frame (+ACK)";
746
0
            return H2O_HTTP2_ERROR_FRAME_SIZE;
747
0
        }
748
0
    } else {
749
0
        uint32_t prev_initial_window_size = conn->peer_settings.initial_window_size;
750
0
        int ret = h2o_http2_update_peer_settings(&conn->peer_settings, frame->payload, frame->length, err_desc);
751
0
        if (ret != 0)
752
0
            return ret;
753
0
        { /* schedule ack */
754
0
            h2o_iovec_t header_buf = h2o_buffer_reserve(&conn->output.buf, H2O_HTTP2_FRAME_HEADER_SIZE);
755
0
            h2o_http2_encode_frame_header((void *)header_buf.base, 0, H2O_HTTP2_FRAME_TYPE_SETTINGS, H2O_HTTP2_FRAME_FLAG_ACK, 0);
756
0
            conn->output.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE;
757
0
            request_write(conn);
758
0
        }
759
        /* apply the change to window size (to all the streams but not the connection, see 6.9.2 of draft-15) */
760
0
        if (prev_initial_window_size != conn->peer_settings.initial_window_size) {
761
0
            ssize_t delta = conn->peer_settings.initial_window_size - prev_initial_window_size;
762
0
            struct st_h2o_http2client_stream_t *stream;
763
0
            kh_foreach_value(conn->streams, stream, { update_stream_output_window((void *)stream, delta); });
764
765
0
            if (conn_get_buffer_window(conn) > 0)
766
0
                request_write(conn);
767
0
        }
768
0
    }
769
770
0
    return 0;
771
0
}
772
773
static int handle_push_promise_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
774
0
{
775
0
    *err_desc = "received PUSH_PROMISE frame";
776
0
    return H2O_HTTP2_ERROR_PROTOCOL;
777
0
}
778
779
static int handle_ping_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
780
0
{
781
0
    h2o_http2_ping_payload_t payload;
782
0
    int ret;
783
784
0
    if ((ret = h2o_http2_decode_ping_payload(&payload, frame, err_desc)) != 0)
785
0
        return ret;
786
787
0
    if ((frame->flags & H2O_HTTP2_FRAME_FLAG_ACK) == 0) {
788
0
        h2o_http2_encode_ping_frame(&conn->output.buf, 1, payload.data);
789
0
        request_write(conn);
790
0
    }
791
792
0
    return 0;
793
0
}
794
795
static int handle_goaway_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
796
0
{
797
0
    h2o_http2_goaway_payload_t payload;
798
0
    int ret;
799
800
0
    if ((ret = h2o_http2_decode_goaway_payload(&payload, frame, err_desc)) != 0)
801
0
        return ret;
802
803
0
    struct st_h2o_http2client_stream_t *stream;
804
0
    kh_foreach_value(conn->streams, stream, {
805
0
        if (stream->stream_id > payload.last_stream_id) {
806
0
            call_callback_with_error(stream, h2o_httpclient_error_refused_stream);
807
0
            close_stream(stream);
808
0
        }
809
0
    });
810
811
    /* stop opening new streams */
812
0
    if (h2o_linklist_is_linked(&conn->super.link))
813
0
        h2o_linklist_unlink(&conn->super.link);
814
815
0
    return 0;
816
0
}
817
818
static int handle_window_update_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc)
819
0
{
820
0
    h2o_http2_window_update_payload_t payload;
821
0
    int ret, err_is_stream_level;
822
823
0
    if ((ret = h2o_http2_decode_window_update_payload(&payload, frame, err_desc, &err_is_stream_level)) != 0) {
824
0
        if (err_is_stream_level) {
825
0
            stream_send_error(conn, frame->stream_id, ret);
826
0
            struct st_h2o_http2client_stream_t *stream = get_stream(conn, frame->stream_id);
827
0
            if (stream != NULL) {
828
0
                call_callback_with_error(stream, h2o_httpclient_error_protocol_violation);
829
0
                close_stream(stream);
830
0
            }
831
0
            return 0;
832
0
        } else {
833
0
            return ret;
834
0
        }
835
0
    }
836
837
0
    if (frame->stream_id == 0) {
838
0
        if (h2o_http2_window_update(&conn->output.window, payload.window_size_increment) != 0) {
839
0
            *err_desc = "flow control window overflow";
840
0
            return H2O_HTTP2_ERROR_FLOW_CONTROL;
841
0
        }
842
0
    } else if (frame->stream_id <= conn->max_open_stream_id) {
843
0
        struct st_h2o_http2client_stream_t *stream = get_stream(conn, frame->stream_id);
844
0
        if (stream != NULL) {
845
0
            if (update_stream_output_window(stream, payload.window_size_increment) != 0) {
846
0
                stream_send_error(conn, frame->stream_id, H2O_HTTP2_ERROR_FLOW_CONTROL);
847
0
                call_callback_with_error(stream, h2o_httpclient_error_flow_control);
848
0
                close_stream(stream);
849
0
                return 0;
850
0
            }
851
0
        }
852
0
    } else {
853
0
        *err_desc = "invalid stream id in WINDOW_UPDATE frame";
854
0
        return H2O_HTTP2_ERROR_PROTOCOL;
855
0
    }
856
857
0
    if (conn_get_buffer_window(conn) > 0)
858
0
        request_write(conn);
859
860
0
    return 0;
861
0
}
862
863
static int handle_invalid_continuation_frame(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame,
864
                                             const char **err_desc)
865
0
{
866
0
    *err_desc = "received invalid CONTINUATION frame";
867
0
    return H2O_HTTP2_ERROR_PROTOCOL;
868
0
}
869
870
ssize_t expect_default(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
871
0
{
872
0
    assert(conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING);
873
874
0
    h2o_http2_frame_t frame;
875
0
    ssize_t ret;
876
0
    static int (*FRAME_HANDLERS[])(struct st_h2o_http2client_conn_t *conn, h2o_http2_frame_t *frame, const char **err_desc) = {
877
0
        handle_data_frame,                /* DATA */
878
0
        handle_headers_frame,             /* HEADERS */
879
0
        handle_priority_frame,            /* PRIORITY */
880
0
        handle_rst_stream_frame,          /* RST_STREAM */
881
0
        handle_settings_frame,            /* SETTINGS */
882
0
        handle_push_promise_frame,        /* PUSH_PROMISE */
883
0
        handle_ping_frame,                /* PING */
884
0
        handle_goaway_frame,              /* GOAWAY */
885
0
        handle_window_update_frame,       /* WINDOW_UPDATE */
886
0
        handle_invalid_continuation_frame /* CONTINUATION */
887
0
    };
888
889
0
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE, err_desc)) < 0)
890
0
        return ret;
891
892
0
    if (frame.type < sizeof(FRAME_HANDLERS) / sizeof(FRAME_HANDLERS[0])) {
893
0
        int hret = FRAME_HANDLERS[frame.type](conn, &frame, err_desc);
894
0
        if (hret != 0)
895
0
            ret = hret;
896
0
    } else {
897
0
        h2o_error_printf("skipping frame (type:%d)\n", frame.type);
898
0
    }
899
900
0
    return ret;
901
0
}
902
903
static ssize_t expect_settings(struct st_h2o_http2client_conn_t *conn, const uint8_t *src, size_t len, const char **err_desc)
904
0
{
905
0
    assert(conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING);
906
907
0
    h2o_http2_frame_t frame;
908
0
    ssize_t ret;
909
910
0
    if ((ret = h2o_http2_decode_frame(&frame, src, len, H2O_HTTP2_SETTINGS_CLIENT_MAX_FRAME_SIZE, err_desc)) < 0)
911
0
        return ret;
912
913
0
    if (frame.type != H2O_HTTP2_FRAME_TYPE_SETTINGS)
914
0
        return H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY;
915
916
0
    int hret = handle_settings_frame(conn, &frame, err_desc);
917
0
    if (hret != 0)
918
0
        return hret;
919
920
0
    conn->input.read_frame = expect_default;
921
0
    return ret;
922
0
}
923
924
static void close_connection_now(struct st_h2o_http2client_conn_t *conn)
925
0
{
926
0
    free(conn->super.origin_url.authority.base);
927
0
    free(conn->super.origin_url.host.base);
928
0
    free(conn->super.origin_url.path.base);
929
930
0
    h2o_socket_close(conn->super.sock);
931
932
0
    struct st_h2o_http2client_stream_t *stream;
933
0
    kh_foreach_value(conn->streams, stream, { close_stream(stream); });
934
0
    kh_destroy(stream, conn->streams);
935
936
0
    if (h2o_linklist_is_linked(&conn->super.link))
937
0
        h2o_linklist_unlink(&conn->super.link);
938
939
0
    if (h2o_timer_is_linked(&conn->io_timeout))
940
0
        h2o_timer_unlink(&conn->io_timeout);
941
0
    if (h2o_timer_is_linked(&conn->keepalive_timeout))
942
0
        h2o_timer_unlink(&conn->keepalive_timeout);
943
944
    /* output */
945
0
    h2o_hpack_dispose_header_table(&conn->output.header_table);
946
0
    h2o_buffer_dispose(&conn->output.buf);
947
0
    if (conn->output.buf_in_flight != NULL)
948
0
        h2o_buffer_dispose(&conn->output.buf_in_flight);
949
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout))
950
0
        h2o_timer_unlink(&conn->output.defer_timeout);
951
0
    assert(h2o_linklist_is_empty(&conn->output.sending_streams));
952
0
    assert(h2o_linklist_is_empty(&conn->output.sent_streams));
953
954
    /* input */
955
0
    h2o_hpack_dispose_header_table(&conn->input.header_table);
956
0
    if (conn->input.headers_unparsed != NULL)
957
0
        h2o_buffer_dispose(&conn->input.headers_unparsed);
958
959
0
    h2o_mem_clear_pool(&conn->rst_streams_pool);
960
0
    free(conn);
961
0
}
962
963
static int close_connection_if_necessary(struct st_h2o_http2client_conn_t *conn)
964
0
{
965
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_HALF_CLOSED && conn->super.num_streams == 0)
966
0
        conn->state = H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING;
967
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING) {
968
0
        close_connection_now(conn);
969
0
        return 1;
970
0
    }
971
0
    return 0;
972
0
}
973
974
static int close_connection(struct st_h2o_http2client_conn_t *conn)
975
0
{
976
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING;
977
0
    h2o_socket_read_stop(conn->super.sock);
978
979
0
    if (conn->output.buf_in_flight != NULL || h2o_timer_is_linked(&conn->output.defer_timeout)) {
980
        /* there is a pending write, let close_connection_if_necessary actually close the connection */
981
0
    } else {
982
0
        close_connection_now(conn);
983
0
        return -1;
984
0
    }
985
0
    return 0;
986
0
}
987
988
static void enqueue_goaway(struct st_h2o_http2client_conn_t *conn, int errnum, h2o_iovec_t additional_data)
989
0
{
990
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING)
991
0
        return;
992
993
0
    h2o_http2_encode_goaway_frame(&conn->output.buf, 0, errnum, additional_data);
994
0
    request_write(conn);
995
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_HALF_CLOSED;
996
997
    /* stop opening new streams */
998
0
    if (h2o_linklist_is_linked(&conn->super.link))
999
0
        h2o_linklist_unlink(&conn->super.link);
1000
0
}
1001
1002
static void on_connect_error(struct st_h2o_http2client_stream_t *stream, const char *errstr)
1003
0
{
1004
0
    assert(errstr != NULL);
1005
0
    stream->super._cb.on_connect(&stream->super, errstr, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL);
1006
0
    close_stream(stream);
1007
0
}
1008
1009
static void do_stream_timeout(struct st_h2o_http2client_stream_t *stream)
1010
0
{
1011
0
    if (stream->conn == NULL) {
1012
0
        on_connect_error(stream, h2o_httpclient_error_connect_timeout);
1013
0
        return;
1014
0
    }
1015
0
    const char *errstr =
1016
0
        stream->state.res == STREAM_STATE_HEAD ? h2o_httpclient_error_first_byte_timeout : h2o_httpclient_error_io_timeout;
1017
0
    call_callback_with_error(stream, errstr);
1018
0
    close_stream(stream);
1019
0
}
1020
1021
static void on_stream_timeout(h2o_timer_t *entry)
1022
0
{
1023
0
    struct st_h2o_http2client_stream_t *stream = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, super._timeout, entry);
1024
0
    do_stream_timeout(stream);
1025
0
}
1026
1027
static void on_io_timeout(h2o_timer_t *entry)
1028
0
{
1029
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, io_timeout, entry);
1030
0
    struct st_h2o_http2client_stream_t *stream;
1031
0
    kh_foreach_value(conn->streams, stream, { do_stream_timeout(stream); });
1032
0
    close_connection_now(conn);
1033
0
}
1034
1035
static void on_keepalive_timeout(h2o_timer_t *entry)
1036
0
{
1037
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, keepalive_timeout, entry);
1038
0
    enqueue_goaway(conn, H2O_HTTP2_ERROR_NONE, h2o_iovec_init(NULL, 0));
1039
0
    request_write(conn);
1040
0
    close_connection(conn);
1041
0
}
1042
1043
static int parse_input(struct st_h2o_http2client_conn_t *conn)
1044
0
{
1045
    /* handle the input */
1046
0
    while (conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING && conn->super.sock->input->size != 0) {
1047
        /* process a frame */
1048
0
        const char *err_desc = NULL;
1049
0
        ssize_t ret =
1050
0
            conn->input.read_frame(conn, (uint8_t *)conn->super.sock->input->bytes, conn->super.sock->input->size, &err_desc);
1051
0
        if (ret == H2O_HTTP2_ERROR_INCOMPLETE) {
1052
0
            break;
1053
0
        } else if (ret < 0) {
1054
0
            if (ret != H2O_HTTP2_ERROR_PROTOCOL_CLOSE_IMMEDIATELY) {
1055
0
                enqueue_goaway(conn, (int)ret,
1056
0
                               err_desc != NULL ? (h2o_iovec_t){(char *)err_desc, strlen(err_desc)} : (h2o_iovec_t){NULL});
1057
0
            }
1058
0
            call_stream_callbacks_with_error(conn, h2o_httpclient_error_protocol_violation);
1059
0
            return close_connection(conn);
1060
0
        }
1061
        /* advance to the next frame */
1062
0
        h2o_buffer_consume(&conn->super.sock->input, ret);
1063
0
    }
1064
0
    return 0;
1065
0
}
1066
1067
static void on_read(h2o_socket_t *sock, const char *err)
1068
0
{
1069
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1070
1071
0
    h2o_timer_unlink(&conn->io_timeout);
1072
1073
0
    if (err != NULL) {
1074
0
        call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1075
0
        close_connection(conn);
1076
0
        return;
1077
0
    }
1078
1079
0
    if (parse_input(conn) != 0)
1080
0
        return;
1081
1082
    /* write immediately, if pending write exists */
1083
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout)) {
1084
0
        h2o_timer_unlink(&conn->output.defer_timeout);
1085
0
        do_emit_writereq(conn);
1086
0
    }
1087
1088
0
    if (!h2o_timer_is_linked(&conn->io_timeout))
1089
0
        h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1090
0
}
1091
1092
static void on_connection_ready(struct st_h2o_http2client_stream_t *stream, struct st_h2o_http2client_conn_t *conn)
1093
0
{
1094
0
    h2o_iovec_t method;
1095
0
    h2o_url_t url;
1096
0
    h2o_header_t *headers;
1097
0
    size_t num_headers;
1098
0
    h2o_iovec_t body;
1099
0
    h2o_httpclient_properties_t props = (h2o_httpclient_properties_t){NULL};
1100
1101
0
    register_stream(stream, conn);
1102
1103
0
    stream->super._cb.on_head =
1104
0
        stream->super._cb.on_connect(&stream->super, NULL, &method, &url, (const h2o_header_t **)&headers, &num_headers, &body,
1105
0
                                     &stream->output.proceed_req, &props, &conn->super.origin_url);
1106
0
    if (stream->super._cb.on_head == NULL) {
1107
0
        close_stream(stream);
1108
0
        return;
1109
0
    }
1110
1111
0
    h2o_http2_window_init(&stream->output.window, conn->peer_settings.initial_window_size);
1112
1113
    /* forward request state */
1114
0
    if (stream->output.proceed_req != NULL) {
1115
0
        stream->state.req = STREAM_STATE_BODY;
1116
0
    } else if (body.base != NULL) {
1117
0
        stream->state.req = STREAM_STATE_BODY;
1118
0
    } else {
1119
0
        stream->state.req = STREAM_STATE_CLOSED;
1120
0
    }
1121
1122
0
    if (h2o_memis(method.base, method.len, H2O_STRLIT("HEAD"))) {
1123
0
        stream->input.message_body_forbidden = 1;
1124
0
    }
1125
1126
0
    if (props.send_own_expect && (stream->output.proceed_req != NULL || body.len != 0))
1127
0
        stream->send_own_expect = 1;
1128
1129
    /* send headers */
1130
0
    h2o_hpack_flatten_request(&conn->output.buf, &conn->output.header_table, conn->peer_settings.header_table_size,
1131
0
                              stream->stream_id, conn->peer_settings.max_frame_size, method, &url,
1132
0
                              stream->super.upgrade_to != NULL && stream->super.upgrade_to != h2o_httpclient_upgrade_to_connect
1133
0
                                  ? h2o_iovec_init(stream->super.upgrade_to, strlen(stream->super.upgrade_to))
1134
0
                                  : h2o_iovec_init(NULL, 0),
1135
0
                              headers, num_headers, stream->state.req == STREAM_STATE_CLOSED, stream->send_own_expect);
1136
1137
0
    if (stream->state.req == STREAM_STATE_BODY) {
1138
0
        h2o_buffer_init(&stream->output.buf, &h2o_socket_buffer_prototype);
1139
0
        h2o_buffer_append(&stream->output.buf, body.base, body.len);
1140
0
    }
1141
0
    h2o_linklist_insert(&conn->output.sending_streams, &stream->output.sending_link);
1142
0
    request_write(conn);
1143
0
}
1144
1145
static void on_notify_write(h2o_socket_t *sock, const char *err)
1146
0
{
1147
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1148
1149
0
    if (err != NULL) {
1150
0
        call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1151
0
        close_connection_now(conn);
1152
0
        return;
1153
0
    }
1154
0
    do_emit_writereq(conn);
1155
0
    close_connection_if_necessary(conn);
1156
0
}
1157
1158
static void on_write_complete(h2o_socket_t *sock, const char *err)
1159
0
{
1160
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1161
1162
0
    assert(conn->output.buf_in_flight != NULL);
1163
1164
0
    h2o_timer_unlink(&conn->io_timeout);
1165
1166
    /* close by error if necessary */
1167
0
    if (err != NULL) {
1168
0
        if (conn->state != H2O_HTTP2CLIENT_CONN_STATE_IS_CLOSING)
1169
0
            call_stream_callbacks_with_error(conn, h2o_httpclient_error_io);
1170
0
        close_connection_now(conn);
1171
0
        return;
1172
0
    }
1173
1174
0
    if (close_connection_if_necessary(conn))
1175
0
        return;
1176
1177
    /* unlink timeouts of streams that has finished sending requests */
1178
0
    while (!h2o_linklist_is_empty(&conn->output.sent_streams)) {
1179
0
        h2o_linklist_t *link = conn->output.sent_streams.next;
1180
0
        struct st_h2o_http2client_stream_t *stream =
1181
0
            H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, output.sending_link, link);
1182
0
        h2o_linklist_unlink(link);
1183
1184
0
        if (stream->send_own_expect && stream->state.req == STREAM_STATE_BODY) {
1185
0
            h2o_timer_link(stream->super.ctx->loop, stream->super.ctx->first_byte_timeout, &stream->super._timeout);
1186
0
            continue;
1187
0
        }
1188
1189
        /* request the app to send more, unless the stream is already closed (note: invocation of `proceed_req` might invoke
1190
         * `do_write_req` synchronously) */
1191
0
        int stream_destroyed = 0;
1192
0
        if (stream->output.proceed_req != NULL) {
1193
0
            stream->notify_destroyed = &stream_destroyed;
1194
0
            stream->output.proceed_req(&stream->super, NULL);
1195
0
            if (stream_destroyed)
1196
0
                continue;
1197
0
            stream->notify_destroyed = NULL;
1198
0
        }
1199
1200
0
        if (stream->output.proceed_req == NULL && !h2o_linklist_is_linked(&stream->output.sending_link)) {
1201
0
            stream->state.req = STREAM_STATE_CLOSED;
1202
0
            h2o_timer_link(stream->super.ctx->loop, stream->super.ctx->first_byte_timeout, &stream->super._timeout);
1203
0
        }
1204
0
    }
1205
1206
    /* reset the other buffer */
1207
0
    h2o_buffer_dispose(&conn->output.buf_in_flight);
1208
1209
    /* bail out if nothing can be written */
1210
0
    if (conn->output.buf->size == 0 && h2o_linklist_is_empty(&conn->output.sending_streams)) {
1211
0
        assert(!h2o_timer_is_linked(&conn->output.defer_timeout));
1212
0
        close_connection_if_necessary(conn);
1213
0
        return;
1214
0
    }
1215
1216
    /* run next write now instead of relying on the deferred timeout */
1217
0
    if (h2o_timer_is_linked(&conn->output.defer_timeout))
1218
0
        h2o_timer_unlink(&conn->output.defer_timeout);
1219
0
#if !H2O_USE_LIBUV
1220
0
    if (conn->state == H2O_HTTP2CLIENT_CONN_STATE_OPEN) {
1221
0
        h2o_socket_notify_write(sock, on_notify_write);
1222
0
        return;
1223
0
    }
1224
0
#endif
1225
0
    do_emit_writereq(conn);
1226
0
    close_connection_if_necessary(conn);
1227
0
}
1228
1229
static size_t sz_min(size_t x, size_t y)
1230
0
{
1231
0
    return x < y ? x : y;
1232
0
}
1233
1234
static size_t calc_max_payload_size(struct st_h2o_http2client_stream_t *stream)
1235
0
{
1236
0
    ssize_t conn_max, stream_max;
1237
1238
0
    if ((conn_max = conn_get_buffer_window(stream->conn)) <= 0)
1239
0
        return 0;
1240
0
    if ((stream_max = h2o_http2_window_get_avail(&stream->output.window)) <= 0)
1241
0
        return 0;
1242
0
    return sz_min(sz_min(conn_max, stream_max), stream->conn->peer_settings.max_frame_size);
1243
0
}
1244
1245
static void stream_emit_pending_data(struct st_h2o_http2client_stream_t *stream)
1246
0
{
1247
0
    size_t max_payload_size = calc_max_payload_size(stream);
1248
0
    size_t payload_size = sz_min(max_payload_size, stream->output.buf->size);
1249
0
    int end_stream = stream->output.proceed_req == NULL && payload_size == stream->output.buf->size;
1250
0
    if (payload_size == 0 && !end_stream)
1251
0
        return;
1252
0
    char *dst = h2o_buffer_reserve(&stream->conn->output.buf, H2O_HTTP2_FRAME_HEADER_SIZE + payload_size).base;
1253
0
    h2o_http2_encode_frame_header((void *)dst, payload_size, H2O_HTTP2_FRAME_TYPE_DATA,
1254
0
                                  end_stream ? H2O_HTTP2_FRAME_FLAG_END_STREAM : 0, stream->stream_id);
1255
0
    h2o_memcpy(dst + H2O_HTTP2_FRAME_HEADER_SIZE, stream->output.buf->bytes, payload_size);
1256
0
    stream->conn->output.buf->size += H2O_HTTP2_FRAME_HEADER_SIZE + payload_size;
1257
0
    h2o_buffer_consume(&stream->output.buf, payload_size);
1258
1259
0
    h2o_http2_window_consume_window(&stream->conn->output.window, payload_size);
1260
0
    h2o_http2_window_consume_window(&stream->output.window, payload_size);
1261
0
}
1262
1263
static void do_emit_writereq(struct st_h2o_http2client_conn_t *conn)
1264
0
{
1265
0
    assert(conn->output.buf_in_flight == NULL);
1266
1267
    /* send DATA frames */
1268
0
    h2o_linklist_t pending;
1269
0
    h2o_linklist_init_anchor(&pending);
1270
0
    h2o_linklist_insert_list(&pending, &conn->output.sending_streams);
1271
0
    while (!h2o_linklist_is_empty(&pending)) {
1272
0
        struct st_h2o_http2client_stream_t *stream =
1273
0
            H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_stream_t, output.sending_link, pending.next);
1274
0
        h2o_linklist_unlink(&stream->output.sending_link);
1275
1276
0
        if (stream->output.buf != NULL && !stream->send_own_expect)
1277
0
            stream_emit_pending_data(stream);
1278
1279
0
        if (stream->output.buf == NULL || stream->output.buf->size == 0) {
1280
0
            h2o_linklist_insert(&conn->output.sent_streams, &stream->output.sending_link);
1281
0
        } else if (h2o_http2_window_get_avail(&stream->output.window) > 0 && !stream->send_own_expect) {
1282
            /* re-insert to tail so that streams would be sent round-robin */
1283
0
            h2o_linklist_insert(&conn->output.sending_streams, &stream->output.sending_link);
1284
0
        } else {
1285
            /* stream is flow-control-blocked; is not linked until WINDOW_UPDATE frame is received */
1286
0
        }
1287
0
    }
1288
1289
0
    if (conn->output.buf->size != 0) {
1290
        /* write and wait for completion */
1291
0
        h2o_iovec_t buf = {conn->output.buf->bytes, conn->output.buf->size};
1292
0
        h2o_socket_write(conn->super.sock, &buf, 1, on_write_complete);
1293
0
        conn->output.buf_in_flight = conn->output.buf;
1294
0
        h2o_buffer_init(&conn->output.buf, &h2o_http2_wbuf_buffer_prototype);
1295
0
        if (!h2o_timer_is_linked(&conn->io_timeout))
1296
0
            h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1297
0
    }
1298
0
}
1299
1300
static void emit_writereq(h2o_timer_t *entry)
1301
0
{
1302
0
    struct st_h2o_http2client_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http2client_conn_t, output.defer_timeout, entry);
1303
0
    do_emit_writereq(conn);
1304
0
}
1305
1306
static struct st_h2o_http2client_conn_t *create_connection(h2o_httpclient_ctx_t *ctx, h2o_socket_t *sock, h2o_url_t *origin_url,
1307
                                                           h2o_httpclient_connection_pool_t *connpool)
1308
0
{
1309
0
    struct st_h2o_http2client_conn_t *conn = h2o_mem_alloc(sizeof(*conn));
1310
1311
0
    memset(conn, 0, offsetof(struct st_h2o_http2client_conn_t, rst_streams_pool));
1312
0
    h2o_mem_init_pool(&conn->rst_streams_pool);
1313
1314
0
    conn->super.ctx = ctx;
1315
0
    conn->super.sock = sock;
1316
0
    conn->state = H2O_HTTP2CLIENT_CONN_STATE_OPEN;
1317
0
    conn->peer_settings = H2O_HTTP2_SETTINGS_DEFAULT;
1318
0
    conn->streams = kh_init(stream);
1319
0
    h2o_url_copy(NULL, &conn->super.origin_url, origin_url);
1320
0
    if (connpool != NULL)
1321
0
        h2o_linklist_insert(&connpool->http2.conns, &conn->super.link);
1322
0
    conn->io_timeout.cb = on_io_timeout;
1323
0
    conn->keepalive_timeout.cb = on_keepalive_timeout;
1324
1325
    /* output */
1326
0
    conn->output.header_table.hpack_capacity = H2O_HTTP2_SETTINGS_CLIENT_HEADER_TABLE_SIZE;
1327
0
    h2o_http2_window_init(&conn->output.window, conn->peer_settings.initial_window_size);
1328
0
    h2o_buffer_init(&conn->output.buf, &h2o_http2_wbuf_buffer_prototype);
1329
0
    conn->output.defer_timeout.cb = emit_writereq;
1330
0
    h2o_linklist_init_anchor(&conn->output.sending_streams);
1331
0
    h2o_linklist_init_anchor(&conn->output.sent_streams);
1332
1333
    /* input */
1334
0
    conn->input.header_table.hpack_capacity = conn->input.header_table.hpack_max_capacity =
1335
0
        H2O_HTTP2_SETTINGS_DEFAULT.header_table_size;
1336
0
    h2o_http2_window_init(&conn->input.window, H2O_HTTP2_SETTINGS_DEFAULT.initial_window_size);
1337
0
    conn->input.read_frame = expect_settings;
1338
1339
0
    return conn;
1340
0
}
1341
1342
static void send_client_preface(struct st_h2o_http2client_conn_t *conn, h2o_httpclient_ctx_t *ctx)
1343
0
{
1344
0
#define PREFIX                                                                                                                     \
1345
0
    "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"                                                                                             \
1346
0
    "\x00\x00\x12"     /* frame size */                                                                                            \
1347
0
    "\x04"             /* settings frame */                                                                                        \
1348
0
    "\x00"             /* no flags */                                                                                              \
1349
0
    "\x00\x00\x00\x00" /* stream id */                                                                                             \
1350
0
    "\x00\x02"         /* enable_push */                                                                                           \
1351
0
    "\x00\x00\x00\x00" /* 0 */                                                                                                     \
1352
0
    "\x00\x03"         /* max_concurrent_streams */                                                                                \
1353
0
    "\x00\x00\x00\x64" /* 100 */                                                                                                   \
1354
0
    "\x00\x04"         /* initial_window_size */
1355
0
    static const size_t len = sizeof(PREFIX) - 1 + 4;
1356
1357
0
    uint32_t initial_window_size = get_max_buffer_size(ctx);
1358
1359
0
    h2o_iovec_t vec = h2o_buffer_reserve(&conn->output.buf, len);
1360
0
    memcpy(vec.base, PREFIX, sizeof(PREFIX) - 1);
1361
1362
    /* encode max_buffer_size */
1363
0
    vec.base[len - 4] = (char)((initial_window_size >> 24) & 0xff);
1364
0
    vec.base[len - 3] = (char)((initial_window_size >> 16) & 0xff);
1365
0
    vec.base[len - 2] = (char)((initial_window_size >> 8) & 0xff);
1366
0
    vec.base[len - 1] = (char)(initial_window_size & 0xff);
1367
1368
0
    conn->output.buf->size += len;
1369
0
    request_write(conn);
1370
0
#undef PREFIX
1371
0
}
1372
1373
static void do_cancel(h2o_httpclient_t *_client)
1374
0
{
1375
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1376
0
    stream_send_error(stream->conn, stream->stream_id, H2O_HTTP2_ERROR_CANCEL);
1377
0
    close_stream(stream);
1378
0
}
1379
1380
static void do_get_conn_properties(h2o_httpclient_t *_client, h2o_httpclient_conn_properties_t *properties)
1381
0
{
1382
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1383
0
    h2o_httpclient_set_conn_properties_of_socket(stream->conn->super.sock, properties);
1384
0
}
1385
1386
static void do_update_window(h2o_httpclient_t *_client)
1387
0
{
1388
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1389
0
    size_t max = get_max_buffer_size(stream->super.ctx);
1390
0
    size_t bufsize = stream->input.body->size;
1391
0
    assert(bufsize <= max);
1392
0
    enqueue_window_update(stream->conn, stream->stream_id, &stream->input.window, max - bufsize);
1393
0
}
1394
1395
static int do_write_req(h2o_httpclient_t *_client, h2o_iovec_t chunk, int is_end_stream)
1396
0
{
1397
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1398
0
    assert(stream->output.proceed_req != NULL);
1399
0
    assert(!h2o_linklist_is_linked(&stream->output.sending_link));
1400
1401
0
    if (is_end_stream)
1402
0
        stream->output.proceed_req = NULL;
1403
1404
0
    if (stream->output.buf == NULL)
1405
0
        h2o_buffer_init(&stream->output.buf, &h2o_socket_buffer_prototype);
1406
1407
0
    if (chunk.len != 0)
1408
0
        h2o_buffer_append(&stream->output.buf, chunk.base, chunk.len);
1409
1410
0
    h2o_linklist_insert(&stream->conn->output.sending_streams, &stream->output.sending_link);
1411
0
    request_write(stream->conn);
1412
1413
0
    return 0;
1414
0
}
1415
1416
static void setup_stream(struct st_h2o_http2client_stream_t *stream)
1417
0
{
1418
0
    memset(&stream->conn, 0, sizeof(*stream) - offsetof(struct st_h2o_http2client_stream_t, conn));
1419
1420
0
    stream->super._timeout.cb = on_stream_timeout;
1421
0
    h2o_http2_window_init(&stream->input.window, get_max_buffer_size(stream->super.ctx));
1422
0
    h2o_buffer_init(&stream->input.body, &h2o_socket_buffer_prototype);
1423
0
    stream->input.remaining_content_length = SIZE_MAX;
1424
0
    stream->input.message_body_forbidden = 0;
1425
1426
0
    stream->super.buf = &stream->input.body;
1427
0
    stream->super.cancel = do_cancel;
1428
0
    stream->super.get_conn_properties = do_get_conn_properties;
1429
0
    stream->super.update_window = do_update_window;
1430
0
    stream->super.write_req = do_write_req;
1431
0
}
1432
1433
void h2o_httpclient__h2_on_connect(h2o_httpclient_t *_client, h2o_socket_t *sock, h2o_url_t *origin)
1434
0
{
1435
0
    struct st_h2o_http2client_stream_t *stream = (void *)_client;
1436
1437
0
    assert(!h2o_timer_is_linked(&stream->super._timeout));
1438
1439
0
    struct st_h2o_http2client_conn_t *conn = sock->data;
1440
0
    if (conn == NULL) {
1441
0
        conn = create_connection(stream->super.ctx, sock, origin, stream->super.connpool);
1442
0
        sock->data = conn;
1443
        /* send preface, settings, and connection-level window update */
1444
0
        send_client_preface(conn, stream->super.ctx);
1445
0
        h2o_socket_read_start(conn->super.sock, on_read);
1446
0
    }
1447
1448
0
    setup_stream(stream);
1449
1450
0
    if (!h2o_timer_is_linked(&conn->io_timeout))
1451
0
        h2o_timer_link(conn->super.ctx->loop, conn->super.ctx->io_timeout, &conn->io_timeout);
1452
0
    on_connection_ready(stream, conn);
1453
0
}
1454
1455
const size_t h2o_httpclient__h2_size = sizeof(struct st_h2o_http2client_stream_t);