1 /*
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
12
13 #include <utility>
14
15 #include "modules/rtp_rtcp/source/byte_io.h"
16 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/logging.h"
19
20 namespace webrtc {
21 namespace rtcp {
22 constexpr uint8_t ReceiverReport::kPacketType;
23 constexpr size_t ReceiverReport::kMaxNumberOfReportBlocks;
24 // RTCP receiver report (RFC 3550).
25 //
26 // 0 1 2 3
27 // 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
28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29 // |V=2|P| RC | PT=RR=201 | length |
30 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 // | SSRC of packet sender |
32 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
33 // | report block(s) |
34 // | .... |
35
36 ReceiverReport::ReceiverReport() = default;
37
38 ReceiverReport::ReceiverReport(const ReceiverReport& rhs) = default;
39
40 ReceiverReport::~ReceiverReport() = default;
41
Parse(const CommonHeader & packet)42 bool ReceiverReport::Parse(const CommonHeader& packet) {
43 RTC_DCHECK_EQ(packet.type(), kPacketType);
44
45 const uint8_t report_blocks_count = packet.count();
46
47 if (packet.payload_size_bytes() <
48 kRrBaseLength + report_blocks_count * ReportBlock::kLength) {
49 RTC_LOG(LS_WARNING) << "Packet is too small to contain all the data.";
50 return false;
51 }
52
53 SetSenderSsrc(ByteReader<uint32_t>::ReadBigEndian(packet.payload()));
54
55 const uint8_t* next_report_block = packet.payload() + kRrBaseLength;
56
57 report_blocks_.resize(report_blocks_count);
58 for (ReportBlock& block : report_blocks_) {
59 block.Parse(next_report_block, ReportBlock::kLength);
60 next_report_block += ReportBlock::kLength;
61 }
62
63 RTC_DCHECK_LE(next_report_block - packet.payload(),
64 static_cast<ptrdiff_t>(packet.payload_size_bytes()));
65 return true;
66 }
67
BlockLength() const68 size_t ReceiverReport::BlockLength() const {
69 return kHeaderLength + kRrBaseLength +
70 report_blocks_.size() * ReportBlock::kLength;
71 }
72
Create(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback callback) const73 bool ReceiverReport::Create(uint8_t* packet,
74 size_t* index,
75 size_t max_length,
76 PacketReadyCallback callback) const {
77 while (*index + BlockLength() > max_length) {
78 if (!OnBufferFull(packet, index, callback))
79 return false;
80 }
81 CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
82 index);
83 ByteWriter<uint32_t>::WriteBigEndian(packet + *index, sender_ssrc());
84 *index += kRrBaseLength;
85 for (const ReportBlock& block : report_blocks_) {
86 block.Create(packet + *index);
87 *index += ReportBlock::kLength;
88 }
89 return true;
90 }
91
AddReportBlock(const ReportBlock & block)92 bool ReceiverReport::AddReportBlock(const ReportBlock& block) {
93 if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
94 RTC_LOG(LS_WARNING) << "Max report blocks reached.";
95 return false;
96 }
97 report_blocks_.push_back(block);
98 return true;
99 }
100
SetReportBlocks(std::vector<ReportBlock> blocks)101 bool ReceiverReport::SetReportBlocks(std::vector<ReportBlock> blocks) {
102 if (blocks.size() > kMaxNumberOfReportBlocks) {
103 RTC_LOG(LS_WARNING) << "Too many report blocks (" << blocks.size()
104 << ") for receiver report.";
105 return false;
106 }
107 report_blocks_ = std::move(blocks);
108 return true;
109 }
110
111 } // namespace rtcp
112 } // namespace webrtc
113