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