// Copyright (c) 2018 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/tools/quic_tcp_like_trace_converter.h"

#include "quiche/quic/core/quic_constants.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"

namespace quic {

QuicTcpLikeTraceConverter::QuicTcpLikeTraceConverter()
    : largest_observed_control_frame_id_(kInvalidControlFrameId),
      connection_offset_(0) {}

QuicTcpLikeTraceConverter::StreamOffsetSegment::StreamOffsetSegment()
    : connection_offset(0) {}

QuicTcpLikeTraceConverter::StreamOffsetSegment::StreamOffsetSegment(
    QuicStreamOffset stream_offset, uint64_t connection_offset,
    QuicByteCount data_length)
    : stream_data(stream_offset, stream_offset + data_length),
      connection_offset(connection_offset) {}

QuicTcpLikeTraceConverter::StreamInfo::StreamInfo() : fin(false) {}

QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnCryptoFrameSent(
    EncryptionLevel level, QuicStreamOffset offset, QuicByteCount data_length) {
  if (level >= NUM_ENCRYPTION_LEVELS) {
    QUIC_BUG(quic_bug_10907_1) << "Invalid encryption level";
    return {};
  }
  return OnFrameSent(offset, data_length, /*fin=*/false,
                     &crypto_frames_info_[level]);
}

QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnStreamFrameSent(
    QuicStreamId stream_id, QuicStreamOffset offset, QuicByteCount data_length,
    bool fin) {
  return OnFrameSent(
      offset, data_length, fin,
      &streams_info_.emplace(stream_id, StreamInfo()).first->second);
}

QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnFrameSent(
    QuicStreamOffset offset, QuicByteCount data_length, bool fin,
    StreamInfo* info) {
  QuicIntervalSet<uint64_t> connection_offsets;
  if (fin) {
    // Stream fin consumes a connection offset.
    ++data_length;
  }
  // Get connection offsets of retransmission data in this frame.
  for (const auto& segment : info->segments) {
    QuicInterval<QuicStreamOffset> retransmission(offset, offset + data_length);
    retransmission.IntersectWith(segment.stream_data);
    if (retransmission.Empty()) {
      continue;
    }
    const uint64_t connection_offset = segment.connection_offset +
                                       retransmission.min() -
                                       segment.stream_data.min();
    connection_offsets.Add(connection_offset,
                           connection_offset + retransmission.Length());
  }

  if (info->fin) {
    return connection_offsets;
  }

  // Get connection offsets of new data in this frame.
  QuicStreamOffset least_unsent_offset =
      info->segments.empty() ? 0 : info->segments.back().stream_data.max();
  if (least_unsent_offset >= offset + data_length) {
    return connection_offsets;
  }
  // Ignore out-of-order stream data so that as connection offset increases,
  // stream offset increases.
  QuicStreamOffset new_data_offset = std::max(least_unsent_offset, offset);
  QuicByteCount new_data_length = offset + data_length - new_data_offset;
  connection_offsets.Add(connection_offset_,
                         connection_offset_ + new_data_length);
  if (!info->segments.empty() && new_data_offset == least_unsent_offset &&
      connection_offset_ == info->segments.back().connection_offset +
                                info->segments.back().stream_data.Length()) {
    // Extend the last segment if both stream and connection offsets are
    // contiguous.
    info->segments.back().stream_data.SetMax(new_data_offset + new_data_length);
  } else {
    info->segments.emplace_back(new_data_offset, connection_offset_,
                                new_data_length);
  }
  info->fin = fin;
  connection_offset_ += new_data_length;

  return connection_offsets;
}

QuicInterval<uint64_t> QuicTcpLikeTraceConverter::OnControlFrameSent(
    QuicControlFrameId control_frame_id, QuicByteCount control_frame_length) {
  if (control_frame_id > largest_observed_control_frame_id_) {
    // New control frame.
    QuicInterval<uint64_t> connection_offset = QuicInterval<uint64_t>(
        connection_offset_, connection_offset_ + control_frame_length);
    connection_offset_ += control_frame_length;
    control_frames_info_[control_frame_id] = connection_offset;
    largest_observed_control_frame_id_ = control_frame_id;
    return connection_offset;
  }
  const auto iter = control_frames_info_.find(control_frame_id);
  if (iter == control_frames_info_.end()) {
    // Ignore out of order control frames.
    return {};
  }
  return iter->second;
}

}  // namespace quic
