Source code

Revision control

Copy as Markdown

Other Tools

/*
* Copyright 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 TEST_NETWORK_SIMULATED_NETWORK_H_
#define TEST_NETWORK_SIMULATED_NETWORK_H_
#include <stdint.h>
#include <cstdint>
#include <deque>
#include <queue>
#include <vector>
#include "absl/types/optional.h"
#include "api/sequence_checker.h"
#include "api/test/simulated_network.h"
#include "api/units/timestamp.h"
#include "rtc_base/race_checker.h"
#include "rtc_base/random.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
// Class simulating a network link.
//
// This is a basic implementation of NetworkBehaviorInterface that supports:
// - Packet loss
// - Capacity delay: Delay caused by a narrow section that only allows one
// packet through at the time with a limited capacity.
// - Extra delay with or without packets reorder
// - Packet overhead
// - Queue max capacity
class RTC_EXPORT SimulatedNetwork : public SimulatedNetworkInterface {
public:
using Config = BuiltInNetworkBehaviorConfig;
explicit SimulatedNetwork(Config config, uint64_t random_seed = 1);
~SimulatedNetwork() override;
// Sets a new configuration. This will affect packets that will be sent with
// EnqueuePacket but also packets in the network that have not left the
// network emulation. Packets that are ready to be retrieved by
// DequeueDeliverablePackets are not affected by the new configuration.
// This method can be invoked directly by tests on any thread/sequence, but is
// less accurate than the version with timestamp since changes to the
// configuration does not take affect until the time returned by
// NextDeliveryTimeUs has passed.
void SetConfig(const Config& config) override;
// Updates the configuration at a specific time.
// Note that packets that have already passed the narrow section constrained
// by link capacity will not be affected by the change. If packet re-ordering
// is not allowed, packets with new shorter queue delays will arrive
// immediately after packets with the old, longer queue delays. Must be
// invoked on the same sequence as other methods in NetworkBehaviorInterface.
void SetConfig(const BuiltInNetworkBehaviorConfig& config,
Timestamp config_update_time);
void UpdateConfig(std::function<void(BuiltInNetworkBehaviorConfig*)>
config_modifier) override;
void PauseTransmissionUntil(int64_t until_us) override;
// NetworkBehaviorInterface
bool EnqueuePacket(PacketInFlightInfo packet) override;
std::vector<PacketDeliveryInfo> DequeueDeliverablePackets(
int64_t receive_time_us) override;
absl::optional<int64_t> NextDeliveryTimeUs() const override;
void RegisterDeliveryTimeChangedCallback(
absl::AnyInvocable<void()> callback) override;
private:
struct PacketInfo {
PacketInFlightInfo packet;
// Time the packet was last updated by the capacity link.
Timestamp last_update_time;
// Size of the packet left to send through the capacity link. May differ
// from the packet size if the link capacity changes while the packet is in
// the capacity link.
int64_t bits_left_to_send;
// Time when the packet has left (or will leave) the network.
Timestamp arrival_time;
};
// Contains current configuration state.
struct ConfigState {
// Static link configuration.
Config config;
// The probability to drop the packet if we are currently dropping a
// burst of packet
double prob_loss_bursting;
// The probability to drop a burst of packets.
double prob_start_bursting;
// Used for temporary delay spikes.
int64_t pause_transmission_until_us = 0;
};
// Calculates next_process_time_. Returns true if changed.
bool UpdateNextProcessTime() RTC_RUN_ON(&process_checker_);
// Moves packets from capacity- to delay link.
// If `previouse_config` is set, it is the config that was used until
// `time_now_us`
void UpdateCapacityQueue(ConfigState state, Timestamp time_now)
RTC_RUN_ON(&process_checker_);
ConfigState GetConfigState() const;
mutable Mutex config_lock_;
// Guards the data structures involved in delay and loss processing, such as
// the packet queues.
rtc::RaceChecker process_checker_;
// Models the capacity of the network by rejecting packets if the queue is
// full and keeping them in the queue until they are ready to exit (according
// to the link capacity, which cannot be violated, e.g. a 1 kbps link will
// only be able to deliver 1000 bits per second).
//
// Invariant:
// The head of the `capacity_link_` has arrival_time correctly set to the
// time when the packet is supposed to be delivered (without accounting
// potential packet loss or potential extra delay and without accounting for a
// new configuration of the network, which requires a re-computation of the
// arrival_time).
std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_checker_);
// Models the extra delay of the network (see `queue_delay_ms`
// and `delay_standard_deviation_ms` in BuiltInNetworkBehaviorConfig), packets
// in the `delay_link_` have technically already left the network and don't
// use its capacity but they are not delivered yet.
std::deque<PacketInfo> delay_link_ RTC_GUARDED_BY(process_checker_);
// Represents the next moment in time when the network is supposed to deliver
// packets to the client (either by pulling them from `delay_link_` or
// `capacity_link_` or both).
Timestamp next_process_time_ RTC_GUARDED_BY(process_checker_) =
Timestamp::PlusInfinity();
absl::AnyInvocable<void()> next_process_time_changed_callback_
RTC_GUARDED_BY(process_checker_) = nullptr;
ConfigState config_state_ RTC_GUARDED_BY(config_lock_);
Random random_ RTC_GUARDED_BY(process_checker_);
// Are we currently dropping a burst of packets?
bool bursting_;
// The send time of the last enqueued packet, this is only used to check that
// the send time of enqueued packets is monotonically increasing.
int64_t last_enqueue_time_us_;
// The last time a packet left the capacity_link_ (used to enforce
// the capacity of the link and avoid packets starts to get sent before
// the link it free).
Timestamp last_capacity_link_exit_time_ = Timestamp::MinusInfinity();
};
} // namespace webrtc
#endif // TEST_NETWORK_SIMULATED_NETWORK_H_