/
githubmirror
/
nghttp2
Обзор
Документация
Войти
/
githubmirror
/
nghttp2
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/nghttp.h
320 строк
10 KB
Tatsuhiro Tsujikawa
src: MSDMI part3
12 май 2026, 17:32
12 май 2026, 17:32
5d3c693
Код
Авторство
О чём код?
/* * nghttp2 - HTTP/2 C Library * * Copyright (c) 2015 Tatsuhiro Tsujikawa * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef NGHTTP_H #define NGHTTP_H #include "nghttp2_config.h" #include <sys/types.h> #ifdef HAVE_SYS_SOCKET_H # include <sys/socket.h> #endif // defined(HAVE_SYS_SOCKET_H) #ifdef HAVE_NETDB_H # include <netdb.h> #endif // defined(HAVE_NETDB_H) #include <string> #include <vector> #include <unordered_set> #include <chrono> #include <memory> #include <expected> #include "ssl_compat.h" #ifdef NGHTTP2_OPENSSL_IS_WOLFSSL # include <wolfssl/options.h> # include <wolfssl/openssl/ssl.h> #else // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL) # include <openssl/ssl.h> #endif // !defined(NGHTTP2_OPENSSL_IS_WOLFSSL) #include <ev.h> #define NGHTTP2_NO_SSIZE_T #include <nghttp2/nghttp2.h> #include "llhttp.h" #include "memchunk.h" #include "http2.h" #include "nghttp2_gzip.h" #include "template.h" #include "errors.h" namespace nghttp2 { class HtmlParser; struct Config { Config(); ~Config(); Headers headers; Headers trailer; std::vector<nghttp2_extpri> extpris; std::string certfile; std::string keyfile; std::string datafile; std::string harfile; std::string scheme_override; std::string host_override; nghttp2_option *http2_option; int64_t header_table_size{-1}; int64_t min_header_table_size{std::numeric_limits<uint32_t>::max()}; int64_t encoder_header_table_size{-1}; size_t padding{}; size_t max_concurrent_streams{100}; size_t peer_max_concurrent_streams{100}; int multiply{1}; // milliseconds ev_tstamp timeout{}; int window_bits{-1}; int connection_window_bits{-1}; int verbose{}; uint16_t port_override{}; bool null_out{}; bool remote_name{}; bool get_assets{}; bool stat{}; bool upgrade{}; bool continuation{}; bool no_content_length{}; bool hexdump{}; bool no_push{}; bool expect_continue{}; bool verify_peer{true}; bool ktls{}; }; enum class RequestState { INITIAL, ON_REQUEST, ON_RESPONSE, ON_COMPLETE }; struct RequestTiming { // The point in time when request is started to be sent. // Corresponds to requestStart in Resource Timing TR. std::chrono::steady_clock::time_point request_start_time; // The point in time when first byte of response is received. // Corresponds to responseStart in Resource Timing TR. std::chrono::steady_clock::time_point response_start_time; // The point in time when last byte of response is received. // Corresponds to responseEnd in Resource Timing TR. std::chrono::steady_clock::time_point response_end_time; RequestState state{RequestState::INITIAL}; RequestTiming() noexcept = default; }; struct Request; // forward declaration for ContinueTimer struct ContinueTimer { ContinueTimer(struct ev_loop *loop, Request *req); ~ContinueTimer(); void start(); void stop(); // Schedules an immediate run of the continue callback on the loop, if the // callback has not already been run void dispatch_continue(); struct ev_loop *loop; ev_timer timer; }; struct Request { // For pushed request, |uri| is empty and |u| is zero-cleared. Request(const std::string &uri, const urlparse_url &u, const nghttp2_data_provider2 *data_prd, int64_t data_length, const nghttp2_extpri &extpri, int level = 0); ~Request(); void init_inflater(); void init_html_parser(); std::expected<void, Error> update_html_parser(std::span<const uint8_t> data, int fin); std::string make_reqpath() const; bool is_ipv6_literal_addr() const; Headers::value_type *get_res_header(int32_t token); Headers::value_type *get_req_header(int32_t token); void record_request_start_time(); void record_response_start_time(); void record_response_end_time(); // Returns scheme taking into account overridden scheme. std::string_view get_real_scheme() const; // Returns request host, without port, taking into account // overridden host. std::string_view get_real_host() const; // Returns request port, taking into account overridden host, port, // and scheme. uint16_t get_real_port() const; Headers res_nva; Headers req_nva; std::string method; // URI without fragment std::string uri; urlparse_url u; nghttp2_extpri extpri; RequestTiming timing; int64_t data_length; int64_t data_offset{}; // Number of bytes received from server int64_t response_len{}; nghttp2_gzip *inflater{}; std::unique_ptr<HtmlParser> html_parser; const nghttp2_data_provider2 *data_prd; size_t header_buffer_size{}; int32_t stream_id{-1}; int status{}; // Recursion level: 0: first entity, 1: entity linked from first entity int level; http2::HeaderIndex res_hdidx; // used for incoming PUSH_PROMISE http2::HeaderIndex req_hdidx; bool expect_final_response{}; // only assigned if this request is using Expect/Continue std::unique_ptr<ContinueTimer> continue_timer; }; struct SessionTiming { // The point in time when operation was started. Corresponds to // startTime in Resource Timing TR, but recorded in system clock time. std::chrono::system_clock::time_point system_start_time; // Same as above, but recorded in steady clock time. std::chrono::steady_clock::time_point start_time; // The point in time when DNS resolution was completed. Corresponds // to domainLookupEnd in Resource Timing TR. std::chrono::steady_clock::time_point domain_lookup_end_time; // The point in time when connection was established or SSL/TLS // handshake was completed. Corresponds to connectEnd in Resource // Timing TR. std::chrono::steady_clock::time_point connect_end_time; }; enum class ClientState { IDLE, CONNECTED }; struct HttpClient { HttpClient(const nghttp2_session_callbacks *callbacks, struct ev_loop *loop, SSL_CTX *ssl_ctx); ~HttpClient(); bool need_upgrade() const; std::expected<void, Error> resolve_host(const std::string &host, uint16_t port); std::expected<void, Error> initiate_connection(); void disconnect(); std::expected<void, Error> noop() { return {}; } std::expected<void, Error> read_clear(); std::expected<void, Error> write_clear(); std::expected<void, Error> connected(); std::expected<void, Error> tls_handshake(); std::expected<void, Error> read_tls(); std::expected<void, Error> write_tls(); std::expected<void, Error> do_read(); std::expected<void, Error> do_write(); std::expected<void, Error> on_upgrade_connect(); std::expected<void, Error> on_upgrade_read(std::span<const uint8_t> data); std::expected<void, Error> on_read(std::span<const uint8_t> data); std::expected<void, Error> on_write(); std::expected<void, Error> connection_made(); void connect_fail(); void request_done(Request *req); void signal_write(); bool all_requests_processed() const; void update_hostport(); bool add_request(const std::string &uri, const nghttp2_data_provider2 *data_prd, int64_t data_length, const nghttp2_extpri &extpri, int level = 0); void record_start_time(); void record_domain_lookup_end_time(); void record_connect_end_time(); #ifdef HAVE_JANSSON void output_har(FILE *outfile); #endif // defined(HAVE_JANSSON) MemchunkPool mcpool; DefaultMemchunks wb; std::vector<std::unique_ptr<Request>> reqvec; // Insert path already added in reqvec to prevent multiple request // for 1 resource. std::unordered_set<std::string> path_cache; std::string scheme; std::string host; std::string hostport; // Used for parse the HTTP upgrade response from server std::unique_ptr<llhttp_t> htp; SessionTiming timing; ev_io wev; ev_io rev; ev_timer wt; ev_timer rt; ev_timer settings_timer; std::function<std::expected<void, Error>(HttpClient &)> readfn, writefn; std::function<std::expected<void, Error>(HttpClient &, std::span<const uint8_t>)> on_readfn; std::function<std::expected<void, Error>(HttpClient &)> on_writefn; nghttp2_session *session{}; const nghttp2_session_callbacks *callbacks; struct ev_loop *loop; SSL_CTX *ssl_ctx; SSL *ssl{}; addrinfo *addrs{}; addrinfo *next_addr{}; addrinfo *cur_addr{}; // The number of completed requests, including failed ones. size_t complete{}; // The number of requests that local endpoint received END_STREAM // from peer. size_t success{}; // The length of settings_payload size_t settings_payloadlen{}; ClientState state{ClientState::IDLE}; // The HTTP status code of the response message of HTTP Upgrade. unsigned int upgrade_response_status_code{}; int fd{-1}; // true if the response message of HTTP Upgrade request is fully // received. It is not relevant the upgrade succeeds, or not. bool upgrade_response_complete{}; // SETTINGS payload sent as token68 in HTTP Upgrade std::array<uint8_t, 128> settings_payload; }; } // namespace nghttp2 #endif // !defined(NGHTTP_H)