// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/cast/net/cast_transport_impl.h"

#include <stddef.h>

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "media/cast/net/cast_transport_defines.h"
#include "media/cast/net/rtcp/sender_rtcp_session.h"
#include "media/cast/net/transport_util.h"
#include "net/base/net_errors.h"

using media::cast::transport_util::kOptionPacerMaxBurstSize;
using media::cast::transport_util::kOptionPacerTargetBurstSize;
using media::cast::transport_util::LookupOptionWithDefault;

namespace media {
namespace cast {

namespace {

// Wifi options.
const char kOptionWifiDisableScan[] = "disable_wifi_scan";
const char kOptionWifiMediaStreamingMode[] = "media_streaming_mode";

}  // namespace

std::unique_ptr<CastTransport> CastTransport::Create(
    const base::TickClock* clock,  // Owned by the caller.
    base::TimeDelta logging_flush_interval,
    std::unique_ptr<Client> client,
    std::unique_ptr<PacketTransport> transport,
    const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner) {
  return std::unique_ptr<CastTransport>(
      new CastTransportImpl(clock, logging_flush_interval, std::move(client),
                            std::move(transport), transport_task_runner.get()));
}

PacketReceiverCallback CastTransport::PacketReceiverForTesting() {
  return base::NullCallback();
}

class CastTransportImpl::RtcpClient : public RtcpObserver {
 public:
  RtcpClient(std::unique_ptr<RtcpObserver> observer,
             uint32_t rtp_sender_ssrc,
             EventMediaType media_type,
             CastTransportImpl* cast_transport_impl)
      : rtp_sender_ssrc_(rtp_sender_ssrc),
        rtcp_observer_(std::move(observer)),
        media_type_(media_type),
        cast_transport_impl_(cast_transport_impl) {}

  void OnReceivedCastMessage(const RtcpCastMessage& cast_message) override {
    rtcp_observer_->OnReceivedCastMessage(cast_message);
    cast_transport_impl_->OnReceivedCastMessage(rtp_sender_ssrc_, cast_message);
  }

  void OnReceivedRtt(base::TimeDelta round_trip_time) override {
    rtcp_observer_->OnReceivedRtt(round_trip_time);
  }

  void OnReceivedReceiverLog(const RtcpReceiverLogMessage& log) override {
    cast_transport_impl_->OnReceivedLogMessage(media_type_, log);
  }

  void OnReceivedPli() override { rtcp_observer_->OnReceivedPli(); }

 private:
  const uint32_t rtp_sender_ssrc_;
  const std::unique_ptr<RtcpObserver> rtcp_observer_;
  const EventMediaType media_type_;
  CastTransportImpl* const cast_transport_impl_;

  DISALLOW_COPY_AND_ASSIGN(RtcpClient);
};

struct CastTransportImpl::RtpStreamSession {
  explicit RtpStreamSession(bool is_audio_stream) : is_audio(is_audio_stream) {}

  // Packetizer for audio and video frames.
  std::unique_ptr<RtpSender> rtp_sender;

  // Maintains RTCP session for audio and video.
  std::unique_ptr<SenderRtcpSession> rtcp_session;

  // RTCP observer for SenderRtcpSession.
  std::unique_ptr<RtcpObserver> rtcp_observer;

  // Encrypts data in EncodedFrames before they are sent.  Note that it's
  // important for the encryption to happen here, in code that would execute in
  // the main browser process, for security reasons.  This helps to mitigate
  // the damage that could be caused by a compromised renderer process.
  TransportEncryptionHandler encryptor;

  const bool is_audio;
};

CastTransportImpl::CastTransportImpl(
    const base::TickClock* clock,
    base::TimeDelta logging_flush_interval,
    std::unique_ptr<Client> client,
    std::unique_ptr<PacketTransport> transport,
    const scoped_refptr<base::SingleThreadTaskRunner>& transport_task_runner)
    : clock_(clock),
      logging_flush_interval_(logging_flush_interval),
      transport_client_(std::move(client)),
      transport_(std::move(transport)),
      transport_task_runner_(transport_task_runner),
      pacer_(kTargetBurstSize,
             kMaxBurstSize,
             clock,
             logging_flush_interval > base::TimeDelta() ? &recent_packet_events_
                                                        : nullptr,
             transport_.get(),
             transport_task_runner),
      last_byte_acked_for_audio_(0) {
  DCHECK(clock);
  DCHECK(transport_client_);
  DCHECK(transport_);
  DCHECK(transport_task_runner_);
  if (logging_flush_interval_ > base::TimeDelta()) {
    transport_task_runner_->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&CastTransportImpl::SendRawEvents,
                       weak_factory_.GetWeakPtr()),
        logging_flush_interval_);
  }
  transport_->StartReceiving(base::BindRepeating(
      &CastTransportImpl::OnReceivedPacket, base::Unretained(this)));
}

CastTransportImpl::~CastTransportImpl() {
  transport_->StopReceiving();
}

void CastTransportImpl::InitializeStream(
    const CastTransportRtpConfig& config,
    std::unique_ptr<RtcpObserver> rtcp_observer) {
  if (sessions_.find(config.ssrc) != sessions_.end())
    DVLOG(1) << "Initialize an existing stream on RTP sender." << config.ssrc;

  LOG_IF(WARNING, config.aes_key.empty() || config.aes_iv_mask.empty())
      << "Unsafe to send stream with encryption DISABLED.";

  bool is_audio = config.rtp_payload_type <= RtpPayloadType::AUDIO_LAST;
  std::unique_ptr<RtpStreamSession> session(new RtpStreamSession(is_audio));

  if (!session->encryptor.Initialize(config.aes_key, config.aes_iv_mask)) {
    transport_client_->OnStatusChanged(TRANSPORT_STREAM_UNINITIALIZED);
    return;
  }

  session->rtp_sender =
      std::make_unique<RtpSender>(transport_task_runner_, &pacer_);
  if (!session->rtp_sender->Initialize(config)) {
    session->rtp_sender.reset();
    transport_client_->OnStatusChanged(TRANSPORT_STREAM_UNINITIALIZED);
    return;
  }

  pacer_.RegisterSsrc(config.ssrc, is_audio);
  // Audio packets have a higher priority.
  if (is_audio)
    pacer_.RegisterPrioritySsrc(config.ssrc);

  session->rtcp_observer =
      std::make_unique<RtcpClient>(std::move(rtcp_observer), config.ssrc,
                                   is_audio ? AUDIO_EVENT : VIDEO_EVENT, this);
  session->rtcp_session = std::make_unique<SenderRtcpSession>(
      clock_, &pacer_, session->rtcp_observer.get(), config.ssrc,
      config.feedback_ssrc);

  valid_sender_ssrcs_.insert(config.feedback_ssrc);
  sessions_[config.ssrc] = std::move(session);
  transport_client_->OnStatusChanged(TRANSPORT_STREAM_INITIALIZED);
}

namespace {
void EncryptAndSendFrame(const EncodedFrame& frame,
                         TransportEncryptionHandler* encryptor,
                         RtpSender* sender) {
  if (encryptor->is_activated()) {
    EncodedFrame encrypted_frame;
    frame.CopyMetadataTo(&encrypted_frame);
    if (encryptor->Encrypt(frame.frame_id, frame.data, &encrypted_frame.data)) {
      sender->SendFrame(encrypted_frame);
    } else {
      LOG(ERROR) << "Encryption failed.  Not sending frame with ID "
                 << frame.frame_id;
    }
  } else {
    sender->SendFrame(frame);
  }
}
}  // namespace

void CastTransportImpl::InsertFrame(uint32_t ssrc, const EncodedFrame& frame) {
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end()) {
    NOTREACHED() << "Invalid InsertFrame call.";
    return;
  }

  it->second->rtcp_session->WillSendFrame(frame.frame_id);
  EncryptAndSendFrame(frame, &it->second->encryptor,
                      it->second->rtp_sender.get());
}

void CastTransportImpl::SendSenderReport(
    uint32_t ssrc,
    base::TimeTicks current_time,
    RtpTimeTicks current_time_as_rtp_timestamp) {
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end()) {
    NOTREACHED() << "Invalid request for sending RTCP packet.";
    return;
  }

  it->second->rtcp_session->SendRtcpReport(
      current_time, current_time_as_rtp_timestamp,
      it->second->rtp_sender->send_packet_count(),
      it->second->rtp_sender->send_octet_count());
}

void CastTransportImpl::CancelSendingFrames(
    uint32_t ssrc,
    const std::vector<FrameId>& frame_ids) {
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end()) {
    NOTREACHED() << "Invalid request for cancel sending.";
    return;
  }

  it->second->rtp_sender->CancelSendingFrames(frame_ids);
}

void CastTransportImpl::ResendFrameForKickstart(uint32_t ssrc,
                                                FrameId frame_id) {
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end()) {
    NOTREACHED() << "Invalid request for kickstart.";
    return;
  }

  DCHECK(it->second->rtcp_session);
  it->second->rtp_sender->ResendFrameForKickstart(
      frame_id, it->second->rtcp_session->current_round_trip_time());
}

void CastTransportImpl::ResendPackets(
    uint32_t ssrc,
    const MissingFramesAndPacketsMap& missing_packets,
    bool cancel_rtx_if_not_in_list,
    const DedupInfo& dedup_info) {
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end()) {
    NOTREACHED() << "Invalid request for retransmission.";
    return;
  }

  it->second->rtp_sender->ResendPackets(missing_packets,
                                        cancel_rtx_if_not_in_list, dedup_info);
}

PacketReceiverCallback CastTransportImpl::PacketReceiverForTesting() {
  return base::BindRepeating(
      base::IgnoreResult(&CastTransportImpl::OnReceivedPacket),
      weak_factory_.GetWeakPtr());
}

void CastTransportImpl::SendRawEvents() {
  DCHECK(logging_flush_interval_ > base::TimeDelta());

  if (!recent_frame_events_.empty() || !recent_packet_events_.empty()) {
    std::unique_ptr<std::vector<FrameEvent>> frame_events(
        new std::vector<FrameEvent>());
    frame_events->swap(recent_frame_events_);
    std::unique_ptr<std::vector<PacketEvent>> packet_events(
        new std::vector<PacketEvent>());
    packet_events->swap(recent_packet_events_);
    transport_client_->OnLoggingEventsReceived(std::move(frame_events),
                                               std::move(packet_events));
  }

  transport_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&CastTransportImpl::SendRawEvents,
                     weak_factory_.GetWeakPtr()),
      logging_flush_interval_);
}

bool CastTransportImpl::OnReceivedPacket(std::unique_ptr<Packet> packet) {
  const uint8_t* const data = &packet->front();
  const size_t length = packet->size();
  uint32_t ssrc;
  if (IsRtcpPacket(data, length)) {
    ssrc = GetSsrcOfSender(data, length);
  } else if (!RtpParser::ParseSsrc(data, length, &ssrc)) {
    VLOG(1) << "Invalid RTP packet.";
    return false;
  }
  if (valid_sender_ssrcs_.find(ssrc) == valid_sender_ssrcs_.end()) {
    VLOG(1) << "Stale packet received.";
    return false;
  }

  for (const auto& session : sessions_) {
    if (session.second->rtcp_session->IncomingRtcpPacket(data, length))
      return true;
  }

  transport_client_->ProcessRtpPacket(std::move(packet));
  return true;
}

void CastTransportImpl::OnReceivedLogMessage(
    EventMediaType media_type,
    const RtcpReceiverLogMessage& log) {
  if (logging_flush_interval_ <= base::TimeDelta())
    return;

  // Add received log messages into our log system.
  for (const RtcpReceiverFrameLogMessage& frame_log_message : log) {
    for (const RtcpReceiverEventLogMessage& event_log_message :
         frame_log_message.event_log_messages_) {
      switch (event_log_message.type) {
        case PACKET_RECEIVED: {
          recent_packet_events_.push_back(PacketEvent());
          PacketEvent& receive_event = recent_packet_events_.back();
          receive_event.timestamp = event_log_message.event_timestamp;
          receive_event.type = event_log_message.type;
          receive_event.media_type = media_type;
          receive_event.rtp_timestamp = frame_log_message.rtp_timestamp_;
          receive_event.packet_id = event_log_message.packet_id;
          break;
        }
        case FRAME_ACK_SENT:
        case FRAME_DECODED:
        case FRAME_PLAYOUT: {
          recent_frame_events_.push_back(FrameEvent());
          FrameEvent& frame_event = recent_frame_events_.back();
          frame_event.timestamp = event_log_message.event_timestamp;
          frame_event.type = event_log_message.type;
          frame_event.media_type = media_type;
          frame_event.rtp_timestamp = frame_log_message.rtp_timestamp_;
          if (event_log_message.type == FRAME_PLAYOUT)
            frame_event.delay_delta = event_log_message.delay_delta;
          break;
        }
        default:
          VLOG(2) << "Received log message via RTCP that we did not expect: "
                  << event_log_message.type;
          break;
      }
    }
  }
}

void CastTransportImpl::OnReceivedCastMessage(
    uint32_t ssrc,
    const RtcpCastMessage& cast_message) {

  DedupInfo dedup_info;
  auto it = sessions_.find(ssrc);
  if (it == sessions_.end() || !it->second->rtp_sender)
    return;

  if (it->second->is_audio) {
    const int64_t acked_bytes = it->second->rtp_sender->GetLastByteSentForFrame(
        cast_message.ack_frame_id);
    last_byte_acked_for_audio_ =
        std::max(acked_bytes, last_byte_acked_for_audio_);
  } else {
    dedup_info.resend_interval =
        it->second->rtcp_session->current_round_trip_time();

    // Only use audio stream to dedup if there is one.
    if (last_byte_acked_for_audio_) {
      dedup_info.last_byte_acked_for_audio = last_byte_acked_for_audio_;
    }
  }

  if (!cast_message.missing_frames_and_packets.empty()) {
    VLOG(2) << "feedback_count: "
            << static_cast<uint32_t>(cast_message.feedback_count);
    // This call does two things.
    // 1. Specifies that retransmissions for packets not listed in the set are
    //    cancelled.
    // 2. Specifies a deduplication window. For video this would be the most
    //    recent RTT. For audio there is no deduplication.
    ResendPackets(ssrc, cast_message.missing_frames_and_packets, true,
                  dedup_info);
  }

  if (!cast_message.received_later_frames.empty()) {
    // Cancel resending frames that were received by the RTP receiver.
    CancelSendingFrames(ssrc, cast_message.received_later_frames);
  }
}

void CastTransportImpl::AddValidRtpReceiver(uint32_t rtp_sender_ssrc,
                                            uint32_t rtp_receiver_ssrc) {
  valid_sender_ssrcs_.insert(rtp_sender_ssrc);
  valid_rtp_receiver_ssrcs_.insert(rtp_receiver_ssrc);
}

void CastTransportImpl::SetOptions(const base::DictionaryValue& options) {
  // Set PacedSender options.
  int burst_size = LookupOptionWithDefault(options, kOptionPacerTargetBurstSize,
                                           media::cast::kTargetBurstSize);
  if (burst_size != media::cast::kTargetBurstSize)
    pacer_.SetTargetBurstSize(burst_size);
  burst_size = LookupOptionWithDefault(options, kOptionPacerMaxBurstSize,
                                       media::cast::kMaxBurstSize);
  if (burst_size != media::cast::kMaxBurstSize)
    pacer_.SetMaxBurstSize(burst_size);

  // Set Wifi options.
  int wifi_options = 0;
  if (options.HasKey(kOptionWifiDisableScan)) {
    wifi_options |= net::WIFI_OPTIONS_DISABLE_SCAN;
  }
  if (options.HasKey(kOptionWifiMediaStreamingMode)) {
    wifi_options |= net::WIFI_OPTIONS_MEDIA_STREAMING_MODE;
  }
  if (wifi_options)
    wifi_options_autoreset_ = net::SetWifiOptions(wifi_options);
}

void CastTransportImpl::InitializeRtpReceiverRtcpBuilder(
    uint32_t rtp_receiver_ssrc,
    const RtcpTimeData& time_data) {
  if (valid_rtp_receiver_ssrcs_.find(rtp_receiver_ssrc) ==
      valid_rtp_receiver_ssrcs_.end()) {
    VLOG(1) << "Invalid RTP receiver ssrc in "
            << "CastTransportImpl::InitializeRtpReceiverRtcpBuilder.";
    return;
  }
  if (rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "Re-initialize rtcp_builder_at_rtp_receiver_ in "
               "CastTransportImpl.";
    return;
  }
  rtcp_builder_at_rtp_receiver_ =
      std::make_unique<RtcpBuilder>(rtp_receiver_ssrc);
  rtcp_builder_at_rtp_receiver_->Start();
  RtcpReceiverReferenceTimeReport rrtr;
  rrtr.ntp_seconds = time_data.ntp_seconds;
  rrtr.ntp_fraction = time_data.ntp_fraction;
  rtcp_builder_at_rtp_receiver_->AddRrtr(rrtr);
}

void CastTransportImpl::AddCastFeedback(const RtcpCastMessage& cast_message,
                                        base::TimeDelta target_delay) {
  if (!rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "rtcp_builder_at_rtp_receiver_ is not initialized before "
               "calling CastTransportImpl::AddCastFeedback.";
    return;
  }
  rtcp_builder_at_rtp_receiver_->AddCast(cast_message, target_delay);
}

void CastTransportImpl::AddPli(const RtcpPliMessage& pli_message) {
  if (!rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "rtcp_builder_at_rtp_receiver_ is not initialized before "
               "calling CastTransportImpl::AddPli.";
    return;
  }
  rtcp_builder_at_rtp_receiver_->AddPli(pli_message);
}

void CastTransportImpl::AddRtcpEvents(
    const ReceiverRtcpEventSubscriber::RtcpEvents& rtcp_events) {
  if (!rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "rtcp_builder_at_rtp_receiver_ is not initialized before "
               "calling CastTransportImpl::AddRtcpEvents.";
    return;
  }
  rtcp_builder_at_rtp_receiver_->AddReceiverLog(rtcp_events);
}

void CastTransportImpl::AddRtpReceiverReport(
    const RtcpReportBlock& rtp_receiver_report_block) {
  if (!rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "rtcp_builder_at_rtp_receiver_ is not initialized before "
               "calling CastTransportImpl::AddRtpReceiverReport.";
    return;
  }
  rtcp_builder_at_rtp_receiver_->AddRR(&rtp_receiver_report_block);
}

void CastTransportImpl::SendRtcpFromRtpReceiver() {
  if (!rtcp_builder_at_rtp_receiver_) {
    VLOG(1) << "rtcp_builder_at_rtp_receiver_ is not initialized before "
               "calling CastTransportImpl::SendRtcpFromRtpReceiver.";
    return;
  }
  pacer_.SendRtcpPacket(rtcp_builder_at_rtp_receiver_->local_ssrc(),
                        rtcp_builder_at_rtp_receiver_->Finish());
  rtcp_builder_at_rtp_receiver_.reset();
}

}  // namespace cast
}  // namespace media
