/*
 *  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);
}

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);
  }
}

}  // namespace webrtc
