1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cast/streaming/packet_util.h"
6
7 #include "absl/types/span.h"
8 #include "gtest/gtest.h"
9
10 namespace openscreen {
11 namespace cast {
12 namespace {
13
14 // Tests that a simple RTCP packet containing only a Sender Report can be
15 // identified.
TEST(PacketUtilTest,InspectsRtcpPacketFromSender)16 TEST(PacketUtilTest, InspectsRtcpPacketFromSender) {
17 // clang-format off
18 const uint8_t kSenderReportPacket[] = {
19 0b10000000, // Version=2, Padding=no, ItemCount=0.
20 200, // RTCP Packet type.
21 0x00, 0x06, // Length of remainder of packet, in 32-bit words.
22 1, 2, 3, 4, // SSRC of sender.
23 0xe0, 0x73, 0x2e, 0x54, // NTP Timestamp (late evening on 2019-04-30).
24 0x80, 0x00, 0x00, 0x00,
25 0x00, 0x14, 0x99, 0x70, // RTP Timestamp (15 seconds, 90kHz timebase).
26 0x00, 0x00, 0x01, 0xff, // Sender's Packet Count.
27 0x00, 0x07, 0x11, 0x0d, // Sender's Octet Count.
28 };
29 // clang-format on
30 const Ssrc kSenderSsrc = 0x01020304;
31
32 const auto result = InspectPacketForRouting(kSenderReportPacket);
33 EXPECT_EQ(ApparentPacketType::RTCP, result.first);
34 EXPECT_EQ(kSenderSsrc, result.second);
35 }
36
37 // Tests that compound RTCP packets containing a Receiver Report and/or a Cast
38 // Feedback message can be identified.
TEST(PacketUtilTest,InspectsRtcpPacketFromReceiver)39 TEST(PacketUtilTest, InspectsRtcpPacketFromReceiver) {
40 // clang-format off
41 const uint8_t kReceiverReportPacket[] = {
42 0b10000001, // Version=2, Padding=no, ItemCount=1.
43 201, // RTCP Packet type.
44 0x00, 0x01, // Length of remainder of packet, in 32-bit words.
45 9, 8, 7, 6, // SSRC of receiver.
46 };
47 const uint8_t kCastFeedbackPacket[] = {
48 // Cast Feedback
49 0b10000000 | 15, // Version=2, Padding=no, Subtype=15.
50 206, // RTCP Packet type byte.
51 0x00, 0x04, // Length of remainder of packet, in 32-bit words.
52 9, 8, 7, 6, // SSRC of receiver.
53 1, 2, 3, 4, // SSRC of sender.
54 'C', 'A', 'S', 'T',
55 0x0a, // Checkpoint Frame ID (lower 8 bits).
56 0x00, // Number of "Loss Fields"
57 0x00, 0x28, // Current Playout Delay in milliseconds.
58 };
59 // clang-format on
60 const Ssrc kReceiverSsrc = 0x09080706;
61
62 {
63 const auto result = InspectPacketForRouting(kReceiverReportPacket);
64 EXPECT_EQ(ApparentPacketType::RTCP, result.first);
65 EXPECT_EQ(kReceiverSsrc, result.second);
66 }
67
68 {
69 const auto result = InspectPacketForRouting(kCastFeedbackPacket);
70 EXPECT_EQ(ApparentPacketType::RTCP, result.first);
71 EXPECT_EQ(kReceiverSsrc, result.second);
72 }
73
74 const absl::Span<const uint8_t> kCompoundCombinations[2][2] = {
75 {kReceiverReportPacket, kCastFeedbackPacket},
76 {kCastFeedbackPacket, kReceiverReportPacket},
77 };
78 for (const auto& combo : kCompoundCombinations) {
79 uint8_t compound_packet[sizeof(kReceiverReportPacket) +
80 sizeof(kCastFeedbackPacket)];
81 memcpy(compound_packet, combo[0].data(), combo[0].size());
82 memcpy(compound_packet + combo[0].size(), combo[1].data(), combo[1].size());
83
84 const auto result = InspectPacketForRouting(compound_packet);
85 EXPECT_EQ(ApparentPacketType::RTCP, result.first);
86 EXPECT_EQ(kReceiverSsrc, result.second);
87 }
88 }
89
90 // Tests that a RTP packet can be identified.
TEST(PacketUtilTest,InspectsRtpPacket)91 TEST(PacketUtilTest, InspectsRtpPacket) {
92 // clang-format off
93 const uint8_t kInput[] = {
94 0b10000000, // Version/Padding byte.
95 96, // Payload type byte.
96 0xbe, 0xef, // Sequence number.
97 9, 8, 7, 6, // RTP timestamp.
98 1, 2, 3, 4, // SSRC.
99 0b10000000, // Is key frame, no extensions.
100 5, // Frame ID.
101 0xa, 0xb, // Packet ID.
102 0xa, 0xc, // Max packet ID.
103 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
104 };
105 // clang-format on
106 const Ssrc kSenderSsrc = 0x01020304;
107
108 const auto result = InspectPacketForRouting(kInput);
109 EXPECT_EQ(ApparentPacketType::RTP, result.first);
110 EXPECT_EQ(kSenderSsrc, result.second);
111 }
112
113 // Tests that a RTP packet with the "127 payload type" hack can be identified as
114 // valid. See comments in rtp_defines.h for the RtpPayloadType enum definition,
115 // for further details.
TEST(PacketUtilTest,InspectsAndroidAudioRtpPacket)116 TEST(PacketUtilTest, InspectsAndroidAudioRtpPacket) {
117 // clang-format off
118 const uint8_t kInput[] = {
119 0b10000000, // Version/Padding byte.
120 127, // Payload type byte.
121 0xbe, 0xef, // Sequence number.
122 9, 8, 7, 6, // RTP timestamp.
123 1, 2, 3, 4, // SSRC.
124 0b10000000, // Is key frame, no extensions.
125 5, // Frame ID.
126 0xa, 0xb, // Packet ID.
127 0xa, 0xc, // Max packet ID.
128 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
129 };
130 // clang-format on
131 const Ssrc kSenderSsrc = 0x01020304;
132
133 const auto result = InspectPacketForRouting(kInput);
134 EXPECT_EQ(ApparentPacketType::RTP, result.first);
135 EXPECT_EQ(kSenderSsrc, result.second);
136 }
137
138 // Tests that a malformed RTP packet can be identified.
TEST(PacketUtilTest,InspectsMalformedRtpPacket)139 TEST(PacketUtilTest, InspectsMalformedRtpPacket) {
140 // clang-format off
141 const uint8_t kInput[] = {
142 0b11000000, // BAD: Version/Padding byte.
143 96, // Payload type byte.
144 0xbe, 0xef, // Sequence number.
145 9, 8, 7, 6, // RTP timestamp.
146 1, 2, 3, 4, // SSRC.
147 0b10000000, // Is key frame, no extensions.
148 5, // Frame ID.
149 0xa, 0xb, // Packet ID.
150 0xa, 0xc, // Max packet ID.
151 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
152 };
153 // clang-format on
154
155 const auto result = InspectPacketForRouting(kInput);
156 EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
157 }
158
159 // Tests that an empty packet is classified as unknown.
TEST(PacketUtilTest,InspectsEmptyPacket)160 TEST(PacketUtilTest, InspectsEmptyPacket) {
161 const uint8_t kInput[] = {};
162
163 const auto result =
164 InspectPacketForRouting(absl::Span<const uint8_t>(kInput, 0));
165 EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
166 }
167
168 // Tests that a packet with garbage is classified as unknown.
TEST(PacketUtilTest,InspectsGarbagePacket)169 TEST(PacketUtilTest, InspectsGarbagePacket) {
170 // clang-format off
171 const uint8_t kInput[] = {
172 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
173 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
174 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
175 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
176 };
177 // clang-format on
178
179 const auto result = InspectPacketForRouting(kInput);
180 EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
181 }
182
183 } // namespace
184 } // namespace cast
185 } // namespace openscreen
186