// 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/qbone_client_interface.h"
#include "quiche/quic/qbone/qbone_client_session.h"
#include "quiche/quic/qbone/qbone_packet_exchanger.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,
              QbonePacketExchanger* 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;

  QbonePacketExchanger& 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:
  QbonePacketExchanger& 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_
