186 lines
6.2 KiB
C++
186 lines
6.2 KiB
C++
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "cast/streaming/packet_util.h"
|
|
|
|
#include "absl/types/span.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace openscreen {
|
|
namespace cast {
|
|
namespace {
|
|
|
|
// Tests that a simple RTCP packet containing only a Sender Report can be
|
|
// identified.
|
|
TEST(PacketUtilTest, InspectsRtcpPacketFromSender) {
|
|
// clang-format off
|
|
const uint8_t kSenderReportPacket[] = {
|
|
0b10000000, // Version=2, Padding=no, ItemCount=0.
|
|
200, // RTCP Packet type.
|
|
0x00, 0x06, // Length of remainder of packet, in 32-bit words.
|
|
1, 2, 3, 4, // SSRC of sender.
|
|
0xe0, 0x73, 0x2e, 0x54, // NTP Timestamp (late evening on 2019-04-30).
|
|
0x80, 0x00, 0x00, 0x00,
|
|
0x00, 0x14, 0x99, 0x70, // RTP Timestamp (15 seconds, 90kHz timebase).
|
|
0x00, 0x00, 0x01, 0xff, // Sender's Packet Count.
|
|
0x00, 0x07, 0x11, 0x0d, // Sender's Octet Count.
|
|
};
|
|
// clang-format on
|
|
const Ssrc kSenderSsrc = 0x01020304;
|
|
|
|
const auto result = InspectPacketForRouting(kSenderReportPacket);
|
|
EXPECT_EQ(ApparentPacketType::RTCP, result.first);
|
|
EXPECT_EQ(kSenderSsrc, result.second);
|
|
}
|
|
|
|
// Tests that compound RTCP packets containing a Receiver Report and/or a Cast
|
|
// Feedback message can be identified.
|
|
TEST(PacketUtilTest, InspectsRtcpPacketFromReceiver) {
|
|
// clang-format off
|
|
const uint8_t kReceiverReportPacket[] = {
|
|
0b10000001, // Version=2, Padding=no, ItemCount=1.
|
|
201, // RTCP Packet type.
|
|
0x00, 0x01, // Length of remainder of packet, in 32-bit words.
|
|
9, 8, 7, 6, // SSRC of receiver.
|
|
};
|
|
const uint8_t kCastFeedbackPacket[] = {
|
|
// Cast Feedback
|
|
0b10000000 | 15, // Version=2, Padding=no, Subtype=15.
|
|
206, // RTCP Packet type byte.
|
|
0x00, 0x04, // Length of remainder of packet, in 32-bit words.
|
|
9, 8, 7, 6, // SSRC of receiver.
|
|
1, 2, 3, 4, // SSRC of sender.
|
|
'C', 'A', 'S', 'T',
|
|
0x0a, // Checkpoint Frame ID (lower 8 bits).
|
|
0x00, // Number of "Loss Fields"
|
|
0x00, 0x28, // Current Playout Delay in milliseconds.
|
|
};
|
|
// clang-format on
|
|
const Ssrc kReceiverSsrc = 0x09080706;
|
|
|
|
{
|
|
const auto result = InspectPacketForRouting(kReceiverReportPacket);
|
|
EXPECT_EQ(ApparentPacketType::RTCP, result.first);
|
|
EXPECT_EQ(kReceiverSsrc, result.second);
|
|
}
|
|
|
|
{
|
|
const auto result = InspectPacketForRouting(kCastFeedbackPacket);
|
|
EXPECT_EQ(ApparentPacketType::RTCP, result.first);
|
|
EXPECT_EQ(kReceiverSsrc, result.second);
|
|
}
|
|
|
|
const absl::Span<const uint8_t> kCompoundCombinations[2][2] = {
|
|
{kReceiverReportPacket, kCastFeedbackPacket},
|
|
{kCastFeedbackPacket, kReceiverReportPacket},
|
|
};
|
|
for (const auto& combo : kCompoundCombinations) {
|
|
uint8_t compound_packet[sizeof(kReceiverReportPacket) +
|
|
sizeof(kCastFeedbackPacket)];
|
|
memcpy(compound_packet, combo[0].data(), combo[0].size());
|
|
memcpy(compound_packet + combo[0].size(), combo[1].data(), combo[1].size());
|
|
|
|
const auto result = InspectPacketForRouting(compound_packet);
|
|
EXPECT_EQ(ApparentPacketType::RTCP, result.first);
|
|
EXPECT_EQ(kReceiverSsrc, result.second);
|
|
}
|
|
}
|
|
|
|
// Tests that a RTP packet can be identified.
|
|
TEST(PacketUtilTest, InspectsRtpPacket) {
|
|
// clang-format off
|
|
const uint8_t kInput[] = {
|
|
0b10000000, // Version/Padding byte.
|
|
96, // Payload type byte.
|
|
0xbe, 0xef, // Sequence number.
|
|
9, 8, 7, 6, // RTP timestamp.
|
|
1, 2, 3, 4, // SSRC.
|
|
0b10000000, // Is key frame, no extensions.
|
|
5, // Frame ID.
|
|
0xa, 0xb, // Packet ID.
|
|
0xa, 0xc, // Max packet ID.
|
|
0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
|
|
};
|
|
// clang-format on
|
|
const Ssrc kSenderSsrc = 0x01020304;
|
|
|
|
const auto result = InspectPacketForRouting(kInput);
|
|
EXPECT_EQ(ApparentPacketType::RTP, result.first);
|
|
EXPECT_EQ(kSenderSsrc, result.second);
|
|
}
|
|
|
|
// Tests that a RTP packet with the "127 payload type" hack can be identified as
|
|
// valid. See comments in rtp_defines.h for the RtpPayloadType enum definition,
|
|
// for further details.
|
|
TEST(PacketUtilTest, InspectsAndroidAudioRtpPacket) {
|
|
// clang-format off
|
|
const uint8_t kInput[] = {
|
|
0b10000000, // Version/Padding byte.
|
|
127, // Payload type byte.
|
|
0xbe, 0xef, // Sequence number.
|
|
9, 8, 7, 6, // RTP timestamp.
|
|
1, 2, 3, 4, // SSRC.
|
|
0b10000000, // Is key frame, no extensions.
|
|
5, // Frame ID.
|
|
0xa, 0xb, // Packet ID.
|
|
0xa, 0xc, // Max packet ID.
|
|
0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
|
|
};
|
|
// clang-format on
|
|
const Ssrc kSenderSsrc = 0x01020304;
|
|
|
|
const auto result = InspectPacketForRouting(kInput);
|
|
EXPECT_EQ(ApparentPacketType::RTP, result.first);
|
|
EXPECT_EQ(kSenderSsrc, result.second);
|
|
}
|
|
|
|
// Tests that a malformed RTP packet can be identified.
|
|
TEST(PacketUtilTest, InspectsMalformedRtpPacket) {
|
|
// clang-format off
|
|
const uint8_t kInput[] = {
|
|
0b11000000, // BAD: Version/Padding byte.
|
|
96, // Payload type byte.
|
|
0xbe, 0xef, // Sequence number.
|
|
9, 8, 7, 6, // RTP timestamp.
|
|
1, 2, 3, 4, // SSRC.
|
|
0b10000000, // Is key frame, no extensions.
|
|
5, // Frame ID.
|
|
0xa, 0xb, // Packet ID.
|
|
0xa, 0xc, // Max packet ID.
|
|
0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, // Payload.
|
|
};
|
|
// clang-format on
|
|
|
|
const auto result = InspectPacketForRouting(kInput);
|
|
EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
|
|
}
|
|
|
|
// Tests that an empty packet is classified as unknown.
|
|
TEST(PacketUtilTest, InspectsEmptyPacket) {
|
|
const uint8_t kInput[] = {};
|
|
|
|
const auto result =
|
|
InspectPacketForRouting(absl::Span<const uint8_t>(kInput, 0));
|
|
EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
|
|
}
|
|
|
|
// Tests that a packet with garbage is classified as unknown.
|
|
TEST(PacketUtilTest, InspectsGarbagePacket) {
|
|
// clang-format off
|
|
const uint8_t kInput[] = {
|
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
|
};
|
|
// clang-format on
|
|
|
|
const auto result = InspectPacketForRouting(kInput);
|
|
EXPECT_EQ(ApparentPacketType::UNKNOWN, result.first);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace cast
|
|
} // namespace openscreen
|