// 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 "net/third_party/quiche/src/quic/quartc/test/quartc_peer.h"

#include <utility>

#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_storage.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"

namespace quic {
namespace test {

QuartcPeer::QuartcPeer(const QuicClock* clock,
                       QuicAlarmFactory* alarm_factory,
                       QuicRandom* random,
                       QuicBufferAllocator* buffer_allocator,
                       const std::vector<QuartcDataSource::Config>& configs)
    : clock_(clock),
      alarm_factory_(alarm_factory),
      random_(random),
      buffer_allocator_(buffer_allocator),
      enabled_(false),
      session_(nullptr),
      configs_(configs),
      last_available_(QuicBandwidth::Zero()) {}

QuartcPeer::~QuartcPeer() {
  session_->CloseConnection("~QuartcPeer()");
}

void QuartcPeer::SetEnabled(bool value) {
  enabled_ = value;
  for (auto& source : data_sources_) {
    source->SetEnabled(enabled_);
  }
}

IdToSequenceNumberMap QuartcPeer::GetLastSequenceNumbers() const {
  DCHECK_GE(configs_.size(), data_sources_.size());
  IdToSequenceNumberMap out;
  for (size_t i = 0; i < data_sources_.size(); ++i) {
    out[configs_[i].id] = data_sources_[i]->sequence_number();
  }
  return out;
}

void QuartcPeer::OnSessionCreated(QuartcSession* session) {
  session_ = session;

  session_->StartCryptoHandshake();

  QuicByteCount largest_message_payload =
      session_->GetGuaranteedLargestMessagePayload();
  for (auto& config : configs_) {
    // Clamp maximum frame sizes to the largest supported by the session before
    // creating data sources.
    config.max_frame_size =
        config.max_frame_size > 0
            ? std::min(config.max_frame_size, largest_message_payload)
            : largest_message_payload;
    QUIC_LOG(INFO) << "Set max frame size for source " << config.id << " to "
                   << config.max_frame_size;
    data_sources_.push_back(std::make_unique<QuartcDataSource>(
        clock_, alarm_factory_, random_, config, this));
  }
}

void QuartcPeer::OnCryptoHandshakeComplete() {
  SetEnabled(true);
}

void QuartcPeer::OnConnectionWritable() {
  SetEnabled(true);
}

void QuartcPeer::OnIncomingStream(QuartcStream* stream) {
  QUIC_LOG(DFATAL) << "Unexpected incoming stream, id=" << stream->id();
}

void QuartcPeer::OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
                                           QuicBandwidth pacing_rate,
                                           QuicTime::Delta /*latest_rtt*/) {
  // Note: this is fairly crude rate adaptation and makes no effort to account
  // for overhead.  The congestion controller is assumed to account for this.
  // It may do so by detecting overuse and pushing back on its bandwidth
  // estimate, or it may explicitly subtract overhead before surfacing its
  // estimate.
  QuicBandwidth available = std::min(bandwidth_estimate, pacing_rate);
  last_available_ = available;
  for (auto& source : data_sources_) {
    available = source->AllocateBandwidth(available);
  }
}

void QuartcPeer::OnConnectionClosed(const QuicConnectionCloseFrame& frame,
                                    ConnectionCloseSource /*source*/) {
  QUIC_LOG(INFO) << "Connection closed, frame=" << frame;
  SetEnabled(false);
}

void QuartcPeer::OnMessageReceived(quiche::QuicheStringPiece message) {
  ReceivedMessage received;
  received.receive_time = clock_->Now();

  if (!ParsedQuartcDataFrame::Parse(message, &received.frame)) {
    QUIC_LOG(DFATAL) << "Failed to parse incoming message as test data frame: ["
                     << message << "]";
  }
  received_messages_.push_back(received);
}

void QuartcPeer::OnDataProduced(const char* data, size_t length) {
  // Further packetization is not required, as sources are configured to produce
  // frames that fit within message payloads.
  DCHECK_LE(length, session_->GetCurrentLargestMessagePayload());
  struct iovec iov = {const_cast<char*>(data), length};
  QuicMemSliceStorage storage(&iov, 1, buffer_allocator_, length);
  session_->SendOrQueueMessage(storage.ToSpan(), /*datagram_id=*/0);
}

}  // namespace test
}  // namespace quic
