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