/*
 *  Copyright 2016 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/quicdatachannel.h"

#include "p2p/quic/quictransportchannel.h"
#include "p2p/quic/reliablequicstream.h"
#include "rtc_base/bind.h"
#include "rtc_base/bytebuffer.h"
#include "rtc_base/copyonwritebuffer.h"
#include "rtc_base/logging.h"

namespace webrtc {

void WriteQuicDataChannelMessageHeader(int data_channel_id,
                                       uint64_t message_id,
                                       rtc::CopyOnWriteBuffer* header) {
  RTC_DCHECK(header);
  // 64-bit varints require at most 10 bytes (7*10 == 70), and 32-bit varints
  // require at most 5 bytes (7*5 == 35).
  size_t max_length = 15;
  rtc::ByteBufferWriter byte_buffer(nullptr, max_length,
                                    rtc::ByteBuffer::ByteOrder::ORDER_HOST);
  byte_buffer.WriteUVarint(data_channel_id);
  byte_buffer.WriteUVarint(message_id);
  header->SetData(byte_buffer.Data(), byte_buffer.Length());
}

bool ParseQuicDataMessageHeader(const char* data,
                                size_t len,
                                int* data_channel_id,
                                uint64_t* message_id,
                                size_t* bytes_read) {
  RTC_DCHECK(data_channel_id);
  RTC_DCHECK(message_id);
  RTC_DCHECK(bytes_read);

  rtc::ByteBufferReader byte_buffer(data, len, rtc::ByteBuffer::ORDER_HOST);
  uint64_t dcid;
  if (!byte_buffer.ReadUVarint(&dcid)) {
    LOG(LS_ERROR) << "Could not read the data channel ID";
    return false;
  }
  *data_channel_id = dcid;
  if (!byte_buffer.ReadUVarint(message_id)) {
    LOG(LS_ERROR) << "Could not read message ID for data channel "
                  << *data_channel_id;
    return false;
  }
  size_t remaining_bytes = byte_buffer.Length();
  *bytes_read = len - remaining_bytes;
  return true;
}

QuicDataChannel::QuicDataChannel(rtc::Thread* signaling_thread,
                                 rtc::Thread* worker_thread,
                                 rtc::Thread* network_thread,
                                 const std::string& label,
                                 const DataChannelInit& config)
    : signaling_thread_(signaling_thread),
      worker_thread_(worker_thread),
      network_thread_(network_thread),
      id_(config.id),
      state_(kConnecting),
      buffered_amount_(0),
      next_message_id_(0),
      label_(label),
      protocol_(config.protocol) {}

QuicDataChannel::~QuicDataChannel() {}

void QuicDataChannel::RegisterObserver(DataChannelObserver* observer) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  observer_ = observer;
}

void QuicDataChannel::UnregisterObserver() {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  observer_ = nullptr;
}

bool QuicDataChannel::Send(const DataBuffer& buffer) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (state_ != kOpen) {
    LOG(LS_ERROR) << "QUIC data channel " << id_
                  << " is not open so cannot send.";
    return false;
  }
  return network_thread_->Invoke<bool>(
      RTC_FROM_HERE, rtc::Bind(&QuicDataChannel::Send_n, this, buffer));
}

bool QuicDataChannel::Send_n(const DataBuffer& buffer) {
  RTC_DCHECK(network_thread_->IsCurrent());

  // Encode and send the header containing the data channel ID and message ID.
  rtc::CopyOnWriteBuffer header;
  WriteQuicDataChannelMessageHeader(id_, ++next_message_id_, &header);
  RTC_DCHECK(quic_transport_channel_);
  cricket::ReliableQuicStream* stream =
      quic_transport_channel_->CreateQuicStream();
  RTC_DCHECK(stream);

  // Send the header with a FIN if the message is empty.
  bool header_fin = (buffer.size() == 0);
  rtc::StreamResult header_result =
      stream->Write(header.data<char>(), header.size(), header_fin);

  if (header_result == rtc::SR_BLOCK) {
    // The header is write blocked but we should try sending the message. Since
    // the ReliableQuicStream queues data in order, if the header is write
    // blocked then the message will be write blocked. Otherwise if the message
    // is sent then the header is sent.
    LOG(LS_INFO) << "Stream " << stream->id()
                 << " header is write blocked for QUIC data channel " << id_;
  } else if (header_result != rtc::SR_SUCCESS) {
    LOG(LS_ERROR) << "Stream " << stream->id()
                  << " failed to write header for QUIC data channel " << id_
                  << ". Unexpected error " << header_result;
    return false;
  }

  // If the message is not empty, then send the message with a FIN.
  bool message_fin = true;
  rtc::StreamResult message_result =
      header_fin ? header_result : stream->Write(buffer.data.data<char>(),
                                                 buffer.size(), message_fin);

  if (message_result == rtc::SR_SUCCESS) {
    // The message is sent and we don't need this QUIC stream.
    LOG(LS_INFO) << "Stream " << stream->id()
                 << " successfully wrote message for QUIC data channel " << id_;
    stream->Close();
    return true;
  }
  // TODO(mikescarlett): Register the ReliableQuicStream's priority to the
  // QuicWriteBlockedList so that the QUIC session doesn't drop messages when
  // the QUIC transport channel becomes unwritable.
  if (message_result == rtc::SR_BLOCK) {
    // The QUIC stream is write blocked, so the message is queued by the QUIC
    // session. If this is due to the QUIC not being writable, it will be sent
    // once QUIC becomes writable again. Otherwise it may be due to exceeding
    // the QUIC flow control limit, in which case the remote peer's QUIC session
    // will tell the QUIC stream to send more data.
    LOG(LS_INFO) << "Stream " << stream->id()
                 << " message is write blocked for QUIC data channel " << id_;
    SetBufferedAmount_w(buffered_amount_ + stream->queued_data_bytes());
    stream->SignalQueuedBytesWritten.connect(
        this, &QuicDataChannel::OnQueuedBytesWritten);
    write_blocked_quic_streams_[stream->id()] = stream;
    // The QUIC stream will be removed from |write_blocked_quic_streams_| once
    // it closes.
    stream->SignalClosed.connect(this,
                                 &QuicDataChannel::OnWriteBlockedStreamClosed);
    return true;
  }
  LOG(LS_ERROR) << "Stream " << stream->id()
                << " failed to write message for QUIC data channel " << id_
                << ". Unexpected error: " << message_result;
  return false;
}

void QuicDataChannel::OnQueuedBytesWritten(net::QuicStreamId stream_id,
                                           uint64_t queued_bytes_written) {
  RTC_DCHECK(worker_thread_->IsCurrent());
  SetBufferedAmount_w(buffered_amount_ - queued_bytes_written);
  const auto& kv = write_blocked_quic_streams_.find(stream_id);
  if (kv == write_blocked_quic_streams_.end()) {
    RTC_NOTREACHED();
    return;
  }
  cricket::ReliableQuicStream* stream = kv->second;
  // True if the QUIC stream is done sending data.
  if (stream->fin_sent()) {
    LOG(LS_INFO) << "Stream " << stream->id()
                 << " successfully wrote data for QUIC data channel " << id_;
    stream->Close();
  }
}

void QuicDataChannel::SetBufferedAmount_w(uint64_t buffered_amount) {
  RTC_DCHECK(worker_thread_->IsCurrent());
  buffered_amount_ = buffered_amount;
  invoker_.AsyncInvoke<void>(
      RTC_FROM_HERE, signaling_thread_,
      rtc::Bind(&QuicDataChannel::OnBufferedAmountChange_s, this,
                buffered_amount));
}

void QuicDataChannel::Close() {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (state_ == kClosed || state_ == kClosing) {
    return;
  }
  LOG(LS_INFO) << "Closing QUIC data channel.";
  SetState_s(kClosing);
  worker_thread_->Invoke<void>(RTC_FROM_HERE,
                               rtc::Bind(&QuicDataChannel::Close_w, this));
  SetState_s(kClosed);
}

void QuicDataChannel::Close_w() {
  RTC_DCHECK(worker_thread_->IsCurrent());
  for (auto& kv : incoming_quic_messages_) {
    Message& message = kv.second;
    cricket::ReliableQuicStream* stream = message.stream;
    stream->Close();
  }

  for (auto& kv : write_blocked_quic_streams_) {
    cricket::ReliableQuicStream* stream = kv.second;
    stream->Close();
  }
}

bool QuicDataChannel::SetTransportChannel(
    cricket::QuicTransportChannel* channel) {
  RTC_DCHECK(signaling_thread_->IsCurrent());

  if (!channel) {
    LOG(LS_ERROR) << "|channel| is NULL. Cannot set transport channel.";
    return false;
  }
  if (quic_transport_channel_) {
    if (channel == quic_transport_channel_) {
      LOG(LS_WARNING) << "Ignoring duplicate transport channel.";
      return true;
    }
    LOG(LS_ERROR) << "|channel| does not match existing transport channel.";
    return false;
  }

  quic_transport_channel_ = channel;
  LOG(LS_INFO) << "Setting QuicTransportChannel for QUIC data channel " << id_;
  DataState data_channel_state = worker_thread_->Invoke<DataState>(
      RTC_FROM_HERE, rtc::Bind(&QuicDataChannel::SetTransportChannel_w, this));
  SetState_s(data_channel_state);
  return true;
}

DataChannelInterface::DataState QuicDataChannel::SetTransportChannel_w() {
  RTC_DCHECK(worker_thread_->IsCurrent());
  quic_transport_channel_->SignalReadyToSend.connect(
      this, &QuicDataChannel::OnReadyToSend);
  quic_transport_channel_->SignalClosed.connect(
      this, &QuicDataChannel::OnConnectionClosed);
  if (quic_transport_channel_->writable()) {
    return kOpen;
  }
  return kConnecting;
}

void QuicDataChannel::OnIncomingMessage(Message&& message) {
  RTC_DCHECK(network_thread_->IsCurrent());
  RTC_DCHECK(message.stream);
  if (!observer_) {
    LOG(LS_WARNING) << "QUIC data channel " << id_
                    << " received a message but has no observer.";
    message.stream->Close();
    return;
  }
  // A FIN is received if the message fits into a single QUIC stream frame and
  // the remote peer is done sending.
  if (message.stream->fin_received()) {
    LOG(LS_INFO) << "Stream " << message.stream->id()
                 << " has finished receiving data for QUIC data channel "
                 << id_;
    DataBuffer final_message(message.buffer, false);
    invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
                               rtc::Bind(&QuicDataChannel::OnMessage_s, this,
                                         std::move(final_message)));
    message.stream->Close();
    return;
  }
  // Otherwise the message is divided across multiple QUIC stream frames, so
  // queue the data. OnDataReceived() will be called each time the remaining
  // QUIC stream frames arrive.
  LOG(LS_INFO) << "QUIC data channel " << id_
               << " is queuing incoming data for stream "
               << message.stream->id();
  incoming_quic_messages_[message.stream->id()] = std::move(message);
  message.stream->SignalDataReceived.connect(this,
                                             &QuicDataChannel::OnDataReceived);
  // The QUIC stream will be removed from |incoming_quic_messages_| once it
  // closes.
  message.stream->SignalClosed.connect(
      this, &QuicDataChannel::OnIncomingQueuedStreamClosed);
}

void QuicDataChannel::OnDataReceived(net::QuicStreamId stream_id,
                                     const char* data,
                                     size_t len) {
  RTC_DCHECK(network_thread_->IsCurrent());
  RTC_DCHECK(data);
  const auto& kv = incoming_quic_messages_.find(stream_id);
  if (kv == incoming_quic_messages_.end()) {
    RTC_NOTREACHED();
    return;
  }
  Message& message = kv->second;
  cricket::ReliableQuicStream* stream = message.stream;
  rtc::CopyOnWriteBuffer& received_data = message.buffer;
  // If the QUIC stream has not received a FIN, then the remote peer is not
  // finished sending data.
  if (!stream->fin_received()) {
    received_data.AppendData(data, len);
    return;
  }
  // Otherwise we are done receiving and can provide the data channel observer
  // with the message.
  LOG(LS_INFO) << "Stream " << stream_id
               << " has finished receiving data for QUIC data channel " << id_;
  received_data.AppendData(data, len);
  DataBuffer final_message(std::move(received_data), false);
  invoker_.AsyncInvoke<void>(
      RTC_FROM_HERE, signaling_thread_,
      rtc::Bind(&QuicDataChannel::OnMessage_s, this, std::move(final_message)));
  // Once the stream is closed, OnDataReceived will not fire for the stream.
  stream->Close();
}

void QuicDataChannel::OnReadyToSend(cricket::TransportChannel* channel) {
  RTC_DCHECK(network_thread_->IsCurrent());
  RTC_DCHECK(channel == quic_transport_channel_);
  LOG(LS_INFO) << "QuicTransportChannel is ready to send";
  invoker_.AsyncInvoke<void>(
      RTC_FROM_HERE, signaling_thread_,
      rtc::Bind(&QuicDataChannel::SetState_s, this, kOpen));
}

void QuicDataChannel::OnWriteBlockedStreamClosed(net::QuicStreamId stream_id,
                                                 int error) {
  RTC_DCHECK(worker_thread_->IsCurrent());
  LOG(LS_VERBOSE) << "Write blocked stream " << stream_id << " is closed.";
  write_blocked_quic_streams_.erase(stream_id);
}

void QuicDataChannel::OnIncomingQueuedStreamClosed(net::QuicStreamId stream_id,
                                                   int error) {
  RTC_DCHECK(network_thread_->IsCurrent());
  LOG(LS_VERBOSE) << "Incoming queued stream " << stream_id << " is closed.";
  incoming_quic_messages_.erase(stream_id);
}

void QuicDataChannel::OnConnectionClosed() {
  RTC_DCHECK(worker_thread_->IsCurrent());
  invoker_.AsyncInvoke<void>(RTC_FROM_HERE, signaling_thread_,
                             rtc::Bind(&QuicDataChannel::Close, this));
}

void QuicDataChannel::OnMessage_s(const DataBuffer& received_data) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (observer_) {
    observer_->OnMessage(received_data);
  }
}

void QuicDataChannel::SetState_s(DataState state) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (state_ == state || state_ == kClosed) {
    return;
  }
  if (state_ == kClosing && state != kClosed) {
    return;
  }
  LOG(LS_INFO) << "Setting state to " << state << " for QUIC data channel "
               << id_;
  state_ = state;
  if (observer_) {
    observer_->OnStateChange();
  }
}

void QuicDataChannel::OnBufferedAmountChange_s(uint64_t buffered_amount) {
  RTC_DCHECK(signaling_thread_->IsCurrent());
  if (observer_) {
    observer_->OnBufferedAmountChange(buffered_amount);
  }
}

size_t QuicDataChannel::GetNumWriteBlockedStreams() const {
  return write_blocked_quic_streams_.size();
}

size_t QuicDataChannel::GetNumIncomingStreams() const {
  return incoming_quic_messages_.size();
}

}  // namespace webrtc
