// 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.

#include "quiche/quic/qbone/qbone_client.h"

#include <limits>
#include <memory>
#include <utility>

#include "absl/base/casts.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/core/quic_default_connection_helper.h"
#include "quiche/quic/platform/api/quic_testvalue.h"
#include "quiche/quic/qbone/bonnet/qbone_client_packet_exchanger.h"
#include "quiche/quic/tools/quic_client_base.h"
#include "quiche/quic/tools/quic_client_default_network_helper.h"
#include "quiche/common/platform/api/quiche_command_line_flags.h"

DEFINE_QUICHE_COMMAND_LINE_FLAG(
    int, qbone_client_max_tunnel_reads, std::numeric_limits<int>::max(),
    "Maximum number of reads from the tunnel socket per event. Note that "
    "each read represents a single syscall and QUICHE will read multiple "
    "packets per syscall (currently 16).");

namespace quic {
namespace {
std::unique_ptr<QuicClientBase::NetworkHelper> CreateNetworkHelper(
    QuicEventLoop* event_loop, QboneClient* client) {
  auto helper_impl =
      std::make_unique<QuicClientDefaultNetworkHelper>(event_loop, client);
  helper_impl->set_max_reads_per_event_loop(
      quiche::GetQuicheCommandLineFlag(FLAGS_qbone_client_max_tunnel_reads));

  std::unique_ptr<QuicClientBase::NetworkHelper> helper =
      std::move(helper_impl);
  quic::AdjustTestValue("QboneClient/network_helper", &helper);
  return helper;
}
}  // namespace

QboneClient::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,
    QboneClientControlStream::Handler* qbone_handler)
    : QuicClientBase(server_id, supported_versions, config,
                     new QuicDefaultConnectionHelper(),
                     event_loop->CreateAlarmFactory().release(),
                     CreateNetworkHelper(event_loop, this),
                     std::move(proof_verifier), nullptr),
      local_network_packet_exchanger_(*local_network_packet_exchanger),
      qbone_handler_(qbone_handler),
      session_owner_(session_owner),
      max_pacing_rate_(QuicBandwidth::Zero()) {
  set_server_address(server_address);
  crypto_config()->set_alpn("qbone");
}

QboneClient::~QboneClient() { ResetSession(); }

QboneClientSession* QboneClient::qbone_session() {
  return absl::down_cast<QboneClientSession*>(QuicClientBase::session());
}

void QboneClient::ProcessPacketFromNetwork(absl::string_view packet) {
  qbone_session()->ProcessPacketFromNetwork(packet);
}

bool QboneClient::EarlyDataAccepted() {
  return qbone_session()->EarlyDataAccepted();
}

bool QboneClient::ReceivedInchoateReject() {
  return qbone_session()->ReceivedInchoateReject();
}

int QboneClient::GetNumSentClientHellosFromSession() {
  return qbone_session()->GetNumSentClientHellos();
}

int QboneClient::GetNumReceivedServerConfigUpdatesFromSession() {
  return qbone_session()->GetNumReceivedServerConfigUpdates();
}

bool QboneClient::HasActiveRequests() {
  return qbone_session()->HasActiveRequests();
}

class QboneClientSessionWithConnection : public QboneClientSession {
 public:
  using QboneClientSession::QboneClientSession;

  ~QboneClientSessionWithConnection() override { DeleteConnection(); }
};

// Takes ownership of |connection|.
std::unique_ptr<QuicSession> QboneClient::CreateQuicClientSession(
    const ParsedQuicVersionVector& supported_versions,
    QuicConnection* connection) {
  if (max_pacing_rate() > quic::QuicBandwidth::Zero()) {
    QUIC_LOG(INFO) << "Setting max pacing rate to " << max_pacing_rate();
    connection->SetMaxPacingRate(max_pacing_rate());
  }
  return std::make_unique<QboneClientSessionWithConnection>(
      connection, crypto_config(), session_owner(), *config(),
      supported_versions, server_id(), &local_network_packet_exchanger_,
      qbone_handler_);
}

bool QboneClient::use_quarantine_mode() const { return use_quarantine_mode_; }
void QboneClient::set_use_quarantine_mode(bool use_quarantine_mode) {
  use_quarantine_mode_ = use_quarantine_mode;
}
}  // namespace quic
