// Copyright (c) 2012 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 "quic/test_tools/simulator/quic_endpoint_base.h"

#include <memory>
#include <utility>

#include "absl/strings/str_cat.h"
#include "quic/core/crypto/crypto_handshake_message.h"
#include "quic/core/crypto/crypto_protocol.h"
#include "quic/core/quic_connection.h"
#include "quic/core/quic_data_writer.h"
#include "quic/platform/api/quic_test_output.h"
#include "quic/test_tools/quic_connection_peer.h"
#include "quic/test_tools/quic_test_utils.h"
#include "quic/test_tools/simulator/simulator.h"

namespace quic {
namespace simulator {

// Takes a SHA-1 hash of the name and converts it into five 32-bit integers.
static std::vector<uint32_t> HashNameIntoFive32BitIntegers(std::string name) {
  const std::string hash = test::Sha1Hash(name);

  std::vector<uint32_t> output;
  uint32_t current_number = 0;
  for (size_t i = 0; i < hash.size(); i++) {
    current_number = (current_number << 8) + hash[i];
    if (i % 4 == 3) {
      output.push_back(i);
      current_number = 0;
    }
  }

  return output;
}

QuicSocketAddress GetAddressFromName(std::string name) {
  const std::vector<uint32_t> hash = HashNameIntoFive32BitIntegers(name);

  // Generate a random port between 1025 and 65535.
  const uint16_t port = 1025 + hash[0] % (65535 - 1025 + 1);

  // Generate a random 10.x.x.x address, where x is between 1 and 254.
  std::string ip_address{"\xa\0\0\0", 4};
  for (size_t i = 1; i < 4; i++) {
    ip_address[i] = 1 + hash[i] % 254;
  }
  QuicIpAddress host;
  host.FromPackedString(ip_address.c_str(), ip_address.length());
  return QuicSocketAddress(host, port);
}

QuicEndpointBase::QuicEndpointBase(Simulator* simulator,
                                   std::string name,
                                   std::string peer_name)
    : Endpoint(simulator, name),
      peer_name_(peer_name),
      writer_(this),
      nic_tx_queue_(simulator,
                    absl::StrCat(name, " (TX Queue)"),
                    kMaxOutgoingPacketSize * kTxQueueSize),
      connection_(nullptr),
      write_blocked_count_(0),
      drop_next_packet_(false) {
  nic_tx_queue_.set_listener_interface(this);
}

QuicEndpointBase::~QuicEndpointBase() {
  if (trace_visitor_ != nullptr) {
    const char* perspective_prefix =
        connection_->perspective() == Perspective::IS_CLIENT ? "C" : "S";

    std::string identifier = absl::StrCat(
        perspective_prefix, connection_->connection_id().ToString());
    QuicRecordTrace(identifier, trace_visitor_->trace()->SerializeAsString());
  }
}

void QuicEndpointBase::DropNextIncomingPacket() {
  drop_next_packet_ = true;
}

void QuicEndpointBase::RecordTrace() {
  trace_visitor_ = std::make_unique<QuicTraceVisitor>(connection_.get());
  connection_->set_debug_visitor(trace_visitor_.get());
}

void QuicEndpointBase::AcceptPacket(std::unique_ptr<Packet> packet) {
  if (packet->destination != name_) {
    return;
  }
  if (drop_next_packet_) {
    drop_next_packet_ = false;
    return;
  }

  QuicReceivedPacket received_packet(packet->contents.data(),
                                     packet->contents.size(), clock_->Now());
  connection_->ProcessUdpPacket(connection_->self_address(),
                                connection_->peer_address(), received_packet);
}

UnconstrainedPortInterface* QuicEndpointBase::GetRxPort() {
  return this;
}

void QuicEndpointBase::SetTxPort(ConstrainedPortInterface* port) {
  // Any egress done by the endpoint is actually handled by a queue on an NIC.
  nic_tx_queue_.set_tx_port(port);
}

void QuicEndpointBase::OnPacketDequeued() {
  if (writer_.IsWriteBlocked() &&
      (nic_tx_queue_.capacity() - nic_tx_queue_.bytes_queued()) >=
          kMaxOutgoingPacketSize) {
    writer_.SetWritable();
    connection_->OnCanWrite();
  }
}

QuicEndpointBase::Writer::Writer(QuicEndpointBase* endpoint)
    : endpoint_(endpoint), is_blocked_(false) {}

QuicEndpointBase::Writer::~Writer() {}

WriteResult QuicEndpointBase::Writer::WritePacket(
    const char* buffer,
    size_t buf_len,
    const QuicIpAddress& /*self_address*/,
    const QuicSocketAddress& /*peer_address*/,
    PerPacketOptions* options) {
  QUICHE_DCHECK(!IsWriteBlocked());
  QUICHE_DCHECK(options == nullptr);
  QUICHE_DCHECK(buf_len <= kMaxOutgoingPacketSize);

  // Instead of losing a packet, become write-blocked when the egress queue is
  // full.
  if (endpoint_->nic_tx_queue_.packets_queued() > kTxQueueSize) {
    is_blocked_ = true;
    endpoint_->write_blocked_count_++;
    return WriteResult(WRITE_STATUS_BLOCKED, 0);
  }

  auto packet = std::make_unique<Packet>();
  packet->source = endpoint_->name();
  packet->destination = endpoint_->peer_name_;
  packet->tx_timestamp = endpoint_->clock_->Now();

  packet->contents = std::string(buffer, buf_len);
  packet->size = buf_len;

  endpoint_->nic_tx_queue_.AcceptPacket(std::move(packet));

  return WriteResult(WRITE_STATUS_OK, buf_len);
}

bool QuicEndpointBase::Writer::IsWriteBlocked() const {
  return is_blocked_;
}

void QuicEndpointBase::Writer::SetWritable() {
  is_blocked_ = false;
}

absl::optional<int> QuicEndpointBase::Writer::MessageTooBigErrorCode() const {
  return absl::nullopt;
}

QuicByteCount QuicEndpointBase::Writer::GetMaxPacketSize(
    const QuicSocketAddress& /*peer_address*/) const {
  return kMaxOutgoingPacketSize;
}

bool QuicEndpointBase::Writer::SupportsReleaseTime() const {
  return false;
}

bool QuicEndpointBase::Writer::IsBatchMode() const {
  return false;
}

QuicPacketBuffer QuicEndpointBase::Writer::GetNextWriteLocation(
    const QuicIpAddress& /*self_address*/,
    const QuicSocketAddress& /*peer_address*/) {
  return {nullptr, nullptr};
}

WriteResult QuicEndpointBase::Writer::Flush() {
  return WriteResult(WRITE_STATUS_OK, 0);
}

QuicEndpointMultiplexer::QuicEndpointMultiplexer(
    std::string name,
    const std::vector<QuicEndpointBase*>& endpoints)
    : Endpoint((*endpoints.begin())->simulator(), name) {
  for (QuicEndpointBase* endpoint : endpoints) {
    mapping_.insert(std::make_pair(endpoint->name(), endpoint));
  }
}

QuicEndpointMultiplexer::~QuicEndpointMultiplexer() {}

void QuicEndpointMultiplexer::AcceptPacket(std::unique_ptr<Packet> packet) {
  auto key_value_pair_it = mapping_.find(packet->destination);
  if (key_value_pair_it == mapping_.end()) {
    return;
  }

  key_value_pair_it->second->GetRxPort()->AcceptPacket(std::move(packet));
}
UnconstrainedPortInterface* QuicEndpointMultiplexer::GetRxPort() {
  return this;
}
void QuicEndpointMultiplexer::SetTxPort(ConstrainedPortInterface* port) {
  for (auto& key_value_pair : mapping_) {
    key_value_pair.second->SetTxPort(port);
  }
}

}  // namespace simulator
}  // namespace quic
