blob: a8c0d372c9a0ac71d0e9b0a5d3f4e1ee1353f310 [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>
18#include <string>
19
20#include "api/call/transport.h"
21#include "call/call.h"
22#include "common_types.h" // NOLINT(build/include)
23#include "modules/include/module.h"
24#include "rtc_base/constructormagic.h"
25#include "rtc_base/criticalsection.h"
26#include "rtc_base/random.h"
27#include "rtc_base/thread_annotations.h"
28#include "typedefs.h" // NOLINT(build/include)
29
30namespace webrtc {
31
32class Clock;
33class PacketReceiver;
34enum class MediaType;
35
36class NetworkPacket {
37 public:
38 NetworkPacket(rtc::CopyOnWriteBuffer packet,
39 int64_t send_time,
40 int64_t arrival_time,
41 rtc::Optional<PacketOptions> packet_options,
42 bool is_rtcp,
43 MediaType media_type_,
44 rtc::Optional<PacketTime> packet_time_);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010045 // Disallow copy constructor and copy assignment (no deep copies of |data_|).
Erik Språng09708512018-03-14 15:16:50 +010046 NetworkPacket(const NetworkPacket&) = delete;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +010047 NetworkPacket& operator=(const NetworkPacket&) = delete;
Erik Språng09708512018-03-14 15:16:50 +010048 // Allow move constructor/assignment, so that we can use in stl containers.
49 NetworkPacket(NetworkPacket&&);
50 NetworkPacket& operator=(NetworkPacket&&);
51
52 const uint8_t* data() const { return packet_.data(); }
53 size_t data_length() const { return packet_.size(); }
54 rtc::CopyOnWriteBuffer* raw_packet() { return &packet_; }
55 int64_t send_time() const { return send_time_; }
56 int64_t arrival_time() const { return arrival_time_; }
57 void IncrementArrivalTime(int64_t extra_delay) {
58 arrival_time_ += extra_delay;
59 }
60 PacketOptions packet_options() const {
61 return packet_options_.value_or(PacketOptions());
62 }
63 bool is_rtcp() const { return is_rtcp_; }
64 MediaType media_type() const { return media_type_; }
65 PacketTime packet_time() const { return packet_time_.value_or(PacketTime()); }
66
67 private:
68 rtc::CopyOnWriteBuffer packet_;
69 // The time the packet was sent out on the network.
70 int64_t send_time_;
71 // The time the packet should arrive at the receiver.
72 int64_t arrival_time_;
73 // If using a Transport for outgoing degradation, populate with
74 // PacketOptions (transport-wide sequence number) for RTP.
75 rtc::Optional<PacketOptions> packet_options_;
76 bool is_rtcp_;
77 // If using a PacketReceiver for incoming degradation, populate with
78 // appropriate MediaType and PacketTime. This type/timing will be kept and
79 // forwarded. The PacketTime might be altered to reflect time spent in fake
80 // network pipe.
81 MediaType media_type_;
82 rtc::Optional<PacketTime> packet_time_;
83};
84
Erik Språng09708512018-03-14 15:16:50 +010085
86// Class faking a network link. This is a simple and naive solution just faking
87// capacity and adding an extra transport delay in addition to the capacity
88// introduced delay.
89
90class FakeNetworkPipe : public Transport, public PacketReceiver, public Module {
91 public:
92 struct Config {
93 Config() {}
94 // Queue length in number of packets.
95 size_t queue_length_packets = 0;
96 // Delay in addition to capacity induced delay.
97 int queue_delay_ms = 0;
98 // Standard deviation of the extra delay.
99 int delay_standard_deviation_ms = 0;
100 // Link capacity in kbps.
101 int link_capacity_kbps = 0;
102 // Random packet loss.
103 int loss_percent = 0;
104 // If packets are allowed to be reordered.
105 bool allow_reordering = false;
106 // The average length of a burst of lost packets.
107 int avg_burst_loss_length = -1;
108 };
109
Sebastian Jansson09408112018-04-24 14:41:22 +0200110 // Use these constructors if you plan to insert packets using DeliverPacket().
Erik Språng09708512018-03-14 15:16:50 +0100111 FakeNetworkPipe(Clock* clock, const FakeNetworkPipe::Config& config);
Erik Språng09708512018-03-14 15:16:50 +0100112 FakeNetworkPipe(Clock* clock,
113 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200114 PacketReceiver* receiver);
Erik Språng09708512018-03-14 15:16:50 +0100115 FakeNetworkPipe(Clock* clock,
116 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +0200117 PacketReceiver* receiver,
Erik Språng09708512018-03-14 15:16:50 +0100118 uint64_t seed);
119
120 // Use this constructor if you plan to insert packets using SendRt[c?]p().
121 FakeNetworkPipe(Clock* clock,
122 const FakeNetworkPipe::Config& config,
123 Transport* transport);
124
125 virtual ~FakeNetworkPipe();
126
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200127 void SetClockOffset(int64_t offset_ms);
128
Erik Språng09708512018-03-14 15:16:50 +0100129 // Sets a new configuration. This won't affect packets already in the pipe.
130 void SetConfig(const FakeNetworkPipe::Config& config);
131
Sebastian Jansson09408112018-04-24 14:41:22 +0200132 // Must not be called in parallel with DeliverPacket or Process.
Erik Språng09708512018-03-14 15:16:50 +0100133 void SetReceiver(PacketReceiver* receiver);
134
135 // Implements Transport interface. When/if packets are delivered, they will
136 // be passed to the transport instance given in SetReceiverTransport(). These
137 // methods should only be called if a Transport instance was provided in the
138 // constructor.
139 bool SendRtp(const uint8_t* packet,
140 size_t length,
141 const PacketOptions& options) override;
142 bool SendRtcp(const uint8_t* packet, size_t length) override;
143
144 // Implements the PacketReceiver interface. When/if packets are delivered,
145 // they will be passed directly to the receiver instance given in
146 // SetReceiver(), without passing through a Demuxer. The receive time in
147 // PacketTime will be increased by the amount of time the packet spent in the
148 // fake network pipe.
149 PacketReceiver::DeliveryStatus DeliverPacket(
150 MediaType media_type,
151 rtc::CopyOnWriteBuffer packet,
152 const PacketTime& packet_time) override;
153
154 // Processes the network queues and trigger PacketReceiver::IncomingPacket for
155 // packets ready to be delivered.
156 void Process() override;
157 int64_t TimeUntilNextProcess() override;
158
159 // Get statistics.
160 float PercentageLoss();
161 int AverageDelay();
162 size_t DroppedPackets();
163 size_t SentPackets();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100164 void ResetStats();
165
166 protected:
167 void DeliverPacketWithLock(NetworkPacket* packet);
168 int GetConfigCapacityKbps() const;
169 void AddToPacketDropCount();
170 void AddToPacketSentCount(int count);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200171 void AddToTotalDelay(int delay_us);
172 int64_t GetTimeInMicroseconds() const;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100173 bool IsRandomLoss(double prob_loss);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200174 bool ShouldProcess(int64_t time_now_us) const;
175 void SetTimeToNextProcess(int64_t skip_us);
Erik Språng09708512018-03-14 15:16:50 +0100176
177 private:
178 // Returns true if enqueued, or false if packet was dropped.
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100179 virtual bool EnqueuePacket(rtc::CopyOnWriteBuffer packet,
Erik Språng09708512018-03-14 15:16:50 +0100180 rtc::Optional<PacketOptions> options,
181 bool is_rtcp,
182 MediaType media_type,
183 rtc::Optional<PacketTime> packet_time);
184 void DeliverPacket(NetworkPacket* packet)
185 RTC_EXCLUSIVE_LOCKS_REQUIRED(config_lock_);
186 bool HasTransport() const;
Sebastian Jansson09408112018-04-24 14:41:22 +0200187 bool HasReceiver() const;
Erik Språng09708512018-03-14 15:16:50 +0100188
189 Clock* const clock_;
190 // |config_lock| guards the mostly constant things like the callbacks.
191 rtc::CriticalSection config_lock_;
Erik Språng09708512018-03-14 15:16:50 +0100192 PacketReceiver* receiver_ RTC_GUARDED_BY(config_lock_);
193 Transport* const transport_ RTC_GUARDED_BY(config_lock_);
194
195 // |process_lock| guards the data structures involved in delay and loss
196 // processes, such as the packet queues.
197 rtc::CriticalSection process_lock_;
198 std::queue<NetworkPacket> capacity_link_ RTC_GUARDED_BY(process_lock_);
199 Random random_;
200
201 std::deque<NetworkPacket> delay_link_;
202
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200203 int64_t clock_offset_ms_ RTC_GUARDED_BY(config_lock_);
204
Erik Språng09708512018-03-14 15:16:50 +0100205 // Link configuration.
206 Config config_ RTC_GUARDED_BY(config_lock_);
207
208 // Statistics.
209 size_t dropped_packets_ RTC_GUARDED_BY(process_lock_);
210 size_t sent_packets_ RTC_GUARDED_BY(process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200211 int64_t total_packet_delay_us_ RTC_GUARDED_BY(process_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100212
213 // Are we currently dropping a burst of packets?
214 bool bursting_;
215
216 // The probability to drop the packet if we are currently dropping a
217 // burst of packet
218 double prob_loss_bursting_ RTC_GUARDED_BY(config_lock_);
219
220 // The probability to drop a burst of packets.
221 double prob_start_bursting_ RTC_GUARDED_BY(config_lock_);
222
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200223 int64_t next_process_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100224
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200225 int64_t last_log_time_us_;
Erik Språng09708512018-03-14 15:16:50 +0100226
227 int64_t capacity_delay_error_bytes_ = 0;
228
229 RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
230};
231
232} // namespace webrtc
233
234#endif // CALL_FAKE_NETWORK_PIPE_H_