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