Exposing more features in the network emulation manager API.

Bug: webrtc:9883
Change-Id: I2a687b46e3374db0dd08b0c02dfea1482e6fb89f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161229
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30024}
This commit is contained in:
Sebastian Jansson
2019-12-04 14:26:50 +01:00
committed by Commit Bot
parent 1fce3f8e55
commit cec2433c47
24 changed files with 393 additions and 269 deletions

View File

@ -420,6 +420,7 @@ if (rtc_include_tests) {
] ]
} }
# TODO(srte): Move to network_emulation sub directory.
rtc_library("create_network_emulation_manager") { rtc_library("create_network_emulation_manager") {
visibility = [ "*" ] visibility = [ "*" ]
testonly = true testonly = true
@ -541,6 +542,7 @@ rtc_source_set("bitrate_allocation") {
] ]
} }
# TODO(srte): Move to network_emulation sub directory.
rtc_source_set("simulated_network_api") { rtc_source_set("simulated_network_api") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ sources = [
@ -553,14 +555,18 @@ rtc_source_set("simulated_network_api") {
] ]
} }
# TODO(srte): Move to network_emulation sub directory.
rtc_source_set("network_emulation_manager_api") { rtc_source_set("network_emulation_manager_api") {
visibility = [ "*" ] visibility = [ "*" ]
sources = [ sources = [
"test/network_emulation_manager.cc",
"test/network_emulation_manager.h", "test/network_emulation_manager.h",
] ]
deps = [ deps = [
":simulated_network_api", ":simulated_network_api",
"../call:simulated_network",
"../rtc_base", "../rtc_base",
"test/network_emulation",
"units:data_rate", "units:data_rate",
"units:data_size", "units:data_size",
"units:timestamp", "units:timestamp",

View File

@ -0,0 +1,28 @@
# Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import("../../../webrtc.gni")
rtc_library("network_emulation") {
visibility = [ "*" ]
sources = [
"network_emulation_interfaces.cc",
"network_emulation_interfaces.h",
]
deps = [
"../../../rtc_base",
"../../../rtc_base:checks",
"../../../rtc_base:rtc_base_approved",
"../../units:data_rate",
"../../units:data_size",
"../../units:timestamp",
"//third_party/abseil-cpp/absl/types:optional",
]
}

View File

@ -0,0 +1,7 @@
specific_include_rules = {
".*": [
"+rtc_base/socket_address.h",
"+rtc_base/ip_address.h",
"+rtc_base/copy_on_write_buffer.h",
],
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "api/test/network_emulation/network_emulation_interfaces.h"
namespace webrtc {
namespace {
constexpr size_t kIPv4HeaderSize = 20;
constexpr size_t kIPv6HeaderSize = 40;
} // namespace
EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
Timestamp arrival_time)
: from(from),
to(to),
data(data),
ip_header_size((to.family() == AF_INET) ? kIPv4HeaderSize
: kIPv6HeaderSize),
arrival_time(arrival_time) {
RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6);
}
} // namespace webrtc

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
#define API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_
#include "absl/types/optional.h"
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/timestamp.h"
#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/ip_address.h"
#include "rtc_base/socket_address.h"
namespace webrtc {
struct EmulatedIpPacket {
public:
static constexpr int kUdpHeaderSize = 8;
EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
Timestamp arrival_time);
~EmulatedIpPacket() = default;
// This object is not copyable or assignable.
EmulatedIpPacket(const EmulatedIpPacket&) = delete;
EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
// This object is only moveable.
EmulatedIpPacket(EmulatedIpPacket&&) = default;
EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
size_t size() const { return data.size(); }
const uint8_t* cdata() const { return data.cdata(); }
size_t ip_packet_size() const {
return size() + kUdpHeaderSize + ip_header_size;
}
rtc::SocketAddress from;
rtc::SocketAddress to;
// Holds the UDP payload.
rtc::CopyOnWriteBuffer data;
int ip_header_size;
Timestamp arrival_time;
};
// Interface for handling IP packets from an emulated network. This is used with
// EmulatedEndpoint to receive packets on a specific port.
class EmulatedNetworkReceiverInterface {
public:
virtual ~EmulatedNetworkReceiverInterface() = default;
virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
};
struct EmulatedNetworkStats {
int64_t packets_sent = 0;
DataSize bytes_sent = DataSize::Zero();
// Total amount of packets received with or without destination.
int64_t packets_received = 0;
// Total amount of bytes in received packets.
DataSize bytes_received = DataSize::Zero();
// Total amount of packets that were received, but no destination was found.
int64_t packets_dropped = 0;
// Total amount of bytes in dropped packets.
DataSize bytes_dropped = DataSize::Zero();
DataSize first_received_packet_size = DataSize::Zero();
DataSize first_sent_packet_size = DataSize::Zero();
Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
Timestamp last_packet_sent_time = Timestamp::PlusInfinity();
Timestamp first_packet_received_time = Timestamp::PlusInfinity();
Timestamp last_packet_received_time = Timestamp::PlusInfinity();
DataRate AverageSendRate() const {
RTC_DCHECK_GE(packets_sent, 2);
return (bytes_sent - first_sent_packet_size) /
(last_packet_sent_time - first_packet_sent_time);
}
DataRate AverageReceiveRate() const {
RTC_DCHECK_GE(packets_received, 2);
return (bytes_received - first_received_packet_size) /
(last_packet_received_time - first_packet_received_time);
}
};
// EmulatedEndpoint is an abstraction for network interface on device. Instances
// of this are created by NetworkEmulationManager::CreateEndpoint.
class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
public:
// Send packet into network.
// |from| will be used to set source address for the packet in destination
// socket.
// |to| will be used for routing verification and picking right socket by port
// on destination endpoint.
virtual void SendPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer packet_data) = 0;
// Binds receiver to this endpoint to send and receive data.
// |desired_port| is a port that should be used. If it is equal to 0,
// endpoint will pick the first available port starting from
// |kFirstEphemeralPort|.
//
// Returns the port, that should be used (it will be equals to desired, if
// |desired_port| != 0 and is free or will be the one, selected by endpoint)
// or absl::nullopt if desired_port in used. Also fails if there are no more
// free ports to bind to.
virtual absl::optional<uint16_t> BindReceiver(
uint16_t desired_port,
EmulatedNetworkReceiverInterface* receiver) = 0;
virtual void UnbindReceiver(uint16_t port) = 0;
virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
virtual EmulatedNetworkStats stats() = 0;
private:
// Ensure that there can be no other subclass than EmulatedEndpointImpl. This
// means that it's always safe to downcast EmulatedEndpoint instances to
// EmulatedEndpointImpl.
friend class EmulatedEndpointImpl;
EmulatedEndpoint() = default;
};
// Simulates a TCP connection, this roughly implements the Reno algorithm. In
// difference from TCP this only support sending messages with a fixed length,
// no streaming. This is useful to simulate signaling and cross traffic using
// message based protocols such as HTTP. It differs from UDP messages in that
// they are guranteed to be delivered eventually, even on lossy networks.
class TcpMessageRoute {
public:
// Sends a TCP message of the given |size| over the route, |on_received| is
// called when the message has been delivered. Note that the connection
// parameters are reset iff there's no currently pending message on the route.
virtual void SendMessage(size_t size, std::function<void()> on_received) = 0;
protected:
~TcpMessageRoute() = default;
};
} // namespace webrtc
#endif // API_TEST_NETWORK_EMULATION_NETWORK_EMULATION_INTERFACES_H_

View File

@ -7,62 +7,53 @@
* in the file PATENTS. All contributing project authors may * in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "test/network/simulated_network_node.h"
#include <memory>
#include <utility> #include <utility>
#include "api/test/network_emulation_manager.h"
#include "call/simulated_network.h"
namespace webrtc { namespace webrtc {
namespace test {
SimulatedNetworkNode::Builder::Builder() {} NetworkEmulationManager::SimulatedNetworkNode::Builder&
NetworkEmulationManager::SimulatedNetworkNode::Builder::config(
SimulatedNetworkNode::Builder::Builder(NetworkEmulationManager* net) BuiltInNetworkBehaviorConfig config) {
: net_(net) {}
SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::config(
SimulatedNetwork::Config config) {
config_ = config; config_ = config;
return *this; return *this;
} }
SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::delay_ms( NetworkEmulationManager::SimulatedNetworkNode::Builder&
NetworkEmulationManager::SimulatedNetworkNode::Builder::delay_ms(
int queue_delay_ms) { int queue_delay_ms) {
config_.queue_delay_ms = queue_delay_ms; config_.queue_delay_ms = queue_delay_ms;
return *this; return *this;
} }
SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::capacity_kbps( NetworkEmulationManager::SimulatedNetworkNode::Builder&
NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_kbps(
int link_capacity_kbps) { int link_capacity_kbps) {
config_.link_capacity_kbps = link_capacity_kbps; config_.link_capacity_kbps = link_capacity_kbps;
return *this; return *this;
} }
SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::capacity_Mbps( NetworkEmulationManager::SimulatedNetworkNode::Builder&
NetworkEmulationManager::SimulatedNetworkNode::Builder::capacity_Mbps(
int link_capacity_Mbps) { int link_capacity_Mbps) {
config_.link_capacity_kbps = link_capacity_Mbps * 1000; config_.link_capacity_kbps = link_capacity_Mbps * 1000;
return *this; return *this;
} }
SimulatedNetworkNode::Builder& SimulatedNetworkNode::Builder::loss( NetworkEmulationManager::SimulatedNetworkNode::Builder&
double loss_rate) { NetworkEmulationManager::SimulatedNetworkNode::Builder::loss(double loss_rate) {
config_.loss_percent = std::round(loss_rate * 100); config_.loss_percent = std::round(loss_rate * 100);
return *this; return *this;
} }
SimulatedNetworkNode SimulatedNetworkNode::Builder::Build() const { NetworkEmulationManager::SimulatedNetworkNode
RTC_DCHECK(net_); NetworkEmulationManager::SimulatedNetworkNode::Builder::Build() const {
return Build(net_);
}
SimulatedNetworkNode SimulatedNetworkNode::Builder::Build(
NetworkEmulationManager* net) const {
SimulatedNetworkNode res; SimulatedNetworkNode res;
auto behavior = std::make_unique<SimulatedNetwork>(config_); auto behavior = std::make_unique<SimulatedNetwork>(config_);
res.simulation = behavior.get(); res.simulation = behavior.get();
res.node = net->CreateEmulatedNode(std::move(behavior)); res.node = net_->CreateEmulatedNode(std::move(behavior));
return res; return res;
} }
} // namespace test
} // namespace webrtc } // namespace webrtc

View File

@ -14,9 +14,9 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "api/test/network_emulation/network_emulation_interfaces.h"
#include "api/test/simulated_network.h" #include "api/test/simulated_network.h"
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/timestamp.h" #include "api/units/timestamp.h"
#include "rtc_base/network.h" #include "rtc_base/network.h"
#include "rtc_base/thread.h" #include "rtc_base/thread.h"
@ -36,8 +36,7 @@ namespace webrtc {
// Multiple networks can be joined into chain emulating a network path from // Multiple networks can be joined into chain emulating a network path from
// one peer to another. // one peer to another.
class EmulatedNetworkNode; class EmulatedNetworkNode;
// EmulatedEndpoint is and abstraction for network interface on device.
class EmulatedEndpoint;
// EmulatedRoute is handle for single route from one network interface on one // EmulatedRoute is handle for single route from one network interface on one
// peer device to another network interface on another peer device. // peer device to another network interface on another peer device.
class EmulatedRoute; class EmulatedRoute;
@ -54,37 +53,6 @@ struct EmulatedEndpointConfig {
bool start_as_enabled = true; bool start_as_enabled = true;
}; };
struct EmulatedNetworkStats {
int64_t packets_sent = 0;
DataSize bytes_sent = DataSize::Zero();
// Total amount of packets received with or without destination.
int64_t packets_received = 0;
// Total amount of bytes in received packets.
DataSize bytes_received = DataSize::Zero();
// Total amount of packets that were received, but no destination was found.
int64_t packets_dropped = 0;
// Total amount of bytes in dropped packets.
DataSize bytes_dropped = DataSize::Zero();
DataSize first_received_packet_size = DataSize::Zero();
DataSize first_sent_packet_size = DataSize::Zero();
Timestamp first_packet_sent_time = Timestamp::PlusInfinity();
Timestamp last_packet_sent_time = Timestamp::PlusInfinity();
Timestamp first_packet_received_time = Timestamp::PlusInfinity();
Timestamp last_packet_received_time = Timestamp::PlusInfinity();
DataRate AverageSendRate() const {
RTC_DCHECK_GE(packets_sent, 2);
return (bytes_sent - first_sent_packet_size) /
(last_packet_sent_time - first_packet_sent_time);
}
DataRate AverageReceiveRate() const {
RTC_DCHECK_GE(packets_received, 2);
return (bytes_received - first_received_packet_size) /
(last_packet_received_time - first_packet_received_time);
}
};
// Provide interface to obtain all required objects to inject network emulation // Provide interface to obtain all required objects to inject network emulation
// layer into PeerConnection. Also contains information about network interfaces // layer into PeerConnection. Also contains information about network interfaces
@ -106,6 +74,30 @@ class EmulatedNetworkManagerInterface {
// and will be deleted when manager will be deleted. // and will be deleted when manager will be deleted.
class NetworkEmulationManager { class NetworkEmulationManager {
public: public:
// Helper struct to simplify creation of simulated network behaviors. Contains
// non-owning pointers as the underlying instances are owned by the manager.
struct SimulatedNetworkNode {
SimulatedNetworkInterface* simulation;
EmulatedNetworkNode* node;
class Builder {
public:
explicit Builder(NetworkEmulationManager* net) : net_(net) {}
Builder(const Builder&) = default;
// Sets the config state, note that this will replace any previously set
// values.
Builder& config(BuiltInNetworkBehaviorConfig config);
Builder& delay_ms(int queue_delay_ms);
Builder& capacity_kbps(int link_capacity_kbps);
Builder& capacity_Mbps(int link_capacity_Mbps);
Builder& loss(double loss_rate);
SimulatedNetworkNode Build() const;
private:
NetworkEmulationManager* const net_;
BuiltInNetworkBehaviorConfig config_;
};
};
virtual ~NetworkEmulationManager() = default; virtual ~NetworkEmulationManager() = default;
// Creates an emulated network node, which represents single network in // Creates an emulated network node, which represents single network in
@ -115,6 +107,8 @@ class NetworkEmulationManager {
virtual EmulatedNetworkNode* CreateEmulatedNode( virtual EmulatedNetworkNode* CreateEmulatedNode(
std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0; std::unique_ptr<NetworkBehaviorInterface> network_behavior) = 0;
virtual SimulatedNetworkNode::Builder NodeBuilder() = 0;
// Creates an emulated endpoint, which represents single network interface on // Creates an emulated endpoint, which represents single network interface on
// the peer's device. // the peer's device.
virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0; virtual EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) = 0;
@ -149,11 +143,25 @@ class NetworkEmulationManager {
EmulatedEndpoint* from, EmulatedEndpoint* from,
const std::vector<EmulatedNetworkNode*>& via_nodes, const std::vector<EmulatedNetworkNode*>& via_nodes,
EmulatedEndpoint* to) = 0; EmulatedEndpoint* to) = 0;
// Creates a route over the given |via_nodes| creating the required endpoints
// in the process. The returned EmulatedRoute pointer can be used in other
// calls as a transport route for message or cross traffic.
virtual EmulatedRoute* CreateRoute(
const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
// Removes route previously created by CreateRoute(...). // Removes route previously created by CreateRoute(...).
// Caller mustn't call this function with route, that have been already // Caller mustn't call this function with route, that have been already
// removed earlier. // removed earlier.
virtual void ClearRoute(EmulatedRoute* route) = 0; virtual void ClearRoute(EmulatedRoute* route) = 0;
// Creates a simulated TCP connection using |send_route| for traffic and
// |ret_route| for feedback. This can be used to emulate HTTP cross traffic
// and to implement realistic reliable signaling over lossy networks.
// TODO(srte): Handle clearing of the routes involved.
virtual TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
EmulatedRoute* ret_route) = 0;
// Creates EmulatedNetworkManagerInterface which can be used then to inject // Creates EmulatedNetworkManagerInterface which can be used then to inject
// network emulation layer into PeerConnection. |endpoints| - are available // network emulation layer into PeerConnection. |endpoints| - are available
// network interfaces for PeerConnection. If endpoint is enabled, it will be // network interfaces for PeerConnection. If endpoint is enabled, it will be

View File

@ -80,6 +80,16 @@ class NetworkBehaviorInterface {
virtual ~NetworkBehaviorInterface() = default; virtual ~NetworkBehaviorInterface() = default;
}; };
// Class simulating a network link. This is a simple and naive solution just
// faking capacity and adding an extra transport delay in addition to the
// capacity introduced delay.
class SimulatedNetworkInterface : public NetworkBehaviorInterface {
public:
// Sets a new configuration. This won't affect packets already in the pipe.
virtual void SetConfig(const BuiltInNetworkBehaviorConfig& config) = 0;
virtual void PauseTransmissionUntil(int64_t until_us) = 0;
};
} // namespace webrtc } // namespace webrtc
#endif // API_TEST_SIMULATED_NETWORK_H_ #endif // API_TEST_SIMULATED_NETWORK_H_

View File

@ -79,15 +79,14 @@ bool CoDelSimulation::DropDequeuedPacket(Timestamp now,
} }
} }
SimulatedNetwork::SimulatedNetwork(SimulatedNetwork::Config config, SimulatedNetwork::SimulatedNetwork(Config config, uint64_t random_seed)
uint64_t random_seed)
: random_(random_seed), bursting_(false) { : random_(random_seed), bursting_(false) {
SetConfig(config); SetConfig(config);
} }
SimulatedNetwork::~SimulatedNetwork() = default; SimulatedNetwork::~SimulatedNetwork() = default;
void SimulatedNetwork::SetConfig(const SimulatedNetwork::Config& config) { void SimulatedNetwork::SetConfig(const Config& config) {
rtc::CritScope crit(&config_lock_); rtc::CritScope crit(&config_lock_);
config_state_.config = config; // Shallow copy of the struct. config_state_.config = config; // Shallow copy of the struct.
double prob_loss = config.loss_percent / 100.0; double prob_loss = config.loss_percent / 100.0;

View File

@ -54,15 +54,15 @@ class CoDelSimulation {
// Class simulating a network link. This is a simple and naive solution just // Class simulating a network link. This is a simple and naive solution just
// faking capacity and adding an extra transport delay in addition to the // faking capacity and adding an extra transport delay in addition to the
// capacity introduced delay. // capacity introduced delay.
class SimulatedNetwork : public NetworkBehaviorInterface { class SimulatedNetwork : public SimulatedNetworkInterface {
public: public:
using Config = BuiltInNetworkBehaviorConfig; using Config = BuiltInNetworkBehaviorConfig;
explicit SimulatedNetwork(Config config, uint64_t random_seed = 1); explicit SimulatedNetwork(Config config, uint64_t random_seed = 1);
~SimulatedNetwork() override; ~SimulatedNetwork() override;
// Sets a new configuration. This won't affect packets already in the pipe. // Sets a new configuration. This won't affect packets already in the pipe.
void SetConfig(const Config& config); void SetConfig(const Config& config) override;
void PauseTransmissionUntil(int64_t until_us); void PauseTransmissionUntil(int64_t until_us) override;
// NetworkBehaviorInterface // NetworkBehaviorInterface
bool EnqueuePacket(PacketInFlightInfo packet) override; bool EnqueuePacket(PacketInFlightInfo packet) override;

View File

@ -33,8 +33,6 @@ rtc_library("emulated_network") {
"network_emulation.h", "network_emulation.h",
"network_emulation_manager.cc", "network_emulation_manager.cc",
"network_emulation_manager.h", "network_emulation_manager.h",
"simulated_network_node.cc",
"simulated_network_node.h",
"traffic_route.cc", "traffic_route.cc",
"traffic_route.h", "traffic_route.h",
] ]

View File

@ -116,7 +116,7 @@ ColumnPrinter PulsedPeaksCrossTraffic::StatsPrinter() {
32); 32);
} }
TcpMessageRoute::TcpMessageRoute(Clock* clock, TcpMessageRouteImpl::TcpMessageRouteImpl(Clock* clock,
TaskQueueBase* task_queue, TaskQueueBase* task_queue,
EmulatedRoute* send_route, EmulatedRoute* send_route,
EmulatedRoute* ret_route) EmulatedRoute* ret_route)
@ -131,7 +131,7 @@ TcpMessageRoute::TcpMessageRoute(Clock* clock,
OnResponse(std::move(packet), arrival_time); OnResponse(std::move(packet), arrival_time);
}) {} }) {}
void TcpMessageRoute::SendMessage(size_t size, void TcpMessageRouteImpl::SendMessage(size_t size,
std::function<void()> on_received) { std::function<void()> on_received) {
task_queue_->PostTask( task_queue_->PostTask(
ToQueuedTask([this, size, handler = std::move(on_received)] { ToQueuedTask([this, size, handler = std::move(on_received)] {
@ -159,7 +159,7 @@ void TcpMessageRoute::SendMessage(size_t size,
})); }));
} }
void TcpMessageRoute::OnRequest(TcpPacket packet_info) { void TcpMessageRouteImpl::OnRequest(TcpPacket packet_info) {
for (auto it = messages_.begin(); it != messages_.end(); ++it) { for (auto it = messages_.begin(); it != messages_.end(); ++it) {
if (it->pending_fragment_ids.count(packet_info.fragment.fragment_id) != 0) { if (it->pending_fragment_ids.count(packet_info.fragment.fragment_id) != 0) {
it->pending_fragment_ids.erase(packet_info.fragment.fragment_id); it->pending_fragment_ids.erase(packet_info.fragment.fragment_id);
@ -174,7 +174,7 @@ void TcpMessageRoute::OnRequest(TcpPacket packet_info) {
response_route_.SendPacket(kAckPacketSize, packet_info); response_route_.SendPacket(kAckPacketSize, packet_info);
} }
void TcpMessageRoute::OnResponse(TcpPacket packet_info, Timestamp at_time) { void TcpMessageRouteImpl::OnResponse(TcpPacket packet_info, Timestamp at_time) {
auto it = in_flight_.find(packet_info.sequence_number); auto it = in_flight_.find(packet_info.sequence_number);
if (it != in_flight_.end()) { if (it != in_flight_.end()) {
last_rtt_ = at_time - packet_info.send_time; last_rtt_ = at_time - packet_info.send_time;
@ -198,7 +198,7 @@ void TcpMessageRoute::OnResponse(TcpPacket packet_info, Timestamp at_time) {
SendPackets(at_time); SendPackets(at_time);
} }
void TcpMessageRoute::HandleLoss(Timestamp at_time) { void TcpMessageRouteImpl::HandleLoss(Timestamp at_time) {
if (at_time - last_reduction_time_ < last_rtt_) if (at_time - last_reduction_time_ < last_rtt_)
return; return;
last_reduction_time_ = at_time; last_reduction_time_ = at_time;
@ -206,7 +206,7 @@ void TcpMessageRoute::HandleLoss(Timestamp at_time) {
cwnd_ = ssthresh_; cwnd_ = ssthresh_;
} }
void TcpMessageRoute::SendPackets(Timestamp at_time) { void TcpMessageRouteImpl::SendPackets(Timestamp at_time) {
const TimeDelta kPacketTimeout = TimeDelta::seconds(1); const TimeDelta kPacketTimeout = TimeDelta::seconds(1);
int cwnd = std::ceil(cwnd_); int cwnd = std::ceil(cwnd_);
int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0); int packets_to_send = std::max(cwnd - static_cast<int>(in_flight_.size()), 0);
@ -227,7 +227,7 @@ void TcpMessageRoute::SendPackets(Timestamp at_time) {
} }
} }
void TcpMessageRoute::HandlePacketTimeout(int seq_num, Timestamp at_time) { void TcpMessageRouteImpl::HandlePacketTimeout(int seq_num, Timestamp at_time) {
auto lost = in_flight_.find(seq_num); auto lost = in_flight_.find(seq_num);
if (lost != in_flight_.end()) { if (lost != in_flight_.end()) {
pending_.push_front(lost->second.fragment); pending_.push_front(lost->second.fragment);

View File

@ -92,14 +92,9 @@ class PulsedPeaksCrossTraffic {
bool sending_ RTC_GUARDED_BY(sequence_checker_) = false; bool sending_ RTC_GUARDED_BY(sequence_checker_) = false;
}; };
// Simulates a TCP connection, this roughly implements the Reno algorithm. In class TcpMessageRouteImpl final : public TcpMessageRoute {
// difference from TCP this only support sending messages with a fixed length,
// no streaming. This is useful to simulate signaling and cross traffic using
// message based protocols such as HTTP. It differs from UDP messages in that
// they are guranteed to be delivered eventually, even on lossy networks.
class TcpMessageRoute {
public: public:
TcpMessageRoute(Clock* clock, TcpMessageRouteImpl(Clock* clock,
TaskQueueBase* task_queue, TaskQueueBase* task_queue,
EmulatedRoute* send_route, EmulatedRoute* send_route,
EmulatedRoute* ret_route); EmulatedRoute* ret_route);
@ -107,7 +102,7 @@ class TcpMessageRoute {
// Sends a TCP message of the given |size| over the route, |on_received| is // Sends a TCP message of the given |size| over the route, |on_received| is
// called when the message has been delivered. Note that the connection // called when the message has been delivered. Note that the connection
// parameters are reset iff there's no currently pending message on the route. // parameters are reset iff there's no currently pending message on the route.
void SendMessage(size_t size, std::function<void()> on_received); void SendMessage(size_t size, std::function<void()> on_received) override;
private: private:
// Represents a message sent over the route. When all fragments has been // Represents a message sent over the route. When all fragments has been

View File

@ -45,7 +45,7 @@ struct TrafficCounterFixture {
SimulatedClock clock{0}; SimulatedClock clock{0};
CountingReceiver counter; CountingReceiver counter;
TaskQueueForTest task_queue_; TaskQueueForTest task_queue_;
EmulatedEndpoint endpoint{/*id=*/1, rtc::IPAddress(kTestIpAddress), EmulatedEndpointImpl endpoint{/*id=*/1, rtc::IPAddress(kTestIpAddress),
/*is_enabled=*/true, &task_queue_, &clock}; /*is_enabled=*/true, &task_queue_, &clock};
}; };

View File

@ -32,7 +32,7 @@ EmulatedNetworkManager::EmulatedNetworkManager(
network_thread_.Start(); network_thread_.Start();
} }
void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpoint* endpoint) { void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpointImpl* endpoint) {
RTC_CHECK(endpoints_container_->HasEndpoint(endpoint)) RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
<< "No such interface: " << endpoint->GetPeerLocalAddress().ToString(); << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() { network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() {
@ -41,7 +41,7 @@ void EmulatedNetworkManager::EnableEndpoint(EmulatedEndpoint* endpoint) {
}); });
} }
void EmulatedNetworkManager::DisableEndpoint(EmulatedEndpoint* endpoint) { void EmulatedNetworkManager::DisableEndpoint(EmulatedEndpointImpl* endpoint) {
RTC_CHECK(endpoints_container_->HasEndpoint(endpoint)) RTC_CHECK(endpoints_container_->HasEndpoint(endpoint))
<< "No such interface: " << endpoint->GetPeerLocalAddress().ToString(); << "No such interface: " << endpoint->GetPeerLocalAddress().ToString();
network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() { network_thread_.PostTask(RTC_FROM_HERE, [this, endpoint]() {

View File

@ -36,8 +36,8 @@ class EmulatedNetworkManager : public rtc::NetworkManagerBase,
TaskQueueForTest* task_queue, TaskQueueForTest* task_queue,
EndpointsContainer* endpoints_container); EndpointsContainer* endpoints_container);
void EnableEndpoint(EmulatedEndpoint* endpoint); void EnableEndpoint(EmulatedEndpointImpl* endpoint);
void DisableEndpoint(EmulatedEndpoint* endpoint); void DisableEndpoint(EmulatedEndpointImpl* endpoint);
// NetworkManager interface. All these methods are supposed to be called from // NetworkManager interface. All these methods are supposed to be called from
// the same thread. // the same thread.

View File

@ -39,7 +39,7 @@ class SocketManager {
virtual void WakeUp() = 0; virtual void WakeUp() = 0;
virtual void Unregister(SocketIoProcessor* io_processor) = 0; virtual void Unregister(SocketIoProcessor* io_processor) = 0;
// Provides endpoints by IP address. // Provides endpoints by IP address.
virtual EmulatedEndpoint* GetEndpointNode(const rtc::IPAddress& ip) = 0; virtual EmulatedEndpointImpl* GetEndpointNode(const rtc::IPAddress& ip) = 0;
}; };
// Represents a socket, which will operate with emulated network. // Represents a socket, which will operate with emulated network.
@ -82,7 +82,7 @@ class FakeNetworkSocket : public rtc::AsyncSocket,
absl::optional<EmulatedIpPacket> PopFrontPacket(); absl::optional<EmulatedIpPacket> PopFrontPacket();
SocketManager* const socket_manager_; SocketManager* const socket_manager_;
EmulatedEndpoint* endpoint_; EmulatedEndpointImpl* endpoint_;
rtc::SocketAddress local_addr_; rtc::SocketAddress local_addr_;
rtc::SocketAddress remote_addr_; rtc::SocketAddress remote_addr_;

View File

@ -29,7 +29,7 @@ void FakeNetworkSocketServer::OnMessageQueueDestroyed() {
msg_queue_ = nullptr; msg_queue_ = nullptr;
} }
EmulatedEndpoint* FakeNetworkSocketServer::GetEndpointNode( EmulatedEndpointImpl* FakeNetworkSocketServer::GetEndpointNode(
const rtc::IPAddress& ip) { const rtc::IPAddress& ip) {
return endpoints_container_->LookupByLocalAddress(ip); return endpoints_container_->LookupByLocalAddress(ip);
} }

View File

@ -38,7 +38,7 @@ class FakeNetworkSocketServer : public rtc::SocketServer,
EndpointsContainer* endpoints_controller); EndpointsContainer* endpoints_controller);
~FakeNetworkSocketServer() override; ~FakeNetworkSocketServer() override;
EmulatedEndpoint* GetEndpointNode(const rtc::IPAddress& ip) override; EmulatedEndpointImpl* GetEndpointNode(const rtc::IPAddress& ip) override;
void Unregister(SocketIoProcessor* io_processor) override; void Unregister(SocketIoProcessor* io_processor) override;
void OnMessageQueueDestroyed(); void OnMessageQueueDestroyed();

View File

@ -20,24 +20,6 @@
namespace webrtc { namespace webrtc {
namespace {
constexpr size_t kIPv4HeaderSize = 20;
constexpr size_t kIPv6HeaderSize = 40;
} // namespace
EmulatedIpPacket::EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
Timestamp arrival_time)
: from(from),
to(to),
data(data),
ip_header_size((to.family() == AF_INET) ? kIPv4HeaderSize
: kIPv6HeaderSize),
arrival_time(arrival_time) {
RTC_DCHECK(to.family() == AF_INET || to.family() == AF_INET6);
}
void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) { void LinkEmulation::OnPacketReceived(EmulatedIpPacket packet) {
task_queue_->PostTask([this, packet = std::move(packet)]() mutable { task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_); RTC_DCHECK_RUN_ON(task_queue_);
@ -172,7 +154,7 @@ void EmulatedNetworkNode::ClearRoute(rtc::IPAddress receiver_ip,
EmulatedNetworkNode::~EmulatedNetworkNode() = default; EmulatedNetworkNode::~EmulatedNetworkNode() = default;
EmulatedEndpoint::EmulatedEndpoint(uint64_t id, EmulatedEndpointImpl::EmulatedEndpointImpl(uint64_t id,
const rtc::IPAddress& ip, const rtc::IPAddress& ip,
bool is_enabled, bool is_enabled,
rtc::TaskQueue* task_queue, rtc::TaskQueue* task_queue,
@ -201,13 +183,13 @@ EmulatedEndpoint::EmulatedEndpoint(uint64_t id,
enabled_state_checker_.Detach(); enabled_state_checker_.Detach();
} }
EmulatedEndpoint::~EmulatedEndpoint() = default; EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
uint64_t EmulatedEndpoint::GetId() const { uint64_t EmulatedEndpointImpl::GetId() const {
return id_; return id_;
} }
void EmulatedEndpoint::SendPacket(const rtc::SocketAddress& from, void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to, const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer packet_data) { rtc::CopyOnWriteBuffer packet_data) {
RTC_CHECK(from.ipaddr() == peer_local_addr_); RTC_CHECK(from.ipaddr() == peer_local_addr_);
@ -228,7 +210,7 @@ void EmulatedEndpoint::SendPacket(const rtc::SocketAddress& from,
}); });
} }
absl::optional<uint16_t> EmulatedEndpoint::BindReceiver( absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver(
uint16_t desired_port, uint16_t desired_port,
EmulatedNetworkReceiverInterface* receiver) { EmulatedNetworkReceiverInterface* receiver) {
rtc::CritScope crit(&receiver_lock_); rtc::CritScope crit(&receiver_lock_);
@ -259,7 +241,7 @@ absl::optional<uint16_t> EmulatedEndpoint::BindReceiver(
return port; return port;
} }
uint16_t EmulatedEndpoint::NextPort() { uint16_t EmulatedEndpointImpl::NextPort() {
uint16_t out = next_port_; uint16_t out = next_port_;
if (next_port_ == std::numeric_limits<uint16_t>::max()) { if (next_port_ == std::numeric_limits<uint16_t>::max()) {
next_port_ = kFirstEphemeralPort; next_port_ = kFirstEphemeralPort;
@ -269,16 +251,16 @@ uint16_t EmulatedEndpoint::NextPort() {
return out; return out;
} }
void EmulatedEndpoint::UnbindReceiver(uint16_t port) { void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) {
rtc::CritScope crit(&receiver_lock_); rtc::CritScope crit(&receiver_lock_);
port_to_receiver_.erase(port); port_to_receiver_.erase(port);
} }
rtc::IPAddress EmulatedEndpoint::GetPeerLocalAddress() const { rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const {
return peer_local_addr_; return peer_local_addr_;
} }
void EmulatedEndpoint::OnPacketReceived(EmulatedIpPacket packet) { void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
RTC_DCHECK_RUN_ON(task_queue_); RTC_DCHECK_RUN_ON(task_queue_);
RTC_CHECK(packet.to.ipaddr() == peer_local_addr_) RTC_CHECK(packet.to.ipaddr() == peer_local_addr_)
<< "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: " << "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
@ -303,29 +285,29 @@ void EmulatedEndpoint::OnPacketReceived(EmulatedIpPacket packet) {
it->second->OnPacketReceived(std::move(packet)); it->second->OnPacketReceived(std::move(packet));
} }
void EmulatedEndpoint::Enable() { void EmulatedEndpointImpl::Enable() {
RTC_DCHECK_RUN_ON(&enabled_state_checker_); RTC_DCHECK_RUN_ON(&enabled_state_checker_);
RTC_CHECK(!is_enabled_); RTC_CHECK(!is_enabled_);
is_enabled_ = true; is_enabled_ = true;
} }
void EmulatedEndpoint::Disable() { void EmulatedEndpointImpl::Disable() {
RTC_DCHECK_RUN_ON(&enabled_state_checker_); RTC_DCHECK_RUN_ON(&enabled_state_checker_);
RTC_CHECK(is_enabled_); RTC_CHECK(is_enabled_);
is_enabled_ = false; is_enabled_ = false;
} }
bool EmulatedEndpoint::Enabled() const { bool EmulatedEndpointImpl::Enabled() const {
RTC_DCHECK_RUN_ON(&enabled_state_checker_); RTC_DCHECK_RUN_ON(&enabled_state_checker_);
return is_enabled_; return is_enabled_;
} }
EmulatedNetworkStats EmulatedEndpoint::stats() { EmulatedNetworkStats EmulatedEndpointImpl::stats() {
RTC_DCHECK_RUN_ON(task_queue_); RTC_DCHECK_RUN_ON(task_queue_);
return stats_; return stats_;
} }
void EmulatedEndpoint::UpdateReceiveStats(const EmulatedIpPacket& packet) { void EmulatedEndpointImpl::UpdateReceiveStats(const EmulatedIpPacket& packet) {
RTC_DCHECK_RUN_ON(task_queue_); RTC_DCHECK_RUN_ON(task_queue_);
Timestamp current_time = clock_->CurrentTime(); Timestamp current_time = clock_->CurrentTime();
if (stats_.first_packet_received_time.IsInfinite()) { if (stats_.first_packet_received_time.IsInfinite()) {
@ -339,10 +321,10 @@ void EmulatedEndpoint::UpdateReceiveStats(const EmulatedIpPacket& packet) {
} }
EndpointsContainer::EndpointsContainer( EndpointsContainer::EndpointsContainer(
const std::vector<EmulatedEndpoint*>& endpoints) const std::vector<EmulatedEndpointImpl*>& endpoints)
: endpoints_(endpoints) {} : endpoints_(endpoints) {}
EmulatedEndpoint* EndpointsContainer::LookupByLocalAddress( EmulatedEndpointImpl* EndpointsContainer::LookupByLocalAddress(
const rtc::IPAddress& local_ip) const { const rtc::IPAddress& local_ip) const {
for (auto* endpoint : endpoints_) { for (auto* endpoint : endpoints_) {
rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress(); rtc::IPAddress peer_local_address = endpoint->GetPeerLocalAddress();
@ -353,7 +335,7 @@ EmulatedEndpoint* EndpointsContainer::LookupByLocalAddress(
RTC_CHECK(false) << "No network found for address" << local_ip.ToString(); RTC_CHECK(false) << "No network found for address" << local_ip.ToString();
} }
bool EndpointsContainer::HasEndpoint(EmulatedEndpoint* endpoint) const { bool EndpointsContainer::HasEndpoint(EmulatedEndpointImpl* endpoint) const {
for (auto* e : endpoints_) { for (auto* e : endpoints_) {
if (e->GetId() == endpoint->GetId()) { if (e->GetId() == endpoint->GetId()) {
return true; return true;

View File

@ -33,42 +33,6 @@
namespace webrtc { namespace webrtc {
struct EmulatedIpPacket {
public:
static constexpr int kUdpHeaderSize = 8;
EmulatedIpPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer data,
Timestamp arrival_time);
~EmulatedIpPacket() = default;
// This object is not copyable or assignable.
EmulatedIpPacket(const EmulatedIpPacket&) = delete;
EmulatedIpPacket& operator=(const EmulatedIpPacket&) = delete;
// This object is only moveable.
EmulatedIpPacket(EmulatedIpPacket&&) = default;
EmulatedIpPacket& operator=(EmulatedIpPacket&&) = default;
size_t size() const { return data.size(); }
const uint8_t* cdata() const { return data.cdata(); }
size_t ip_packet_size() const {
return size() + kUdpHeaderSize + ip_header_size;
}
rtc::SocketAddress from;
rtc::SocketAddress to;
// Holds the UDP payload.
rtc::CopyOnWriteBuffer data;
int ip_header_size;
Timestamp arrival_time;
};
class EmulatedNetworkReceiverInterface {
public:
virtual ~EmulatedNetworkReceiverInterface() = default;
virtual void OnPacketReceived(EmulatedIpPacket packet) = 0;
};
class LinkEmulation : public EmulatedNetworkReceiverInterface { class LinkEmulation : public EmulatedNetworkReceiverInterface {
public: public:
@ -158,42 +122,29 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
// It will be used as sender from socket side to send data to the network and // It will be used as sender from socket side to send data to the network and
// will act as packet receiver from emulated network side to receive packets // will act as packet receiver from emulated network side to receive packets
// from other EmulatedNetworkNodes. // from other EmulatedNetworkNodes.
class EmulatedEndpoint : public EmulatedNetworkReceiverInterface { class EmulatedEndpointImpl : public EmulatedEndpoint {
public: public:
EmulatedEndpoint(uint64_t id, EmulatedEndpointImpl(uint64_t id,
const rtc::IPAddress& ip, const rtc::IPAddress& ip,
bool is_enabled, bool is_enabled,
rtc::TaskQueue* task_queue, rtc::TaskQueue* task_queue,
Clock* clock); Clock* clock);
~EmulatedEndpoint() override; ~EmulatedEndpointImpl() override;
uint64_t GetId() const; uint64_t GetId() const;
NetworkRouterNode* router() { return &router_; } NetworkRouterNode* router() { return &router_; }
// Send packet into network.
// |from| will be used to set source address for the packet in destination
// socket.
// |to| will be used for routing verification and picking right socket by port
// on destination endpoint.
void SendPacket(const rtc::SocketAddress& from, void SendPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to, const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer packet_data); rtc::CopyOnWriteBuffer packet_data) override;
// Binds receiver to this endpoint to send and receive data.
// |desired_port| is a port that should be used. If it is equal to 0,
// endpoint will pick the first available port starting from
// |kFirstEphemeralPort|.
//
// Returns the port, that should be used (it will be equals to desired, if
// |desired_port| != 0 and is free or will be the one, selected by endpoint)
// or absl::nullopt if desired_port in used. Also fails if there are no more
// free ports to bind to.
absl::optional<uint16_t> BindReceiver( absl::optional<uint16_t> BindReceiver(
uint16_t desired_port, uint16_t desired_port,
EmulatedNetworkReceiverInterface* receiver); EmulatedNetworkReceiverInterface* receiver) override;
void UnbindReceiver(uint16_t port); void UnbindReceiver(uint16_t port) override;
rtc::IPAddress GetPeerLocalAddress() const; rtc::IPAddress GetPeerLocalAddress() const override;
// Will be called to deliver packet into endpoint from network node. // Will be called to deliver packet into endpoint from network node.
void OnPacketReceived(EmulatedIpPacket packet) override; void OnPacketReceived(EmulatedIpPacket packet) override;
@ -204,7 +155,7 @@ class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
const rtc::Network& network() const { return *network_.get(); } const rtc::Network& network() const { return *network_.get(); }
EmulatedNetworkStats stats(); EmulatedNetworkStats stats() override;
private: private:
static constexpr uint16_t kFirstEphemeralPort = 49152; static constexpr uint16_t kFirstEphemeralPort = 49152;
@ -232,29 +183,31 @@ class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
class EmulatedRoute { class EmulatedRoute {
public: public:
EmulatedRoute(EmulatedEndpoint* from, EmulatedRoute(EmulatedEndpointImpl* from,
std::vector<EmulatedNetworkNode*> via_nodes, std::vector<EmulatedNetworkNode*> via_nodes,
EmulatedEndpoint* to) EmulatedEndpointImpl* to)
: from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {} : from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
EmulatedEndpoint* from; EmulatedEndpointImpl* from;
std::vector<EmulatedNetworkNode*> via_nodes; std::vector<EmulatedNetworkNode*> via_nodes;
EmulatedEndpoint* to; EmulatedEndpointImpl* to;
bool active; bool active;
}; };
class EndpointsContainer { class EndpointsContainer {
public: public:
explicit EndpointsContainer(const std::vector<EmulatedEndpoint*>& endpoints); explicit EndpointsContainer(
const std::vector<EmulatedEndpointImpl*>& endpoints);
EmulatedEndpoint* LookupByLocalAddress(const rtc::IPAddress& local_ip) const; EmulatedEndpointImpl* LookupByLocalAddress(
bool HasEndpoint(EmulatedEndpoint* endpoint) const; const rtc::IPAddress& local_ip) const;
bool HasEndpoint(EmulatedEndpointImpl* endpoint) const;
// Returns list of networks for enabled endpoints. Caller takes ownership of // Returns list of networks for enabled endpoints. Caller takes ownership of
// returned rtc::Network objects. // returned rtc::Network objects.
std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const; std::vector<std::unique_ptr<rtc::Network>> GetEnabledNetworks() const;
EmulatedNetworkStats GetStats() const; EmulatedNetworkStats GetStats() const;
private: private:
const std::vector<EmulatedEndpoint*> endpoints_; const std::vector<EmulatedEndpointImpl*> endpoints_;
}; };
template <typename FakePacketType> template <typename FakePacketType>

View File

@ -62,7 +62,8 @@ EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
return out; return out;
} }
SimulatedNetworkNode::Builder NetworkEmulationManagerImpl::NodeBuilder() { NetworkEmulationManager::SimulatedNetworkNode::Builder
NetworkEmulationManagerImpl::NodeBuilder() {
return SimulatedNetworkNode::Builder(this); return SimulatedNetworkNode::Builder(this);
} }
@ -85,7 +86,7 @@ EmulatedEndpoint* NetworkEmulationManagerImpl::CreateEndpoint(
bool res = used_ip_addresses_.insert(*ip).second; bool res = used_ip_addresses_.insert(*ip).second;
RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use"; RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
auto node = std::make_unique<EmulatedEndpoint>( auto node = std::make_unique<EmulatedEndpointImpl>(
next_node_id_++, *ip, config.start_as_enabled, &task_queue_, clock_); next_node_id_++, *ip, config.start_as_enabled, &task_queue_, clock_);
EmulatedEndpoint* out = node.get(); EmulatedEndpoint* out = node.get();
endpoints_.push_back(std::move(node)); endpoints_.push_back(std::move(node));
@ -96,14 +97,15 @@ void NetworkEmulationManagerImpl::EnableEndpoint(EmulatedEndpoint* endpoint) {
EmulatedNetworkManager* network_manager = EmulatedNetworkManager* network_manager =
endpoint_to_network_manager_[endpoint]; endpoint_to_network_manager_[endpoint];
RTC_CHECK(network_manager); RTC_CHECK(network_manager);
network_manager->EnableEndpoint(endpoint); network_manager->EnableEndpoint(static_cast<EmulatedEndpointImpl*>(endpoint));
} }
void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) { void NetworkEmulationManagerImpl::DisableEndpoint(EmulatedEndpoint* endpoint) {
EmulatedNetworkManager* network_manager = EmulatedNetworkManager* network_manager =
endpoint_to_network_manager_[endpoint]; endpoint_to_network_manager_[endpoint];
RTC_CHECK(network_manager); RTC_CHECK(network_manager);
network_manager->DisableEndpoint(endpoint); network_manager->DisableEndpoint(
static_cast<EmulatedEndpointImpl*>(endpoint));
} }
EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute( EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
@ -114,7 +116,8 @@ EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
// provided here. // provided here.
RTC_CHECK(!via_nodes.empty()); RTC_CHECK(!via_nodes.empty());
from->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[0]); static_cast<EmulatedEndpointImpl*>(from)->router()->SetReceiver(
to->GetPeerLocalAddress(), via_nodes[0]);
EmulatedNetworkNode* cur_node = via_nodes[0]; EmulatedNetworkNode* cur_node = via_nodes[0];
for (size_t i = 1; i < via_nodes.size(); ++i) { for (size_t i = 1; i < via_nodes.size(); ++i) {
cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]); cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), via_nodes[i]);
@ -122,8 +125,9 @@ EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
} }
cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to); cur_node->router()->SetReceiver(to->GetPeerLocalAddress(), to);
std::unique_ptr<EmulatedRoute> route = std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
std::make_unique<EmulatedRoute>(from, std::move(via_nodes), to); static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
static_cast<EmulatedEndpointImpl*>(to));
EmulatedRoute* out = route.get(); EmulatedRoute* out = route.get();
routes_.push_back(std::move(route)); routes_.push_back(std::move(route));
return out; return out;
@ -231,8 +235,8 @@ FakeTcpCrossTraffic* NetworkEmulationManagerImpl::StartFakeTcpCrossTraffic(
TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute( TcpMessageRoute* NetworkEmulationManagerImpl::CreateTcpRoute(
EmulatedRoute* send_route, EmulatedRoute* send_route,
EmulatedRoute* ret_route) { EmulatedRoute* ret_route) {
auto tcp_route = std::make_unique<TcpMessageRoute>(clock_, task_queue_.Get(), auto tcp_route = std::make_unique<TcpMessageRouteImpl>(
send_route, ret_route); clock_, task_queue_.Get(), send_route, ret_route);
auto* route_ptr = tcp_route.get(); auto* route_ptr = tcp_route.get();
task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable { task_queue_.PostTask([this, tcp_route = std::move(tcp_route)]() mutable {
tcp_message_routes_.push_back(std::move(tcp_route)); tcp_message_routes_.push_back(std::move(tcp_route));
@ -254,7 +258,12 @@ void NetworkEmulationManagerImpl::StopCrossTraffic(
EmulatedNetworkManagerInterface* EmulatedNetworkManagerInterface*
NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface( NetworkEmulationManagerImpl::CreateEmulatedNetworkManagerInterface(
const std::vector<EmulatedEndpoint*>& endpoints) { const std::vector<EmulatedEndpoint*>& endpoints) {
auto endpoints_container = std::make_unique<EndpointsContainer>(endpoints); std::vector<EmulatedEndpointImpl*> endpoint_impls;
for (EmulatedEndpoint* endpoint : endpoints) {
endpoint_impls.push_back(static_cast<EmulatedEndpointImpl*>(endpoint));
}
auto endpoints_container =
std::make_unique<EndpointsContainer>(endpoint_impls);
auto network_manager = std::make_unique<EmulatedNetworkManager>( auto network_manager = std::make_unique<EmulatedNetworkManager>(
clock_, &task_queue_, endpoints_container.get()); clock_, &task_queue_, endpoints_container.get());
for (auto* endpoint : endpoints) { for (auto* endpoint : endpoints) {

View File

@ -32,7 +32,6 @@
#include "test/network/emulated_network_manager.h" #include "test/network/emulated_network_manager.h"
#include "test/network/fake_network_socket_server.h" #include "test/network/fake_network_socket_server.h"
#include "test/network/network_emulation.h" #include "test/network/network_emulation.h"
#include "test/network/simulated_network_node.h"
#include "test/network/traffic_route.h" #include "test/network/traffic_route.h"
namespace webrtc { namespace webrtc {
@ -49,7 +48,7 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
EmulatedNetworkNode* CreateEmulatedNode( EmulatedNetworkNode* CreateEmulatedNode(
std::unique_ptr<NetworkBehaviorInterface> network_behavior) override; std::unique_ptr<NetworkBehaviorInterface> network_behavior) override;
SimulatedNetworkNode::Builder NodeBuilder(); SimulatedNetworkNode::Builder NodeBuilder() override;
EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) override; EmulatedEndpoint* CreateEndpoint(EmulatedEndpointConfig config) override;
void EnableEndpoint(EmulatedEndpoint* endpoint) override; void EnableEndpoint(EmulatedEndpoint* endpoint) override;
@ -60,7 +59,7 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
EmulatedEndpoint* to) override; EmulatedEndpoint* to) override;
EmulatedRoute* CreateRoute( EmulatedRoute* CreateRoute(
const std::vector<EmulatedNetworkNode*>& via_nodes); const std::vector<EmulatedNetworkNode*>& via_nodes) override;
void ClearRoute(EmulatedRoute* route) override; void ClearRoute(EmulatedRoute* route) override;
@ -78,7 +77,7 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
FakeTcpConfig config); FakeTcpConfig config);
TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route, TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,
EmulatedRoute* ret_route); EmulatedRoute* ret_route) override;
void StopCrossTraffic(FakeTcpCrossTraffic* traffic); void StopCrossTraffic(FakeTcpCrossTraffic* traffic);
@ -105,7 +104,7 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
std::vector<std::unique_ptr<RandomWalkCrossTraffic>> random_cross_traffics_; std::vector<std::unique_ptr<RandomWalkCrossTraffic>> random_cross_traffics_;
std::vector<std::unique_ptr<PulsedPeaksCrossTraffic>> pulsed_cross_traffics_; std::vector<std::unique_ptr<PulsedPeaksCrossTraffic>> pulsed_cross_traffics_;
std::list<std::unique_ptr<FakeTcpCrossTraffic>> tcp_cross_traffics_; std::list<std::unique_ptr<FakeTcpCrossTraffic>> tcp_cross_traffics_;
std::list<std::unique_ptr<TcpMessageRoute>> tcp_message_routes_; std::list<std::unique_ptr<TcpMessageRouteImpl>> tcp_message_routes_;
std::vector<std::unique_ptr<EndpointsContainer>> endpoints_containers_; std::vector<std::unique_ptr<EndpointsContainer>> endpoints_containers_;
std::vector<std::unique_ptr<EmulatedNetworkManager>> network_managers_; std::vector<std::unique_ptr<EmulatedNetworkManager>> network_managers_;

View File

@ -1,42 +0,0 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef TEST_NETWORK_SIMULATED_NETWORK_NODE_H_
#define TEST_NETWORK_SIMULATED_NETWORK_NODE_H_
#include "api/test/network_emulation_manager.h"
#include "call/simulated_network.h"
namespace webrtc {
namespace test {
// Helper struct to simplify creation of simulated network behaviors.
struct SimulatedNetworkNode {
SimulatedNetwork* simulation;
EmulatedNetworkNode* node;
class Builder {
public:
Builder();
explicit Builder(NetworkEmulationManager* net);
Builder& config(SimulatedNetwork::Config config);
Builder& delay_ms(int queue_delay_ms);
Builder& capacity_kbps(int link_capacity_kbps);
Builder& capacity_Mbps(int link_capacity_Mbps);
Builder& loss(double loss_rate);
SimulatedNetworkNode Build() const;
SimulatedNetworkNode Build(NetworkEmulationManager* net) const;
private:
NetworkEmulationManager* const net_ = nullptr;
SimulatedNetwork::Config config_;
};
};
} // namespace test
} // namespace webrtc
#endif // TEST_NETWORK_SIMULATED_NETWORK_NODE_H_