text: // 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_CLIENT_SESSION_H_
  #define QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_
  
  #include <string>
  
  #include "absl/container/flat_hash_map.h"
  #include "absl/strings/string_view.h"
  #include "quiche/quic/core/http/quic_spdy_client_session.h"
  #include "quiche/quic/masque/masque_utils.h"
  #include "quiche/quic/platform/api/quic_export.h"
  #include "quiche/quic/platform/api/quic_socket_address.h"
  
  namespace quic {
  
  // QUIC client session for connection to MASQUE proxy. This session establishes
  // a connection to a MASQUE proxy and handles sending and receiving DATAGRAM
  // frames for operation of the MASQUE protocol. Multiple end-to-end encapsulated
  // sessions can then coexist inside this session. Once these are created, they
  // need to be registered with this session.
  class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
   public:
    // Interface meant to be implemented by the owner of the
    // MasqueClientSession instance.
    class QUIC_NO_EXPORT Owner {
     public:
      virtual ~Owner() {}
  
      // Notifies the owner that a settings frame has been received.
      virtual void OnSettingsReceived() = 0;
    };
    // Interface meant to be implemented by encapsulated client sessions, i.e.
    // the end-to-end QUIC client sessions that run inside MASQUE encapsulation.
    class QUIC_NO_EXPORT EncapsulatedClientSession {
     public:
      virtual ~EncapsulatedClientSession() {}
  
      // Process packet that was just decapsulated.
      virtual void ProcessPacket(absl::string_view packet,
                                 QuicSocketAddress target_server_address) = 0;
  
      // Close the encapsulated connection.
      virtual void CloseConnection(
          QuicErrorCode error, const std::string& details,
          ConnectionCloseBehavior connection_close_behavior) = 0;
    };
  
    // Takes ownership of |connection|, but not of |crypto_config| or
    // |push_promise_index| or |owner|. All pointers must be non-null. Caller
    // must ensure that |push_promise_index| and |owner| stay valid for the
    // lifetime of the newly created MasqueClientSession.
    MasqueClientSession(MasqueMode masque_mode, const std::string& uri_template,
                        const QuicConfig& config,
                        const ParsedQuicVersionVector& supported_versions,
                        QuicConnection* connection, const QuicServerId& server_id,
                        QuicCryptoClientConfig* crypto_config,
                        QuicClientPushPromiseIndex* push_promise_index,
                        Owner* owner);
  
    // Disallow copy and assign.
    MasqueClientSession(const MasqueClientSession&) = delete;
    MasqueClientSession& operator=(const MasqueClientSession&) = 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 QuicSpdySession.
    bool OnSettingsFrame(const SettingsFrame& frame) override;
  
    // Send encapsulated packet.
    void SendPacket(absl::string_view packet,
                    const QuicSocketAddress& target_server_address,
                    EncapsulatedClientSession* encapsulated_client_session);
  
    // Close CONNECT-UDP stream tied to this encapsulated client session.
    void CloseConnectUdpStream(
        EncapsulatedClientSession* encapsulated_client_session);
  
   private:
    // State that the MasqueClientSession keeps for each CONNECT-UDP request.
    class QUIC_NO_EXPORT ConnectUdpClientState
        : public QuicSpdyStream::Http3DatagramVisitor {
     public:
      // |stream| and |encapsulated_client_session| must be valid for the lifetime
      // of the ConnectUdpClientState.
      explicit ConnectUdpClientState(
          QuicSpdyClientStream* stream,
          EncapsulatedClientSession* encapsulated_client_session,
          MasqueClientSession* masque_session,
          const QuicSocketAddress& target_server_address);
  
      ~ConnectUdpClientState();
  
      // Disallow copy but allow move.
      ConnectUdpClientState(const ConnectUdpClientState&) = delete;
      ConnectUdpClientState(ConnectUdpClientState&&);
      ConnectUdpClientState& operator=(const ConnectUdpClientState&) = delete;
      ConnectUdpClientState& operator=(ConnectUdpClientState&&);
  
      QuicSpdyClientStream* stream() const { return stream_; }
      EncapsulatedClientSession* encapsulated_client_session() const {
        return encapsulated_client_session_;
      }
      const QuicSocketAddress& target_server_address() const {
        return target_server_address_;
      }
  
      // From QuicSpdyStream::Http3DatagramVisitor.
      void OnHttp3Datagram(QuicStreamId stream_id,
                           absl::string_view payload) override;
  
     private:
      QuicSpdyClientStream* stream_;                            // Unowned.
      EncapsulatedClientSession* encapsulated_client_session_;  // Unowned.
      MasqueClientSession* masque_session_;                     // Unowned.
      QuicSocketAddress target_server_address_;
    };
  
    HttpDatagramSupport LocalHttpDatagramSupport() override {
      return HttpDatagramSupport::kDraft09;
    }
  
    const ConnectUdpClientState* GetOrCreateConnectUdpClientState(
        const QuicSocketAddress& target_server_address,
        EncapsulatedClientSession* encapsulated_client_session);
  
    MasqueMode masque_mode_;
    std::string uri_template_;
    std::list<ConnectUdpClientState> connect_udp_client_states_;
    Owner* owner_;  // Unowned;
  };
  
  }  // namespace quic
  
  #endif  // QUICHE_QUIC_MASQUE_MASQUE_CLIENT_SESSION_H_
  