12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2012 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 SHRPX_HTTP2_SESSION_H 262c593315Sopenharmony_ci#define SHRPX_HTTP2_SESSION_H 272c593315Sopenharmony_ci 282c593315Sopenharmony_ci#include "shrpx.h" 292c593315Sopenharmony_ci 302c593315Sopenharmony_ci#include <unordered_set> 312c593315Sopenharmony_ci#include <memory> 322c593315Sopenharmony_ci 332c593315Sopenharmony_ci#include <openssl/ssl.h> 342c593315Sopenharmony_ci 352c593315Sopenharmony_ci#include <ev.h> 362c593315Sopenharmony_ci 372c593315Sopenharmony_ci#include <nghttp2/nghttp2.h> 382c593315Sopenharmony_ci 392c593315Sopenharmony_ci#include "llhttp.h" 402c593315Sopenharmony_ci 412c593315Sopenharmony_ci#include "shrpx_connection.h" 422c593315Sopenharmony_ci#include "buffer.h" 432c593315Sopenharmony_ci#include "template.h" 442c593315Sopenharmony_ci 452c593315Sopenharmony_ciusing namespace nghttp2; 462c593315Sopenharmony_ci 472c593315Sopenharmony_cinamespace shrpx { 482c593315Sopenharmony_ci 492c593315Sopenharmony_ciclass Http2DownstreamConnection; 502c593315Sopenharmony_ciclass Worker; 512c593315Sopenharmony_ciclass Downstream; 522c593315Sopenharmony_cistruct DownstreamAddrGroup; 532c593315Sopenharmony_cistruct DownstreamAddr; 542c593315Sopenharmony_cistruct DNSQuery; 552c593315Sopenharmony_ci 562c593315Sopenharmony_cistruct StreamData { 572c593315Sopenharmony_ci StreamData *dlnext, *dlprev; 582c593315Sopenharmony_ci Http2DownstreamConnection *dconn; 592c593315Sopenharmony_ci}; 602c593315Sopenharmony_ci 612c593315Sopenharmony_cienum class FreelistZone { 622c593315Sopenharmony_ci // Http2Session object is not linked in any freelist. 632c593315Sopenharmony_ci NONE, 642c593315Sopenharmony_ci // Http2Session object is linked in address scope 652c593315Sopenharmony_ci // http2_extra_freelist. 662c593315Sopenharmony_ci EXTRA, 672c593315Sopenharmony_ci // Http2Session object is about to be deleted, and it does not 682c593315Sopenharmony_ci // belong to any linked list. 692c593315Sopenharmony_ci GONE 702c593315Sopenharmony_ci}; 712c593315Sopenharmony_ci 722c593315Sopenharmony_cienum class Http2SessionState { 732c593315Sopenharmony_ci // Disconnected 742c593315Sopenharmony_ci DISCONNECTED, 752c593315Sopenharmony_ci // Connecting proxy and making CONNECT request 762c593315Sopenharmony_ci PROXY_CONNECTING, 772c593315Sopenharmony_ci // Tunnel is established with proxy 782c593315Sopenharmony_ci PROXY_CONNECTED, 792c593315Sopenharmony_ci // Establishing tunnel is failed 802c593315Sopenharmony_ci PROXY_FAILED, 812c593315Sopenharmony_ci // Connecting to downstream and/or performing SSL/TLS handshake 822c593315Sopenharmony_ci CONNECTING, 832c593315Sopenharmony_ci // Connected to downstream 842c593315Sopenharmony_ci CONNECTED, 852c593315Sopenharmony_ci // Connection is started to fail 862c593315Sopenharmony_ci CONNECT_FAILING, 872c593315Sopenharmony_ci // Resolving host name 882c593315Sopenharmony_ci RESOLVING_NAME, 892c593315Sopenharmony_ci}; 902c593315Sopenharmony_ci 912c593315Sopenharmony_cienum class ConnectionCheck { 922c593315Sopenharmony_ci // Connection checking is not required 932c593315Sopenharmony_ci NONE, 942c593315Sopenharmony_ci // Connection checking is required 952c593315Sopenharmony_ci REQUIRED, 962c593315Sopenharmony_ci // Connection checking has been started 972c593315Sopenharmony_ci STARTED, 982c593315Sopenharmony_ci}; 992c593315Sopenharmony_ci 1002c593315Sopenharmony_ciclass Http2Session { 1012c593315Sopenharmony_cipublic: 1022c593315Sopenharmony_ci Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, Worker *worker, 1032c593315Sopenharmony_ci const std::shared_ptr<DownstreamAddrGroup> &group, 1042c593315Sopenharmony_ci DownstreamAddr *addr); 1052c593315Sopenharmony_ci ~Http2Session(); 1062c593315Sopenharmony_ci 1072c593315Sopenharmony_ci // If hard is true, all pending requests are abandoned and 1082c593315Sopenharmony_ci // associated ClientHandlers will be deleted. 1092c593315Sopenharmony_ci int disconnect(bool hard = false); 1102c593315Sopenharmony_ci int initiate_connection(); 1112c593315Sopenharmony_ci int resolve_name(); 1122c593315Sopenharmony_ci 1132c593315Sopenharmony_ci void add_downstream_connection(Http2DownstreamConnection *dconn); 1142c593315Sopenharmony_ci void remove_downstream_connection(Http2DownstreamConnection *dconn); 1152c593315Sopenharmony_ci 1162c593315Sopenharmony_ci void remove_stream_data(StreamData *sd); 1172c593315Sopenharmony_ci 1182c593315Sopenharmony_ci int submit_request(Http2DownstreamConnection *dconn, const nghttp2_nv *nva, 1192c593315Sopenharmony_ci size_t nvlen, const nghttp2_data_provider *data_prd); 1202c593315Sopenharmony_ci 1212c593315Sopenharmony_ci int submit_rst_stream(int32_t stream_id, uint32_t error_code); 1222c593315Sopenharmony_ci 1232c593315Sopenharmony_ci int terminate_session(uint32_t error_code); 1242c593315Sopenharmony_ci 1252c593315Sopenharmony_ci nghttp2_session *get_session() const; 1262c593315Sopenharmony_ci 1272c593315Sopenharmony_ci int resume_data(Http2DownstreamConnection *dconn); 1282c593315Sopenharmony_ci 1292c593315Sopenharmony_ci int connection_made(); 1302c593315Sopenharmony_ci 1312c593315Sopenharmony_ci int do_read(); 1322c593315Sopenharmony_ci int do_write(); 1332c593315Sopenharmony_ci 1342c593315Sopenharmony_ci int on_read(const uint8_t *data, size_t datalen); 1352c593315Sopenharmony_ci int on_write(); 1362c593315Sopenharmony_ci 1372c593315Sopenharmony_ci int connected(); 1382c593315Sopenharmony_ci int read_clear(); 1392c593315Sopenharmony_ci int write_clear(); 1402c593315Sopenharmony_ci int tls_handshake(); 1412c593315Sopenharmony_ci int read_tls(); 1422c593315Sopenharmony_ci int write_tls(); 1432c593315Sopenharmony_ci // This is a special write function which just stop write event 1442c593315Sopenharmony_ci // watcher. 1452c593315Sopenharmony_ci int write_void(); 1462c593315Sopenharmony_ci 1472c593315Sopenharmony_ci int downstream_read_proxy(const uint8_t *data, size_t datalen); 1482c593315Sopenharmony_ci int downstream_connect_proxy(); 1492c593315Sopenharmony_ci 1502c593315Sopenharmony_ci int downstream_read(const uint8_t *data, size_t datalen); 1512c593315Sopenharmony_ci int downstream_write(); 1522c593315Sopenharmony_ci 1532c593315Sopenharmony_ci int noop(); 1542c593315Sopenharmony_ci int read_noop(const uint8_t *data, size_t datalen); 1552c593315Sopenharmony_ci int write_noop(); 1562c593315Sopenharmony_ci 1572c593315Sopenharmony_ci void signal_write(); 1582c593315Sopenharmony_ci 1592c593315Sopenharmony_ci struct ev_loop *get_loop() const; 1602c593315Sopenharmony_ci 1612c593315Sopenharmony_ci ev_io *get_wev(); 1622c593315Sopenharmony_ci 1632c593315Sopenharmony_ci Http2SessionState get_state() const; 1642c593315Sopenharmony_ci void set_state(Http2SessionState state); 1652c593315Sopenharmony_ci 1662c593315Sopenharmony_ci void start_settings_timer(); 1672c593315Sopenharmony_ci void stop_settings_timer(); 1682c593315Sopenharmony_ci 1692c593315Sopenharmony_ci SSL *get_ssl() const; 1702c593315Sopenharmony_ci 1712c593315Sopenharmony_ci int consume(int32_t stream_id, size_t len); 1722c593315Sopenharmony_ci 1732c593315Sopenharmony_ci // Returns true if request can be issued on downstream connection. 1742c593315Sopenharmony_ci bool can_push_request(const Downstream *downstream) const; 1752c593315Sopenharmony_ci // Initiates the connection checking if downstream connection has 1762c593315Sopenharmony_ci // been established and connection checking is required. 1772c593315Sopenharmony_ci void start_checking_connection(); 1782c593315Sopenharmony_ci // Resets connection check timer to timeout |t|. After timeout, we 1792c593315Sopenharmony_ci // require connection checking. If connection checking is already 1802c593315Sopenharmony_ci // enabled, this timeout is for PING ACK timeout. 1812c593315Sopenharmony_ci void reset_connection_check_timer(ev_tstamp t); 1822c593315Sopenharmony_ci void reset_connection_check_timer_if_not_checking(); 1832c593315Sopenharmony_ci // Signals that connection is alive. Internally 1842c593315Sopenharmony_ci // reset_connection_check_timer() is called. 1852c593315Sopenharmony_ci void connection_alive(); 1862c593315Sopenharmony_ci // Change connection check state. 1872c593315Sopenharmony_ci void set_connection_check_state(ConnectionCheck state); 1882c593315Sopenharmony_ci ConnectionCheck get_connection_check_state() const; 1892c593315Sopenharmony_ci 1902c593315Sopenharmony_ci bool should_hard_fail() const; 1912c593315Sopenharmony_ci 1922c593315Sopenharmony_ci void submit_pending_requests(); 1932c593315Sopenharmony_ci 1942c593315Sopenharmony_ci DownstreamAddr *get_addr() const; 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_ci const std::shared_ptr<DownstreamAddrGroup> &get_downstream_addr_group() const; 1972c593315Sopenharmony_ci 1982c593315Sopenharmony_ci int handle_downstream_push_promise(Downstream *downstream, 1992c593315Sopenharmony_ci int32_t promised_stream_id); 2002c593315Sopenharmony_ci int handle_downstream_push_promise_complete(Downstream *downstream, 2012c593315Sopenharmony_ci Downstream *promised_downstream); 2022c593315Sopenharmony_ci 2032c593315Sopenharmony_ci // Returns number of downstream connections, including pushed 2042c593315Sopenharmony_ci // streams. 2052c593315Sopenharmony_ci size_t get_num_dconns() const; 2062c593315Sopenharmony_ci 2072c593315Sopenharmony_ci // Adds to group scope http2_avail_freelist. 2082c593315Sopenharmony_ci void add_to_avail_freelist(); 2092c593315Sopenharmony_ci // Adds to address scope http2_extra_freelist. 2102c593315Sopenharmony_ci void add_to_extra_freelist(); 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_ci // Removes this object from any freelist. If this object is not 2132c593315Sopenharmony_ci // linked from any freelist, this function does nothing. 2142c593315Sopenharmony_ci void remove_from_freelist(); 2152c593315Sopenharmony_ci 2162c593315Sopenharmony_ci // Removes this object form any freelist, and marks this object as 2172c593315Sopenharmony_ci // not schedulable. 2182c593315Sopenharmony_ci void exclude_from_scheduling(); 2192c593315Sopenharmony_ci 2202c593315Sopenharmony_ci // Returns true if the maximum concurrency is reached. In other 2212c593315Sopenharmony_ci // words, the number of currently participated streams in this 2222c593315Sopenharmony_ci // session is equal or greater than the max concurrent streams limit 2232c593315Sopenharmony_ci // advertised by server. If |extra| is nonzero, it is added to the 2242c593315Sopenharmony_ci // number of current concurrent streams when comparing against 2252c593315Sopenharmony_ci // server initiated concurrency limit. 2262c593315Sopenharmony_ci bool max_concurrency_reached(size_t extra = 0) const; 2272c593315Sopenharmony_ci 2282c593315Sopenharmony_ci DefaultMemchunks *get_request_buf(); 2292c593315Sopenharmony_ci 2302c593315Sopenharmony_ci void on_timeout(); 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci // This is called periodically using ev_prepare watcher, and if 2332c593315Sopenharmony_ci // group_ is retired (backend has been replaced), send GOAWAY to 2342c593315Sopenharmony_ci // shutdown the connection. 2352c593315Sopenharmony_ci void check_retire(); 2362c593315Sopenharmony_ci 2372c593315Sopenharmony_ci // Returns address used to connect to backend. Could be nullptr. 2382c593315Sopenharmony_ci const Address *get_raddr() const; 2392c593315Sopenharmony_ci 2402c593315Sopenharmony_ci // This is called when SETTINGS frame without ACK flag set is 2412c593315Sopenharmony_ci // received. 2422c593315Sopenharmony_ci void on_settings_received(const nghttp2_frame *frame); 2432c593315Sopenharmony_ci 2442c593315Sopenharmony_ci bool get_allow_connect_proto() const; 2452c593315Sopenharmony_ci 2462c593315Sopenharmony_ci using ReadBuf = Buffer<8_k>; 2472c593315Sopenharmony_ci 2482c593315Sopenharmony_ci Http2Session *dlnext, *dlprev; 2492c593315Sopenharmony_ci 2502c593315Sopenharmony_ciprivate: 2512c593315Sopenharmony_ci Connection conn_; 2522c593315Sopenharmony_ci DefaultMemchunks wb_; 2532c593315Sopenharmony_ci ev_timer settings_timer_; 2542c593315Sopenharmony_ci // This timer has 2 purpose: when it first timeout, set 2552c593315Sopenharmony_ci // connection_check_state_ = ConnectionCheck::REQUIRED. After 2562c593315Sopenharmony_ci // connection check has started, this timer is started again and 2572c593315Sopenharmony_ci // traps PING ACK timeout. 2582c593315Sopenharmony_ci ev_timer connchk_timer_; 2592c593315Sopenharmony_ci // timer to initiate connection. usually, this fires immediately. 2602c593315Sopenharmony_ci ev_timer initiate_connection_timer_; 2612c593315Sopenharmony_ci ev_prepare prep_; 2622c593315Sopenharmony_ci DList<Http2DownstreamConnection> dconns_; 2632c593315Sopenharmony_ci DList<StreamData> streams_; 2642c593315Sopenharmony_ci std::function<int(Http2Session &)> read_, write_; 2652c593315Sopenharmony_ci std::function<int(Http2Session &, const uint8_t *, size_t)> on_read_; 2662c593315Sopenharmony_ci std::function<int(Http2Session &)> on_write_; 2672c593315Sopenharmony_ci // Used to parse the response from HTTP proxy 2682c593315Sopenharmony_ci std::unique_ptr<llhttp_t> proxy_htp_; 2692c593315Sopenharmony_ci Worker *worker_; 2702c593315Sopenharmony_ci // NULL if no TLS is configured 2712c593315Sopenharmony_ci SSL_CTX *ssl_ctx_; 2722c593315Sopenharmony_ci std::shared_ptr<DownstreamAddrGroup> group_; 2732c593315Sopenharmony_ci // Address of remote endpoint 2742c593315Sopenharmony_ci DownstreamAddr *addr_; 2752c593315Sopenharmony_ci nghttp2_session *session_; 2762c593315Sopenharmony_ci // Actual remote address used to contact backend. This is initially 2772c593315Sopenharmony_ci // nullptr, and may point to either &addr_->addr, 2782c593315Sopenharmony_ci // resolved_addr_.get(), or HTTP proxy's address structure. 2792c593315Sopenharmony_ci const Address *raddr_; 2802c593315Sopenharmony_ci // Resolved IP address if dns parameter is used 2812c593315Sopenharmony_ci std::unique_ptr<Address> resolved_addr_; 2822c593315Sopenharmony_ci std::unique_ptr<DNSQuery> dns_query_; 2832c593315Sopenharmony_ci Http2SessionState state_; 2842c593315Sopenharmony_ci ConnectionCheck connection_check_state_; 2852c593315Sopenharmony_ci FreelistZone freelist_zone_; 2862c593315Sopenharmony_ci // true if SETTINGS without ACK is received from peer. 2872c593315Sopenharmony_ci bool settings_recved_; 2882c593315Sopenharmony_ci // true if peer enables RFC 8441 CONNECT protocol. 2892c593315Sopenharmony_ci bool allow_connect_proto_; 2902c593315Sopenharmony_ci}; 2912c593315Sopenharmony_ci 2922c593315Sopenharmony_cinghttp2_session_callbacks *create_http2_downstream_callbacks(); 2932c593315Sopenharmony_ci 2942c593315Sopenharmony_ci} // namespace shrpx 2952c593315Sopenharmony_ci 2962c593315Sopenharmony_ci#endif // SHRPX_HTTP2_SESSION_H 297