/* * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef API_TEST_SIMULATED_NETWORK_H_ #define API_TEST_SIMULATED_NETWORK_H_ #include #include #include #include #include #include "absl/types/optional.h" #include "rtc_base/random.h" #include "rtc_base/thread_annotations.h" namespace webrtc { struct PacketInFlightInfo { PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id) : size(size), send_time_us(send_time_us), packet_id(packet_id) {} size_t size; int64_t send_time_us; // Unique identifier for the packet in relation to other packets in flight. uint64_t packet_id; }; struct PacketDeliveryInfo { static constexpr int kNotReceived = -1; PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us) : receive_time_us(receive_time_us), packet_id(source.packet_id) {} bool operator==(const PacketDeliveryInfo& other) const { return receive_time_us == other.receive_time_us && packet_id == other.packet_id; } int64_t receive_time_us; uint64_t packet_id; }; // BuiltInNetworkBehaviorConfig is a built-in network behavior configuration // for built-in network behavior that will be used by WebRTC if no custom // NetworkBehaviorInterface is provided. struct BuiltInNetworkBehaviorConfig { // Queue length in number of packets. size_t queue_length_packets = 0; // Delay in addition to capacity induced delay. int queue_delay_ms = 0; // Standard deviation of the extra delay. int delay_standard_deviation_ms = 0; // Link capacity in kbps. int link_capacity_kbps = 0; // Random packet loss. int loss_percent = 0; // If packets are allowed to be reordered. bool allow_reordering = false; // The average length of a burst of lost packets. int avg_burst_loss_length = -1; // Additional bytes to add to packet size. int packet_overhead = 0; }; // Interface that represents a Network behaviour. // // It is clients of this interface responsibility to enqueue and dequeue // packets (based on the estimated delivery time expressed by // NextDeliveryTimeUs). // // To enqueue packets, call EnqueuePacket: // EXPECT_TRUE(network.EnqueuePacket( // PacketInFlightInfo(/*size=*/1, /*send_time_us=*/0, /*packet_id=*/1))); // // To know when to call DequeueDeliverablePackets to pull packets out of the // network, call NextDeliveryTimeUs and schedule a task to invoke // DequeueDeliverablePackets (if not already scheduled). // // DequeueDeliverablePackets will return a vector of delivered packets, but this // vector can be empty in case of extra delay. In such case, make sure to invoke // NextDeliveryTimeUs and schedule a task to call DequeueDeliverablePackets for // the next estimated delivery of packets. // // std::vector delivered_packets = // network.DequeueDeliverablePackets(/*receive_time_us=*/1000000); class NetworkBehaviorInterface { public: // Enqueues a packet in the network and returns true if the action was // successful, false otherwise (for example, because the network capacity has // been saturated). If the return value is false, the packet should be // considered as dropped and it will not be returned by future calls // to DequeueDeliverablePackets. // Packets enqueued will exit the network when DequeueDeliverablePackets is // called and enough time has passed (see NextDeliveryTimeUs). virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0; // Retrieves all packets that should be delivered by the given receive time. // Not all the packets in the returned std::vector are actually delivered. // In order to know the state of each packet it is necessary to check the // `receive_time_us` field of each packet. If that is set to // PacketDeliveryInfo::kNotReceived then the packet is considered lost in the // network. virtual std::vector DequeueDeliverablePackets( int64_t receive_time_us) = 0; // Returns time in microseconds when caller should call // DequeueDeliverablePackets to get the next set of delivered packets. It is // possible that no packet will be delivered by that time (e.g. in case of // random extra delay), in such case this method should be called again to get // the updated estimated delivery time. virtual absl::optional NextDeliveryTimeUs() const = 0; virtual ~NetworkBehaviorInterface() = default; }; // Class simulating a network link. This is a simple and naive solution just // faking capacity and adding an extra transport delay in addition to the // capacity introduced delay. class SimulatedNetworkInterface : public NetworkBehaviorInterface { public: // Sets a new configuration. virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0; virtual void UpdateConfig( std::function config_modifier) = 0; // Pauses the network until `until_us`. This affects both delivery (calling // DequeueDeliverablePackets before `until_us` results in an empty std::vector // of packets) and capacity (the network is paused, so packets are not // flowing and they will restart flowing at `until_us`). virtual void PauseTransmissionUntil(int64_t until_us) = 0; }; } // namespace webrtc #endif // API_TEST_SIMULATED_NETWORK_H_