12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2015 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#ifndef NGHTTP_H 262c593315Sopenharmony_ci#define NGHTTP_H 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci#include "nghttp2_config.h" 292c593315Sopenharmony_ci 302c593315Sopenharmony_ci#include <sys/types.h> 312c593315Sopenharmony_ci#ifdef HAVE_SYS_SOCKET_H 322c593315Sopenharmony_ci# include <sys/socket.h> 332c593315Sopenharmony_ci#endif // HAVE_SYS_SOCKET_H 342c593315Sopenharmony_ci#ifdef HAVE_NETDB_H 352c593315Sopenharmony_ci# include <netdb.h> 362c593315Sopenharmony_ci#endif // HAVE_NETDB_H 372c593315Sopenharmony_ci 382c593315Sopenharmony_ci#include <string> 392c593315Sopenharmony_ci#include <vector> 402c593315Sopenharmony_ci#include <set> 412c593315Sopenharmony_ci#include <chrono> 422c593315Sopenharmony_ci#include <memory> 432c593315Sopenharmony_ci 442c593315Sopenharmony_ci#include <openssl/ssl.h> 452c593315Sopenharmony_ci 462c593315Sopenharmony_ci#include <ev.h> 472c593315Sopenharmony_ci 482c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 492c593315Sopenharmony_ci 502c593315Sopenharmony_ci#include "llhttp.h" 512c593315Sopenharmony_ci 522c593315Sopenharmony_ci#include "memchunk.h" 532c593315Sopenharmony_ci#include "http2.h" 542c593315Sopenharmony_ci#include "nghttp2_gzip.h" 552c593315Sopenharmony_ci#include "template.h" 562c593315Sopenharmony_ci 572c593315Sopenharmony_cinamespace nghttp2 { 582c593315Sopenharmony_ci 592c593315Sopenharmony_ciclass HtmlParser; 602c593315Sopenharmony_ci 612c593315Sopenharmony_cistruct Config { 622c593315Sopenharmony_ci Config(); 632c593315Sopenharmony_ci ~Config(); 642c593315Sopenharmony_ci 652c593315Sopenharmony_ci Headers headers; 662c593315Sopenharmony_ci Headers trailer; 672c593315Sopenharmony_ci std::vector<int32_t> weight; 682c593315Sopenharmony_ci std::string certfile; 692c593315Sopenharmony_ci std::string keyfile; 702c593315Sopenharmony_ci std::string datafile; 712c593315Sopenharmony_ci std::string harfile; 722c593315Sopenharmony_ci std::string scheme_override; 732c593315Sopenharmony_ci std::string host_override; 742c593315Sopenharmony_ci nghttp2_option *http2_option; 752c593315Sopenharmony_ci int64_t header_table_size; 762c593315Sopenharmony_ci int64_t min_header_table_size; 772c593315Sopenharmony_ci int64_t encoder_header_table_size; 782c593315Sopenharmony_ci size_t padding; 792c593315Sopenharmony_ci size_t max_concurrent_streams; 802c593315Sopenharmony_ci ssize_t peer_max_concurrent_streams; 812c593315Sopenharmony_ci int multiply; 822c593315Sopenharmony_ci // milliseconds 832c593315Sopenharmony_ci ev_tstamp timeout; 842c593315Sopenharmony_ci int window_bits; 852c593315Sopenharmony_ci int connection_window_bits; 862c593315Sopenharmony_ci int verbose; 872c593315Sopenharmony_ci uint16_t port_override; 882c593315Sopenharmony_ci bool null_out; 892c593315Sopenharmony_ci bool remote_name; 902c593315Sopenharmony_ci bool get_assets; 912c593315Sopenharmony_ci bool stat; 922c593315Sopenharmony_ci bool upgrade; 932c593315Sopenharmony_ci bool continuation; 942c593315Sopenharmony_ci bool no_content_length; 952c593315Sopenharmony_ci bool no_dep; 962c593315Sopenharmony_ci bool hexdump; 972c593315Sopenharmony_ci bool no_push; 982c593315Sopenharmony_ci bool expect_continue; 992c593315Sopenharmony_ci bool verify_peer; 1002c593315Sopenharmony_ci bool ktls; 1012c593315Sopenharmony_ci bool no_rfc7540_pri; 1022c593315Sopenharmony_ci}; 1032c593315Sopenharmony_ci 1042c593315Sopenharmony_cienum class RequestState { INITIAL, ON_REQUEST, ON_RESPONSE, ON_COMPLETE }; 1052c593315Sopenharmony_ci 1062c593315Sopenharmony_cistruct RequestTiming { 1072c593315Sopenharmony_ci // The point in time when request is started to be sent. 1082c593315Sopenharmony_ci // Corresponds to requestStart in Resource Timing TR. 1092c593315Sopenharmony_ci std::chrono::steady_clock::time_point request_start_time; 1102c593315Sopenharmony_ci // The point in time when first byte of response is received. 1112c593315Sopenharmony_ci // Corresponds to responseStart in Resource Timing TR. 1122c593315Sopenharmony_ci std::chrono::steady_clock::time_point response_start_time; 1132c593315Sopenharmony_ci // The point in time when last byte of response is received. 1142c593315Sopenharmony_ci // Corresponds to responseEnd in Resource Timing TR. 1152c593315Sopenharmony_ci std::chrono::steady_clock::time_point response_end_time; 1162c593315Sopenharmony_ci RequestState state; 1172c593315Sopenharmony_ci RequestTiming() : state(RequestState::INITIAL) {} 1182c593315Sopenharmony_ci}; 1192c593315Sopenharmony_ci 1202c593315Sopenharmony_cistruct Request; // forward declaration for ContinueTimer 1212c593315Sopenharmony_ci 1222c593315Sopenharmony_cistruct ContinueTimer { 1232c593315Sopenharmony_ci ContinueTimer(struct ev_loop *loop, Request *req); 1242c593315Sopenharmony_ci ~ContinueTimer(); 1252c593315Sopenharmony_ci 1262c593315Sopenharmony_ci void start(); 1272c593315Sopenharmony_ci void stop(); 1282c593315Sopenharmony_ci 1292c593315Sopenharmony_ci // Schedules an immediate run of the continue callback on the loop, if the 1302c593315Sopenharmony_ci // callback has not already been run 1312c593315Sopenharmony_ci void dispatch_continue(); 1322c593315Sopenharmony_ci 1332c593315Sopenharmony_ci struct ev_loop *loop; 1342c593315Sopenharmony_ci ev_timer timer; 1352c593315Sopenharmony_ci}; 1362c593315Sopenharmony_ci 1372c593315Sopenharmony_cistruct Request { 1382c593315Sopenharmony_ci // For pushed request, |uri| is empty and |u| is zero-cleared. 1392c593315Sopenharmony_ci Request(const std::string &uri, const http_parser_url &u, 1402c593315Sopenharmony_ci const nghttp2_data_provider *data_prd, int64_t data_length, 1412c593315Sopenharmony_ci const nghttp2_priority_spec &pri_spec, int level = 0); 1422c593315Sopenharmony_ci ~Request(); 1432c593315Sopenharmony_ci 1442c593315Sopenharmony_ci void init_inflater(); 1452c593315Sopenharmony_ci 1462c593315Sopenharmony_ci void init_html_parser(); 1472c593315Sopenharmony_ci int update_html_parser(const uint8_t *data, size_t len, int fin); 1482c593315Sopenharmony_ci 1492c593315Sopenharmony_ci std::string make_reqpath() const; 1502c593315Sopenharmony_ci 1512c593315Sopenharmony_ci bool is_ipv6_literal_addr() const; 1522c593315Sopenharmony_ci 1532c593315Sopenharmony_ci Headers::value_type *get_res_header(int32_t token); 1542c593315Sopenharmony_ci Headers::value_type *get_req_header(int32_t token); 1552c593315Sopenharmony_ci 1562c593315Sopenharmony_ci void record_request_start_time(); 1572c593315Sopenharmony_ci void record_response_start_time(); 1582c593315Sopenharmony_ci void record_response_end_time(); 1592c593315Sopenharmony_ci 1602c593315Sopenharmony_ci // Returns scheme taking into account overridden scheme. 1612c593315Sopenharmony_ci StringRef get_real_scheme() const; 1622c593315Sopenharmony_ci // Returns request host, without port, taking into account 1632c593315Sopenharmony_ci // overridden host. 1642c593315Sopenharmony_ci StringRef get_real_host() const; 1652c593315Sopenharmony_ci // Returns request port, taking into account overridden host, port, 1662c593315Sopenharmony_ci // and scheme. 1672c593315Sopenharmony_ci uint16_t get_real_port() const; 1682c593315Sopenharmony_ci 1692c593315Sopenharmony_ci Headers res_nva; 1702c593315Sopenharmony_ci Headers req_nva; 1712c593315Sopenharmony_ci std::string method; 1722c593315Sopenharmony_ci // URI without fragment 1732c593315Sopenharmony_ci std::string uri; 1742c593315Sopenharmony_ci http_parser_url u; 1752c593315Sopenharmony_ci nghttp2_priority_spec pri_spec; 1762c593315Sopenharmony_ci RequestTiming timing; 1772c593315Sopenharmony_ci int64_t data_length; 1782c593315Sopenharmony_ci int64_t data_offset; 1792c593315Sopenharmony_ci // Number of bytes received from server 1802c593315Sopenharmony_ci int64_t response_len; 1812c593315Sopenharmony_ci nghttp2_gzip *inflater; 1822c593315Sopenharmony_ci std::unique_ptr<HtmlParser> html_parser; 1832c593315Sopenharmony_ci const nghttp2_data_provider *data_prd; 1842c593315Sopenharmony_ci size_t header_buffer_size; 1852c593315Sopenharmony_ci int32_t stream_id; 1862c593315Sopenharmony_ci int status; 1872c593315Sopenharmony_ci // Recursion level: 0: first entity, 1: entity linked from first entity 1882c593315Sopenharmony_ci int level; 1892c593315Sopenharmony_ci http2::HeaderIndex res_hdidx; 1902c593315Sopenharmony_ci // used for incoming PUSH_PROMISE 1912c593315Sopenharmony_ci http2::HeaderIndex req_hdidx; 1922c593315Sopenharmony_ci bool expect_final_response; 1932c593315Sopenharmony_ci // only assigned if this request is using Expect/Continue 1942c593315Sopenharmony_ci std::unique_ptr<ContinueTimer> continue_timer; 1952c593315Sopenharmony_ci}; 1962c593315Sopenharmony_ci 1972c593315Sopenharmony_cistruct SessionTiming { 1982c593315Sopenharmony_ci // The point in time when operation was started. Corresponds to 1992c593315Sopenharmony_ci // startTime in Resource Timing TR, but recorded in system clock time. 2002c593315Sopenharmony_ci std::chrono::system_clock::time_point system_start_time; 2012c593315Sopenharmony_ci // Same as above, but recorded in steady clock time. 2022c593315Sopenharmony_ci std::chrono::steady_clock::time_point start_time; 2032c593315Sopenharmony_ci // The point in time when DNS resolution was completed. Corresponds 2042c593315Sopenharmony_ci // to domainLookupEnd in Resource Timing TR. 2052c593315Sopenharmony_ci std::chrono::steady_clock::time_point domain_lookup_end_time; 2062c593315Sopenharmony_ci // The point in time when connection was established or SSL/TLS 2072c593315Sopenharmony_ci // handshake was completed. Corresponds to connectEnd in Resource 2082c593315Sopenharmony_ci // Timing TR. 2092c593315Sopenharmony_ci std::chrono::steady_clock::time_point connect_end_time; 2102c593315Sopenharmony_ci}; 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_cienum class ClientState { IDLE, CONNECTED }; 2132c593315Sopenharmony_ci 2142c593315Sopenharmony_cistruct HttpClient { 2152c593315Sopenharmony_ci HttpClient(const nghttp2_session_callbacks *callbacks, struct ev_loop *loop, 2162c593315Sopenharmony_ci SSL_CTX *ssl_ctx); 2172c593315Sopenharmony_ci ~HttpClient(); 2182c593315Sopenharmony_ci 2192c593315Sopenharmony_ci bool need_upgrade() const; 2202c593315Sopenharmony_ci int resolve_host(const std::string &host, uint16_t port); 2212c593315Sopenharmony_ci int initiate_connection(); 2222c593315Sopenharmony_ci void disconnect(); 2232c593315Sopenharmony_ci 2242c593315Sopenharmony_ci int noop(); 2252c593315Sopenharmony_ci int read_clear(); 2262c593315Sopenharmony_ci int write_clear(); 2272c593315Sopenharmony_ci int connected(); 2282c593315Sopenharmony_ci int tls_handshake(); 2292c593315Sopenharmony_ci int read_tls(); 2302c593315Sopenharmony_ci int write_tls(); 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci int do_read(); 2332c593315Sopenharmony_ci int do_write(); 2342c593315Sopenharmony_ci 2352c593315Sopenharmony_ci int on_upgrade_connect(); 2362c593315Sopenharmony_ci int on_upgrade_read(const uint8_t *data, size_t len); 2372c593315Sopenharmony_ci int on_read(const uint8_t *data, size_t len); 2382c593315Sopenharmony_ci int on_write(); 2392c593315Sopenharmony_ci 2402c593315Sopenharmony_ci int connection_made(); 2412c593315Sopenharmony_ci void connect_fail(); 2422c593315Sopenharmony_ci void request_done(Request *req); 2432c593315Sopenharmony_ci 2442c593315Sopenharmony_ci void signal_write(); 2452c593315Sopenharmony_ci 2462c593315Sopenharmony_ci bool all_requests_processed() const; 2472c593315Sopenharmony_ci void update_hostport(); 2482c593315Sopenharmony_ci bool add_request(const std::string &uri, 2492c593315Sopenharmony_ci const nghttp2_data_provider *data_prd, int64_t data_length, 2502c593315Sopenharmony_ci const nghttp2_priority_spec &pri_spec, int level = 0); 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_ci void record_start_time(); 2532c593315Sopenharmony_ci void record_domain_lookup_end_time(); 2542c593315Sopenharmony_ci void record_connect_end_time(); 2552c593315Sopenharmony_ci 2562c593315Sopenharmony_ci#ifdef HAVE_JANSSON 2572c593315Sopenharmony_ci void output_har(FILE *outfile); 2582c593315Sopenharmony_ci#endif // HAVE_JANSSON 2592c593315Sopenharmony_ci 2602c593315Sopenharmony_ci MemchunkPool mcpool; 2612c593315Sopenharmony_ci DefaultMemchunks wb; 2622c593315Sopenharmony_ci std::vector<std::unique_ptr<Request>> reqvec; 2632c593315Sopenharmony_ci // Insert path already added in reqvec to prevent multiple request 2642c593315Sopenharmony_ci // for 1 resource. 2652c593315Sopenharmony_ci std::set<std::string> path_cache; 2662c593315Sopenharmony_ci std::string scheme; 2672c593315Sopenharmony_ci std::string host; 2682c593315Sopenharmony_ci std::string hostport; 2692c593315Sopenharmony_ci // Used for parse the HTTP upgrade response from server 2702c593315Sopenharmony_ci std::unique_ptr<llhttp_t> htp; 2712c593315Sopenharmony_ci SessionTiming timing; 2722c593315Sopenharmony_ci ev_io wev; 2732c593315Sopenharmony_ci ev_io rev; 2742c593315Sopenharmony_ci ev_timer wt; 2752c593315Sopenharmony_ci ev_timer rt; 2762c593315Sopenharmony_ci ev_timer settings_timer; 2772c593315Sopenharmony_ci std::function<int(HttpClient &)> readfn, writefn; 2782c593315Sopenharmony_ci std::function<int(HttpClient &, const uint8_t *, size_t)> on_readfn; 2792c593315Sopenharmony_ci std::function<int(HttpClient &)> on_writefn; 2802c593315Sopenharmony_ci nghttp2_session *session; 2812c593315Sopenharmony_ci const nghttp2_session_callbacks *callbacks; 2822c593315Sopenharmony_ci struct ev_loop *loop; 2832c593315Sopenharmony_ci SSL_CTX *ssl_ctx; 2842c593315Sopenharmony_ci SSL *ssl; 2852c593315Sopenharmony_ci addrinfo *addrs; 2862c593315Sopenharmony_ci addrinfo *next_addr; 2872c593315Sopenharmony_ci addrinfo *cur_addr; 2882c593315Sopenharmony_ci // The number of completed requests, including failed ones. 2892c593315Sopenharmony_ci size_t complete; 2902c593315Sopenharmony_ci // The number of requests that local endpoint received END_STREAM 2912c593315Sopenharmony_ci // from peer. 2922c593315Sopenharmony_ci size_t success; 2932c593315Sopenharmony_ci // The length of settings_payload 2942c593315Sopenharmony_ci size_t settings_payloadlen; 2952c593315Sopenharmony_ci ClientState state; 2962c593315Sopenharmony_ci // The HTTP status code of the response message of HTTP Upgrade. 2972c593315Sopenharmony_ci unsigned int upgrade_response_status_code; 2982c593315Sopenharmony_ci int fd; 2992c593315Sopenharmony_ci // true if the response message of HTTP Upgrade request is fully 3002c593315Sopenharmony_ci // received. It is not relevant the upgrade succeeds, or not. 3012c593315Sopenharmony_ci bool upgrade_response_complete; 3022c593315Sopenharmony_ci // SETTINGS payload sent as token68 in HTTP Upgrade 3032c593315Sopenharmony_ci std::array<uint8_t, 128> settings_payload; 3042c593315Sopenharmony_ci 3052c593315Sopenharmony_ci enum { ERR_CONNECT_FAIL = -100 }; 3062c593315Sopenharmony_ci}; 3072c593315Sopenharmony_ci 3082c593315Sopenharmony_ci} // namespace nghttp2 3092c593315Sopenharmony_ci 3102c593315Sopenharmony_ci#endif // NGHTTP_H 311