// 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/qbone_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,
    QbonePacketExchanger* 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
