/*
 *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include "net/dcsctp/socket/transmission_control_block.h"

#include <algorithm>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "api/units/time_delta.h"
#include "net/dcsctp/packet/chunk/data_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/idata_chunk.h"
#include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
#include "net/dcsctp/packet/chunk/sack_chunk.h"
#include "net/dcsctp/packet/sctp_packet.h"
#include "net/dcsctp/public/dcsctp_options.h"
#include "net/dcsctp/public/types.h"
#include "net/dcsctp/rx/data_tracker.h"
#include "net/dcsctp/rx/reassembly_queue.h"
#include "net/dcsctp/socket/capabilities.h"
#include "net/dcsctp/socket/stream_reset_handler.h"
#include "net/dcsctp/timer/timer.h"
#include "net/dcsctp/tx/retransmission_queue.h"
#include "net/dcsctp/tx/retransmission_timeout.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"

namespace dcsctp {
using ::webrtc::TimeDelta;
using ::webrtc::Timestamp;

TransmissionControlBlock::TransmissionControlBlock(
    TimerManager& timer_manager,
    absl::string_view log_prefix,
    const DcSctpOptions& options,
    const Capabilities& capabilities,
    DcSctpSocketCallbacks& callbacks,
    SendQueue& send_queue,
    VerificationTag my_verification_tag,
    TSN my_initial_tsn,
    VerificationTag peer_verification_tag,
    TSN peer_initial_tsn,
    size_t a_rwnd,
    TieTag tie_tag,
    PacketSender& packet_sender,
    std::function<bool()> is_connection_established)
    : log_prefix_(log_prefix),
      options_(options),
      timer_manager_(timer_manager),
      capabilities_(capabilities),
      callbacks_(callbacks),
      t3_rtx_(timer_manager_.CreateTimer(
          "t3-rtx",
          absl::bind_front(&TransmissionControlBlock::OnRtxTimerExpiry, this),
          TimerOptions(options.rto_initial.ToTimeDelta(),
                       TimerBackoffAlgorithm::kExponential,
                       /*max_restarts=*/std::nullopt,
                       options.max_timer_backoff_duration.has_value()
                           ? options.max_timer_backoff_duration->ToTimeDelta()
                           : TimeDelta::PlusInfinity()))),
      delayed_ack_timer_(timer_manager_.CreateTimer(
          "delayed-ack",
          absl::bind_front(&TransmissionControlBlock::OnDelayedAckTimerExpiry,
                           this),
          TimerOptions(options.delayed_ack_max_timeout.ToTimeDelta(),
                       TimerBackoffAlgorithm::kExponential,
                       /*max_restarts=*/0,
                       /*max_backoff_duration=*/TimeDelta::PlusInfinity(),
                       webrtc::TaskQueueBase::DelayPrecision::kHigh))),
      my_verification_tag_(my_verification_tag),
      my_initial_tsn_(my_initial_tsn),
      peer_verification_tag_(peer_verification_tag),
      peer_initial_tsn_(peer_initial_tsn),
      tie_tag_(tie_tag),
      is_connection_established_(std::move(is_connection_established)),
      packet_sender_(packet_sender),
      rto_(options),
      tx_error_counter_(log_prefix, options),
      data_tracker_(log_prefix, delayed_ack_timer_.get(), peer_initial_tsn),
      reassembly_queue_(log_prefix,
                        options.max_receiver_window_buffer_size,
                        capabilities.message_interleaving),
      retransmission_queue_(
          log_prefix,
          &callbacks_,
          my_initial_tsn,
          a_rwnd,
          send_queue,
          absl::bind_front(&TransmissionControlBlock::ObserveRTT, this),
          [this]() { tx_error_counter_.Clear(); },
          *t3_rtx_,
          options,
          capabilities.partial_reliability,
          capabilities.message_interleaving),
      stream_reset_handler_(log_prefix,
                            this,
                            &timer_manager,
                            &data_tracker_,
                            &reassembly_queue_,
                            &retransmission_queue_),
      heartbeat_handler_(log_prefix, options, this, &timer_manager_) {
  send_queue.EnableMessageInterleaving(capabilities.message_interleaving);
}

void TransmissionControlBlock::ObserveRTT(TimeDelta rtt) {
  TimeDelta prev_rto = rto_.rto();
  rto_.ObserveRTT(rtt);
  RTC_DLOG(LS_VERBOSE) << log_prefix_ << "new rtt=" << webrtc::ToString(rtt)
                       << ", srtt=" << webrtc::ToString(rto_.srtt())
                       << ", rto=" << webrtc::ToString(rto_.rto()) << " ("
                       << webrtc::ToString(prev_rto) << ")";
  t3_rtx_->set_duration(rto_.rto());

  TimeDelta delayed_ack_tmo = std::min(
      rto_.rto() * 0.5, options_.delayed_ack_max_timeout.ToTimeDelta());
  delayed_ack_timer_->set_duration(delayed_ack_tmo);
}

TimeDelta TransmissionControlBlock::OnRtxTimerExpiry() {
  Timestamp now = callbacks_.Now();
  RTC_DLOG(LS_INFO) << log_prefix_ << "Timer " << t3_rtx_->name()
                    << " has expired";
  if (cookie_echo_chunk_.has_value()) {
    // In the COOKIE_ECHO state, let the T1-COOKIE timer trigger
    // retransmissions, to avoid having two timers doing that.
    RTC_DLOG(LS_VERBOSE) << "Not retransmitting as T1-cookie is active.";
  } else {
    if (IncrementTxErrorCounter("t3-rtx expired")) {
      retransmission_queue_.HandleT3RtxTimerExpiry();
      SendBufferedPackets(now);
    }
  }
  return TimeDelta::Zero();
}

TimeDelta TransmissionControlBlock::OnDelayedAckTimerExpiry() {
  data_tracker_.HandleDelayedAckTimerExpiry();
  MaybeSendSack();
  return TimeDelta::Zero();
}

void TransmissionControlBlock::MaybeSendSack() {
  if (data_tracker_.ShouldSendAck(/*also_if_delayed=*/false)) {
    SctpPacket::Builder builder = PacketBuilder();
    builder.Add(
        data_tracker_.CreateSelectiveAck(reassembly_queue_.remaining_bytes()));
    Send(builder);
  }
}

void TransmissionControlBlock::MaybeSendForwardTsn(SctpPacket::Builder& builder,
                                                   Timestamp now) {
  if (now >= limit_forward_tsn_until_ &&
      retransmission_queue_.ShouldSendForwardTsn(now)) {
    if (capabilities_.message_interleaving) {
      builder.Add(retransmission_queue_.CreateIForwardTsn());
    } else {
      builder.Add(retransmission_queue_.CreateForwardTsn());
    }
    // https://datatracker.ietf.org/doc/html/rfc3758
    // "IMPLEMENTATION NOTE: An implementation may wish to limit the number of
    // duplicate FORWARD TSN chunks it sends by ... waiting a full RTT before
    // sending a duplicate FORWARD TSN."
    // "Any delay applied to the sending of FORWARD TSN chunk SHOULD NOT exceed
    // 200ms and MUST NOT exceed 500ms".
    limit_forward_tsn_until_ =
        now + std::min(TimeDelta::Millis(200), rto_.srtt());
  }
}

void TransmissionControlBlock::MaybeSendFastRetransmit() {
  if (!retransmission_queue_.has_data_to_be_fast_retransmitted()) {
    return;
  }

  // https://datatracker.ietf.org/doc/html/rfc4960#section-7.2.4
  // "Determine how many of the earliest (i.e., lowest TSN) DATA chunks marked
  // for retransmission will fit into a single packet, subject to constraint of
  // the path MTU of the destination transport address to which the packet is
  // being sent.  Call this value K. Retransmit those K DATA chunks in a single
  // packet.  When a Fast Retransmit is being performed, the sender SHOULD
  // ignore the value of cwnd and SHOULD NOT delay retransmission for this
  // single packet."

  SctpPacket::Builder builder(peer_verification_tag_, options_);
  auto chunks = retransmission_queue_.GetChunksForFastRetransmit(
      builder.bytes_remaining());
  for (auto& [tsn, data] : chunks) {
    if (capabilities_.message_interleaving) {
      builder.Add(IDataChunk(tsn, std::move(data), false));
    } else {
      builder.Add(DataChunk(tsn, std::move(data), false));
    }
  }
  Send(builder);
}

void TransmissionControlBlock::SendBufferedPackets(SctpPacket::Builder& builder,
                                                   Timestamp now) {
  for (int packet_idx = 0; packet_idx < options_.max_burst; ++packet_idx) {
    // Only add control chunks to the first packet that is sent, if sending
    // multiple packets in one go (as allowed by the congestion window).
    if (packet_idx == 0) {
      if (cookie_echo_chunk_.has_value()) {
        // https://tools.ietf.org/html/rfc4960#section-5.1
        // "The COOKIE ECHO chunk can be bundled with any pending outbound DATA
        // chunks, but it MUST be the first chunk in the packet..."
        RTC_DCHECK(builder.empty());
        builder.Add(*cookie_echo_chunk_);
      }

      // https://tools.ietf.org/html/rfc4960#section-6
      // "Before an endpoint transmits a DATA chunk, if any received DATA
      // chunks have not been acknowledged (e.g., due to delayed ack), the
      // sender should create a SACK and bundle it with the outbound DATA chunk,
      // as long as the size of the final SCTP packet does not exceed the
      // current MTU."
      if (data_tracker_.ShouldSendAck(/*also_if_delayed=*/true)) {
        builder.Add(data_tracker_.CreateSelectiveAck(
            reassembly_queue_.remaining_bytes()));
      }
      MaybeSendForwardTsn(builder, now);
      std::optional<ReConfigChunk> reconfig =
          stream_reset_handler_.MakeStreamResetRequest();
      if (reconfig.has_value()) {
        builder.Add(*reconfig);
      }
    }

    auto chunks =
        retransmission_queue_.GetChunksToSend(now, builder.bytes_remaining());

    if (!chunks.empty()) {
      // https://datatracker.ietf.org/doc/html/rfc9260#section-8.3
      // Sending DATA means that the path is not idle - restart heartbeat timer.
      heartbeat_handler_.RestartTimer();
    }

    for (auto& [tsn, data] : chunks) {
      if (capabilities_.message_interleaving) {
        builder.Add(IDataChunk(tsn, std::move(data), false));
      } else {
        builder.Add(DataChunk(tsn, std::move(data), false));
      }
    }

    // https://www.ietf.org/archive/id/draft-tuexen-tsvwg-sctp-zero-checksum-02.html#section-4.2
    // "When an end point sends a packet containing a COOKIE ECHO chunk, it MUST
    // include a correct CRC32c checksum in the packet containing the COOKIE
    // ECHO chunk."
    bool write_checksum =
        !capabilities_.zero_checksum || cookie_echo_chunk_.has_value();
    if (!packet_sender_.Send(builder, write_checksum)) {
      break;
    }

    if (cookie_echo_chunk_.has_value()) {
      // https://tools.ietf.org/html/rfc4960#section-5.1
      // "...  until the COOKIE ACK is returned the sender MUST NOT send any
      // other packets to the peer."
      break;
    }
  }
}

std::string TransmissionControlBlock::ToString() const {
  rtc::StringBuilder sb;

  sb.AppendFormat(
      "verification_tag=%08x, last_cumulative_ack=%u, capabilities=",
      *peer_verification_tag_, *data_tracker_.last_cumulative_acked_tsn());

  if (capabilities_.partial_reliability) {
    sb << "PR,";
  }
  if (capabilities_.message_interleaving) {
    sb << "IL,";
  }
  if (capabilities_.reconfig) {
    sb << "Reconfig,";
  }
  if (capabilities_.zero_checksum) {
    sb << "ZeroChecksum,";
  }
  sb << " max_in=" << capabilities_.negotiated_maximum_incoming_streams;
  sb << " max_out=" << capabilities_.negotiated_maximum_outgoing_streams;

  return sb.Release();
}

HandoverReadinessStatus TransmissionControlBlock::GetHandoverReadiness() const {
  HandoverReadinessStatus status;
  status.Add(data_tracker_.GetHandoverReadiness());
  status.Add(stream_reset_handler_.GetHandoverReadiness());
  status.Add(reassembly_queue_.GetHandoverReadiness());
  status.Add(retransmission_queue_.GetHandoverReadiness());
  return status;
}

void TransmissionControlBlock::AddHandoverState(
    DcSctpSocketHandoverState& state) {
  state.capabilities.partial_reliability = capabilities_.partial_reliability;
  state.capabilities.message_interleaving = capabilities_.message_interleaving;
  state.capabilities.reconfig = capabilities_.reconfig;
  state.capabilities.zero_checksum = capabilities_.zero_checksum;
  state.capabilities.negotiated_maximum_incoming_streams =
      capabilities_.negotiated_maximum_incoming_streams;
  state.capabilities.negotiated_maximum_outgoing_streams =
      capabilities_.negotiated_maximum_outgoing_streams;

  state.my_verification_tag = my_verification_tag().value();
  state.peer_verification_tag = peer_verification_tag().value();
  state.my_initial_tsn = my_initial_tsn().value();
  state.peer_initial_tsn = peer_initial_tsn().value();
  state.tie_tag = tie_tag().value();

  data_tracker_.AddHandoverState(state);
  stream_reset_handler_.AddHandoverState(state);
  reassembly_queue_.AddHandoverState(state);
  retransmission_queue_.AddHandoverState(state);
}

void TransmissionControlBlock::RestoreFromState(
    const DcSctpSocketHandoverState& state) {
  data_tracker_.RestoreFromState(state);
  retransmission_queue_.RestoreFromState(state);
  reassembly_queue_.RestoreFromState(state);
}
}  // namespace dcsctp
