OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/sdes.h" |
12 | 12 |
13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
14 | 14 |
15 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | |
16 #include "webrtc/test/rtcp_packet_parser.h" | |
17 | |
18 using webrtc::rtcp::RawPacket; | 15 using webrtc::rtcp::RawPacket; |
19 using webrtc::rtcp::Sdes; | 16 using webrtc::rtcp::Sdes; |
20 using webrtc::test::RtcpPacketParser; | 17 using webrtc::RTCPUtility::RtcpCommonHeader; |
| 18 using webrtc::RTCPUtility::RtcpParseCommonHeader; |
21 | 19 |
22 namespace webrtc { | 20 namespace webrtc { |
| 21 namespace { |
23 const uint32_t kSenderSsrc = 0x12345678; | 22 const uint32_t kSenderSsrc = 0x12345678; |
| 23 const uint8_t kPadding = 0; |
| 24 const uint8_t kTerminatorTag = 0; |
| 25 const uint8_t kCnameTag = 1; |
| 26 const uint8_t kNameTag = 2; |
| 27 const uint8_t kEmailTag = 3; |
| 28 |
| 29 bool Parse(const uint8_t* buffer, size_t length, Sdes* sdes) { |
| 30 RtcpCommonHeader header; |
| 31 EXPECT_TRUE(RtcpParseCommonHeader(buffer, length, &header)); |
| 32 // Check that there is exactly one RTCP packet in the buffer. |
| 33 EXPECT_EQ(length, header.BlockSize()); |
| 34 return sdes->Parse(header, buffer + RtcpCommonHeader::kHeaderSizeBytes); |
| 35 } |
| 36 } // namespace |
| 37 |
| 38 TEST(RtcpPacketSdesTest, WithoutChunks) { |
| 39 Sdes sdes; |
| 40 |
| 41 rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
| 42 Sdes parsed; |
| 43 EXPECT_TRUE(Parse(packet->Buffer(), packet->Length(), &parsed)); |
| 44 |
| 45 EXPECT_EQ(0u, parsed.chunks().size()); |
| 46 } |
24 | 47 |
25 TEST(RtcpPacketSdesTest, WithOneChunk) { | 48 TEST(RtcpPacketSdesTest, WithOneChunk) { |
| 49 const std::string kCname = "alice@host"; |
| 50 |
26 Sdes sdes; | 51 Sdes sdes; |
27 EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "alice@host")); | 52 EXPECT_TRUE(sdes.WithCName(kSenderSsrc, kCname)); |
28 | 53 |
29 rtc::scoped_ptr<RawPacket> packet(sdes.Build()); | 54 rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
30 RtcpPacketParser parser; | 55 Sdes sdes_parsed; |
31 parser.Parse(packet->Buffer(), packet->Length()); | 56 Parse(packet->Buffer(), packet->Length(), &sdes_parsed); |
32 EXPECT_EQ(1, parser.sdes()->num_packets()); | 57 const Sdes& parsed = sdes_parsed; // Ensure accessors are const. |
33 EXPECT_EQ(1, parser.sdes_chunk()->num_packets()); | 58 |
34 EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc()); | 59 EXPECT_EQ(1u, parsed.chunks().size()); |
35 EXPECT_EQ("alice@host", parser.sdes_chunk()->Cname()); | 60 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
| 61 EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
36 } | 62 } |
37 | 63 |
38 TEST(RtcpPacketSdesTest, WithMultipleChunks) { | 64 TEST(RtcpPacketSdesTest, WithMultipleChunks) { |
39 Sdes sdes; | 65 Sdes sdes; |
40 EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "a")); | 66 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 0, "a")); |
41 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 1, "ab")); | 67 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 1, "ab")); |
42 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 2, "abc")); | 68 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 2, "abc")); |
43 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 3, "abcd")); | 69 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 3, "abcd")); |
44 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 4, "abcde")); | 70 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 4, "abcde")); |
45 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 5, "abcdef")); | 71 EXPECT_TRUE(sdes.WithCName(kSenderSsrc + 5, "abcdef")); |
46 | 72 |
47 rtc::scoped_ptr<RawPacket> packet(sdes.Build()); | 73 rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
48 RtcpPacketParser parser; | 74 Sdes parsed; |
49 parser.Parse(packet->Buffer(), packet->Length()); | 75 Parse(packet->Buffer(), packet->Length(), &parsed); |
50 EXPECT_EQ(1, parser.sdes()->num_packets()); | 76 |
51 EXPECT_EQ(6, parser.sdes_chunk()->num_packets()); | 77 EXPECT_EQ(6u, parsed.chunks().size()); |
52 EXPECT_EQ(kSenderSsrc + 5, parser.sdes_chunk()->Ssrc()); | 78 EXPECT_EQ(kSenderSsrc + 5, parsed.chunks()[5].ssrc); |
53 EXPECT_EQ("abcdef", parser.sdes_chunk()->Cname()); | 79 EXPECT_EQ("abcdef", parsed.chunks()[5].cname); |
54 } | 80 } |
55 | 81 |
56 TEST(RtcpPacketSdesTest, WithTooManyChunks) { | 82 TEST(RtcpPacketSdesTest, WithTooManyChunks) { |
| 83 const size_t kMaxChunks = (1 << 5) - 1; |
57 Sdes sdes; | 84 Sdes sdes; |
58 const int kMaxChunks = (1 << 5) - 1; | 85 for (size_t i = 0; i < kMaxChunks; ++i) { |
59 for (int i = 0; i < kMaxChunks; ++i) { | |
60 uint32_t ssrc = kSenderSsrc + i; | 86 uint32_t ssrc = kSenderSsrc + i; |
61 std::ostringstream oss; | 87 std::ostringstream oss; |
62 oss << "cname" << i; | 88 oss << "cname" << i; |
63 EXPECT_TRUE(sdes.WithCName(ssrc, oss.str())); | 89 EXPECT_TRUE(sdes.WithCName(ssrc, oss.str())); |
64 } | 90 } |
65 EXPECT_FALSE(sdes.WithCName(kSenderSsrc + kMaxChunks, "foo")); | 91 EXPECT_FALSE(sdes.WithCName(kSenderSsrc + kMaxChunks, "foo")); |
66 } | 92 } |
67 | 93 |
68 TEST(RtcpPacketSdesTest, CnameItemWithEmptyString) { | 94 TEST(RtcpPacketSdesTest, CnameItemWithEmptyString) { |
69 Sdes sdes; | 95 Sdes sdes; |
70 EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "")); | 96 EXPECT_TRUE(sdes.WithCName(kSenderSsrc, "")); |
71 | 97 |
72 rtc::scoped_ptr<RawPacket> packet(sdes.Build()); | 98 rtc::scoped_ptr<RawPacket> packet = sdes.Build(); |
73 RtcpPacketParser parser; | 99 Sdes parsed; |
74 parser.Parse(packet->Buffer(), packet->Length()); | 100 Parse(packet->Buffer(), packet->Length(), &parsed); |
75 EXPECT_EQ(1, parser.sdes()->num_packets()); | 101 |
76 EXPECT_EQ(1, parser.sdes_chunk()->num_packets()); | 102 EXPECT_EQ(1u, parsed.chunks().size()); |
77 EXPECT_EQ(kSenderSsrc, parser.sdes_chunk()->Ssrc()); | 103 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
78 EXPECT_EQ("", parser.sdes_chunk()->Cname()); | 104 EXPECT_EQ("", parsed.chunks()[0].cname); |
79 } | 105 } |
80 | 106 |
| 107 TEST(RtcpPacketSdesTest, ParseSkipsNonCNameField) { |
| 108 const char kName[] = "abc"; |
| 109 const std::string kCname = "de"; |
| 110 const uint8_t kValidPacket[] = {0x81, 202, 0x00, 0x04, |
| 111 0x12, 0x34, 0x56, 0x78, |
| 112 kNameTag, 3, kName[0], kName[1], kName[2], |
| 113 kCnameTag, 2, kCname[0], kCname[1], |
| 114 kTerminatorTag, kPadding, kPadding}; |
| 115 // Sanity checks packet was assembled correctly. |
| 116 ASSERT_EQ(0u, sizeof(kValidPacket) % 4); |
| 117 ASSERT_EQ(kValidPacket[3] + 1u, sizeof(kValidPacket) / 4); |
| 118 |
| 119 Sdes parsed; |
| 120 EXPECT_TRUE(Parse(kValidPacket, sizeof(kValidPacket), &parsed)); |
| 121 |
| 122 EXPECT_EQ(1u, parsed.chunks().size()); |
| 123 EXPECT_EQ(kSenderSsrc, parsed.chunks()[0].ssrc); |
| 124 EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
| 125 } |
| 126 |
| 127 TEST(RtcpPacketSdesTest, ParseSkipsChunksWithoutCName) { |
| 128 const char kName[] = "ab"; |
| 129 const char kEmail[] = "de"; |
| 130 const std::string kCname = "def"; |
| 131 const uint8_t kPacket[] = {0x82, 202, 0x00, 0x07, |
| 132 0x12, 0x34, 0x56, 0x78, // 1st chunk. |
| 133 kNameTag, 3, kName[0], kName[1], kName[2], |
| 134 kEmailTag, 2, kEmail[0], kEmail[1], |
| 135 kTerminatorTag, kPadding, kPadding, |
| 136 0x23, 0x45, 0x67, 0x89, // 2nd chunk. |
| 137 kCnameTag, 3, kCname[0], kCname[1], kCname[2], |
| 138 kTerminatorTag, kPadding, kPadding}; |
| 139 // Sanity checks packet was assembled correctly. |
| 140 ASSERT_EQ(0u, sizeof(kPacket) % 4); |
| 141 ASSERT_EQ(kPacket[3] + 1u, sizeof(kPacket) / 4); |
| 142 |
| 143 Sdes parsed; |
| 144 EXPECT_TRUE(Parse(kPacket, sizeof(kPacket), &parsed)); |
| 145 ASSERT_EQ(1u, parsed.chunks().size()); |
| 146 EXPECT_EQ(0x23456789u, parsed.chunks()[0].ssrc); |
| 147 EXPECT_EQ(kCname, parsed.chunks()[0].cname); |
| 148 } |
| 149 |
| 150 TEST(RtcpPacketSdesTest, ParseFailsWithoutChunkItemTerminator) { |
| 151 const char kName[] = "abc"; |
| 152 const char kCname[] = "d"; |
| 153 // No place for next chunk item. |
| 154 const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
| 155 0x12, 0x34, 0x56, 0x78, |
| 156 kNameTag, 3, kName[0], kName[1], kName[2], |
| 157 kCnameTag, 1, kCname[0]}; |
| 158 // Sanity checks packet was assembled correctly. |
| 159 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
| 160 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
| 161 |
| 162 Sdes parsed; |
| 163 EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
| 164 } |
| 165 |
| 166 TEST(RtcpPacketSdesTest, ParseFailsWithDamagedChunkItem) { |
| 167 const char kName[] = "ab"; |
| 168 const char kCname[] = "d"; |
| 169 // Next chunk item has non-terminator type, but not the size. |
| 170 const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
| 171 0x12, 0x34, 0x56, 0x78, |
| 172 kNameTag, 2, kName[0], kName[1], |
| 173 kCnameTag, 1, kCname[0], |
| 174 kEmailTag}; |
| 175 // Sanity checks packet was assembled correctly. |
| 176 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
| 177 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
| 178 |
| 179 Sdes parsed; |
| 180 EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
| 181 } |
| 182 |
| 183 TEST(RtcpPacketSdesTest, ParseFailsWithTooLongChunkItem) { |
| 184 const char kName[] = "abc"; |
| 185 const char kCname[] = "d"; |
| 186 // Last chunk item has length that goes beyond the buffer end. |
| 187 const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
| 188 0x12, 0x34, 0x56, 0x78, |
| 189 kNameTag, 3, kName[0], kName[1], kName[2], |
| 190 kCnameTag, 2, kCname[0]}; |
| 191 // Sanity checks packet was assembled correctly. |
| 192 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
| 193 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
| 194 |
| 195 Sdes parsed; |
| 196 EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
| 197 } |
| 198 |
| 199 TEST(RtcpPacketSdesTest, ParseFailsWithTwoCNames) { |
| 200 const char kCname1[] = "a"; |
| 201 const char kCname2[] = "de"; |
| 202 const uint8_t kInvalidPacket[] = {0x81, 202, 0x00, 0x03, |
| 203 0x12, 0x34, 0x56, 0x78, |
| 204 kCnameTag, 1, kCname1[0], |
| 205 kCnameTag, 2, kCname2[0], kCname2[1], |
| 206 kTerminatorTag}; |
| 207 // Sanity checks packet was assembled correctly. |
| 208 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
| 209 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
| 210 |
| 211 Sdes parsed; |
| 212 EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
| 213 } |
| 214 |
| 215 TEST(RtcpPacketSdesTest, ParseFailsWithTooLittleSpaceForNextChunk) { |
| 216 const char kCname[] = "a"; |
| 217 const char kEmail[] = "de"; |
| 218 // Two chunks are promised in the header, but no place for the second chunk. |
| 219 const uint8_t kInvalidPacket[] = {0x82, 202, 0x00, 0x04, |
| 220 0x12, 0x34, 0x56, 0x78, // 1st chunk. |
| 221 kCnameTag, 1, kCname[0], |
| 222 kEmailTag, 2, kEmail[0], kEmail[1], |
| 223 kTerminatorTag, |
| 224 0x23, 0x45, 0x67, 0x89}; // 2nd chunk. |
| 225 // Sanity checks packet was assembled correctly. |
| 226 ASSERT_EQ(0u, sizeof(kInvalidPacket) % 4); |
| 227 ASSERT_EQ(kInvalidPacket[3] + 1u, sizeof(kInvalidPacket) / 4); |
| 228 |
| 229 Sdes parsed; |
| 230 EXPECT_FALSE(Parse(kInvalidPacket, sizeof(kInvalidPacket), &parsed)); |
| 231 } |
| 232 |
| 233 TEST(RtcpPacketSdesTest, ParsedSdesCanBeReusedForBuilding) { |
| 234 Sdes source; |
| 235 const std::string kAlice = "alice@host"; |
| 236 const std::string kBob = "bob@host"; |
| 237 source.WithCName(kSenderSsrc, kAlice); |
| 238 |
| 239 rtc::scoped_ptr<RawPacket> packet1 = source.Build(); |
| 240 Sdes middle; |
| 241 Parse(packet1->Buffer(), packet1->Length(), &middle); |
| 242 |
| 243 EXPECT_EQ(source.BlockLength(), middle.BlockLength()); |
| 244 |
| 245 middle.WithCName(kSenderSsrc + 1, kBob); |
| 246 |
| 247 rtc::scoped_ptr<RawPacket> packet2 = middle.Build(); |
| 248 Sdes destination; |
| 249 Parse(packet2->Buffer(), packet2->Length(), &destination); |
| 250 |
| 251 EXPECT_EQ(middle.BlockLength(), destination.BlockLength()); |
| 252 |
| 253 EXPECT_EQ(2u, destination.chunks().size()); |
| 254 EXPECT_EQ(kSenderSsrc, destination.chunks()[0].ssrc); |
| 255 EXPECT_EQ(kAlice, destination.chunks()[0].cname); |
| 256 EXPECT_EQ(kSenderSsrc + 1, destination.chunks()[1].ssrc); |
| 257 EXPECT_EQ(kBob, destination.chunks()[1].cname); |
| 258 } |
81 } // namespace webrtc | 259 } // namespace webrtc |
OLD | NEW |