Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(234)

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.cc

Issue 1439553003: [rtp_rtcp] rtcp::Sdes cleaned and got Parse function (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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/sdes.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"
17
18 using webrtc::RTCPUtility::RtcpCommonHeader;
19
20 namespace webrtc {
21 namespace rtcp {
22
23 // Source Description (SDES) (RFC 3550).
24 //
25 // 0 1 2 3
26 // 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
27 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28 // header |V=2|P| SC | PT=SDES=202 | length |
29 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
30 // chunk | SSRC/CSRC_1 |
31 // 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 // | SDES items |
33 // | ... |
34 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
35 // chunk | SSRC/CSRC_2 |
36 // 2 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 // | SDES items |
38 // | ... |
39 // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
40 //
41 // Canonical End-Point Identifier SDES Item (CNAME)
42 //
43 // 0 1 2 3
44 // 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
45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 // | CNAME=1 | length | user and domain name ...
47 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 bool Sdes::Parse(const RtcpCommonHeader& header, const uint8_t* payload) {
49 RTC_DCHECK(header.packet_type == kPacketType);
50
51 const uint8_t chunk_count = header.count_or_format;
52 std::vector<Chunk> chunks; // Read chunk into temporary array, so that in
53 // case of an error original array would stay
54 // unchanged.
sprang_webrtc 2015/11/12 15:27:15 This will only be a problem if we try to reuse an
danilchap 2015/11/12 16:59:09 If packet is partially parsed, it means it is dama
sprang_webrtc 2015/11/16 09:50:34 Fair enough.
55
56 RTC_DCHECK_EQ(0u, header.payload_size_bytes % 4u);
57 const uint8_t* const payload_end = payload + header.payload_size_bytes;
58 const uint8_t* next_chunk = payload;
sprang_webrtc 2015/11/12 15:27:15 Don't like the name next_chunk, since it doesn't n
danilchap 2015/11/12 16:59:09 Agree, can't keep it stay at a chunk since it also
59 chunks.resize(chunk_count);
60 for (size_t i = 0; i < chunk_count; ++i) {
61 // Each chunk consumes at least 8 bytes.
62 if (payload_end - next_chunk < 8) {
63 LOG(LS_WARNING) << "Not enough space left for chunk #" << (i + 1);
64 return false;
65 }
66 chunks[i].ssrc = ByteReader<uint32_t>::ReadBigEndian(next_chunk);
67 next_chunk += sizeof(uint32_t);
68 bool cname_found = false;
69
70 const uint8_t kTerminateId = 0;
71 const uint8_t kCnameId = 1;
72 uint8_t item_type;
73 while ((item_type = *(next_chunk++)) != kTerminateId) {
74 if (next_chunk >= payload_end) {
75 LOG(LS_WARNING) << "Unexpected end of packet while reading chunk #"
76 << (i + 1) << ". Expected to find size of the text.";
77 return false;
78 }
79 uint8_t size = *(next_chunk++);
80 if (next_chunk + size + 1 > payload_end) {
81 LOG(LS_WARNING) << "Unexpected end of packet while reading chunk #"
82 << (i + 1) << ". Expected to find text of size "
83 << size;
84 return false;
85 }
86 if (item_type == kCnameId) {
87 if (cname_found) {
88 LOG(LS_WARNING) << "Found extra CNAME for same ssrc in chunk #"
89 << (i + 1);
90 return false;
91 }
92 cname_found = true;
93 chunks[i].name.assign(reinterpret_cast<const char*>(next_chunk), size);
94 }
95 next_chunk += size;
96 }
97 if (!cname_found) {
98 LOG(LS_WARNING) << "CNAME not found for chunk #" << (i + 1);
99 return false;
100 }
101 // Adjust to 32bit boundary.
102 next_chunk += (payload_end - next_chunk) % 4;
103 }
104
105 chunks_.swap(chunks);
106 return true;
107 }
108
109 bool Sdes::WithCName(uint32_t ssrc, const std::string& cname) {
110 RTC_DCHECK(cname.length() <= 0xff);
111 if (chunks_.size() >= kMaxNumberOfChunks) {
112 LOG(LS_WARNING) << "Max SDES chunks reached.";
113 return false;
114 }
115 Chunk chunk;
116 chunk.ssrc = ssrc;
117 chunk.name = cname;
118 chunks_.push_back(chunk);
119 return true;
120 }
121
122 bool Sdes::Create(uint8_t* packet,
123 size_t* index,
124 size_t max_length,
125 RtcpPacket::PacketReadyCallback* callback) const {
126 RTC_DCHECK(!chunks_.empty());
127 while (*index + BlockLength() > max_length) {
128 if (!OnBufferFull(packet, index, callback))
129 return false;
130 }
131 const size_t index_end = *index + BlockLength();
132 CreateHeader(chunks_.size(), kPacketType, HeaderLength(), packet, index);
133
134 const uint8_t kCnameId = 1;
135 for (const Sdes::Chunk& chunk : chunks_) {
136 ByteWriter<uint32_t>::WriteBigEndian(&packet[*index + 0], chunk.ssrc);
137 ByteWriter<uint8_t>::WriteBigEndian(&packet[*index + 4], kCnameId);
138 ByteWriter<uint8_t>::WriteBigEndian(&packet[*index + 5], chunk.name.size());
139 memcpy(&packet[*index + 6], chunk.name.data(), chunk.name.size());
140 *index += (6 + chunk.name.size());
141
142 // In each chunk, the list of items must be terminated by one or more null
143 // octets. The next chunk must start on a 32-bit boundary.
144 // CNAME (1 byte) | length (1 byte) | name | padding.
145 size_t padding_size = 4 - ((6 + chunk.name.size()) % 4);
146 memset(packet + *index, 0, padding_size);
147 *index += padding_size;
148 }
149
150 RTC_DCHECK_EQ(index_end, *index);
151 return true;
152 }
153
154 size_t Sdes::BlockLength() const {
155 // Header (4 bytes).
156 // Chunk:
157 // SSRC/CSRC (4 bytes) | CNAME (1 byte) | length (1 byte) | name | padding.
158 size_t length = kHeaderLength;
159 for (const Chunk& chunk : chunks_) {
160 size_t padding_size = 4 - ((6 + chunk.name.size()) % 4);
161 length += 6 + chunk.name.size() + padding_size;
162 }
163 RTC_DCHECK_EQ(0u, length % 4);
164 return length;
sprang_webrtc 2015/11/12 15:27:15 Should we perhaps store this as a member instead,
danilchap 2015/11/12 16:59:09 Agree, calculation of the length is not trivial bu
165 }
166
167 } // namespace rtcp
168 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698