/*
 *  Copyright (c) 2015 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/bye.h"

#include <utility>

#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 Bye::kPacketType;
// Bye packet (BYE) (RFC 3550).
//
//        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|    SC   |   PT=BYE=203  |             length            |
//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//       |                           SSRC/CSRC                           |
//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//       :                              ...                              :
//       +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// (opt) |     length    |               reason for leaving            ...
//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Bye::Bye() : sender_ssrc_(0) {}

Bye::~Bye() = default;

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

  const uint8_t src_count = packet.count();
  // Validate packet.
  if (packet.payload_size_bytes() < 4u * src_count) {
    RTC_LOG(LS_WARNING)
        << "Packet is too small to contain CSRCs it promise to have.";
    return false;
  }
  const uint8_t* const payload = packet.payload();
  bool has_reason = packet.payload_size_bytes() > 4u * src_count;
  uint8_t reason_length = 0;
  if (has_reason) {
    reason_length = payload[4u * src_count];
    if (packet.payload_size_bytes() - 4u * src_count < 1u + reason_length) {
      RTC_LOG(LS_WARNING) << "Invalid reason length: " << reason_length;
      return false;
    }
  }
  // Once sure packet is valid, copy values.
  if (src_count == 0) {  // A count value of zero is valid, but useless.
    sender_ssrc_ = 0;
    csrcs_.clear();
  } else {
    sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload);
    csrcs_.resize(src_count - 1);
    for (size_t i = 1; i < src_count; ++i)
      csrcs_[i - 1] = ByteReader<uint32_t>::ReadBigEndian(&payload[4 * i]);
  }

  if (has_reason) {
    reason_.assign(reinterpret_cast<const char*>(&payload[4u * src_count + 1]),
                   reason_length);
  } else {
    reason_.clear();
  }

  return true;
}

bool Bye::Create(uint8_t* packet,
                 size_t* index,
                 size_t max_length,
                 RtcpPacket::PacketReadyCallback* callback) const {
  while (*index + BlockLength() > max_length) {
    if (!OnBufferFull(packet, index, callback))
      return false;
  }
  const size_t index_end = *index + BlockLength();

  CreateHeader(1 + csrcs_.size(), kPacketType, HeaderLength(), packet, index);
  // Store srcs of the leaving clients.
  ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], sender_ssrc_);
  *index += sizeof(uint32_t);
  for (uint32_t csrc : csrcs_) {
    ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], csrc);
    *index += sizeof(uint32_t);
  }
  // Store the reason to leave.
  if (!reason_.empty()) {
    uint8_t reason_length = static_cast<uint8_t>(reason_.size());
    packet[(*index)++] = reason_length;
    memcpy(&packet[*index], reason_.data(), reason_length);
    *index += reason_length;
    // Add padding bytes if needed.
    size_t bytes_to_pad = index_end - *index;
    RTC_DCHECK_LE(bytes_to_pad, 3);
    if (bytes_to_pad > 0) {
      memset(&packet[*index], 0, bytes_to_pad);
      *index += bytes_to_pad;
    }
  }
  RTC_DCHECK_EQ(index_end, *index);
  return true;
}

bool Bye::SetCsrcs(std::vector<uint32_t> csrcs) {
  if (csrcs.size() > kMaxNumberOfCsrcs) {
    RTC_LOG(LS_WARNING) << "Too many CSRCs for Bye packet.";
    return false;
  }
  csrcs_ = std::move(csrcs);
  return true;
}

void Bye::SetReason(std::string reason) {
  RTC_DCHECK_LE(reason.size(), 0xffu);
  reason_ = std::move(reason);
}

size_t Bye::BlockLength() const {
  size_t src_count = (1 + csrcs_.size());
  size_t reason_size_in_32bits = reason_.empty() ? 0 : (reason_.size() / 4 + 1);
  return kHeaderLength + 4 * (src_count + reason_size_in_32bits);
}

}  // namespace rtcp
}  // namespace webrtc
