/*
 *  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/dcsctp_socket.h"

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

#include "absl/functional/bind_front.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "net/dcsctp/packet/chunk/abort_chunk.h"
#include "net/dcsctp/packet/chunk/chunk.h"
#include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
#include "net/dcsctp/packet/chunk/cookie_echo_chunk.h"
#include "net/dcsctp/packet/chunk/data_chunk.h"
#include "net/dcsctp/packet/chunk/data_common.h"
#include "net/dcsctp/packet/chunk/error_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_common.h"
#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
#include "net/dcsctp/packet/chunk/heartbeat_request_chunk.h"
#include "net/dcsctp/packet/chunk/idata_chunk.h"
#include "net/dcsctp/packet/chunk/iforward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/init_ack_chunk.h"
#include "net/dcsctp/packet/chunk/init_chunk.h"
#include "net/dcsctp/packet/chunk/reconfig_chunk.h"
#include "net/dcsctp/packet/chunk/sack_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_ack_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_chunk.h"
#include "net/dcsctp/packet/chunk/shutdown_complete_chunk.h"
#include "net/dcsctp/packet/chunk_validators.h"
#include "net/dcsctp/packet/data.h"
#include "net/dcsctp/packet/error_cause/cookie_received_while_shutting_down_cause.h"
#include "net/dcsctp/packet/error_cause/error_cause.h"
#include "net/dcsctp/packet/error_cause/no_user_data_cause.h"
#include "net/dcsctp/packet/error_cause/out_of_resource_error_cause.h"
#include "net/dcsctp/packet/error_cause/protocol_violation_cause.h"
#include "net/dcsctp/packet/error_cause/unrecognized_chunk_type_cause.h"
#include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
#include "net/dcsctp/packet/parameter/forward_tsn_supported_parameter.h"
#include "net/dcsctp/packet/parameter/parameter.h"
#include "net/dcsctp/packet/parameter/state_cookie_parameter.h"
#include "net/dcsctp/packet/parameter/supported_extensions_parameter.h"
#include "net/dcsctp/packet/sctp_packet.h"
#include "net/dcsctp/packet/tlv_trait.h"
#include "net/dcsctp/public/dcsctp_message.h"
#include "net/dcsctp/public/dcsctp_options.h"
#include "net/dcsctp/public/dcsctp_socket.h"
#include "net/dcsctp/public/packet_observer.h"
#include "net/dcsctp/rx/data_tracker.h"
#include "net/dcsctp/rx/reassembly_queue.h"
#include "net/dcsctp/socket/callback_deferrer.h"
#include "net/dcsctp/socket/capabilities.h"
#include "net/dcsctp/socket/heartbeat_handler.h"
#include "net/dcsctp/socket/state_cookie.h"
#include "net/dcsctp/socket/stream_reset_handler.h"
#include "net/dcsctp/socket/transmission_control_block.h"
#include "net/dcsctp/timer/timer.h"
#include "net/dcsctp/tx/retransmission_queue.h"
#include "net/dcsctp/tx/send_queue.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/strings/string_format.h"

namespace dcsctp {
namespace {

// https://tools.ietf.org/html/rfc4960#section-5.1
constexpr uint32_t kMinVerificationTag = 1;
constexpr uint32_t kMaxVerificationTag = std::numeric_limits<uint32_t>::max();

// https://tools.ietf.org/html/rfc4960#section-3.3.2
constexpr uint32_t kMinInitialTsn = 0;
constexpr uint32_t kMaxInitialTsn = std::numeric_limits<uint32_t>::max();

Capabilities GetCapabilities(const DcSctpOptions& options,
                             const Parameters& parameters) {
  Capabilities capabilities;
  absl::optional<SupportedExtensionsParameter> supported_extensions =
      parameters.get<SupportedExtensionsParameter>();

  if (options.enable_partial_reliability) {
    capabilities.partial_reliability =
        parameters.get<ForwardTsnSupportedParameter>().has_value();
    if (supported_extensions.has_value()) {
      capabilities.partial_reliability |=
          supported_extensions->supports(ForwardTsnChunk::kType);
    }
  }

  if (options.enable_message_interleaving && supported_extensions.has_value()) {
    capabilities.message_interleaving =
        supported_extensions->supports(IDataChunk::kType) &&
        supported_extensions->supports(IForwardTsnChunk::kType);
  }
  if (supported_extensions.has_value() &&
      supported_extensions->supports(ReConfigChunk::kType)) {
    capabilities.reconfig = true;
  }
  return capabilities;
}

void AddCapabilityParameters(const DcSctpOptions& options,
                             Parameters::Builder& builder) {
  std::vector<uint8_t> chunk_types = {ReConfigChunk::kType};

  if (options.enable_partial_reliability) {
    builder.Add(ForwardTsnSupportedParameter());
    chunk_types.push_back(ForwardTsnChunk::kType);
  }
  if (options.enable_message_interleaving) {
    chunk_types.push_back(IDataChunk::kType);
    chunk_types.push_back(IForwardTsnChunk::kType);
  }
  builder.Add(SupportedExtensionsParameter(std::move(chunk_types)));
}

TieTag MakeTieTag(DcSctpSocketCallbacks& cb) {
  uint32_t tie_tag_upper =
      cb.GetRandomInt(0, std::numeric_limits<uint32_t>::max());
  uint32_t tie_tag_lower =
      cb.GetRandomInt(1, std::numeric_limits<uint32_t>::max());
  return TieTag(static_cast<uint64_t>(tie_tag_upper) << 32 |
                static_cast<uint64_t>(tie_tag_lower));
}

SctpImplementation DeterminePeerImplementation(
    rtc::ArrayView<const uint8_t> cookie) {
  if (cookie.size() > 8) {
    absl::string_view magic(reinterpret_cast<const char*>(cookie.data()), 8);
    if (magic == "dcSCTP00") {
      return SctpImplementation::kDcsctp;
    }
    if (magic == "KAME-BSD") {
      return SctpImplementation::kUsrSctp;
    }
  }
  return SctpImplementation::kOther;
}
}  // namespace

DcSctpSocket::DcSctpSocket(absl::string_view log_prefix,
                           DcSctpSocketCallbacks& callbacks,
                           std::unique_ptr<PacketObserver> packet_observer,
                           const DcSctpOptions& options)
    : log_prefix_(std::string(log_prefix) + ": "),
      packet_observer_(std::move(packet_observer)),
      options_(options),
      callbacks_(callbacks),
      timer_manager_([this]() { return callbacks_.CreateTimeout(); }),
      t1_init_(timer_manager_.CreateTimer(
          "t1-init",
          absl::bind_front(&DcSctpSocket::OnInitTimerExpiry, this),
          TimerOptions(options.t1_init_timeout,
                       TimerBackoffAlgorithm::kExponential,
                       options.max_init_retransmits))),
      t1_cookie_(timer_manager_.CreateTimer(
          "t1-cookie",
          absl::bind_front(&DcSctpSocket::OnCookieTimerExpiry, this),
          TimerOptions(options.t1_cookie_timeout,
                       TimerBackoffAlgorithm::kExponential,
                       options.max_init_retransmits))),
      t2_shutdown_(timer_manager_.CreateTimer(
          "t2-shutdown",
          absl::bind_front(&DcSctpSocket::OnShutdownTimerExpiry, this),
          TimerOptions(options.t2_shutdown_timeout,
                       TimerBackoffAlgorithm::kExponential,
                       options.max_retransmissions))),
      packet_sender_(callbacks_,
                     absl::bind_front(&DcSctpSocket::OnSentPacket, this)),
      send_queue_(
          log_prefix_,
          options_.max_send_buffer_size,
          [this](StreamID stream_id) {
            callbacks_.OnBufferedAmountLow(stream_id);
          },
          options_.total_buffered_amount_low_threshold,
          [this]() { callbacks_.OnTotalBufferedAmountLow(); }) {}

std::string DcSctpSocket::log_prefix() const {
  return log_prefix_ + "[" + std::string(ToString(state_)) + "] ";
}

bool DcSctpSocket::IsConsistent() const {
  if (tcb_ != nullptr && tcb_->reassembly_queue().HasMessages()) {
    return false;
  }
  switch (state_) {
    case State::kClosed:
      return (tcb_ == nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && !t2_shutdown_->is_running());
    case State::kCookieWait:
      return (tcb_ == nullptr && t1_init_->is_running() &&
              !t1_cookie_->is_running() && !t2_shutdown_->is_running());
    case State::kCookieEchoed:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              t1_cookie_->is_running() && !t2_shutdown_->is_running() &&
              tcb_->has_cookie_echo_chunk());
    case State::kEstablished:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && !t2_shutdown_->is_running());
    case State::kShutdownPending:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && !t2_shutdown_->is_running());
    case State::kShutdownSent:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && t2_shutdown_->is_running());
    case State::kShutdownReceived:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && !t2_shutdown_->is_running());
    case State::kShutdownAckSent:
      return (tcb_ != nullptr && !t1_init_->is_running() &&
              !t1_cookie_->is_running() && t2_shutdown_->is_running());
  }
}

constexpr absl::string_view DcSctpSocket::ToString(DcSctpSocket::State state) {
  switch (state) {
    case DcSctpSocket::State::kClosed:
      return "CLOSED";
    case DcSctpSocket::State::kCookieWait:
      return "COOKIE_WAIT";
    case DcSctpSocket::State::kCookieEchoed:
      return "COOKIE_ECHOED";
    case DcSctpSocket::State::kEstablished:
      return "ESTABLISHED";
    case DcSctpSocket::State::kShutdownPending:
      return "SHUTDOWN_PENDING";
    case DcSctpSocket::State::kShutdownSent:
      return "SHUTDOWN_SENT";
    case DcSctpSocket::State::kShutdownReceived:
      return "SHUTDOWN_RECEIVED";
    case DcSctpSocket::State::kShutdownAckSent:
      return "SHUTDOWN_ACK_SENT";
  }
}

void DcSctpSocket::SetState(State state, absl::string_view reason) {
  if (state_ != state) {
    RTC_DLOG(LS_VERBOSE) << log_prefix_ << "Socket state changed from "
                         << ToString(state_) << " to " << ToString(state)
                         << " due to " << reason;
    state_ = state;
  }
}

void DcSctpSocket::SendInit() {
  Parameters::Builder params_builder;
  AddCapabilityParameters(options_, params_builder);
  InitChunk init(/*initiate_tag=*/connect_params_.verification_tag,
                 /*a_rwnd=*/options_.max_receiver_window_buffer_size,
                 options_.announced_maximum_outgoing_streams,
                 options_.announced_maximum_incoming_streams,
                 connect_params_.initial_tsn, params_builder.Build());
  SctpPacket::Builder b(VerificationTag(0), options_);
  b.Add(init);
  packet_sender_.Send(b);
}

void DcSctpSocket::MakeConnectionParameters() {
  VerificationTag new_verification_tag(
      callbacks_.GetRandomInt(kMinVerificationTag, kMaxVerificationTag));
  TSN initial_tsn(callbacks_.GetRandomInt(kMinInitialTsn, kMaxInitialTsn));
  connect_params_.initial_tsn = initial_tsn;
  connect_params_.verification_tag = new_verification_tag;
}

void DcSctpSocket::Connect() {
  if (state_ == State::kClosed) {
    MakeConnectionParameters();
    RTC_DLOG(LS_INFO)
        << log_prefix()
        << rtc::StringFormat(
               "Connecting. my_verification_tag=%08x, my_initial_tsn=%u",
               *connect_params_.verification_tag, *connect_params_.initial_tsn);
    SendInit();
    t1_init_->Start();
    SetState(State::kCookieWait, "Connect called");
  } else {
    RTC_DLOG(LS_WARNING) << log_prefix()
                         << "Called Connect on a socket that is not closed";
  }
  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::RestoreFromState(const DcSctpSocketHandoverState& state) {
  if (state_ != State::kClosed) {
    callbacks_.OnError(ErrorKind::kUnsupportedOperation,
                       "Only closed socket can be restored from state");
  } else {
    if (state.socket_state ==
        DcSctpSocketHandoverState::SocketState::kConnected) {
      VerificationTag my_verification_tag =
          VerificationTag(state.my_verification_tag);
      connect_params_.verification_tag = my_verification_tag;

      Capabilities capabilities;
      capabilities.partial_reliability = state.capabilities.partial_reliability;
      capabilities.message_interleaving =
          state.capabilities.message_interleaving;
      capabilities.reconfig = state.capabilities.reconfig;

      send_queue_.RestoreFromState(state);

      tcb_ = std::make_unique<TransmissionControlBlock>(
          timer_manager_, log_prefix_, options_, capabilities, callbacks_,
          send_queue_, my_verification_tag, TSN(state.my_initial_tsn),
          VerificationTag(state.peer_verification_tag),
          TSN(state.peer_initial_tsn), static_cast<size_t>(0),
          TieTag(state.tie_tag), packet_sender_,
          [this]() { return state_ == State::kEstablished; }, &state);
      RTC_DLOG(LS_VERBOSE) << log_prefix() << "Created peer TCB from state: "
                           << tcb_->ToString();

      SetState(State::kEstablished, "restored from handover state");
      callbacks_.OnConnected();
    }
  }

  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::Shutdown() {
  if (tcb_ != nullptr) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "Upon receipt of the SHUTDOWN primitive from its upper layer, the
    // endpoint enters the SHUTDOWN-PENDING state and remains there until all
    // outstanding data has been acknowledged by its peer."

    // TODO(webrtc:12739): Remove this check, as it just hides the problem that
    // the socket can transition from ShutdownSent to ShutdownPending, or
    // ShutdownAckSent to ShutdownPending which is illegal.
    if (state_ != State::kShutdownSent && state_ != State::kShutdownAckSent) {
      SetState(State::kShutdownPending, "Shutdown called");
      t1_init_->Stop();
      t1_cookie_->Stop();
      MaybeSendShutdownOrAck();
    }
  } else {
    // Connection closed before even starting to connect, or during the initial
    // connection phase. There is no outstanding data, so the socket can just
    // be closed (stopping any connection timers, if any), as this is the
    // client's intention, by calling Shutdown.
    InternalClose(ErrorKind::kNoError, "");
  }
  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::Close() {
  if (state_ != State::kClosed) {
    if (tcb_ != nullptr) {
      SctpPacket::Builder b = tcb_->PacketBuilder();
      b.Add(AbortChunk(/*filled_in_verification_tag=*/true,
                       Parameters::Builder()
                           .Add(UserInitiatedAbortCause("Close called"))
                           .Build()));
      packet_sender_.Send(b);
    }
    InternalClose(ErrorKind::kNoError, "");
  } else {
    RTC_DLOG(LS_INFO) << log_prefix() << "Called Close on a closed socket";
  }
  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::CloseConnectionBecauseOfTooManyTransmissionErrors() {
  packet_sender_.Send(tcb_->PacketBuilder().Add(AbortChunk(
      true, Parameters::Builder()
                .Add(UserInitiatedAbortCause("Too many retransmissions"))
                .Build())));
  InternalClose(ErrorKind::kTooManyRetries, "Too many retransmissions");
}

void DcSctpSocket::InternalClose(ErrorKind error, absl::string_view message) {
  if (state_ != State::kClosed) {
    t1_init_->Stop();
    t1_cookie_->Stop();
    t2_shutdown_->Stop();
    tcb_ = nullptr;

    if (error == ErrorKind::kNoError) {
      callbacks_.OnClosed();
    } else {
      callbacks_.OnAborted(error, message);
    }
    SetState(State::kClosed, message);
  }
  // This method's purpose is to abort/close and make it consistent by ensuring
  // that e.g. all timers really are stopped.
  RTC_DCHECK(IsConsistent());
}

SendStatus DcSctpSocket::Send(DcSctpMessage message,
                              const SendOptions& send_options) {
  if (message.payload().empty()) {
    callbacks_.OnError(ErrorKind::kProtocolViolation,
                       "Unable to send empty message");
    return SendStatus::kErrorMessageEmpty;
  }
  if (message.payload().size() > options_.max_message_size) {
    callbacks_.OnError(ErrorKind::kProtocolViolation,
                       "Unable to send too large message");
    return SendStatus::kErrorMessageTooLarge;
  }
  if (state_ == State::kShutdownPending || state_ == State::kShutdownSent ||
      state_ == State::kShutdownReceived || state_ == State::kShutdownAckSent) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "An endpoint should reject any new data request from its upper layer
    // if it is in the SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED, or
    // SHUTDOWN-ACK-SENT state."
    callbacks_.OnError(ErrorKind::kWrongSequence,
                       "Unable to send message as the socket is shutting down");
    return SendStatus::kErrorShuttingDown;
  }
  if (send_queue_.IsFull()) {
    callbacks_.OnError(ErrorKind::kResourceExhaustion,
                       "Unable to send message as the send queue is full");
    return SendStatus::kErrorResourceExhaustion;
  }

  TimeMs now = callbacks_.TimeMillis();
  ++metrics_.tx_messages_count;
  send_queue_.Add(now, std::move(message), send_options);
  if (tcb_ != nullptr) {
    tcb_->SendBufferedPackets(now);
  }

  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
  return SendStatus::kSuccess;
}

ResetStreamsStatus DcSctpSocket::ResetStreams(
    rtc::ArrayView<const StreamID> outgoing_streams) {
  if (tcb_ == nullptr) {
    callbacks_.OnError(ErrorKind::kWrongSequence,
                       "Can't reset streams as the socket is not connected");
    return ResetStreamsStatus::kNotConnected;
  }
  if (!tcb_->capabilities().reconfig) {
    callbacks_.OnError(ErrorKind::kUnsupportedOperation,
                       "Can't reset streams as the peer doesn't support it");
    return ResetStreamsStatus::kNotSupported;
  }

  tcb_->stream_reset_handler().ResetStreams(outgoing_streams);
  absl::optional<ReConfigChunk> reconfig =
      tcb_->stream_reset_handler().MakeStreamResetRequest();
  if (reconfig.has_value()) {
    SctpPacket::Builder builder = tcb_->PacketBuilder();
    builder.Add(*reconfig);
    packet_sender_.Send(builder);
  }

  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
  return ResetStreamsStatus::kPerformed;
}

SocketState DcSctpSocket::state() const {
  switch (state_) {
    case State::kClosed:
      return SocketState::kClosed;
    case State::kCookieWait:
      ABSL_FALLTHROUGH_INTENDED;
    case State::kCookieEchoed:
      return SocketState::kConnecting;
    case State::kEstablished:
      return SocketState::kConnected;
    case State::kShutdownPending:
      ABSL_FALLTHROUGH_INTENDED;
    case State::kShutdownSent:
      ABSL_FALLTHROUGH_INTENDED;
    case State::kShutdownReceived:
      ABSL_FALLTHROUGH_INTENDED;
    case State::kShutdownAckSent:
      return SocketState::kShuttingDown;
  }
}

void DcSctpSocket::SetMaxMessageSize(size_t max_message_size) {
  options_.max_message_size = max_message_size;
}

size_t DcSctpSocket::buffered_amount(StreamID stream_id) const {
  return send_queue_.buffered_amount(stream_id);
}

size_t DcSctpSocket::buffered_amount_low_threshold(StreamID stream_id) const {
  return send_queue_.buffered_amount_low_threshold(stream_id);
}

void DcSctpSocket::SetBufferedAmountLowThreshold(StreamID stream_id,
                                                 size_t bytes) {
  send_queue_.SetBufferedAmountLowThreshold(stream_id, bytes);
}

Metrics DcSctpSocket::GetMetrics() const {
  Metrics metrics = metrics_;

  if (tcb_ != nullptr) {
    // Update the metrics with some stats that are extracted from
    // sub-components.
    metrics.cwnd_bytes = tcb_->cwnd();
    metrics.srtt_ms = tcb_->current_srtt().value();
    size_t packet_payload_size =
        options_.mtu - SctpPacket::kHeaderSize - DataChunk::kHeaderSize;
    metrics.unack_data_count =
        tcb_->retransmission_queue().outstanding_items() +
        (send_queue_.total_buffered_amount() + packet_payload_size - 1) /
            packet_payload_size;
    metrics.peer_rwnd_bytes = tcb_->retransmission_queue().rwnd();
  }

  return metrics;
}

void DcSctpSocket::MaybeSendShutdownOnPacketReceived(const SctpPacket& packet) {
  if (state_ == State::kShutdownSent) {
    bool has_data_chunk =
        std::find_if(packet.descriptors().begin(), packet.descriptors().end(),
                     [](const SctpPacket::ChunkDescriptor& descriptor) {
                       return descriptor.type == DataChunk::kType;
                     }) != packet.descriptors().end();
    if (has_data_chunk) {
      // https://tools.ietf.org/html/rfc4960#section-9.2
      // "While in the SHUTDOWN-SENT state, the SHUTDOWN sender MUST immediately
      // respond to each received packet containing one or more DATA chunks with
      // a SHUTDOWN chunk and restart the T2-shutdown timer.""
      SendShutdown();
      t2_shutdown_->set_duration(tcb_->current_rto());
      t2_shutdown_->Start();
    }
  }
}

bool DcSctpSocket::ValidatePacket(const SctpPacket& packet) {
  const CommonHeader& header = packet.common_header();
  VerificationTag my_verification_tag =
      tcb_ != nullptr ? tcb_->my_verification_tag() : VerificationTag(0);

  if (header.verification_tag == VerificationTag(0)) {
    if (packet.descriptors().size() == 1 &&
        packet.descriptors()[0].type == InitChunk::kType) {
      // https://tools.ietf.org/html/rfc4960#section-8.5.1
      // "When an endpoint receives an SCTP packet with the Verification Tag
      // set to 0, it should verify that the packet contains only an INIT chunk.
      // Otherwise, the receiver MUST silently discard the packet.""
      return true;
    }
    callbacks_.OnError(
        ErrorKind::kParseFailed,
        "Only a single INIT chunk can be present in packets sent on "
        "verification_tag = 0");
    return false;
  }

  if (packet.descriptors().size() == 1 &&
      packet.descriptors()[0].type == AbortChunk::kType) {
    // https://tools.ietf.org/html/rfc4960#section-8.5.1
    // "The receiver of an ABORT MUST accept the packet if the Verification
    // Tag field of the packet matches its own tag and the T bit is not set OR
    // if it is set to its peer's tag and the T bit is set in the Chunk Flags.
    // Otherwise, the receiver MUST silently discard the packet and take no
    // further action."
    bool t_bit = (packet.descriptors()[0].flags & 0x01) != 0;
    if (t_bit && tcb_ == nullptr) {
      // Can't verify the tag - assume it's okey.
      return true;
    }
    if ((!t_bit && header.verification_tag == my_verification_tag) ||
        (t_bit && header.verification_tag == tcb_->peer_verification_tag())) {
      return true;
    }
    callbacks_.OnError(ErrorKind::kParseFailed,
                       "ABORT chunk verification tag was wrong");
    return false;
  }

  if (packet.descriptors()[0].type == InitAckChunk::kType) {
    if (header.verification_tag == connect_params_.verification_tag) {
      return true;
    }
    callbacks_.OnError(
        ErrorKind::kParseFailed,
        rtc::StringFormat(
            "Packet has invalid verification tag: %08x, expected %08x",
            *header.verification_tag, *connect_params_.verification_tag));
    return false;
  }

  if (packet.descriptors()[0].type == CookieEchoChunk::kType) {
    // Handled in chunk handler (due to RFC 4960, section 5.2.4).
    return true;
  }

  if (packet.descriptors().size() == 1 &&
      packet.descriptors()[0].type == ShutdownCompleteChunk::kType) {
    // https://tools.ietf.org/html/rfc4960#section-8.5.1
    // "The receiver of a SHUTDOWN COMPLETE shall accept the packet if the
    // Verification Tag field of the packet matches its own tag and the T bit is
    // not set OR if it is set to its peer's tag and the T bit is set in the
    // Chunk Flags.  Otherwise, the receiver MUST silently discard the packet
    // and take no further action."
    bool t_bit = (packet.descriptors()[0].flags & 0x01) != 0;
    if (t_bit && tcb_ == nullptr) {
      // Can't verify the tag - assume it's okey.
      return true;
    }
    if ((!t_bit && header.verification_tag == my_verification_tag) ||
        (t_bit && header.verification_tag == tcb_->peer_verification_tag())) {
      return true;
    }
    callbacks_.OnError(ErrorKind::kParseFailed,
                       "SHUTDOWN_COMPLETE chunk verification tag was wrong");
    return false;
  }

  // https://tools.ietf.org/html/rfc4960#section-8.5
  // "When receiving an SCTP packet, the endpoint MUST ensure that the value
  // in the Verification Tag field of the received SCTP packet matches its own
  // tag.  If the received Verification Tag value does not match the receiver's
  // own tag value, the receiver shall silently discard the packet and shall not
  // process it any further..."
  if (header.verification_tag == my_verification_tag) {
    return true;
  }

  callbacks_.OnError(
      ErrorKind::kParseFailed,
      rtc::StringFormat(
          "Packet has invalid verification tag: %08x, expected %08x",
          *header.verification_tag, *my_verification_tag));
  return false;
}

void DcSctpSocket::HandleTimeout(TimeoutID timeout_id) {
  timer_manager_.HandleTimeout(timeout_id);

  if (tcb_ != nullptr && tcb_->HasTooManyTxErrors()) {
    // Tearing down the TCB has to be done outside the handlers.
    CloseConnectionBecauseOfTooManyTransmissionErrors();
  }

  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::ReceivePacket(rtc::ArrayView<const uint8_t> data) {
  ++metrics_.rx_packets_count;

  if (packet_observer_ != nullptr) {
    packet_observer_->OnReceivedPacket(callbacks_.TimeMillis(), data);
  }

  absl::optional<SctpPacket> packet =
      SctpPacket::Parse(data, options_.disable_checksum_verification);
  if (!packet.has_value()) {
    // https://tools.ietf.org/html/rfc4960#section-6.8
    // "The default procedure for handling invalid SCTP packets is to
    // silently discard them."
    callbacks_.OnError(ErrorKind::kParseFailed,
                       "Failed to parse received SCTP packet");
    RTC_DCHECK(IsConsistent());
    callbacks_.TriggerDeferred();
    return;
  }

  if (RTC_DLOG_IS_ON) {
    for (const auto& descriptor : packet->descriptors()) {
      RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received "
                           << DebugConvertChunkToString(descriptor.data);
    }
  }

  if (!ValidatePacket(*packet)) {
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Packet failed verification tag check - dropping";
    RTC_DCHECK(IsConsistent());
    callbacks_.TriggerDeferred();
    return;
  }

  MaybeSendShutdownOnPacketReceived(*packet);

  for (const auto& descriptor : packet->descriptors()) {
    if (!Dispatch(packet->common_header(), descriptor)) {
      break;
    }
  }

  if (tcb_ != nullptr) {
    tcb_->data_tracker().ObservePacketEnd();
    tcb_->MaybeSendSack();
  }

  RTC_DCHECK(IsConsistent());
  callbacks_.TriggerDeferred();
}

void DcSctpSocket::DebugPrintOutgoing(rtc::ArrayView<const uint8_t> payload) {
  auto packet = SctpPacket::Parse(payload);
  RTC_DCHECK(packet.has_value());

  for (const auto& desc : packet->descriptors()) {
    RTC_DLOG(LS_VERBOSE) << log_prefix() << "Sent "
                         << DebugConvertChunkToString(desc.data);
  }
}

bool DcSctpSocket::Dispatch(const CommonHeader& header,
                            const SctpPacket::ChunkDescriptor& descriptor) {
  switch (descriptor.type) {
    case DataChunk::kType:
      HandleData(header, descriptor);
      break;
    case InitChunk::kType:
      HandleInit(header, descriptor);
      break;
    case InitAckChunk::kType:
      HandleInitAck(header, descriptor);
      break;
    case SackChunk::kType:
      HandleSack(header, descriptor);
      break;
    case HeartbeatRequestChunk::kType:
      HandleHeartbeatRequest(header, descriptor);
      break;
    case HeartbeatAckChunk::kType:
      HandleHeartbeatAck(header, descriptor);
      break;
    case AbortChunk::kType:
      HandleAbort(header, descriptor);
      break;
    case ErrorChunk::kType:
      HandleError(header, descriptor);
      break;
    case CookieEchoChunk::kType:
      HandleCookieEcho(header, descriptor);
      break;
    case CookieAckChunk::kType:
      HandleCookieAck(header, descriptor);
      break;
    case ShutdownChunk::kType:
      HandleShutdown(header, descriptor);
      break;
    case ShutdownAckChunk::kType:
      HandleShutdownAck(header, descriptor);
      break;
    case ShutdownCompleteChunk::kType:
      HandleShutdownComplete(header, descriptor);
      break;
    case ReConfigChunk::kType:
      HandleReconfig(header, descriptor);
      break;
    case ForwardTsnChunk::kType:
      HandleForwardTsn(header, descriptor);
      break;
    case IDataChunk::kType:
      HandleIData(header, descriptor);
      break;
    case IForwardTsnChunk::kType:
      HandleForwardTsn(header, descriptor);
      break;
    default:
      return HandleUnrecognizedChunk(descriptor);
  }
  return true;
}

bool DcSctpSocket::HandleUnrecognizedChunk(
    const SctpPacket::ChunkDescriptor& descriptor) {
  bool report_as_error = (descriptor.type & 0x40) != 0;
  bool continue_processing = (descriptor.type & 0x80) != 0;
  RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received unknown chunk: "
                       << static_cast<int>(descriptor.type);
  if (report_as_error) {
    rtc::StringBuilder sb;
    sb << "Received unknown chunk of type: "
       << static_cast<int>(descriptor.type) << " with report-error bit set";
    callbacks_.OnError(ErrorKind::kParseFailed, sb.str());
    RTC_DLOG(LS_VERBOSE)
        << log_prefix()
        << "Unknown chunk, with type indicating it should be reported.";

    // https://tools.ietf.org/html/rfc4960#section-3.2
    // "... report in an ERROR chunk using the 'Unrecognized Chunk Type'
    // cause."
    if (tcb_ != nullptr) {
      // Need TCB - this chunk must be sent with a correct verification tag.
      packet_sender_.Send(tcb_->PacketBuilder().Add(
          ErrorChunk(Parameters::Builder()
                         .Add(UnrecognizedChunkTypeCause(std::vector<uint8_t>(
                             descriptor.data.begin(), descriptor.data.end())))
                         .Build())));
    }
  }
  if (!continue_processing) {
    // https://tools.ietf.org/html/rfc4960#section-3.2
    // "Stop processing this SCTP packet and discard it, do not process any
    // further chunks within it."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Unknown chunk, with type indicating not to "
                            "process any further chunks";
  }

  return continue_processing;
}

absl::optional<DurationMs> DcSctpSocket::OnInitTimerExpiry() {
  RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_init_->name()
                       << " has expired: " << t1_init_->expiration_count()
                       << "/" << t1_init_->options().max_restarts.value_or(-1);
  RTC_DCHECK(state_ == State::kCookieWait);

  if (t1_init_->is_running()) {
    SendInit();
  } else {
    InternalClose(ErrorKind::kTooManyRetries, "No INIT_ACK received");
  }
  RTC_DCHECK(IsConsistent());
  return absl::nullopt;
}

absl::optional<DurationMs> DcSctpSocket::OnCookieTimerExpiry() {
  // https://tools.ietf.org/html/rfc4960#section-4
  // "If the T1-cookie timer expires, the endpoint MUST retransmit COOKIE
  // ECHO and restart the T1-cookie timer without changing state.  This MUST
  // be repeated up to 'Max.Init.Retransmits' times. After that, the endpoint
  // MUST abort the initialization process and report the error to the SCTP
  // user."
  RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_cookie_->name()
                       << " has expired: " << t1_cookie_->expiration_count()
                       << "/"
                       << t1_cookie_->options().max_restarts.value_or(-1);

  RTC_DCHECK(state_ == State::kCookieEchoed);

  if (t1_cookie_->is_running()) {
    tcb_->SendBufferedPackets(callbacks_.TimeMillis());
  } else {
    InternalClose(ErrorKind::kTooManyRetries, "No COOKIE_ACK received");
  }

  RTC_DCHECK(IsConsistent());
  return absl::nullopt;
}

absl::optional<DurationMs> DcSctpSocket::OnShutdownTimerExpiry() {
  RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t2_shutdown_->name()
                       << " has expired: " << t2_shutdown_->expiration_count()
                       << "/"
                       << t2_shutdown_->options().max_restarts.value_or(-1);

  if (!t2_shutdown_->is_running()) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "An endpoint should limit the number of retransmissions of the SHUTDOWN
    // chunk to the protocol parameter 'Association.Max.Retrans'. If this
    // threshold is exceeded, the endpoint should destroy the TCB..."

    packet_sender_.Send(tcb_->PacketBuilder().Add(
        AbortChunk(true, Parameters::Builder()
                             .Add(UserInitiatedAbortCause(
                                 "Too many retransmissions of SHUTDOWN"))
                             .Build())));

    InternalClose(ErrorKind::kTooManyRetries, "No SHUTDOWN_ACK received");
    RTC_DCHECK(IsConsistent());
    return absl::nullopt;
  }

  // https://tools.ietf.org/html/rfc4960#section-9.2
  // "If the timer expires, the endpoint must resend the SHUTDOWN with the
  // updated last sequential TSN received from its peer."
  SendShutdown();
  RTC_DCHECK(IsConsistent());
  return tcb_->current_rto();
}

void DcSctpSocket::OnSentPacket(rtc::ArrayView<const uint8_t> packet,
                                SendPacketStatus status) {
  // The packet observer is invoked even if the packet was failed to be sent, to
  // indicate an attempt was made.
  if (packet_observer_ != nullptr) {
    packet_observer_->OnSentPacket(callbacks_.TimeMillis(), packet);
  }

  if (status == SendPacketStatus::kSuccess) {
    if (RTC_DLOG_IS_ON) {
      DebugPrintOutgoing(packet);
    }

    // The heartbeat interval timer is restarted for every sent packet, to
    // fire when the outgoing channel is inactive.
    if (tcb_ != nullptr) {
      tcb_->heartbeat_handler().RestartTimer();
    }

    ++metrics_.tx_packets_count;
  }
}

bool DcSctpSocket::ValidateHasTCB() {
  if (tcb_ != nullptr) {
    return true;
  }

  callbacks_.OnError(
      ErrorKind::kNotConnected,
      "Received unexpected commands on socket that is not connected");
  return false;
}

void DcSctpSocket::ReportFailedToParseChunk(int chunk_type) {
  rtc::StringBuilder sb;
  sb << "Failed to parse chunk of type: " << chunk_type;
  callbacks_.OnError(ErrorKind::kParseFailed, sb.str());
}

void DcSctpSocket::HandleData(const CommonHeader& header,
                              const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<DataChunk> chunk = DataChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    HandleDataCommon(*chunk);
  }
}

void DcSctpSocket::HandleIData(const CommonHeader& header,
                               const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<IDataChunk> chunk = IDataChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    HandleDataCommon(*chunk);
  }
}

void DcSctpSocket::HandleDataCommon(AnyDataChunk& chunk) {
  TSN tsn = chunk.tsn();
  AnyDataChunk::ImmediateAckFlag immediate_ack = chunk.options().immediate_ack;
  Data data = std::move(chunk).extract();

  if (data.payload.empty()) {
    // Empty DATA chunks are illegal.
    packet_sender_.Send(tcb_->PacketBuilder().Add(
        ErrorChunk(Parameters::Builder().Add(NoUserDataCause(tsn)).Build())));
    callbacks_.OnError(ErrorKind::kProtocolViolation,
                       "Received DATA chunk with no user data");
    return;
  }

  RTC_DLOG(LS_VERBOSE) << log_prefix() << "Handle DATA, queue_size="
                       << tcb_->reassembly_queue().queued_bytes()
                       << ", water_mark="
                       << tcb_->reassembly_queue().watermark_bytes()
                       << ", full=" << tcb_->reassembly_queue().is_full()
                       << ", above="
                       << tcb_->reassembly_queue().is_above_watermark();

  if (tcb_->reassembly_queue().is_full()) {
    // If the reassembly queue is full, there is nothing that can be done. The
    // specification only allows dropping gap-ack-blocks, and that's not
    // likely to help as the socket has been trying to fill gaps since the
    // watermark was reached.
    packet_sender_.Send(tcb_->PacketBuilder().Add(AbortChunk(
        true, Parameters::Builder().Add(OutOfResourceErrorCause()).Build())));
    InternalClose(ErrorKind::kResourceExhaustion,
                  "Reassembly Queue is exhausted");
    return;
  }

  if (tcb_->reassembly_queue().is_above_watermark()) {
    RTC_DLOG(LS_VERBOSE) << log_prefix() << "Is above high watermark";
    // If the reassembly queue is above its high watermark, only accept data
    // chunks that increase its cumulative ack tsn in an attempt to fill gaps
    // to deliver messages.
    if (!tcb_->data_tracker().will_increase_cum_ack_tsn(tsn)) {
      RTC_DLOG(LS_VERBOSE) << log_prefix()
                           << "Rejected data because of exceeding watermark";
      tcb_->data_tracker().ForceImmediateSack();
      return;
    }
  }

  if (!tcb_->data_tracker().IsTSNValid(tsn)) {
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Rejected data because of failing TSN validity";
    return;
  }

  tcb_->data_tracker().Observe(tsn, immediate_ack);
  tcb_->reassembly_queue().MaybeResetStreamsDeferred(
      tcb_->data_tracker().last_cumulative_acked_tsn());
  tcb_->reassembly_queue().Add(tsn, std::move(data));
  DeliverReassembledMessages();
}

void DcSctpSocket::HandleInit(const CommonHeader& header,
                              const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<InitChunk> chunk = InitChunk::Parse(descriptor.data);
  if (!ValidateParseSuccess(chunk)) {
    return;
  }

  if (chunk->initiate_tag() == VerificationTag(0) ||
      chunk->nbr_outbound_streams() == 0 || chunk->nbr_inbound_streams() == 0) {
    // https://tools.ietf.org/html/rfc4960#section-3.3.2
    // "If the value of the Initiate Tag in a received INIT chunk is found
    // to be 0, the receiver MUST treat it as an error and close the
    // association by transmitting an ABORT."

    // "A receiver of an INIT with the OS value set to 0 SHOULD abort the
    // association."

    // "A receiver of an INIT with the MIS value of 0 SHOULD abort the
    // association."

    packet_sender_.Send(
        SctpPacket::Builder(VerificationTag(0), options_)
            .Add(AbortChunk(
                /*filled_in_verification_tag=*/false,
                Parameters::Builder()
                    .Add(ProtocolViolationCause("INIT malformed"))
                    .Build())));
    InternalClose(ErrorKind::kProtocolViolation, "Received invalid INIT");
    return;
  }

  if (state_ == State::kShutdownAckSent) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "If an endpoint is in the SHUTDOWN-ACK-SENT state and receives an
    // INIT chunk (e.g., if the SHUTDOWN COMPLETE was lost) with source and
    // destination transport addresses (either in the IP addresses or in the
    // INIT chunk) that belong to this association, it should discard the INIT
    // chunk and retransmit the SHUTDOWN ACK chunk."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received Init indicating lost ShutdownComplete";
    SendShutdownAck();
    return;
  }

  TieTag tie_tag(0);
  if (state_ == State::kClosed) {
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received Init in closed state (normal)";

    MakeConnectionParameters();
  } else if (state_ == State::kCookieWait || state_ == State::kCookieEchoed) {
    // https://tools.ietf.org/html/rfc4960#section-5.2.1
    // "This usually indicates an initialization collision, i.e., each
    // endpoint is attempting, at about the same time, to establish an
    // association with the other endpoint. Upon receipt of an INIT in the
    // COOKIE-WAIT state, an endpoint MUST respond with an INIT ACK using the
    // same parameters it sent in its original INIT chunk (including its
    // Initiate Tag, unchanged).  When responding, the endpoint MUST send the
    // INIT ACK back to the same address that the original INIT (sent by this
    // endpoint) was sent."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received Init indicating simultaneous connections";
  } else {
    RTC_DCHECK(tcb_ != nullptr);
    // https://tools.ietf.org/html/rfc4960#section-5.2.2
    // "The outbound SCTP packet containing this INIT ACK MUST carry a
    // Verification Tag value equal to the Initiate Tag found in the
    // unexpected INIT.  And the INIT ACK MUST contain a new Initiate Tag
    // (randomly generated; see Section 5.3.1).  Other parameters for the
    // endpoint SHOULD be copied from the existing parameters of the
    // association (e.g., number of outbound streams) into the INIT ACK and
    // cookie."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received Init indicating restarted connection";
    // Create a new verification tag - different from the previous one.
    for (int tries = 0; tries < 10; ++tries) {
      connect_params_.verification_tag = VerificationTag(
          callbacks_.GetRandomInt(kMinVerificationTag, kMaxVerificationTag));
      if (connect_params_.verification_tag != tcb_->my_verification_tag()) {
        break;
      }
    }

    // Make the initial TSN make a large jump, so that there is no overlap
    // with the old and new association.
    connect_params_.initial_tsn =
        TSN(*tcb_->retransmission_queue().next_tsn() + 1000000);
    tie_tag = tcb_->tie_tag();
  }

  RTC_DLOG(LS_VERBOSE)
      << log_prefix()
      << rtc::StringFormat(
             "Proceeding with connection. my_verification_tag=%08x, "
             "my_initial_tsn=%u, peer_verification_tag=%08x, "
             "peer_initial_tsn=%u",
             *connect_params_.verification_tag, *connect_params_.initial_tsn,
             *chunk->initiate_tag(), *chunk->initial_tsn());

  Capabilities capabilities = GetCapabilities(options_, chunk->parameters());

  SctpPacket::Builder b(chunk->initiate_tag(), options_);
  Parameters::Builder params_builder =
      Parameters::Builder().Add(StateCookieParameter(
          StateCookie(chunk->initiate_tag(), chunk->initial_tsn(),
                      chunk->a_rwnd(), tie_tag, capabilities)
              .Serialize()));
  AddCapabilityParameters(options_, params_builder);

  InitAckChunk init_ack(/*initiate_tag=*/connect_params_.verification_tag,
                        options_.max_receiver_window_buffer_size,
                        options_.announced_maximum_outgoing_streams,
                        options_.announced_maximum_incoming_streams,
                        connect_params_.initial_tsn, params_builder.Build());
  b.Add(init_ack);
  packet_sender_.Send(b);
}

void DcSctpSocket::HandleInitAck(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<InitAckChunk> chunk = InitAckChunk::Parse(descriptor.data);
  if (!ValidateParseSuccess(chunk)) {
    return;
  }

  if (state_ != State::kCookieWait) {
    // https://tools.ietf.org/html/rfc4960#section-5.2.3
    // "If an INIT ACK is received by an endpoint in any state other than
    // the COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received INIT_ACK in unexpected state";
    return;
  }

  auto cookie = chunk->parameters().get<StateCookieParameter>();
  if (!cookie.has_value()) {
    packet_sender_.Send(
        SctpPacket::Builder(connect_params_.verification_tag, options_)
            .Add(AbortChunk(
                /*filled_in_verification_tag=*/false,
                Parameters::Builder()
                    .Add(ProtocolViolationCause("INIT-ACK malformed"))
                    .Build())));
    InternalClose(ErrorKind::kProtocolViolation,
                  "InitAck chunk doesn't contain a cookie");
    return;
  }
  Capabilities capabilities = GetCapabilities(options_, chunk->parameters());
  t1_init_->Stop();

  peer_implementation_ = DeterminePeerImplementation(cookie->data());

  tcb_ = std::make_unique<TransmissionControlBlock>(
      timer_manager_, log_prefix_, options_, capabilities, callbacks_,
      send_queue_, connect_params_.verification_tag,
      connect_params_.initial_tsn, chunk->initiate_tag(), chunk->initial_tsn(),
      chunk->a_rwnd(), MakeTieTag(callbacks_), packet_sender_,
      [this]() { return state_ == State::kEstablished; });
  RTC_DLOG(LS_VERBOSE) << log_prefix()
                       << "Created peer TCB: " << tcb_->ToString();

  SetState(State::kCookieEchoed, "INIT_ACK received");

  // The connection isn't fully established just yet.
  tcb_->SetCookieEchoChunk(CookieEchoChunk(cookie->data()));
  tcb_->SendBufferedPackets(callbacks_.TimeMillis());
  t1_cookie_->Start();
}

void DcSctpSocket::HandleCookieEcho(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<CookieEchoChunk> chunk =
      CookieEchoChunk::Parse(descriptor.data);
  if (!ValidateParseSuccess(chunk)) {
    return;
  }

  absl::optional<StateCookie> cookie =
      StateCookie::Deserialize(chunk->cookie());
  if (!cookie.has_value()) {
    callbacks_.OnError(ErrorKind::kParseFailed, "Failed to parse state cookie");
    return;
  }

  if (tcb_ != nullptr) {
    if (!HandleCookieEchoWithTCB(header, *cookie)) {
      return;
    }
  } else {
    if (header.verification_tag != connect_params_.verification_tag) {
      callbacks_.OnError(
          ErrorKind::kParseFailed,
          rtc::StringFormat(
              "Received CookieEcho with invalid verification tag: %08x, "
              "expected %08x",
              *header.verification_tag, *connect_params_.verification_tag));
      return;
    }
  }

  // The init timer can be running on simultaneous connections.
  t1_init_->Stop();
  t1_cookie_->Stop();
  if (state_ != State::kEstablished) {
    if (tcb_ != nullptr) {
      tcb_->ClearCookieEchoChunk();
    }
    SetState(State::kEstablished, "COOKIE_ECHO received");
    callbacks_.OnConnected();
  }

  if (tcb_ == nullptr) {
    tcb_ = std::make_unique<TransmissionControlBlock>(
        timer_manager_, log_prefix_, options_, cookie->capabilities(),
        callbacks_, send_queue_, connect_params_.verification_tag,
        connect_params_.initial_tsn, cookie->initiate_tag(),
        cookie->initial_tsn(), cookie->a_rwnd(), MakeTieTag(callbacks_),
        packet_sender_, [this]() { return state_ == State::kEstablished; });
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Created peer TCB: " << tcb_->ToString();
  }

  SctpPacket::Builder b = tcb_->PacketBuilder();
  b.Add(CookieAckChunk());

  // https://tools.ietf.org/html/rfc4960#section-5.1
  // "A COOKIE ACK chunk may be bundled with any pending DATA chunks (and/or
  // SACK chunks), but the COOKIE ACK chunk MUST be the first chunk in the
  // packet."
  tcb_->SendBufferedPackets(b, callbacks_.TimeMillis());
}

bool DcSctpSocket::HandleCookieEchoWithTCB(const CommonHeader& header,
                                           const StateCookie& cookie) {
  RTC_DLOG(LS_VERBOSE) << log_prefix()
                       << "Handling CookieEchoChunk with TCB. local_tag="
                       << *tcb_->my_verification_tag()
                       << ", peer_tag=" << *header.verification_tag
                       << ", tcb_tag=" << *tcb_->peer_verification_tag()
                       << ", cookie_tag=" << *cookie.initiate_tag()
                       << ", local_tie_tag=" << *tcb_->tie_tag()
                       << ", peer_tie_tag=" << *cookie.tie_tag();
  // https://tools.ietf.org/html/rfc4960#section-5.2.4
  // "Handle a COOKIE ECHO when a TCB Exists"
  if (header.verification_tag != tcb_->my_verification_tag() &&
      tcb_->peer_verification_tag() != cookie.initiate_tag() &&
      cookie.tie_tag() == tcb_->tie_tag()) {
    // "A) In this case, the peer may have restarted."
    if (state_ == State::kShutdownAckSent) {
      // "If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes
      // that the peer has restarted ...  it MUST NOT set up a new association
      // but instead resend the SHUTDOWN ACK and send an ERROR chunk with a
      // "Cookie Received While Shutting Down" error cause to its peer."
      SctpPacket::Builder b(cookie.initiate_tag(), options_);
      b.Add(ShutdownAckChunk());
      b.Add(ErrorChunk(Parameters::Builder()
                           .Add(CookieReceivedWhileShuttingDownCause())
                           .Build()));
      packet_sender_.Send(b);
      callbacks_.OnError(ErrorKind::kWrongSequence,
                         "Received COOKIE-ECHO while shutting down");
      return false;
    }

    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received COOKIE-ECHO indicating a restarted peer";

    // If a message was partly sent, and the peer restarted, resend it in
    // full by resetting the send queue.
    send_queue_.Reset();
    tcb_ = nullptr;
    callbacks_.OnConnectionRestarted();
  } else if (header.verification_tag == tcb_->my_verification_tag() &&
             tcb_->peer_verification_tag() != cookie.initiate_tag()) {
    // TODO(boivie): Handle the peer_tag == 0?
    // "B) In this case, both sides may be attempting to start an
    // association at about the same time, but the peer endpoint started its
    // INIT after responding to the local endpoint's INIT."
    RTC_DLOG(LS_VERBOSE)
        << log_prefix()
        << "Received COOKIE-ECHO indicating simultaneous connections";
    tcb_ = nullptr;
  } else if (header.verification_tag != tcb_->my_verification_tag() &&
             tcb_->peer_verification_tag() == cookie.initiate_tag() &&
             cookie.tie_tag() == TieTag(0)) {
    // "C) In this case, the local endpoint's cookie has arrived late.
    // Before it arrived, the local endpoint sent an INIT and received an
    // INIT ACK and finally sent a COOKIE ECHO with the peer's same tag but
    // a new tag of its own. The cookie should be silently discarded. The
    // endpoint SHOULD NOT change states and should leave any timers
    // running."
    RTC_DLOG(LS_VERBOSE)
        << log_prefix()
        << "Received COOKIE-ECHO indicating a late COOKIE-ECHO. Discarding";
    return false;
  } else if (header.verification_tag == tcb_->my_verification_tag() &&
             tcb_->peer_verification_tag() == cookie.initiate_tag()) {
    // "D) When both local and remote tags match, the endpoint should enter
    // the ESTABLISHED state, if it is in the COOKIE-ECHOED state.  It
    // should stop any cookie timer that may be running and send a COOKIE
    // ACK."
    RTC_DLOG(LS_VERBOSE)
        << log_prefix()
        << "Received duplicate COOKIE-ECHO, probably because of peer not "
           "receiving COOKIE-ACK and retransmitting COOKIE-ECHO. Continuing.";
  }
  return true;
}

void DcSctpSocket::HandleCookieAck(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<CookieAckChunk> chunk = CookieAckChunk::Parse(descriptor.data);
  if (!ValidateParseSuccess(chunk)) {
    return;
  }

  if (state_ != State::kCookieEchoed) {
    // https://tools.ietf.org/html/rfc4960#section-5.2.5
    // "At any state other than COOKIE-ECHOED, an endpoint should silently
    // discard a received COOKIE ACK chunk."
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received COOKIE_ACK not in COOKIE_ECHOED state";
    return;
  }

  // RFC 4960, Errata ID: 4400
  t1_cookie_->Stop();
  tcb_->ClearCookieEchoChunk();
  SetState(State::kEstablished, "COOKIE_ACK received");
  tcb_->SendBufferedPackets(callbacks_.TimeMillis());
  callbacks_.OnConnected();
}

void DcSctpSocket::DeliverReassembledMessages() {
  if (tcb_->reassembly_queue().HasMessages()) {
    for (auto& message : tcb_->reassembly_queue().FlushMessages()) {
      ++metrics_.rx_messages_count;
      callbacks_.OnMessageReceived(std::move(message));
    }
  }
}

void DcSctpSocket::HandleSack(const CommonHeader& header,
                              const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<SackChunk> chunk = SackChunk::Parse(descriptor.data);

  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    TimeMs now = callbacks_.TimeMillis();
    SackChunk sack = ChunkValidators::Clean(*std::move(chunk));

    if (tcb_->retransmission_queue().HandleSack(now, sack)) {
      MaybeSendShutdownOrAck();
      // Receiving an ACK will decrease outstanding bytes (maybe now below
      // cwnd?) or indicate packet loss that may result in sending FORWARD-TSN.
      tcb_->SendBufferedPackets(now);
    } else {
      RTC_DLOG(LS_VERBOSE) << log_prefix()
                           << "Dropping out-of-order SACK with TSN "
                           << *sack.cumulative_tsn_ack();
    }
  }
}

void DcSctpSocket::HandleHeartbeatRequest(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<HeartbeatRequestChunk> chunk =
      HeartbeatRequestChunk::Parse(descriptor.data);

  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    tcb_->heartbeat_handler().HandleHeartbeatRequest(*std::move(chunk));
  }
}

void DcSctpSocket::HandleHeartbeatAck(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<HeartbeatAckChunk> chunk =
      HeartbeatAckChunk::Parse(descriptor.data);

  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    tcb_->heartbeat_handler().HandleHeartbeatAck(*std::move(chunk));
  }
}

void DcSctpSocket::HandleAbort(const CommonHeader& header,
                               const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<AbortChunk> chunk = AbortChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk)) {
    std::string error_string = ErrorCausesToString(chunk->error_causes());
    if (tcb_ == nullptr) {
      // https://tools.ietf.org/html/rfc4960#section-3.3.7
      // "If an endpoint receives an ABORT with a format error or no TCB is
      // found, it MUST silently discard it."
      RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received ABORT (" << error_string
                           << ") on a connection with no TCB. Ignoring";
      return;
    }

    RTC_DLOG(LS_WARNING) << log_prefix() << "Received ABORT (" << error_string
                         << ") - closing connection.";
    InternalClose(ErrorKind::kPeerReported, error_string);
  }
}

void DcSctpSocket::HandleError(const CommonHeader& header,
                               const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<ErrorChunk> chunk = ErrorChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk)) {
    std::string error_string = ErrorCausesToString(chunk->error_causes());
    if (tcb_ == nullptr) {
      RTC_DLOG(LS_VERBOSE) << log_prefix() << "Received ERROR (" << error_string
                           << ") on a connection with no TCB. Ignoring";
      return;
    }

    RTC_DLOG(LS_WARNING) << log_prefix() << "Received ERROR: " << error_string;
    callbacks_.OnError(ErrorKind::kPeerReported,
                       "Peer reported error: " + error_string);
  }
}

void DcSctpSocket::HandleReconfig(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<ReConfigChunk> chunk = ReConfigChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    tcb_->stream_reset_handler().HandleReConfig(*std::move(chunk));
  }
}

void DcSctpSocket::HandleShutdown(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  if (!ValidateParseSuccess(ShutdownChunk::Parse(descriptor.data))) {
    return;
  }

  if (state_ == State::kClosed) {
    return;
  } else if (state_ == State::kCookieWait || state_ == State::kCookieEchoed) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "If a SHUTDOWN is received in the COOKIE-WAIT or COOKIE ECHOED state,
    // the SHUTDOWN chunk SHOULD be silently discarded."
  } else if (state_ == State::kShutdownSent) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "If an endpoint is in the SHUTDOWN-SENT state and receives a
    // SHUTDOWN chunk from its peer, the endpoint shall respond immediately
    // with a SHUTDOWN ACK to its peer, and move into the SHUTDOWN-ACK-SENT
    // state restarting its T2-shutdown timer."
    SendShutdownAck();
    SetState(State::kShutdownAckSent, "SHUTDOWN received");
  } else if (state_ == State::kShutdownAckSent) {
    // TODO(webrtc:12739): This condition should be removed and handled by the
    // next (state_ != State::kShutdownReceived).
    return;
  } else if (state_ != State::kShutdownReceived) {
    RTC_DLOG(LS_VERBOSE) << log_prefix()
                         << "Received SHUTDOWN - shutting down the socket";
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "Upon reception of the SHUTDOWN, the peer endpoint shall enter the
    // SHUTDOWN-RECEIVED state, stop accepting new data from its SCTP user,
    // and verify, by checking the Cumulative TSN Ack field of the chunk, that
    // all its outstanding DATA chunks have been received by the SHUTDOWN
    // sender."
    SetState(State::kShutdownReceived, "SHUTDOWN received");
    MaybeSendShutdownOrAck();
  }
}

void DcSctpSocket::HandleShutdownAck(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  if (!ValidateParseSuccess(ShutdownAckChunk::Parse(descriptor.data))) {
    return;
  }

  if (state_ == State::kShutdownSent || state_ == State::kShutdownAckSent) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "Upon the receipt of the SHUTDOWN ACK, the SHUTDOWN sender shall stop
    // the T2-shutdown timer, send a SHUTDOWN COMPLETE chunk to its peer, and
    // remove all record of the association."

    // "If an endpoint is in the SHUTDOWN-ACK-SENT state and receives a
    // SHUTDOWN ACK, it shall stop the T2-shutdown timer, send a SHUTDOWN
    // COMPLETE chunk to its peer, and remove all record of the association."

    SctpPacket::Builder b = tcb_->PacketBuilder();
    b.Add(ShutdownCompleteChunk(/*tag_reflected=*/false));
    packet_sender_.Send(b);
    InternalClose(ErrorKind::kNoError, "");
  } else {
    // https://tools.ietf.org/html/rfc4960#section-8.5.1
    // "If the receiver is in COOKIE-ECHOED or COOKIE-WAIT state
    // the procedures in Section 8.4 SHOULD be followed; in other words, it
    // should be treated as an Out Of The Blue packet."

    // https://tools.ietf.org/html/rfc4960#section-8.4
    // "If the packet contains a SHUTDOWN ACK chunk, the receiver
    // should respond to the sender of the OOTB packet with a SHUTDOWN
    // COMPLETE. When sending the SHUTDOWN COMPLETE, the receiver of the OOTB
    // packet must fill in the Verification Tag field of the outbound packet
    // with the Verification Tag received in the SHUTDOWN ACK and set the T
    // bit in the Chunk Flags to indicate that the Verification Tag is
    // reflected."

    SctpPacket::Builder b(header.verification_tag, options_);
    b.Add(ShutdownCompleteChunk(/*tag_reflected=*/true));
    packet_sender_.Send(b);
  }
}

void DcSctpSocket::HandleShutdownComplete(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  if (!ValidateParseSuccess(ShutdownCompleteChunk::Parse(descriptor.data))) {
    return;
  }

  if (state_ == State::kShutdownAckSent) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "Upon reception of the SHUTDOWN COMPLETE chunk, the endpoint will
    // verify that it is in the SHUTDOWN-ACK-SENT state; if it is not, the
    // chunk should be discarded.  If the endpoint is in the SHUTDOWN-ACK-SENT
    // state, the endpoint should stop the T2-shutdown timer and remove all
    // knowledge of the association (and thus the association enters the
    // CLOSED state)."
    InternalClose(ErrorKind::kNoError, "");
  }
}

void DcSctpSocket::HandleForwardTsn(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<ForwardTsnChunk> chunk =
      ForwardTsnChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    HandleForwardTsnCommon(*chunk);
  }
}

void DcSctpSocket::HandleIForwardTsn(
    const CommonHeader& header,
    const SctpPacket::ChunkDescriptor& descriptor) {
  absl::optional<IForwardTsnChunk> chunk =
      IForwardTsnChunk::Parse(descriptor.data);
  if (ValidateParseSuccess(chunk) && ValidateHasTCB()) {
    HandleForwardTsnCommon(*chunk);
  }
}

void DcSctpSocket::HandleForwardTsnCommon(const AnyForwardTsnChunk& chunk) {
  if (!tcb_->capabilities().partial_reliability) {
    SctpPacket::Builder b = tcb_->PacketBuilder();
    b.Add(AbortChunk(/*filled_in_verification_tag=*/true,
                     Parameters::Builder()
                         .Add(ProtocolViolationCause(
                             "I-FORWARD-TSN received, but not indicated "
                             "during connection establishment"))
                         .Build()));
    packet_sender_.Send(b);

    callbacks_.OnError(ErrorKind::kProtocolViolation,
                       "Received a FORWARD_TSN without announced peer support");
    return;
  }
  tcb_->data_tracker().HandleForwardTsn(chunk.new_cumulative_tsn());
  tcb_->reassembly_queue().Handle(chunk);
  // A forward TSN - for ordered streams - may allow messages to be
  // delivered.
  DeliverReassembledMessages();

  // Processing a FORWARD_TSN might result in sending a SACK.
  tcb_->MaybeSendSack();
}

void DcSctpSocket::MaybeSendShutdownOrAck() {
  if (tcb_->retransmission_queue().outstanding_bytes() != 0) {
    return;
  }

  if (state_ == State::kShutdownPending) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "Once all its outstanding data has been acknowledged, the endpoint
    // shall send a SHUTDOWN chunk to its peer including in the Cumulative TSN
    // Ack field the last sequential TSN it has received from the peer. It
    // shall then start the T2-shutdown timer and enter the SHUTDOWN-SENT
    // state.""

    SendShutdown();
    t2_shutdown_->set_duration(tcb_->current_rto());
    t2_shutdown_->Start();
    SetState(State::kShutdownSent, "No more outstanding data");
  } else if (state_ == State::kShutdownReceived) {
    // https://tools.ietf.org/html/rfc4960#section-9.2
    // "If the receiver of the SHUTDOWN has no more outstanding DATA
    // chunks, the SHUTDOWN receiver MUST send a SHUTDOWN ACK and start a
    // T2-shutdown timer of its own, entering the SHUTDOWN-ACK-SENT state.  If
    // the timer expires, the endpoint must resend the SHUTDOWN ACK."

    SendShutdownAck();
    SetState(State::kShutdownAckSent, "No more outstanding data");
  }
}

void DcSctpSocket::SendShutdown() {
  SctpPacket::Builder b = tcb_->PacketBuilder();
  b.Add(ShutdownChunk(tcb_->data_tracker().last_cumulative_acked_tsn()));
  packet_sender_.Send(b);
}

void DcSctpSocket::SendShutdownAck() {
  packet_sender_.Send(tcb_->PacketBuilder().Add(ShutdownAckChunk()));
  t2_shutdown_->set_duration(tcb_->current_rto());
  t2_shutdown_->Start();
}

HandoverReadinessStatus DcSctpSocket::GetHandoverReadiness() const {
  HandoverReadinessStatus status;
  if (state_ != State::kClosed && state_ != State::kEstablished) {
    status.Add(HandoverUnreadinessReason::kWrongConnectionState);
  }
  status.Add(send_queue_.GetHandoverReadiness());
  if (tcb_) {
    status.Add(tcb_->GetHandoverReadiness());
  }
  return status;
}

absl::optional<DcSctpSocketHandoverState>
DcSctpSocket::GetHandoverStateAndClose() {
  if (!GetHandoverReadiness().IsReady()) {
    return absl::nullopt;
  }

  DcSctpSocketHandoverState state;

  if (state_ == State::kClosed) {
    state.socket_state = DcSctpSocketHandoverState::SocketState::kClosed;
  } else if (state_ == State::kEstablished) {
    state.socket_state = DcSctpSocketHandoverState::SocketState::kConnected;
    tcb_->AddHandoverState(state);
    send_queue_.AddHandoverState(state);
    InternalClose(ErrorKind::kNoError, "handover");
    callbacks_.TriggerDeferred();
  }

  return std::move(state);
}

}  // namespace dcsctp
