| // Copyright 2019 The Chromium Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_ | 
 | #define QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_ | 
 |  | 
 | #include <sys/types.h> | 
 |  | 
 | #include <cstdint> | 
 | #include <limits> | 
 | #include <list> | 
 | #include <memory> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h" | 
 | #include "quiche/quic/core/crypto/quic_crypto_server_config.h" | 
 | #include "quiche/quic/core/frames/quic_connection_close_frame.h" | 
 | #include "quiche/quic/core/http/http_frames.h" | 
 | #include "quiche/quic/core/http/quic_spdy_session.h" | 
 | #include "quiche/quic/core/http/quic_spdy_stream.h" | 
 | #include "quiche/quic/core/io/quic_event_loop.h" | 
 | #include "quiche/quic/core/quic_config.h" | 
 | #include "quiche/quic/core/quic_connection.h" | 
 | #include "quiche/quic/core/quic_crypto_server_stream_base.h" | 
 | #include "quiche/quic/core/quic_session.h" | 
 | #include "quiche/quic/core/quic_time.h" | 
 | #include "quiche/quic/core/quic_types.h" | 
 | #include "quiche/quic/core/quic_udp_socket.h" | 
 | #include "quiche/quic/core/quic_versions.h" | 
 | #include "quiche/quic/masque/masque_server_backend.h" | 
 | #include "quiche/quic/masque/masque_utils.h" | 
 | #include "quiche/quic/platform/api/quic_export.h" | 
 | #include "quiche/quic/platform/api/quic_ip_address.h" | 
 | #include "quiche/quic/platform/api/quic_socket_address.h" | 
 | #include "quiche/quic/tools/quic_backend_response.h" | 
 | #include "quiche/quic/tools/quic_simple_server_backend.h" | 
 | #include "quiche/quic/tools/quic_simple_server_session.h" | 
 | #include "quiche/common/capsule.h" | 
 | #include "quiche/common/http/http_header_block.h" | 
 |  | 
 | namespace quic { | 
 |  | 
 | // QUIC server session for connection to MASQUE proxy. | 
 | class QUIC_NO_EXPORT MasqueServerSession | 
 |     : public QuicSimpleServerSession, | 
 |       public MasqueServerBackend::BackendClient, | 
 |       public QuicSocketEventListener { | 
 |  public: | 
 |   using ContextId = uint64_t; | 
 |   constexpr static ContextId kInvalidContextId = | 
 |       std::numeric_limits<uint64_t>::max(); | 
 |  | 
 |   explicit MasqueServerSession( | 
 |       MasqueMode masque_mode, const QuicConfig& config, | 
 |       const ParsedQuicVersionVector& supported_versions, | 
 |       QuicConnection* connection, QuicSession::Visitor* visitor, | 
 |       QuicEventLoop* event_loop, QuicCryptoServerStreamBase::Helper* helper, | 
 |       const QuicCryptoServerConfig* crypto_config, | 
 |       QuicCompressedCertsCache* compressed_certs_cache, | 
 |       MasqueServerBackend* masque_server_backend); | 
 |  | 
 |   // Disallow copy and assign. | 
 |   MasqueServerSession(const MasqueServerSession&) = delete; | 
 |   MasqueServerSession& operator=(const MasqueServerSession&) = delete; | 
 |  | 
 |   // From QuicSession. | 
 |   void OnMessageAcked(QuicMessageId message_id, | 
 |                       QuicTime receive_timestamp) override; | 
 |   void OnMessageLost(QuicMessageId message_id) override; | 
 |   void OnConnectionClosed(const QuicConnectionCloseFrame& frame, | 
 |                           ConnectionCloseSource source) override; | 
 |   void OnStreamClosed(QuicStreamId stream_id) override; | 
 |  | 
 |   // From MasqueServerBackend::BackendClient. | 
 |   std::unique_ptr<QuicBackendResponse> HandleMasqueRequest( | 
 |       const quiche::HttpHeaderBlock& request_headers, | 
 |       QuicSimpleServerBackend::RequestHandler* request_handler) override; | 
 |   QuicSpdySession* GetQuicSpdySession() override; | 
 |  | 
 |   // From QuicSocketEventListener. | 
 |   void OnSocketEvent(QuicEventLoop* event_loop, QuicUdpSocketFd fd, | 
 |                      QuicSocketEventMask events) override; | 
 |  | 
 |   QuicEventLoop* event_loop() const { return event_loop_; } | 
 |  | 
 |  private: | 
 |   bool HandleConnectUdpSocketEvent(QuicUdpSocketFd fd, | 
 |                                    QuicSocketEventMask events); | 
 |   bool HandleConnectIpSocketEvent(QuicUdpSocketFd fd, | 
 |                                   QuicSocketEventMask events); | 
 |   bool HandleConnectEthernetSocketEvent(QuicUdpSocketFd fd, | 
 |                                         QuicSocketEventMask events); | 
 |   std::unique_ptr<QuicBackendResponse> MaybeCheckConcealedAuth( | 
 |       const quiche::HttpHeaderBlock& request_headers, | 
 |       absl::string_view authority, absl::string_view scheme, | 
 |       QuicSimpleServerBackend::RequestHandler* request_handler); | 
 |  | 
 |   // State that the MasqueServerSession keeps for each CONNECT-UDP request. | 
 |   class QUIC_NO_EXPORT ConnectUdpServerState | 
 |       : public QuicSpdyStream::Http3DatagramVisitor, | 
 |         public QuicSpdyStream::ConnectUdpBindVisitor { | 
 |    public: | 
 |     // Server state for CONNECT-UDP and CONNECT-UDP-BIND. | 
 |     // is_bind is true for CONNECT-UDP-BIND. | 
 |     explicit ConnectUdpServerState( | 
 |         QuicSpdyStream* stream, const QuicSocketAddress& target_server_address, | 
 |         QuicUdpSocketFd bind_fd, MasqueServerSession* masque_session, | 
 |         bool is_bind = false); | 
 |  | 
 |     ~ConnectUdpServerState(); | 
 |  | 
 |     // Disallow copy but allow move. | 
 |     ConnectUdpServerState(const ConnectUdpServerState&) = delete; | 
 |     ConnectUdpServerState(ConnectUdpServerState&&); | 
 |     ConnectUdpServerState& operator=(const ConnectUdpServerState&) = delete; | 
 |     ConnectUdpServerState& operator=(ConnectUdpServerState&&); | 
 |  | 
 |     QuicSpdyStream* stream() const { return stream_; } | 
 |     const QuicSocketAddress& target_server_address() const { | 
 |       return target_server_address_; | 
 |     } | 
 |     QuicUdpSocketFd fd() const { return fd_; } | 
 |  | 
 |     // CONNECT-UDP-BIND. | 
 |     bool is_bind() const { return is_bind_; } | 
 |  | 
 |     // From QuicSpdyStream::Http3DatagramVisitor. | 
 |     void OnHttp3Datagram(QuicStreamId stream_id, | 
 |                          absl::string_view payload) override; | 
 |     void OnUnknownCapsule(QuicStreamId /*stream_id*/, | 
 |                           const quiche::UnknownCapsule& /*capsule*/) override {} | 
 |  | 
 |     // From QuicSpdyStream::ConnectUdpBindVisitor. | 
 |     bool OnCompressionAssignCapsule( | 
 |         const quiche::CompressionAssignCapsule& capsule) override; | 
 |     bool OnCompressionCloseCapsule( | 
 |         const quiche::CompressionCloseCapsule& capsule) override; | 
 |  | 
 |     absl::flat_hash_map<ContextId, quic::QuicSocketAddress>& | 
 |     bind_context_ip_map() { | 
 |       return bind_context_ip_map_; | 
 |     } | 
 |     ContextId uncompressed_context_id() const { | 
 |       return uncompressed_context_id_; | 
 |     } | 
 |  | 
 |    private: | 
 |     QuicSpdyStream* stream_; | 
 |     QuicSocketAddress target_server_address_; | 
 |     QuicUdpSocketFd fd_;                   // Owned. | 
 |     MasqueServerSession* masque_session_;  // Unowned. | 
 |     bool is_bind_; | 
 |  | 
 |     // CONNECT-UDP-BIND context id to ip:port map. | 
 |     absl::flat_hash_map<ContextId, quic::QuicSocketAddress> | 
 |         bind_context_ip_map_ = {}; | 
 |     ContextId uncompressed_context_id_ = kInvalidContextId; | 
 |     // TODO(abhisinghx): Add Server's ability to request compression | 
 |     // or close contexts. | 
 |   }; | 
 |  | 
 |   // State that the MasqueServerSession keeps for each CONNECT-IP request. | 
 |   class QUIC_NO_EXPORT ConnectIpServerState | 
 |       : public QuicSpdyStream::Http3DatagramVisitor, | 
 |         public QuicSpdyStream::ConnectIpVisitor { | 
 |    public: | 
 |     // ConnectIpServerState takes ownership of |fd|. It will unregister it | 
 |     // from |event_loop| and close the file descriptor when destructed. | 
 |     explicit ConnectIpServerState(QuicIpAddress client_ip, | 
 |                                   QuicSpdyStream* stream, QuicUdpSocketFd fd, | 
 |                                   MasqueServerSession* masque_session); | 
 |  | 
 |     ~ConnectIpServerState(); | 
 |  | 
 |     // Disallow copy but allow move. | 
 |     ConnectIpServerState(const ConnectIpServerState&) = delete; | 
 |     ConnectIpServerState(ConnectIpServerState&&); | 
 |     ConnectIpServerState& operator=(const ConnectIpServerState&) = delete; | 
 |     ConnectIpServerState& operator=(ConnectIpServerState&&); | 
 |  | 
 |     QuicSpdyStream* stream() const { return stream_; } | 
 |     QuicUdpSocketFd fd() const { return fd_; } | 
 |  | 
 |     // From QuicSpdyStream::Http3DatagramVisitor. | 
 |     void OnHttp3Datagram(QuicStreamId stream_id, | 
 |                          absl::string_view payload) override; | 
 |     void OnUnknownCapsule(QuicStreamId /*stream_id*/, | 
 |                           const quiche::UnknownCapsule& /*capsule*/) override {} | 
 |  | 
 |     // From QuicSpdyStream::ConnectIpVisitor. | 
 |     bool OnAddressAssignCapsule( | 
 |         const quiche::AddressAssignCapsule& capsule) override; | 
 |     bool OnAddressRequestCapsule( | 
 |         const quiche::AddressRequestCapsule& capsule) override; | 
 |     bool OnRouteAdvertisementCapsule( | 
 |         const quiche::RouteAdvertisementCapsule& capsule) override; | 
 |     void OnHeadersWritten() override; | 
 |  | 
 |    private: | 
 |     QuicIpAddress client_ip_; | 
 |     QuicSpdyStream* stream_; | 
 |     QuicUdpSocketFd fd_;                   // Owned. | 
 |     MasqueServerSession* masque_session_;  // Unowned. | 
 |   }; | 
 |  | 
 |   // State that the MasqueServerSession keeps for each CONNECT-ETHERNET request. | 
 |   class QUIC_NO_EXPORT ConnectEthernetServerState | 
 |       : public QuicSpdyStream::Http3DatagramVisitor { | 
 |    public: | 
 |     // ConnectEthernetServerState takes ownership of |fd|. It will unregister it | 
 |     // from |event_loop| and close the file descriptor when destructed. | 
 |     explicit ConnectEthernetServerState(QuicSpdyStream* stream, | 
 |                                         QuicUdpSocketFd fd, | 
 |                                         MasqueServerSession* masque_session); | 
 |  | 
 |     ~ConnectEthernetServerState(); | 
 |  | 
 |     // Disallow copy but allow move. | 
 |     ConnectEthernetServerState(const ConnectEthernetServerState&) = delete; | 
 |     ConnectEthernetServerState(ConnectEthernetServerState&&); | 
 |     ConnectEthernetServerState& operator=(const ConnectEthernetServerState&) = | 
 |         delete; | 
 |     ConnectEthernetServerState& operator=(ConnectEthernetServerState&&); | 
 |  | 
 |     QuicSpdyStream* stream() const { return stream_; } | 
 |     QuicUdpSocketFd fd() const { return fd_; } | 
 |  | 
 |     // From QuicSpdyStream::Http3DatagramVisitor. | 
 |     void OnHttp3Datagram(QuicStreamId stream_id, | 
 |                          absl::string_view payload) override; | 
 |     void OnUnknownCapsule(QuicStreamId /*stream_id*/, | 
 |                           const quiche::UnknownCapsule& /*capsule*/) override {} | 
 |  | 
 |    private: | 
 |     QuicSpdyStream* stream_; | 
 |     QuicUdpSocketFd fd_;                   // Owned. | 
 |     MasqueServerSession* masque_session_;  // Unowned. | 
 |   }; | 
 |  | 
 |   // From QuicSpdySession. | 
 |   bool OnSettingsFrame(const SettingsFrame& frame) override; | 
 |   HttpDatagramSupport LocalHttpDatagramSupport() override { | 
 |     return HttpDatagramSupport::kRfc; | 
 |   } | 
 |  | 
 |   MasqueServerBackend* masque_server_backend_;  // Unowned. | 
 |   QuicEventLoop* event_loop_;                   // Unowned. | 
 |   MasqueMode masque_mode_; | 
 |   std::list<ConnectUdpServerState> connect_udp_server_states_; | 
 |   std::list<ConnectIpServerState> connect_ip_server_states_; | 
 |   std::list<ConnectEthernetServerState> connect_ethernet_server_states_; | 
 | }; | 
 |  | 
 | }  // namespace quic | 
 |  | 
 | #endif  // QUICHE_QUIC_MASQUE_MASQUE_SERVER_SESSION_H_ |