/*
 *  Copyright 2019 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 "pc/sctp_data_channel_transport.h"
#include "pc/sctp_utils.h"

namespace webrtc {

SctpDataChannelTransport::SctpDataChannelTransport(
    cricket::SctpTransportInternal* sctp_transport)
    : sctp_transport_(sctp_transport) {
  sctp_transport_->SignalReadyToSendData.connect(
      this, &SctpDataChannelTransport::OnReadyToSendData);
  sctp_transport_->SignalDataReceived.connect(
      this, &SctpDataChannelTransport::OnDataReceived);
  sctp_transport_->SignalClosingProcedureStartedRemotely.connect(
      this, &SctpDataChannelTransport::OnClosingProcedureStartedRemotely);
  sctp_transport_->SignalClosingProcedureComplete.connect(
      this, &SctpDataChannelTransport::OnClosingProcedureComplete);
  sctp_transport_->SignalClosedAbruptly.connect(
      this, &SctpDataChannelTransport::OnClosedAbruptly);
}

RTCError SctpDataChannelTransport::OpenChannel(int channel_id) {
  sctp_transport_->OpenStream(channel_id);
  return RTCError::OK();
}

RTCError SctpDataChannelTransport::SendData(
    int channel_id,
    const SendDataParams& params,
    const rtc::CopyOnWriteBuffer& buffer) {
  // Map webrtc::SendDataParams to cricket::SendDataParams.
  // TODO(mellem):  See about unifying these structs.
  cricket::SendDataParams sd_params;
  sd_params.sid = channel_id;
  sd_params.type = ToCricketDataMessageType(params.type);
  sd_params.ordered = params.ordered;
  sd_params.reliable = !(params.max_rtx_count || params.max_rtx_ms);
  sd_params.max_rtx_count = params.max_rtx_count.value_or(-1);
  sd_params.max_rtx_ms = params.max_rtx_ms.value_or(-1);

  cricket::SendDataResult result;
  sctp_transport_->SendData(sd_params, buffer, &result);

  // TODO(mellem):  See about changing the interfaces to not require mapping
  // SendDataResult to RTCError and back again.
  switch (result) {
    case cricket::SendDataResult::SDR_SUCCESS:
      return RTCError::OK();
    case cricket::SendDataResult::SDR_BLOCK: {
      // Send buffer is full.
      ready_to_send_ = false;
      return RTCError(RTCErrorType::RESOURCE_EXHAUSTED);
    }
    case cricket::SendDataResult::SDR_ERROR:
      return RTCError(RTCErrorType::NETWORK_ERROR);
  }
  return RTCError(RTCErrorType::NETWORK_ERROR);
}

RTCError SctpDataChannelTransport::CloseChannel(int channel_id) {
  sctp_transport_->ResetStream(channel_id);
  return RTCError::OK();
}

void SctpDataChannelTransport::SetDataSink(DataChannelSink* sink) {
  sink_ = sink;
  if (sink_ && ready_to_send_) {
    sink_->OnReadyToSend();
  }
}

bool SctpDataChannelTransport::IsReadyToSend() const {
  return ready_to_send_;
}

void SctpDataChannelTransport::OnReadyToSendData() {
  ready_to_send_ = true;
  if (sink_) {
    sink_->OnReadyToSend();
  }
}

void SctpDataChannelTransport::OnDataReceived(
    const cricket::ReceiveDataParams& params,
    const rtc::CopyOnWriteBuffer& buffer) {
  if (sink_) {
    sink_->OnDataReceived(params.sid, ToWebrtcDataMessageType(params.type),
                          buffer);
  }
}

void SctpDataChannelTransport::OnClosingProcedureStartedRemotely(
    int channel_id) {
  if (sink_) {
    sink_->OnChannelClosing(channel_id);
  }
}

void SctpDataChannelTransport::OnClosingProcedureComplete(int channel_id) {
  if (sink_) {
    sink_->OnChannelClosed(channel_id);
  }
}

void SctpDataChannelTransport::OnClosedAbruptly() {
  if (sink_) {
    sink_->OnTransportClosed();
  }
}

}  // namespace webrtc
