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