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