1 /* 2 * Copyright (c) 2018 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 API_TEST_SIMULATED_NETWORK_H_ 12 #define API_TEST_SIMULATED_NETWORK_H_ 13 14 #include <stddef.h> 15 #include <stdint.h> 16 17 #include <deque> 18 #include <queue> 19 #include <vector> 20 21 #include "absl/types/optional.h" 22 #include "rtc_base/random.h" 23 #include "rtc_base/thread_annotations.h" 24 25 namespace webrtc { 26 27 struct PacketInFlightInfo { PacketInFlightInfoPacketInFlightInfo28 PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id) 29 : size(size), send_time_us(send_time_us), packet_id(packet_id) {} 30 31 size_t size; 32 int64_t send_time_us; 33 // Unique identifier for the packet in relation to other packets in flight. 34 uint64_t packet_id; 35 }; 36 37 struct PacketDeliveryInfo { 38 static constexpr int kNotReceived = -1; PacketDeliveryInfoPacketDeliveryInfo39 PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us) 40 : receive_time_us(receive_time_us), packet_id(source.packet_id) {} 41 42 bool operator==(const PacketDeliveryInfo& other) const { 43 return receive_time_us == other.receive_time_us && 44 packet_id == other.packet_id; 45 } 46 47 int64_t receive_time_us; 48 uint64_t packet_id; 49 }; 50 51 // BuiltInNetworkBehaviorConfig is a built-in network behavior configuration 52 // for built-in network behavior that will be used by WebRTC if no custom 53 // NetworkBehaviorInterface is provided. 54 struct BuiltInNetworkBehaviorConfig { 55 // Queue length in number of packets. 56 size_t queue_length_packets = 0; 57 // Delay in addition to capacity induced delay. 58 int queue_delay_ms = 0; 59 // Standard deviation of the extra delay. 60 int delay_standard_deviation_ms = 0; 61 // Link capacity in kbps. 62 int link_capacity_kbps = 0; 63 // Random packet loss. 64 int loss_percent = 0; 65 // If packets are allowed to be reordered. 66 bool allow_reordering = false; 67 // The average length of a burst of lost packets. 68 int avg_burst_loss_length = -1; 69 // Additional bytes to add to packet size. 70 int packet_overhead = 0; 71 }; 72 73 // Interface that represents a Network behaviour. 74 // 75 // It is clients of this interface responsibility to enqueue and dequeue 76 // packets (based on the estimated delivery time expressed by 77 // NextDeliveryTimeUs). 78 // 79 // To enqueue packets, call EnqueuePacket: 80 // EXPECT_TRUE(network.EnqueuePacket( 81 // PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/1))); 82 // 83 // To know when to call DequeueDeliverablePackets to pull packets out of the 84 // network, call NextDeliveryTimeUs and schedule a task to invoke 85 // DequeueDeliverablePackets (if not already scheduled). 86 // 87 // DequeueDeliverablePackets will return a vector of delivered packets, but this 88 // vector can be empty in case of extra delay. In such case, make sure to invoke 89 // NextDeliveryTimeUs and schedule a task to call DequeueDeliverablePackets for 90 // the next estimated delivery of packets. 91 // 92 // std::vector<PacketDeliveryInfo> delivered_packets = 93 // network.DequeueDeliverablePackets(/*receive_time_us=*/1000000); 94 class NetworkBehaviorInterface { 95 public: 96 // Enqueues a packet in the network and returns true if the action was 97 // successful, false otherwise (for example, because the network capacity has 98 // been saturated). If the return value is false, the packet should be 99 // considered as dropped and it will not be returned by future calls 100 // to DequeueDeliverablePackets. 101 // Packets enqueued will exit the network when DequeueDeliverablePackets is 102 // called and enough time has passed (see NextDeliveryTimeUs). 103 virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0; 104 // Retrieves all packets that should be delivered by the given receive time. 105 // Not all the packets in the returned std::vector are actually delivered. 106 // In order to know the state of each packet it is necessary to check the 107 // `receive_time_us` field of each packet. If that is set to 108 // PacketDeliveryInfo::kNotReceived then the packet is considered lost in the 109 // network. 110 virtual std::vector<PacketDeliveryInfo> DequeueDeliverablePackets( 111 int64_t receive_time_us) = 0; 112 // Returns time in microseconds when caller should call 113 // DequeueDeliverablePackets to get the next set of delivered packets. It is 114 // possible that no packet will be delivered by that time (e.g. in case of 115 // random extra delay), in such case this method should be called again to get 116 // the updated estimated delivery time. 117 virtual absl::optional<int64_t> NextDeliveryTimeUs() const = 0; 118 virtual ~NetworkBehaviorInterface() = default; 119 }; 120 121 // Class simulating a network link. This is a simple and naive solution just 122 // faking capacity and adding an extra transport delay in addition to the 123 // capacity introduced delay. 124 class SimulatedNetworkInterface : public NetworkBehaviorInterface { 125 public: 126 // Sets a new configuration. 127 virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0; 128 virtual void UpdateConfig( 129 std::function<void(BuiltInNetworkBehaviorConfig*)> config_modifier) = 0; 130 // Pauses the network until `until_us`. This affects both delivery (calling 131 // DequeueDeliverablePackets before `until_us` results in an empty std::vector 132 // of packets) and capacity (the network is paused, so packets are not 133 // flowing and they will restart flowing at `until_us`). 134 virtual void PauseTransmissionUntil(int64_t until_us) = 0; 135 }; 136 137 } // namespace webrtc 138 139 #endif // API_TEST_SIMULATED_NETWORK_H_ 140