Home | History | Annotate | Download | only in rtcp_packet
      1 /*
      2  *  Copyright (c) 2015 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 "webrtc/modules/rtp_rtcp/source/rtcp_packet/nack.h"
     12 
     13 #include "testing/gmock/include/gmock/gmock.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 using ::testing::_;
     17 using ::testing::ElementsAreArray;
     18 using ::testing::Invoke;
     19 using ::testing::UnorderedElementsAreArray;
     20 
     21 using webrtc::rtcp::Nack;
     22 using webrtc::rtcp::RawPacket;
     23 using webrtc::RTCPUtility::RtcpCommonHeader;
     24 using webrtc::RTCPUtility::RtcpParseCommonHeader;
     25 
     26 namespace webrtc {
     27 namespace {
     28 
     29 const uint32_t kSenderSsrc = 0x12345678;
     30 const uint32_t kRemoteSsrc = 0x23456789;
     31 
     32 const uint16_t kList[] = {0, 1, 3, 8, 16};
     33 const size_t kListLength = sizeof(kList) / sizeof(kList[0]);
     34 const uint8_t kPacket[] = {0x81, 205,  0x00, 0x03, 0x12, 0x34, 0x56, 0x78,
     35                            0x23, 0x45, 0x67, 0x89, 0x00, 0x00, 0x80, 0x85};
     36 const size_t kPacketLength = sizeof(kPacket);
     37 
     38 const uint16_t kWrapList[] = {0xffdc, 0xffec, 0xfffe, 0xffff, 0x0000,
     39                               0x0001, 0x0003, 0x0014, 0x0064};
     40 const size_t kWrapListLength = sizeof(kWrapList) / sizeof(kWrapList[0]);
     41 const uint8_t kWrapPacket[] = {0x81, 205,  0x00, 0x06, 0x12, 0x34, 0x56, 0x78,
     42                                0x23, 0x45, 0x67, 0x89, 0xff, 0xdc, 0x80, 0x00,
     43                                0xff, 0xfe, 0x00, 0x17, 0x00, 0x14, 0x00, 0x00,
     44                                0x00, 0x64, 0x00, 0x00};
     45 const size_t kWrapPacketLength = sizeof(kWrapPacket);
     46 
     47 TEST(RtcpPacketNackTest, Create) {
     48   Nack nack;
     49   nack.From(kSenderSsrc);
     50   nack.To(kRemoteSsrc);
     51   nack.WithList(kList, kListLength);
     52 
     53   rtc::scoped_ptr<RawPacket> packet = nack.Build();
     54 
     55   EXPECT_EQ(kPacketLength, packet->Length());
     56   EXPECT_EQ(0, memcmp(kPacket, packet->Buffer(), kPacketLength));
     57 }
     58 
     59 TEST(RtcpPacketNackTest, Parse) {
     60   RtcpCommonHeader header;
     61   EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header));
     62   EXPECT_EQ(kPacketLength, header.BlockSize());
     63   Nack parsed;
     64 
     65   EXPECT_TRUE(
     66       parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes));
     67   const Nack& const_parsed = parsed;
     68 
     69   EXPECT_EQ(kSenderSsrc, const_parsed.sender_ssrc());
     70   EXPECT_EQ(kRemoteSsrc, const_parsed.media_ssrc());
     71   EXPECT_THAT(const_parsed.packet_ids(), ElementsAreArray(kList));
     72 }
     73 
     74 TEST(RtcpPacketNackTest, CreateWrap) {
     75   Nack nack;
     76   nack.From(kSenderSsrc);
     77   nack.To(kRemoteSsrc);
     78   nack.WithList(kWrapList, kWrapListLength);
     79 
     80   rtc::scoped_ptr<RawPacket> packet = nack.Build();
     81 
     82   EXPECT_EQ(kWrapPacketLength, packet->Length());
     83   EXPECT_EQ(0, memcmp(kWrapPacket, packet->Buffer(), kWrapPacketLength));
     84 }
     85 
     86 TEST(RtcpPacketNackTest, ParseWrap) {
     87   RtcpCommonHeader header;
     88   EXPECT_TRUE(RtcpParseCommonHeader(kWrapPacket, kWrapPacketLength, &header));
     89   EXPECT_EQ(kWrapPacketLength, header.BlockSize());
     90 
     91   Nack parsed;
     92   EXPECT_TRUE(
     93       parsed.Parse(header, kWrapPacket + RtcpCommonHeader::kHeaderSizeBytes));
     94 
     95   EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc());
     96   EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc());
     97   EXPECT_THAT(parsed.packet_ids(), ElementsAreArray(kWrapList));
     98 }
     99 
    100 TEST(RtcpPacketNackTest, BadOrder) {
    101   // Does not guarantee optimal packing, but should guarantee correctness.
    102   const uint16_t kUnorderedList[] = {1, 25, 13, 12, 9, 27, 29};
    103   const size_t kUnorderedListLength =
    104       sizeof(kUnorderedList) / sizeof(kUnorderedList[0]);
    105   Nack nack;
    106   nack.From(kSenderSsrc);
    107   nack.To(kRemoteSsrc);
    108   nack.WithList(kUnorderedList, kUnorderedListLength);
    109 
    110   rtc::scoped_ptr<RawPacket> packet = nack.Build();
    111 
    112   Nack parsed;
    113   RtcpCommonHeader header;
    114   EXPECT_TRUE(
    115       RtcpParseCommonHeader(packet->Buffer(), packet->Length(), &header));
    116   EXPECT_TRUE(parsed.Parse(
    117       header, packet->Buffer() + RtcpCommonHeader::kHeaderSizeBytes));
    118 
    119   EXPECT_EQ(kSenderSsrc, parsed.sender_ssrc());
    120   EXPECT_EQ(kRemoteSsrc, parsed.media_ssrc());
    121   EXPECT_THAT(parsed.packet_ids(), UnorderedElementsAreArray(kUnorderedList));
    122 }
    123 
    124 TEST(RtcpPacketNackTest, CreateFragmented) {
    125   Nack nack;
    126   const uint16_t kList[] = {1, 100, 200, 300, 400};
    127   const uint16_t kListLength = sizeof(kList) / sizeof(kList[0]);
    128   nack.From(kSenderSsrc);
    129   nack.To(kRemoteSsrc);
    130   nack.WithList(kList, kListLength);
    131 
    132   class MockPacketReadyCallback : public rtcp::RtcpPacket::PacketReadyCallback {
    133    public:
    134     MOCK_METHOD2(OnPacketReady, void(uint8_t*, size_t));
    135   } verifier;
    136 
    137   class NackVerifier {
    138    public:
    139     explicit NackVerifier(std::vector<uint16_t> ids) : ids_(ids) {}
    140     void operator()(uint8_t* data, size_t length) {
    141       RtcpCommonHeader header;
    142       EXPECT_TRUE(RtcpParseCommonHeader(data, length, &header));
    143       EXPECT_EQ(length, header.BlockSize());
    144       Nack nack;
    145       EXPECT_TRUE(
    146           nack.Parse(header, data + RtcpCommonHeader::kHeaderSizeBytes));
    147       EXPECT_EQ(kSenderSsrc, nack.sender_ssrc());
    148       EXPECT_EQ(kRemoteSsrc, nack.media_ssrc());
    149       EXPECT_THAT(nack.packet_ids(), ElementsAreArray(ids_));
    150     }
    151     std::vector<uint16_t> ids_;
    152   } packet1({1, 100, 200}), packet2({300, 400});
    153 
    154   EXPECT_CALL(verifier, OnPacketReady(_, _))
    155       .WillOnce(Invoke(packet1))
    156       .WillOnce(Invoke(packet2));
    157   const size_t kBufferSize = 12 + (3 * 4);  // Fits common header + 3 nack items
    158   uint8_t buffer[kBufferSize];
    159   EXPECT_TRUE(nack.BuildExternalBuffer(buffer, kBufferSize, &verifier));
    160 }
    161 
    162 TEST(RtcpPacketNackTest, CreateFailsWithTooSmallBuffer) {
    163   const uint16_t kList[] = {1};
    164   const size_t kMinNackBlockSize = 16;
    165   Nack nack;
    166   nack.From(kSenderSsrc);
    167   nack.To(kRemoteSsrc);
    168   nack.WithList(kList, 1);
    169   class Verifier : public rtcp::RtcpPacket::PacketReadyCallback {
    170    public:
    171     void OnPacketReady(uint8_t* data, size_t length) override {
    172       ADD_FAILURE() << "Buffer should be too small.";
    173     }
    174   } verifier;
    175   uint8_t buffer[kMinNackBlockSize - 1];
    176   EXPECT_FALSE(
    177       nack.BuildExternalBuffer(buffer, kMinNackBlockSize - 1, &verifier));
    178 }
    179 
    180 TEST(RtcpPacketNackTest, ParseFailsWithTooSmallBuffer) {
    181   RtcpCommonHeader header;
    182   EXPECT_TRUE(RtcpParseCommonHeader(kPacket, kPacketLength, &header));
    183   header.payload_size_bytes--;  // Damage the packet
    184   Nack parsed;
    185   EXPECT_FALSE(
    186       parsed.Parse(header, kPacket + RtcpCommonHeader::kHeaderSizeBytes));
    187 }
    188 
    189 }  // namespace
    190 }  // namespace webrtc
    191