// Copyright (c) 2015 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.

// A base class for the toy client, which connects to a specified port and sends
// QUIC request to that endpoint.

#ifndef QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_
#define QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_

#include <memory>
#include <string>

#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/crypto_handshake.h"
#include "quiche/quic/core/deterministic_connection_id_generator.h"
#include "quiche/quic/core/http/quic_spdy_client_session.h"
#include "quiche/quic/core/http/quic_spdy_client_stream.h"
#include "quiche/quic/core/quic_config.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/platform/api/quic_socket_address.h"

namespace quic {

class ProofVerifier;
class QuicServerId;
class SessionCache;

// A path context which owns the writer.
class QUIC_EXPORT_PRIVATE PathMigrationContext
    : public QuicPathValidationContext {
 public:
  PathMigrationContext(std::unique_ptr<QuicPacketWriter> writer,
                       const QuicSocketAddress& self_address,
                       const QuicSocketAddress& peer_address)
      : QuicPathValidationContext(self_address, peer_address),
        alternative_writer_(std::move(writer)) {}

  QuicPacketWriter* WriterToUse() override { return alternative_writer_.get(); }

  QuicPacketWriter* ReleaseWriter() { return alternative_writer_.release(); }

 private:
  std::unique_ptr<QuicPacketWriter> alternative_writer_;
};

// QuicClientBase handles establishing a connection to the passed in
// server id, including ensuring that it supports the passed in versions
// and config.
// Subclasses derived from this class are responsible for creating the
// actual QuicSession instance, as well as defining functions that
// create and run the underlying network transport.
class QuicClientBase : public QuicSession::Visitor {
 public:
  // An interface to various network events that the QuicClient will need to
  // interact with.
  class NetworkHelper {
   public:
    virtual ~NetworkHelper();

    // Runs one iteration of the event loop.
    virtual void RunEventLoop() = 0;

    // Used during initialization: creates the UDP socket FD, sets socket
    // options, and binds the socket to our address.
    virtual bool CreateUDPSocketAndBind(QuicSocketAddress server_address,
                                        QuicIpAddress bind_to_address,
                                        int bind_to_port) = 0;

    // Unregister and close all open UDP sockets.
    virtual void CleanUpAllUDPSockets() = 0;

    // If the client has at least one UDP socket, return address of the latest
    // created one. Otherwise, return an empty socket address.
    virtual QuicSocketAddress GetLatestClientAddress() const = 0;

    // Creates a packet writer to be used for the next connection.
    virtual QuicPacketWriter* CreateQuicPacketWriter() = 0;
  };

  QuicClientBase(const QuicServerId& server_id,
                 const ParsedQuicVersionVector& supported_versions,
                 const QuicConfig& config,
                 QuicConnectionHelperInterface* helper,
                 QuicAlarmFactory* alarm_factory,
                 std::unique_ptr<NetworkHelper> network_helper,
                 std::unique_ptr<ProofVerifier> proof_verifier,
                 std::unique_ptr<SessionCache> session_cache);
  QuicClientBase(const QuicClientBase&) = delete;
  QuicClientBase& operator=(const QuicClientBase&) = delete;

  virtual ~QuicClientBase();

  // Implmenets QuicSession::Visitor
  void OnConnectionClosed(QuicConnectionId /*server_connection_id*/,
                          QuicErrorCode /*error*/,
                          const std::string& /*error_details*/,
                          ConnectionCloseSource /*source*/) override {}

  void OnWriteBlocked(QuicBlockedWriterInterface* /*blocked_writer*/) override {
  }
  void OnRstStreamReceived(const QuicRstStreamFrame& /*frame*/) override {}
  void OnStopSendingReceived(const QuicStopSendingFrame& /*frame*/) override {}
  bool TryAddNewConnectionId(
      const QuicConnectionId& /*server_connection_id*/,
      const QuicConnectionId& /*new_connection_id*/) override {
    return false;
  }
  void OnConnectionIdRetired(
      const QuicConnectionId& /*server_connection_id*/) override {}
  void OnServerPreferredAddressAvailable(
      const QuicSocketAddress& server_preferred_address) override;
  void OnPathDegrading() override;

  // Initializes the client to create a connection. Should be called exactly
  // once before calling StartConnect or Connect. Returns true if the
  // initialization succeeds, false otherwise.
  virtual bool Initialize();

  // "Connect" to the QUIC server, including performing synchronous crypto
  // handshake.
  bool Connect();

  // Start the crypto handshake.  This can be done in place of the synchronous
  // Connect(), but callers are responsible for making sure the crypto handshake
  // completes.
  void StartConnect();

  // Calls session()->Initialize(). Subclasses may override this if any extra
  // initialization needs to be done. Subclasses should expect that session()
  // is non-null and valid.
  virtual void InitializeSession();

  // Disconnects from the QUIC server.
  void Disconnect();

  // Returns true if the crypto handshake has yet to establish encryption.
  // Returns false if encryption is active (even if the server hasn't confirmed
  // the handshake) or if the connection has been closed.
  bool EncryptionBeingEstablished();

  // Wait for events until the stream with the given ID is closed.
  void WaitForStreamToClose(QuicStreamId id);

  // Wait for 1-RTT keys become available.
  // Returns true once 1-RTT keys are available, false otherwise.
  ABSL_MUST_USE_RESULT bool WaitForOneRttKeysAvailable();

  // Wait for handshake state proceeds to HANDSHAKE_CONFIRMED.
  // In QUIC crypto, this does the same as WaitForOneRttKeysAvailable, while in
  // TLS, this waits for HANDSHAKE_DONE frame is received.
  ABSL_MUST_USE_RESULT bool WaitForHandshakeConfirmed();

  // Wait up to 50ms, and handle any events which occur.
  // Returns true if there are any outstanding requests.
  bool WaitForEvents();

  // Performs the part of WaitForEvents() that is done after the actual event
  // loop call.
  bool WaitForEventsPostprocessing();

  // Migrate to a new socket (new_host) during an active connection.
  bool MigrateSocket(const QuicIpAddress& new_host);

  // Migrate to a new socket (new_host, port) during an active connection.
  bool MigrateSocketWithSpecifiedPort(const QuicIpAddress& new_host, int port);

  // Validate the new socket and migrate to it if the validation succeeds.
  // Otherwise stay on the current socket. Return true if the validation has
  // started.
  bool ValidateAndMigrateSocket(const QuicIpAddress& new_host);

  // Open a new socket to change to a new ephemeral port.
  bool ChangeEphemeralPort();

  QuicSession* session();
  const QuicSession* session() const;

  bool connected() const;
  virtual bool goaway_received() const;

  const QuicServerId& server_id() const { return server_id_; }

  // This should only be set before the initial Connect()
  void set_server_id(const QuicServerId& server_id) { server_id_ = server_id; }

  void SetUserAgentID(const std::string& user_agent_id) {
    crypto_config_.set_user_agent_id(user_agent_id);
  }

  void SetTlsSignatureAlgorithms(std::string signature_algorithms) {
    crypto_config_.set_tls_signature_algorithms(
        std::move(signature_algorithms));
  }

  const ParsedQuicVersionVector& supported_versions() const {
    return supported_versions_;
  }

  void SetSupportedVersions(const ParsedQuicVersionVector& versions) {
    supported_versions_ = versions;
  }

  QuicConfig* config() { return &config_; }

  QuicCryptoClientConfig* crypto_config() { return &crypto_config_; }

  // Change the initial maximum packet size of the connection.  Has to be called
  // before Connect()/StartConnect() in order to have any effect.
  void set_initial_max_packet_length(QuicByteCount initial_max_packet_length) {
    initial_max_packet_length_ = initial_max_packet_length;
  }

  // The number of client hellos sent.
  int GetNumSentClientHellos();

  // Returns true if early data (0-RTT data) was sent and the server accepted
  // it.
  virtual bool EarlyDataAccepted() = 0;

  // Returns true if the handshake was delayed one round trip by the server
  // because the server wanted proof the client controls its source address
  // before progressing further. In Google QUIC, this would be due to an
  // inchoate REJ in the QUIC Crypto handshake; in IETF QUIC this would be due
  // to a Retry packet.
  // TODO(nharper): Consider a better name for this method.
  virtual bool ReceivedInchoateReject() = 0;

  // Gather the stats for the last session and update the stats for the overall
  // connection.
  void UpdateStats();

  // The number of server config updates received.
  int GetNumReceivedServerConfigUpdates();

  // Returns any errors that occurred at the connection-level.
  QuicErrorCode connection_error() const;
  void set_connection_error(QuicErrorCode connection_error) {
    connection_error_ = connection_error;
  }

  bool connected_or_attempting_connect() const {
    return connected_or_attempting_connect_;
  }
  void set_connected_or_attempting_connect(
      bool connected_or_attempting_connect) {
    connected_or_attempting_connect_ = connected_or_attempting_connect;
  }

  QuicPacketWriter* writer() { return writer_.get(); }
  void set_writer(QuicPacketWriter* writer) {
    if (writer_.get() != writer) {
      writer_.reset(writer);
    }
  }

  void reset_writer() { writer_.reset(); }

  ProofVerifier* proof_verifier() const;

  void set_bind_to_address(QuicIpAddress address) {
    bind_to_address_ = address;
  }

  QuicIpAddress bind_to_address() const { return bind_to_address_; }

  void set_local_port(int local_port) { local_port_ = local_port; }

  int local_port() const { return local_port_; }

  const QuicSocketAddress& server_address() const { return server_address_; }

  void set_server_address(const QuicSocketAddress& server_address) {
    server_address_ = server_address;
  }

  QuicConnectionHelperInterface* helper() { return helper_.get(); }

  QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }

  NetworkHelper* network_helper();
  const NetworkHelper* network_helper() const;

  bool initialized() const { return initialized_; }

  void SetPreSharedKey(absl::string_view key) {
    crypto_config_.set_pre_shared_key(key);
  }

  void set_connection_debug_visitor(
      QuicConnectionDebugVisitor* connection_debug_visitor) {
    connection_debug_visitor_ = connection_debug_visitor;
  }

  // Sets the interface name to bind. If empty, will not attempt to bind the
  // socket to that interface. Defaults to empty string.
  void set_interface_name(std::string interface_name) {
    interface_name_ = interface_name;
  }

  std::string interface_name() const { return interface_name_; }

  void set_server_connection_id_override(
      const QuicConnectionId& connection_id) {
    server_connection_id_override_ = connection_id;
  }

  void set_server_connection_id_length(uint8_t server_connection_id_length) {
    server_connection_id_length_ = server_connection_id_length;
  }

  void set_client_connection_id_length(uint8_t client_connection_id_length) {
    client_connection_id_length_ = client_connection_id_length;
  }

  bool HasPendingPathValidation();

  void ValidateNewNetwork(const QuicIpAddress& host);

  void AddValidatedPath(std::unique_ptr<QuicPathValidationContext> context) {
    validated_paths_.push_back(std::move(context));
  }

  const std::vector<std::unique_ptr<QuicPathValidationContext>>&
  validated_paths() const {
    return validated_paths_;
  }

  // Enable port migration upon path degrading after given number of PTOs.
  // If no value is provided, path degrading will be detected after 4 PTOs by
  // default.
  void EnablePortMigrationUponPathDegrading(
      std::optional<int> num_ptos_for_path_degrading) {
    allow_port_migration_ = true;
    if (num_ptos_for_path_degrading.has_value()) {
      session_->connection()
          ->sent_packet_manager()
          .set_num_ptos_for_path_degrading(num_ptos_for_path_degrading.value());
    }
  }

  virtual void OnSocketMigrationProbingSuccess(
      std::unique_ptr<QuicPathValidationContext> context);

  virtual void OnSocketMigrationProbingFailure() {}

 protected:
  // TODO(rch): Move GetNumSentClientHellosFromSession and
  // GetNumReceivedServerConfigUpdatesFromSession into a new/better
  // QuicSpdyClientSession class. The current inherits dependencies from
  // Spdy. When that happens this class and all its subclasses should
  // work with QuicSpdyClientSession instead of QuicSession.
  // That will obviate the need for the pure virtual functions below.

  // Extract the number of sent client hellos from the session.
  virtual int GetNumSentClientHellosFromSession() = 0;

  // The number of server config updates received.
  virtual int GetNumReceivedServerConfigUpdatesFromSession() = 0;

  // If this client supports buffering data, resend it.
  virtual void ResendSavedData() = 0;

  // If this client supports buffering data, clear it.
  virtual void ClearDataToResend() = 0;

  // Takes ownership of |connection|. If you override this function,
  // you probably want to call ResetSession() in your destructor.
  // TODO(rch): Change the connection parameter to take in a
  // std::unique_ptr<QuicConnection> instead.
  virtual std::unique_ptr<QuicSession> CreateQuicClientSession(
      const ParsedQuicVersionVector& supported_versions,
      QuicConnection* connection) = 0;

  // Generates the next ConnectionId for |server_id_|.  By default, if the
  // cached server config contains a server-designated ID, that ID will be
  // returned.  Otherwise, the next random ID will be returned.
  QuicConnectionId GetNextConnectionId();

  // Generates a new, random connection ID (as opposed to a server-designated
  // connection ID).
  virtual QuicConnectionId GenerateNewConnectionId();

  // Returns the client connection ID to use.
  virtual QuicConnectionId GetClientConnectionId();

  // Subclasses may need to explicitly clear the session on destruction
  // if they create it with objects that will be destroyed before this is.
  // You probably want to call this if you override CreateQuicSpdyClientSession.
  void ResetSession() { session_.reset(); }

  // Returns true if the corresponding of this client has active requests.
  virtual bool HasActiveRequests() = 0;

  // Allows derived classes to access this when creating connections.
  ConnectionIdGeneratorInterface& connection_id_generator();

 private:
  // Returns true and set |version| if client can reconnect with a different
  // version.
  bool CanReconnectWithDifferentVersion(ParsedQuicVersion* version) const;

  std::unique_ptr<QuicPacketWriter> CreateWriterForNewNetwork(
      const QuicIpAddress& new_host, int port);

  // |server_id_| is a tuple (hostname, port, is_https) of the server.
  QuicServerId server_id_;

  // Tracks if the client is initialized to connect.
  bool initialized_;

  // Address of the server.
  QuicSocketAddress server_address_;

  // If initialized, the address to bind to.
  QuicIpAddress bind_to_address_;

  // Local port to bind to. Initialize to 0.
  int local_port_;

  // config_ and crypto_config_ contain configuration and cached state about
  // servers.
  QuicConfig config_;
  QuicCryptoClientConfig crypto_config_;

  // Helper to be used by created connections. Must outlive |session_|.
  std::unique_ptr<QuicConnectionHelperInterface> helper_;

  // Alarm factory to be used by created connections. Must outlive |session_|.
  std::unique_ptr<QuicAlarmFactory> alarm_factory_;

  // Writer used to actually send packets to the wire. Must outlive |session_|.
  std::unique_ptr<QuicPacketWriter> writer_;

  // Session which manages streams.
  std::unique_ptr<QuicSession> session_;

  // This vector contains QUIC versions which we currently support.
  // This should be ordered such that the highest supported version is the first
  // element, with subsequent elements in descending order (versions can be
  // skipped as necessary). We will always pick supported_versions_[0] as the
  // initial version to use.
  ParsedQuicVersionVector supported_versions_;

  // The initial value of maximum packet size of the connection.  If set to
  // zero, the default is used.
  QuicByteCount initial_max_packet_length_;

  // The number of hellos sent during the current/latest connection.
  int num_sent_client_hellos_;

  // Used to store any errors that occurred with the overall connection (as
  // opposed to that associated with the last session object).
  QuicErrorCode connection_error_;

  // True when the client is attempting to connect.  Set to false between a call
  // to Disconnect() and the subsequent call to StartConnect().  When
  // connected_or_attempting_connect_ is false, the session object corresponds
  // to the previous client-level connection.
  bool connected_or_attempting_connect_;

  // The network helper used to create sockets and manage the event loop.
  // Not owned by this class.
  std::unique_ptr<NetworkHelper> network_helper_;

  // The debug visitor set on the connection right after it is constructed.
  // Not owned, must be valid for the lifetime of the QuicClientBase instance.
  QuicConnectionDebugVisitor* connection_debug_visitor_;

  // If set,
  // - GetNextConnectionId will use this as the next server connection id.
  // - GenerateNewConnectionId will not be called.
  std::optional<QuicConnectionId> server_connection_id_override_;

  // GenerateNewConnectionId creates a random connection ID of this length.
  // Defaults to 8.
  uint8_t server_connection_id_length_;

  // GetClientConnectionId creates a random connection ID of this length.
  // Defaults to 0.
  uint8_t client_connection_id_length_;

  // Stores validated paths.
  std::vector<std::unique_ptr<QuicPathValidationContext>> validated_paths_;

  // Stores the interface name to bind. If empty, will not attempt to bind the
  // socket to that interface. Defaults to empty string.
  std::string interface_name_;

  DeterministicConnectionIdGenerator connection_id_generator_{
      kQuicDefaultConnectionIdLength};

  bool allow_port_migration_{false};
};

}  // namespace quic

#endif  // QUICHE_QUIC_TOOLS_QUIC_CLIENT_BASE_H_
