// 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 "quic/core/batch_writer/quic_batch_writer_buffer.h"

#include <sstream>

namespace quic {

QuicBatchWriterBuffer::QuicBatchWriterBuffer() {
  memset(buffer_, 0, sizeof(buffer_));
}

void QuicBatchWriterBuffer::Clear() {
  buffered_writes_.clear();
}

std::string QuicBatchWriterBuffer::DebugString() const {
  std::ostringstream os;
  os << "{ buffer: " << static_cast<const void*>(buffer_)
     << " buffer_end: " << static_cast<const void*>(buffer_end())
     << " buffered_writes_.size(): " << buffered_writes_.size()
     << " next_write_loc: " << static_cast<const void*>(GetNextWriteLocation())
     << " SizeInUse: " << SizeInUse() << " }";
  return os.str();
}

bool QuicBatchWriterBuffer::Invariants() const {
  // Buffers in buffered_writes_ should not overlap, and collectively they
  // should cover a continuous prefix of buffer_.
  const char* next_buffer = buffer_;
  for (auto iter = buffered_writes_.begin(); iter != buffered_writes_.end();
       ++iter) {
    if ((iter->buffer != next_buffer) ||
        (iter->buffer + iter->buf_len > buffer_end())) {
      return false;
    }
    next_buffer += iter->buf_len;
  }

  return static_cast<size_t>(next_buffer - buffer_) == SizeInUse();
}

char* QuicBatchWriterBuffer::GetNextWriteLocation() const {
  const char* next_loc =
      buffered_writes_.empty()
          ? buffer_
          : buffered_writes_.back().buffer + buffered_writes_.back().buf_len;
  if (static_cast<size_t>(buffer_end() - next_loc) < kMaxOutgoingPacketSize) {
    return nullptr;
  }
  return const_cast<char*>(next_loc);
}

QuicBatchWriterBuffer::PushResult QuicBatchWriterBuffer::PushBufferedWrite(
    const char* buffer,
    size_t buf_len,
    const QuicIpAddress& self_address,
    const QuicSocketAddress& peer_address,
    const PerPacketOptions* options,
    uint64_t release_time) {
  QUICHE_DCHECK(Invariants());
  QUICHE_DCHECK_LE(buf_len, kMaxOutgoingPacketSize);

  PushResult result = {/*succeeded=*/false, /*buffer_copied=*/false};
  char* next_write_location = GetNextWriteLocation();
  if (next_write_location == nullptr) {
    return result;
  }

  if (buffer != next_write_location) {
    if (IsExternalBuffer(buffer, buf_len)) {
      memcpy(next_write_location, buffer, buf_len);
    } else if (IsInternalBuffer(buffer, buf_len)) {
      memmove(next_write_location, buffer, buf_len);
    } else {
      QUIC_BUG(quic_bug_10831_1)
          << "Buffer[" << static_cast<const void*>(buffer) << ", "
          << static_cast<const void*>(buffer + buf_len)
          << ") overlaps with internal buffer["
          << static_cast<const void*>(buffer_) << ", "
          << static_cast<const void*>(buffer_end()) << ")";
      return result;
    }
    result.buffer_copied = true;
  } else {
    // In place push, do nothing.
  }
  buffered_writes_.emplace_back(
      next_write_location, buf_len, self_address, peer_address,
      options ? options->Clone() : std::unique_ptr<PerPacketOptions>(),
      release_time);

  QUICHE_DCHECK(Invariants());

  result.succeeded = true;
  return result;
}

void QuicBatchWriterBuffer::UndoLastPush() {
  if (!buffered_writes_.empty()) {
    buffered_writes_.pop_back();
  }
}

QuicBatchWriterBuffer::PopResult QuicBatchWriterBuffer::PopBufferedWrite(
    int32_t num_buffered_writes) {
  QUICHE_DCHECK(Invariants());
  QUICHE_DCHECK_GE(num_buffered_writes, 0);
  QUICHE_DCHECK_LE(static_cast<size_t>(num_buffered_writes),
                   buffered_writes_.size());

  PopResult result = {/*num_buffers_popped=*/0,
                      /*moved_remaining_buffers=*/false};

  result.num_buffers_popped = std::max<int32_t>(num_buffered_writes, 0);
  result.num_buffers_popped =
      std::min<int32_t>(result.num_buffers_popped, buffered_writes_.size());
  buffered_writes_.pop_front_n(result.num_buffers_popped);

  if (!buffered_writes_.empty()) {
    // If not all buffered writes are erased, the remaining ones will not cover
    // a continuous prefix of buffer_. We'll fix it by moving the remaining
    // buffers to the beginning of buffer_ and adjust the buffer pointers in all
    // remaining buffered writes.
    // This should happen very rarely, about once per write block.
    result.moved_remaining_buffers = true;
    const char* buffer_before_move = buffered_writes_.front().buffer;
    size_t buffer_len_to_move = buffered_writes_.back().buffer +
                                buffered_writes_.back().buf_len -
                                buffer_before_move;
    memmove(buffer_, buffer_before_move, buffer_len_to_move);

    size_t distance_to_move = buffer_before_move - buffer_;
    for (BufferedWrite& buffered_write : buffered_writes_) {
      buffered_write.buffer -= distance_to_move;
    }

    QUICHE_DCHECK_EQ(buffer_, buffered_writes_.front().buffer);
  }
  QUICHE_DCHECK(Invariants());

  return result;
}

size_t QuicBatchWriterBuffer::SizeInUse() const {
  if (buffered_writes_.empty()) {
    return 0;
  }

  return buffered_writes_.back().buffer + buffered_writes_.back().buf_len -
         buffer_;
}

}  // namespace quic
