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/bye.h"
12
13 #include <string.h>
14
15 #include <cstdint>
16 #include <utility>
17
18 #include "modules/rtp_rtcp/source/byte_io.h"
19 #include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/logging.h"
22
23 namespace webrtc {
24 namespace rtcp {
25 constexpr uint8_t Bye::kPacketType;
26 // Bye packet (BYE) (RFC 3550).
27 //
28 // 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
29 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
30 // |V=2|P| SC | PT=BYE=203 | length |
31 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 // | SSRC/CSRC |
33 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 // : ... :
35 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
36 // (opt) | length | reason for leaving ...
37 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 Bye::Bye() = default;
39
40 Bye::~Bye() = default;
41
Parse(const CommonHeader & packet)42 bool Bye::Parse(const CommonHeader& packet) {
43 RTC_DCHECK_EQ(packet.type(), kPacketType);
44
45 const uint8_t src_count = packet.count();
46 // Validate packet.
47 if (packet.payload_size_bytes() < 4u * src_count) {
48 RTC_LOG(LS_WARNING)
49 << "Packet is too small to contain CSRCs it promise to have.";
50 return false;
51 }
52 const uint8_t* const payload = packet.payload();
53 bool has_reason = packet.payload_size_bytes() > 4u * src_count;
54 uint8_t reason_length = 0;
55 if (has_reason) {
56 reason_length = payload[4u * src_count];
57 if (packet.payload_size_bytes() - 4u * src_count < 1u + reason_length) {
58 RTC_LOG(LS_WARNING) << "Invalid reason length: " << reason_length;
59 return false;
60 }
61 }
62 // Once sure packet is valid, copy values.
63 if (src_count == 0) { // A count value of zero is valid, but useless.
64 SetSenderSsrc(0);
65 csrcs_.clear();
66 } else {
67 SetSenderSsrc(ByteReader<uint32_t>::ReadBigEndian(payload));
68 csrcs_.resize(src_count - 1);
69 for (size_t i = 1; i < src_count; ++i)
70 csrcs_[i - 1] = ByteReader<uint32_t>::ReadBigEndian(&payload[4 * i]);
71 }
72
73 if (has_reason) {
74 reason_.assign(reinterpret_cast<const char*>(&payload[4u * src_count + 1]),
75 reason_length);
76 } else {
77 reason_.clear();
78 }
79
80 return true;
81 }
82
Create(uint8_t * packet,size_t * index,size_t max_length,PacketReadyCallback callback) const83 bool Bye::Create(uint8_t* packet,
84 size_t* index,
85 size_t max_length,
86 PacketReadyCallback callback) const {
87 while (*index + BlockLength() > max_length) {
88 if (!OnBufferFull(packet, index, callback))
89 return false;
90 }
91 const size_t index_end = *index + BlockLength();
92
93 CreateHeader(1 + csrcs_.size(), kPacketType, HeaderLength(), packet, index);
94 // Store srcs of the leaving clients.
95 ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], sender_ssrc());
96 *index += sizeof(uint32_t);
97 for (uint32_t csrc : csrcs_) {
98 ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], csrc);
99 *index += sizeof(uint32_t);
100 }
101 // Store the reason to leave.
102 if (!reason_.empty()) {
103 uint8_t reason_length = static_cast<uint8_t>(reason_.size());
104 packet[(*index)++] = reason_length;
105 memcpy(&packet[*index], reason_.data(), reason_length);
106 *index += reason_length;
107 // Add padding bytes if needed.
108 size_t bytes_to_pad = index_end - *index;
109 RTC_DCHECK_LE(bytes_to_pad, 3);
110 if (bytes_to_pad > 0) {
111 memset(&packet[*index], 0, bytes_to_pad);
112 *index += bytes_to_pad;
113 }
114 }
115 RTC_DCHECK_EQ(index_end, *index);
116 return true;
117 }
118
SetCsrcs(std::vector<uint32_t> csrcs)119 bool Bye::SetCsrcs(std::vector<uint32_t> csrcs) {
120 if (csrcs.size() > kMaxNumberOfCsrcs) {
121 RTC_LOG(LS_WARNING) << "Too many CSRCs for Bye packet.";
122 return false;
123 }
124 csrcs_ = std::move(csrcs);
125 return true;
126 }
127
SetReason(std::string reason)128 void Bye::SetReason(std::string reason) {
129 RTC_DCHECK_LE(reason.size(), 0xffu);
130 reason_ = std::move(reason);
131 }
132
BlockLength() const133 size_t Bye::BlockLength() const {
134 size_t src_count = (1 + csrcs_.size());
135 size_t reason_size_in_32bits = reason_.empty() ? 0 : (reason_.size() / 4 + 1);
136 return kHeaderLength + 4 * (src_count + reason_size_in_32bits);
137 }
138
139 } // namespace rtcp
140 } // namespace webrtc
141