// Copyright (c) 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_QBONE_QBONE_CLIENT_H_
#define QUICHE_QUIC_QBONE_QBONE_CLIENT_H_

#include <memory>

#include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/io/quic_event_loop.h"
#include "quiche/quic/core/quic_bandwidth.h"
#include "quiche/quic/qbone/bonnet/qbone_client_packet_exchanger.h"
#include "quiche/quic/qbone/qbone_client_interface.h"
#include "quiche/quic/qbone/qbone_client_session.h"
#include "quiche/quic/tools/quic_client_base.h"

namespace quic {
// A QboneClient encapsulates connecting to a server via an event loop
// and setting up a QBONE tunnel. See the QboneTestClient in qbone_client_test
// for usage.
class QboneClient : public QuicClientBase, public QboneClientInterface {
 public:
  // Note that the event loop, QBONE writer, and handler are owned
  // by the caller.
  QboneClient(QuicSocketAddress server_address, const QuicServerId& server_id,
              const ParsedQuicVersionVector& supported_versions,
              QuicSession::Visitor* session_owner, const QuicConfig& config,
              QuicEventLoop* event_loop,
              std::unique_ptr<ProofVerifier> proof_verifier,
              QboneClientPacketExchanger* absl_nonnull
                  local_network_packet_exchanger ABSL_ATTRIBUTE_LIFETIME_BOUND,
              QboneClientControlStream::Handler* qbone_handler);
  ~QboneClient() override;
  QboneClientSession* qbone_session();

  // From QboneClientInterface. Accepts a given packet from the network and
  // sends the packet down to the QBONE connection.
  void ProcessPacketFromNetwork(absl::string_view packet) override;

  bool EarlyDataAccepted() override;
  bool ReceivedInchoateReject() override;

  void set_max_pacing_rate(QuicBandwidth max_pacing_rate) {
    max_pacing_rate_ = max_pacing_rate;
  }

  QuicBandwidth max_pacing_rate() const { return max_pacing_rate_; }

  bool use_quarantine_mode() const;
  void set_use_quarantine_mode(bool use_quarantine_mode);

 protected:
  int GetNumSentClientHellosFromSession() override;
  int GetNumReceivedServerConfigUpdatesFromSession() override;

  // Takes ownership of |connection|.
  std::unique_ptr<QuicSession> CreateQuicClientSession(
      const ParsedQuicVersionVector& supported_versions,
      QuicConnection* connection) override;

  QboneClientPacketExchanger& local_network_packet_exchanger() {
    return local_network_packet_exchanger_;
  }

  QboneClientControlStream::Handler* qbone_control_handler() {
    return qbone_handler_;
  }

  QuicSession::Visitor* session_owner() { return session_owner_; }

  bool HasActiveRequests() override;

 private:
  QboneClientPacketExchanger& local_network_packet_exchanger_;
  QboneClientControlStream::Handler* qbone_handler_;

  QuicSession::Visitor* session_owner_;

  // When nonzero, the pacing rate set with`QuicConnection::SetMaxPacingRate`.
  QuicBandwidth max_pacing_rate_;

  // When true, the connection will be made in quarantine mode.
  bool use_quarantine_mode_ = false;
};

}  // namespace quic

#endif  // QUICHE_QUIC_QBONE_QBONE_CLIENT_H_
