1 /*
2  *  Copyright (c) 2016 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/sender_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 SenderReport::kPacketType;
23 constexpr size_t SenderReport::kMaxNumberOfReportBlocks;
24 constexpr size_t SenderReport::kSenderBaseLength;
25 //    Sender report (SR) (RFC 3550).
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=SR=200   |             length            |
30 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 //  0 |                         SSRC of sender                        |
32 //    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
33 //  4 |              NTP timestamp, most significant word             |
34 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 //  8 |             NTP timestamp, least significant word             |
36 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 // 12 |                         RTP timestamp                         |
38 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 // 16 |                     sender's packet count                     |
40 //    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 // 20 |                      sender's octet count                     |
42 // 24 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
43 
SenderReport()44 SenderReport::SenderReport()
45     : rtp_timestamp_(0), sender_packet_count_(0), sender_octet_count_(0) {}
46 
47 SenderReport::SenderReport(const SenderReport&) = default;
48 SenderReport::SenderReport(SenderReport&&) = default;
49 SenderReport& SenderReport::operator=(const SenderReport&) = default;
50 SenderReport& SenderReport::operator=(SenderReport&&) = default;
51 SenderReport::~SenderReport() = default;
52 
Parse(const CommonHeader & packet)53 bool SenderReport::Parse(const CommonHeader& packet) {
54   RTC_DCHECK_EQ(packet.type(), kPacketType);
55 
56   const uint8_t report_block_count = packet.count();
57   if (packet.payload_size_bytes() <
58       kSenderBaseLength + report_block_count * ReportBlock::kLength) {
59     RTC_LOG(LS_WARNING) << "Packet is too small to contain all the data.";
60     return false;
61   }
62   // Read SenderReport header.
63   const uint8_t* const payload = packet.payload();
64   SetSenderSsrc(ByteReader<uint32_t>::ReadBigEndian(&payload[0]));
65   uint32_t secs = ByteReader<uint32_t>::ReadBigEndian(&payload[4]);
66   uint32_t frac = ByteReader<uint32_t>::ReadBigEndian(&payload[8]);
67   ntp_.Set(secs, frac);
68   rtp_timestamp_ = ByteReader<uint32_t>::ReadBigEndian(&payload[12]);
69   sender_packet_count_ = ByteReader<uint32_t>::ReadBigEndian(&payload[16]);
70   sender_octet_count_ = ByteReader<uint32_t>::ReadBigEndian(&payload[20]);
71   report_blocks_.resize(report_block_count);
72   const uint8_t* next_block = payload + kSenderBaseLength;
73   for (ReportBlock& block : report_blocks_) {
74     bool block_parsed = block.Parse(next_block, ReportBlock::kLength);
75     RTC_DCHECK(block_parsed);
76     next_block += ReportBlock::kLength;
77   }
78   // Double check we didn't read beyond provided buffer.
79   RTC_DCHECK_LE(next_block - payload,
80                 static_cast<ptrdiff_t>(packet.payload_size_bytes()));
81   return true;
82 }
83 
BlockLength() const84 size_t SenderReport::BlockLength() const {
85   return kHeaderLength + kSenderBaseLength +
86          report_blocks_.size() * ReportBlock::kLength;
87 }
88 
Create(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback callback) const89 bool SenderReport::Create(uint8_t* packet,
90                           size_t* index,
91                           size_t max_length,
92                           PacketReadyCallback callback) const {
93   while (*index + BlockLength() > max_length) {
94     if (!OnBufferFull(packet, index, callback))
95       return false;
96   }
97   const size_t index_end = *index + BlockLength();
98 
99   CreateHeader(report_blocks_.size(), kPacketType, HeaderLength(), packet,
100                index);
101   // Write SenderReport header.
102   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 0], sender_ssrc());
103   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 4], ntp_.seconds());
104   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 8], ntp_.fractions());
105   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 12], rtp_timestamp_);
106   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 16],
107                                        sender_packet_count_);
108   ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 20],
109                                        sender_octet_count_);
110   *index += kSenderBaseLength;
111   // Write report blocks.
112   for (const ReportBlock& block : report_blocks_) {
113     block.Create(packet + *index);
114     *index += ReportBlock::kLength;
115   }
116   // Ensure bytes written match expected.
117   RTC_DCHECK_EQ(*index, index_end);
118   return true;
119 }
120 
AddReportBlock(const ReportBlock & block)121 bool SenderReport::AddReportBlock(const ReportBlock& block) {
122   if (report_blocks_.size() >= kMaxNumberOfReportBlocks) {
123     RTC_LOG(LS_WARNING) << "Max report blocks reached.";
124     return false;
125   }
126   report_blocks_.push_back(block);
127   return true;
128 }
129 
SetReportBlocks(std::vector<ReportBlock> blocks)130 bool SenderReport::SetReportBlocks(std::vector<ReportBlock> blocks) {
131   if (blocks.size() > kMaxNumberOfReportBlocks) {
132     RTC_LOG(LS_WARNING) << "Too many report blocks (" << blocks.size()
133                         << ") for sender report.";
134     return false;
135   }
136   report_blocks_ = std::move(blocks);
137   return true;
138 }
139 
140 }  // namespace rtcp
141 }  // namespace webrtc
142