Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2018 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 | |
Artem Titov | 386802e | 2019-07-05 10:48:17 +0200 | [diff] [blame] | 11 | #include "test/network/network_emulation.h" |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 12 | |
Artem Titov | 386802e | 2019-07-05 10:48:17 +0200 | [diff] [blame] | 13 | #include <algorithm> |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 14 | #include <limits> |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 15 | #include <memory> |
| 16 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 17 | #include "api/units/data_size.h" |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 18 | #include "rtc_base/bind.h" |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 19 | #include "rtc_base/logging.h" |
| 20 | |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 21 | namespace webrtc { |
| 22 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 23 | void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 24 | task_queue_->PostTask([this, packet = std::move(packet)]() mutable { |
| 25 | RTC_DCHECK_RUN_ON(task_queue_); |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 26 | |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 27 | uint64_t packet_id = next_packet_id_++; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 28 | bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo( |
| 29 | packet.ip_packet_size(), packet.arrival_time.us(), packet_id)); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 30 | if (sent) { |
| 31 | packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false}); |
| 32 | } |
| 33 | if (process_task_.Running()) |
| 34 | return; |
| 35 | absl::optional<int64_t> next_time_us = |
| 36 | network_behavior_->NextDeliveryTimeUs(); |
| 37 | if (!next_time_us) |
| 38 | return; |
| 39 | Timestamp current_time = clock_->CurrentTime(); |
| 40 | process_task_ = RepeatingTaskHandle::DelayedStart( |
| 41 | task_queue_->Get(), |
| 42 | std::max(TimeDelta::Zero(), |
| 43 | Timestamp::us(*next_time_us) - current_time), |
| 44 | [this]() { |
| 45 | RTC_DCHECK_RUN_ON(task_queue_); |
| 46 | Timestamp current_time = clock_->CurrentTime(); |
| 47 | Process(current_time); |
| 48 | absl::optional<int64_t> next_time_us = |
| 49 | network_behavior_->NextDeliveryTimeUs(); |
| 50 | if (!next_time_us) { |
| 51 | process_task_.Stop(); |
| 52 | return TimeDelta::Zero(); // This is ignored. |
| 53 | } |
| 54 | RTC_DCHECK_GE(*next_time_us, current_time.us()); |
| 55 | return Timestamp::us(*next_time_us) - current_time; |
| 56 | }); |
| 57 | }); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 58 | } |
| 59 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 60 | void LinkEmulation::Process(Timestamp at_time) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 61 | std::vector<PacketDeliveryInfo> delivery_infos = |
| 62 | network_behavior_->DequeueDeliverablePackets(at_time.us()); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 63 | for (PacketDeliveryInfo& delivery_info : delivery_infos) { |
| 64 | StoredPacket* packet = nullptr; |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 65 | for (auto& stored_packet : packets_) { |
| 66 | if (stored_packet.id == delivery_info.packet_id) { |
| 67 | packet = &stored_packet; |
| 68 | break; |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 69 | } |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 70 | } |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 71 | RTC_CHECK(packet); |
| 72 | RTC_DCHECK(!packet->removed); |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 73 | packet->removed = true; |
| 74 | |
Johannes Kron | a8f9e25 | 2019-01-24 15:38:23 +0100 | [diff] [blame] | 75 | if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) { |
| 76 | packet->packet.arrival_time = |
| 77 | Timestamp::us(delivery_info.receive_time_us); |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 78 | receiver_->OnPacketReceived(std::move(packet->packet)); |
Johannes Kron | a8f9e25 | 2019-01-24 15:38:23 +0100 | [diff] [blame] | 79 | } |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 80 | while (!packets_.empty() && packets_.front().removed) { |
| 81 | packets_.pop_front(); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 82 | } |
| 83 | } |
| 84 | } |
| 85 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 86 | NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue) |
| 87 | : task_queue_(task_queue) {} |
| 88 | |
| 89 | void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) { |
| 90 | RTC_DCHECK_RUN_ON(task_queue_); |
Sebastian Jansson | 71c6b56 | 2019-08-14 11:31:02 +0200 | [diff] [blame] | 91 | if (watcher_) { |
| 92 | watcher_(packet); |
| 93 | } |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 94 | auto receiver_it = routing_.find(packet.to.ipaddr()); |
| 95 | if (receiver_it == routing_.end()) { |
| 96 | return; |
| 97 | } |
| 98 | RTC_CHECK(receiver_it != routing_.end()); |
| 99 | |
| 100 | receiver_it->second->OnPacketReceived(std::move(packet)); |
| 101 | } |
| 102 | |
| 103 | void NetworkRouterNode::SetReceiver( |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 104 | const rtc::IPAddress& dest_ip, |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 105 | EmulatedNetworkReceiverInterface* receiver) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 106 | task_queue_->PostTask([=] { |
| 107 | RTC_DCHECK_RUN_ON(task_queue_); |
| 108 | EmulatedNetworkReceiverInterface* cur_receiver = routing_[dest_ip]; |
| 109 | RTC_CHECK(cur_receiver == nullptr || cur_receiver == receiver) |
| 110 | << "Routing for dest_ip=" << dest_ip.ToString() << " already exists"; |
| 111 | routing_[dest_ip] = receiver; |
| 112 | }); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 113 | } |
| 114 | |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 115 | void NetworkRouterNode::RemoveReceiver(const rtc::IPAddress& dest_ip) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 116 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 117 | routing_.erase(dest_ip); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 118 | } |
| 119 | |
Sebastian Jansson | 71c6b56 | 2019-08-14 11:31:02 +0200 | [diff] [blame] | 120 | void NetworkRouterNode::SetWatcher( |
| 121 | std::function<void(const EmulatedIpPacket&)> watcher) { |
| 122 | task_queue_->PostTask([=] { |
| 123 | RTC_DCHECK_RUN_ON(task_queue_); |
| 124 | watcher_ = watcher; |
| 125 | }); |
| 126 | } |
| 127 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 128 | EmulatedNetworkNode::EmulatedNetworkNode( |
| 129 | Clock* clock, |
| 130 | rtc::TaskQueue* task_queue, |
| 131 | std::unique_ptr<NetworkBehaviorInterface> network_behavior) |
| 132 | : router_(task_queue), |
| 133 | link_(clock, task_queue, std::move(network_behavior), &router_) {} |
| 134 | |
| 135 | void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) { |
| 136 | link_.OnPacketReceived(std::move(packet)); |
| 137 | } |
| 138 | |
| 139 | void EmulatedNetworkNode::CreateRoute( |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 140 | const rtc::IPAddress& receiver_ip, |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 141 | std::vector<EmulatedNetworkNode*> nodes, |
| 142 | EmulatedNetworkReceiverInterface* receiver) { |
| 143 | RTC_CHECK(!nodes.empty()); |
| 144 | for (size_t i = 0; i + 1 < nodes.size(); ++i) |
| 145 | nodes[i]->router()->SetReceiver(receiver_ip, nodes[i + 1]); |
| 146 | nodes.back()->router()->SetReceiver(receiver_ip, receiver); |
| 147 | } |
| 148 | |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 149 | void EmulatedNetworkNode::ClearRoute(const rtc::IPAddress& receiver_ip, |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 150 | std::vector<EmulatedNetworkNode*> nodes) { |
| 151 | for (EmulatedNetworkNode* node : nodes) |
| 152 | node->router()->RemoveReceiver(receiver_ip); |
| 153 | } |
| 154 | |
| 155 | EmulatedNetworkNode::~EmulatedNetworkNode() = default; |
| 156 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 157 | EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id, |
| 158 | const rtc::IPAddress& ip, |
| 159 | bool is_enabled, |
| 160 | rtc::TaskQueue* task_queue, |
| 161 | Clock* clock) |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 162 | : id_(id), |
| 163 | peer_local_addr_(ip), |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 164 | is_enabled_(is_enabled), |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 165 | clock_(clock), |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 166 | task_queue_(task_queue), |
| 167 | router_(task_queue_), |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 168 | next_port_(kFirstEphemeralPort) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 169 | constexpr int kIPv4NetworkPrefixLength = 24; |
| 170 | constexpr int kIPv6NetworkPrefixLength = 64; |
| 171 | |
| 172 | int prefix_length = 0; |
| 173 | if (ip.family() == AF_INET) { |
| 174 | prefix_length = kIPv4NetworkPrefixLength; |
| 175 | } else if (ip.family() == AF_INET6) { |
| 176 | prefix_length = kIPv6NetworkPrefixLength; |
| 177 | } |
| 178 | rtc::IPAddress prefix = TruncateIP(ip, prefix_length); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 179 | network_ = std::make_unique<rtc::Network>( |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 180 | ip.ToString(), "Endpoint id=" + std::to_string(id_), prefix, |
| 181 | prefix_length, rtc::AdapterType::ADAPTER_TYPE_UNKNOWN); |
| 182 | network_->AddIP(ip); |
| 183 | |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 184 | enabled_state_checker_.Detach(); |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 185 | } |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 186 | EmulatedEndpointImpl::~EmulatedEndpointImpl() = default; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 187 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 188 | uint64_t EmulatedEndpointImpl::GetId() const { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 189 | return id_; |
| 190 | } |
| 191 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 192 | void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from, |
| 193 | const rtc::SocketAddress& to, |
| 194 | rtc::CopyOnWriteBuffer packet_data) { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 195 | RTC_CHECK(from.ipaddr() == peer_local_addr_); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 196 | EmulatedIpPacket packet(from, to, std::move(packet_data), |
| 197 | clock_->CurrentTime()); |
| 198 | task_queue_->PostTask([this, packet = std::move(packet)]() mutable { |
| 199 | RTC_DCHECK_RUN_ON(task_queue_); |
| 200 | Timestamp current_time = clock_->CurrentTime(); |
| 201 | if (stats_.first_packet_sent_time.IsInfinite()) { |
| 202 | stats_.first_packet_sent_time = current_time; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 203 | stats_.first_sent_packet_size = DataSize::bytes(packet.ip_packet_size()); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 204 | } |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 205 | stats_.last_packet_sent_time = current_time; |
| 206 | stats_.packets_sent++; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 207 | stats_.bytes_sent += DataSize::bytes(packet.ip_packet_size()); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 208 | |
| 209 | router_.OnPacketReceived(std::move(packet)); |
| 210 | }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 211 | } |
| 212 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 213 | absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver( |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 214 | uint16_t desired_port, |
| 215 | EmulatedNetworkReceiverInterface* receiver) { |
| 216 | rtc::CritScope crit(&receiver_lock_); |
| 217 | uint16_t port = desired_port; |
| 218 | if (port == 0) { |
| 219 | // Because client can specify its own port, next_port_ can be already in |
| 220 | // use, so we need to find next available port. |
| 221 | int ports_pool_size = |
| 222 | std::numeric_limits<uint16_t>::max() - kFirstEphemeralPort + 1; |
| 223 | for (int i = 0; i < ports_pool_size; ++i) { |
| 224 | uint16_t next_port = NextPort(); |
| 225 | if (port_to_receiver_.find(next_port) == port_to_receiver_.end()) { |
| 226 | port = next_port; |
| 227 | break; |
| 228 | } |
| 229 | } |
| 230 | } |
| 231 | RTC_CHECK(port != 0) << "Can't find free port for receiver in endpoint " |
| 232 | << id_; |
| 233 | bool result = port_to_receiver_.insert({port, receiver}).second; |
| 234 | if (!result) { |
| 235 | RTC_LOG(INFO) << "Can't bind receiver to used port " << desired_port |
| 236 | << " in endpoint " << id_; |
| 237 | return absl::nullopt; |
| 238 | } |
| 239 | RTC_LOG(INFO) << "New receiver is binded to endpoint " << id_ << " on port " |
| 240 | << port; |
| 241 | return port; |
| 242 | } |
| 243 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 244 | uint16_t EmulatedEndpointImpl::NextPort() { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 245 | uint16_t out = next_port_; |
| 246 | if (next_port_ == std::numeric_limits<uint16_t>::max()) { |
| 247 | next_port_ = kFirstEphemeralPort; |
| 248 | } else { |
| 249 | next_port_++; |
| 250 | } |
| 251 | return out; |
| 252 | } |
| 253 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 254 | void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 255 | rtc::CritScope crit(&receiver_lock_); |
| 256 | port_to_receiver_.erase(port); |
| 257 | } |
| 258 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 259 | rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 260 | return peer_local_addr_; |
| 261 | } |
| 262 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 263 | void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) { |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 264 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 265 | RTC_CHECK(packet.to.ipaddr() == peer_local_addr_) |
| 266 | << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: " |
| 267 | << packet.to.ipaddr().ToString() |
| 268 | << "; Receiver peer_local_addr_=" << peer_local_addr_.ToString(); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 269 | rtc::CritScope crit(&receiver_lock_); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 270 | UpdateReceiveStats(packet); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 271 | auto it = port_to_receiver_.find(packet.to.port()); |
| 272 | if (it == port_to_receiver_.end()) { |
| 273 | // It can happen, that remote peer closed connection, but there still some |
| 274 | // packets, that are going to it. It can happen during peer connection close |
| 275 | // process: one peer closed connection, second still sending data. |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 276 | RTC_LOG(INFO) << "Drop packet: no receiver registered in " << id_ |
| 277 | << " on port " << packet.to.port(); |
| 278 | stats_.packets_dropped++; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 279 | stats_.bytes_dropped += DataSize::bytes(packet.ip_packet_size()); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 280 | return; |
| 281 | } |
| 282 | // Endpoint assumes frequent calls to bind and unbind methods, so it holds |
| 283 | // lock during packet processing to ensure that receiver won't be deleted |
| 284 | // before call to OnPacketReceived. |
| 285 | it->second->OnPacketReceived(std::move(packet)); |
| 286 | } |
| 287 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 288 | void EmulatedEndpointImpl::Enable() { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 289 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 290 | RTC_CHECK(!is_enabled_); |
| 291 | is_enabled_ = true; |
| 292 | } |
| 293 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 294 | void EmulatedEndpointImpl::Disable() { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 295 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 296 | RTC_CHECK(is_enabled_); |
| 297 | is_enabled_ = false; |
| 298 | } |
| 299 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 300 | bool EmulatedEndpointImpl::Enabled() const { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 301 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 302 | return is_enabled_; |
| 303 | } |
| 304 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 305 | EmulatedNetworkStats EmulatedEndpointImpl::stats() { |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 306 | RTC_DCHECK_RUN_ON(task_queue_); |
| 307 | return stats_; |
| 308 | } |
| 309 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 310 | void EmulatedEndpointImpl::UpdateReceiveStats(const EmulatedIpPacket& packet) { |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 311 | RTC_DCHECK_RUN_ON(task_queue_); |
Sebastian Jansson | b64ad0e | 2019-06-19 09:39:34 +0200 | [diff] [blame] | 312 | Timestamp current_time = clock_->CurrentTime(); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 313 | if (stats_.first_packet_received_time.IsInfinite()) { |
| 314 | stats_.first_packet_received_time = current_time; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 315 | stats_.first_received_packet_size = |
| 316 | DataSize::bytes(packet.ip_packet_size()); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 317 | } |
| 318 | stats_.last_packet_received_time = current_time; |
| 319 | stats_.packets_received++; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 320 | stats_.bytes_received += DataSize::bytes(packet.ip_packet_size()); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 321 | } |
| 322 | |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 323 | EndpointsContainer::EndpointsContainer( |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 324 | const std::vector<EmulatedEndpointImpl*>& endpoints) |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 325 | : endpoints_(endpoints) {} |
| 326 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 327 | EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress( |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 328 | const rtc::IPAddress& local_ip) const { |
| 329 | for (auto* endpoint : endpoints_) { |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 330 | rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress(); |
| 331 | if (peer_local_address == local_ip) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 332 | return endpoint; |
| 333 | } |
| 334 | } |
| 335 | RTC_CHECK(false) << "No network found for address" << local_ip.ToString(); |
| 336 | } |
| 337 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 338 | bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 339 | for (auto* e : endpoints_) { |
| 340 | if (e->GetId() == endpoint->GetId()) { |
| 341 | return true; |
| 342 | } |
| 343 | } |
| 344 | return false; |
| 345 | } |
| 346 | |
| 347 | std::vector<std::unique_ptr<rtc::Network>> |
| 348 | EndpointsContainer::GetEnabledNetworks() const { |
| 349 | std::vector<std::unique_ptr<rtc::Network>> networks; |
| 350 | for (auto* endpoint : endpoints_) { |
| 351 | if (endpoint->Enabled()) { |
| 352 | networks.emplace_back( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 353 | std::make_unique<rtc::Network>(endpoint->network())); |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 354 | } |
| 355 | } |
| 356 | return networks; |
| 357 | } |
| 358 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 359 | EmulatedNetworkStats EndpointsContainer::GetStats() const { |
| 360 | EmulatedNetworkStats stats; |
| 361 | for (auto* endpoint : endpoints_) { |
| 362 | EmulatedNetworkStats endpoint_stats = endpoint->stats(); |
| 363 | stats.packets_sent += endpoint_stats.packets_sent; |
| 364 | stats.bytes_sent += endpoint_stats.bytes_sent; |
| 365 | stats.packets_received += endpoint_stats.packets_received; |
| 366 | stats.bytes_received += endpoint_stats.bytes_received; |
| 367 | stats.packets_dropped += endpoint_stats.packets_dropped; |
| 368 | stats.bytes_dropped += endpoint_stats.bytes_dropped; |
| 369 | if (stats.first_packet_received_time > |
| 370 | endpoint_stats.first_packet_received_time) { |
| 371 | stats.first_packet_received_time = |
| 372 | endpoint_stats.first_packet_received_time; |
| 373 | stats.first_received_packet_size = |
| 374 | endpoint_stats.first_received_packet_size; |
| 375 | } |
| 376 | if (stats.first_packet_sent_time > endpoint_stats.first_packet_sent_time) { |
| 377 | stats.first_packet_sent_time = endpoint_stats.first_packet_sent_time; |
| 378 | stats.first_sent_packet_size = endpoint_stats.first_sent_packet_size; |
| 379 | } |
| 380 | if (stats.last_packet_received_time.IsInfinite() || |
| 381 | stats.last_packet_received_time < |
| 382 | endpoint_stats.last_packet_received_time) { |
| 383 | stats.last_packet_received_time = |
| 384 | endpoint_stats.last_packet_received_time; |
| 385 | } |
| 386 | if (stats.last_packet_sent_time.IsInfinite() || |
| 387 | stats.last_packet_sent_time < endpoint_stats.last_packet_sent_time) { |
| 388 | stats.last_packet_sent_time = endpoint_stats.last_packet_sent_time; |
| 389 | } |
| 390 | } |
| 391 | return stats; |
| 392 | } |
| 393 | |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 394 | } // namespace webrtc |