blob: 8844700e67ac9acea1183f37af1957de493a4029 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "call/fake_network_pipe.h"
12
Erik Språng09708512018-03-14 15:16:50 +010013#include <string.h>
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Erik Språng09708512018-03-14 15:16:50 +010015#include <algorithm>
Yves Gerey3e707812018-11-28 16:47:49 +010016#include <queue>
Erik Språng09708512018-03-14 15:16:50 +010017#include <utility>
Yves Gerey3e707812018-11-28 16:47:49 +010018#include <vector>
Erik Språng09708512018-03-14 15:16:50 +010019
Steve Anton10542f22019-01-11 09:11:00 -080020#include "api/media_types.h"
Sebastian Jansson71822862018-10-30 08:23:27 +010021#include "modules/utility/include/process_thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "rtc_base/checks.h"
Erik Språng09708512018-03-14 15:16:50 +010023#include "rtc_base/logging.h"
24#include "system_wrappers/include/clock.h"
25
26namespace webrtc {
27
28namespace {
Sebastian Jansson512bdce2018-04-23 13:15:04 +020029constexpr int64_t kLogIntervalMs = 5000;
Erik Språng09708512018-03-14 15:16:50 +010030} // namespace
31
32NetworkPacket::NetworkPacket(rtc::CopyOnWriteBuffer packet,
33 int64_t send_time,
34 int64_t arrival_time,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +020035 absl::optional<PacketOptions> packet_options,
Erik Språng09708512018-03-14 15:16:50 +010036 bool is_rtcp,
37 MediaType media_type,
Erik Språngeea605d2019-08-12 15:56:51 +020038 absl::optional<int64_t> packet_time_us,
39 Transport* transport)
Erik Språng09708512018-03-14 15:16:50 +010040 : packet_(std::move(packet)),
41 send_time_(send_time),
42 arrival_time_(arrival_time),
43 packet_options_(packet_options),
44 is_rtcp_(is_rtcp),
45 media_type_(media_type),
Erik Språngeea605d2019-08-12 15:56:51 +020046 packet_time_us_(packet_time_us),
47 transport_(transport) {}
Artem Titov537b7fe2018-08-16 11:20:45 +020048
Erik Språng09708512018-03-14 15:16:50 +010049NetworkPacket::NetworkPacket(NetworkPacket&& o)
50 : packet_(std::move(o.packet_)),
51 send_time_(o.send_time_),
52 arrival_time_(o.arrival_time_),
53 packet_options_(o.packet_options_),
54 is_rtcp_(o.is_rtcp_),
55 media_type_(o.media_type_),
Erik Språngeea605d2019-08-12 15:56:51 +020056 packet_time_us_(o.packet_time_us_),
57 transport_(o.transport_) {}
Erik Språng09708512018-03-14 15:16:50 +010058
Mirko Bonadeied1dcf92018-07-26 09:15:11 +020059NetworkPacket::~NetworkPacket() = default;
60
Erik Språng09708512018-03-14 15:16:50 +010061NetworkPacket& NetworkPacket::operator=(NetworkPacket&& o) {
62 packet_ = std::move(o.packet_);
63 send_time_ = o.send_time_;
64 arrival_time_ = o.arrival_time_;
65 packet_options_ = o.packet_options_;
66 is_rtcp_ = o.is_rtcp_;
67 media_type_ = o.media_type_;
Niels Möller70082872018-08-07 11:03:12 +020068 packet_time_us_ = o.packet_time_us_;
Erik Språngeea605d2019-08-12 15:56:51 +020069 transport_ = o.transport_;
Erik Språng09708512018-03-14 15:16:50 +010070
71 return *this;
72}
73
Artem Titovb0050872018-08-16 17:02:20 +020074FakeNetworkPipe::FakeNetworkPipe(
75 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020076 std::unique_ptr<NetworkBehaviorInterface> network_behavior)
77 : FakeNetworkPipe(clock, std::move(network_behavior), nullptr, 1) {}
Artem Titovb0050872018-08-16 17:02:20 +020078
79FakeNetworkPipe::FakeNetworkPipe(
80 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020081 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +020082 PacketReceiver* receiver)
Artem Titov8ea1e9d2018-10-04 14:46:31 +020083 : FakeNetworkPipe(clock, std::move(network_behavior), receiver, 1) {}
Artem Titovb0050872018-08-16 17:02:20 +020084
85FakeNetworkPipe::FakeNetworkPipe(
86 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +020087 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +020088 PacketReceiver* receiver,
89 uint64_t seed)
90 : clock_(clock),
Artem Titov8ea1e9d2018-10-04 14:46:31 +020091 network_behavior_(std::move(network_behavior)),
Artem Titovb0050872018-08-16 17:02:20 +020092 receiver_(receiver),
Erik Språngeea605d2019-08-12 15:56:51 +020093 global_transport_(nullptr),
Artem Titovb0050872018-08-16 17:02:20 +020094 clock_offset_ms_(0),
95 dropped_packets_(0),
96 sent_packets_(0),
97 total_packet_delay_us_(0),
Artem Titovb0050872018-08-16 17:02:20 +020098 last_log_time_us_(clock_->TimeInMicroseconds()) {}
99
100FakeNetworkPipe::FakeNetworkPipe(
101 Clock* clock,
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200102 std::unique_ptr<NetworkBehaviorInterface> network_behavior,
Artem Titovb0050872018-08-16 17:02:20 +0200103 Transport* transport)
104 : clock_(clock),
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200105 network_behavior_(std::move(network_behavior)),
Artem Titovb0050872018-08-16 17:02:20 +0200106 receiver_(nullptr),
Erik Språngeea605d2019-08-12 15:56:51 +0200107 global_transport_(transport),
Artem Titovb0050872018-08-16 17:02:20 +0200108 clock_offset_ms_(0),
109 dropped_packets_(0),
110 sent_packets_(0),
111 total_packet_delay_us_(0),
Erik Språngeea605d2019-08-12 15:56:51 +0200112 last_log_time_us_(clock_->TimeInMicroseconds()) {
113 RTC_DCHECK(global_transport_);
114 AddActiveTransport(global_transport_);
115}
Artem Titovb0050872018-08-16 17:02:20 +0200116
Erik Språngeea605d2019-08-12 15:56:51 +0200117FakeNetworkPipe::~FakeNetworkPipe() {
118 if (global_transport_) {
119 RemoveActiveTransport(global_transport_);
120 }
121 RTC_DCHECK(active_transports_.empty());
122}
Erik Språng09708512018-03-14 15:16:50 +0100123
124void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
125 rtc::CritScope crit(&config_lock_);
Erik Språng09708512018-03-14 15:16:50 +0100126 receiver_ = receiver;
127}
128
Erik Språngeea605d2019-08-12 15:56:51 +0200129void FakeNetworkPipe::AddActiveTransport(Transport* transport) {
130 rtc::CritScope crit(&config_lock_);
131 active_transports_[transport]++;
132}
133
134void FakeNetworkPipe::RemoveActiveTransport(Transport* transport) {
135 rtc::CritScope crit(&config_lock_);
136 auto it = active_transports_.find(transport);
137 RTC_CHECK(it != active_transports_.end());
138 if (--(it->second) == 0) {
139 active_transports_.erase(it);
140 }
141}
142
Erik Språng09708512018-03-14 15:16:50 +0100143bool FakeNetworkPipe::SendRtp(const uint8_t* packet,
144 size_t length,
145 const PacketOptions& options) {
Erik Språngeea605d2019-08-12 15:56:51 +0200146 RTC_DCHECK(global_transport_);
Erik Språng09708512018-03-14 15:16:50 +0100147 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), options, false,
Erik Språngeea605d2019-08-12 15:56:51 +0200148 global_transport_);
Erik Språng09708512018-03-14 15:16:50 +0100149 return true;
150}
151
152bool FakeNetworkPipe::SendRtcp(const uint8_t* packet, size_t length) {
Erik Språngeea605d2019-08-12 15:56:51 +0200153 RTC_DCHECK(global_transport_);
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200154 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), absl::nullopt, true,
Erik Språngeea605d2019-08-12 15:56:51 +0200155 global_transport_);
156 return true;
157}
158
159bool FakeNetworkPipe::SendRtp(const uint8_t* packet,
160 size_t length,
161 const PacketOptions& options,
162 Transport* transport) {
163 RTC_DCHECK(transport);
164 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), options, false,
165 transport);
166 return true;
167}
168
169bool FakeNetworkPipe::SendRtcp(const uint8_t* packet,
170 size_t length,
171 Transport* transport) {
172 RTC_DCHECK(transport);
173 EnqueuePacket(rtc::CopyOnWriteBuffer(packet, length), absl::nullopt, true,
174 transport);
Erik Språng09708512018-03-14 15:16:50 +0100175 return true;
176}
177
178PacketReceiver::DeliveryStatus FakeNetworkPipe::DeliverPacket(
179 MediaType media_type,
180 rtc::CopyOnWriteBuffer packet,
Niels Möller70082872018-08-07 11:03:12 +0200181 int64_t packet_time_us) {
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200182 return EnqueuePacket(std::move(packet), absl::nullopt, false, media_type,
Niels Möller70082872018-08-07 11:03:12 +0200183 packet_time_us)
Erik Språng09708512018-03-14 15:16:50 +0100184 ? PacketReceiver::DELIVERY_OK
185 : PacketReceiver::DELIVERY_PACKET_ERROR;
186}
187
Sebastian Jansson7e85d672018-04-06 09:56:21 +0200188void FakeNetworkPipe::SetClockOffset(int64_t offset_ms) {
189 rtc::CritScope crit(&config_lock_);
190 clock_offset_ms_ = offset_ms;
191}
192
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200193FakeNetworkPipe::StoredPacket::StoredPacket(NetworkPacket&& packet)
194 : packet(std::move(packet)) {}
195
196bool FakeNetworkPipe::EnqueuePacket(rtc::CopyOnWriteBuffer packet,
Danil Chapovalovb9b146c2018-06-15 12:28:07 +0200197 absl::optional<PacketOptions> options,
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200198 bool is_rtcp,
199 MediaType media_type,
Niels Möller70082872018-08-07 11:03:12 +0200200 absl::optional<int64_t> packet_time_us) {
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200201 rtc::CritScope crit(&process_lock_);
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200202 int64_t time_now_us = clock_->TimeInMicroseconds();
Erik Språngeea605d2019-08-12 15:56:51 +0200203 return EnqueuePacket(NetworkPacket(std::move(packet), time_now_us,
204 time_now_us, options, is_rtcp, media_type,
205 packet_time_us, nullptr));
206}
207
208bool FakeNetworkPipe::EnqueuePacket(rtc::CopyOnWriteBuffer packet,
209 absl::optional<PacketOptions> options,
210 bool is_rtcp,
211 Transport* transport) {
212 rtc::CritScope crit(&process_lock_);
213 int64_t time_now_us = clock_->TimeInMicroseconds();
214 return EnqueuePacket(NetworkPacket(std::move(packet), time_now_us,
215 time_now_us, options, is_rtcp,
216 MediaType::ANY, absl::nullopt, transport));
217}
218
219bool FakeNetworkPipe::EnqueuePacket(NetworkPacket&& net_packet) {
220 int64_t send_time_us = net_packet.send_time();
221 size_t packet_size = net_packet.data_length();
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200222
223 packets_in_flight_.emplace_back(StoredPacket(std::move(net_packet)));
224 int64_t packet_id = reinterpret_cast<uint64_t>(&packets_in_flight_.back());
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200225 bool sent = network_behavior_->EnqueuePacket(
Erik Språngeea605d2019-08-12 15:56:51 +0200226 PacketInFlightInfo(packet_size, send_time_us, packet_id));
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200227
228 if (!sent) {
229 packets_in_flight_.pop_back();
230 ++dropped_packets_;
231 }
232 return sent;
233}
234
Erik Språng09708512018-03-14 15:16:50 +0100235float FakeNetworkPipe::PercentageLoss() {
236 rtc::CritScope crit(&process_lock_);
237 if (sent_packets_ == 0)
238 return 0;
239
240 return static_cast<float>(dropped_packets_) /
241 (sent_packets_ + dropped_packets_);
242}
243
244int FakeNetworkPipe::AverageDelay() {
245 rtc::CritScope crit(&process_lock_);
246 if (sent_packets_ == 0)
247 return 0;
248
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200249 return static_cast<int>(total_packet_delay_us_ /
250 (1000 * static_cast<int64_t>(sent_packets_)));
Erik Språng09708512018-03-14 15:16:50 +0100251}
252
253size_t FakeNetworkPipe::DroppedPackets() {
254 rtc::CritScope crit(&process_lock_);
255 return dropped_packets_;
256}
257
258size_t FakeNetworkPipe::SentPackets() {
259 rtc::CritScope crit(&process_lock_);
260 return sent_packets_;
261}
262
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200263void FakeNetworkPipe::Process() {
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200264 int64_t time_now_us;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200265 std::queue<NetworkPacket> packets_to_deliver;
266 {
267 rtc::CritScope crit(&process_lock_);
Christoffer Rodbro1803bb22018-10-25 12:39:49 +0200268 time_now_us = clock_->TimeInMicroseconds();
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200269 if (time_now_us - last_log_time_us_ > kLogIntervalMs * 1000) {
270 int64_t queueing_delay_us = 0;
271 if (!packets_in_flight_.empty())
272 queueing_delay_us =
273 time_now_us - packets_in_flight_.front().packet.send_time();
274
275 RTC_LOG(LS_INFO) << "Network queue: " << queueing_delay_us / 1000
276 << " ms.";
277 last_log_time_us_ = time_now_us;
278 }
279
280 std::vector<PacketDeliveryInfo> delivery_infos =
Artem Titov8ea1e9d2018-10-04 14:46:31 +0200281 network_behavior_->DequeueDeliverablePackets(time_now_us);
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200282 for (auto& delivery_info : delivery_infos) {
283 // In the common case where no reordering happens, find will return early
284 // as the first packet will be a match.
285 auto packet_it =
286 std::find_if(packets_in_flight_.begin(), packets_in_flight_.end(),
287 [&delivery_info](StoredPacket& packet_ref) {
288 return reinterpret_cast<uint64_t>(&packet_ref) ==
289 delivery_info.packet_id;
290 });
291 // Check that the packet is in the deque of packets in flight.
292 RTC_CHECK(packet_it != packets_in_flight_.end());
293 // Check that the packet is not already removed.
294 RTC_DCHECK(!packet_it->removed);
295
296 NetworkPacket packet = std::move(packet_it->packet);
297 packet_it->removed = true;
298
299 // Cleanup of removed packets at the beginning of the deque.
300 while (!packets_in_flight_.empty() &&
301 packets_in_flight_.front().removed) {
302 packets_in_flight_.pop_front();
303 }
304
305 if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) {
306 int64_t added_delay_us =
307 delivery_info.receive_time_us - packet.send_time();
308 packet.IncrementArrivalTime(added_delay_us);
309 packets_to_deliver.emplace(std::move(packet));
310 // |time_now_us| might be later than when the packet should have
311 // arrived, due to NetworkProcess being called too late. For stats, use
312 // the time it should have been on the link.
313 total_packet_delay_us_ += added_delay_us;
Christoffer Rodbro3284b612018-10-23 16:51:51 +0200314 ++sent_packets_;
315 } else {
316 ++dropped_packets_;
Sebastian Jansson7ee2e252018-05-07 14:49:39 +0200317 }
Erik Språng09708512018-03-14 15:16:50 +0100318 }
Erik Språng09708512018-03-14 15:16:50 +0100319 }
320
321 rtc::CritScope crit(&config_lock_);
322 while (!packets_to_deliver.empty()) {
323 NetworkPacket packet = std::move(packets_to_deliver.front());
324 packets_to_deliver.pop();
Niels Möller70082872018-08-07 11:03:12 +0200325 DeliverNetworkPacket(&packet);
Erik Språng09708512018-03-14 15:16:50 +0100326 }
Erik Språng09708512018-03-14 15:16:50 +0100327}
328
Niels Möller70082872018-08-07 11:03:12 +0200329void FakeNetworkPipe::DeliverNetworkPacket(NetworkPacket* packet) {
Erik Språngeea605d2019-08-12 15:56:51 +0200330 Transport* transport = packet->transport();
331 if (transport) {
Sebastian Janssona44ab182018-04-06 12:59:14 +0200332 RTC_DCHECK(!receiver_);
Erik Språngeea605d2019-08-12 15:56:51 +0200333 if (active_transports_.find(transport) == active_transports_.end()) {
334 // Transport has been destroyed, ignore this packet.
335 return;
336 }
Erik Språng09708512018-03-14 15:16:50 +0100337 if (packet->is_rtcp()) {
Erik Språngeea605d2019-08-12 15:56:51 +0200338 transport->SendRtcp(packet->data(), packet->data_length());
Erik Språng09708512018-03-14 15:16:50 +0100339 } else {
Erik Språngeea605d2019-08-12 15:56:51 +0200340 transport->SendRtp(packet->data(), packet->data_length(),
341 packet->packet_options());
Erik Språng09708512018-03-14 15:16:50 +0100342 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200343 } else if (receiver_) {
Niels Möller70082872018-08-07 11:03:12 +0200344 int64_t packet_time_us = packet->packet_time_us().value_or(-1);
345 if (packet_time_us != -1) {
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200346 int64_t queue_time_us = packet->arrival_time() - packet->send_time();
347 RTC_CHECK(queue_time_us >= 0);
Niels Möller70082872018-08-07 11:03:12 +0200348 packet_time_us += queue_time_us;
349 packet_time_us += (clock_offset_ms_ * 1000);
Erik Språng09708512018-03-14 15:16:50 +0100350 }
Sebastian Jansson09408112018-04-24 14:41:22 +0200351 receiver_->DeliverPacket(packet->media_type(),
Niels Möller70082872018-08-07 11:03:12 +0200352 std::move(*packet->raw_packet()), packet_time_us);
Erik Språng09708512018-03-14 15:16:50 +0100353 }
354}
355
Sebastian Jansson836fee12019-02-08 16:08:10 +0100356absl::optional<int64_t> FakeNetworkPipe::TimeUntilNextProcess() {
Erik Språng09708512018-03-14 15:16:50 +0100357 rtc::CritScope crit(&process_lock_);
Sebastian Jansson71822862018-10-30 08:23:27 +0100358 absl::optional<int64_t> delivery_us = network_behavior_->NextDeliveryTimeUs();
359 if (delivery_us) {
360 int64_t delay_us = *delivery_us - clock_->TimeInMicroseconds();
361 return std::max<int64_t>((delay_us + 500) / 1000, 0);
362 }
Sebastian Jansson836fee12019-02-08 16:08:10 +0100363 return absl::nullopt;
Erik Språng09708512018-03-14 15:16:50 +0100364}
365
Sebastian Jansson09408112018-04-24 14:41:22 +0200366bool FakeNetworkPipe::HasReceiver() const {
Erik Språng09708512018-03-14 15:16:50 +0100367 rtc::CritScope crit(&config_lock_);
Sebastian Jansson09408112018-04-24 14:41:22 +0200368 return receiver_ != nullptr;
Erik Språng09708512018-03-14 15:16:50 +0100369}
370
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100371void FakeNetworkPipe::DeliverPacketWithLock(NetworkPacket* packet) {
372 rtc::CritScope crit(&config_lock_);
Niels Möller70082872018-08-07 11:03:12 +0200373 DeliverNetworkPacket(packet);
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100374}
375
376void FakeNetworkPipe::ResetStats() {
377 rtc::CritScope crit(&process_lock_);
378 dropped_packets_ = 0;
379 sent_packets_ = 0;
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200380 total_packet_delay_us_ = 0;
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100381}
382
Sebastian Jansson512bdce2018-04-23 13:15:04 +0200383int64_t FakeNetworkPipe::GetTimeInMicroseconds() const {
384 return clock_->TimeInMicroseconds();
Christoffer Rodbro8ef59a42018-03-20 14:34:01 +0100385}
386
Erik Språng09708512018-03-14 15:16:50 +0100387} // namespace webrtc