blob: 234e229dfa62b01a4ffc602ca960ea2e4f17b979 [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#include <assert.h>
12#include <math.h>
13#include <string.h>
14
15#include <algorithm>
16#include <cmath>
17#include <utility>
18
19#include "call/call.h"
20#include "call/fake_network_pipe.h"
Erik Språng09708512018-03-14 15:16:50 +010021#include "rtc_base/logging.h"
22#include "system_wrappers/include/clock.h"
23
24namespace webrtc {
25
26namespace {
27constexpr int64_t kDefaultProcessIntervalMs = 5;
Sebastian Jansson512bdce2018-04-23 13:15:04 +020028constexpr int64_t kLogIntervalMs = 5000;
Erik Språng09708512018-03-14 15:16:50 +010029struct PacketArrivalTimeComparator {
30 bool operator()(const NetworkPacket& p1, const NetworkPacket& p2) {
31 return p1.arrival_time() < p2.arrival_time();
32 }
33};
34} // namespace
35
36NetworkPacket::NetworkPacket(rtc::CopyOnWriteBuffer packet,
37 int64_t send_time,
38 int64_t arrival_time,
39 rtc::Optional<PacketOptions> packet_options,
40 bool is_rtcp,
41 MediaType media_type,
42 rtc::Optional<PacketTime> packet_time)
43 : packet_(std::move(packet)),
44 send_time_(send_time),
45 arrival_time_(arrival_time),
46 packet_options_(packet_options),
47 is_rtcp_(is_rtcp),
48 media_type_(media_type),
49 packet_time_(packet_time) {}
50
51NetworkPacket::NetworkPacket(NetworkPacket&& o)
52 : packet_(std::move(o.packet_)),
53 send_time_(o.send_time_),
54 arrival_time_(o.arrival_time_),
55 packet_options_(o.packet_options_),
56 is_rtcp_(o.is_rtcp_),
57 media_type_(o.media_type_),
58 packet_time_(o.packet_time_) {}
59
60NetworkPacket& NetworkPacket::operator=(NetworkPacket&& o) {
61 packet_ = std::move(o.packet_);
62 send_time_ = o.send_time_;
63 arrival_time_ = o.arrival_time_;
64 packet_options_ = o.packet_options_;
65 is_rtcp_ = o.is_rtcp_;
66 media_type_ = o.media_type_;
67 packet_time_ = o.packet_time_;
68
69 return *this;
70}
71
Erik Språng09708512018-03-14 15:16:50 +010072FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
73 const FakeNetworkPipe::Config& config)
74 : FakeNetworkPipe(clock, config, nullptr, 1) {}
75
76FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
77 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +020078 PacketReceiver* receiver)
79 : FakeNetworkPipe(clock, config, receiver, 1) {}
Erik Språng09708512018-03-14 15:16:50 +010080
81FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
82 const FakeNetworkPipe::Config& config,
Sebastian Jansson09408112018-04-24 14:41:22 +020083 PacketReceiver* receiver,
Erik Språng09708512018-03-14 15:16:50 +010084 uint64_t seed)
85 : clock_(clock),
Sebastian Jansson09408112018-04-24 14:41:22 +020086 receiver_(receiver),
Erik Språng09708512018-03-14 15:16:50 +010087 transport_(nullptr),
88 random_(seed),
Sebastian Jansson7e85d672018-04-06 09:56:21 +020089 clock_offset_ms_(0),
Erik Språng09708512018-03-14 15:16:50 +010090 config_(),
91 dropped_packets_(0),
92 sent_packets_(0),
Sebastian Jansson512bdce2018-04-23 13:15:04 +020093 total_packet_delay_us_(0),
Erik Språng09708512018-03-14 15:16:50 +010094 bursting_(false),
Sebastian Jansson512bdce2018-04-23 13:15:04 +020095 next_process_time_us_(clock_->TimeInMicroseconds()),
96 last_log_time_us_(clock_->TimeInMicroseconds()) {
Erik Språng09708512018-03-14 15:16:50 +010097 SetConfig(config);
98}
99
100FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
101 const FakeNetworkPipe::Config& config,
102 Transport* transport)
103 : clock_(clock),
104 receiver_(nullptr),
105 transport_(transport),
106 random_(1),
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200107 clock_offset_ms_(0),
Erik Språng09708512018-03-14 15:16:50 +0100108 config_(),
109 dropped_packets_(0),
110 sent_packets_(0),
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200111 total_packet_delay_us_(0),
Erik Språng09708512018-03-14 15:16:50 +0100112 bursting_(false),
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200113 next_process_time_us_(clock_->TimeInMicroseconds()),
114 last_log_time_us_(clock_->TimeInMicroseconds()) {
Erik Språng09708512018-03-14 15:16:50 +0100115 SetConfig(config);
116}
117
118FakeNetworkPipe::~FakeNetworkPipe() = default;
119
120void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
121 rtc::CritScope crit(&config_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100122 receiver_ = receiver;
123}
124
125bool FakeNetworkPipe::SendRtp(const uint8_t* packet,
126 size_t length,
127 const PacketOptions& options) {
128 RTC_DCHECK(HasTransport());
129 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), options, false,
130 MediaType::ANY, rtc::nullopt);
131 return true;
132}
133
134bool FakeNetworkPipe::SendRtcp(const uint8_t* packet, size_t length) {
135 RTC_DCHECK(HasTransport());
136 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), rtc::nullopt, true,
137 MediaType::ANY, rtc::nullopt);
138 return true;
139}
140
141PacketReceiver::DeliveryStatus FakeNetworkPipe::DeliverPacket(
142 MediaType media_type,
143 rtc::CopyOnWriteBuffer packet,
144 const PacketTime& packet_time) {
145 return EnqueuePacket(std::move(packet), rtc::nullopt, false, media_type,
146 packet_time)
147 ? PacketReceiver::DELIVERY_OK
148 : PacketReceiver::DELIVERY_PACKET_ERROR;
149}
150
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200151void FakeNetworkPipe::SetClockOffset(int64_t offset_ms) {
152 rtc::CritScope crit(&config_lock_);
153 clock_offset_ms_ = offset_ms;
154}
155
Erik Språng09708512018-03-14 15:16:50 +0100156void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) {
157 rtc::CritScope crit(&config_lock_);
158 config_ = config; // Shallow copy of the struct.
159 double prob_loss = config.loss_percent / 100.0;
160 if (config_.avg_burst_loss_length == -1) {
161 // Uniform loss
162 prob_loss_bursting_ = prob_loss;
163 prob_start_bursting_ = prob_loss;
164 } else {
165 // Lose packets according to a gilbert-elliot model.
166 int avg_burst_loss_length = config.avg_burst_loss_length;
167 int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
168
169 RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
170 << "For a total packet loss of " << config.loss_percent << "%% then"
171 << " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
172 << " or higher.";
173
174 prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
175 prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
176 }
177}
178
Erik Språng09708512018-03-14 15:16:50 +0100179bool FakeNetworkPipe::EnqueuePacket(rtc::CopyOnWriteBuffer packet,
180 rtc::Optional<PacketOptions> options,
181 bool is_rtcp,
182 MediaType media_type,
183 rtc::Optional<PacketTime> packet_time) {
184 Config config;
185 {
186 rtc::CritScope crit(&config_lock_);
187 config = config_;
188 }
189 rtc::CritScope crit(&process_lock_);
190 if (config.queue_length_packets > 0 &&
191 capacity_link_.size() >= config.queue_length_packets) {
192 // Too many packet on the link, drop this one.
193 ++dropped_packets_;
194 return false;
195 }
196
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200197 int64_t time_now_us = clock_->TimeInMicroseconds();
Erik Språng09708512018-03-14 15:16:50 +0100198
199 // Delay introduced by the link capacity.
200 int64_t capacity_delay_ms = 0;
201 if (config.link_capacity_kbps > 0) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200202 // Using bytes per millisecond to avoid losing precision.
203 const int64_t bytes_per_millisecond = config.link_capacity_kbps / 8;
Erik Språng09708512018-03-14 15:16:50 +0100204 // To round to the closest millisecond we add half a milliseconds worth of
205 // bytes to the delay calculation.
206 capacity_delay_ms = (packet.size() + capacity_delay_error_bytes_ +
207 bytes_per_millisecond / 2) /
208 bytes_per_millisecond;
209 capacity_delay_error_bytes_ +=
210 packet.size() - capacity_delay_ms * bytes_per_millisecond;
211 }
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200212 int64_t network_start_time_us = time_now_us;
Erik Språng09708512018-03-14 15:16:50 +0100213
214 // Check if there already are packets on the link and change network start
215 // time forward if there is.
216 if (!capacity_link_.empty() &&
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200217 network_start_time_us < capacity_link_.back().arrival_time())
218 network_start_time_us = capacity_link_.back().arrival_time();
Erik Språng09708512018-03-14 15:16:50 +0100219
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200220 int64_t arrival_time_us = network_start_time_us + capacity_delay_ms * 1000;
221 capacity_link_.emplace(std::move(packet), time_now_us, arrival_time_us,
222 options, is_rtcp, media_type, packet_time);
Erik Språng09708512018-03-14 15:16:50 +0100223 return true;
224}
225
226float FakeNetworkPipe::PercentageLoss() {
227 rtc::CritScope crit(&process_lock_);
228 if (sent_packets_ == 0)
229 return 0;
230
231 return static_cast<float>(dropped_packets_) /
232 (sent_packets_ + dropped_packets_);
233}
234
235int FakeNetworkPipe::AverageDelay() {
236 rtc::CritScope crit(&process_lock_);
237 if (sent_packets_ == 0)
238 return 0;
239
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200240 return static_cast<int>(total_packet_delay_us_ /
241 (1000 * static_cast<int64_t>(sent_packets_)));
Erik Språng09708512018-03-14 15:16:50 +0100242}
243
244size_t FakeNetworkPipe::DroppedPackets() {
245 rtc::CritScope crit(&process_lock_);
246 return dropped_packets_;
247}
248
249size_t FakeNetworkPipe::SentPackets() {
250 rtc::CritScope crit(&process_lock_);
251 return sent_packets_;
252}
253
254void FakeNetworkPipe::Process() {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200255 int64_t time_now_us = clock_->TimeInMicroseconds();
Erik Språng09708512018-03-14 15:16:50 +0100256 std::queue<NetworkPacket> packets_to_deliver;
257 Config config;
258 double prob_loss_bursting;
259 double prob_start_bursting;
260 {
261 rtc::CritScope crit(&config_lock_);
262 config = config_;
263 prob_loss_bursting = prob_loss_bursting_;
264 prob_start_bursting = prob_start_bursting_;
265 }
266 {
267 rtc::CritScope crit(&process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200268 if (time_now_us - last_log_time_us_ > kLogIntervalMs * 1000) {
269 int64_t queueing_delay_us = 0;
Erik Språng09708512018-03-14 15:16:50 +0100270 if (!capacity_link_.empty()) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200271 queueing_delay_us = time_now_us - capacity_link_.front().send_time();
Erik Språng09708512018-03-14 15:16:50 +0100272 }
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200273 RTC_LOG(LS_INFO) << "Network queue: " << queueing_delay_us << " us.";
274 last_log_time_us_ = time_now_us;
Erik Språng09708512018-03-14 15:16:50 +0100275 }
276
277 // Check the capacity link first.
278 if (!capacity_link_.empty()) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200279 int64_t last_arrival_time_us =
Erik Språng09708512018-03-14 15:16:50 +0100280 delay_link_.empty() ? -1 : delay_link_.back().arrival_time();
281 bool needs_sort = false;
282 while (!capacity_link_.empty() &&
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200283 time_now_us >= capacity_link_.front().arrival_time()) {
Erik Språng09708512018-03-14 15:16:50 +0100284 // Time to get this packet.
285 NetworkPacket packet = std::move(capacity_link_.front());
286 capacity_link_.pop();
287
288 // Drop packets at an average rate of |config_.loss_percent| with
289 // and average loss burst length of |config_.avg_burst_loss_length|.
290 if ((bursting_ && random_.Rand<double>() < prob_loss_bursting) ||
291 (!bursting_ && random_.Rand<double>() < prob_start_bursting)) {
292 bursting_ = true;
293 continue;
294 } else {
295 bursting_ = false;
296 }
297
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200298 int64_t arrival_time_jitter_us =
299 random_.Gaussian(config.queue_delay_ms,
300 config.delay_standard_deviation_ms) *
301 1000;
Erik Språng09708512018-03-14 15:16:50 +0100302
303 // If reordering is not allowed then adjust arrival_time_jitter
304 // to make sure all packets are sent in order.
305 if (!config.allow_reordering && !delay_link_.empty() &&
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200306 packet.arrival_time() + arrival_time_jitter_us <
307 last_arrival_time_us) {
308 arrival_time_jitter_us = last_arrival_time_us - packet.arrival_time();
Erik Språng09708512018-03-14 15:16:50 +0100309 }
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200310 packet.IncrementArrivalTime(arrival_time_jitter_us);
311 if (packet.arrival_time() >= last_arrival_time_us) {
312 last_arrival_time_us = packet.arrival_time();
Erik Språng09708512018-03-14 15:16:50 +0100313 } else {
314 needs_sort = true;
315 }
316 delay_link_.emplace_back(std::move(packet));
317 }
318
319 if (needs_sort) {
320 // Packet(s) arrived out of order, make sure list is sorted.
321 std::sort(delay_link_.begin(), delay_link_.end(),
322 PacketArrivalTimeComparator());
323 }
324 }
325
326 // Check the extra delay queue.
327 while (!delay_link_.empty() &&
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200328 time_now_us >= delay_link_.front().arrival_time()) {
Erik Språng09708512018-03-14 15:16:50 +0100329 // Deliver this packet.
330 NetworkPacket packet(std::move(delay_link_.front()));
331 delay_link_.pop_front();
332 // |time_now| might be later than when the packet should have arrived, due
333 // to NetworkProcess being called too late. For stats, use the time it
334 // should have been on the link.
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200335 total_packet_delay_us_ += packet.arrival_time() - packet.send_time();
Erik Språng09708512018-03-14 15:16:50 +0100336 packets_to_deliver.push(std::move(packet));
337 }
338 sent_packets_ += packets_to_deliver.size();
339 }
340
341 rtc::CritScope crit(&config_lock_);
342 while (!packets_to_deliver.empty()) {
343 NetworkPacket packet = std::move(packets_to_deliver.front());
344 packets_to_deliver.pop();
345 DeliverPacket(&packet);
346 }
347
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200348 next_process_time_us_ = !delay_link_.empty()
349 ? delay_link_.begin()->arrival_time()
350 : time_now_us + kDefaultProcessIntervalMs * 1000;
Erik Språng09708512018-03-14 15:16:50 +0100351}
352
353void FakeNetworkPipe::DeliverPacket(NetworkPacket* packet) {
Sebastian Janssona44ab182018-04-06 12:59:14 +0200354 if (transport_) {
355 RTC_DCHECK(!receiver_);
Erik Språng09708512018-03-14 15:16:50 +0100356 if (packet->is_rtcp()) {
357 transport_->SendRtcp(packet->data(), packet->data_length());
358 } else {
359 transport_->SendRtp(packet->data(), packet->data_length(),
360 packet->packet_options());
361 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200362 } else if (receiver_) {
Erik Språng09708512018-03-14 15:16:50 +0100363 PacketTime packet_time = packet->packet_time();
364 if (packet_time.timestamp != -1) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200365 int64_t queue_time_us = packet->arrival_time() - packet->send_time();
366 RTC_CHECK(queue_time_us >= 0);
367 packet_time.timestamp += queue_time_us;
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200368 packet_time.timestamp += (clock_offset_ms_ * 1000);
Erik Språng09708512018-03-14 15:16:50 +0100369 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200370 receiver_->DeliverPacket(packet->media_type(),
371 std::move(*packet->raw_packet()), packet_time);
Erik Språng09708512018-03-14 15:16:50 +0100372 }
373}
374
375int64_t FakeNetworkPipe::TimeUntilNextProcess() {
376 rtc::CritScope crit(&process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200377 int64_t delay_us = next_process_time_us_ - clock_->TimeInMicroseconds();
378 return std::max<int64_t>((delay_us + 500) / 1000, 0);
Erik Språng09708512018-03-14 15:16:50 +0100379}
380
381bool FakeNetworkPipe::HasTransport() const {
382 rtc::CritScope crit(&config_lock_);
383 return transport_ != nullptr;
384}
Sebastian Jansson09408112018-04-24 14:41:22 +0200385bool FakeNetworkPipe::HasReceiver() const {
Erik Språng09708512018-03-14 15:16:50 +0100386 rtc::CritScope crit(&config_lock_);
Sebastian Jansson09408112018-04-24 14:41:22 +0200387 return receiver_ != nullptr;
Erik Språng09708512018-03-14 15:16:50 +0100388}
389
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100390void FakeNetworkPipe::DeliverPacketWithLock(NetworkPacket* packet) {
391 rtc::CritScope crit(&config_lock_);
392 DeliverPacket(packet);
393}
394
395void FakeNetworkPipe::ResetStats() {
396 rtc::CritScope crit(&process_lock_);
397 dropped_packets_ = 0;
398 sent_packets_ = 0;
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200399 total_packet_delay_us_ = 0;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100400}
401
402int FakeNetworkPipe::GetConfigCapacityKbps() const {
403 rtc::CritScope crit(&config_lock_);
404 return config_.link_capacity_kbps;
405}
406
407void FakeNetworkPipe::AddToPacketDropCount() {
408 rtc::CritScope crit(&process_lock_);
409 ++dropped_packets_;
410}
411
412void FakeNetworkPipe::AddToPacketSentCount(int count) {
413 rtc::CritScope crit(&process_lock_);
414 sent_packets_ += count;
415}
416
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200417void FakeNetworkPipe::AddToTotalDelay(int delay_us) {
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100418 rtc::CritScope crit(&process_lock_);
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200419 total_packet_delay_us_ += delay_us;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100420}
421
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200422int64_t FakeNetworkPipe::GetTimeInMicroseconds() const {
423 return clock_->TimeInMicroseconds();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100424}
425
426bool FakeNetworkPipe::IsRandomLoss(double prob_loss) {
427 return random_.Rand<double>() < prob_loss;
428}
429
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200430bool FakeNetworkPipe::ShouldProcess(int64_t time_now_us) const {
431 return time_now_us >= next_process_time_us_;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100432}
433
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200434void FakeNetworkPipe::SetTimeToNextProcess(int64_t skip_us) {
435 next_process_time_us_ += skip_us;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100436}
437
Erik Språng09708512018-03-14 15:16:50 +0100438} // namespace webrtc