1 /*
2  *  Copyright (c) 2012 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/include/ulpfec_receiver.h"
12 
13 #include <string.h>
14 
15 #include <list>
16 #include <memory>
17 
18 #include "modules/rtp_rtcp/mocks/mock_recovered_packet_receiver.h"
19 #include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
20 #include "modules/rtp_rtcp/source/byte_io.h"
21 #include "modules/rtp_rtcp/source/fec_test_helper.h"
22 #include "modules/rtp_rtcp/source/forward_error_correction.h"
23 #include "modules/rtp_rtcp/source/rtp_packet_received.h"
24 #include "test/gmock.h"
25 #include "test/gtest.h"
26 
27 namespace webrtc {
28 
29 namespace {
30 using ::testing::_;
31 using ::testing::Args;
32 using ::testing::ElementsAreArray;
33 
34 using test::fec::AugmentedPacket;
35 using Packet = ForwardErrorCorrection::Packet;
36 using test::fec::UlpfecPacketGenerator;
37 
38 constexpr int kFecPayloadType = 96;
39 constexpr uint32_t kMediaSsrc = 835424;
40 
41 class NullRecoveredPacketReceiver : public RecoveredPacketReceiver {
42  public:
OnRecoveredPacket(const uint8_t * packet,size_t length)43   void OnRecoveredPacket(const uint8_t* packet, size_t length) override {}
44 };
45 
46 }  // namespace
47 
48 class UlpfecReceiverTest : public ::testing::Test {
49  protected:
UlpfecReceiverTest()50   UlpfecReceiverTest()
51       : fec_(ForwardErrorCorrection::CreateUlpfec(kMediaSsrc)),
52         receiver_fec_(UlpfecReceiver::Create(kMediaSsrc,
53                                              &recovered_packet_receiver_,
54                                              {})),
55         packet_generator_(kMediaSsrc) {}
56 
57   // Generates |num_fec_packets| FEC packets, given |media_packets|.
58   void EncodeFec(const ForwardErrorCorrection::PacketList& media_packets,
59                  size_t num_fec_packets,
60                  std::list<ForwardErrorCorrection::Packet*>* fec_packets);
61 
62   // Generates |num_media_packets| corresponding to a single frame.
63   void PacketizeFrame(size_t num_media_packets,
64                       size_t frame_offset,
65                       std::list<AugmentedPacket*>* augmented_packets,
66                       ForwardErrorCorrection::PacketList* packets);
67 
68   // Build a media packet using |packet_generator_| and add it
69   // to the receiver.
70   void BuildAndAddRedMediaPacket(AugmentedPacket* packet,
71                                  bool is_recovered = false);
72 
73   // Build a FEC packet using |packet_generator_| and add it
74   // to the receiver.
75   void BuildAndAddRedFecPacket(Packet* packet);
76 
77   // Ensure that |recovered_packet_receiver_| will be called correctly
78   // and that the recovered packet will be identical to the lost packet.
79   void VerifyReconstructedMediaPacket(const AugmentedPacket& packet,
80                                       size_t times);
81 
82   void InjectGarbagePacketLength(size_t fec_garbage_offset);
83 
84   static void SurvivesMaliciousPacket(const uint8_t* data,
85                                       size_t length,
86                                       uint8_t ulpfec_payload_type);
87 
88   MockRecoveredPacketReceiver recovered_packet_receiver_;
89   std::unique_ptr<ForwardErrorCorrection> fec_;
90   std::unique_ptr<UlpfecReceiver> receiver_fec_;
91   UlpfecPacketGenerator packet_generator_;
92 };
93 
EncodeFec(const ForwardErrorCorrection::PacketList & media_packets,size_t num_fec_packets,std::list<ForwardErrorCorrection::Packet * > * fec_packets)94 void UlpfecReceiverTest::EncodeFec(
95     const ForwardErrorCorrection::PacketList& media_packets,
96     size_t num_fec_packets,
97     std::list<ForwardErrorCorrection::Packet*>* fec_packets) {
98   const uint8_t protection_factor =
99       num_fec_packets * 255 / media_packets.size();
100   // Unequal protection is turned off, and the number of important
101   // packets is thus irrelevant.
102   constexpr int kNumImportantPackets = 0;
103   constexpr bool kUseUnequalProtection = false;
104   constexpr FecMaskType kFecMaskType = kFecMaskBursty;
105   EXPECT_EQ(
106       0, fec_->EncodeFec(media_packets, protection_factor, kNumImportantPackets,
107                          kUseUnequalProtection, kFecMaskType, fec_packets));
108   ASSERT_EQ(num_fec_packets, fec_packets->size());
109 }
110 
PacketizeFrame(size_t num_media_packets,size_t frame_offset,std::list<AugmentedPacket * > * augmented_packets,ForwardErrorCorrection::PacketList * packets)111 void UlpfecReceiverTest::PacketizeFrame(
112     size_t num_media_packets,
113     size_t frame_offset,
114     std::list<AugmentedPacket*>* augmented_packets,
115     ForwardErrorCorrection::PacketList* packets) {
116   packet_generator_.NewFrame(num_media_packets);
117   for (size_t i = 0; i < num_media_packets; ++i) {
118     std::unique_ptr<AugmentedPacket> next_packet(
119         packet_generator_.NextPacket(frame_offset + i, kRtpHeaderSize + 10));
120     augmented_packets->push_back(next_packet.get());
121     packets->push_back(std::move(next_packet));
122   }
123 }
124 
BuildAndAddRedMediaPacket(AugmentedPacket * packet,bool is_recovered)125 void UlpfecReceiverTest::BuildAndAddRedMediaPacket(AugmentedPacket* packet,
126                                                    bool is_recovered) {
127   RtpPacketReceived red_packet =
128       packet_generator_.BuildMediaRedPacket(*packet, is_recovered);
129   EXPECT_TRUE(receiver_fec_->AddReceivedRedPacket(red_packet, kFecPayloadType));
130 }
131 
BuildAndAddRedFecPacket(Packet * packet)132 void UlpfecReceiverTest::BuildAndAddRedFecPacket(Packet* packet) {
133   RtpPacketReceived red_packet =
134       packet_generator_.BuildUlpfecRedPacket(*packet);
135   EXPECT_TRUE(receiver_fec_->AddReceivedRedPacket(red_packet, kFecPayloadType));
136 }
137 
VerifyReconstructedMediaPacket(const AugmentedPacket & packet,size_t times)138 void UlpfecReceiverTest::VerifyReconstructedMediaPacket(
139     const AugmentedPacket& packet,
140     size_t times) {
141   // Verify that the content of the reconstructed packet is equal to the
142   // content of |packet|, and that the same content is received |times| number
143   // of times in a row.
144   EXPECT_CALL(recovered_packet_receiver_,
145               OnRecoveredPacket(_, packet.data.size()))
146       .With(
147           Args<0, 1>(ElementsAreArray(packet.data.cdata(), packet.data.size())))
148       .Times(times);
149 }
150 
InjectGarbagePacketLength(size_t fec_garbage_offset)151 void UlpfecReceiverTest::InjectGarbagePacketLength(size_t fec_garbage_offset) {
152   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _));
153 
154   const size_t kNumFecPackets = 1;
155   std::list<AugmentedPacket*> augmented_media_packets;
156   ForwardErrorCorrection::PacketList media_packets;
157   PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
158   std::list<ForwardErrorCorrection::Packet*> fec_packets;
159   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
160   ByteWriter<uint16_t>::WriteBigEndian(
161       &fec_packets.front()->data[fec_garbage_offset], 0x4711);
162 
163   // Inject first media packet, then first FEC packet, skipping the second media
164   // packet to cause a recovery from the FEC packet.
165   BuildAndAddRedMediaPacket(augmented_media_packets.front());
166   BuildAndAddRedFecPacket(fec_packets.front());
167   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
168 
169   FecPacketCounter counter = receiver_fec_->GetPacketCounter();
170   EXPECT_EQ(2U, counter.num_packets);
171   EXPECT_EQ(1U, counter.num_fec_packets);
172   EXPECT_EQ(0U, counter.num_recovered_packets);
173 }
174 
SurvivesMaliciousPacket(const uint8_t * data,size_t length,uint8_t ulpfec_payload_type)175 void UlpfecReceiverTest::SurvivesMaliciousPacket(const uint8_t* data,
176                                                  size_t length,
177                                                  uint8_t ulpfec_payload_type) {
178   NullRecoveredPacketReceiver null_callback;
179   std::unique_ptr<UlpfecReceiver> receiver_fec(
180       UlpfecReceiver::Create(kMediaSsrc, &null_callback, {}));
181 
182   RtpPacketReceived rtp_packet;
183   ASSERT_TRUE(rtp_packet.Parse(data, length));
184   receiver_fec->AddReceivedRedPacket(rtp_packet, ulpfec_payload_type);
185 }
186 
TEST_F(UlpfecReceiverTest,TwoMediaOneFec)187 TEST_F(UlpfecReceiverTest, TwoMediaOneFec) {
188   constexpr size_t kNumFecPackets = 1u;
189   std::list<AugmentedPacket*> augmented_media_packets;
190   ForwardErrorCorrection::PacketList media_packets;
191   PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
192   std::list<ForwardErrorCorrection::Packet*> fec_packets;
193   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
194 
195   FecPacketCounter counter = receiver_fec_->GetPacketCounter();
196   EXPECT_EQ(0u, counter.num_packets);
197   EXPECT_EQ(-1, counter.first_packet_time_ms);
198 
199   // Recovery
200   auto it = augmented_media_packets.begin();
201   BuildAndAddRedMediaPacket(*it);
202   VerifyReconstructedMediaPacket(**it, 1);
203   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
204   counter = receiver_fec_->GetPacketCounter();
205   EXPECT_EQ(1u, counter.num_packets);
206   EXPECT_EQ(0u, counter.num_fec_packets);
207   EXPECT_EQ(0u, counter.num_recovered_packets);
208   const int64_t first_packet_time_ms = counter.first_packet_time_ms;
209   EXPECT_NE(-1, first_packet_time_ms);
210 
211   // Drop one media packet.
212   auto fec_it = fec_packets.begin();
213   BuildAndAddRedFecPacket(*fec_it);
214   ++it;
215   VerifyReconstructedMediaPacket(**it, 1);
216   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
217 
218   counter = receiver_fec_->GetPacketCounter();
219   EXPECT_EQ(2u, counter.num_packets);
220   EXPECT_EQ(1u, counter.num_fec_packets);
221   EXPECT_EQ(1u, counter.num_recovered_packets);
222   EXPECT_EQ(first_packet_time_ms, counter.first_packet_time_ms);
223 }
224 
TEST_F(UlpfecReceiverTest,TwoMediaOneFecNotUsesRecoveredPackets)225 TEST_F(UlpfecReceiverTest, TwoMediaOneFecNotUsesRecoveredPackets) {
226   constexpr size_t kNumFecPackets = 1u;
227   std::list<AugmentedPacket*> augmented_media_packets;
228   ForwardErrorCorrection::PacketList media_packets;
229   PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
230   std::list<ForwardErrorCorrection::Packet*> fec_packets;
231   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
232 
233   FecPacketCounter counter = receiver_fec_->GetPacketCounter();
234   EXPECT_EQ(0u, counter.num_packets);
235   EXPECT_EQ(-1, counter.first_packet_time_ms);
236 
237   // Recovery
238   auto it = augmented_media_packets.begin();
239   BuildAndAddRedMediaPacket(*it, /*is_recovered=*/true);
240   VerifyReconstructedMediaPacket(**it, 1);
241   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
242   counter = receiver_fec_->GetPacketCounter();
243   EXPECT_EQ(1u, counter.num_packets);
244   EXPECT_EQ(0u, counter.num_fec_packets);
245   EXPECT_EQ(0u, counter.num_recovered_packets);
246   const int64_t first_packet_time_ms = counter.first_packet_time_ms;
247   EXPECT_NE(-1, first_packet_time_ms);
248 
249   // Drop one media packet.
250   auto fec_it = fec_packets.begin();
251   BuildAndAddRedFecPacket(*fec_it);
252   ++it;
253   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
254 
255   counter = receiver_fec_->GetPacketCounter();
256   EXPECT_EQ(2u, counter.num_packets);
257   EXPECT_EQ(1u, counter.num_fec_packets);
258   EXPECT_EQ(0u, counter.num_recovered_packets);
259   EXPECT_EQ(first_packet_time_ms, counter.first_packet_time_ms);
260 }
261 
TEST_F(UlpfecReceiverTest,InjectGarbageFecHeaderLengthRecovery)262 TEST_F(UlpfecReceiverTest, InjectGarbageFecHeaderLengthRecovery) {
263   // Byte offset 8 is the 'length recovery' field of the FEC header.
264   InjectGarbagePacketLength(8);
265 }
266 
TEST_F(UlpfecReceiverTest,InjectGarbageFecLevelHeaderProtectionLength)267 TEST_F(UlpfecReceiverTest, InjectGarbageFecLevelHeaderProtectionLength) {
268   // Byte offset 10 is the 'protection length' field in the first FEC level
269   // header.
270   InjectGarbagePacketLength(10);
271 }
272 
TEST_F(UlpfecReceiverTest,TwoMediaTwoFec)273 TEST_F(UlpfecReceiverTest, TwoMediaTwoFec) {
274   const size_t kNumFecPackets = 2;
275   std::list<AugmentedPacket*> augmented_media_packets;
276   ForwardErrorCorrection::PacketList media_packets;
277   PacketizeFrame(2, 0, &augmented_media_packets, &media_packets);
278   std::list<ForwardErrorCorrection::Packet*> fec_packets;
279   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
280 
281   // Recovery
282   // Drop both media packets.
283   auto it = augmented_media_packets.begin();
284   auto fec_it = fec_packets.begin();
285   BuildAndAddRedFecPacket(*fec_it);
286   VerifyReconstructedMediaPacket(**it, 1);
287   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
288   ++fec_it;
289   BuildAndAddRedFecPacket(*fec_it);
290   ++it;
291   VerifyReconstructedMediaPacket(**it, 1);
292   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
293 }
294 
TEST_F(UlpfecReceiverTest,TwoFramesOneFec)295 TEST_F(UlpfecReceiverTest, TwoFramesOneFec) {
296   const size_t kNumFecPackets = 1;
297   std::list<AugmentedPacket*> augmented_media_packets;
298   ForwardErrorCorrection::PacketList media_packets;
299   PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
300   PacketizeFrame(1, 1, &augmented_media_packets, &media_packets);
301   std::list<ForwardErrorCorrection::Packet*> fec_packets;
302   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
303 
304   // Recovery
305   auto it = augmented_media_packets.begin();
306   BuildAndAddRedMediaPacket(augmented_media_packets.front());
307   VerifyReconstructedMediaPacket(**it, 1);
308   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
309   // Drop one media packet.
310   BuildAndAddRedFecPacket(fec_packets.front());
311   ++it;
312   VerifyReconstructedMediaPacket(**it, 1);
313   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
314 }
315 
TEST_F(UlpfecReceiverTest,OneCompleteOneUnrecoverableFrame)316 TEST_F(UlpfecReceiverTest, OneCompleteOneUnrecoverableFrame) {
317   const size_t kNumFecPackets = 1;
318   std::list<AugmentedPacket*> augmented_media_packets;
319   ForwardErrorCorrection::PacketList media_packets;
320   PacketizeFrame(1, 0, &augmented_media_packets, &media_packets);
321   PacketizeFrame(2, 1, &augmented_media_packets, &media_packets);
322 
323   std::list<ForwardErrorCorrection::Packet*> fec_packets;
324   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
325 
326   // Recovery
327   auto it = augmented_media_packets.begin();
328   BuildAndAddRedMediaPacket(*it);  // First frame: one packet.
329   VerifyReconstructedMediaPacket(**it, 1);
330   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
331   ++it;
332   BuildAndAddRedMediaPacket(*it);  // First packet of second frame.
333   VerifyReconstructedMediaPacket(**it, 1);
334   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
335 }
336 
TEST_F(UlpfecReceiverTest,MaxFramesOneFec)337 TEST_F(UlpfecReceiverTest, MaxFramesOneFec) {
338   const size_t kNumFecPackets = 1;
339   const size_t kNumMediaPackets = 48;
340   std::list<AugmentedPacket*> augmented_media_packets;
341   ForwardErrorCorrection::PacketList media_packets;
342   for (size_t i = 0; i < kNumMediaPackets; ++i) {
343     PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
344   }
345   std::list<ForwardErrorCorrection::Packet*> fec_packets;
346   EncodeFec(media_packets, kNumFecPackets, &fec_packets);
347 
348   // Recovery
349   auto it = augmented_media_packets.begin();
350   ++it;  // Drop first packet.
351   for (; it != augmented_media_packets.end(); ++it) {
352     BuildAndAddRedMediaPacket(*it);
353     VerifyReconstructedMediaPacket(**it, 1);
354     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
355   }
356   BuildAndAddRedFecPacket(fec_packets.front());
357   it = augmented_media_packets.begin();
358   VerifyReconstructedMediaPacket(**it, 1);
359   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
360 }
361 
TEST_F(UlpfecReceiverTest,TooManyFrames)362 TEST_F(UlpfecReceiverTest, TooManyFrames) {
363   const size_t kNumFecPackets = 1;
364   const size_t kNumMediaPackets = 49;
365   std::list<AugmentedPacket*> augmented_media_packets;
366   ForwardErrorCorrection::PacketList media_packets;
367   for (size_t i = 0; i < kNumMediaPackets; ++i) {
368     PacketizeFrame(1, i, &augmented_media_packets, &media_packets);
369   }
370   std::list<ForwardErrorCorrection::Packet*> fec_packets;
371   EXPECT_EQ(-1, fec_->EncodeFec(media_packets,
372                                 kNumFecPackets * 255 / kNumMediaPackets, 0,
373                                 false, kFecMaskBursty, &fec_packets));
374 }
375 
TEST_F(UlpfecReceiverTest,PacketNotDroppedTooEarly)376 TEST_F(UlpfecReceiverTest, PacketNotDroppedTooEarly) {
377   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
378   // Delay the FEC packet.
379   Packet* delayed_fec = nullptr;
380   const size_t kNumFecPacketsBatch1 = 1;
381   const size_t kNumMediaPacketsBatch1 = 2;
382   std::list<AugmentedPacket*> augmented_media_packets_batch1;
383   ForwardErrorCorrection::PacketList media_packets_batch1;
384   PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
385                  &media_packets_batch1);
386   std::list<ForwardErrorCorrection::Packet*> fec_packets;
387   EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
388 
389   BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
390   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
391   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
392   delayed_fec = fec_packets.front();
393 
394   // Fill the FEC decoder. No packets should be dropped.
395   const size_t kNumMediaPacketsBatch2 = 46;
396   std::list<AugmentedPacket*> augmented_media_packets_batch2;
397   ForwardErrorCorrection::PacketList media_packets_batch2;
398   for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
399     PacketizeFrame(1, i, &augmented_media_packets_batch2,
400                    &media_packets_batch2);
401   }
402   for (auto it = augmented_media_packets_batch2.begin();
403        it != augmented_media_packets_batch2.end(); ++it) {
404     BuildAndAddRedMediaPacket(*it);
405     EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
406     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
407   }
408 
409   // Add the delayed FEC packet. One packet should be reconstructed.
410   BuildAndAddRedFecPacket(delayed_fec);
411   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
412   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
413 }
414 
TEST_F(UlpfecReceiverTest,PacketDroppedWhenTooOld)415 TEST_F(UlpfecReceiverTest, PacketDroppedWhenTooOld) {
416   // 1 frame with 2 media packets and one FEC packet. One media packet missing.
417   // Delay the FEC packet.
418   Packet* delayed_fec = nullptr;
419   const size_t kNumFecPacketsBatch1 = 1;
420   const size_t kNumMediaPacketsBatch1 = 2;
421   std::list<AugmentedPacket*> augmented_media_packets_batch1;
422   ForwardErrorCorrection::PacketList media_packets_batch1;
423   PacketizeFrame(kNumMediaPacketsBatch1, 0, &augmented_media_packets_batch1,
424                  &media_packets_batch1);
425   std::list<ForwardErrorCorrection::Packet*> fec_packets;
426   EncodeFec(media_packets_batch1, kNumFecPacketsBatch1, &fec_packets);
427 
428   BuildAndAddRedMediaPacket(augmented_media_packets_batch1.front());
429   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
430   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
431   delayed_fec = fec_packets.front();
432 
433   // Fill the FEC decoder and force the last packet to be dropped.
434   const size_t kNumMediaPacketsBatch2 = 48;
435   std::list<AugmentedPacket*> augmented_media_packets_batch2;
436   ForwardErrorCorrection::PacketList media_packets_batch2;
437   for (size_t i = 0; i < kNumMediaPacketsBatch2; ++i) {
438     PacketizeFrame(1, i, &augmented_media_packets_batch2,
439                    &media_packets_batch2);
440   }
441   for (auto it = augmented_media_packets_batch2.begin();
442        it != augmented_media_packets_batch2.end(); ++it) {
443     BuildAndAddRedMediaPacket(*it);
444     EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
445     EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
446   }
447 
448   // Add the delayed FEC packet. No packet should be reconstructed since the
449   // first media packet of that frame has been dropped due to being too old.
450   BuildAndAddRedFecPacket(delayed_fec);
451   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
452   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
453 }
454 
TEST_F(UlpfecReceiverTest,OldFecPacketDropped)455 TEST_F(UlpfecReceiverTest, OldFecPacketDropped) {
456   // 49 frames with 2 media packets and one FEC packet. All media packets
457   // missing.
458   const size_t kNumMediaPackets = 49 * 2;
459   std::list<AugmentedPacket*> augmented_media_packets;
460   ForwardErrorCorrection::PacketList media_packets;
461   for (size_t i = 0; i < kNumMediaPackets / 2; ++i) {
462     std::list<AugmentedPacket*> frame_augmented_media_packets;
463     ForwardErrorCorrection::PacketList frame_media_packets;
464     std::list<ForwardErrorCorrection::Packet*> fec_packets;
465     PacketizeFrame(2, 0, &frame_augmented_media_packets, &frame_media_packets);
466     EncodeFec(frame_media_packets, 1, &fec_packets);
467     for (auto it = fec_packets.begin(); it != fec_packets.end(); ++it) {
468       // Only FEC packets inserted. No packets recoverable at this time.
469       BuildAndAddRedFecPacket(*it);
470       EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(0);
471       EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
472     }
473     // Move unique_ptr's to media_packets for lifetime management.
474     media_packets.insert(media_packets.end(),
475                          std::make_move_iterator(frame_media_packets.begin()),
476                          std::make_move_iterator(frame_media_packets.end()));
477     augmented_media_packets.insert(augmented_media_packets.end(),
478                                    frame_augmented_media_packets.begin(),
479                                    frame_augmented_media_packets.end());
480   }
481   // Insert the oldest media packet. The corresponding FEC packet is too old
482   // and should have been dropped. Only the media packet we inserted will be
483   // returned.
484   BuildAndAddRedMediaPacket(augmented_media_packets.front());
485   EXPECT_CALL(recovered_packet_receiver_, OnRecoveredPacket(_, _)).Times(1);
486   EXPECT_EQ(0, receiver_fec_->ProcessReceivedFec());
487 }
488 
TEST_F(UlpfecReceiverTest,TruncatedPacketWithFBitSet)489 TEST_F(UlpfecReceiverTest, TruncatedPacketWithFBitSet) {
490   const uint8_t kTruncatedPacket[] = {0x80, 0x2a, 0x68, 0x71, 0x29, 0xa1, 0x27,
491                                       0x3a, 0x29, 0x12, 0x2a, 0x98, 0xe0, 0x29};
492 
493   SurvivesMaliciousPacket(kTruncatedPacket, sizeof(kTruncatedPacket), 100);
494 }
495 
TEST_F(UlpfecReceiverTest,TruncatedPacketWithFBitSetEndingAfterFirstRedHeader)496 TEST_F(UlpfecReceiverTest,
497        TruncatedPacketWithFBitSetEndingAfterFirstRedHeader) {
498   const uint8_t kPacket[] = {
499       0x89, 0x27, 0x3a, 0x83, 0x27, 0x3a, 0x3a, 0xf3, 0x67, 0xbe, 0x2a,
500       0xa9, 0x27, 0x54, 0x3a, 0x3a, 0x2a, 0x67, 0x3a, 0xf3, 0x67, 0xbe,
501       0x2a, 0x27, 0xe6, 0xf6, 0x03, 0x3e, 0x29, 0x27, 0x21, 0x27, 0x2a,
502       0x29, 0x21, 0x4b, 0x29, 0x3a, 0x28, 0x29, 0xbf, 0x29, 0x2a, 0x26,
503       0x29, 0xae, 0x27, 0xa6, 0xf6, 0x00, 0x03, 0x3e};
504   SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
505 }
506 
TEST_F(UlpfecReceiverTest,TruncatedPacketWithoutDataPastFirstBlock)507 TEST_F(UlpfecReceiverTest, TruncatedPacketWithoutDataPastFirstBlock) {
508   const uint8_t kPacket[] = {
509       0x82, 0x38, 0x92, 0x38, 0x92, 0x38, 0xde, 0x2a, 0x11, 0xc8, 0xa3, 0xc4,
510       0x82, 0x38, 0x2a, 0x21, 0x2a, 0x28, 0x92, 0x38, 0x92, 0x00, 0x00, 0x0a,
511       0x3a, 0xc8, 0xa3, 0x3a, 0x27, 0xc4, 0x2a, 0x21, 0x2a, 0x28};
512   SurvivesMaliciousPacket(kPacket, sizeof(kPacket), 100);
513 }
514 
515 }  // namespace webrtc
516