2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2015 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "nghttp2_config.h"
30 #include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 #include <sys/socket.h>
33 #endif // HAVE_SYS_SOCKET_H
36 #endif // HAVE_NETDB_H
44 #include <openssl/ssl.h>
48 #include <nghttp2/nghttp2.h>
50 #include "http-parser/http_parser.h"
54 #include "nghttp2_gzip.h"
70 nghttp2_option *http2_option;
71 size_t output_upper_thres;
73 ssize_t peer_max_concurrent_streams;
74 ssize_t header_table_size;
80 int connection_window_bits;
88 bool no_content_length;
94 enum class RequestState { INITIAL, ON_REQUEST, ON_RESPONSE, ON_COMPLETE };
96 struct RequestTiming {
97 // The point in time when request is started to be sent.
98 // Corresponds to requestStart in Resource Timing TR.
99 std::chrono::steady_clock::time_point request_start_time;
100 // The point in time when first byte of response is received.
101 // Corresponds to responseStart in Resource Timing TR.
102 std::chrono::steady_clock::time_point response_start_time;
103 // The point in time when last byte of response is received.
104 // Corresponds to responseEnd in Resource Timing TR.
105 std::chrono::steady_clock::time_point response_end_time;
107 RequestTiming() : state(RequestState::INITIAL) {}
111 // For pushed request, |uri| is empty and |u| is zero-cleared.
112 Request(const std::string &uri, const http_parser_url &u,
113 const nghttp2_data_provider *data_prd, int64_t data_length,
114 const nghttp2_priority_spec &pri_spec, int level = 0);
117 void init_inflater();
119 void init_html_parser();
120 int update_html_parser(const uint8_t *data, size_t len, int fin);
122 std::string make_reqpath() const;
124 bool is_ipv6_literal_addr() const;
126 bool response_pseudo_header_allowed(int16_t token) const;
127 bool push_request_pseudo_header_allowed(int16_t token) const;
129 Headers::value_type *get_res_header(int16_t token);
130 Headers::value_type *get_req_header(int16_t token);
132 void record_request_start_time();
133 void record_response_start_time();
134 void record_response_end_time();
138 // URI without fragment
141 nghttp2_priority_spec pri_spec;
142 RequestTiming timing;
145 // Number of bytes received from server
146 int64_t response_len;
147 nghttp2_gzip *inflater;
148 HtmlParser *html_parser;
149 const nghttp2_data_provider *data_prd;
152 // Recursion level: 0: first entity, 1: entity linked from first entity
154 http2::HeaderIndex res_hdidx;
155 // used for incoming PUSH_PROMISE
156 http2::HeaderIndex req_hdidx;
157 bool expect_final_response;
160 struct SessionTiming {
161 // The point in time when operation was started. Corresponds to
162 // startTime in Resource Timing TR, but recorded in system clock time.
163 std::chrono::system_clock::time_point system_start_time;
164 // Same as above, but recorded in steady clock time.
165 std::chrono::steady_clock::time_point start_time;
166 // The point in time when DNS resolution was completed. Corresponds
167 // to domainLookupEnd in Resource Timing TR.
168 std::chrono::steady_clock::time_point domain_lookup_end_time;
169 // The point in time when connection was established or SSL/TLS
170 // handshake was completed. Corresponds to connectEnd in Resource
172 std::chrono::steady_clock::time_point connect_end_time;
175 enum class ClientState { IDLE, CONNECTED };
178 HttpClient(const nghttp2_session_callbacks *callbacks, struct ev_loop *loop,
182 bool need_upgrade() const;
183 int resolve_host(const std::string &host, uint16_t port);
184 int initiate_connection();
198 int on_upgrade_connect();
199 int on_upgrade_read(const uint8_t *data, size_t len);
200 int on_read(const uint8_t *data, size_t len);
203 int connection_made();
205 void request_done(Request *req);
209 bool all_requests_processed() const;
210 void update_hostport();
211 bool add_request(const std::string &uri,
212 const nghttp2_data_provider *data_prd, int64_t data_length,
213 const nghttp2_priority_spec &pri_spec, int level = 0);
215 void record_start_time();
216 void record_domain_lookup_end_time();
217 void record_connect_end_time();
220 void output_har(FILE *outfile);
221 #endif // HAVE_JANSSON
223 std::vector<std::unique_ptr<Request>> reqvec;
224 // Insert path already added in reqvec to prevent multiple request
226 std::set<std::string> path_cache;
229 std::string hostport;
230 // Used for parse the HTTP upgrade response from server
231 std::unique_ptr<http_parser> htp;
232 SessionTiming timing;
237 ev_timer settings_timer;
238 std::function<int(HttpClient &)> readfn, writefn;
239 std::function<int(HttpClient &, const uint8_t *, size_t)> on_readfn;
240 std::function<int(HttpClient &)> on_writefn;
241 nghttp2_session *session;
242 const nghttp2_session_callbacks *callbacks;
243 struct ev_loop *loop;
249 // The number of completed requests, including failed ones.
251 // The number of requests that local endpoint received END_STREAM
254 // The length of settings_payload
255 size_t settings_payloadlen;
257 // The HTTP status code of the response message of HTTP Upgrade.
258 unsigned int upgrade_response_status_code;
260 // true if the response message of HTTP Upgrade request is fully
261 // received. It is not relevant the upgrade succeeds, or not.
262 bool upgrade_response_complete;
264 // SETTINGS payload sent as token68 in HTTP Upgrade
265 std::array<uint8_t, 128> settings_payload;
267 enum { ERR_CONNECT_FAIL = -100 };
270 } // namespace nghttp2