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