/*
 *  Copyright (c) 2012 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 "webrtc/media/sctp/sctpdataengine.h"

#include <stdarg.h>
#include <stdio.h>

#include <memory>
#include <sstream>
#include <vector>

#include "usrsctplib/usrsctp.h"
#include "webrtc/base/arraysize.h"
#include "webrtc/base/copyonwritebuffer.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/safe_conversions.h"
#include "webrtc/media/base/codec.h"
#include "webrtc/media/base/mediaconstants.h"
#include "webrtc/media/base/streamparams.h"

namespace cricket {
// The biggest SCTP packet.  Starting from a 'safe' wire MTU value of 1280,
// take off 80 bytes for DTLS/TURN/TCP/IP overhead.
static const size_t kSctpMtu = 1200;

// The size of the SCTP association send buffer.  256kB, the usrsctp default.
static const int kSendBufferSize = 262144;

struct SctpInboundPacket {
  rtc::CopyOnWriteBuffer buffer;
  ReceiveDataParams params;
  // The |flags| parameter is used by SCTP to distinguish notification packets
  // from other types of packets.
  int flags;
};

namespace {
// Set the initial value of the static SCTP Data Engines reference count.
int g_usrsctp_usage_count = 0;
rtc::GlobalLockPod g_usrsctp_lock_;

typedef SctpDataMediaChannel::StreamSet StreamSet;

// Returns a comma-separated, human-readable list of the stream IDs in 's'
std::string ListStreams(const StreamSet& s) {
  std::stringstream result;
  bool first = true;
  for (StreamSet::const_iterator it = s.begin(); it != s.end(); ++it) {
    if (!first) {
      result << ", " << *it;
    } else {
      result << *it;
      first = false;
    }
  }
  return result.str();
}

// Returns a pipe-separated, human-readable list of the SCTP_STREAM_RESET
// flags in 'flags'
std::string ListFlags(int flags) {
  std::stringstream result;
  bool first = true;
  // Skip past the first 12 chars (strlen("SCTP_STREAM_"))
#define MAKEFLAG(X) { X, #X + 12}
  struct flaginfo_t {
    int value;
    const char* name;
  } flaginfo[] = {
    MAKEFLAG(SCTP_STREAM_RESET_INCOMING_SSN),
    MAKEFLAG(SCTP_STREAM_RESET_OUTGOING_SSN),
    MAKEFLAG(SCTP_STREAM_RESET_DENIED),
    MAKEFLAG(SCTP_STREAM_RESET_FAILED),
    MAKEFLAG(SCTP_STREAM_CHANGE_DENIED)
  };
#undef MAKEFLAG
  for (uint32_t i = 0; i < arraysize(flaginfo); ++i) {
    if (flags & flaginfo[i].value) {
      if (!first) result << " | ";
      result << flaginfo[i].name;
      first = false;
    }
  }
  return result.str();
}

// Returns a comma-separated, human-readable list of the integers in 'array'.
// All 'num_elems' of them.
std::string ListArray(const uint16_t* array, int num_elems) {
  std::stringstream result;
  for (int i = 0; i < num_elems; ++i) {
    if (i) {
      result << ", " << array[i];
    } else {
      result << array[i];
    }
  }
  return result.str();
}

typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage;
typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage;

enum {
  MSG_SCTPINBOUNDPACKET = 1,   // MessageData is SctpInboundPacket
  MSG_SCTPOUTBOUNDPACKET = 2,  // MessageData is rtc:Buffer
};

// Helper for logging SCTP messages.
void DebugSctpPrintf(const char* format, ...) {
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
  char s[255];
  va_list ap;
  va_start(ap, format);
  vsnprintf(s, sizeof(s), format, ap);
  LOG(LS_INFO) << "SCTP: " << s;
  va_end(ap);
#endif
}

// Get the PPID to use for the terminating fragment of this type.
SctpDataMediaChannel::PayloadProtocolIdentifier GetPpid(DataMessageType type) {
  switch (type) {
  default:
  case DMT_NONE:
    return SctpDataMediaChannel::PPID_NONE;
  case DMT_CONTROL:
    return SctpDataMediaChannel::PPID_CONTROL;
  case DMT_BINARY:
    return SctpDataMediaChannel::PPID_BINARY_LAST;
  case DMT_TEXT:
    return SctpDataMediaChannel::PPID_TEXT_LAST;
  };
}

bool GetDataMediaType(SctpDataMediaChannel::PayloadProtocolIdentifier ppid,
                      DataMessageType* dest) {
  ASSERT(dest != NULL);
  switch (ppid) {
    case SctpDataMediaChannel::PPID_BINARY_PARTIAL:
    case SctpDataMediaChannel::PPID_BINARY_LAST:
      *dest = DMT_BINARY;
      return true;

    case SctpDataMediaChannel::PPID_TEXT_PARTIAL:
    case SctpDataMediaChannel::PPID_TEXT_LAST:
      *dest = DMT_TEXT;
      return true;

    case SctpDataMediaChannel::PPID_CONTROL:
      *dest = DMT_CONTROL;
      return true;

    case SctpDataMediaChannel::PPID_NONE:
      *dest = DMT_NONE;
      return true;

    default:
      return false;
  }
}

// Log the packet in text2pcap format, if log level is at LS_VERBOSE.
void VerboseLogPacket(const void* data, size_t length, int direction) {
  if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
    char *dump_buf;
    // Some downstream project uses an older version of usrsctp that expects
    // a non-const "void*" as first parameter when dumping the packet, so we
    // need to cast the const away here to avoid a compiler error.
    if ((dump_buf = usrsctp_dumppacket(
        const_cast<void*>(data), length, direction)) != NULL) {
      LOG(LS_VERBOSE) << dump_buf;
      usrsctp_freedumpbuffer(dump_buf);
    }
  }
}

// This is the callback usrsctp uses when there's data to send on the network
// that has been wrapped appropriatly for the SCTP protocol.
int OnSctpOutboundPacket(void* addr,
                         void* data,
                         size_t length,
                         uint8_t tos,
                         uint8_t set_df) {
  SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(addr);
  LOG(LS_VERBOSE) << "global OnSctpOutboundPacket():"
                  << "addr: " << addr << "; length: " << length
                  << "; tos: " << std::hex << static_cast<int>(tos)
                  << "; set_df: " << std::hex << static_cast<int>(set_df);

  VerboseLogPacket(data, length, SCTP_DUMP_OUTBOUND);
  // Note: We have to copy the data; the caller will delete it.
  auto* msg = new OutboundPacketMessage(
      new rtc::CopyOnWriteBuffer(reinterpret_cast<uint8_t*>(data), length));
  channel->worker_thread()->Post(RTC_FROM_HERE, channel, MSG_SCTPOUTBOUNDPACKET,
                                 msg);
  return 0;
}

// This is the callback called from usrsctp when data has been received, after
// a packet has been interpreted and parsed by usrsctp and found to contain
// payload data. It is called by a usrsctp thread. It is assumed this function
// will free the memory used by 'data'.
int OnSctpInboundPacket(struct socket* sock,
                        union sctp_sockstore addr,
                        void* data,
                        size_t length,
                        struct sctp_rcvinfo rcv,
                        int flags,
                        void* ulp_info) {
  SctpDataMediaChannel* channel = static_cast<SctpDataMediaChannel*>(ulp_info);
  // Post data to the channel's receiver thread (copying it).
  // TODO(ldixon): Unclear if copy is needed as this method is responsible for
  // memory cleanup. But this does simplify code.
  const SctpDataMediaChannel::PayloadProtocolIdentifier ppid =
      static_cast<SctpDataMediaChannel::PayloadProtocolIdentifier>(
          rtc::HostToNetwork32(rcv.rcv_ppid));
  DataMessageType type = DMT_NONE;
  if (!GetDataMediaType(ppid, &type) && !(flags & MSG_NOTIFICATION)) {
    // It's neither a notification nor a recognized data packet.  Drop it.
    LOG(LS_ERROR) << "Received an unknown PPID " << ppid
                  << " on an SCTP packet.  Dropping.";
  } else {
    SctpInboundPacket* packet = new SctpInboundPacket;
    packet->buffer.SetData(reinterpret_cast<uint8_t*>(data), length);
    packet->params.ssrc = rcv.rcv_sid;
    packet->params.seq_num = rcv.rcv_ssn;
    packet->params.timestamp = rcv.rcv_tsn;
    packet->params.type = type;
    packet->flags = flags;
    // The ownership of |packet| transfers to |msg|.
    InboundPacketMessage* msg = new InboundPacketMessage(packet);
    channel->worker_thread()->Post(RTC_FROM_HERE, channel,
                                   MSG_SCTPINBOUNDPACKET, msg);
  }
  free(data);
  return 1;
}

void InitializeUsrSctp() {
  LOG(LS_INFO) << __FUNCTION__;
  // First argument is udp_encapsulation_port, which is not releveant for our
  // AF_CONN use of sctp.
  usrsctp_init(0, &OnSctpOutboundPacket, &DebugSctpPrintf);

  // To turn on/off detailed SCTP debugging. You will also need to have the
  // SCTP_DEBUG cpp defines flag.
  // usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);

  // TODO(ldixon): Consider turning this on/off.
  usrsctp_sysctl_set_sctp_ecn_enable(0);

  // This is harmless, but we should find out when the library default
  // changes.
  int send_size = usrsctp_sysctl_get_sctp_sendspace();
  if (send_size != kSendBufferSize) {
    LOG(LS_ERROR) << "Got different send size than expected: " << send_size;
  }

  // TODO(ldixon): Consider turning this on/off.
  // This is not needed right now (we don't do dynamic address changes):
  // If SCTP Auto-ASCONF is enabled, the peer is informed automatically
  // when a new address is added or removed. This feature is enabled by
  // default.
  // usrsctp_sysctl_set_sctp_auto_asconf(0);

  // TODO(ldixon): Consider turning this on/off.
  // Add a blackhole sysctl. Setting it to 1 results in no ABORTs
  // being sent in response to INITs, setting it to 2 results
  // in no ABORTs being sent for received OOTB packets.
  // This is similar to the TCP sysctl.
  //
  // See: http://lakerest.net/pipermail/sctp-coders/2012-January/009438.html
  // See: http://svnweb.freebsd.org/base?view=revision&revision=229805
  // usrsctp_sysctl_set_sctp_blackhole(2);

  // Set the number of default outgoing streams.  This is the number we'll
  // send in the SCTP INIT message.  The 'appropriate default' in the
  // second paragraph of
  // http://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-05#section-6.2
  // is kMaxSctpSid.
  usrsctp_sysctl_set_sctp_nr_outgoing_streams_default(kMaxSctpSid);
}

void UninitializeUsrSctp() {
  LOG(LS_INFO) << __FUNCTION__;
  // usrsctp_finish() may fail if it's called too soon after the channels are
  // closed. Wait and try again until it succeeds for up to 3 seconds.
  for (size_t i = 0; i < 300; ++i) {
    if (usrsctp_finish() == 0) {
      return;
    }

    rtc::Thread::SleepMs(10);
  }
  LOG(LS_ERROR) << "Failed to shutdown usrsctp.";
}

void IncrementUsrSctpUsageCount() {
  rtc::GlobalLockScope lock(&g_usrsctp_lock_);
  if (!g_usrsctp_usage_count) {
    InitializeUsrSctp();
  }
  ++g_usrsctp_usage_count;
}

void DecrementUsrSctpUsageCount() {
  rtc::GlobalLockScope lock(&g_usrsctp_lock_);
  --g_usrsctp_usage_count;
  if (!g_usrsctp_usage_count) {
    UninitializeUsrSctp();
  }
}

DataCodec GetSctpDataCodec() {
  DataCodec codec(kGoogleSctpDataCodecId, kGoogleSctpDataCodecName);
  codec.SetParam(kCodecParamPort, kSctpDefaultPort);
  return codec;
}

}  // namespace

SctpDataEngine::SctpDataEngine() : codecs_(1, GetSctpDataCodec()) {}

SctpDataEngine::~SctpDataEngine() {}

// Called on the worker thread.
DataMediaChannel* SctpDataEngine::CreateChannel(
    DataChannelType data_channel_type) {
  if (data_channel_type != DCT_SCTP) {
    return NULL;
  }
  return new SctpDataMediaChannel(rtc::Thread::Current());
}

// static
SctpDataMediaChannel* SctpDataMediaChannel::GetChannelFromSocket(
    struct socket* sock) {
  struct sockaddr* addrs = nullptr;
  int naddrs = usrsctp_getladdrs(sock, 0, &addrs);
  if (naddrs <= 0 || addrs[0].sa_family != AF_CONN) {
    return nullptr;
  }
  // usrsctp_getladdrs() returns the addresses bound to this socket, which
  // contains the SctpDataMediaChannel* as sconn_addr.  Read the pointer,
  // then free the list of addresses once we have the pointer.  We only open
  // AF_CONN sockets, and they should all have the sconn_addr set to the
  // pointer that created them, so [0] is as good as any other.
  struct sockaddr_conn* sconn =
      reinterpret_cast<struct sockaddr_conn*>(&addrs[0]);
  SctpDataMediaChannel* channel =
      reinterpret_cast<SctpDataMediaChannel*>(sconn->sconn_addr);
  usrsctp_freeladdrs(addrs);

  return channel;
}

// static
int SctpDataMediaChannel::SendThresholdCallback(struct socket* sock,
                                                uint32_t sb_free) {
  // Fired on our I/O thread.  SctpDataMediaChannel::OnPacketReceived() gets
  // a packet containing acknowledgments, which goes into usrsctp_conninput,
  // and then back here.
  SctpDataMediaChannel* channel = GetChannelFromSocket(sock);
  if (!channel) {
    LOG(LS_ERROR) << "SendThresholdCallback: Failed to get channel for socket "
                  << sock;
    return 0;
  }
  channel->OnSendThresholdCallback();
  return 0;
}

SctpDataMediaChannel::SctpDataMediaChannel(rtc::Thread* thread)
    : worker_thread_(thread),
      local_port_(kSctpDefaultPort),
      remote_port_(kSctpDefaultPort),
      sock_(NULL),
      sending_(false),
      receiving_(false),
      debug_name_("SctpDataMediaChannel") {
}

SctpDataMediaChannel::~SctpDataMediaChannel() {
  CloseSctpSocket();
}

void SctpDataMediaChannel::OnSendThresholdCallback() {
  RTC_DCHECK(rtc::Thread::Current() == worker_thread_);
  SignalReadyToSend(true);
}

sockaddr_conn SctpDataMediaChannel::GetSctpSockAddr(int port) {
  sockaddr_conn sconn = {0};
  sconn.sconn_family = AF_CONN;
#ifdef HAVE_SCONN_LEN
  sconn.sconn_len = sizeof(sockaddr_conn);
#endif
  // Note: conversion from int to uint16_t happens here.
  sconn.sconn_port = rtc::HostToNetwork16(port);
  sconn.sconn_addr = this;
  return sconn;
}

bool SctpDataMediaChannel::OpenSctpSocket() {
  if (sock_) {
    LOG(LS_VERBOSE) << debug_name_
                    << "->Ignoring attempt to re-create existing socket.";
    return false;
  }

  IncrementUsrSctpUsageCount();

  // If kSendBufferSize isn't reflective of reality, we log an error, but we
  // still have to do something reasonable here.  Look up what the buffer's
  // real size is and set our threshold to something reasonable.
  const static int kSendThreshold = usrsctp_sysctl_get_sctp_sendspace() / 2;

  sock_ = usrsctp_socket(
      AF_CONN, SOCK_STREAM, IPPROTO_SCTP, OnSctpInboundPacket,
      &SctpDataMediaChannel::SendThresholdCallback, kSendThreshold, this);
  if (!sock_) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to create SCTP socket.";
    DecrementUsrSctpUsageCount();
    return false;
  }

  // Make the socket non-blocking. Connect, close, shutdown etc will not block
  // the thread waiting for the socket operation to complete.
  if (usrsctp_set_non_blocking(sock_, 1) < 0) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP to non blocking.";
    return false;
  }

  // This ensures that the usrsctp close call deletes the association. This
  // prevents usrsctp from calling OnSctpOutboundPacket with references to
  // this class as the address.
  linger linger_opt;
  linger_opt.l_onoff = 1;
  linger_opt.l_linger = 0;
  if (usrsctp_setsockopt(sock_, SOL_SOCKET, SO_LINGER, &linger_opt,
                         sizeof(linger_opt))) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SO_LINGER.";
    return false;
  }

  // Enable stream ID resets.
  struct sctp_assoc_value stream_rst;
  stream_rst.assoc_id = SCTP_ALL_ASSOC;
  stream_rst.assoc_value = 1;
  if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET,
                         &stream_rst, sizeof(stream_rst))) {
    LOG_ERRNO(LS_ERROR) << debug_name_
                        << "Failed to set SCTP_ENABLE_STREAM_RESET.";
    return false;
  }

  // Nagle.
  uint32_t nodelay = 1;
  if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_NODELAY, &nodelay,
                         sizeof(nodelay))) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_NODELAY.";
    return false;
  }

  // Disable MTU discovery
  sctp_paddrparams params = {{0}};
  params.spp_assoc_id = 0;
  params.spp_flags = SPP_PMTUD_DISABLE;
  params.spp_pathmtu = kSctpMtu;
  if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &params,
      sizeof(params))) {
    LOG_ERRNO(LS_ERROR) << debug_name_
                        << "Failed to set SCTP_PEER_ADDR_PARAMS.";
    return false;
  }

  // Subscribe to SCTP event notifications.
  int event_types[] = {SCTP_ASSOC_CHANGE,
                       SCTP_PEER_ADDR_CHANGE,
                       SCTP_SEND_FAILED_EVENT,
                       SCTP_SENDER_DRY_EVENT,
                       SCTP_STREAM_RESET_EVENT};
  struct sctp_event event = {0};
  event.se_assoc_id = SCTP_ALL_ASSOC;
  event.se_on = 1;
  for (size_t i = 0; i < arraysize(event_types); i++) {
    event.se_type = event_types[i];
    if (usrsctp_setsockopt(sock_, IPPROTO_SCTP, SCTP_EVENT, &event,
                           sizeof(event)) < 0) {
      LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to set SCTP_EVENT type: "
                          << event.se_type;
      return false;
    }
  }

  // Register this class as an address for usrsctp. This is used by SCTP to
  // direct the packets received (by the created socket) to this class.
  usrsctp_register_address(this);
  sending_ = true;
  return true;
}

void SctpDataMediaChannel::CloseSctpSocket() {
  sending_ = false;
  if (sock_) {
    // We assume that SO_LINGER option is set to close the association when
    // close is called. This means that any pending packets in usrsctp will be
    // discarded instead of being sent.
    usrsctp_close(sock_);
    sock_ = NULL;
    usrsctp_deregister_address(this);

    DecrementUsrSctpUsageCount();
  }
}

bool SctpDataMediaChannel::Connect() {
  LOG(LS_VERBOSE) << debug_name_ << "->Connect().";

  // If we already have a socket connection, just return.
  if (sock_) {
    LOG(LS_WARNING) << debug_name_ << "->Connect(): Ignored as socket "
                                      "is already established.";
    return true;
  }

  // If no socket (it was closed) try to start it again. This can happen when
  // the socket we are connecting to closes, does an sctp shutdown handshake,
  // or behaves unexpectedly causing us to perform a CloseSctpSocket.
  if (!sock_ && !OpenSctpSocket()) {
    return false;
  }

  // Note: conversion from int to uint16_t happens on assignment.
  sockaddr_conn local_sconn = GetSctpSockAddr(local_port_);
  if (usrsctp_bind(sock_, reinterpret_cast<sockaddr *>(&local_sconn),
                   sizeof(local_sconn)) < 0) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "->Connect(): "
                        << ("Failed usrsctp_bind");
    CloseSctpSocket();
    return false;
  }

  // Note: conversion from int to uint16_t happens on assignment.
  sockaddr_conn remote_sconn = GetSctpSockAddr(remote_port_);
  int connect_result = usrsctp_connect(
      sock_, reinterpret_cast<sockaddr *>(&remote_sconn), sizeof(remote_sconn));
  if (connect_result < 0 && errno != SCTP_EINPROGRESS) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed usrsctp_connect. got errno="
                        << errno << ", but wanted " << SCTP_EINPROGRESS;
    CloseSctpSocket();
    return false;
  }
  return true;
}

void SctpDataMediaChannel::Disconnect() {
  // TODO(ldixon): Consider calling |usrsctp_shutdown(sock_, ...)| to do a
  // shutdown handshake and remove the association.
  CloseSctpSocket();
}

bool SctpDataMediaChannel::SetSend(bool send) {
  if (!sending_ && send) {
    return Connect();
  }
  if (sending_ && !send) {
    Disconnect();
  }
  return true;
}

bool SctpDataMediaChannel::SetReceive(bool receive) {
  receiving_ = receive;
  return true;
}

bool SctpDataMediaChannel::SetSendParameters(const DataSendParameters& params) {
  return SetSendCodecs(params.codecs);
}

bool SctpDataMediaChannel::SetRecvParameters(const DataRecvParameters& params) {
  return SetRecvCodecs(params.codecs);
}

bool SctpDataMediaChannel::AddSendStream(const StreamParams& stream) {
  return AddStream(stream);
}

bool SctpDataMediaChannel::RemoveSendStream(uint32_t ssrc) {
  return ResetStream(ssrc);
}

bool SctpDataMediaChannel::AddRecvStream(const StreamParams& stream) {
  // SCTP DataChannels are always bi-directional and calling AddSendStream will
  // enable both sending and receiving on the stream. So AddRecvStream is a
  // no-op.
  return true;
}

bool SctpDataMediaChannel::RemoveRecvStream(uint32_t ssrc) {
  // SCTP DataChannels are always bi-directional and calling RemoveSendStream
  // will disable both sending and receiving on the stream. So RemoveRecvStream
  // is a no-op.
  return true;
}

bool SctpDataMediaChannel::SendData(
    const SendDataParams& params,
    const rtc::CopyOnWriteBuffer& payload,
    SendDataResult* result) {
  if (result) {
    // Preset |result| to assume an error.  If SendData succeeds, we'll
    // overwrite |*result| once more at the end.
    *result = SDR_ERROR;
  }

  if (!sending_) {
    LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
                    << "Not sending packet with ssrc=" << params.ssrc
                    << " len=" << payload.size() << " before SetSend(true).";
    return false;
  }

  if (params.type != DMT_CONTROL &&
      open_streams_.find(params.ssrc) == open_streams_.end()) {
    LOG(LS_WARNING) << debug_name_ << "->SendData(...): "
                    << "Not sending data because ssrc is unknown: "
                    << params.ssrc;
    return false;
  }

  //
  // Send data using SCTP.
  ssize_t send_res = 0;  // result from usrsctp_sendv.
  struct sctp_sendv_spa spa = {0};
  spa.sendv_flags |= SCTP_SEND_SNDINFO_VALID;
  spa.sendv_sndinfo.snd_sid = params.ssrc;
  spa.sendv_sndinfo.snd_ppid = rtc::HostToNetwork32(
      GetPpid(params.type));

  // Ordered implies reliable.
  if (!params.ordered) {
    spa.sendv_sndinfo.snd_flags |= SCTP_UNORDERED;
    if (params.max_rtx_count >= 0 || params.max_rtx_ms == 0) {
      spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
      spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
      spa.sendv_prinfo.pr_value = params.max_rtx_count;
    } else {
      spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
      spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
      spa.sendv_prinfo.pr_value = params.max_rtx_ms;
    }
  }

  // We don't fragment.
  send_res = usrsctp_sendv(
      sock_, payload.data(), static_cast<size_t>(payload.size()), NULL, 0, &spa,
      rtc::checked_cast<socklen_t>(sizeof(spa)), SCTP_SENDV_SPA, 0);
  if (send_res < 0) {
    if (errno == SCTP_EWOULDBLOCK) {
      *result = SDR_BLOCK;
      LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned";
    } else {
      LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_
                          << "->SendData(...): "
                          << " usrsctp_sendv: ";
    }
    return false;
  }
  if (result) {
    // Only way out now is success.
    *result = SDR_SUCCESS;
  }
  return true;
}

// Called by network interface when a packet has been received.
void SctpDataMediaChannel::OnPacketReceived(
    rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
  RTC_DCHECK(rtc::Thread::Current() == worker_thread_);
  LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): "
                  << " length=" << packet->size() << ", sending: " << sending_;
  // Only give receiving packets to usrsctp after if connected. This enables two
  // peers to each make a connect call, but for them not to receive an INIT
  // packet before they have called connect; least the last receiver of the INIT
  // packet will have called connect, and a connection will be established.
  if (sending_) {
    // Pass received packet to SCTP stack. Once processed by usrsctp, the data
    // will be will be given to the global OnSctpInboundData, and then,
    // marshalled by a Post and handled with OnMessage.
    VerboseLogPacket(packet->cdata(), packet->size(), SCTP_DUMP_INBOUND);
    usrsctp_conninput(this, packet->cdata(), packet->size(), 0);
  } else {
    // TODO(ldixon): Consider caching the packet for very slightly better
    // reliability.
  }
}

void SctpDataMediaChannel::OnInboundPacketFromSctpToChannel(
    SctpInboundPacket* packet) {
  LOG(LS_VERBOSE) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): "
                  << "Received SCTP data:"
                  << " ssrc=" << packet->params.ssrc
                  << " notification: " << (packet->flags & MSG_NOTIFICATION)
                  << " length=" << packet->buffer.size();
  // Sending a packet with data == NULL (no data) is SCTPs "close the
  // connection" message. This sets sock_ = NULL;
  if (!packet->buffer.size() || !packet->buffer.data()) {
    LOG(LS_INFO) << debug_name_ << "->OnInboundPacketFromSctpToChannel(...): "
                                   "No data, closing.";
    return;
  }
  if (packet->flags & MSG_NOTIFICATION) {
    OnNotificationFromSctp(packet->buffer);
  } else {
    OnDataFromSctpToChannel(packet->params, packet->buffer);
  }
}

void SctpDataMediaChannel::OnDataFromSctpToChannel(
    const ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
  if (receiving_) {
    LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): "
                    << "Posting with length: " << buffer.size()
                    << " on stream " << params.ssrc;
    // Reports all received messages to upper layers, no matter whether the sid
    // is known.
    SignalDataReceived(params, buffer.data<char>(), buffer.size());
  } else {
    LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
                    << "Not receiving packet with sid=" << params.ssrc
                    << " len=" << buffer.size() << " before SetReceive(true).";
  }
}

bool SctpDataMediaChannel::AddStream(const StreamParams& stream) {
  if (!stream.has_ssrcs()) {
    return false;
  }

  const uint32_t ssrc = stream.first_ssrc();
  if (ssrc >= kMaxSctpSid) {
    LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
                    << "Not adding data stream '" << stream.id
                    << "' with ssrc=" << ssrc
                    << " because stream ssrc is too high.";
    return false;
  } else if (open_streams_.find(ssrc) != open_streams_.end()) {
    LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
                    << "Not adding data stream '" << stream.id
                    << "' with ssrc=" << ssrc
                    << " because stream is already open.";
    return false;
  } else if (queued_reset_streams_.find(ssrc) != queued_reset_streams_.end()
             || sent_reset_streams_.find(ssrc) != sent_reset_streams_.end()) {
    LOG(LS_WARNING) << debug_name_ << "->Add(Send|Recv)Stream(...): "
                    << "Not adding data stream '" << stream.id
                    << "' with ssrc=" << ssrc
                    << " because stream is still closing.";
    return false;
  }

  open_streams_.insert(ssrc);
  return true;
}

bool SctpDataMediaChannel::ResetStream(uint32_t ssrc) {
  // We typically get this called twice for the same stream, once each for
  // Send and Recv.
  StreamSet::iterator found = open_streams_.find(ssrc);

  if (found == open_streams_.end()) {
    LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): "
                    << "stream not found.";
    return false;
  } else {
    LOG(LS_VERBOSE) << debug_name_ << "->ResetStream(" << ssrc << "): "
                    << "Removing and queuing RE-CONFIG chunk.";
    open_streams_.erase(found);
  }

  // SCTP won't let you have more than one stream reset pending at a time, but
  // you can close multiple streams in a single reset.  So, we keep an internal
  // queue of streams-to-reset, and send them as one reset message in
  // SendQueuedStreamResets().
  queued_reset_streams_.insert(ssrc);

  // Signal our stream-reset logic that it should try to send now, if it can.
  SendQueuedStreamResets();

  // The stream will actually get removed when we get the acknowledgment.
  return true;
}

void SctpDataMediaChannel::OnNotificationFromSctp(
    const rtc::CopyOnWriteBuffer& buffer) {
  const sctp_notification& notification =
      reinterpret_cast<const sctp_notification&>(*buffer.data());
  ASSERT(notification.sn_header.sn_length == buffer.size());

  // TODO(ldixon): handle notifications appropriately.
  switch (notification.sn_header.sn_type) {
    case SCTP_ASSOC_CHANGE:
      LOG(LS_VERBOSE) << "SCTP_ASSOC_CHANGE";
      OnNotificationAssocChange(notification.sn_assoc_change);
      break;
    case SCTP_REMOTE_ERROR:
      LOG(LS_INFO) << "SCTP_REMOTE_ERROR";
      break;
    case SCTP_SHUTDOWN_EVENT:
      LOG(LS_INFO) << "SCTP_SHUTDOWN_EVENT";
      break;
    case SCTP_ADAPTATION_INDICATION:
      LOG(LS_INFO) << "SCTP_ADAPTATION_INDICATION";
      break;
    case SCTP_PARTIAL_DELIVERY_EVENT:
      LOG(LS_INFO) << "SCTP_PARTIAL_DELIVERY_EVENT";
      break;
    case SCTP_AUTHENTICATION_EVENT:
      LOG(LS_INFO) << "SCTP_AUTHENTICATION_EVENT";
      break;
    case SCTP_SENDER_DRY_EVENT:
      LOG(LS_VERBOSE) << "SCTP_SENDER_DRY_EVENT";
      SignalReadyToSend(true);
      break;
    // TODO(ldixon): Unblock after congestion.
    case SCTP_NOTIFICATIONS_STOPPED_EVENT:
      LOG(LS_INFO) << "SCTP_NOTIFICATIONS_STOPPED_EVENT";
      break;
    case SCTP_SEND_FAILED_EVENT:
      LOG(LS_INFO) << "SCTP_SEND_FAILED_EVENT";
      break;
    case SCTP_STREAM_RESET_EVENT:
      OnStreamResetEvent(&notification.sn_strreset_event);
      break;
    case SCTP_ASSOC_RESET_EVENT:
      LOG(LS_INFO) << "SCTP_ASSOC_RESET_EVENT";
      break;
    case SCTP_STREAM_CHANGE_EVENT:
      LOG(LS_INFO) << "SCTP_STREAM_CHANGE_EVENT";
      // An acknowledgment we get after our stream resets have gone through,
      // if they've failed.  We log the message, but don't react -- we don't
      // keep around the last-transmitted set of SSIDs we wanted to close for
      // error recovery.  It doesn't seem likely to occur, and if so, likely
      // harmless within the lifetime of a single SCTP association.
      break;
    default:
      LOG(LS_WARNING) << "Unknown SCTP event: "
                      << notification.sn_header.sn_type;
      break;
  }
}

void SctpDataMediaChannel::OnNotificationAssocChange(
    const sctp_assoc_change& change) {
  switch (change.sac_state) {
    case SCTP_COMM_UP:
      LOG(LS_VERBOSE) << "Association change SCTP_COMM_UP";
      break;
    case SCTP_COMM_LOST:
      LOG(LS_INFO) << "Association change SCTP_COMM_LOST";
      break;
    case SCTP_RESTART:
      LOG(LS_INFO) << "Association change SCTP_RESTART";
      break;
    case SCTP_SHUTDOWN_COMP:
      LOG(LS_INFO) << "Association change SCTP_SHUTDOWN_COMP";
      break;
    case SCTP_CANT_STR_ASSOC:
      LOG(LS_INFO) << "Association change SCTP_CANT_STR_ASSOC";
      break;
    default:
      LOG(LS_INFO) << "Association change UNKNOWN";
      break;
  }
}

void SctpDataMediaChannel::OnStreamResetEvent(
    const struct sctp_stream_reset_event* evt) {
  // A stream reset always involves two RE-CONFIG chunks for us -- we always
  // simultaneously reset a sid's sequence number in both directions.  The
  // requesting side transmits a RE-CONFIG chunk and waits for the peer to send
  // one back.  Both sides get this SCTP_STREAM_RESET_EVENT when they receive
  // RE-CONFIGs.
  const int num_ssrcs = (evt->strreset_length - sizeof(*evt)) /
      sizeof(evt->strreset_stream_list[0]);
  LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
                  << "): Flags = 0x"
                  << std::hex << evt->strreset_flags << " ("
                  << ListFlags(evt->strreset_flags) << ")";
  LOG(LS_VERBOSE) << "Assoc = " << evt->strreset_assoc_id << ", Streams = ["
                  << ListArray(evt->strreset_stream_list, num_ssrcs)
                  << "], Open: ["
                  << ListStreams(open_streams_) << "], Q'd: ["
                  << ListStreams(queued_reset_streams_) << "], Sent: ["
                  << ListStreams(sent_reset_streams_) << "]";

  // If both sides try to reset some streams at the same time (even if they're
  // disjoint sets), we can get reset failures.
  if (evt->strreset_flags & SCTP_STREAM_RESET_FAILED) {
    // OK, just try again.  The stream IDs sent over when the RESET_FAILED flag
    // is set seem to be garbage values.  Ignore them.
    queued_reset_streams_.insert(
        sent_reset_streams_.begin(),
        sent_reset_streams_.end());
    sent_reset_streams_.clear();

  } else if (evt->strreset_flags & SCTP_STREAM_RESET_INCOMING_SSN) {
    // Each side gets an event for each direction of a stream.  That is,
    // closing sid k will make each side receive INCOMING and OUTGOING reset
    // events for k.  As per RFC6525, Section 5, paragraph 2, each side will
    // get an INCOMING event first.
    for (int i = 0; i < num_ssrcs; i++) {
      const int stream_id = evt->strreset_stream_list[i];

      // See if this stream ID was closed by our peer or ourselves.
      StreamSet::iterator it = sent_reset_streams_.find(stream_id);

      // The reset was requested locally.
      if (it != sent_reset_streams_.end()) {
        LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
                        << "): local sid " << stream_id << " acknowledged.";
        sent_reset_streams_.erase(it);

      } else if ((it = open_streams_.find(stream_id))
                 != open_streams_.end()) {
        // The peer requested the reset.
        LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
                        << "): closing sid " << stream_id;
        open_streams_.erase(it);
        SignalStreamClosedRemotely(stream_id);

      } else if ((it = queued_reset_streams_.find(stream_id))
                 != queued_reset_streams_.end()) {
        // The peer requested the reset, but there was a local reset
        // queued.
        LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
                        << "): double-sided close for sid " << stream_id;
        // Both sides want the stream closed, and the peer got to send the
        // RE-CONFIG first.  Treat it like the local Remove(Send|Recv)Stream
        // finished quickly.
        queued_reset_streams_.erase(it);

      } else {
        // This stream is unknown.  Sometimes this can be from an
        // RESET_FAILED-related retransmit.
        LOG(LS_VERBOSE) << "SCTP_STREAM_RESET_EVENT(" << debug_name_
                        << "): Unknown sid " << stream_id;
      }
    }
  }

  // Always try to send the queued RESET because this call indicates that the
  // last local RESET or remote RESET has made some progress.
  SendQueuedStreamResets();
}

// Puts the specified |param| from the codec identified by |id| into |dest|
// and returns true.  Or returns false if it wasn't there, leaving |dest|
// untouched.
static bool GetCodecIntParameter(const std::vector<DataCodec>& codecs,
                                 int id, const std::string& name,
                                 const std::string& param, int* dest) {
  std::string value;
  Codec match_pattern;
  match_pattern.id = id;
  match_pattern.name = name;
  for (size_t i = 0; i < codecs.size(); ++i) {
    if (codecs[i].Matches(match_pattern)) {
      if (codecs[i].GetParam(param, &value)) {
        *dest = rtc::FromString<int>(value);
        return true;
      }
    }
  }
  return false;
}

bool SctpDataMediaChannel::SetSendCodecs(const std::vector<DataCodec>& codecs) {
  return GetCodecIntParameter(
      codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
      &remote_port_);
}

bool SctpDataMediaChannel::SetRecvCodecs(const std::vector<DataCodec>& codecs) {
  return GetCodecIntParameter(
      codecs, kGoogleSctpDataCodecId, kGoogleSctpDataCodecName, kCodecParamPort,
      &local_port_);
}

void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
    rtc::CopyOnWriteBuffer* buffer) {
  // usrsctp seems to interpret the MTU we give it strangely -- it seems to
  // give us back packets bigger than that MTU, if only by a fixed amount.
  // This is that amount that we've observed.
  const int kSctpOverhead = 76;
  if (buffer->size() > (kSctpOverhead + kSctpMtu)) {
    LOG(LS_ERROR) << debug_name_ << "->OnPacketFromSctpToNetwork(...): "
                  << "SCTP seems to have made a packet that is bigger "
                  << "than its official MTU: " << buffer->size()
                  << " vs max of " << kSctpMtu
                  << " even after adding " << kSctpOverhead
                  << " extra SCTP overhead";
  }
  MediaChannel::SendPacket(buffer, rtc::PacketOptions());
}

bool SctpDataMediaChannel::SendQueuedStreamResets() {
  if (!sent_reset_streams_.empty() || queued_reset_streams_.empty()) {
    return true;
  }

  LOG(LS_VERBOSE) << "SendQueuedStreamResets[" << debug_name_ << "]: Sending ["
                  << ListStreams(queued_reset_streams_) << "], Open: ["
                  << ListStreams(open_streams_) << "], Sent: ["
                  << ListStreams(sent_reset_streams_) << "]";

  const size_t num_streams = queued_reset_streams_.size();
  const size_t num_bytes =
      sizeof(struct sctp_reset_streams) + (num_streams * sizeof(uint16_t));

  std::vector<uint8_t> reset_stream_buf(num_bytes, 0);
  struct sctp_reset_streams* resetp = reinterpret_cast<sctp_reset_streams*>(
      &reset_stream_buf[0]);
  resetp->srs_assoc_id = SCTP_ALL_ASSOC;
  resetp->srs_flags = SCTP_STREAM_RESET_INCOMING | SCTP_STREAM_RESET_OUTGOING;
  resetp->srs_number_streams = rtc::checked_cast<uint16_t>(num_streams);
  int result_idx = 0;
  for (StreamSet::iterator it = queued_reset_streams_.begin();
       it != queued_reset_streams_.end(); ++it) {
    resetp->srs_stream_list[result_idx++] = *it;
  }

  int ret = usrsctp_setsockopt(
      sock_, IPPROTO_SCTP, SCTP_RESET_STREAMS, resetp,
      rtc::checked_cast<socklen_t>(reset_stream_buf.size()));
  if (ret < 0) {
    LOG_ERRNO(LS_ERROR) << debug_name_ << "Failed to send a stream reset for "
                        << num_streams << " streams";
    return false;
  }

  // sent_reset_streams_ is empty, and all the queued_reset_streams_ go into
  // it now.
  queued_reset_streams_.swap(sent_reset_streams_);
  return true;
}

void SctpDataMediaChannel::OnMessage(rtc::Message* msg) {
  switch (msg->message_id) {
    case MSG_SCTPINBOUNDPACKET: {
      std::unique_ptr<InboundPacketMessage> pdata(
          static_cast<InboundPacketMessage*>(msg->pdata));
      OnInboundPacketFromSctpToChannel(pdata->data().get());
      break;
    }
    case MSG_SCTPOUTBOUNDPACKET: {
      std::unique_ptr<OutboundPacketMessage> pdata(
          static_cast<OutboundPacketMessage*>(msg->pdata));
      OnPacketFromSctpToNetwork(pdata->data().get());
      break;
    }
  }
}
}  // namespace cricket
