blob: 8597367addf4be7b26f67bb0fcd6f27222d30f5c [file] [log] [blame]
/*
* 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 CALL_SIMULATED_NETWORK_H_
#define CALL_SIMULATED_NETWORK_H_
#include <stdint.h>
#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/data_size.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
// - Extra delay with or without packets reorder
// - Packet overhead
// - Queue max capacity
class 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.
// TODO(bugs.webrtc.org/14525): Fix SetConfig and make it apply only to the
// part of the packet that is currently being sent (instead of applying to
// all of it).
void SetConfig(const Config& config) override;
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;
private:
struct PacketInfo {
PacketInFlightInfo packet;
// Time when the packet has left (or will leave) the network.
int64_t arrival_time_us;
};
// 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;
};
// Moves packets from capacity- to delay link.
void UpdateCapacityQueue(ConfigState state, int64_t time_now_us)
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_us 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_us).
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).
absl::optional<int64_t> next_process_time_us_
RTC_GUARDED_BY(process_checker_);
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).
int64_t last_capacity_link_exit_time_;
};
} // namespace webrtc
#endif // CALL_SIMULATED_NETWORK_H_