• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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