Coverage Report

Created: 2026-07-16 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/h2o/lib/http1.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2014-2016 DeNA Co., Ltd., Kazuho Oku, Shota Fukumori,
3
 *                         Fastly, Inc.
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to
7
 * deal in the Software without restriction, including without limitation the
8
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
 * sell copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be included in
13
 * all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21
 * IN THE SOFTWARE.
22
 */
23
#include <inttypes.h>
24
#include <stddef.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include "picohttpparser.h"
28
#include "h2o.h"
29
#include "h2o/http1.h"
30
#include "h2o/http2.h"
31
#include "./probes_.h"
32
33
enum enum_h2o_http1_ostream_state {
34
    OSTREAM_STATE_HEAD,
35
    OSTREAM_STATE_BODY,
36
    OSTREAM_STATE_DONE,
37
};
38
39
struct st_h2o_http1_finalostream_t {
40
    h2o_ostream_t super;
41
    enum enum_h2o_http1_ostream_state state;
42
    char *chunked_buf; /* buffer used for chunked-encoding (NULL unless chunked encoding is used) */
43
    struct {
44
        /**
45
         * if `h2o_socket_write` is currently writing an informational response
46
         */
47
        unsigned write_inflight : 1;
48
        /**
49
         * buffer used to store informational responses to be sent, when write of an informational response is inflight
50
         */
51
        h2o_iovec_vector_t pending;
52
        /**
53
         * buffer used to delay the execution of `finalostream_send`, when write of an informational respnose is inflight;
54
         * availability is indicated by `inbufs != NULL`
55
         */
56
        struct {
57
            h2o_sendvec_t *inbufs;
58
            size_t inbufcnt;
59
            h2o_send_state_t send_state;
60
        } pending_final;
61
    } informational;
62
};
63
64
struct st_h2o_http1_conn_t {
65
    h2o_conn_t super;
66
    h2o_socket_t *sock;
67
    h2o_timer_t _timeout_entry;
68
    h2o_timer_t _io_timeout_entry;
69
    uint64_t _req_index;
70
    size_t _prevreqlen;
71
    size_t _unconsumed_request_size;
72
    struct st_h2o_http1_req_entity_reader *_req_entity_reader;
73
    struct st_h2o_http1_finalostream_t _ostr_final;
74
    struct {
75
        void *data;
76
        h2o_http1_upgrade_cb cb;
77
    } upgrade;
78
    /**
79
     * the request body buffer
80
     */
81
    h2o_buffer_t *req_body;
82
    /**
83
     * the HTTP request / response (intentionally placed at the last, since it is a large structure and has it's own ctor)
84
     */
85
    h2o_req_t req;
86
};
87
88
struct st_h2o_http1_req_entity_reader {
89
    void (*handle_incoming_entity)(struct st_h2o_http1_conn_t *conn);
90
};
91
92
struct st_h2o_http1_content_length_entity_reader {
93
    struct st_h2o_http1_req_entity_reader super;
94
    size_t content_length;
95
};
96
97
struct st_h2o_http1_chunked_entity_reader {
98
    struct st_h2o_http1_req_entity_reader super;
99
    struct phr_chunked_decoder decoder;
100
};
101
102
static void finalostream_send(h2o_ostream_t *_self, h2o_req_t *req, h2o_sendvec_t *inbufs, size_t inbufcnt, h2o_send_state_t state);
103
static void finalostream_send_informational(h2o_ostream_t *_self, h2o_req_t *req);
104
static void reqread_on_read(h2o_socket_t *sock, const char *err);
105
static void reqread_on_timeout(h2o_timer_t *entry);
106
static void req_io_on_timeout(h2o_timer_t *entry);
107
static void reqread_start(struct st_h2o_http1_conn_t *conn);
108
static int foreach_request(h2o_conn_t *_conn, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata);
109
110
static void init_request(struct st_h2o_http1_conn_t *conn)
111
17.4k
{
112
17.4k
    if (conn->_req_index != 0) {
113
6.91k
        if (conn->req_body != NULL)
114
1.01k
            h2o_buffer_dispose(&conn->req_body);
115
6.91k
        h2o_dispose_request(&conn->req);
116
6.91k
        if (conn->_unconsumed_request_size)
117
5.89k
            h2o_buffer_consume(&conn->sock->input, conn->_unconsumed_request_size);
118
6.91k
    }
119
17.4k
    assert(conn->req_body == NULL);
120
17.4k
    h2o_init_request(&conn->req, &conn->super, NULL);
121
122
17.4k
    ++conn->_req_index;
123
17.4k
    conn->req._ostr_top = &conn->_ostr_final.super;
124
125
17.4k
    conn->_ostr_final = (struct st_h2o_http1_finalostream_t){{
126
17.4k
        NULL,              /* next */
127
17.4k
        finalostream_send, /* do_send */
128
17.4k
        NULL,              /* stop */
129
17.4k
        conn->super.ctx->globalconf->send_informational_mode == H2O_SEND_INFORMATIONAL_MODE_ALL ? finalostream_send_informational
130
17.4k
                                                                                                : NULL, /* send_informational */
131
17.4k
    }};
132
17.4k
}
133
134
static void close_connection(struct st_h2o_http1_conn_t *conn, int close_socket)
135
10.5k
{
136
10.5k
    if (conn->sock != NULL) {
137
5.91k
        H2O_PROBE_CONN0(H1_CLOSE, &conn->super);
138
5.91k
        H2O_LOG_CONN(h1_close, &conn->super, {});
139
5.91k
    }
140
10.5k
    h2o_timer_unlink(&conn->_timeout_entry);
141
10.5k
    h2o_timer_unlink(&conn->_io_timeout_entry);
142
10.5k
    if (conn->req_body != NULL)
143
729
        h2o_buffer_dispose(&conn->req_body);
144
10.5k
    h2o_dispose_request(&conn->req);
145
10.5k
    if (conn->sock != NULL && close_socket)
146
5.80k
        h2o_socket_close(conn->sock);
147
10.5k
    h2o_destroy_connection(&conn->super);
148
10.5k
}
149
150
static void cleanup_connection(struct st_h2o_http1_conn_t *conn)
151
9.94k
{
152
9.94k
    if (!conn->req.http1_is_persistent) {
153
        /* TODO use lingering close */
154
3.02k
        close_connection(conn, 1);
155
3.02k
        return;
156
3.02k
    }
157
158
9.94k
    assert(conn->req.proceed_req == NULL);
159
6.91k
    assert(conn->_req_entity_reader == NULL);
160
161
    /* handle next request */
162
6.91k
    init_request(conn);
163
6.91k
    conn->req.write_req.cb = NULL;
164
6.91k
    conn->req.write_req.ctx = NULL;
165
6.91k
    conn->req.proceed_req = NULL;
166
6.91k
    conn->_prevreqlen = 0;
167
6.91k
    conn->_unconsumed_request_size = 0;
168
169
6.91k
    if (conn->sock->input->size == 0)
170
2.02k
        h2o_conn_set_state(&conn->super, H2O_CONN_STATE_IDLE);
171
172
6.91k
    reqread_start(conn);
173
6.91k
}
174
175
/**
176
 * timer is activated if cb != NULL, disactivated otherwise
177
 */
178
static void set_req_timeout(struct st_h2o_http1_conn_t *conn, uint64_t timeout, h2o_timer_cb cb)
179
29.1k
{
180
29.1k
    if (conn->req.is_tunnel_req)
181
117
        cb = NULL;
182
29.1k
    if (conn->_timeout_entry.cb != NULL)
183
10.2k
        h2o_timer_unlink(&conn->_timeout_entry);
184
29.1k
    conn->_timeout_entry.cb = cb;
185
29.1k
    if (cb != NULL)
186
18.8k
        h2o_timer_link(conn->super.ctx->loop, timeout, &conn->_timeout_entry);
187
29.1k
}
188
189
static void set_req_io_timeout(struct st_h2o_http1_conn_t *conn, uint64_t timeout, h2o_timer_cb cb)
190
65.7k
{
191
65.7k
    if (conn->req.is_tunnel_req)
192
265
        cb = NULL;
193
65.7k
    if (conn->_io_timeout_entry.cb != NULL)
194
44.9k
        h2o_timer_unlink(&conn->_io_timeout_entry);
195
65.7k
    conn->_io_timeout_entry.cb = cb;
196
65.7k
    if (cb != NULL)
197
55.2k
        h2o_timer_link(conn->super.ctx->loop, timeout, &conn->_io_timeout_entry);
198
65.7k
}
199
200
static void clear_timeouts(struct st_h2o_http1_conn_t *conn)
201
10.2k
{
202
10.2k
    set_req_timeout(conn, 0, NULL);
203
10.2k
    set_req_io_timeout(conn, 0, NULL);
204
10.2k
}
205
206
static void entity_read_do_send_error(struct st_h2o_http1_conn_t *conn, int status, size_t status_error_index, const char *reason,
207
                                      const char *body)
208
266
{
209
266
    conn->req.proceed_req = NULL;
210
266
    conn->_req_entity_reader = NULL;
211
266
    clear_timeouts(conn);
212
266
    h2o_socket_read_stop(conn->sock);
213
    /* FIXME We should check if `h2o_proceed_request` has been called, rather than trying to guess if we have (I'm unsure if the
214
     * contract is for h2o_req_t::_generator to become non-NULL immediately after `h2o_proceed_request` is being called). */
215
266
    if (conn->req._generator == NULL && conn->_ostr_final.state == OSTREAM_STATE_HEAD) {
216
238
        conn->super.ctx->emitted_error_status[status_error_index]++;
217
238
        h2o_send_error_generic(&conn->req, status, reason, body, H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION);
218
238
    } else {
219
28
        conn->req.http1_is_persistent = 0;
220
28
        if (conn->_ostr_final.state == OSTREAM_STATE_DONE)
221
27
            cleanup_connection(conn);
222
28
    }
223
266
}
224
225
#define DECL_ENTITY_READ_SEND_ERROR_XXX(status_)                                                                                   \
226
    static void entity_read_send_error_##status_(struct st_h2o_http1_conn_t *conn, const char *reason, const char *body)           \
227
266
    {                                                                                                                              \
228
266
        entity_read_do_send_error(conn, status_, H2O_STATUS_ERROR_##status_, reason, body);                                        \
229
266
    }
http1.c:entity_read_send_error_400
Line
Count
Source
227
168
    {                                                                                                                              \
228
168
        entity_read_do_send_error(conn, status_, H2O_STATUS_ERROR_##status_, reason, body);                                        \
229
168
    }
http1.c:entity_read_send_error_502
Line
Count
Source
227
27
    {                                                                                                                              \
228
27
        entity_read_do_send_error(conn, status_, H2O_STATUS_ERROR_##status_, reason, body);                                        \
229
27
    }
http1.c:entity_read_send_error_413
Line
Count
Source
227
71
    {                                                                                                                              \
228
71
        entity_read_do_send_error(conn, status_, H2O_STATUS_ERROR_##status_, reason, body);                                        \
229
71
    }
230
231
DECL_ENTITY_READ_SEND_ERROR_XXX(400)
232
DECL_ENTITY_READ_SEND_ERROR_XXX(413)
233
DECL_ENTITY_READ_SEND_ERROR_XXX(502)
234
235
static void handle_one_body_fragment(struct st_h2o_http1_conn_t *conn, size_t fragment_size, size_t extra_bytes, int complete)
236
2.95k
{
237
2.95k
    if (fragment_size == 0 && !complete) {
238
500
        h2o_buffer_consume(&conn->sock->input, extra_bytes);
239
500
        return;
240
500
    }
241
242
2.45k
    clear_timeouts(conn);
243
2.45k
    h2o_socket_read_stop(conn->sock);
244
245
    /* move data being read to req_body */
246
2.45k
    if (!h2o_buffer_try_append(&conn->req_body, conn->sock->input->bytes, fragment_size)) {
247
0
        entity_read_send_error_502(conn, "Bad Gateway", "Bad Gateway");
248
0
        return;
249
0
    }
250
2.45k
    h2o_buffer_consume(&conn->sock->input, fragment_size + extra_bytes);
251
2.45k
    conn->req.req_body_bytes_received += fragment_size;
252
253
    /* invoke action */
254
2.45k
    conn->req.entity = h2o_iovec_init(conn->req_body->bytes, conn->req_body->size);
255
2.45k
    if (conn->req.write_req.cb(conn->req.write_req.ctx, complete) != 0) {
256
0
        entity_read_send_error_502(conn, "Bad Gateway", "Bad Gateway");
257
0
        return;
258
0
    }
259
2.45k
    if (complete) {
260
1.04k
        conn->req.proceed_req = NULL;
261
1.04k
        conn->_req_entity_reader = NULL;
262
1.04k
        if (conn->_ostr_final.state == OSTREAM_STATE_DONE) {
263
243
            cleanup_connection(conn);
264
243
        }
265
1.04k
    }
266
2.45k
}
267
268
static void handle_chunked_entity_read(struct st_h2o_http1_conn_t *conn)
269
1.36k
{
270
1.36k
    struct st_h2o_http1_chunked_entity_reader *reader = (void *)conn->_req_entity_reader;
271
1.36k
    size_t bufsz;
272
1.36k
    ssize_t ret;
273
274
    /* decode the incoming data */
275
1.36k
    if ((bufsz = conn->sock->input->size) == 0)
276
65
        return;
277
1.29k
    ret = phr_decode_chunked(&reader->decoder, conn->sock->input->bytes, &bufsz);
278
1.29k
    if (ret != -1 && bufsz + conn->req.req_body_bytes_received >= conn->super.ctx->globalconf->max_request_entity_size) {
279
0
        entity_read_send_error_413(conn, "Request Entity Too Large", "request entity is too large");
280
0
        return;
281
0
    }
282
1.29k
    if (ret < 0) {
283
1.11k
        if (ret == -2) {
284
            /* incomplete */
285
1.01k
            handle_one_body_fragment(conn, bufsz, conn->sock->input->size - bufsz, 0);
286
1.01k
        } else {
287
            /* error */
288
100
            entity_read_send_error_400(conn, "Invalid Request", "broken chunked-encoding");
289
100
        }
290
1.11k
    } else {
291
        /* complete */
292
180
        assert(bufsz + ret <= conn->sock->input->size);
293
180
        conn->sock->input->size = bufsz + ret;
294
180
        handle_one_body_fragment(conn, bufsz, 0, 1);
295
180
    }
296
1.29k
}
297
298
static int create_chunked_entity_reader(struct st_h2o_http1_conn_t *conn)
299
619
{
300
619
    struct st_h2o_http1_chunked_entity_reader *reader = h2o_mem_alloc_pool(&conn->req.pool, *reader, 1);
301
619
    conn->_req_entity_reader = &reader->super;
302
303
619
    reader->super.handle_incoming_entity = handle_chunked_entity_read;
304
619
    memset(&reader->decoder, 0, sizeof(reader->decoder));
305
619
    reader->decoder.consume_trailer = 1;
306
307
619
    return 0;
308
619
}
309
310
static void handle_content_length_entity_read(struct st_h2o_http1_conn_t *conn)
311
1.85k
{
312
1.85k
    int complete = 0;
313
1.85k
    struct st_h2o_http1_content_length_entity_reader *reader = (void *)conn->_req_entity_reader;
314
1.85k
    size_t length = conn->sock->input->size;
315
316
1.85k
    if (conn->req.req_body_bytes_received + conn->sock->input->size >= reader->content_length) {
317
863
        complete = 1;
318
863
        length = reader->content_length - conn->req.req_body_bytes_received;
319
863
    }
320
1.85k
    if (!complete && length == 0)
321
93
        return;
322
323
1.76k
    handle_one_body_fragment(conn, length, 0, complete);
324
1.76k
}
325
326
static int create_content_length_entity_reader(struct st_h2o_http1_conn_t *conn, size_t content_length)
327
1.12k
{
328
1.12k
    struct st_h2o_http1_content_length_entity_reader *reader = h2o_mem_alloc_pool(&conn->req.pool, *reader, 1);
329
1.12k
    conn->_req_entity_reader = &reader->super;
330
331
1.12k
    reader->super.handle_incoming_entity = handle_content_length_entity_read;
332
1.12k
    reader->content_length = content_length;
333
334
1.12k
    return 0;
335
1.12k
}
336
337
static int create_entity_reader(struct st_h2o_http1_conn_t *conn, const struct phr_header *entity_header)
338
1.83k
{
339
    /* strlen("content-length") is unequal to sizeof("transfer-encoding"), and thus checking the length only is sufficient */
340
1.83k
    if (entity_header->name_len == sizeof("transfer-encoding") - 1) {
341
        /* transfer-encoding */
342
650
        if (!h2o_lcstris(entity_header->value, entity_header->value_len, H2O_STRLIT("chunked"))) {
343
31
            entity_read_send_error_400(conn, "Invalid Request", "unknown transfer-encoding");
344
31
            return -1;
345
31
        }
346
619
        return create_chunked_entity_reader(conn);
347
1.18k
    } else {
348
        /* content-length */
349
1.18k
        size_t content_length = h2o_strtosize(entity_header->value, entity_header->value_len);
350
1.18k
        if (content_length == SIZE_MAX) {
351
37
            entity_read_send_error_400(conn, "Invalid Request", "broken content-length header");
352
37
            return -1;
353
37
        }
354
1.14k
        if (content_length > conn->super.ctx->globalconf->max_request_entity_size) {
355
71
            entity_read_send_error_413(conn, "Request Entity Too Large", "request entity is too large");
356
71
            return -1;
357
71
        }
358
1.07k
        conn->req.content_length = content_length;
359
1.07k
        return create_content_length_entity_reader(conn, (size_t)content_length);
360
1.14k
    }
361
    /* failed */
362
0
    return -1;
363
1.83k
}
364
365
static const char *init_headers(h2o_mem_pool_t *pool, h2o_headers_t *headers, const struct phr_header *src, size_t len,
366
                                h2o_iovec_t *connection, h2o_iovec_t *host, h2o_iovec_t *upgrade, ssize_t *expect_header_index,
367
                                ssize_t *entity_header_index)
368
9.39k
{
369
9.39k
    *entity_header_index = -1;
370
9.39k
    *expect_header_index = -1;
371
372
9.39k
    assert(headers->size == 0);
373
374
    /* setup */
375
9.39k
    if (len != 0) {
376
6.38k
        size_t i;
377
6.38k
        h2o_vector_reserve(pool, headers, len);
378
60.2k
        for (i = 0; i != len; ++i) {
379
53.8k
            const h2o_token_t *name_token;
380
            /* reject multiline header */
381
53.8k
            if (src[i].name_len == 0)
382
35
                return "line folding of header fields is not supported";
383
53.8k
            char orig_case[src[i].name_len];
384
            /* preserve the original case */
385
53.8k
            memcpy(orig_case, src[i].name, src[i].name_len);
386
            /* convert to lower-case in-place */
387
53.8k
            h2o_strtolower((char *)src[i].name, src[i].name_len);
388
53.8k
            if ((name_token = h2o_lookup_token(src[i].name, src[i].name_len)) != NULL) {
389
21.2k
                if (name_token->flags.is_init_header_special) {
390
4.35k
                    if (name_token == H2O_TOKEN_HOST) {
391
862
                        host->base = (char *)src[i].value;
392
862
                        host->len = src[i].value_len;
393
3.49k
                    } else if (name_token == H2O_TOKEN_CONTENT_LENGTH) {
394
1.31k
                        if (*entity_header_index == -1)
395
1.18k
                            *entity_header_index = i;
396
2.18k
                    } else if (name_token == H2O_TOKEN_TRANSFER_ENCODING) {
397
725
                        *entity_header_index = i;
398
1.45k
                    } else if (name_token == H2O_TOKEN_EXPECT) {
399
328
                        *expect_header_index = i;
400
1.12k
                    } else if (name_token == H2O_TOKEN_UPGRADE) {
401
1.12k
                        upgrade->base = (char *)src[i].value;
402
1.12k
                        upgrade->len = src[i].value_len;
403
1.12k
                    } else {
404
0
                        assert(!"logic flaw");
405
0
                    }
406
16.8k
                } else {
407
16.8k
                    h2o_add_header(pool, headers, name_token, orig_case, src[i].value, src[i].value_len);
408
16.8k
                    if (name_token == H2O_TOKEN_CONNECTION)
409
1.46k
                        *connection = headers->entries[headers->size - 1].value;
410
16.8k
                }
411
32.6k
            } else {
412
32.6k
                h2o_add_header_by_str(pool, headers, src[i].name, src[i].name_len, 0, orig_case, src[i].value, src[i].value_len);
413
32.6k
            }
414
53.8k
        }
415
6.38k
    }
416
417
9.35k
    return NULL;
418
9.39k
}
419
420
static int upgrade_is_h2(h2o_iovec_t upgrade)
421
673
{
422
673
    if (h2o_lcstris(upgrade.base, upgrade.len, H2O_STRLIT("h2c")) || h2o_lcstris(upgrade.base, upgrade.len, H2O_STRLIT("h2c-14")) ||
423
89
        h2o_lcstris(upgrade.base, upgrade.len, H2O_STRLIT("h2c-16")))
424
618
        return 1;
425
55
    return 0;
426
673
}
427
428
static const char fixup_request_is_h2_upgrade[] = "fixup h2 upgrade";
429
430
static const char *fixup_request(struct st_h2o_http1_conn_t *conn, struct phr_header *headers, size_t num_headers,
431
                                 int minor_version, ssize_t *expect_header_index, ssize_t *entity_header_index)
432
9.39k
{
433
9.39k
    h2o_iovec_t connection = {NULL, 0}, host = {NULL, 0}, upgrade = {NULL, 0};
434
9.39k
    enum { METHOD_NORMAL, METHOD_CONNECT, METHOD_CONNECT_UDP } method_type;
435
9.39k
    const char *ret;
436
437
9.39k
    conn->req.input.scheme = conn->sock->ssl != NULL ? &H2O_URL_SCHEME_HTTPS : &H2O_URL_SCHEME_HTTP;
438
9.39k
    conn->req.version = 0x100 | (minor_version != 0);
439
440
    /* RFC 7231 6.2: a server MUST NOT send a 1xx response to an HTTP/1.0 client */
441
9.39k
    if (conn->req.version < 0x101)
442
2.05k
        conn->_ostr_final.super.send_informational = NULL;
443
444
9.39k
    if (h2o_memis(conn->req.input.method.base, conn->req.input.method.len, H2O_STRLIT("CONNECT"))) {
445
92
        method_type = METHOD_CONNECT;
446
9.30k
    } else if (h2o_memis(conn->req.input.method.base, conn->req.input.method.len, H2O_STRLIT("CONNECT-UDP"))) {
447
1
        method_type = METHOD_CONNECT_UDP;
448
9.29k
    } else {
449
9.29k
        method_type = METHOD_NORMAL;
450
9.29k
    }
451
452
    /* init headers */
453
9.39k
    if ((ret = init_headers(&conn->req.pool, &conn->req.headers, headers, num_headers, &connection, &host, &upgrade,
454
9.39k
                            expect_header_index, entity_header_index)) != NULL)
455
35
        return ret;
456
457
    /* copy the values to pool, since the buffer pointed by the headers may get realloced */
458
9.35k
    if (*entity_header_index != -1 || method_type != METHOD_NORMAL || upgrade.base != NULL) {
459
2.73k
        size_t i;
460
2.73k
        conn->req.input.method = h2o_strdup(&conn->req.pool, conn->req.input.method.base, conn->req.input.method.len);
461
2.73k
        conn->req.input.path = h2o_strdup(&conn->req.pool, conn->req.input.path.base, conn->req.input.path.len);
462
17.6k
        for (i = 0; i != conn->req.headers.size; ++i) {
463
14.8k
            h2o_header_t *header = conn->req.headers.entries + i;
464
14.8k
            if (!h2o_iovec_is_token(header->name)) {
465
9.82k
                *header->name = h2o_strdup(&conn->req.pool, header->name->base, header->name->len);
466
9.82k
            }
467
14.8k
            header->value = h2o_strdup(&conn->req.pool, header->value.base, header->value.len);
468
14.8k
        }
469
2.73k
        if (host.base != NULL)
470
247
            host = h2o_strdup(&conn->req.pool, host.base, host.len);
471
2.73k
        if (upgrade.base != NULL)
472
871
            upgrade = h2o_strdup(&conn->req.pool, upgrade.base, upgrade.len);
473
2.73k
    }
474
475
9.35k
    if (method_type == METHOD_CONNECT) {
476
        /* CONNECT method, validate, setting the target host in `req->input.authority`. Path becomes empty. */
477
92
        if (conn->req.version < 0x101 || conn->req.input.path.len == 0 ||
478
73
            (host.base != NULL && !h2o_memis(conn->req.input.path.base, conn->req.input.path.len, host.base, host.len)) ||
479
18
            *entity_header_index != -1)
480
75
            return "invalid request";
481
17
        conn->req.input.authority = conn->req.input.path;
482
17
        conn->req.input.path = h2o_iovec_init(NULL, 0);
483
17
        conn->req.is_tunnel_req = 1;
484
9.26k
    } else {
485
        /* request line is in ordinary form, path might contain absolute URL; if so, convert it */
486
9.26k
        if (conn->req.input.path.len != 0 && conn->req.input.path.base[0] != '/') {
487
7.61k
            h2o_url_t url;
488
7.61k
            if (h2o_url_parse(&conn->req.pool, conn->req.input.path.base, conn->req.input.path.len, &url) == 0) {
489
339
                conn->req.input.scheme = url.scheme;
490
339
                conn->req.input.path = url.path;
491
339
                host = url.authority; /* authority part of the absolute form overrides the host header field (RFC 7230 S5.4) */
492
339
            }
493
7.61k
        }
494
        /* move host header to req->authority */
495
9.26k
        if (host.base != NULL)
496
738
            conn->req.input.authority = host;
497
        /* each protocol implementation validates masque */
498
9.26k
        if (!h2o_req_validate_pseudo_headers(&conn->req))
499
2
            return "invalid request";
500
        /* special handling for CONNECT-UDP, else it is an ordinary request */
501
9.26k
        if (method_type == METHOD_CONNECT_UDP) {
502
0
            conn->req.is_tunnel_req = 1;
503
9.26k
        } else {
504
            /* handle Connection and Upgrade header fields */
505
9.26k
            if (connection.base != NULL) {
506
                /* TODO contains_token function can be faster */
507
1.12k
                if (h2o_contains_token(connection.base, connection.len, H2O_STRLIT("keep-alive"), ',')) {
508
763
                    conn->req.http1_is_persistent = 1;
509
763
                }
510
                /* Upgrade is respected only for requests without bodies. Use of upgrade on a request with body is unsupported,
511
                 * because we reuse the entity reader for reading the body and the tunnelled data. */
512
1.12k
                if (upgrade.base != NULL && h2o_contains_token(connection.base, connection.len, H2O_STRLIT("upgrade"), ',') &&
513
684
                    *entity_header_index == -1) {
514
                    /* early return if upgrading to h2 */
515
673
                    if (upgrade_is_h2(upgrade)) {
516
618
                        if (conn->sock->ssl == NULL && conn->super.ctx->globalconf->http1.upgrade_to_http2)
517
618
                            return fixup_request_is_h2_upgrade;
518
618
                    } else {
519
55
                        conn->req.upgrade = upgrade;
520
55
                        conn->req.is_tunnel_req = 1;
521
55
                        conn->req.http1_is_persistent = 0;
522
55
                    }
523
673
                }
524
8.14k
            } else if (conn->req.version >= 0x101) {
525
                /* defaults to keep-alive if >= HTTP/1.1 */
526
6.67k
                conn->req.http1_is_persistent = 1;
527
6.67k
            }
528
            /* disable keep-alive if shutdown is requested */
529
8.64k
            if (conn->req.http1_is_persistent && conn->super.ctx->shutdown_requested)
530
0
                conn->req.http1_is_persistent = 0;
531
8.64k
        }
532
9.26k
    }
533
534
8.66k
    return NULL;
535
9.35k
}
536
537
static void on_continue_sent(h2o_socket_t *sock, const char *err)
538
0
{
539
0
    struct st_h2o_http1_conn_t *conn = sock->data;
540
541
0
    if (err != NULL) {
542
0
        close_connection(conn, 1);
543
0
        return;
544
0
    }
545
546
0
    h2o_socket_read_start(sock, reqread_on_read);
547
0
    conn->_req_entity_reader->handle_incoming_entity(conn);
548
0
}
549
550
static int contains_crlf_only(const char *s, size_t len)
551
192
{
552
347
    for (; len != 0; ++s, --len)
553
317
        if (!(*s == '\r' || *s == '\n'))
554
162
            return 0;
555
30
    return 1;
556
192
}
557
558
static void send_bad_request(struct st_h2o_http1_conn_t *conn, const char *body)
559
1.28k
{
560
1.28k
    h2o_socket_read_stop(conn->sock);
561
1.28k
    h2o_send_error_400(&conn->req, "Bad Request", body, H2O_SEND_ERROR_BROKEN_REQUEST | H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION);
562
1.28k
}
563
564
static void resume_request_read(struct st_h2o_http1_conn_t *conn)
565
1.36k
{
566
1.36k
    set_req_timeout(conn, conn->super.ctx->globalconf->http1.req_timeout, reqread_on_timeout);
567
1.36k
    set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
568
1.36k
    h2o_socket_read_start(conn->sock, reqread_on_read);
569
1.36k
}
570
571
static void proceed_request(h2o_req_t *req, const char *errstr)
572
751
{
573
751
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, req);
574
575
751
    if (errstr != NULL) {
576
27
        entity_read_send_error_502(conn, "Bad Gateway", "Bad Gateway");
577
27
        return;
578
27
    }
579
580
751
    assert(conn->req.entity.len == conn->req_body->size);
581
724
    h2o_buffer_consume(&conn->req_body, conn->req_body->size);
582
583
724
    resume_request_read(conn);
584
724
}
585
586
static int write_req_non_streaming(void *_req, int is_end_stream)
587
1.11k
{
588
1.11k
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, _req);
589
590
1.11k
    if (is_end_stream) {
591
472
        conn->req.proceed_req = NULL;
592
472
        h2o_process_request(&conn->req);
593
638
    } else {
594
638
        resume_request_read(conn);
595
638
    }
596
1.11k
    return 0;
597
1.11k
}
598
599
static int write_req_first(void *_req, int is_end_stream)
600
1.39k
{
601
1.39k
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, _req);
602
603
    /* if possible, switch to streaming request body mode */
604
1.39k
    if (!is_end_stream && h2o_req_can_stream_request(&conn->req)) {
605
705
        conn->req.write_req.cb = NULL; /* will be set to something before `proceed_req` is being invoked */
606
705
        conn->req.proceed_req = proceed_request;
607
705
        h2o_process_request(&conn->req);
608
705
        return 0;
609
705
    }
610
611
692
    conn->req.write_req.cb = write_req_non_streaming;
612
692
    return write_req_non_streaming(&conn->req, is_end_stream);
613
1.39k
}
614
615
static int write_req_connect_first(void *_req, int is_end_stream)
616
31
{
617
31
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, _req);
618
619
31
    conn->req.write_req.cb = NULL; /* will not be called again until proceed_req is called by the generator */
620
31
    if (is_end_stream)
621
0
        conn->req.proceed_req = NULL;
622
623
31
    return 0;
624
31
}
625
626
static void handle_incoming_request(struct st_h2o_http1_conn_t *conn)
627
17.5k
{
628
17.5k
    size_t inreqlen = conn->sock->input->size < H2O_MAX_REQLEN ? conn->sock->input->size : H2O_MAX_REQLEN;
629
17.5k
    int reqlen, minor_version;
630
17.5k
    struct phr_header headers[H2O_MAX_HEADERS];
631
17.5k
    size_t num_headers = H2O_MAX_HEADERS;
632
633
17.5k
    if (conn->sock->input->size != 0)
634
17.5k
        h2o_conn_set_state(&conn->super, H2O_CONN_STATE_ACTIVE);
635
636
    /* need to set request_begin_at here for keep-alive connection */
637
17.5k
    if (h2o_timeval_is_null(&conn->req.timestamps.request_begin_at))
638
15.7k
        conn->req.timestamps.request_begin_at = h2o_gettimeofday(conn->super.ctx->loop);
639
640
17.5k
    reqlen = phr_parse_request(conn->sock->input->bytes, inreqlen, (const char **)&conn->req.input.method.base,
641
17.5k
                               &conn->req.input.method.len, (const char **)&conn->req.input.path.base, &conn->req.input.path.len,
642
17.5k
                               &minor_version, headers, &num_headers, conn->_prevreqlen);
643
17.5k
    conn->_prevreqlen = inreqlen;
644
645
    /* handle incomplete or broken HTTP headers */
646
17.5k
    switch (reqlen) {
647
2.26k
    case -2: /* incomplete */
648
2.26k
        if (inreqlen == H2O_MAX_REQLEN) {
649
0
            send_bad_request(conn, "Bad Request");
650
0
        }
651
2.26k
        return;
652
5.84k
    case -1: // error
653
        /* upgrade to HTTP/2 if the request starts with: PRI * HTTP/2 */
654
5.84k
        if (conn->super.ctx->globalconf->http1.upgrade_to_http2) {
655
            /* should check up to the first octet that phr_parse_request returns an error */
656
5.84k
            static const h2o_iovec_t HTTP2_SIG = {H2O_STRLIT("PRI * HTTP/2")};
657
5.84k
            if (conn->sock->input->size >= HTTP2_SIG.len && memcmp(conn->sock->input->bytes, HTTP2_SIG.base, HTTP2_SIG.len) == 0) {
658
4.64k
                h2o_accept_ctx_t accept_ctx = {conn->super.ctx, conn->super.hosts};
659
4.64k
                h2o_socket_t *sock = conn->sock;
660
4.64k
                struct timeval connected_at = conn->super.connected_at;
661
                /* destruct the connection after detatching the socket */
662
4.64k
                conn->sock = NULL;
663
4.64k
                close_connection(conn, 1);
664
                /* and accept as http2 connection */
665
4.64k
                h2o_http2_accept(&accept_ctx, sock, connected_at);
666
4.64k
                return;
667
4.64k
            }
668
5.84k
        }
669
1.20k
        if (inreqlen <= 4 && contains_crlf_only(conn->sock->input->bytes, inreqlen)) {
670
30
            close_connection(conn, 1);
671
1.17k
        } else {
672
1.17k
            send_bad_request(conn, "Bad Request");
673
1.17k
        }
674
1.20k
        return;
675
9.39k
    default: /* parse complete */
676
9.39k
        break;
677
17.5k
    }
678
679
    /* parse complete */
680
9.39k
    const char *err;
681
9.39k
    ssize_t entity_body_header_index;
682
9.39k
    ssize_t expect_header_index;
683
9.39k
    conn->_unconsumed_request_size = reqlen;
684
9.39k
    if ((err = fixup_request(conn, headers, num_headers, minor_version, &expect_header_index, &entity_body_header_index)) != NULL &&
685
730
        err != fixup_request_is_h2_upgrade) {
686
112
        clear_timeouts(conn);
687
112
        send_bad_request(conn, err);
688
112
        return;
689
112
    }
690
9.28k
    h2o_probe_log_request(&conn->req, conn->_req_index);
691
692
    /* handle H2 upgrade */
693
9.28k
    if (err == fixup_request_is_h2_upgrade) {
694
618
        clear_timeouts(conn);
695
618
        h2o_socket_read_stop(conn->sock);
696
618
        if (h2o_http2_handle_upgrade(&conn->req, conn->super.connected_at) != 0)
697
506
            h2o_send_error_400(&conn->req, "Invalid Request", "Broken upgrade request to HTTP/2", 0);
698
618
        return;
699
618
    }
700
701
    /* handle request with body */
702
8.66k
    if (entity_body_header_index != -1) {
703
        /* Request has body, start reading it */
704
1.83k
        conn->req.timestamps.request_body_begin_at = h2o_gettimeofday(conn->super.ctx->loop);
705
1.83k
        if (create_entity_reader(conn, headers + entity_body_header_index) != 0)
706
139
            return;
707
1.69k
        conn->_unconsumed_request_size = 0;
708
1.69k
        h2o_buffer_init(&conn->req_body, &h2o_socket_buffer_prototype);
709
1.69k
        conn->req.write_req.cb = write_req_first;
710
1.69k
        conn->req.write_req.ctx = &conn->req;
711
1.69k
        if (expect_header_index != -1) {
712
11
            h2o_iovec_t expect_value = h2o_iovec_init(headers[expect_header_index].value, headers[expect_header_index].value_len);
713
11
            if (!h2o_lcstris(expect_value.base, expect_value.len, H2O_STRLIT("100-continue"))) {
714
11
                clear_timeouts(conn);
715
11
                h2o_socket_read_stop(conn->sock);
716
11
                h2o_send_error_417(&conn->req, "Expectation Failed", "unknown expectation", H2O_SEND_ERROR_HTTP1_CLOSE_CONNECTION);
717
11
                return;
718
11
            }
719
0
            if (h2o_req_should_forward_expect(&conn->req)) {
720
                /* in forward mode, expect header is treated like other normal headers */
721
0
                char orig_case_cstr[sizeof("expect")] = {0};
722
0
                assert(sizeof(orig_case_cstr) - 1 == headers[expect_header_index].name_len);
723
0
                h2o_memcpy(orig_case_cstr, headers[expect_header_index].name, sizeof(orig_case_cstr) - 1);
724
0
                h2o_add_header(&conn->req.pool, &conn->req.headers, H2O_TOKEN_EXPECT, orig_case_cstr,
725
0
                               h2o_strdup(&conn->req.pool, expect_value.base, expect_value.len).base, expect_value.len);
726
0
                h2o_buffer_consume(&conn->sock->input, reqlen);
727
0
                goto ProcessImmediately;
728
0
            }
729
            /* not in forward mode, send out own 100-continue */
730
0
            h2o_buffer_consume(&conn->sock->input, reqlen);
731
0
            static const h2o_iovec_t res = {H2O_STRLIT("HTTP/1.1 100 Continue\r\n\r\n")};
732
0
            h2o_socket_write(conn->sock, (void *)&res, 1, on_continue_sent);
733
            /* processing of the incoming entity is postponed until the 100 response is sent */
734
0
            h2o_socket_read_stop(conn->sock);
735
1.68k
        } else {
736
1.68k
            h2o_buffer_consume(&conn->sock->input, reqlen);
737
            /* Invocation of `h2o_process_request` is delayed to reduce backend concurrency */
738
1.68k
            conn->_req_entity_reader->handle_incoming_entity(conn);
739
1.68k
        }
740
1.68k
        return;
741
1.69k
    }
742
743
    /* handle tunnel request */
744
6.83k
    if (conn->req.is_tunnel_req) {
745
        /* Is a CONNECT request or an upgrade (e.g., WebSocket). Request is submitted immediately and body is streamed. */
746
72
        if (!h2o_req_can_stream_request(&conn->req) &&
747
59
            h2o_memis(conn->req.input.method.base, conn->req.input.method.len, H2O_STRLIT("CONNECT"))) {
748
17
            clear_timeouts(conn);
749
17
            h2o_socket_read_stop(conn->sock);
750
17
            h2o_send_error_405(&conn->req, "Method Not Allowed", "Method Not Allowed", 0);
751
17
            return;
752
17
        }
753
55
        if (create_content_length_entity_reader(conn, SIZE_MAX) != 0)
754
0
            return;
755
55
        conn->_unconsumed_request_size = 0;
756
55
        h2o_buffer_consume(&conn->sock->input, reqlen);
757
55
        h2o_buffer_init(&conn->req_body, &h2o_socket_buffer_prototype);
758
55
        goto ProcessImmediately;
759
55
    }
760
761
    /* handle ordinary request without request body */
762
6.75k
    clear_timeouts(conn);
763
6.75k
    h2o_socket_read_stop(conn->sock);
764
6.75k
    h2o_process_request(&conn->req);
765
6.75k
    return;
766
767
55
ProcessImmediately:
768
55
    conn->req.write_req.cb = write_req_connect_first;
769
55
    conn->req.write_req.ctx = &conn->req;
770
55
    conn->req.proceed_req = proceed_request;
771
55
    conn->_req_entity_reader->handle_incoming_entity(conn); /* read payload received early before submitting the request */
772
55
    if (conn->req.entity.base == NULL)
773
24
        conn->req.entity = h2o_iovec_init("", 0); /* if nothing was read, still indicate that body exists */
774
    /* stop reading (this might or might not be done by `handle_incoming_entity`) until HTTP response is given */
775
55
    h2o_socket_read_stop(conn->sock);
776
55
    clear_timeouts(conn);
777
55
    h2o_process_request(&conn->req);
778
55
    return;
779
6.83k
}
780
781
void reqread_on_read(h2o_socket_t *sock, const char *err)
782
16.8k
{
783
16.8k
    struct st_h2o_http1_conn_t *conn = sock->data;
784
785
16.8k
    if (err != NULL) {
786
2.74k
        close_connection(conn, 1);
787
2.74k
        return;
788
2.74k
    }
789
790
14.0k
    set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
791
14.0k
    if (conn->_req_entity_reader == NULL)
792
12.6k
        handle_incoming_request(conn);
793
1.47k
    else
794
1.47k
        conn->_req_entity_reader->handle_incoming_entity(conn);
795
14.0k
}
796
797
static void close_idle_connection(h2o_conn_t *_conn)
798
0
{
799
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
800
0
    conn->req.http1_is_persistent = 0;
801
0
    close_connection(conn, 1);
802
0
}
803
804
static void on_timeout(struct st_h2o_http1_conn_t *conn)
805
0
{
806
0
    if (conn->_req_index == 1) {
807
        /* assign hostconf and bind conf so that the request can be logged */
808
0
        h2o_hostconf_t *hostconf = h2o_req_setup(&conn->req);
809
0
        h2o_req_bind_conf(&conn->req, hostconf, &hostconf->fallback_path);
810
        /* set error status for logging */
811
0
        conn->req.res.reason = "Request Timeout";
812
0
    }
813
814
0
    close_idle_connection(&conn->super);
815
0
}
816
817
static void req_io_on_timeout(h2o_timer_t *entry)
818
0
{
819
0
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _io_timeout_entry, entry);
820
0
    conn->super.ctx->http1.events.request_io_timeouts++;
821
0
    on_timeout(conn);
822
0
}
823
824
static void reqread_on_timeout(h2o_timer_t *entry)
825
0
{
826
0
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, _timeout_entry, entry);
827
0
    conn->super.ctx->http1.events.request_timeouts++;
828
0
    on_timeout(conn);
829
0
}
830
831
static inline void reqread_start(struct st_h2o_http1_conn_t *conn)
832
17.4k
{
833
17.4k
    set_req_timeout(conn, conn->super.ctx->globalconf->http1.req_timeout, reqread_on_timeout);
834
17.4k
    set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
835
17.4k
    h2o_socket_read_start(conn->sock, reqread_on_read);
836
17.4k
    if (conn->sock->input->size != 0)
837
4.89k
        handle_incoming_request(conn);
838
17.4k
}
839
840
static void on_send_next(h2o_socket_t *sock, const char *err)
841
3.25k
{
842
3.25k
    struct st_h2o_http1_conn_t *conn = sock->data;
843
844
3.25k
    if (err == h2o_socket_error_write_progress) {
845
1.62k
        set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
846
1.62k
        return;
847
1.62k
    }
848
849
1.62k
    if (err != NULL)
850
2
        close_connection(conn, 1);
851
1.62k
    else
852
1.62k
        h2o_proceed_response(&conn->req);
853
1.62k
}
854
855
static void on_send_complete_post_trailers(h2o_socket_t *sock, const char *err)
856
0
{
857
0
    struct st_h2o_http1_conn_t *conn = sock->data;
858
859
0
    if (err != NULL)
860
0
        conn->req.http1_is_persistent = 0;
861
862
0
    conn->_ostr_final.state = OSTREAM_STATE_DONE;
863
0
    if (conn->req.proceed_req == NULL)
864
0
        cleanup_connection(conn);
865
0
}
866
867
static void on_send_complete(h2o_socket_t *sock, const char *err)
868
19.6k
{
869
19.6k
    struct st_h2o_http1_conn_t *conn = sock->data;
870
871
19.6k
    if (err == h2o_socket_error_write_progress) {
872
9.62k
        set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
873
9.62k
        return;
874
9.62k
    }
875
876
10.0k
    if (err == NULL) {
877
10.0k
        if (conn->req._ostr_top != &conn->_ostr_final.super) {
878
0
            err = "pull error";
879
10.0k
        } else {
880
            /* success */
881
10.0k
            conn->req.timestamps.response_end_at = h2o_gettimeofday(conn->super.ctx->loop);
882
10.0k
            if (h2o_timeval_is_null(&conn->req.timestamps.response_start_at)) {
883
0
                conn->req.timestamps.response_start_at = conn->req.timestamps.response_end_at;
884
0
            }
885
10.0k
        }
886
10.0k
    }
887
888
10.0k
    if (err != NULL)
889
4
        conn->req.http1_is_persistent = 0;
890
891
10.0k
    if (err == NULL && conn->req.send_server_timing && conn->_ostr_final.chunked_buf != NULL) {
892
0
        h2o_iovec_t trailer;
893
0
        if ((trailer = h2o_build_server_timing_trailer(&conn->req, H2O_STRLIT("server-timing: "), H2O_STRLIT("\r\n\r\n"))).len !=
894
0
            0) {
895
0
            h2o_socket_write(conn->sock, &trailer, 1, on_send_complete_post_trailers);
896
0
            return;
897
0
        }
898
0
    }
899
900
10.0k
    conn->_ostr_final.state = OSTREAM_STATE_DONE;
901
902
10.0k
    if (conn->req.is_tunnel_req) {
903
        /* We have received a complete request (the end of the request is the request headers, see `fixup_request`), and the
904
         * connection is not going to handle any more requests. Therefore, we can close the connection immediately, regardless of if
905
         * the connection had been turned into a tunnel. */
906
72
        assert(!conn->req.http1_is_persistent);
907
72
        cleanup_connection(conn);
908
9.96k
    } else if (conn->req.proceed_req == NULL) {
909
        /* Upstream has sent an early response. Continue forwarding the request body. */
910
9.59k
        cleanup_connection(conn);
911
9.59k
    }
912
10.0k
}
913
914
static void on_upgrade_complete(h2o_socket_t *socket, const char *err)
915
112
{
916
112
    struct st_h2o_http1_conn_t *conn = socket->data;
917
112
    h2o_http1_upgrade_cb cb = conn->upgrade.cb;
918
112
    void *data = conn->upgrade.data;
919
112
    h2o_socket_t *sock = NULL;
920
112
    size_t headers_size = 0;
921
922
    /* destruct the connection (after detaching the socket) */
923
112
    if (err == 0) {
924
111
        sock = conn->sock;
925
111
        headers_size = conn->_unconsumed_request_size;
926
111
        close_connection(conn, 0);
927
111
    } else {
928
1
        close_connection(conn, 1);
929
1
    }
930
931
112
    cb(data, sock, headers_size);
932
112
}
933
934
static size_t flatten_headers_estimate_size(h2o_req_t *req, size_t server_name_and_connection_len)
935
10.1k
{
936
10.1k
    size_t len = sizeof("HTTP/1.1  \r\nserver: \r\nconnection: \r\ncontent-length: \r\n\r\n") + 3 + strlen(req->res.reason) +
937
10.1k
                 server_name_and_connection_len + sizeof(H2O_UINT64_LONGEST_STR) - 1 + sizeof("cache-control: private") - 1;
938
10.1k
    const h2o_header_t *header, *end;
939
940
21.5k
    for (header = req->res.headers.entries, end = header + req->res.headers.size; header != end; ++header)
941
11.4k
        len += header->name->len + header->value.len + 4;
942
943
10.1k
    return len;
944
10.1k
}
945
946
static size_t flatten_res_headers(char *buf, h2o_req_t *req)
947
10.1k
{
948
10.1k
    char *dst = buf;
949
10.1k
    size_t i;
950
21.5k
    for (i = 0; i != req->res.headers.size; ++i) {
951
11.4k
        const h2o_header_t *header = req->res.headers.entries + i;
952
11.4k
        memcpy(dst, header->orig_name ? header->orig_name : header->name->base, header->name->len);
953
11.4k
        dst += header->name->len;
954
11.4k
        *dst++ = ':';
955
11.4k
        *dst++ = ' ';
956
11.4k
        memcpy(dst, header->value.base, header->value.len);
957
11.4k
        dst += header->value.len;
958
11.4k
        *dst++ = '\r';
959
11.4k
        *dst++ = '\n';
960
11.4k
    }
961
962
10.1k
    return dst - buf;
963
10.1k
}
964
965
static size_t flatten_headers(char *buf, h2o_req_t *req, const char *connection)
966
10.1k
{
967
10.1k
    h2o_context_t *ctx = req->conn->ctx;
968
10.1k
    char *dst = buf;
969
970
10.1k
    assert(req->res.status <= 999);
971
972
    /* send essential headers with the first chars uppercased for max. interoperability (#72) */
973
10.1k
    if (req->res.content_length != SIZE_MAX) {
974
7.76k
        dst += sprintf(dst, "HTTP/1.1 %d %s\r\nConnection: %s\r\nContent-Length: %zu\r\n", req->res.status, req->res.reason,
975
7.76k
                       connection, req->res.content_length);
976
7.76k
    } else {
977
2.38k
        dst += sprintf(dst, "HTTP/1.1 %d %s\r\nConnection: %s\r\n", req->res.status, req->res.reason, connection);
978
2.38k
    }
979
10.1k
    if (ctx->globalconf->server_name.len) {
980
10.1k
        dst += sprintf(dst, "Server: %s\r\n", ctx->globalconf->server_name.base);
981
10.1k
    }
982
983
10.1k
    dst += flatten_res_headers(dst, req);
984
10.1k
    *dst++ = '\r';
985
10.1k
    *dst++ = '\n';
986
987
10.1k
    return dst - buf;
988
10.1k
}
989
990
static int should_use_chunked_encoding(h2o_req_t *req)
991
10.0k
{
992
10.0k
    if (req->is_tunnel_req)
993
72
        return 0;
994
9.96k
    if (req->version != 0x101)
995
3.06k
        return 0;
996
    /* do nothing if content-length is known */
997
6.90k
    if (req->res.content_length != SIZE_MAX)
998
5.04k
        return 0;
999
    /* RFC 2616 4.4 states that the following status codes (and response to a HEAD method) should not include message body */
1000
1.85k
    if ((100 <= req->res.status && req->res.status <= 199) || req->res.status == 204 || req->res.status == 304)
1001
0
        return 0;
1002
1.85k
    if (h2o_memis(req->input.method.base, req->input.method.len, H2O_STRLIT("HEAD")))
1003
576
        return 0;
1004
1005
1.28k
    return 1;
1006
1.85k
}
1007
1008
static void setup_chunked(struct st_h2o_http1_finalostream_t *self, h2o_req_t *req)
1009
10.0k
{
1010
10.0k
    if (should_use_chunked_encoding(req)) {
1011
1.28k
        h2o_add_header(&req->pool, &req->res.headers, H2O_TOKEN_TRANSFER_ENCODING, NULL, H2O_STRLIT("chunked"));
1012
1.28k
        self->chunked_buf = h2o_mem_alloc_pool_aligned(&req->pool, 1, sizeof(size_t) * 2 + sizeof("\r\n"));
1013
1.28k
    }
1014
10.0k
}
1015
1016
static void encode_chunked(h2o_sendvec_t *prefix, h2o_sendvec_t *suffix, h2o_send_state_t state, size_t chunk_size,
1017
                           int send_trailers, char *buffer)
1018
2.49k
{
1019
2.49k
    h2o_sendvec_init_raw(prefix, NULL, 0);
1020
2.49k
    h2o_sendvec_init_raw(suffix, NULL, 0);
1021
1022
    /* create chunk header and output data */
1023
2.49k
    if (chunk_size != 0) {
1024
1.28k
        prefix->raw = buffer;
1025
1.28k
        prefix->len = sprintf(buffer, "%zx\r\n", chunk_size);
1026
1.28k
        if (state != H2O_SEND_STATE_ERROR) {
1027
1.28k
            suffix->raw = "\r\n0\r\n\r\n";
1028
1.28k
            suffix->len = state == H2O_SEND_STATE_FINAL ? (send_trailers ? 5 : 7) : 2;
1029
1.28k
        }
1030
1.28k
    } else if (state == H2O_SEND_STATE_FINAL) {
1031
1.21k
        suffix->raw = "0\r\n\r\n";
1032
1.21k
        suffix->len = send_trailers ? 3 : 5;
1033
1.21k
    }
1034
1035
    /* if state is error, send a broken chunk to pass the error down to the browser */
1036
2.49k
    if (state == H2O_SEND_STATE_ERROR) {
1037
0
        suffix->raw = "\r\n1\r\n";
1038
0
        suffix->len = 5;
1039
0
    }
1040
2.49k
}
1041
1042
void finalostream_send(h2o_ostream_t *_self, h2o_req_t *_req, h2o_sendvec_t *inbufs, size_t inbufcnt, h2o_send_state_t send_state)
1043
11.6k
{
1044
11.6k
    struct st_h2o_http1_conn_t *conn = (struct st_h2o_http1_conn_t *)_req->conn;
1045
11.6k
    h2o_sendvec_t bufs[inbufcnt + 1 + 2]; /* 1 for header, 2 for chunked encoding */
1046
11.6k
    size_t bufcnt = 0, chunked_prefix_index = 0;
1047
11.6k
    int empty_payload_allowed = conn->_ostr_final.state == OSTREAM_STATE_HEAD || send_state != H2O_SEND_STATE_IN_PROGRESS;
1048
1049
11.6k
    assert(&conn->req == _req);
1050
11.6k
    assert(_self == &conn->_ostr_final.super);
1051
1052
11.6k
    if (conn->_ostr_final.informational.write_inflight) {
1053
0
        conn->_ostr_final.informational.pending_final.inbufs = h2o_mem_alloc_pool(&conn->req.pool, h2o_sendvec_t, inbufcnt);
1054
0
        memcpy(conn->_ostr_final.informational.pending_final.inbufs, inbufs, sizeof(*inbufs) * inbufcnt);
1055
0
        conn->_ostr_final.informational.pending_final.inbufcnt = inbufcnt;
1056
0
        conn->_ostr_final.informational.pending_final.send_state = send_state;
1057
0
        return;
1058
0
    }
1059
1060
11.6k
    if (send_state == H2O_SEND_STATE_ERROR) {
1061
0
        conn->req.http1_is_persistent = 0;
1062
0
        conn->req.send_server_timing = 0;
1063
0
        if (conn->req.upstream_refused) {
1064
            /* to let the client retry, immediately close the connection without sending any data */
1065
0
            on_send_complete(conn->sock, NULL);
1066
0
            return;
1067
0
        }
1068
0
    }
1069
1070
11.6k
    if (conn->_ostr_final.state == OSTREAM_STATE_HEAD) {
1071
        /* build headers and send */
1072
10.0k
        conn->req.timestamps.response_start_at = h2o_gettimeofday(conn->super.ctx->loop);
1073
10.0k
        setup_chunked(&conn->_ostr_final, &conn->req);
1074
10.0k
        if (conn->req.send_server_timing)
1075
0
            h2o_add_server_timing_header(&conn->req, conn->_ostr_final.chunked_buf != NULL);
1076
1077
10.0k
        const char *connection = conn->req.http1_is_persistent ? "keep-alive" : "close";
1078
10.0k
        if (conn->req.is_tunnel_req && conn->req.res.status == 101 && conn->req.upgrade.base)
1079
6
            connection = "upgrade";
1080
10.0k
        size_t headers_est_size =
1081
10.0k
            flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + strlen(connection));
1082
10.0k
        h2o_sendvec_init_raw(bufs + bufcnt, h2o_mem_alloc_pool(&conn->req.pool, char, headers_est_size), 0);
1083
10.0k
        bufs[bufcnt].len = flatten_headers(bufs[bufcnt].raw, &conn->req, connection);
1084
10.0k
        conn->req.header_bytes_sent += bufs[bufcnt].len;
1085
10.0k
        ++bufcnt;
1086
10.0k
        h2o_probe_log_response(&conn->req, conn->_req_index);
1087
10.0k
        conn->_ostr_final.state = OSTREAM_STATE_BODY;
1088
10.0k
    }
1089
1090
11.6k
    if (conn->_ostr_final.chunked_buf != NULL)
1091
2.49k
        chunked_prefix_index = bufcnt++;
1092
1093
11.6k
    size_t bytes_sent = 0;
1094
20.8k
    for (size_t i = 0; i != inbufcnt; ++i) {
1095
9.22k
        if (inbufs[i].len == 0)
1096
0
            continue;
1097
9.22k
        bufs[bufcnt++] = inbufs[i];
1098
9.22k
        bytes_sent += inbufs[i].len;
1099
9.22k
    }
1100
11.6k
    assert(empty_payload_allowed || bytes_sent != 0 || !"h2o_data must only be called when there is progress");
1101
11.6k
    conn->req.bytes_sent += bytes_sent;
1102
1103
11.6k
    if (conn->_ostr_final.chunked_buf != NULL) {
1104
2.49k
        encode_chunked(bufs + chunked_prefix_index, bufs + bufcnt, send_state, bytes_sent, conn->req.send_server_timing != 0,
1105
2.49k
                       conn->_ostr_final.chunked_buf);
1106
2.49k
        if (bufs[bufcnt].len != 0)
1107
2.49k
            ++bufcnt;
1108
2.49k
    }
1109
1110
11.6k
    if (bufcnt != 0)
1111
11.2k
        set_req_io_timeout(conn, conn->super.ctx->globalconf->http1.req_io_timeout, req_io_on_timeout);
1112
1113
11.6k
    h2o_socket_sendvec(conn->sock, bufs, bufcnt, H2O_SOCKET_SENDVEC_FLAG_REPORT_PROGRESS,
1114
11.6k
                       h2o_send_state_is_in_progress(send_state) ? on_send_next : on_send_complete);
1115
11.6k
}
1116
1117
static void on_send_informational_complete(h2o_socket_t *sock, const char *err);
1118
1119
static void do_send_informational(struct st_h2o_http1_conn_t *conn)
1120
0
{
1121
0
    assert(!conn->_ostr_final.informational.write_inflight && conn->_ostr_final.informational.pending.size != 0);
1122
1123
0
    conn->_ostr_final.informational.write_inflight = 1;
1124
0
    h2o_socket_write(conn->sock, conn->_ostr_final.informational.pending.entries, conn->_ostr_final.informational.pending.size,
1125
0
                     on_send_informational_complete);
1126
0
    conn->_ostr_final.informational.pending.size = 0;
1127
0
}
1128
1129
static void on_send_informational_complete(h2o_socket_t *sock, const char *err)
1130
0
{
1131
0
    struct st_h2o_http1_conn_t *conn = sock->data;
1132
0
    if (err != NULL) {
1133
0
        close_connection(conn, 1);
1134
0
        return;
1135
0
    }
1136
1137
0
    conn->_ostr_final.informational.write_inflight = 0;
1138
1139
0
    if (conn->_ostr_final.informational.pending_final.inbufs != NULL) {
1140
0
        finalostream_send(&conn->_ostr_final.super, &conn->req, conn->_ostr_final.informational.pending_final.inbufs,
1141
0
                          conn->_ostr_final.informational.pending_final.inbufcnt,
1142
0
                          conn->_ostr_final.informational.pending_final.send_state);
1143
0
        return;
1144
0
    }
1145
1146
0
    if (conn->_ostr_final.informational.pending.size != 0)
1147
0
        do_send_informational(conn);
1148
0
}
1149
1150
static void finalostream_send_informational(h2o_ostream_t *_self, h2o_req_t *req)
1151
0
{
1152
0
    struct st_h2o_http1_conn_t *conn = (struct st_h2o_http1_conn_t *)req->conn;
1153
0
    assert(_self == &conn->_ostr_final.super);
1154
1155
0
    size_t len = sizeof("HTTP/1.1  \r\n\r\n") + 3 + strlen(req->res.reason) - 1;
1156
0
    h2o_iovec_t buf = h2o_iovec_init(NULL, len);
1157
1158
0
    int i;
1159
0
    for (i = 0; i != req->res.headers.size; ++i)
1160
0
        buf.len += req->res.headers.entries[i].name->len + req->res.headers.entries[i].value.len + 4;
1161
1162
0
    buf.base = h2o_mem_alloc_pool(&req->pool, char, buf.len);
1163
0
    char *dst = buf.base;
1164
0
    dst += sprintf(dst, "HTTP/1.1 %d %s\r\n", req->res.status, req->res.reason);
1165
0
    dst += flatten_res_headers(dst, req);
1166
0
    *dst++ = '\r';
1167
0
    *dst++ = '\n';
1168
1169
0
    req->header_bytes_sent += dst - buf.base;
1170
1171
0
    h2o_vector_reserve(&req->pool, &conn->_ostr_final.informational.pending, conn->_ostr_final.informational.pending.size + 1);
1172
0
    conn->_ostr_final.informational.pending.entries[conn->_ostr_final.informational.pending.size++] = buf;
1173
1174
0
    if (!conn->_ostr_final.informational.write_inflight)
1175
0
        do_send_informational(conn);
1176
0
}
1177
1178
static socklen_t get_sockname(h2o_conn_t *_conn, struct sockaddr *sa)
1179
0
{
1180
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1181
0
    return h2o_socket_getsockname(conn->sock, sa);
1182
0
}
1183
1184
static socklen_t get_peername(h2o_conn_t *_conn, struct sockaddr *sa)
1185
2.36k
{
1186
2.36k
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1187
2.36k
    return h2o_socket_getpeername(conn->sock, sa);
1188
2.36k
}
1189
1190
static ptls_t *get_ptls(h2o_conn_t *_conn)
1191
2.36k
{
1192
2.36k
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1193
2.36k
    assert(conn->sock != NULL && "it never becomes NULL, right?");
1194
2.36k
    return h2o_socket_get_ptls(conn->sock);
1195
2.36k
}
1196
1197
static const char *get_ssl_server_name(h2o_conn_t *_conn)
1198
0
{
1199
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1200
0
    return h2o_socket_get_ssl_server_name(conn->sock);
1201
0
}
1202
1203
static ptls_log_conn_state_t *log_state(h2o_conn_t *_conn)
1204
0
{
1205
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1206
0
    return h2o_socket_log_state(conn->sock);
1207
0
}
1208
1209
static int can_zerocopy(h2o_conn_t *_conn)
1210
2.36k
{
1211
2.36k
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1212
2.36k
    return conn->sock->ssl == NULL || h2o_socket_can_tls_offload(conn->sock);
1213
2.36k
}
1214
1215
static uint64_t get_req_id(h2o_req_t *req)
1216
0
{
1217
0
    struct st_h2o_http1_conn_t *conn = H2O_STRUCT_FROM_MEMBER(struct st_h2o_http1_conn_t, req, req);
1218
0
    return conn->_req_index;
1219
0
}
1220
1221
static h2o_socket_t *steal_socket(h2o_conn_t *_conn)
1222
0
{
1223
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1224
0
    h2o_socket_t *sock = conn->sock;
1225
1226
0
    if (sock->ssl != NULL)
1227
0
        return NULL;
1228
1229
0
    close_connection(conn, 0);
1230
0
    return sock;
1231
0
}
1232
1233
#define DEFINE_LOGGER(name)                                                                                                        \
1234
    static h2o_iovec_t log_##name(h2o_req_t *req)                                                                                  \
1235
0
    {                                                                                                                              \
1236
0
        struct st_h2o_http1_conn_t *conn = (void *)req->conn;                                                                      \
1237
0
        return h2o_socket_log_##name(conn->sock, &req->pool);                                                                      \
1238
0
    }
Unexecuted instantiation: http1.c:log_tcp_congestion_controller
Unexecuted instantiation: http1.c:log_tcp_delivery_rate
Unexecuted instantiation: http1.c:log_ssl_protocol_version
Unexecuted instantiation: http1.c:log_ssl_session_reused
Unexecuted instantiation: http1.c:log_ssl_cipher
Unexecuted instantiation: http1.c:log_ssl_cipher_bits
Unexecuted instantiation: http1.c:log_ssl_session_id
Unexecuted instantiation: http1.c:log_ssl_negotiated_protocol
Unexecuted instantiation: http1.c:log_ssl_ech_config_id
Unexecuted instantiation: http1.c:log_ssl_ech_kem
Unexecuted instantiation: http1.c:log_ssl_ech_cipher
Unexecuted instantiation: http1.c:log_ssl_ech_cipher_bits
Unexecuted instantiation: http1.c:log_ssl_backend
1239
1240
DEFINE_LOGGER(tcp_congestion_controller)
1241
DEFINE_LOGGER(tcp_delivery_rate)
1242
DEFINE_LOGGER(ssl_protocol_version)
1243
DEFINE_LOGGER(ssl_session_reused)
1244
DEFINE_LOGGER(ssl_cipher)
1245
DEFINE_LOGGER(ssl_cipher_bits)
1246
DEFINE_LOGGER(ssl_session_id)
1247
DEFINE_LOGGER(ssl_negotiated_protocol)
1248
DEFINE_LOGGER(ssl_ech_config_id)
1249
DEFINE_LOGGER(ssl_ech_kem)
1250
DEFINE_LOGGER(ssl_ech_cipher)
1251
DEFINE_LOGGER(ssl_ech_cipher_bits)
1252
DEFINE_LOGGER(ssl_backend)
1253
1254
#undef DEFINE_LOGGER
1255
1256
static h2o_iovec_t log_request_index(h2o_req_t *req)
1257
0
{
1258
0
    struct st_h2o_http1_conn_t *conn = (void *)req->conn;
1259
0
    char *s = h2o_mem_alloc_pool(&req->pool, char, sizeof(H2O_UINT64_LONGEST_STR));
1260
0
    size_t len = sprintf(s, "%" PRIu64, conn->_req_index);
1261
0
    return h2o_iovec_init(s, len);
1262
0
}
1263
1264
static int foreach_request(h2o_conn_t *_conn, int (*cb)(h2o_req_t *req, void *cbdata), void *cbdata)
1265
0
{
1266
0
    struct st_h2o_http1_conn_t *conn = (void *)_conn;
1267
0
    return cb(&conn->req, cbdata);
1268
0
}
1269
1270
static void initiate_graceful_shutdown(h2o_conn_t *_conn)
1271
0
{
1272
    /* note: nothing special needs to be done for handling graceful shutdown */
1273
0
}
1274
1275
static const h2o_conn_callbacks_t h1_callbacks = {
1276
    .get_sockname = get_sockname,
1277
    .get_peername = get_peername,
1278
    .get_ptls = get_ptls,
1279
    .get_ssl_server_name = get_ssl_server_name,
1280
    .log_state = log_state,
1281
    .close_idle_connection = close_idle_connection,
1282
    .foreach_request = foreach_request,
1283
    .request_shutdown = initiate_graceful_shutdown,
1284
    .can_zerocopy = can_zerocopy,
1285
    .get_req_id = get_req_id,
1286
    .steal_socket = steal_socket,
1287
    .log_ = {{
1288
        .transport =
1289
            {
1290
                .cc_name = log_tcp_congestion_controller,
1291
                .delivery_rate = log_tcp_delivery_rate,
1292
            },
1293
        .ssl =
1294
            {
1295
                .protocol_version = log_ssl_protocol_version,
1296
                .session_reused = log_ssl_session_reused,
1297
                .cipher = log_ssl_cipher,
1298
                .cipher_bits = log_ssl_cipher_bits,
1299
                .session_id = log_ssl_session_id,
1300
                .negotiated_protocol = log_ssl_negotiated_protocol,
1301
                .ech_config_id = log_ssl_ech_config_id,
1302
                .ech_kem = log_ssl_ech_kem,
1303
                .ech_cipher = log_ssl_ech_cipher,
1304
                .ech_cipher_bits = log_ssl_ech_cipher_bits,
1305
                .backend = log_ssl_backend,
1306
            },
1307
        .http1 =
1308
            {
1309
                .request_index = log_request_index,
1310
            },
1311
    }},
1312
};
1313
1314
static int conn_is_h1(h2o_conn_t *conn)
1315
112
{
1316
112
    return conn->callbacks == &h1_callbacks;
1317
112
}
1318
1319
void h2o_http1_accept(h2o_accept_ctx_t *ctx, h2o_socket_t *sock, struct timeval connected_at)
1320
10.5k
{
1321
10.5k
    struct st_h2o_http1_conn_t *conn =
1322
10.5k
        (void *)h2o_create_connection(sizeof(*conn), ctx->ctx, ctx->hosts, connected_at, &h1_callbacks);
1323
1324
    /* zero-fill all properties expect req */
1325
10.5k
    memset((char *)conn + sizeof(conn->super), 0, offsetof(struct st_h2o_http1_conn_t, req) - sizeof(conn->super));
1326
1327
    /* init properties that need to be non-zero */
1328
10.5k
    conn->sock = sock;
1329
10.5k
    sock->data = conn;
1330
1331
10.5k
    H2O_PROBE_CONN(H1_ACCEPT, &conn->super, conn->sock, &conn->super, h2o_conn_get_uuid(&conn->super));
1332
10.5k
    H2O_LOG_CONN(h1_accept, &conn->super, {
1333
10.5k
        PTLS_LOG_ELEMENT_PTR(sock, conn->sock);
1334
10.5k
        PTLS_LOG_ELEMENT_SAFESTR(uuid, h2o_conn_get_uuid(&conn->super));
1335
10.5k
    });
1336
1337
10.5k
    init_request(conn);
1338
10.5k
    reqread_start(conn);
1339
10.5k
}
1340
1341
void h2o_http1_upgrade(h2o_req_t *req, h2o_iovec_t *inbufs, size_t inbufcnt, h2o_http1_upgrade_cb on_complete, void *user_data)
1342
112
{
1343
1344
112
    assert(conn_is_h1(req->conn));
1345
112
    struct st_h2o_http1_conn_t *conn = (void *)req->conn;
1346
1347
112
    h2o_iovec_t *bufs = alloca(sizeof(h2o_iovec_t) * (inbufcnt + 1));
1348
1349
112
    conn->upgrade.data = user_data;
1350
112
    conn->upgrade.cb = on_complete;
1351
1352
112
    bufs[0].base = h2o_mem_alloc_pool(
1353
112
        &conn->req.pool, char,
1354
112
        flatten_headers_estimate_size(&conn->req, conn->super.ctx->globalconf->server_name.len + sizeof("upgrade") - 1));
1355
112
    bufs[0].len = flatten_headers(bufs[0].base, &conn->req, conn->req.res.status == 101 ? "upgrade" : "close");
1356
112
    h2o_memcpy(bufs + 1, inbufs, sizeof(h2o_iovec_t) * inbufcnt);
1357
1358
112
    h2o_socket_write(conn->sock, bufs, inbufcnt + 1, on_upgrade_complete);
1359
112
}