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