/src/h2o/include/h2o/httpclient.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2017 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 | | #ifndef h2o__httpclient_h |
23 | | #define h2o__httpclient_h |
24 | | |
25 | | #ifdef __cplusplus |
26 | | extern "C" { |
27 | | #endif |
28 | | |
29 | | #include "quicly.h" |
30 | | #include "h2o/header.h" |
31 | | #include "h2o/hostinfo.h" |
32 | | #include "h2o/http3_common.h" |
33 | | #include "h2o/send_state.h" |
34 | | #include "h2o/socket.h" |
35 | | #include "h2o/socketpool.h" |
36 | | |
37 | | typedef struct st_h2o_httpclient_t h2o_httpclient_t; |
38 | | |
39 | | typedef void (*h2o_httpclient_forward_datagram_cb)(h2o_httpclient_t *client, h2o_iovec_t *datagrams, size_t num_datagrams); |
40 | | |
41 | | /** |
42 | | * Additional properties related to the HTTP request being issued. |
43 | | * When the connect callback is being called, the properties of the objects are set to their initial values. Applications MAY alter |
44 | | * the properties to achieve desirable behavior. The reason we require the protocol stacks to initialize the values to their default |
45 | | * values instead of requiring applications to set all the values correctly is to avoid requiring applications making changes |
46 | | * every time a new field is added to the object. |
47 | | */ |
48 | | typedef struct st_h2o_httpclient_properties_t { |
49 | | /** |
50 | | * When the value is a non-NULL pointer (at the moment, only happens with the HTTP/1 client), the application MAY set it to an |
51 | | * iovec pointing to the payload of the PROXY protocol (i.e., the first line). |
52 | | */ |
53 | | h2o_iovec_t *proxy_protocol; |
54 | | /** |
55 | | * When the value is a non-NULL pointer (at the moment, only happens with the HTTP/1 client), the application MAY set it to 1 to |
56 | | * indicate that the request body should be encoded using the chunked transfer-encoding. |
57 | | */ |
58 | | int *chunked; |
59 | | /** |
60 | | * When the value is a non-NULL pointer (at the moment, only happens with the HTTP/1 client), the application MAY set it to the |
61 | | * value of the connection header field to be sent to the server. This value is advisory in sense that 1) the server might |
62 | | * decide to close the connection even if the client sent `keep-alive` and 2) the field may be rewritten to `upgrade` if the |
63 | | * client requested upgrade (extended CONNECT). |
64 | | */ |
65 | | h2o_iovec_t *connection_header; |
66 | | /** |
67 | | * defaults to false |
68 | | */ |
69 | | unsigned prefer_pipe_reader : 1; |
70 | | /** |
71 | | * When the value is 1, httpclient sends 'expect: 100-continue' header and suspends sending request body |
72 | | * until it sees 100-continue response |
73 | | */ |
74 | | unsigned send_own_expect : 1; |
75 | | } h2o_httpclient_properties_t; |
76 | | |
77 | | typedef struct st_h2o_httpclient_pipe_reader_t h2o_httpclient_pipe_reader_t; |
78 | | |
79 | | typedef struct st_h2o_httpclient_on_head_t { |
80 | | int version; |
81 | | int status; |
82 | | h2o_iovec_t msg; |
83 | | h2o_header_t *headers; |
84 | | size_t num_headers; |
85 | | int header_requires_dup; |
86 | | struct { |
87 | | h2o_httpclient_forward_datagram_cb write_, *read_; |
88 | | } forward_datagram; |
89 | | /** |
90 | | * If this pointer is set to non-NULL by the HTTP client, it is offering the user the opportunity to read content to a pipe, |
91 | | * rather than suppliend them as bytes. To take that opportunity, users should set the members of the pointed struct to |
92 | | * appropriate values. Note that even when the user opts in to using a pipe, first chunk of content may still be served through |
93 | | * memory, as the content would be read into memory alongside the HTTP response headers. |
94 | | */ |
95 | | h2o_httpclient_pipe_reader_t *pipe_reader; |
96 | | } h2o_httpclient_on_head_t; |
97 | | |
98 | | typedef void (*h2o_httpclient_proceed_req_cb)(h2o_httpclient_t *client, const char *errstr); |
99 | | typedef int (*h2o_httpclient_body_cb)(h2o_httpclient_t *client, const char *errstr, h2o_header_t *trailers, size_t num_trailers); |
100 | | typedef h2o_httpclient_body_cb (*h2o_httpclient_head_cb)(h2o_httpclient_t *client, const char *errstr, |
101 | | h2o_httpclient_on_head_t *args); |
102 | | /** |
103 | | * Called when the protocol stack is ready to issue a request. Application must set all the output parameters (i.e. all except |
104 | | * `client`, `errstr`, `origin`) and return a callback that will be called when the protocol stack receives the response headers |
105 | | * from the server. |
106 | | */ |
107 | | typedef h2o_httpclient_head_cb (*h2o_httpclient_connect_cb)(h2o_httpclient_t *client, const char *errstr, h2o_iovec_t *method, |
108 | | h2o_url_t *url, const h2o_header_t **headers, size_t *num_headers, |
109 | | h2o_iovec_t *body, h2o_httpclient_proceed_req_cb *proceed_req_cb, |
110 | | h2o_httpclient_properties_t *props, h2o_url_t *origin); |
111 | | typedef int (*h2o_httpclient_informational_cb)(h2o_httpclient_t *client, int version, int status, h2o_iovec_t msg, |
112 | | h2o_header_t *headers, size_t num_headers); |
113 | | |
114 | | typedef void (*h2o_httpclient_finish_cb)(h2o_httpclient_t *client); |
115 | | |
116 | | struct st_h2o_httpclient_pipe_reader_t { |
117 | | int fd; |
118 | | h2o_httpclient_body_cb on_body_piped; |
119 | | }; |
120 | | |
121 | | typedef struct st_h2o_httpclient_connection_pool_t { |
122 | | /** |
123 | | * used to establish connections and pool those when h1 is used. |
124 | | * socketpool is shared among multiple threads while connection pool is dedicated to each thread |
125 | | */ |
126 | | h2o_socketpool_t *socketpool; |
127 | | |
128 | | struct { |
129 | | h2o_linklist_t conns; |
130 | | } http2; |
131 | | |
132 | | struct { |
133 | | h2o_linklist_t conns; |
134 | | } http3; |
135 | | |
136 | | } h2o_httpclient_connection_pool_t; |
137 | | |
138 | | typedef struct st_h2o_httpclient_protocol_ratio_t { |
139 | | /** |
140 | | * If non-negative, indicates the percentage of requests for which use of HTTP/2 will be attempted. If set to negative, all |
141 | | * connections are established with ALPN offering both H1 and H2, then the load is balanced between the different protocol |
142 | | * versions. This behavior helps balance the load among a mixture of servers behind a load balancer, some supporting both H1 and |
143 | | * H2 and some supporting only H1. |
144 | | */ |
145 | | int8_t http2; |
146 | | /** |
147 | | * Indicates the percentage of requests for which HTTP/3 should be used. Unlike HTTP/2, this value cannot be negative, because |
148 | | * unlike ALPN over TLS over TCP, the choice of the protocol is up to the client. |
149 | | */ |
150 | | int8_t http3; |
151 | | } h2o_httpclient_protocol_ratio_t; |
152 | | |
153 | | typedef struct st_h2o_http3client_ctx_t h2o_http3client_ctx_t; |
154 | | |
155 | | typedef struct st_h2o_httpclient_ctx_t { |
156 | | h2o_loop_t *loop; |
157 | | h2o_multithread_receiver_t *getaddr_receiver; |
158 | | uint64_t io_timeout; |
159 | | uint64_t connect_timeout; |
160 | | uint64_t first_byte_timeout; |
161 | | uint64_t keepalive_timeout; /* only used for http2 for now */ |
162 | | size_t max_buffer_size; |
163 | | unsigned tunnel_enabled : 1; |
164 | | unsigned force_cleartext_http2 : 1; |
165 | | |
166 | | struct st_h2o_httpclient_protocol_selector_t { |
167 | | h2o_httpclient_protocol_ratio_t ratio; |
168 | | /** |
169 | | * Each deficit is initialized to zero, then incremented by the respective percentage, and the protocol corresponding to the |
170 | | * one with the highest value is chosen. Then, the chosen variable is decremented by 100. |
171 | | */ |
172 | | int16_t _deficits[4]; |
173 | | } protocol_selector; |
174 | | |
175 | | /** |
176 | | * HTTP/2-specific settings |
177 | | */ |
178 | | struct { |
179 | | h2o_socket_latency_optimization_conditions_t latency_optimization; |
180 | | uint32_t max_concurrent_streams; |
181 | | } http2; |
182 | | |
183 | | /** |
184 | | * HTTP/3-specific settings; 1-to(0|1) relationship, NULL when h3 is not used |
185 | | */ |
186 | | h2o_http3client_ctx_t *http3; |
187 | | |
188 | | } h2o_httpclient_ctx_t; |
189 | | |
190 | | struct st_h2o_http3client_ctx_t { |
191 | | ptls_openssl_verify_certificate_t verify_cert; |
192 | | ptls_context_t tls; |
193 | | quicly_context_t quic; |
194 | | h2o_quic_ctx_t h3; |
195 | | uint64_t max_frame_payload_size; |
196 | | /** |
197 | | * Optional callback invoked by the HTTP/3 client implementation to obtain information used for resuming a connection. When the |
198 | | * connection is to be resumed, the callback should set `*address_token` and `*session_ticket` to a vector that can be freed by |
199 | | * calling free (3), as well as writing the resumed transport parameters to `*resumed_tp`. Otherwise, `*address_token`, |
200 | | * `*session_ticket`, `*resumed_tp` can be left untouched, and a full handshake will be exercised. The function returns if the |
201 | | * operation was successful. When false is returned, the connection attempt is aborted. |
202 | | */ |
203 | | int (*load_session)(h2o_httpclient_ctx_t *ctx, struct sockaddr *server_addr, const char *server_name, |
204 | | ptls_iovec_t *address_token, ptls_iovec_t *session_ticket, quicly_transport_parameters_t *resumed_tp); |
205 | | }; |
206 | | |
207 | | typedef struct st_h2o_httpclient_timings_t { |
208 | | struct timeval start_at; |
209 | | struct timeval request_begin_at; |
210 | | struct timeval request_end_at; |
211 | | struct timeval response_start_at; |
212 | | struct timeval response_end_at; |
213 | | } h2o_httpclient_timings_t; |
214 | | |
215 | | /** |
216 | | * Properties of a HTTP client connection. |
217 | | */ |
218 | | typedef struct st_h2o_httpclient_conn_properties_t { |
219 | | /** |
220 | | * TLS properties. Definitions match that returned by corresponding h2o_socket function: `h2o_socket_ssl_*`. |
221 | | */ |
222 | | struct { |
223 | | const char *protocol_version; |
224 | | int session_reused; |
225 | | const char *cipher; |
226 | | int cipher_bits; |
227 | | } ssl; |
228 | | /** |
229 | | * Underlying TCP connection, if any. |
230 | | */ |
231 | | h2o_socket_t *sock; |
232 | | } h2o_httpclient_conn_properties_t; |
233 | | |
234 | | struct st_h2o_httpclient_t { |
235 | | /** |
236 | | * memory pool |
237 | | */ |
238 | | h2o_mem_pool_t *pool; |
239 | | /** |
240 | | * context |
241 | | */ |
242 | | h2o_httpclient_ctx_t *ctx; |
243 | | /** |
244 | | * connection pool |
245 | | */ |
246 | | h2o_httpclient_connection_pool_t *connpool; |
247 | | /** |
248 | | * buffer in which response data is stored (see update_window) |
249 | | */ |
250 | | h2o_buffer_t **buf; |
251 | | /** |
252 | | * application data pointer |
253 | | */ |
254 | | void *data; |
255 | | /** |
256 | | * optional callback to receive informational response(s); 101 is considered final and is never delivered through this callback |
257 | | */ |
258 | | h2o_httpclient_informational_cb informational_cb; |
259 | | /** |
260 | | * server-timing data |
261 | | */ |
262 | | h2o_httpclient_timings_t timings; |
263 | | /** |
264 | | * If the stream is to be converted to convey some other protocol, this value should be set to the name of the protocol, which |
265 | | * will be indicated by the `upgrade` request header field. Additionally, intent to create a CONNECT tunnel is indicated by a |
266 | | * special label called `h2o_httpclient_upgrade_to_connect`. |
267 | | */ |
268 | | const char *upgrade_to; |
269 | | |
270 | | /** |
271 | | * bytes written (above the TLS layer) |
272 | | */ |
273 | | struct { |
274 | | uint64_t header; |
275 | | uint64_t body; |
276 | | uint64_t total; |
277 | | } bytes_written; |
278 | | |
279 | | /** |
280 | | * bytes read (above the TLS layer) |
281 | | */ |
282 | | struct { |
283 | | uint64_t header; |
284 | | uint64_t body; |
285 | | uint64_t total; |
286 | | } bytes_read; |
287 | | |
288 | | /** |
289 | | * cancels a in-flight request |
290 | | */ |
291 | | void (*cancel)(h2o_httpclient_t *client); |
292 | | /** |
293 | | * returns a pointer to the underlying h2o_socket_t |
294 | | */ |
295 | | void (*get_conn_properties)(h2o_httpclient_t *client, h2o_httpclient_conn_properties_t *properties); |
296 | | /** |
297 | | * callback that should be called when some data is fetched out from `buf`. |
298 | | */ |
299 | | void (*update_window)(h2o_httpclient_t *client); |
300 | | /** |
301 | | * Function for writing request body. `proceed_req_cb` supplied through the `on_connect` callback will be called when the |
302 | | * given data is sent to the server. Regarding the usage, refer to the doc-comment of `h2o_write_req_cb`. |
303 | | */ |
304 | | int (*write_req)(h2o_httpclient_t *client, h2o_iovec_t chunk, int is_end_stream); |
305 | | |
306 | | h2o_timer_t _timeout; |
307 | | h2o_socketpool_connect_request_t *_connect_req; |
308 | | union { |
309 | | h2o_httpclient_connect_cb on_connect; |
310 | | h2o_httpclient_head_cb on_head; |
311 | | h2o_httpclient_body_cb on_body; |
312 | | } _cb; |
313 | | }; |
314 | | |
315 | | /** |
316 | | * public members of h2 client connection |
317 | | */ |
318 | | typedef struct st_h2o_httpclient__h2_conn_t { |
319 | | /** |
320 | | * context |
321 | | */ |
322 | | h2o_httpclient_ctx_t *ctx; |
323 | | /** |
324 | | * origin server (path is ignored) |
325 | | */ |
326 | | h2o_url_t origin_url; |
327 | | /** |
328 | | * underlying socket |
329 | | */ |
330 | | h2o_socket_t *sock; |
331 | | /** |
332 | | * number of open streams (FIXME can't we refer to khash?) |
333 | | */ |
334 | | size_t num_streams; |
335 | | /** |
336 | | * linklist of connections anchored to h2o_httpclient_connection_pool_t::http2.conns. The link is in the ascending order of |
337 | | * `num_streams`. |
338 | | */ |
339 | | h2o_linklist_t link; |
340 | | } h2o_httpclient__h2_conn_t; |
341 | | |
342 | | struct st_h2o_httpclient__h3_conn_t { |
343 | | h2o_http3_conn_t super; |
344 | | h2o_httpclient_ctx_t *ctx; |
345 | | /** |
346 | | * When the socket is associated to a global pool, used to identify the origin. If not associated to a global pool, the values |
347 | | * are zero-filled. |
348 | | */ |
349 | | struct { |
350 | | /** |
351 | | * the origin URL; null-termination of authority and host is guaranteed |
352 | | */ |
353 | | h2o_url_t origin_url; |
354 | | /** |
355 | | * port number in C string |
356 | | */ |
357 | | char named_serv[sizeof(H2O_UINT16_LONGEST_STR)]; |
358 | | } server; |
359 | | ptls_handshake_properties_t handshake_properties; |
360 | | h2o_timer_t timeout; |
361 | | h2o_hostinfo_getaddr_req_t *getaddr_req; |
362 | | /** |
363 | | * linked to h2o_httpclient_ctx_t::http3.conns |
364 | | */ |
365 | | h2o_linklist_t link; |
366 | | /** |
367 | | * linklist used to queue pending requests |
368 | | */ |
369 | | h2o_linklist_t pending_requests; |
370 | | }; |
371 | | |
372 | | extern const char h2o_httpclient_error_is_eos[]; |
373 | | extern const char h2o_httpclient_error_refused_stream[]; |
374 | | extern const char h2o_httpclient_error_unknown_alpn_protocol[]; |
375 | | extern const char h2o_httpclient_error_io[]; |
376 | | extern const char h2o_httpclient_error_connect_timeout[]; |
377 | | extern const char h2o_httpclient_error_first_byte_timeout[]; |
378 | | extern const char h2o_httpclient_error_io_timeout[]; |
379 | | extern const char h2o_httpclient_error_invalid_content_length[]; |
380 | | extern const char h2o_httpclient_error_flow_control[]; |
381 | | extern const char h2o_httpclient_error_http1_line_folding[]; |
382 | | extern const char h2o_httpclient_error_http1_unexpected_transfer_encoding[]; |
383 | | extern const char h2o_httpclient_error_http1_parse_failed[]; |
384 | | extern const char h2o_httpclient_error_protocol_violation[]; |
385 | | extern const char h2o_httpclient_error_internal[]; |
386 | | extern const char h2o_httpclient_error_malformed_frame[]; |
387 | | extern const char h2o_httpclient_error_unexpected_101[]; |
388 | | |
389 | | extern const char h2o_httpclient_upgrade_to_connect[]; |
390 | | |
391 | | void h2o_httpclient_connection_pool_init(h2o_httpclient_connection_pool_t *connpool, h2o_socketpool_t *sockpool); |
392 | | |
393 | | /** |
394 | | * issues a HTTP request using the connection pool. Either H1 or H2 may be used, depending on the given context. |
395 | | * TODO: create H1- or H2-specific connect function that works without the connection pool? |
396 | | */ |
397 | | void h2o_httpclient_connect(h2o_httpclient_t **client, h2o_mem_pool_t *pool, void *data, h2o_httpclient_ctx_t *ctx, |
398 | | h2o_httpclient_connection_pool_t *connpool, h2o_url_t *target, const char *upgrade_to, |
399 | | h2o_httpclient_connect_cb on_connect); |
400 | | |
401 | | void h2o_httpclient__h1_on_connect(h2o_httpclient_t *client, h2o_socket_t *sock, h2o_url_t *origin); |
402 | | extern const size_t h2o_httpclient__h1_size; |
403 | | |
404 | | void h2o_httpclient__h2_on_connect(h2o_httpclient_t *client, h2o_socket_t *sock, h2o_url_t *origin); |
405 | | uint32_t h2o_httpclient__h2_get_max_concurrent_streams(h2o_httpclient__h2_conn_t *conn); |
406 | | extern const size_t h2o_httpclient__h2_size; |
407 | | |
408 | | void h2o_httpclient_set_conn_properties_of_socket(h2o_socket_t *sock, h2o_httpclient_conn_properties_t *properties); |
409 | | |
410 | | #ifdef quicly_h /* create http3client.h? */ |
411 | | |
412 | | #include "h2o/http3_common.h" |
413 | | |
414 | | void h2o_httpclient_http3_notify_connection_update(h2o_quic_ctx_t *ctx, h2o_quic_conn_t *conn); |
415 | | extern quicly_stream_open_t h2o_httpclient_http3_on_stream_open; |
416 | | extern quicly_receive_datagram_frame_t h2o_httpclient_http3_on_receive_datagram_frame; |
417 | | void h2o_httpclient__connect_h3(h2o_httpclient_t **client, h2o_mem_pool_t *pool, void *data, h2o_httpclient_ctx_t *ctx, |
418 | | h2o_httpclient_connection_pool_t *connpool, h2o_url_t *target, const char *upgrade_to, |
419 | | h2o_httpclient_connect_cb cb); |
420 | | /** |
421 | | * internal API for checking if the stream is to be turned into a tunnel |
422 | | */ |
423 | | static int h2o_httpclient__tunnel_is_ready(h2o_httpclient_t *client, int status, int http_version); |
424 | | |
425 | | /* inline definitions */ |
426 | | |
427 | | inline int h2o_httpclient__tunnel_is_ready(h2o_httpclient_t *client, int status, int http_version) |
428 | 3.36k | { |
429 | 3.36k | if (client->upgrade_to != NULL) { |
430 | 0 | if (client->upgrade_to == h2o_httpclient_upgrade_to_connect && 200 <= status && status <= 299) |
431 | 0 | return 1; |
432 | 0 | if (http_version < 0x200) { |
433 | 0 | if (status == 101) |
434 | 0 | return 1; |
435 | 0 | } else { |
436 | 0 | if (200 <= status && status <= 299) |
437 | 0 | return 1; |
438 | 0 | } |
439 | 0 | } |
440 | 3.36k | return 0; |
441 | 3.36k | } Unexecuted instantiation: driver.cc:h2o_httpclient__tunnel_is_ready(st_h2o_httpclient_t*, int, int) Unexecuted instantiation: driver_common.cc:h2o_httpclient__tunnel_is_ready(st_h2o_httpclient_t*, int, int) Unexecuted instantiation: config.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: configurator.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: context.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: headers.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: request.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: util.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: access_log.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: file.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: mimemap.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: proxy.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: http1.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: connection.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: scheduler.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: stream.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: http2_debug_state.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: common.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: server.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: http3client.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: httpclient.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: absprio.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: logconf.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: compress.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: gzip.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: headers_util.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: qpack.c:h2o_httpclient__tunnel_is_ready http1client.c:h2o_httpclient__tunnel_is_ready Line | Count | Source | 428 | 3.36k | { | 429 | 3.36k | if (client->upgrade_to != NULL) { | 430 | 0 | if (client->upgrade_to == h2o_httpclient_upgrade_to_connect && 200 <= status && status <= 299) | 431 | 0 | return 1; | 432 | 0 | if (http_version < 0x200) { | 433 | 0 | if (status == 101) | 434 | 0 | return 1; | 435 | 0 | } else { | 436 | 0 | if (200 <= status && status <= 299) | 437 | 0 | return 1; | 438 | 0 | } | 439 | 0 | } | 440 | 3.36k | return 0; | 441 | 3.36k | } |
Unexecuted instantiation: http2client.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: pipe_sender.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: driver_url.cc:h2o_httpclient__tunnel_is_ready(st_h2o_httpclient_t*, int, int) Unexecuted instantiation: driver_h3.cc:h2o_httpclient__tunnel_is_ready(st_h2o_httpclient_t*, int, int) Unexecuted instantiation: errordoc.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: expires.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: fastcgi.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: h2olog.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: connect.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: redirect.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: reproxy.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: throttle_resp.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: self_trace.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: server_timing.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: status.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: events.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: memory.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: requests.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: ssl.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: durations.c:h2o_httpclient__tunnel_is_ready Unexecuted instantiation: brotli.c:h2o_httpclient__tunnel_is_ready |
442 | | |
443 | | #endif |
444 | | |
445 | | #ifdef __cplusplus |
446 | | } |
447 | | #endif |
448 | | |
449 | | #endif |