/*
 *  Copyright (c) 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 "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"

#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace rtcp {
constexpr uint8_t ExtendedReports::kPacketType;
// From RFC 3611: RTP Control Protocol Extended Reports (RTCP XR).
//
// Format for XR packets:
//
//   0                   1                   2                   3
//   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  |V=2|P|reserved |   PT=XR=207   |             length            |
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  |                              SSRC                             |
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  :                         report blocks                         :
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//
// Extended report block:
//   0                   1                   2                   3
//   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  |  Block Type   |   reserved    |         block length          |
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//  :             type-specific block contents                      :
//  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ExtendedReports::ExtendedReports() : sender_ssrc_(0) {}
ExtendedReports::~ExtendedReports() {}

bool ExtendedReports::Parse(const CommonHeader& packet) {
  RTC_DCHECK_EQ(packet.type(), kPacketType);

  if (packet.payload_size_bytes() < kXrBaseLength) {
    RTC_LOG(LS_WARNING)
        << "Packet is too small to be an ExtendedReports packet.";
    return false;
  }

  sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(packet.payload());
  rrtr_block_.reset();
  dlrr_block_.ClearItems();
  voip_metric_block_.reset();
  target_bitrate_ = rtc::nullopt;

  const uint8_t* current_block = packet.payload() + kXrBaseLength;
  const uint8_t* const packet_end =
      packet.payload() + packet.payload_size_bytes();
  constexpr size_t kBlockHeaderSizeBytes = 4;
  while (current_block + kBlockHeaderSizeBytes <= packet_end) {
    uint8_t block_type = ByteReader<uint8_t>::ReadBigEndian(current_block);
    uint16_t block_length =
        ByteReader<uint16_t>::ReadBigEndian(current_block + 2);
    const uint8_t* next_block =
        current_block + kBlockHeaderSizeBytes + block_length * 4;
    if (next_block > packet_end) {
      RTC_LOG(LS_WARNING)
          << "Report block in extended report packet is too big.";
      return false;
    }
    switch (block_type) {
      case Rrtr::kBlockType:
        ParseRrtrBlock(current_block, block_length);
        break;
      case Dlrr::kBlockType:
        ParseDlrrBlock(current_block, block_length);
        break;
      case VoipMetric::kBlockType:
        ParseVoipMetricBlock(current_block, block_length);
        break;
      case TargetBitrate::kBlockType:
        ParseTargetBitrateBlock(current_block, block_length);
        break;
      default:
        // Unknown block, ignore.
        RTC_LOG(LS_WARNING)
            << "Unknown extended report block type " << block_type;
        break;
    }
    current_block = next_block;
  }

  return true;
}

void ExtendedReports::SetRrtr(const Rrtr& rrtr) {
  if (rrtr_block_)
    RTC_LOG(LS_WARNING) << "Rrtr already set, overwriting.";
  rrtr_block_.emplace(rrtr);
}

void ExtendedReports::AddDlrrItem(const ReceiveTimeInfo& time_info) {
  dlrr_block_.AddDlrrItem(time_info);
}

void ExtendedReports::SetVoipMetric(const VoipMetric& voip_metric) {
  if (voip_metric_block_)
    RTC_LOG(LS_WARNING) << "Voip metric already set, overwriting.";
  voip_metric_block_.emplace(voip_metric);
}

void ExtendedReports::SetTargetBitrate(const TargetBitrate& bitrate) {
  if (target_bitrate_)
    RTC_LOG(LS_WARNING) << "TargetBitrate already set, overwriting.";

  target_bitrate_ = bitrate;
}

size_t ExtendedReports::BlockLength() const {
  return kHeaderLength + kXrBaseLength + RrtrLength() + DlrrLength() +
         VoipMetricLength() + TargetBitrateLength();
}

bool ExtendedReports::Create(uint8_t* packet,
                             size_t* index,
                             size_t max_length,
                             PacketReadyCallback callback) const {
  while (*index + BlockLength() > max_length) {
    if (!OnBufferFull(packet, index, callback))
      return false;
  }
  size_t index_end = *index + BlockLength();
  const uint8_t kReserved = 0;
  CreateHeader(kReserved, kPacketType, HeaderLength(), packet, index);
  ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc_);
  *index += sizeof(uint32_t);
  if (rrtr_block_) {
    rrtr_block_->Create(packet + *index);
    *index += Rrtr::kLength;
  }
  if (dlrr_block_) {
    dlrr_block_.Create(packet + *index);
    *index += dlrr_block_.BlockLength();
  }
  if (voip_metric_block_) {
    voip_metric_block_->Create(packet + *index);
    *index += VoipMetric::kLength;
  }
  if (target_bitrate_) {
    target_bitrate_->Create(packet + *index);
    *index += target_bitrate_->BlockLength();
  }
  RTC_CHECK_EQ(*index, index_end);
  return true;
}

size_t ExtendedReports::TargetBitrateLength() const {
  if (target_bitrate_)
    return target_bitrate_->BlockLength();
  return 0;
}

void ExtendedReports::ParseRrtrBlock(const uint8_t* block,
                                     uint16_t block_length) {
  if (block_length != Rrtr::kBlockLength) {
    RTC_LOG(LS_WARNING) << "Incorrect rrtr block size " << block_length
                        << " Should be " << Rrtr::kBlockLength;
    return;
  }
  if (rrtr_block_) {
    RTC_LOG(LS_WARNING)
        << "Two rrtr blocks found in same Extended Report packet";
    return;
  }
  rrtr_block_.emplace();
  rrtr_block_->Parse(block);
}

void ExtendedReports::ParseDlrrBlock(const uint8_t* block,
                                     uint16_t block_length) {
  if (dlrr_block_) {
    RTC_LOG(LS_WARNING)
        << "Two Dlrr blocks found in same Extended Report packet";
    return;
  }
  dlrr_block_.Parse(block, block_length);
}

void ExtendedReports::ParseVoipMetricBlock(const uint8_t* block,
                                           uint16_t block_length) {
  if (block_length != VoipMetric::kBlockLength) {
    RTC_LOG(LS_WARNING) << "Incorrect voip metric block size " << block_length
                        << " Should be " << VoipMetric::kBlockLength;
    return;
  }
  if (voip_metric_block_) {
    RTC_LOG(LS_WARNING)
        << "Two Voip Metric blocks found in same Extended Report packet";
    return;
  }
  voip_metric_block_.emplace();
  voip_metric_block_->Parse(block);
}

void ExtendedReports::ParseTargetBitrateBlock(const uint8_t* block,
                                              uint16_t block_length) {
  target_bitrate_.emplace();
  target_bitrate_->Parse(block, block_length);
}
}  // namespace rtcp
}  // namespace webrtc
