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