blob: 799970b9875fee61553349fef04d028ca63bd4d3 [file] [log] [blame]
Erik Språng09708512018-03-14 15:16:50 +01001/*
2 * Copyright (c) 2012 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 CALL_FAKE_NETWORK_PIPE_H_
12#define CALL_FAKE_NETWORK_PIPE_H_
13
14#include <deque>
15#include <map>
16#include <memory>
17#include <queue>
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020018#include <set>
Erik Språng09708512018-03-14 15:16:50 +010019#include <string>
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020020#include <vector>
Erik Språng09708512018-03-14 15:16:50 +010021
22#include "api/call/transport.h"
23#include "call/call.h"
24#include "common_types.h" // NOLINT(build/include)
25#include "modules/include/module.h"
26#include "rtc_base/constructormagic.h"
27#include "rtc_base/criticalsection.h"
28#include "rtc_base/random.h"
29#include "rtc_base/thread_annotations.h"
30#include "typedefs.h" // NOLINT(build/include)
31
32namespace webrtc {
33
34class Clock;
35class PacketReceiver;
36enum class MediaType;
37
38class NetworkPacket {
39 public:
40 NetworkPacket(rtc::CopyOnWriteBuffer packet,
41 int64_t send_time,
42 int64_t arrival_time,
43 rtc::Optional<PacketOptions> packet_options,
44 bool is_rtcp,
45 MediaType media_type_,
46 rtc::Optional<PacketTime> packet_time_);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010047 // Disallow copy constructor and copy assignment (no deep copies of |data_|).
Erik Språng09708512018-03-14 15:16:50 +010048 NetworkPacket(const NetworkPacket&) = delete;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010049 NetworkPacket& operator=(const NetworkPacket&) = delete;
Erik Språng09708512018-03-14 15:16:50 +010050 // Allow move constructor/assignment, so that we can use in stl containers.
51 NetworkPacket(NetworkPacket&&);
52 NetworkPacket& operator=(NetworkPacket&&);
53
54 const uint8_t* data() const { return packet_.data(); }
55 size_t data_length() const { return packet_.size(); }
56 rtc::CopyOnWriteBuffer* raw_packet() { return &packet_; }
57 int64_t send_time() const { return send_time_; }
58 int64_t arrival_time() const { return arrival_time_; }
59 void IncrementArrivalTime(int64_t extra_delay) {
60 arrival_time_ += extra_delay;
61 }
62 PacketOptions packet_options() const {
63 return packet_options_.value_or(PacketOptions());
64 }
65 bool is_rtcp() const { return is_rtcp_; }
66 MediaType media_type() const { return media_type_; }
67 PacketTime packet_time() const { return packet_time_.value_or(PacketTime()); }
68
69 private:
70 rtc::CopyOnWriteBuffer packet_;
71 // The time the packet was sent out on the network.
72 int64_t send_time_;
73 // The time the packet should arrive at the receiver.
74 int64_t arrival_time_;
75 // If using a Transport for outgoing degradation, populate with
76 // PacketOptions (transport-wide sequence number) for RTP.
77 rtc::Optional<PacketOptions> packet_options_;
78 bool is_rtcp_;
79 // If using a PacketReceiver for incoming degradation, populate with
80 // appropriate MediaType and PacketTime. This type/timing will be kept and
81 // forwarded. The PacketTime might be altered to reflect time spent in fake
82 // network pipe.
83 MediaType media_type_;
84 rtc::Optional<PacketTime> packet_time_;
85};
86
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020087struct PacketInFlightInfo {
88 PacketInFlightInfo(size_t size, int64_t send_time_us, uint64_t packet_id)
89 : size(size), send_time_us(send_time_us), packet_id(packet_id) {}
Erik Språng09708512018-03-14 15:16:50 +010090
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020091 size_t size;
92 int64_t send_time_us;
93 // Unique identifier for the packet in relation to other packets in flight.
94 uint64_t packet_id;
95};
Erik Språng09708512018-03-14 15:16:50 +010096
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020097struct PacketDeliveryInfo {
98 static constexpr int kNotReceived = -1;
99 PacketDeliveryInfo(PacketInFlightInfo source, int64_t receive_time_us)
100 : receive_time_us(receive_time_us), packet_id(source.packet_id) {}
101 int64_t receive_time_us;
102 uint64_t packet_id;
103};
104
105class NetworkSimulationInterface {
106 public:
107 virtual bool EnqueuePacket(PacketInFlightInfo packet_info) = 0;
108 // Retrieves all packets that should be delivered by the given receive time.
109 virtual std::vector<PacketDeliveryInfo> DequeueDeliverablePackets(
110 int64_t receive_time_us) = 0;
111 virtual rtc::Optional<int64_t> NextDeliveryTimeUs() const = 0;
112 virtual ~NetworkSimulationInterface() = default;
113};
114
115// Class simulating a network link. This is a simple and naive solution just
116// faking capacity and adding an extra transport delay in addition to the
117// capacity introduced delay.
118class SimulatedNetwork : public NetworkSimulationInterface {
Erik Språng09708512018-03-14 15:16:50 +0100119 public:
120 struct Config {
121 Config() {}
122 // Queue length in number of packets.
123 size_t queue_length_packets = 0;
124 // Delay in addition to capacity induced delay.
125 int queue_delay_ms = 0;
126 // Standard deviation of the extra delay.
127 int delay_standard_deviation_ms = 0;
128 // Link capacity in kbps.
129 int link_capacity_kbps = 0;
130 // Random packet loss.
131 int loss_percent = 0;
132 // If packets are allowed to be reordered.
133 bool allow_reordering = false;
134 // The average length of a burst of lost packets.
135 int avg_burst_loss_length = -1;
136 };
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200137 explicit SimulatedNetwork(Config config, uint64_t random_seed = 1);
138
139 // Sets a new configuration. This won't affect packets already in the pipe.
140 void SetConfig(const Config& config);
141
142 // NetworkSimulationInterface
143 bool EnqueuePacket(PacketInFlightInfo packet) override;
144 std::vector<PacketDeliveryInfo> DequeueDeliverablePackets(
145 int64_t receive_time_us) override;
146
147 rtc::Optional<int64_t> NextDeliveryTimeUs() const override;
148
149 private:
150 struct PacketInfo {
151 PacketInFlightInfo packet;
152 int64_t arrival_time_us;
153 };
154 rtc::CriticalSection config_lock_;
155
156 // |process_lock| guards the data structures involved in delay and loss
157 // processes, such as the packet queues.
158 rtc::CriticalSection process_lock_;
159 std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_lock_);
160 Random random_;
161
162 std::deque<PacketInfo> delay_link_;
163
164 // Link configuration.
165 Config config_ RTC_GUARDED_BY(config_lock_);
166
167 // Are we currently dropping a burst of packets?
168 bool bursting_;
169
170 // The probability to drop the packet if we are currently dropping a
171 // burst of packet
172 double prob_loss_bursting_ RTC_GUARDED_BY(config_lock_);
173
174 // The probability to drop a burst of packets.
175 double prob_start_bursting_ RTC_GUARDED_BY(config_lock_);
176 int64_t capacity_delay_error_bytes_ = 0;
177};
178
179// Class faking a network link, internally is uses an implementation of a
180// SimulatedNetworkInterface to simulate network behavior.
181class FakeNetworkPipe : public Transport, public PacketReceiver, public Module {
182 public:
183 using Config = SimulatedNetwork::Config;
Erik Språng09708512018-03-14 15:16:50 +0100184
Sebastian Jansson09408112018-04-24 14:41:22 +0200185 // Use these constructors if you plan to insert packets using DeliverPacket().
Erik Språng09708512018-03-14 15:16:50 +0100186 FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config);
Erik Språng09708512018-03-14 15:16:50 +0100187 FakeNetworkPipe(Clock* clock,
188 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200189 PacketReceiver* receiver);
Erik Språng09708512018-03-14 15:16:50 +0100190 FakeNetworkPipe(Clock* clock,
191 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200192 PacketReceiver* receiver,
Erik Språng09708512018-03-14 15:16:50 +0100193 uint64_t seed);
194
195 // Use this constructor if you plan to insert packets using SendRt[c?]p().
196 FakeNetworkPipe(Clock* clock,
197 const FakeNetworkPipe::Config& config,
198 Transport* transport);
199
200 virtual ~FakeNetworkPipe();
201
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200202 void SetClockOffset(int64_t offset_ms);
203
Erik Språng09708512018-03-14 15:16:50 +0100204 // Sets a new configuration. This won't affect packets already in the pipe.
205 void SetConfig(const FakeNetworkPipe::Config& config);
206
Sebastian Jansson09408112018-04-24 14:41:22 +0200207 // Must not be called in parallel with DeliverPacket or Process.
Erik Språng09708512018-03-14 15:16:50 +0100208 void SetReceiver(PacketReceiver* receiver);
209
210 // Implements Transport interface. When/if packets are delivered, they will
211 // be passed to the transport instance given in SetReceiverTransport(). These
212 // methods should only be called if a Transport instance was provided in the
213 // constructor.
214 bool SendRtp(const uint8_t* packet,
215 size_t length,
216 const PacketOptions& options) override;
217 bool SendRtcp(const uint8_t* packet, size_t length) override;
218
219 // Implements the PacketReceiver interface. When/if packets are delivered,
220 // they will be passed directly to the receiver instance given in
221 // SetReceiver(), without passing through a Demuxer. The receive time in
222 // PacketTime will be increased by the amount of time the packet spent in the
223 // fake network pipe.
224 PacketReceiver::DeliveryStatus DeliverPacket(
225 MediaType media_type,
226 rtc::CopyOnWriteBuffer packet,
227 const PacketTime& packet_time) override;
228
229 // Processes the network queues and trigger PacketReceiver::IncomingPacket for
230 // packets ready to be delivered.
231 void Process() override;
232 int64_t TimeUntilNextProcess() override;
233
234 // Get statistics.
235 float PercentageLoss();
236 int AverageDelay();
237 size_t DroppedPackets();
238 size_t SentPackets();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100239 void ResetStats();
240
241 protected:
242 void DeliverPacketWithLock(NetworkPacket* packet);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100243 void AddToPacketDropCount();
244 void AddToPacketSentCount(int count);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200245 void AddToTotalDelay(int delay_us);
246 int64_t GetTimeInMicroseconds() const;
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200247 bool ShouldProcess(int64_t time_now_us) const;
248 void SetTimeToNextProcess(int64_t skip_us);
Erik Språng09708512018-03-14 15:16:50 +0100249
250 private:
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200251 struct StoredPacket {
252 NetworkPacket packet;
253 bool removed = false;
254 explicit StoredPacket(NetworkPacket&& packet);
255 StoredPacket(StoredPacket&&) = default;
256 StoredPacket(const StoredPacket&) = delete;
257 StoredPacket& operator=(const StoredPacket&) = delete;
258 StoredPacket() = delete;
259 };
260
Erik Språng09708512018-03-14 15:16:50 +0100261 // Returns true if enqueued, or false if packet was dropped.
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100262 virtual bool EnqueuePacket(rtc::CopyOnWriteBuffer packet,
Erik Språng09708512018-03-14 15:16:50 +0100263 rtc::Optional<PacketOptions> options,
264 bool is_rtcp,
265 MediaType media_type,
266 rtc::Optional<PacketTime> packet_time);
267 void DeliverPacket(NetworkPacket* packet)
268 RTC_EXCLUSIVE_LOCKS_REQUIRED(config_lock_);
269 bool HasTransport() const;
Sebastian Jansson09408112018-04-24 14:41:22 +0200270 bool HasReceiver() const;
Erik Språng09708512018-03-14 15:16:50 +0100271
272 Clock* const clock_;
273 // |config_lock| guards the mostly constant things like the callbacks.
274 rtc::CriticalSection config_lock_;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200275 const std::unique_ptr<SimulatedNetwork> network_simulation_;
Erik Språng09708512018-03-14 15:16:50 +0100276 PacketReceiver* receiver_ RTC_GUARDED_BY(config_lock_);
277 Transport* const transport_ RTC_GUARDED_BY(config_lock_);
278
279 // |process_lock| guards the data structures involved in delay and loss
280 // processes, such as the packet queues.
281 rtc::CriticalSection process_lock_;
Erik Språng09708512018-03-14 15:16:50 +0100282
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200283 // Packets are added at the back of the deque, this makes the deque ordered
284 // by increasing send time. The common case when removing packets from the
285 // deque is removing early packets, which will be close to the front of the
286 // deque. This makes finding the packets in the deque efficient in the common
287 // case.
288 std::deque<StoredPacket> packets_in_flight_ RTC_GUARDED_BY(process_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100289
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200290 int64_t clock_offset_ms_ RTC_GUARDED_BY(config_lock_);
291
Erik Språng09708512018-03-14 15:16:50 +0100292 // Statistics.
293 size_t dropped_packets_ RTC_GUARDED_BY(process_lock_);
294 size_t sent_packets_ RTC_GUARDED_BY(process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200295 int64_t total_packet_delay_us_ RTC_GUARDED_BY(process_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100296
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200297 int64_t next_process_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100298
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200299 int64_t last_log_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100300
Erik Språng09708512018-03-14 15:16:50 +0100301 RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
302};
303
304} // namespace webrtc
305
306#endif // CALL_FAKE_NETWORK_PIPE_H_