OLD | NEW |
---|---|
(Empty) | |
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 "webrtc/modules/rtp_rtcp/source/rtcp_packet/bye.h" | |
12 | |
13 #include "webrtc/base/checks.h" | |
14 #include "webrtc/base/logging.h" | |
15 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | |
16 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
åsapersson
2015/11/20 09:44:58
alphabetic order
danilchap
2015/11/20 11:03:21
Done.
| |
17 | |
18 using webrtc::RTCPUtility::RtcpCommonHeader; | |
19 | |
20 namespace webrtc { | |
21 namespace rtcp { | |
22 | |
23 // Bye packet (BYE) (RFC 3550). | |
24 // | |
25 // 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 | |
26 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
27 // |V=2|P| SC | PT=BYE=203 | length | | |
28 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
29 // | SSRC/CSRC | | |
30 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
31 // : ... : | |
32 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | |
33 // (opt) | length | reason for leaving ... | |
34 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
35 Bye::Bye() : sender_ssrc_(0) {} | |
36 | |
37 bool Bye::Parse(const RtcpCommonHeader& header, const uint8_t* payload) { | |
38 RTC_DCHECK(header.packet_type == kPacketType); | |
39 | |
40 const uint8_t src_count = header.count_or_format; | |
41 // Validate packet. | |
42 if (src_count == 0) { | |
43 LOG(LS_WARNING) << "Bye packet must contain SSRC."; | |
åsapersson
2015/11/20 09:44:58
I think a SC value of zero is valid.
danilchap
2015/11/20 11:03:21
Yes, "A count value of zero is valid, but useless.
| |
44 return false; | |
45 } | |
46 if (header.payload_size_bytes < 4u * src_count) { | |
47 LOG(LS_WARNING) | |
48 << "Packet is too small to contain CSRCs it promise to have."; | |
49 return false; | |
50 } | |
51 bool has_reason = (header.payload_size_bytes > 4u * src_count); | |
52 uint8_t reason_length; | |
åsapersson
2015/11/20 09:44:58
initialize to 0 and remove else?
danilchap
2015/11/20 11:03:21
Wasn't sure if logic 'assign to correct value as s
| |
53 if (has_reason) { | |
54 reason_length = payload[4u * src_count]; | |
55 if (header.payload_size_bytes - 4u * src_count < 1u + reason_length) { | |
56 LOG(LS_WARNING) << "Invalid reason length: " << reason_length; | |
57 return false; | |
58 } | |
59 } else { | |
60 reason_length = 0; | |
61 } | |
62 // Once sure packet is valid, copy values. | |
63 sender_ssrc_ = ByteReader<uint32_t>::ReadBigEndian(payload); | |
64 csrcs_.resize(src_count - 1); | |
65 for (size_t i = 1; i < src_count; ++i) | |
66 csrcs_[i - 1] = ByteReader<uint32_t>::ReadBigEndian(&payload[4 * i]); | |
67 | |
68 if (has_reason) { | |
69 reason_.assign(reinterpret_cast<const char*>(&payload[4u * src_count + 1]), | |
70 reason_length); | |
71 } else { | |
72 reason_.clear(); | |
73 } | |
74 | |
75 return true; | |
76 } | |
77 | |
78 bool Bye::Create(uint8_t* packet, | |
79 size_t* index, | |
80 size_t max_length, | |
81 RtcpPacket::PacketReadyCallback* callback) const { | |
82 while (*index + BlockLength() > max_length) { | |
83 if (!OnBufferFull(packet, index, callback)) | |
84 return false; | |
85 } | |
86 const size_t index_end = *index + BlockLength(); | |
87 RTC_DCHECK_EQ(0u, BlockLength() % 4u); | |
88 size_t size_in_32bits = (BlockLength() - kHeaderLength) / 4u; | |
åsapersson
2015/11/20 09:44:58
Can use HeaderLength() instead?
danilchap
2015/11/20 11:03:21
Done.
| |
89 | |
90 CreateHeader(1 + csrcs_.size(), kPacketType, size_in_32bits, packet, index); | |
91 // Store srcs of the leaving clients. | |
92 ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], sender_ssrc_); | |
93 *index += sizeof(uint32_t); | |
94 for (uint32_t csrc : csrcs_) { | |
95 ByteWriter<uint32_t>::WriteBigEndian(&packet[*index], csrc); | |
96 *index += sizeof(uint32_t); | |
97 } | |
98 // Store the reason to leave. | |
99 if (!reason_.empty()) { | |
100 uint8_t reason_length = reason_.size(); | |
101 packet[(*index)++] = reason_length; | |
102 memcpy(&packet[*index], reason_.data(), reason_length); | |
103 *index += reason_length; | |
104 // Add padding bytes if needed. | |
105 size_t bytes_to_pad = index_end - *index; | |
106 RTC_DCHECK_LE(bytes_to_pad, 3u); | |
107 if (bytes_to_pad > 0) { | |
108 memset(&packet[*index], 0, bytes_to_pad); | |
109 *index += bytes_to_pad; | |
110 } | |
111 } | |
112 RTC_DCHECK_EQ(index_end, *index); | |
113 return true; | |
114 } | |
115 | |
116 bool Bye::WithCsrc(uint32_t csrc) { | |
117 if (csrcs_.size() >= kMaxNumberOfCsrcs) { | |
118 LOG(LS_WARNING) << "Max CSRC size reached."; | |
119 return false; | |
120 } | |
121 csrcs_.push_back(csrc); | |
122 return true; | |
123 } | |
124 | |
125 bool Bye::WithReason(const std::string& reason) { | |
126 if (reason.size() > 0xff) { | |
åsapersson
2015/11/20 09:44:58
should we use RTC_DCHECK
danilchap
2015/11/20 11:03:21
Done.
| |
127 LOG(LS_WARNING) << "Reason length should be less than 256."; | |
128 return false; | |
129 } | |
130 reason_ = reason; | |
131 return true; | |
132 } | |
133 | |
134 size_t Bye::BlockLength() const { | |
135 size_t source_count = (1 + csrcs_.size()); | |
åsapersson
2015/11/20 09:44:58
maybe use same name for source count in Parse and
danilchap
2015/11/20 11:03:21
Done.
| |
136 size_t reason_size_in_32bits = reason_.empty() ? 0 : (reason_.size() / 4 + 1); | |
137 return kHeaderLength + 4 * (source_count + reason_size_in_32bits); | |
138 } | |
139 | |
140 } // namespace rtcp | |
141 } // namespace webrtc | |
OLD | NEW |