Coverage Report

Created: 2026-10-28 06:44

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