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> |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 16 | #include <utility> |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 17 | |
Artem Titov | d2dd732 | 2021-01-21 17:28:17 +0100 | [diff] [blame] | 18 | #include "absl/types/optional.h" |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 19 | #include "api/numerics/samples_stats_counter.h" |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 20 | #include "api/test/network_emulation/network_emulation_interfaces.h" |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 21 | #include "api/units/data_size.h" |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 22 | #include "rtc_base/logging.h" |
| 23 | |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 24 | namespace webrtc { |
| 25 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 26 | DataRate EmulatedNetworkOutgoingStatsImpl::AverageSendRate() const { |
| 27 | RTC_DCHECK_GE(packets_sent_, 2); |
| 28 | RTC_DCHECK(first_packet_sent_time_.IsFinite()); |
| 29 | RTC_DCHECK(last_packet_sent_time_.IsFinite()); |
| 30 | return (bytes_sent_ - first_sent_packet_size_) / |
| 31 | (last_packet_sent_time_ - first_packet_sent_time_); |
| 32 | } |
| 33 | |
| 34 | DataRate EmulatedNetworkIncomingStatsImpl::AverageReceiveRate() const { |
| 35 | RTC_DCHECK_GE(packets_received_, 2); |
| 36 | RTC_DCHECK(first_packet_received_time_.IsFinite()); |
| 37 | RTC_DCHECK(last_packet_received_time_.IsFinite()); |
| 38 | return (bytes_received_ - first_received_packet_size_) / |
| 39 | (last_packet_received_time_ - first_packet_received_time_); |
| 40 | } |
| 41 | |
| 42 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 43 | EmulatedNetworkStatsImpl::OutgoingStatsPerDestination() const { |
| 44 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> out; |
| 45 | for (const auto& entry : outgoing_stats_per_destination_) { |
| 46 | out.emplace(entry.first, std::make_unique<EmulatedNetworkOutgoingStatsImpl>( |
| 47 | *entry.second)); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 48 | } |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 49 | return out; |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 50 | } |
| 51 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 52 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 53 | EmulatedNetworkStatsImpl::IncomingStatsPerSource() const { |
| 54 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> out; |
| 55 | for (const auto& entry : incoming_stats_per_source_) { |
| 56 | out.emplace(entry.first, std::make_unique<EmulatedNetworkIncomingStatsImpl>( |
| 57 | *entry.second)); |
| 58 | } |
| 59 | return out; |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 60 | } |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 61 | |
| 62 | std::unique_ptr<EmulatedNetworkOutgoingStats> |
| 63 | EmulatedNetworkStatsImpl::GetOverallOutgoingStats() const { |
| 64 | EmulatedNetworkOutgoingStatsBuilder builder; |
| 65 | for (const auto& entry : outgoing_stats_per_destination_) { |
| 66 | builder.AddOutgoingStats(*entry.second); |
| 67 | } |
| 68 | return builder.Build(); |
| 69 | } |
| 70 | |
| 71 | std::unique_ptr<EmulatedNetworkIncomingStats> |
| 72 | EmulatedNetworkStatsImpl::GetOverallIncomingStats() const { |
| 73 | EmulatedNetworkIncomingStatsBuilder builder; |
| 74 | for (const auto& entry : incoming_stats_per_source_) { |
| 75 | builder.AddIncomingStats(*entry.second); |
| 76 | } |
| 77 | return builder.Build(); |
| 78 | } |
| 79 | |
| 80 | EmulatedNetworkOutgoingStatsBuilder::EmulatedNetworkOutgoingStatsBuilder() { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 81 | sequence_checker_.Detach(); |
| 82 | } |
| 83 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 84 | void EmulatedNetworkOutgoingStatsBuilder::OnPacketSent( |
| 85 | Timestamp sent_time, |
| 86 | DataSize packet_size, |
| 87 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 88 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 89 | RTC_CHECK_GE(packet_size, DataSize::Zero()); |
| 90 | if (first_packet_sent_time_.IsInfinite()) { |
| 91 | first_packet_sent_time_ = sent_time; |
| 92 | first_sent_packet_size_ = packet_size; |
| 93 | } |
| 94 | last_packet_sent_time_ = sent_time; |
| 95 | packets_sent_++; |
| 96 | bytes_sent_ += packet_size; |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 97 | if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) { |
| 98 | sent_packets_size_counter_.AddSample(packet_size.bytes()); |
| 99 | } |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 100 | } |
| 101 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 102 | void EmulatedNetworkOutgoingStatsBuilder::AddOutgoingStats( |
| 103 | const EmulatedNetworkOutgoingStats& stats) { |
| 104 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 105 | packets_sent_ += stats.PacketsSent(); |
| 106 | bytes_sent_ += stats.BytesSent(); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 107 | sent_packets_size_counter_.AddSamples(stats.SentPacketsSizeCounter()); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 108 | if (first_packet_sent_time_ > stats.FirstPacketSentTime()) { |
| 109 | first_packet_sent_time_ = stats.FirstPacketSentTime(); |
| 110 | first_sent_packet_size_ = stats.FirstSentPacketSize(); |
| 111 | } |
| 112 | if (last_packet_sent_time_ < stats.LastPacketSentTime()) { |
| 113 | last_packet_sent_time_ = stats.LastPacketSentTime(); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | std::unique_ptr<EmulatedNetworkOutgoingStats> |
| 118 | EmulatedNetworkOutgoingStatsBuilder::Build() const { |
| 119 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 120 | return std::make_unique<EmulatedNetworkOutgoingStatsImpl>( |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 121 | packets_sent_, bytes_sent_, sent_packets_size_counter_, |
| 122 | first_sent_packet_size_, first_packet_sent_time_, last_packet_sent_time_); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | EmulatedNetworkIncomingStatsBuilder::EmulatedNetworkIncomingStatsBuilder() { |
| 126 | sequence_checker_.Detach(); |
| 127 | } |
| 128 | |
| 129 | void EmulatedNetworkIncomingStatsBuilder::OnPacketDropped( |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 130 | DataSize packet_size, |
| 131 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 132 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 133 | packets_dropped_++; |
| 134 | bytes_dropped_ += packet_size; |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 135 | if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) { |
| 136 | dropped_packets_size_counter_.AddSample(packet_size.bytes()); |
| 137 | } |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | void EmulatedNetworkIncomingStatsBuilder::OnPacketReceived( |
| 141 | Timestamp received_time, |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 142 | DataSize packet_size, |
| 143 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 144 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 145 | RTC_CHECK_GE(packet_size, DataSize::Zero()); |
| 146 | if (first_packet_received_time_.IsInfinite()) { |
| 147 | first_packet_received_time_ = received_time; |
| 148 | first_received_packet_size_ = packet_size; |
| 149 | } |
| 150 | last_packet_received_time_ = received_time; |
| 151 | packets_received_++; |
| 152 | bytes_received_ += packet_size; |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 153 | if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) { |
| 154 | received_packets_size_counter_.AddSample(packet_size.bytes()); |
| 155 | } |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 156 | } |
| 157 | |
| 158 | void EmulatedNetworkIncomingStatsBuilder::AddIncomingStats( |
| 159 | const EmulatedNetworkIncomingStats& stats) { |
| 160 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 161 | packets_received_ += stats.PacketsReceived(); |
| 162 | bytes_received_ += stats.BytesReceived(); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 163 | received_packets_size_counter_.AddSamples(stats.ReceivedPacketsSizeCounter()); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 164 | packets_dropped_ += stats.PacketsDropped(); |
| 165 | bytes_dropped_ += stats.BytesDropped(); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 166 | dropped_packets_size_counter_.AddSamples(stats.DroppedPacketsSizeCounter()); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 167 | if (first_packet_received_time_ > stats.FirstPacketReceivedTime()) { |
| 168 | first_packet_received_time_ = stats.FirstPacketReceivedTime(); |
| 169 | first_received_packet_size_ = stats.FirstReceivedPacketSize(); |
| 170 | } |
| 171 | if (last_packet_received_time_ < stats.LastPacketReceivedTime()) { |
| 172 | last_packet_received_time_ = stats.LastPacketReceivedTime(); |
| 173 | } |
| 174 | } |
| 175 | |
| 176 | std::unique_ptr<EmulatedNetworkIncomingStats> |
| 177 | EmulatedNetworkIncomingStatsBuilder::Build() const { |
| 178 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
| 179 | return std::make_unique<EmulatedNetworkIncomingStatsImpl>( |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 180 | packets_received_, bytes_received_, received_packets_size_counter_, |
| 181 | packets_dropped_, bytes_dropped_, dropped_packets_size_counter_, |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 182 | first_received_packet_size_, first_packet_received_time_, |
| 183 | last_packet_received_time_); |
| 184 | } |
| 185 | |
| 186 | EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder() { |
| 187 | sequence_checker_.Detach(); |
| 188 | } |
| 189 | |
| 190 | EmulatedNetworkStatsBuilder::EmulatedNetworkStatsBuilder( |
| 191 | rtc::IPAddress local_ip) { |
| 192 | local_addresses_.push_back(local_ip); |
| 193 | sequence_checker_.Detach(); |
| 194 | } |
| 195 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 196 | void EmulatedNetworkStatsBuilder::OnPacketSent( |
| 197 | Timestamp queued_time, |
| 198 | Timestamp sent_time, |
| 199 | rtc::IPAddress destination_ip, |
| 200 | DataSize packet_size, |
| 201 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 202 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 203 | if (mode == EmulatedEndpointConfig::StatsGatheringMode::kDebug) { |
| 204 | sent_packets_queue_wait_time_us_.AddSample((sent_time - queued_time).us()); |
| 205 | } |
| 206 | outgoing_stats_per_destination_[destination_ip].OnPacketSent( |
| 207 | sent_time, packet_size, mode); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 208 | } |
| 209 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 210 | void EmulatedNetworkStatsBuilder::OnPacketDropped( |
| 211 | rtc::IPAddress source_ip, |
| 212 | DataSize packet_size, |
| 213 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 214 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 215 | incoming_stats_per_source_[source_ip].OnPacketDropped(packet_size, mode); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 216 | } |
| 217 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 218 | void EmulatedNetworkStatsBuilder::OnPacketReceived( |
| 219 | Timestamp received_time, |
| 220 | rtc::IPAddress source_ip, |
| 221 | DataSize packet_size, |
| 222 | EmulatedEndpointConfig::StatsGatheringMode mode) { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 223 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 224 | incoming_stats_per_source_[source_ip].OnPacketReceived(received_time, |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 225 | packet_size, mode); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 226 | } |
| 227 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 228 | void EmulatedNetworkStatsBuilder::AddEmulatedNetworkStats( |
| 229 | const EmulatedNetworkStats& stats) { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 230 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 231 | |
| 232 | // Append IPs from other endpoints stats to the builder. |
| 233 | for (const rtc::IPAddress& addr : stats.LocalAddresses()) { |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 234 | local_addresses_.push_back(addr); |
| 235 | } |
| 236 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 237 | sent_packets_queue_wait_time_us_.AddSamples( |
| 238 | stats.SentPacketsQueueWaitTimeUs()); |
| 239 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 240 | // Add outgoing stats from other endpoints to the builder. |
| 241 | const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 242 | outgoing_stats_per_destination = stats.OutgoingStatsPerDestination(); |
| 243 | for (const auto& entry : outgoing_stats_per_destination) { |
| 244 | outgoing_stats_per_destination_[entry.first].AddOutgoingStats( |
| 245 | *entry.second); |
| 246 | } |
| 247 | |
| 248 | // Add incoming stats from other endpoints to the builder. |
| 249 | const std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 250 | incoming_stats_per_source = stats.IncomingStatsPerSource(); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 251 | for (const auto& entry : incoming_stats_per_source) { |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 252 | incoming_stats_per_source_[entry.first].AddIncomingStats(*entry.second); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 253 | } |
| 254 | } |
| 255 | |
| 256 | std::unique_ptr<EmulatedNetworkStats> EmulatedNetworkStatsBuilder::Build() |
| 257 | const { |
| 258 | RTC_DCHECK_RUN_ON(&sequence_checker_); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 259 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 260 | outgoing_stats; |
| 261 | for (const auto& entry : outgoing_stats_per_destination_) { |
| 262 | outgoing_stats.emplace(entry.first, entry.second.Build()); |
| 263 | } |
| 264 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 265 | incoming_stats; |
| 266 | for (const auto& entry : incoming_stats_per_source_) { |
| 267 | incoming_stats.emplace(entry.first, entry.second.Build()); |
| 268 | } |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 269 | return std::make_unique<EmulatedNetworkStatsImpl>( |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 270 | local_addresses_, sent_packets_queue_wait_time_us_, |
| 271 | std::move(outgoing_stats), std::move(incoming_stats)); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 272 | } |
| 273 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 274 | void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 275 | task_queue_->PostTask([this, packet = std::move(packet)]() mutable { |
| 276 | RTC_DCHECK_RUN_ON(task_queue_); |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 277 | |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 278 | uint64_t packet_id = next_packet_id_++; |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 279 | bool sent = network_behavior_->EnqueuePacket(PacketInFlightInfo( |
| 280 | packet.ip_packet_size(), packet.arrival_time.us(), packet_id)); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 281 | if (sent) { |
| 282 | packets_.emplace_back(StoredPacket{packet_id, std::move(packet), false}); |
| 283 | } |
| 284 | if (process_task_.Running()) |
| 285 | return; |
| 286 | absl::optional<int64_t> next_time_us = |
| 287 | network_behavior_->NextDeliveryTimeUs(); |
| 288 | if (!next_time_us) |
| 289 | return; |
| 290 | Timestamp current_time = clock_->CurrentTime(); |
| 291 | process_task_ = RepeatingTaskHandle::DelayedStart( |
| 292 | task_queue_->Get(), |
| 293 | std::max(TimeDelta::Zero(), |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 294 | Timestamp::Micros(*next_time_us) - current_time), |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 295 | [this]() { |
| 296 | RTC_DCHECK_RUN_ON(task_queue_); |
| 297 | Timestamp current_time = clock_->CurrentTime(); |
| 298 | Process(current_time); |
| 299 | absl::optional<int64_t> next_time_us = |
| 300 | network_behavior_->NextDeliveryTimeUs(); |
| 301 | if (!next_time_us) { |
| 302 | process_task_.Stop(); |
| 303 | return TimeDelta::Zero(); // This is ignored. |
| 304 | } |
| 305 | RTC_DCHECK_GE(*next_time_us, current_time.us()); |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 306 | return Timestamp::Micros(*next_time_us) - current_time; |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 307 | }); |
| 308 | }); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 309 | } |
| 310 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 311 | void LinkEmulation::Process(Timestamp at_time) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 312 | std::vector<PacketDeliveryInfo> delivery_infos = |
| 313 | network_behavior_->DequeueDeliverablePackets(at_time.us()); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 314 | for (PacketDeliveryInfo& delivery_info : delivery_infos) { |
| 315 | StoredPacket* packet = nullptr; |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 316 | for (auto& stored_packet : packets_) { |
| 317 | if (stored_packet.id == delivery_info.packet_id) { |
| 318 | packet = &stored_packet; |
| 319 | break; |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 320 | } |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 321 | } |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 322 | RTC_CHECK(packet); |
| 323 | RTC_DCHECK(!packet->removed); |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 324 | packet->removed = true; |
| 325 | |
Johannes Kron | a8f9e25 | 2019-01-24 15:38:23 +0100 | [diff] [blame] | 326 | if (delivery_info.receive_time_us != PacketDeliveryInfo::kNotReceived) { |
| 327 | packet->packet.arrival_time = |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 328 | Timestamp::Micros(delivery_info.receive_time_us); |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 329 | receiver_->OnPacketReceived(std::move(packet->packet)); |
Johannes Kron | a8f9e25 | 2019-01-24 15:38:23 +0100 | [diff] [blame] | 330 | } |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 331 | while (!packets_.empty() && packets_.front().removed) { |
| 332 | packets_.pop_front(); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 333 | } |
| 334 | } |
| 335 | } |
| 336 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 337 | NetworkRouterNode::NetworkRouterNode(rtc::TaskQueue* task_queue) |
| 338 | : task_queue_(task_queue) {} |
| 339 | |
| 340 | void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) { |
| 341 | RTC_DCHECK_RUN_ON(task_queue_); |
Sebastian Jansson | 71c6b56 | 2019-08-14 11:31:02 +0200 | [diff] [blame] | 342 | if (watcher_) { |
| 343 | watcher_(packet); |
| 344 | } |
Sebastian Jansson | 3d4d94a | 2020-01-14 14:25:41 +0100 | [diff] [blame] | 345 | if (filter_) { |
| 346 | if (!filter_(packet)) |
| 347 | return; |
| 348 | } |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 349 | auto receiver_it = routing_.find(packet.to.ipaddr()); |
| 350 | if (receiver_it == routing_.end()) { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 351 | if (default_receiver_.has_value()) { |
| 352 | (*default_receiver_)->OnPacketReceived(std::move(packet)); |
| 353 | } |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 354 | return; |
| 355 | } |
| 356 | RTC_CHECK(receiver_it != routing_.end()); |
| 357 | |
| 358 | receiver_it->second->OnPacketReceived(std::move(packet)); |
| 359 | } |
| 360 | |
| 361 | void NetworkRouterNode::SetReceiver( |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 362 | const rtc::IPAddress& dest_ip, |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 363 | EmulatedNetworkReceiverInterface* receiver) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 364 | task_queue_->PostTask([=] { |
| 365 | RTC_DCHECK_RUN_ON(task_queue_); |
| 366 | EmulatedNetworkReceiverInterface* cur_receiver = routing_[dest_ip]; |
| 367 | RTC_CHECK(cur_receiver == nullptr || cur_receiver == receiver) |
| 368 | << "Routing for dest_ip=" << dest_ip.ToString() << " already exists"; |
| 369 | routing_[dest_ip] = receiver; |
| 370 | }); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 371 | } |
| 372 | |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 373 | void NetworkRouterNode::RemoveReceiver(const rtc::IPAddress& dest_ip) { |
Sebastian Jansson | 4124dab | 2019-04-01 14:33:53 +0200 | [diff] [blame] | 374 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 375 | routing_.erase(dest_ip); |
Artem Titov | 37d1848 | 2019-01-08 15:41:45 +0100 | [diff] [blame] | 376 | } |
| 377 | |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 378 | void NetworkRouterNode::SetDefaultReceiver( |
| 379 | EmulatedNetworkReceiverInterface* receiver) { |
| 380 | task_queue_->PostTask([=] { |
| 381 | RTC_DCHECK_RUN_ON(task_queue_); |
| 382 | if (default_receiver_.has_value()) { |
| 383 | RTC_CHECK_EQ(*default_receiver_, receiver) |
| 384 | << "Router already default receiver"; |
| 385 | } |
| 386 | default_receiver_ = receiver; |
| 387 | }); |
| 388 | } |
| 389 | |
| 390 | void NetworkRouterNode::RemoveDefaultReceiver() { |
| 391 | RTC_DCHECK_RUN_ON(task_queue_); |
| 392 | default_receiver_ = absl::nullopt; |
| 393 | } |
| 394 | |
Sebastian Jansson | 71c6b56 | 2019-08-14 11:31:02 +0200 | [diff] [blame] | 395 | void NetworkRouterNode::SetWatcher( |
| 396 | std::function<void(const EmulatedIpPacket&)> watcher) { |
| 397 | task_queue_->PostTask([=] { |
| 398 | RTC_DCHECK_RUN_ON(task_queue_); |
| 399 | watcher_ = watcher; |
| 400 | }); |
| 401 | } |
| 402 | |
Sebastian Jansson | 3d4d94a | 2020-01-14 14:25:41 +0100 | [diff] [blame] | 403 | void NetworkRouterNode::SetFilter( |
| 404 | std::function<bool(const EmulatedIpPacket&)> filter) { |
| 405 | task_queue_->PostTask([=] { |
| 406 | RTC_DCHECK_RUN_ON(task_queue_); |
| 407 | filter_ = filter; |
| 408 | }); |
| 409 | } |
| 410 | |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 411 | EmulatedNetworkNode::EmulatedNetworkNode( |
| 412 | Clock* clock, |
| 413 | rtc::TaskQueue* task_queue, |
| 414 | std::unique_ptr<NetworkBehaviorInterface> network_behavior) |
| 415 | : router_(task_queue), |
| 416 | link_(clock, task_queue, std::move(network_behavior), &router_) {} |
| 417 | |
| 418 | void EmulatedNetworkNode::OnPacketReceived(EmulatedIpPacket packet) { |
| 419 | link_.OnPacketReceived(std::move(packet)); |
| 420 | } |
| 421 | |
| 422 | void EmulatedNetworkNode::CreateRoute( |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 423 | const rtc::IPAddress& receiver_ip, |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 424 | std::vector<EmulatedNetworkNode*> nodes, |
| 425 | EmulatedNetworkReceiverInterface* receiver) { |
| 426 | RTC_CHECK(!nodes.empty()); |
| 427 | for (size_t i = 0; i + 1 < nodes.size(); ++i) |
| 428 | nodes[i]->router()->SetReceiver(receiver_ip, nodes[i + 1]); |
| 429 | nodes.back()->router()->SetReceiver(receiver_ip, receiver); |
| 430 | } |
| 431 | |
Yves Gerey | 2257c08 | 2020-01-03 12:37:56 +0100 | [diff] [blame] | 432 | void EmulatedNetworkNode::ClearRoute(const rtc::IPAddress& receiver_ip, |
Sebastian Jansson | 62bb47f | 2019-04-01 18:23:58 +0200 | [diff] [blame] | 433 | std::vector<EmulatedNetworkNode*> nodes) { |
| 434 | for (EmulatedNetworkNode* node : nodes) |
| 435 | node->router()->RemoveReceiver(receiver_ip); |
| 436 | } |
| 437 | |
| 438 | EmulatedNetworkNode::~EmulatedNetworkNode() = default; |
| 439 | |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 440 | EmulatedEndpointImpl::Options::Options(uint64_t id, |
| 441 | const rtc::IPAddress& ip, |
| 442 | const EmulatedEndpointConfig& config) |
| 443 | : id(id), |
| 444 | ip(ip), |
| 445 | stats_gathering_mode(config.stats_gathering_mode), |
| 446 | type(config.type), |
| 447 | allow_send_packet_with_different_source_ip( |
| 448 | config.allow_send_packet_with_different_source_ip), |
| 449 | allow_receive_packets_with_different_dest_ip( |
Artem Titov | 28547e9 | 2021-02-22 15:01:38 +0100 | [diff] [blame] | 450 | config.allow_receive_packets_with_different_dest_ip), |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 451 | log_name(ip.ToString() + " (" + config.name.value_or("") + ")") {} |
| 452 | |
| 453 | EmulatedEndpointImpl::EmulatedEndpointImpl(const Options& options, |
| 454 | bool is_enabled, |
| 455 | rtc::TaskQueue* task_queue, |
| 456 | Clock* clock) |
| 457 | : options_(options), |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 458 | is_enabled_(is_enabled), |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 459 | clock_(clock), |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 460 | task_queue_(task_queue), |
| 461 | router_(task_queue_), |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 462 | next_port_(kFirstEphemeralPort), |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 463 | stats_builder_(options_.ip) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 464 | constexpr int kIPv4NetworkPrefixLength = 24; |
| 465 | constexpr int kIPv6NetworkPrefixLength = 64; |
| 466 | |
| 467 | int prefix_length = 0; |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 468 | if (options_.ip.family() == AF_INET) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 469 | prefix_length = kIPv4NetworkPrefixLength; |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 470 | } else if (options_.ip.family() == AF_INET6) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 471 | prefix_length = kIPv6NetworkPrefixLength; |
| 472 | } |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 473 | rtc::IPAddress prefix = TruncateIP(options_.ip, prefix_length); |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 474 | network_ = std::make_unique<rtc::Network>( |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 475 | options_.ip.ToString(), "Endpoint id=" + std::to_string(options_.id), |
| 476 | prefix, prefix_length, options_.type); |
| 477 | network_->AddIP(options_.ip); |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 478 | |
Sebastian Jansson | c01367d | 2019-04-08 15:20:44 +0200 | [diff] [blame] | 479 | enabled_state_checker_.Detach(); |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 480 | RTC_LOG(LS_INFO) << "Created emulated endpoint " << options_.log_name |
| 481 | << "; id=" << options_.id; |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 482 | } |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 483 | EmulatedEndpointImpl::~EmulatedEndpointImpl() = default; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 484 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 485 | uint64_t EmulatedEndpointImpl::GetId() const { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 486 | return options_.id; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 487 | } |
| 488 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 489 | void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from, |
| 490 | const rtc::SocketAddress& to, |
Sebastian Jansson | 77bd385 | 2020-01-17 13:05:54 +0100 | [diff] [blame] | 491 | rtc::CopyOnWriteBuffer packet_data, |
| 492 | uint16_t application_overhead) { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 493 | if (!options_.allow_send_packet_with_different_source_ip) { |
| 494 | RTC_CHECK(from.ipaddr() == options_.ip); |
| 495 | } |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 496 | EmulatedIpPacket packet(from, to, std::move(packet_data), |
Sebastian Jansson | 77bd385 | 2020-01-17 13:05:54 +0100 | [diff] [blame] | 497 | clock_->CurrentTime(), application_overhead); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 498 | task_queue_->PostTask([this, packet = std::move(packet)]() mutable { |
| 499 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 500 | stats_builder_.OnPacketSent(packet.arrival_time, clock_->CurrentTime(), |
| 501 | packet.to.ipaddr(), |
| 502 | DataSize::Bytes(packet.ip_packet_size()), |
| 503 | options_.stats_gathering_mode); |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 504 | |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 505 | if (packet.to.ipaddr() == options_.ip) { |
Artem Titov | 5d55597 | 2020-11-12 16:15:44 +0100 | [diff] [blame] | 506 | OnPacketReceived(std::move(packet)); |
| 507 | } else { |
| 508 | router_.OnPacketReceived(std::move(packet)); |
| 509 | } |
Sebastian Jansson | ee5ec9a | 2019-09-17 20:34:03 +0200 | [diff] [blame] | 510 | }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 511 | } |
| 512 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 513 | absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver( |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 514 | uint16_t desired_port, |
| 515 | EmulatedNetworkReceiverInterface* receiver) { |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 516 | return BindReceiverInternal(desired_port, receiver, /*is_one_shot=*/false); |
| 517 | } |
| 518 | |
| 519 | absl::optional<uint16_t> EmulatedEndpointImpl::BindOneShotReceiver( |
| 520 | uint16_t desired_port, |
| 521 | EmulatedNetworkReceiverInterface* receiver) { |
| 522 | return BindReceiverInternal(desired_port, receiver, /*is_one_shot=*/true); |
| 523 | } |
| 524 | |
| 525 | absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiverInternal( |
| 526 | uint16_t desired_port, |
| 527 | EmulatedNetworkReceiverInterface* receiver, |
| 528 | bool is_one_shot) { |
| 529 | MutexLock lock(&receiver_lock_); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 530 | uint16_t port = desired_port; |
| 531 | if (port == 0) { |
| 532 | // Because client can specify its own port, next_port_ can be already in |
| 533 | // use, so we need to find next available port. |
| 534 | int ports_pool_size = |
| 535 | std::numeric_limits<uint16_t>::max() - kFirstEphemeralPort + 1; |
| 536 | for (int i = 0; i < ports_pool_size; ++i) { |
| 537 | uint16_t next_port = NextPort(); |
| 538 | if (port_to_receiver_.find(next_port) == port_to_receiver_.end()) { |
| 539 | port = next_port; |
| 540 | break; |
| 541 | } |
| 542 | } |
| 543 | } |
| 544 | RTC_CHECK(port != 0) << "Can't find free port for receiver in endpoint " |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 545 | << options_.log_name << "; id=" << options_.id; |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 546 | bool result = |
| 547 | port_to_receiver_.insert({port, {receiver, is_one_shot}}).second; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 548 | if (!result) { |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 549 | RTC_LOG(LS_INFO) << "Can't bind receiver to used port " << desired_port |
| 550 | << " in endpoint " << options_.log_name |
| 551 | << "; id=" << options_.id; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 552 | return absl::nullopt; |
| 553 | } |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 554 | RTC_LOG(LS_INFO) << "New receiver is binded to endpoint " << options_.log_name |
| 555 | << "; id=" << options_.id << " on port " << port; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 556 | return port; |
| 557 | } |
| 558 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 559 | uint16_t EmulatedEndpointImpl::NextPort() { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 560 | uint16_t out = next_port_; |
| 561 | if (next_port_ == std::numeric_limits<uint16_t>::max()) { |
| 562 | next_port_ = kFirstEphemeralPort; |
| 563 | } else { |
| 564 | next_port_++; |
| 565 | } |
| 566 | return out; |
| 567 | } |
| 568 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 569 | void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) { |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 570 | MutexLock lock(&receiver_lock_); |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 571 | RTC_LOG(LS_INFO) << "Receiver is removed on port " << port |
| 572 | << " from endpoint " << options_.log_name |
| 573 | << "; id=" << options_.id; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 574 | port_to_receiver_.erase(port); |
| 575 | } |
| 576 | |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 577 | void EmulatedEndpointImpl::BindDefaultReceiver( |
| 578 | EmulatedNetworkReceiverInterface* receiver) { |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 579 | MutexLock lock(&receiver_lock_); |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 580 | RTC_CHECK(!default_receiver_.has_value()) |
| 581 | << "Endpoint " << options_.log_name << "; id=" << options_.id |
| 582 | << " already has default receiver"; |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 583 | RTC_LOG(LS_INFO) << "Default receiver is binded to endpoint " |
| 584 | << options_.log_name << "; id=" << options_.id; |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 585 | default_receiver_ = receiver; |
| 586 | } |
| 587 | |
| 588 | void EmulatedEndpointImpl::UnbindDefaultReceiver() { |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 589 | MutexLock lock(&receiver_lock_); |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 590 | RTC_LOG(LS_INFO) << "Default receiver is removed from endpoint " |
| 591 | << options_.log_name << "; id=" << options_.id; |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 592 | default_receiver_ = absl::nullopt; |
| 593 | } |
| 594 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 595 | rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 596 | return options_.ip; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 597 | } |
| 598 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 599 | void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) { |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 600 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 28547e9 | 2021-02-22 15:01:38 +0100 | [diff] [blame] | 601 | if (!options_.allow_receive_packets_with_different_dest_ip) { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 602 | RTC_CHECK(packet.to.ipaddr() == options_.ip) |
| 603 | << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: " |
| 604 | << packet.to.ipaddr().ToString() |
| 605 | << "; Receiver options_.ip=" << options_.ip.ToString(); |
| 606 | } |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 607 | MutexLock lock(&receiver_lock_); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 608 | stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet.from.ipaddr(), |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 609 | DataSize::Bytes(packet.ip_packet_size()), |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 610 | options_.stats_gathering_mode); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 611 | auto it = port_to_receiver_.find(packet.to.port()); |
| 612 | if (it == port_to_receiver_.end()) { |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 613 | if (default_receiver_.has_value()) { |
| 614 | (*default_receiver_)->OnPacketReceived(std::move(packet)); |
| 615 | return; |
| 616 | } |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 617 | // It can happen, that remote peer closed connection, but there still some |
| 618 | // packets, that are going to it. It can happen during peer connection close |
| 619 | // process: one peer closed connection, second still sending data. |
Harald Alvestrand | 97597c0 | 2021-11-04 12:01:23 +0000 | [diff] [blame] | 620 | RTC_LOG(LS_INFO) << "Drop packet: no receiver registered in " |
| 621 | << options_.log_name << "; id=" << options_.id |
| 622 | << " on port " << packet.to.port(); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 623 | stats_builder_.OnPacketDropped(packet.from.ipaddr(), |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 624 | DataSize::Bytes(packet.ip_packet_size()), |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 625 | options_.stats_gathering_mode); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 626 | return; |
| 627 | } |
Niels Möller | 376cf38 | 2021-02-26 09:24:51 +0100 | [diff] [blame] | 628 | // Endpoint holds lock during packet processing to ensure that a call to |
| 629 | // UnbindReceiver followed by a delete of the receiver cannot race with this |
| 630 | // call to OnPacketReceived. |
| 631 | it->second.receiver->OnPacketReceived(std::move(packet)); |
| 632 | |
| 633 | if (it->second.is_one_shot) { |
| 634 | port_to_receiver_.erase(it); |
| 635 | } |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 636 | } |
| 637 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 638 | void EmulatedEndpointImpl::Enable() { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 639 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 640 | RTC_CHECK(!is_enabled_); |
| 641 | is_enabled_ = true; |
| 642 | } |
| 643 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 644 | void EmulatedEndpointImpl::Disable() { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 645 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 646 | RTC_CHECK(is_enabled_); |
| 647 | is_enabled_ = false; |
| 648 | } |
| 649 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 650 | bool EmulatedEndpointImpl::Enabled() const { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 651 | RTC_DCHECK_RUN_ON(&enabled_state_checker_); |
| 652 | return is_enabled_; |
| 653 | } |
| 654 | |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 655 | std::unique_ptr<EmulatedNetworkStats> EmulatedEndpointImpl::stats() const { |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 656 | RTC_DCHECK_RUN_ON(task_queue_); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 657 | return stats_builder_.Build(); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 658 | } |
| 659 | |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 660 | EndpointsContainer::EndpointsContainer( |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 661 | const std::vector<EmulatedEndpointImpl*>& endpoints) |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 662 | : endpoints_(endpoints) {} |
| 663 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 664 | EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress( |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 665 | const rtc::IPAddress& local_ip) const { |
| 666 | for (auto* endpoint : endpoints_) { |
Artem Titov | 4cd433e | 2019-04-01 11:01:16 +0200 | [diff] [blame] | 667 | rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress(); |
| 668 | if (peer_local_address == local_ip) { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 669 | return endpoint; |
| 670 | } |
| 671 | } |
| 672 | RTC_CHECK(false) << "No network found for address" << local_ip.ToString(); |
| 673 | } |
| 674 | |
Sebastian Jansson | cec2433 | 2019-12-04 14:26:50 +0100 | [diff] [blame] | 675 | bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const { |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 676 | for (auto* e : endpoints_) { |
| 677 | if (e->GetId() == endpoint->GetId()) { |
| 678 | return true; |
| 679 | } |
| 680 | } |
| 681 | return false; |
| 682 | } |
| 683 | |
| 684 | std::vector<std::unique_ptr<rtc::Network>> |
| 685 | EndpointsContainer::GetEnabledNetworks() const { |
| 686 | std::vector<std::unique_ptr<rtc::Network>> networks; |
| 687 | for (auto* endpoint : endpoints_) { |
| 688 | if (endpoint->Enabled()) { |
| 689 | networks.emplace_back( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 690 | std::make_unique<rtc::Network>(endpoint->network())); |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 691 | } |
| 692 | } |
| 693 | return networks; |
| 694 | } |
| 695 | |
Artem Titov | 5501cef | 2020-08-04 11:49:19 +0200 | [diff] [blame] | 696 | std::vector<EmulatedEndpoint*> EndpointsContainer::GetEndpoints() const { |
Artem Titov | cf78128 | 2020-07-28 13:45:16 +0200 | [diff] [blame] | 697 | return std::vector<EmulatedEndpoint*>(endpoints_.begin(), endpoints_.end()); |
| 698 | } |
| 699 | |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 700 | std::unique_ptr<EmulatedNetworkStats> EndpointsContainer::GetStats() const { |
| 701 | EmulatedNetworkStatsBuilder stats_builder; |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 702 | for (auto* endpoint : endpoints_) { |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 703 | stats_builder.AddEmulatedNetworkStats(*endpoint->stats()); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 704 | } |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 705 | return stats_builder.Build(); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 706 | } |
| 707 | |
Artem Titov | 40f5115 | 2019-01-04 15:45:01 +0100 | [diff] [blame] | 708 | } // namespace webrtc |