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 #ifndef WEBRTC_TEST_FAKE_NETWORK_PIPE_H_ 12 #define WEBRTC_TEST_FAKE_NETWORK_PIPE_H_ 13 14 #include <memory> 15 #include <set> 16 #include <string.h> 17 #include <queue> 18 19 #include "webrtc/base/constructormagic.h" 20 #include "webrtc/base/criticalsection.h" 21 #include "webrtc/base/random.h" 22 #include "webrtc/typedefs.h" 23 24 namespace webrtc { 25 26 class Clock; 27 class CriticalSectionWrapper; 28 class PacketReceiver; 29 30 class NetworkPacket { 31 public: NetworkPacket(const uint8_t * data,size_t length,int64_t send_time,int64_t arrival_time)32 NetworkPacket(const uint8_t* data, 33 size_t length, 34 int64_t send_time, 35 int64_t arrival_time) 36 : data_(new uint8_t[length]), 37 data_length_(length), 38 send_time_(send_time), 39 arrival_time_(arrival_time) { 40 memcpy(data_.get(), data, length); 41 } 42 data()43 uint8_t* data() const { return data_.get(); } data_length()44 size_t data_length() const { return data_length_; } send_time()45 int64_t send_time() const { return send_time_; } arrival_time()46 int64_t arrival_time() const { return arrival_time_; } IncrementArrivalTime(int64_t extra_delay)47 void IncrementArrivalTime(int64_t extra_delay) { 48 arrival_time_ += extra_delay; 49 } 50 51 private: 52 // The packet data. 53 std::unique_ptr<uint8_t[]> data_; 54 // Length of data_. 55 size_t data_length_; 56 // The time the packet was sent out on the network. 57 const int64_t send_time_; 58 // The time the packet should arrive at the receiver. 59 int64_t arrival_time_; 60 }; 61 62 // Class faking a network link. This is a simple and naive solution just faking 63 // capacity and adding an extra transport delay in addition to the capacity 64 // introduced delay. 65 66 class FakeNetworkPipe { 67 public: 68 struct Config { ConfigConfig69 Config() {} 70 // Queue length in number of packets. 71 size_t queue_length_packets = 0; 72 // Delay in addition to capacity induced delay. 73 int queue_delay_ms = 0; 74 // Standard deviation of the extra delay. 75 int delay_standard_deviation_ms = 0; 76 // Link capacity in kbps. 77 int link_capacity_kbps = 0; 78 // Random packet loss. 79 int loss_percent = 0; 80 // If packets are allowed to be reordered. 81 bool allow_reordering = false; 82 // The average length of a burst of lost packets. 83 int avg_burst_loss_length = -1; 84 }; 85 86 FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config); 87 FakeNetworkPipe(Clock* clock, 88 const FakeNetworkPipe::Config& config, 89 uint64_t seed); 90 ~FakeNetworkPipe(); 91 92 // Must not be called in parallel with SendPacket or Process. 93 void SetReceiver(PacketReceiver* receiver); 94 95 // Sets a new configuration. This won't affect packets already in the pipe. 96 void SetConfig(const FakeNetworkPipe::Config& config); 97 98 // Sends a new packet to the link. 99 void SendPacket(const uint8_t* packet, size_t packet_length); 100 101 // Processes the network queues and trigger PacketReceiver::IncomingPacket for 102 // packets ready to be delivered. 103 void Process(); 104 int64_t TimeUntilNextProcess() const; 105 106 // Get statistics. 107 float PercentageLoss(); 108 int AverageDelay(); dropped_packets()109 size_t dropped_packets() { return dropped_packets_; } sent_packets()110 size_t sent_packets() { return sent_packets_; } 111 112 private: 113 Clock* const clock_; 114 rtc::CriticalSection lock_; 115 PacketReceiver* packet_receiver_; 116 std::queue<NetworkPacket*> capacity_link_; 117 Random random_; 118 119 // Since we need to access both the packet with the earliest and latest 120 // arrival time we need to use a multiset to keep all packets sorted, 121 // hence, we cannot use a priority queue. 122 struct PacketArrivalTimeComparator { operatorPacketArrivalTimeComparator123 bool operator()(const NetworkPacket* p1, const NetworkPacket* p2) { 124 return p1->arrival_time() < p2->arrival_time(); 125 } 126 }; 127 std::multiset<NetworkPacket*, PacketArrivalTimeComparator> delay_link_; 128 129 // Link configuration. 130 Config config_; 131 132 // Statistics. 133 size_t dropped_packets_; 134 size_t sent_packets_; 135 int64_t total_packet_delay_; 136 137 // Are we currently dropping a burst of packets? 138 bool bursting_; 139 140 // The probability to drop the packet if we are currently dropping a 141 // burst of packet 142 double prob_loss_bursting_; 143 144 // The probability to drop a burst of packets. 145 double prob_start_bursting_; 146 147 int64_t next_process_time_; 148 149 RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe); 150 }; 151 152 } // namespace webrtc 153 154 #endif // WEBRTC_TEST_FAKE_NETWORK_PIPE_H_ 155