blob: b5c0cb52e39fe9ddefe5693e0dd3fabf33668c4f [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
Erik Språng09708512018-03-14 15:16:50 +010011#include <string.h>
Erik Språng09708512018-03-14 15:16:50 +010012#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <queue>
Erik Språng09708512018-03-14 15:16:50 +010014#include <utility>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <vector>
Erik Språng09708512018-03-14 15:16:50 +010016
Steve Anton10542f22019-01-11 09:11:00 -080017#include "api/media_types.h"
Erik Språng09708512018-03-14 15:16:50 +010018#include "call/fake_network_pipe.h"
Sebastian Jansson71822862018-10-30 08:23:27 +010019#include "modules/utility/include/process_thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010020#include "rtc_base/checks.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 +010029} // namespace
30
31NetworkPacket::NetworkPacket(rtc::CopyOnWriteBuffer packet,
32 int64_t send_time,
33 int64_t arrival_time,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020034 absl::optional<PacketOptions> packet_options,
Erik Språng09708512018-03-14 15:16:50 +010035 bool is_rtcp,
36 MediaType media_type,
Niels Möller70082872018-08-07 11:03:12 +020037 absl::optional<int64_t> packet_time_us)
Erik Språng09708512018-03-14 15:16:50 +010038 : packet_(std::move(packet)),
39 send_time_(send_time),
40 arrival_time_(arrival_time),
41 packet_options_(packet_options),
42 is_rtcp_(is_rtcp),
43 media_type_(media_type),
Niels Möller70082872018-08-07 11:03:12 +020044 packet_time_us_(packet_time_us) {}
Artem Titov537b7fe2018-08-16 11:20:45 +020045
Erik Språng09708512018-03-14 15:16:50 +010046NetworkPacket::NetworkPacket(NetworkPacket&& o)
47 : packet_(std::move(o.packet_)),
48 send_time_(o.send_time_),
49 arrival_time_(o.arrival_time_),
50 packet_options_(o.packet_options_),
51 is_rtcp_(o.is_rtcp_),
52 media_type_(o.media_type_),
Niels Möller70082872018-08-07 11:03:12 +020053 packet_time_us_(o.packet_time_us_) {}
Erik Språng09708512018-03-14 15:16:50 +010054
Mirko Bonadeied1dcf92018-07-26 09:15:11 +020055NetworkPacket::~NetworkPacket() = default;
56
Erik Språng09708512018-03-14 15:16:50 +010057NetworkPacket& NetworkPacket::operator=(NetworkPacket&& o) {
58 packet_ = std::move(o.packet_);
59 send_time_ = o.send_time_;
60 arrival_time_ = o.arrival_time_;
61 packet_options_ = o.packet_options_;
62 is_rtcp_ = o.is_rtcp_;
63 media_type_ = o.media_type_;
Niels Möller70082872018-08-07 11:03:12 +020064 packet_time_us_ = o.packet_time_us_;
Erik Språng09708512018-03-14 15:16:50 +010065
66 return *this;
67}
68
Artem Titovb0050872018-08-16 17:02:20 +020069FakeNetworkPipe::FakeNetworkPipe(
70 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020071 std::unique_ptr<NetworkBehaviorInterface> network_behavior)
72 : FakeNetworkPipe(clock, std::move(network_behavior), nullptr, 1) {}
Artem Titovb0050872018-08-16 17:02:20 +020073
74FakeNetworkPipe::FakeNetworkPipe(
75 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020076 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +020077 PacketReceiver* receiver)
Artem Titov8ea1e9d2018-10-04 14:46:31 +020078 : FakeNetworkPipe(clock, std::move(network_behavior), receiver, 1) {}
Artem Titovb0050872018-08-16 17:02:20 +020079
80FakeNetworkPipe::FakeNetworkPipe(
81 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020082 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +020083 PacketReceiver* receiver,
84 uint64_t seed)
85 : clock_(clock),
Artem Titov8ea1e9d2018-10-04 14:46:31 +020086 network_behavior_(std::move(network_behavior)),
Artem Titovb0050872018-08-16 17:02:20 +020087 receiver_(receiver),
88 transport_(nullptr),
89 clock_offset_ms_(0),
90 dropped_packets_(0),
91 sent_packets_(0),
92 total_packet_delay_us_(0),
Artem Titovb0050872018-08-16 17:02:20 +020093 last_log_time_us_(clock_->TimeInMicroseconds()) {}
94
95FakeNetworkPipe::FakeNetworkPipe(
96 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020097 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +020098 Transport* transport)
99 : clock_(clock),
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200100 network_behavior_(std::move(network_behavior)),
Artem Titovb0050872018-08-16 17:02:20 +0200101 receiver_(nullptr),
102 transport_(transport),
103 clock_offset_ms_(0),
104 dropped_packets_(0),
105 sent_packets_(0),
106 total_packet_delay_us_(0),
Artem Titovb0050872018-08-16 17:02:20 +0200107 last_log_time_us_(clock_->TimeInMicroseconds()) {}
108
Erik Språng09708512018-03-14 15:16:50 +0100109FakeNetworkPipe::~FakeNetworkPipe() = default;
110
111void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
112 rtc::CritScope crit(&config_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100113 receiver_ = receiver;
114}
115
116bool FakeNetworkPipe::SendRtp(const uint8_t* packet,
117 size_t length,
118 const PacketOptions& options) {
119 RTC_DCHECK(HasTransport());
120 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), options, false,
Niels Möller70082872018-08-07 11:03:12 +0200121 MediaType::ANY);
Erik Språng09708512018-03-14 15:16:50 +0100122 return true;
123}
124
125bool FakeNetworkPipe::SendRtcp(const uint8_t* packet, size_t length) {
126 RTC_DCHECK(HasTransport());
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200127 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), absl::nullopt, true,
Niels Möller70082872018-08-07 11:03:12 +0200128 MediaType::ANY);
Erik Språng09708512018-03-14 15:16:50 +0100129 return true;
130}
131
132PacketReceiver::DeliveryStatus FakeNetworkPipe::DeliverPacket(
133 MediaType media_type,
134 rtc::CopyOnWriteBuffer packet,
Niels Möller70082872018-08-07 11:03:12 +0200135 int64_t packet_time_us) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200136 return EnqueuePacket(std::move(packet), absl::nullopt, false, media_type,
Niels Möller70082872018-08-07 11:03:12 +0200137 packet_time_us)
Erik Språng09708512018-03-14 15:16:50 +0100138 ? PacketReceiver::DELIVERY_OK
139 : PacketReceiver::DELIVERY_PACKET_ERROR;
140}
141
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200142void FakeNetworkPipe::SetClockOffset(int64_t offset_ms) {
143 rtc::CritScope crit(&config_lock_);
144 clock_offset_ms_ = offset_ms;
145}
146
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200147FakeNetworkPipe::StoredPacket::StoredPacket(NetworkPacket&& packet)
148 : packet(std::move(packet)) {}
149
150bool FakeNetworkPipe::EnqueuePacket(rtc::CopyOnWriteBuffer packet,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200151 absl::optional<PacketOptions> options,
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200152 bool is_rtcp,
153 MediaType media_type,
Niels Möller70082872018-08-07 11:03:12 +0200154 absl::optional<int64_t> packet_time_us) {
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200155 rtc::CritScope crit(&process_lock_);
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200156 int64_t time_now_us = clock_->TimeInMicroseconds();
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200157 size_t packet_size = packet.size();
Niels Möllerf189c482018-08-17 09:49:20 +0200158 NetworkPacket net_packet(std::move(packet), time_now_us, time_now_us, options,
159 is_rtcp, media_type, packet_time_us);
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200160
161 packets_in_flight_.emplace_back(StoredPacket(std::move(net_packet)));
162 int64_t packet_id = reinterpret_cast<uint64_t>(&packets_in_flight_.back());
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200163 bool sent = network_behavior_->EnqueuePacket(
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200164 PacketInFlightInfo(packet_size, time_now_us, packet_id));
165
166 if (!sent) {
167 packets_in_flight_.pop_back();
168 ++dropped_packets_;
169 }
Sebastian Jansson71822862018-10-30 08:23:27 +0100170 if (network_behavior_->NextDeliveryTimeUs()) {
171 rtc::CritScope crit(&process_thread_lock_);
172 if (process_thread_)
173 process_thread_->WakeUp(nullptr);
174 }
175
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200176 return sent;
177}
178
Erik Språng09708512018-03-14 15:16:50 +0100179float FakeNetworkPipe::PercentageLoss() {
180 rtc::CritScope crit(&process_lock_);
181 if (sent_packets_ == 0)
182 return 0;
183
184 return static_cast<float>(dropped_packets_) /
185 (sent_packets_ + dropped_packets_);
186}
187
188int FakeNetworkPipe::AverageDelay() {
189 rtc::CritScope crit(&process_lock_);
190 if (sent_packets_ == 0)
191 return 0;
192
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200193 return static_cast<int>(total_packet_delay_us_ /
194 (1000 * static_cast<int64_t>(sent_packets_)));
Erik Språng09708512018-03-14 15:16:50 +0100195}
196
197size_t FakeNetworkPipe::DroppedPackets() {
198 rtc::CritScope crit(&process_lock_);
199 return dropped_packets_;
200}
201
202size_t FakeNetworkPipe::SentPackets() {
203 rtc::CritScope crit(&process_lock_);
204 return sent_packets_;
205}
206
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200207void FakeNetworkPipe::Process() {
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200208 int64_t time_now_us;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200209 std::queue<NetworkPacket> packets_to_deliver;
210 {
211 rtc::CritScope crit(&process_lock_);
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200212 time_now_us = clock_->TimeInMicroseconds();
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200213 if (time_now_us - last_log_time_us_ > kLogIntervalMs * 1000) {
214 int64_t queueing_delay_us = 0;
215 if (!packets_in_flight_.empty())
216 queueing_delay_us =
217 time_now_us - packets_in_flight_.front().packet.send_time();
218
219 RTC_LOG(LS_INFO) << "Network queue: " << queueing_delay_us / 1000
220 << " ms.";
221 last_log_time_us_ = time_now_us;
222 }
223
224 std::vector<PacketDeliveryInfo> delivery_infos =
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200225 network_behavior_->DequeueDeliverablePackets(time_now_us);
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200226 for (auto& delivery_info : delivery_infos) {
227 // In the common case where no reordering happens, find will return early
228 // as the first packet will be a match.
229 auto packet_it =
230 std::find_if(packets_in_flight_.begin(), packets_in_flight_.end(),
231 [&delivery_info](StoredPacket& packet_ref) {
232 return reinterpret_cast<uint64_t>(&packet_ref) ==
233 delivery_info.packet_id;
234 });
235 // Check that the packet is in the deque of packets in flight.
236 RTC_CHECK(packet_it != packets_in_flight_.end());
237 // Check that the packet is not already removed.
238 RTC_DCHECK(!packet_it->removed);
239
240 NetworkPacket packet = std::move(packet_it->packet);
241 packet_it->removed = true;
242
243 // Cleanup of removed packets at the beginning of the deque.
244 while (!packets_in_flight_.empty() &&
245 packets_in_flight_.front().removed) {
246 packets_in_flight_.pop_front();
247 }
248
249 if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) {
250 int64_t added_delay_us =
251 delivery_info.receive_time_us - packet.send_time();
252 packet.IncrementArrivalTime(added_delay_us);
253 packets_to_deliver.emplace(std::move(packet));
254 // |time_now_us| might be later than when the packet should have
255 // arrived, due to NetworkProcess being called too late. For stats, use
256 // the time it should have been on the link.
257 total_packet_delay_us_ += added_delay_us;
Christoffer Rodbro3284b612018-10-23 16:51:51 +0200258 ++sent_packets_;
259 } else {
260 ++dropped_packets_;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200261 }
Erik Språng09708512018-03-14 15:16:50 +0100262 }
Erik Språng09708512018-03-14 15:16:50 +0100263 }
264
265 rtc::CritScope crit(&config_lock_);
266 while (!packets_to_deliver.empty()) {
267 NetworkPacket packet = std::move(packets_to_deliver.front());
268 packets_to_deliver.pop();
Niels Möller70082872018-08-07 11:03:12 +0200269 DeliverNetworkPacket(&packet);
Erik Språng09708512018-03-14 15:16:50 +0100270 }
Erik Språng09708512018-03-14 15:16:50 +0100271}
272
Niels Möller70082872018-08-07 11:03:12 +0200273void FakeNetworkPipe::DeliverNetworkPacket(NetworkPacket* packet) {
Sebastian Janssona44ab182018-04-06 12:59:14 +0200274 if (transport_) {
275 RTC_DCHECK(!receiver_);
Erik Språng09708512018-03-14 15:16:50 +0100276 if (packet->is_rtcp()) {
277 transport_->SendRtcp(packet->data(), packet->data_length());
278 } else {
279 transport_->SendRtp(packet->data(), packet->data_length(),
280 packet->packet_options());
281 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200282 } else if (receiver_) {
Niels Möller70082872018-08-07 11:03:12 +0200283 int64_t packet_time_us = packet->packet_time_us().value_or(-1);
284 if (packet_time_us != -1) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200285 int64_t queue_time_us = packet->arrival_time() - packet->send_time();
286 RTC_CHECK(queue_time_us >= 0);
Niels Möller70082872018-08-07 11:03:12 +0200287 packet_time_us += queue_time_us;
288 packet_time_us += (clock_offset_ms_ * 1000);
Erik Språng09708512018-03-14 15:16:50 +0100289 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200290 receiver_->DeliverPacket(packet->media_type(),
Niels Möller70082872018-08-07 11:03:12 +0200291 std::move(*packet->raw_packet()), packet_time_us);
Erik Språng09708512018-03-14 15:16:50 +0100292 }
293}
294
295int64_t FakeNetworkPipe::TimeUntilNextProcess() {
296 rtc::CritScope crit(&process_lock_);
Sebastian Jansson71822862018-10-30 08:23:27 +0100297 absl::optional<int64_t> delivery_us = network_behavior_->NextDeliveryTimeUs();
298 if (delivery_us) {
299 int64_t delay_us = *delivery_us - clock_->TimeInMicroseconds();
300 return std::max<int64_t>((delay_us + 500) / 1000, 0);
301 }
302 return kDefaultProcessIntervalMs;
303}
304
305void FakeNetworkPipe::ProcessThreadAttached(ProcessThread* process_thread) {
306 rtc::CritScope cs(&process_thread_lock_);
307 process_thread_ = process_thread;
Erik Språng09708512018-03-14 15:16:50 +0100308}
309
310bool FakeNetworkPipe::HasTransport() const {
311 rtc::CritScope crit(&config_lock_);
312 return transport_ != nullptr;
313}
Sebastian Jansson09408112018-04-24 14:41:22 +0200314bool FakeNetworkPipe::HasReceiver() const {
Erik Språng09708512018-03-14 15:16:50 +0100315 rtc::CritScope crit(&config_lock_);
Sebastian Jansson09408112018-04-24 14:41:22 +0200316 return receiver_ != nullptr;
Erik Språng09708512018-03-14 15:16:50 +0100317}
318
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100319void FakeNetworkPipe::DeliverPacketWithLock(NetworkPacket* packet) {
320 rtc::CritScope crit(&config_lock_);
Niels Möller70082872018-08-07 11:03:12 +0200321 DeliverNetworkPacket(packet);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100322}
323
324void FakeNetworkPipe::ResetStats() {
325 rtc::CritScope crit(&process_lock_);
326 dropped_packets_ = 0;
327 sent_packets_ = 0;
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200328 total_packet_delay_us_ = 0;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100329}
330
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200331int64_t FakeNetworkPipe::GetTimeInMicroseconds() const {
332 return clock_->TimeInMicroseconds();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100333}
334
Erik Språng09708512018-03-14 15:16:50 +0100335} // namespace webrtc