blob: 866c5504d6d8f0f97330604a46bbaccc2e9b7213 [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"
Patrik Höglundb6b29e02018-06-21 16:58:01 +020023#include "api/test/simulated_network.h"
Erik Språng09708512018-03-14 15:16:50 +010024#include "call/call.h"
25#include "common_types.h" // NOLINT(build/include)
26#include "modules/include/module.h"
27#include "rtc_base/constructormagic.h"
28#include "rtc_base/criticalsection.h"
29#include "rtc_base/random.h"
30#include "rtc_base/thread_annotations.h"
31#include "typedefs.h" // NOLINT(build/include)
32
33namespace webrtc {
34
35class Clock;
36class PacketReceiver;
37enum class MediaType;
38
39class NetworkPacket {
40 public:
41 NetworkPacket(rtc::CopyOnWriteBuffer packet,
42 int64_t send_time,
43 int64_t arrival_time,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020044 absl::optional<PacketOptions> packet_options,
Erik Språng09708512018-03-14 15:16:50 +010045 bool is_rtcp,
46 MediaType media_type_,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020047 absl::optional<PacketTime> packet_time_);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010048 // Disallow copy constructor and copy assignment (no deep copies of |data_|).
Erik Språng09708512018-03-14 15:16:50 +010049 NetworkPacket(const NetworkPacket&) = delete;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010050 NetworkPacket& operator=(const NetworkPacket&) = delete;
Erik Språng09708512018-03-14 15:16:50 +010051 // Allow move constructor/assignment, so that we can use in stl containers.
52 NetworkPacket(NetworkPacket&&);
53 NetworkPacket& operator=(NetworkPacket&&);
54
55 const uint8_t* data() const { return packet_.data(); }
56 size_t data_length() const { return packet_.size(); }
57 rtc::CopyOnWriteBuffer* raw_packet() { return &packet_; }
58 int64_t send_time() const { return send_time_; }
59 int64_t arrival_time() const { return arrival_time_; }
60 void IncrementArrivalTime(int64_t extra_delay) {
61 arrival_time_ += extra_delay;
62 }
63 PacketOptions packet_options() const {
64 return packet_options_.value_or(PacketOptions());
65 }
66 bool is_rtcp() const { return is_rtcp_; }
67 MediaType media_type() const { return media_type_; }
68 PacketTime packet_time() const { return packet_time_.value_or(PacketTime()); }
69
70 private:
71 rtc::CopyOnWriteBuffer packet_;
72 // The time the packet was sent out on the network.
73 int64_t send_time_;
74 // The time the packet should arrive at the receiver.
75 int64_t arrival_time_;
76 // If using a Transport for outgoing degradation, populate with
77 // PacketOptions (transport-wide sequence number) for RTP.
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020078 absl::optional<PacketOptions> packet_options_;
Erik Språng09708512018-03-14 15:16:50 +010079 bool is_rtcp_;
80 // If using a PacketReceiver for incoming degradation, populate with
81 // appropriate MediaType and PacketTime. This type/timing will be kept and
82 // forwarded. The PacketTime might be altered to reflect time spent in fake
83 // network pipe.
84 MediaType media_type_;
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020085 absl::optional<PacketTime> packet_time_;
Erik Språng09708512018-03-14 15:16:50 +010086};
87
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020088// Class simulating a network link. This is a simple and naive solution just
89// faking capacity and adding an extra transport delay in addition to the
90// capacity introduced delay.
91class SimulatedNetwork : public NetworkSimulationInterface {
Erik Språng09708512018-03-14 15:16:50 +010092 public:
Patrik Höglundb6b29e02018-06-21 16:58:01 +020093 using Config = NetworkSimulationInterface::SimulatedNetworkConfig;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +020094 explicit SimulatedNetwork(Config config, uint64_t random_seed = 1);
95
96 // Sets a new configuration. This won't affect packets already in the pipe.
97 void SetConfig(const Config& config);
98
99 // NetworkSimulationInterface
100 bool EnqueuePacket(PacketInFlightInfo packet) override;
101 std::vector<PacketDeliveryInfo> DequeueDeliverablePackets(
102 int64_t receive_time_us) override;
103
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200104 absl::optional<int64_t> NextDeliveryTimeUs() const override;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200105
106 private:
107 struct PacketInfo {
108 PacketInFlightInfo packet;
109 int64_t arrival_time_us;
110 };
111 rtc::CriticalSection config_lock_;
112
113 // |process_lock| guards the data structures involved in delay and loss
114 // processes, such as the packet queues.
115 rtc::CriticalSection process_lock_;
116 std::queue<PacketInfo> capacity_link_ RTC_GUARDED_BY(process_lock_);
117 Random random_;
118
119 std::deque<PacketInfo> delay_link_;
120
121 // Link configuration.
122 Config config_ RTC_GUARDED_BY(config_lock_);
123
124 // Are we currently dropping a burst of packets?
125 bool bursting_;
126
127 // The probability to drop the packet if we are currently dropping a
128 // burst of packet
129 double prob_loss_bursting_ RTC_GUARDED_BY(config_lock_);
130
131 // The probability to drop a burst of packets.
132 double prob_start_bursting_ RTC_GUARDED_BY(config_lock_);
133 int64_t capacity_delay_error_bytes_ = 0;
134};
135
136// Class faking a network link, internally is uses an implementation of a
137// SimulatedNetworkInterface to simulate network behavior.
138class FakeNetworkPipe : public Transport, public PacketReceiver, public Module {
139 public:
140 using Config = SimulatedNetwork::Config;
Erik Språng09708512018-03-14 15:16:50 +0100141
Sebastian Jansson09408112018-04-24 14:41:22 +0200142 // Use these constructors if you plan to insert packets using DeliverPacket().
Erik Språng09708512018-03-14 15:16:50 +0100143 FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config);
Erik Språng09708512018-03-14 15:16:50 +0100144 FakeNetworkPipe(Clock* clock,
145 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200146 PacketReceiver* receiver);
Erik Språng09708512018-03-14 15:16:50 +0100147 FakeNetworkPipe(Clock* clock,
148 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200149 PacketReceiver* receiver,
Erik Språng09708512018-03-14 15:16:50 +0100150 uint64_t seed);
151
152 // Use this constructor if you plan to insert packets using SendRt[c?]p().
153 FakeNetworkPipe(Clock* clock,
154 const FakeNetworkPipe::Config& config,
155 Transport* transport);
156
157 virtual ~FakeNetworkPipe();
158
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200159 void SetClockOffset(int64_t offset_ms);
160
Erik Språng09708512018-03-14 15:16:50 +0100161 // Sets a new configuration. This won't affect packets already in the pipe.
162 void SetConfig(const FakeNetworkPipe::Config& config);
163
Sebastian Jansson09408112018-04-24 14:41:22 +0200164 // Must not be called in parallel with DeliverPacket or Process.
Erik Språng09708512018-03-14 15:16:50 +0100165 void SetReceiver(PacketReceiver* receiver);
166
167 // Implements Transport interface. When/if packets are delivered, they will
168 // be passed to the transport instance given in SetReceiverTransport(). These
169 // methods should only be called if a Transport instance was provided in the
170 // constructor.
171 bool SendRtp(const uint8_t* packet,
172 size_t length,
173 const PacketOptions& options) override;
174 bool SendRtcp(const uint8_t* packet, size_t length) override;
175
176 // Implements the PacketReceiver interface. When/if packets are delivered,
177 // they will be passed directly to the receiver instance given in
178 // SetReceiver(), without passing through a Demuxer. The receive time in
179 // PacketTime will be increased by the amount of time the packet spent in the
180 // fake network pipe.
181 PacketReceiver::DeliveryStatus DeliverPacket(
182 MediaType media_type,
183 rtc::CopyOnWriteBuffer packet,
184 const PacketTime& packet_time) override;
185
186 // Processes the network queues and trigger PacketReceiver::IncomingPacket for
187 // packets ready to be delivered.
188 void Process() override;
189 int64_t TimeUntilNextProcess() override;
190
191 // Get statistics.
192 float PercentageLoss();
193 int AverageDelay();
194 size_t DroppedPackets();
195 size_t SentPackets();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100196 void ResetStats();
197
198 protected:
199 void DeliverPacketWithLock(NetworkPacket* packet);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100200 void AddToPacketDropCount();
201 void AddToPacketSentCount(int count);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200202 void AddToTotalDelay(int delay_us);
203 int64_t GetTimeInMicroseconds() const;
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200204 bool ShouldProcess(int64_t time_now_us) const;
205 void SetTimeToNextProcess(int64_t skip_us);
Erik Språng09708512018-03-14 15:16:50 +0100206
207 private:
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200208 struct StoredPacket {
209 NetworkPacket packet;
210 bool removed = false;
211 explicit StoredPacket(NetworkPacket&& packet);
212 StoredPacket(StoredPacket&&) = default;
213 StoredPacket(const StoredPacket&) = delete;
214 StoredPacket& operator=(const StoredPacket&) = delete;
215 StoredPacket() = delete;
216 };
217
Erik Språng09708512018-03-14 15:16:50 +0100218 // Returns true if enqueued, or false if packet was dropped.
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100219 virtual bool EnqueuePacket(rtc::CopyOnWriteBuffer packet,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200220 absl::optional<PacketOptions> options,
221 bool is_rtcp,
222 MediaType media_type,
223 absl::optional<PacketTime> packet_time);
Erik Språng09708512018-03-14 15:16:50 +0100224 void DeliverPacket(NetworkPacket* packet)
225 RTC_EXCLUSIVE_LOCKS_REQUIRED(config_lock_);
226 bool HasTransport() const;
Sebastian Jansson09408112018-04-24 14:41:22 +0200227 bool HasReceiver() const;
Erik Språng09708512018-03-14 15:16:50 +0100228
229 Clock* const clock_;
230 // |config_lock| guards the mostly constant things like the callbacks.
231 rtc::CriticalSection config_lock_;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200232 const std::unique_ptr<SimulatedNetwork> network_simulation_;
Erik Språng09708512018-03-14 15:16:50 +0100233 PacketReceiver* receiver_ RTC_GUARDED_BY(config_lock_);
234 Transport* const transport_ RTC_GUARDED_BY(config_lock_);
235
236 // |process_lock| guards the data structures involved in delay and loss
237 // processes, such as the packet queues.
238 rtc::CriticalSection process_lock_;
Erik Språng09708512018-03-14 15:16:50 +0100239
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200240 // Packets are added at the back of the deque, this makes the deque ordered
241 // by increasing send time. The common case when removing packets from the
242 // deque is removing early packets, which will be close to the front of the
243 // deque. This makes finding the packets in the deque efficient in the common
244 // case.
245 std::deque<StoredPacket> packets_in_flight_ RTC_GUARDED_BY(process_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100246
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200247 int64_t clock_offset_ms_ RTC_GUARDED_BY(config_lock_);
248
Erik Språng09708512018-03-14 15:16:50 +0100249 // Statistics.
250 size_t dropped_packets_ RTC_GUARDED_BY(process_lock_);
251 size_t sent_packets_ RTC_GUARDED_BY(process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200252 int64_t total_packet_delay_us_ RTC_GUARDED_BY(process_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100253
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200254 int64_t next_process_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100255
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200256 int64_t last_log_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100257
Erik Språng09708512018-03-14 15:16:50 +0100258 RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
259};
260
261} // namespace webrtc
262
263#endif // CALL_FAKE_NETWORK_PIPE_H_