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/sdes.h"
12
13 #include "rtc_base/strings/string_builder.h"
14 #include "test/gtest.h"
15 #include "test/rtcp_packet_parser.h"
16
17 using webrtc::rtcp::Sdes;
18
19 namespace webrtc {
20 namespace {
21 const uint32_t kSenderSsrc = 0x12345678;
22 const uint8_t kPadding = 0;
23 const uint8_t kTerminatorTag = 0;
24 const uint8_t kCnameTag = 1;
25 const uint8_t kNameTag = 2;
26 const uint8_t kEmailTag = 3;
27 } // namespace
28
TEST(RtcpPacketSdesTest,CreateAndParseWithoutChunks)29 TEST(RtcpPacketSdesTest, CreateAndParseWithoutChunks) {
30 Sdes sdes;
31
32 rtc::Buffer packet = sdes.Build();
33 Sdes parsed;
34 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed));
35
36 EXPECT_EQ(0u, parsed.chunks().size());
37 }
38
TEST(RtcpPacketSdesTest,CreateAndParseWithOneChunk)39 TEST(RtcpPacketSdesTest, CreateAndParseWithOneChunk) {
40 const std::string kCname = "alice@host";
41
42 Sdes sdes;
43 EXPECT_TRUE(sdes.AddCName(kSenderSsrc, kCname));
44
45 rtc::Buffer packet = sdes.Build();
46 Sdes sdes_parsed;
47 EXPECT_TRUE(test::ParseSinglePacket(packet, &sdes_parsed));
48 const Sdes& parsed = sdes_parsed; // Ensure accessors are const.
49
50 EXPECT_EQ(1u, parsed.chunks().size());
51 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc);
52 EXPECT_EQ(kCname, parsed.chunks()[0].cname);
53 }
54
TEST(RtcpPacketSdesTest,CreateAndParseWithMultipleChunks)55 TEST(RtcpPacketSdesTest, CreateAndParseWithMultipleChunks) {
56 Sdes sdes;
57 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 0, "a"));
58 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 1, "ab"));
59 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 2, "abc"));
60 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 3, "abcd"));
61 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 4, "abcde"));
62 EXPECT_TRUE(sdes.AddCName(kSenderSsrc + 5, "abcdef"));
63
64 rtc::Buffer packet = sdes.Build();
65 Sdes parsed;
66 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed));
67
68 EXPECT_EQ(6u, parsed.chunks().size());
69 EXPECT_EQ(kSenderSsrc + 5, parsed.chunks()[5].ssrc);
70 EXPECT_EQ("abcdef", parsed.chunks()[5].cname);
71 }
72
TEST(RtcpPacketSdesTest,CreateWithTooManyChunks)73 TEST(RtcpPacketSdesTest, CreateWithTooManyChunks) {
74 const size_t kMaxChunks = (1 << 5) - 1;
75 Sdes sdes;
76 for (size_t i = 0; i < kMaxChunks; ++i) {
77 uint32_t ssrc = kSenderSsrc + i;
78 rtc::StringBuilder oss;
79 oss << "cname" << i;
80 EXPECT_TRUE(sdes.AddCName(ssrc, oss.str()));
81 }
82 EXPECT_FALSE(sdes.AddCName(kSenderSsrc + kMaxChunks, "foo"));
83 }
84
TEST(RtcpPacketSdesTest,CreateAndParseCnameItemWithEmptyString)85 TEST(RtcpPacketSdesTest, CreateAndParseCnameItemWithEmptyString) {
86 Sdes sdes;
87 EXPECT_TRUE(sdes.AddCName(kSenderSsrc, ""));
88
89 rtc::Buffer packet = sdes.Build();
90 Sdes parsed;
91 EXPECT_TRUE(test::ParseSinglePacket(packet, &parsed));
92
93 EXPECT_EQ(1u, parsed.chunks().size());
94 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc);
95 EXPECT_EQ("", parsed.chunks()[0].cname);
96 }
97
TEST(RtcpPacketSdesTest,ParseSkipsNonCNameField)98 TEST(RtcpPacketSdesTest, ParseSkipsNonCNameField) {
99 const uint8_t kName[] = "abc";
100 const uint8_t kCname[] = "de";
101 const uint8_t kValidPacket[] = {
102 0x81, 202, 0x00, 0x04, 0x12, 0x34, 0x56,
103 0x78, kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag,
104 2, kCname[0], kCname[1], kTerminatorTag, kPadding, kPadding};
105 // Sanity checks packet was assembled correctly.
106 ASSERT_EQ(0u, sizeof(kValidPacket) % 4);
107 ASSERT_EQ(kValidPacket[3] + 1u, sizeof(kValidPacket) / 4);
108
109 Sdes parsed;
110 EXPECT_TRUE(test::ParseSinglePacket(kValidPacket, &parsed));
111
112 EXPECT_EQ(1u, parsed.chunks().size());
113 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc);
114 EXPECT_EQ("de", parsed.chunks()[0].cname);
115 }
116
TEST(RtcpPacketSdesTest,ParseSkipsChunksWithoutCName)117 TEST(RtcpPacketSdesTest, ParseSkipsChunksWithoutCName) {
118 const uint8_t kName[] = "ab";
119 const uint8_t kEmail[] = "de";
120 const uint8_t kCname[] = "def";
121 const uint8_t kPacket[] = {
122 0x82, 202, 0x00, 0x07, 0x12,
123 0x34, 0x56, 0x78, // 1st chunk.
124 kNameTag, 3, kName[0], kName[1], kName[2],
125 kEmailTag, 2, kEmail[0], kEmail[1], kTerminatorTag,
126 kPadding, kPadding, 0x23, 0x45, 0x67,
127 0x89, // 2nd chunk.
128 kCnameTag, 3, kCname[0], kCname[1], kCname[2],
129 kTerminatorTag, kPadding, kPadding};
130 // Sanity checks packet was assembled correctly.
131 ASSERT_EQ(0u, sizeof(kPacket) % 4);
132 ASSERT_EQ(kPacket[3] + 1u, sizeof(kPacket) / 4);
133
134 Sdes parsed;
135 EXPECT_TRUE(test::ParseSinglePacket(kPacket, &parsed));
136 ASSERT_EQ(1u, parsed.chunks().size());
137 EXPECT_EQ(0x23456789u, parsed.chunks()[0].ssrc);
138 EXPECT_EQ("def", parsed.chunks()[0].cname);
139 }
140
TEST(RtcpPacketSdesTest,ParseFailsWithoutChunkItemTerminator)141 TEST(RtcpPacketSdesTest, ParseFailsWithoutChunkItemTerminator) {
142 const uint8_t kName[] = "abc";
143 const uint8_t kCname[] = "d";
144 // No place for next chunk item.
145 const uint8_t kInvalidPacket[] = {
146 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
147 kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag, 1, kCname[0]};
148 // Sanity checks packet was assembled correctly.
149 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4);
150 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4);
151
152 Sdes parsed;
153 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed));
154 }
155
TEST(RtcpPacketSdesTest,ParseFailsWithDamagedChunkItem)156 TEST(RtcpPacketSdesTest, ParseFailsWithDamagedChunkItem) {
157 const uint8_t kName[] = "ab";
158 const uint8_t kCname[] = "d";
159 // Next chunk item has non-terminator type, but not the size.
160 const uint8_t kInvalidPacket[] = {
161 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
162 kNameTag, 2, kName[0], kName[1], kCnameTag, 1, kCname[0], kEmailTag};
163 // Sanity checks packet was assembled correctly.
164 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4);
165 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4);
166
167 Sdes parsed;
168 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed));
169 }
170
TEST(RtcpPacketSdesTest,ParseFailsWithTooLongChunkItem)171 TEST(RtcpPacketSdesTest, ParseFailsWithTooLongChunkItem) {
172 const uint8_t kName[] = "abc";
173 const uint8_t kCname[] = "d";
174 // Last chunk item has length that goes beyond the buffer end.
175 const uint8_t kInvalidPacket[] = {
176 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
177 kNameTag, 3, kName[0], kName[1], kName[2], kCnameTag, 2, kCname[0]};
178 // Sanity checks packet was assembled correctly.
179 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4);
180 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4);
181
182 Sdes parsed;
183 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed));
184 }
185
TEST(RtcpPacketSdesTest,ParseFailsWithTwoCNames)186 TEST(RtcpPacketSdesTest, ParseFailsWithTwoCNames) {
187 const uint8_t kCname1[] = "a";
188 const uint8_t kCname2[] = "de";
189 const uint8_t kInvalidPacket[] = {
190 0x81, 202, 0x00, 0x03, 0x12, 0x34, 0x56,
191 0x78, kCnameTag, 1, kCname1[0], kCnameTag, 2, kCname2[0],
192 kCname2[1], kTerminatorTag};
193 // Sanity checks packet was assembled correctly.
194 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4);
195 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4);
196
197 Sdes parsed;
198 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed));
199 }
200
TEST(RtcpPacketSdesTest,ParseFailsWithTooLittleSpaceForNextChunk)201 TEST(RtcpPacketSdesTest, ParseFailsWithTooLittleSpaceForNextChunk) {
202 const uint8_t kCname[] = "a";
203 const uint8_t kEmail[] = "de";
204 // Two chunks are promised in the header, but no place for the second chunk.
205 const uint8_t kInvalidPacket[] = {
206 0x82, 202, 0x00, 0x04, 0x12, 0x34, 0x56,
207 0x78, // 1st chunk.
208 kCnameTag, 1, kCname[0], kEmailTag, 2, kEmail[0], kEmail[1],
209 kTerminatorTag, 0x23, 0x45, 0x67, 0x89}; // 2nd chunk.
210 // Sanity checks packet was assembled correctly.
211 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4);
212 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4);
213
214 Sdes parsed;
215 EXPECT_FALSE(test::ParseSinglePacket(kInvalidPacket, &parsed));
216 }
217
TEST(RtcpPacketSdesTest,ParsedSdesCanBeReusedForBuilding)218 TEST(RtcpPacketSdesTest, ParsedSdesCanBeReusedForBuilding) {
219 Sdes source;
220 const std::string kAlice = "alice@host";
221 const std::string kBob = "bob@host";
222 source.AddCName(kSenderSsrc, kAlice);
223
224 rtc::Buffer packet1 = source.Build();
225 Sdes middle;
226 test::ParseSinglePacket(packet1, &middle);
227
228 EXPECT_EQ(source.BlockLength(), middle.BlockLength());
229
230 middle.AddCName(kSenderSsrc + 1, kBob);
231
232 rtc::Buffer packet2 = middle.Build();
233 Sdes destination;
234 test::ParseSinglePacket(packet2, &destination);
235
236 EXPECT_EQ(middle.BlockLength(), destination.BlockLength());
237
238 EXPECT_EQ(2u, destination.chunks().size());
239 EXPECT_EQ(kSenderSsrc, destination.chunks()[0].ssrc);
240 EXPECT_EQ(kAlice, destination.chunks()[0].cname);
241 EXPECT_EQ(kSenderSsrc + 1, destination.chunks()[1].ssrc);
242 EXPECT_EQ(kBob, destination.chunks()[1].cname);
243 }
244 } // namespace webrtc
245