/*
 *  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;
constexpr size_t ExtendedReports::kMaxNumberOfDlrrItems;
// 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();
  target_bitrate_ = absl::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 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);
}

bool ExtendedReports::AddDlrrItem(const ReceiveTimeInfo& time_info) {
  if (dlrr_block_.sub_blocks().size() >= kMaxNumberOfDlrrItems) {
    RTC_LOG(LS_WARNING) << "Reached maximum number of DLRR items.";
    return false;
  }
  dlrr_block_.AddDlrrItem(time_info);
  return true;
}

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() +
         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 (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::ParseTargetBitrateBlock(const uint8_t* block,
                                              uint16_t block_length) {
  target_bitrate_.emplace();
  target_bitrate_->Parse(block, block_length);
}
}  // namespace rtcp
}  // namespace webrtc
