Introduce default routes for network emulation

Change-Id: If9bc941d54844e0f22147fb13e148ced1bc49c71
Bug: b/180750880
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/208227
Reviewed-by: Andrey Logvin <landrey@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33310}
This commit is contained in:
Artem Titov 2021-02-19 20:26:32 +01:00 committed by Commit Bot
parent 1dd94a023a
commit 3d37e06fed
9 changed files with 291 additions and 72 deletions

View File

@ -225,7 +225,16 @@ class EmulatedEndpoint : public EmulatedNetworkReceiverInterface {
virtual absl::optional<uint16_t> BindReceiver(
uint16_t desired_port,
EmulatedNetworkReceiverInterface* receiver) = 0;
// Unbinds receiver from the specified port. Do nothing if no receiver was
// binded before.
virtual void UnbindReceiver(uint16_t port) = 0;
// Binds receiver that will accept all packets which arrived on any port
// for which there are no binded receiver.
virtual void BindDefaultReceiver(
EmulatedNetworkReceiverInterface* receiver) = 0;
// Unbinds default receiver. Do nothing if no default receiver was binded
// before.
virtual void UnbindDefaultReceiver() = 0;
virtual rtc::IPAddress GetPeerLocalAddress() const = 0;
private:

View File

@ -68,6 +68,14 @@ struct EmulatedEndpointConfig {
// Network type which will be used to represent endpoint to WebRTC.
rtc::AdapterType type = rtc::AdapterType::ADAPTER_TYPE_UNKNOWN;
StatsGatheringMode stats_gathering_mode = StatsGatheringMode::kDefault;
// Allow endpoint to send packets specifying source IP address different to
// the current endpoint IP address. If false endpoint will crash if attempt
// to send such packet will be done.
bool allow_send_packet_with_different_source_ip = false;
// Allow endpoint to receive packet with destination IP address different to
// the current endpoint IP address. If false endpoint will crash if such
// packet will arrive.
bool allow_receive_packets_with_different_dest_ip = false;
};
struct EmulatedTURNServerConfig {
@ -226,6 +234,35 @@ class NetworkEmulationManager {
virtual EmulatedRoute* CreateRoute(
const std::vector<EmulatedNetworkNode*>& via_nodes) = 0;
// Creates a default route between endpoints going through specified network
// nodes. Default route is used for packet when there is no known route for
// packet's destination IP.
//
// This route is single direction only and describe how traffic that was
// sent by network interface |from| have to be delivered in case if routing
// was unspecified. Return object can be used to remove created route. The
// route must contains at least one network node inside it.
//
// Assume that E{0-9} are endpoints and N{0-9} are network nodes, then
// creation of the route have to follow these rules:
// 1. A route consists of a source endpoint, an ordered list of one or
// more network nodes, and a destination endpoint.
// 2. If (E1, ..., E2) is a route, then E1 != E2.
// In other words, the source and the destination may not be the same.
// 3. Given two simultaneously existing routes (E1, ..., E2) and
// (E3, ..., E4), either E1 != E3 or E2 != E4.
// In other words, there may be at most one route from any given source
// endpoint to any given destination endpoint.
// 4. Given two simultaneously existing routes (E1, ..., N1, ..., E2)
// and (E3, ..., N2, ..., E4), either N1 != N2 or E2 != E4.
// In other words, a network node may not belong to two routes that lead
// to the same destination endpoint.
// 5. Any node N can belong to only one default route.
virtual EmulatedRoute* CreateDefaultRoute(
EmulatedEndpoint* from,
const std::vector<EmulatedNetworkNode*>& via_nodes,
EmulatedEndpoint* to) = 0;
// Removes route previously created by CreateRoute(...).
// Caller mustn't call this function with route, that have been already
// removed earlier. Removing a route that is currently in use will lead to

View File

@ -46,6 +46,7 @@ rtc_library("emulated_network") {
"../../api:simulated_network_api",
"../../api:time_controller",
"../../api/numerics",
"../../api/test/network_emulation",
"../../api/transport:stun_types",
"../../api/units:data_rate",
"../../api/units:data_size",

View File

@ -49,15 +49,12 @@ struct TrafficCounterFixture {
SimulatedClock clock{0};
CountingReceiver counter;
TaskQueueForTest task_queue_;
EmulatedEndpointImpl endpoint{
/*id=*/1,
absl::nullopt,
rtc::IPAddress(kTestIpAddress),
EmulatedEndpointConfig::StatsGatheringMode::kDefault,
/*is_enabled=*/true,
/*type=*/rtc::AdapterType::ADAPTER_TYPE_UNKNOWN,
&task_queue_,
&clock};
EmulatedEndpointImpl endpoint{EmulatedEndpointImpl::Options{
/*id=*/1,
rtc::IPAddress(kTestIpAddress),
EmulatedEndpointConfig(),
},
/*is_enabled=*/true, &task_queue_, &clock};
};
} // namespace

View File

@ -13,9 +13,11 @@
#include <algorithm>
#include <limits>
#include <memory>
#include <utility>
#include "absl/types/optional.h"
#include "api/numerics/samples_stats_counter.h"
#include "api/test/network_emulation/network_emulation_interfaces.h"
#include "api/units/data_size.h"
#include "rtc_base/logging.h"
@ -346,6 +348,9 @@ void NetworkRouterNode::OnPacketReceived(EmulatedIpPacket packet) {
}
auto receiver_it = routing_.find(packet.to.ipaddr());
if (receiver_it == routing_.end()) {
if (default_receiver_.has_value()) {
(*default_receiver_)->OnPacketReceived(std::move(packet));
}
return;
}
RTC_CHECK(receiver_it != routing_.end());
@ -370,6 +375,23 @@ void NetworkRouterNode::RemoveReceiver(const rtc::IPAddress& dest_ip) {
routing_.erase(dest_ip);
}
void NetworkRouterNode::SetDefaultReceiver(
EmulatedNetworkReceiverInterface* receiver) {
task_queue_->PostTask([=] {
RTC_DCHECK_RUN_ON(task_queue_);
if (default_receiver_.has_value()) {
RTC_CHECK_EQ(*default_receiver_, receiver)
<< "Router already default receiver";
}
default_receiver_ = receiver;
});
}
void NetworkRouterNode::RemoveDefaultReceiver() {
RTC_DCHECK_RUN_ON(task_queue_);
default_receiver_ = absl::nullopt;
}
void NetworkRouterNode::SetWatcher(
std::function<void(const EmulatedIpPacket&)> watcher) {
task_queue_->PostTask([=] {
@ -415,64 +437,72 @@ void EmulatedNetworkNode::ClearRoute(const rtc::IPAddress& receiver_ip,
EmulatedNetworkNode::~EmulatedNetworkNode() = default;
EmulatedEndpointImpl::EmulatedEndpointImpl(
uint64_t id,
absl::optional<std::string> name,
const rtc::IPAddress& ip,
EmulatedEndpointConfig::StatsGatheringMode stats_gathering_mode,
bool is_enabled,
rtc::AdapterType type,
rtc::TaskQueue* task_queue,
Clock* clock)
: id_(id),
log_name_(ip.ToString() + " (" + name.value_or("") + ")"),
peer_local_addr_(ip),
stats_gathering_mode_(stats_gathering_mode),
EmulatedEndpointImpl::Options::Options(uint64_t id,
const rtc::IPAddress& ip,
const EmulatedEndpointConfig& config)
: id(id),
ip(ip),
stats_gathering_mode(config.stats_gathering_mode),
type(config.type),
allow_send_packet_with_different_source_ip(
config.allow_send_packet_with_different_source_ip),
allow_receive_packets_with_different_dest_ip(
config.allow_send_packet_with_different_source_ip),
log_name(ip.ToString() + " (" + config.name.value_or("") + ")") {}
EmulatedEndpointImpl::EmulatedEndpointImpl(const Options& options,
bool is_enabled,
rtc::TaskQueue* task_queue,
Clock* clock)
: options_(options),
is_enabled_(is_enabled),
type_(type),
clock_(clock),
task_queue_(task_queue),
router_(task_queue_),
next_port_(kFirstEphemeralPort),
stats_builder_(peer_local_addr_) {
stats_builder_(options_.ip) {
constexpr int kIPv4NetworkPrefixLength = 24;
constexpr int kIPv6NetworkPrefixLength = 64;
int prefix_length = 0;
if (ip.family() == AF_INET) {
if (options_.ip.family() == AF_INET) {
prefix_length = kIPv4NetworkPrefixLength;
} else if (ip.family() == AF_INET6) {
} else if (options_.ip.family() == AF_INET6) {
prefix_length = kIPv6NetworkPrefixLength;
}
rtc::IPAddress prefix = TruncateIP(ip, prefix_length);
rtc::IPAddress prefix = TruncateIP(options_.ip, prefix_length);
network_ = std::make_unique<rtc::Network>(
ip.ToString(), "Endpoint id=" + std::to_string(id_), prefix,
prefix_length, type_);
network_->AddIP(ip);
options_.ip.ToString(), "Endpoint id=" + std::to_string(options_.id),
prefix, prefix_length, options_.type);
network_->AddIP(options_.ip);
enabled_state_checker_.Detach();
RTC_LOG(INFO) << "Created emulated endpoint " << log_name_ << "; id=" << id_;
RTC_LOG(INFO) << "Created emulated endpoint " << options_.log_name
<< "; id=" << options_.id;
}
EmulatedEndpointImpl::~EmulatedEndpointImpl() = default;
uint64_t EmulatedEndpointImpl::GetId() const {
return id_;
return options_.id;
}
void EmulatedEndpointImpl::SendPacket(const rtc::SocketAddress& from,
const rtc::SocketAddress& to,
rtc::CopyOnWriteBuffer packet_data,
uint16_t application_overhead) {
RTC_CHECK(from.ipaddr() == peer_local_addr_);
if (!options_.allow_send_packet_with_different_source_ip) {
RTC_CHECK(from.ipaddr() == options_.ip);
}
EmulatedIpPacket packet(from, to, std::move(packet_data),
clock_->CurrentTime(), application_overhead);
task_queue_->PostTask([this, packet = std::move(packet)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_);
stats_builder_.OnPacketSent(
packet.arrival_time, clock_->CurrentTime(), packet.to.ipaddr(),
DataSize::Bytes(packet.ip_packet_size()), stats_gathering_mode_);
stats_builder_.OnPacketSent(packet.arrival_time, clock_->CurrentTime(),
packet.to.ipaddr(),
DataSize::Bytes(packet.ip_packet_size()),
options_.stats_gathering_mode);
if (packet.to.ipaddr() == peer_local_addr_) {
if (packet.to.ipaddr() == options_.ip) {
OnPacketReceived(std::move(packet));
} else {
router_.OnPacketReceived(std::move(packet));
@ -499,15 +529,16 @@ absl::optional<uint16_t> EmulatedEndpointImpl::BindReceiver(
}
}
RTC_CHECK(port != 0) << "Can't find free port for receiver in endpoint "
<< log_name_ << "; id=" << id_;
<< options_.log_name << "; id=" << options_.id;
bool result = port_to_receiver_.insert({port, receiver}).second;
if (!result) {
RTC_LOG(INFO) << "Can't bind receiver to used port " << desired_port
<< " in endpoint " << log_name_ << "; id=" << id_;
<< " in endpoint " << options_.log_name
<< "; id=" << options_.id;
return absl::nullopt;
}
RTC_LOG(INFO) << "New receiver is binded to endpoint " << log_name_
<< "; id=" << id_ << " on port " << port;
RTC_LOG(INFO) << "New receiver is binded to endpoint " << options_.log_name
<< "; id=" << options_.id << " on port " << port;
return port;
}
@ -523,33 +554,60 @@ uint16_t EmulatedEndpointImpl::NextPort() {
void EmulatedEndpointImpl::UnbindReceiver(uint16_t port) {
rtc::CritScope crit(&receiver_lock_);
RTC_LOG(INFO) << "Receiver is removed on port " << port << " from endpoint "
<< options_.log_name << "; id=" << options_.id;
port_to_receiver_.erase(port);
}
void EmulatedEndpointImpl::BindDefaultReceiver(
EmulatedNetworkReceiverInterface* receiver) {
rtc::CritScope crit(&receiver_lock_);
RTC_CHECK(!default_receiver_.has_value())
<< "Endpoint " << options_.log_name << "; id=" << options_.id
<< " already has default receiver";
RTC_LOG(INFO) << "Default receiver is binded to endpoint "
<< options_.log_name << "; id=" << options_.id;
default_receiver_ = receiver;
}
void EmulatedEndpointImpl::UnbindDefaultReceiver() {
rtc::CritScope crit(&receiver_lock_);
RTC_LOG(INFO) << "Default receiver is removed from endpoint "
<< options_.log_name << "; id=" << options_.id;
default_receiver_ = absl::nullopt;
}
rtc::IPAddress EmulatedEndpointImpl::GetPeerLocalAddress() const {
return peer_local_addr_;
return options_.ip;
}
void EmulatedEndpointImpl::OnPacketReceived(EmulatedIpPacket packet) {
RTC_DCHECK_RUN_ON(task_queue_);
RTC_CHECK(packet.to.ipaddr() == peer_local_addr_)
<< "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
<< packet.to.ipaddr().ToString()
<< "; Receiver peer_local_addr_=" << peer_local_addr_.ToString();
if (options_.allow_receive_packets_with_different_dest_ip) {
RTC_CHECK(packet.to.ipaddr() == options_.ip)
<< "Routing error: wrong destination endpoint. Packet.to.ipaddr()=: "
<< packet.to.ipaddr().ToString()
<< "; Receiver options_.ip=" << options_.ip.ToString();
}
rtc::CritScope crit(&receiver_lock_);
stats_builder_.OnPacketReceived(clock_->CurrentTime(), packet.from.ipaddr(),
DataSize::Bytes(packet.ip_packet_size()),
stats_gathering_mode_);
options_.stats_gathering_mode);
auto it = port_to_receiver_.find(packet.to.port());
if (it == port_to_receiver_.end()) {
if (default_receiver_.has_value()) {
(*default_receiver_)->OnPacketReceived(std::move(packet));
return;
}
// It can happen, that remote peer closed connection, but there still some
// packets, that are going to it. It can happen during peer connection close
// process: one peer closed connection, second still sending data.
RTC_LOG(INFO) << "Drop packet: no receiver registered in " << log_name_
<< "; id=" << id_ << " on port " << packet.to.port();
RTC_LOG(INFO) << "Drop packet: no receiver registered in "
<< options_.log_name << "; id=" << options_.id << " on port "
<< packet.to.port();
stats_builder_.OnPacketDropped(packet.from.ipaddr(),
DataSize::Bytes(packet.ip_packet_size()),
stats_gathering_mode_);
options_.stats_gathering_mode);
return;
}
// Endpoint assumes frequent calls to bind and unbind methods, so it holds

View File

@ -418,6 +418,10 @@ class LinkEmulation : public EmulatedNetworkReceiverInterface {
uint64_t next_packet_id_ RTC_GUARDED_BY(task_queue_) = 1;
};
// Represents a component responsible for routing packets based on their IP
// address. All possible routes have to be set explicitly before packet for
// desired destination will be seen for the first time. If route is unknown
// the packet will be silently dropped.
class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
public:
explicit NetworkRouterNode(rtc::TaskQueue* task_queue);
@ -426,11 +430,17 @@ class NetworkRouterNode : public EmulatedNetworkReceiverInterface {
void SetReceiver(const rtc::IPAddress& dest_ip,
EmulatedNetworkReceiverInterface* receiver);
void RemoveReceiver(const rtc::IPAddress& dest_ip);
// Sets a default receive that will be used for all incoming packets for which
// there is no specific receiver binded to their destination port.
void SetDefaultReceiver(EmulatedNetworkReceiverInterface* receiver);
void RemoveDefaultReceiver();
void SetWatcher(std::function<void(const EmulatedIpPacket&)> watcher);
void SetFilter(std::function<bool(const EmulatedIpPacket&)> filter);
private:
rtc::TaskQueue* const task_queue_;
absl::optional<EmulatedNetworkReceiverInterface*> default_receiver_
RTC_GUARDED_BY(task_queue_);
std::map<rtc::IPAddress, EmulatedNetworkReceiverInterface*> routing_
RTC_GUARDED_BY(task_queue_);
std::function<void(const EmulatedIpPacket&)> watcher_
@ -481,15 +491,33 @@ class EmulatedNetworkNode : public EmulatedNetworkReceiverInterface {
// from other EmulatedNetworkNodes.
class EmulatedEndpointImpl : public EmulatedEndpoint {
public:
EmulatedEndpointImpl(
uint64_t id,
absl::optional<std::string> name,
const rtc::IPAddress& ip,
EmulatedEndpointConfig::StatsGatheringMode stats_gathering_mode,
bool is_enabled,
rtc::AdapterType type,
rtc::TaskQueue* task_queue,
Clock* clock);
struct Options {
Options(uint64_t id,
const rtc::IPAddress& ip,
const EmulatedEndpointConfig& config);
// TODO(titovartem) check if we can remove id.
uint64_t id;
// Endpoint local IP address.
rtc::IPAddress ip;
EmulatedEndpointConfig::StatsGatheringMode stats_gathering_mode;
rtc::AdapterType type;
// Allow endpoint to send packets specifying source IP address different to
// the current endpoint IP address. If false endpoint will crash if attempt
// to send such packet will be done.
bool allow_send_packet_with_different_source_ip;
// Allow endpoint to receive packet with destination IP address different to
// the current endpoint IP address. If false endpoint will crash if such
// packet will arrive.
bool allow_receive_packets_with_different_dest_ip;
// Name of the endpoint used for logging purposes.
std::string log_name;
};
EmulatedEndpointImpl(const Options& options,
bool is_enabled,
rtc::TaskQueue* task_queue,
Clock* clock);
~EmulatedEndpointImpl() override;
uint64_t GetId() const;
@ -505,6 +533,8 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
uint16_t desired_port,
EmulatedNetworkReceiverInterface* receiver) override;
void UnbindReceiver(uint16_t port) override;
void BindDefaultReceiver(EmulatedNetworkReceiverInterface* receiver) override;
void UnbindDefaultReceiver() override;
rtc::IPAddress GetPeerLocalAddress() const override;
@ -526,19 +556,16 @@ class EmulatedEndpointImpl : public EmulatedEndpoint {
rtc::RecursiveCriticalSection receiver_lock_;
SequenceChecker enabled_state_checker_;
const uint64_t id_;
const std::string log_name_;
// Peer's local IP address for this endpoint network interface.
const rtc::IPAddress peer_local_addr_;
const EmulatedEndpointConfig::StatsGatheringMode stats_gathering_mode_;
const Options options_;
bool is_enabled_ RTC_GUARDED_BY(enabled_state_checker_);
const rtc::AdapterType type_;
Clock* const clock_;
rtc::TaskQueue* const task_queue_;
std::unique_ptr<rtc::Network> network_;
NetworkRouterNode router_;
uint16_t next_port_ RTC_GUARDED_BY(receiver_lock_);
absl::optional<EmulatedNetworkReceiverInterface*> default_receiver_
RTC_GUARDED_BY(receiver_lock_);
std::map<uint16_t, EmulatedNetworkReceiverInterface*> port_to_receiver_
RTC_GUARDED_BY(receiver_lock_);
@ -549,13 +576,19 @@ class EmulatedRoute {
public:
EmulatedRoute(EmulatedEndpointImpl* from,
std::vector<EmulatedNetworkNode*> via_nodes,
EmulatedEndpointImpl* to)
: from(from), via_nodes(std::move(via_nodes)), to(to), active(true) {}
EmulatedEndpointImpl* to,
bool is_default)
: from(from),
via_nodes(std::move(via_nodes)),
to(to),
active(true),
is_default(is_default) {}
EmulatedEndpointImpl* from;
std::vector<EmulatedNetworkNode*> via_nodes;
EmulatedEndpointImpl* to;
bool active;
bool is_default;
};
// This object is immutable and so thread safe.

View File

@ -107,8 +107,8 @@ EmulatedEndpoint* NetworkEmulationManagerImpl::CreateEndpoint(
bool res = used_ip_addresses_.insert(*ip).second;
RTC_CHECK(res) << "IP=" << ip->ToString() << " already in use";
auto node = std::make_unique<EmulatedEndpointImpl>(
next_node_id_++, config.name, *ip, config.stats_gathering_mode,
config.start_as_enabled, config.type, &task_queue_, clock_);
EmulatedEndpointImpl::Options(next_node_id_++, *ip, config),
config.start_as_enabled, &task_queue_, clock_);
EmulatedEndpoint* out = node.get();
endpoints_.push_back(std::move(node));
return out;
@ -148,7 +148,7 @@ EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
static_cast<EmulatedEndpointImpl*>(to));
static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/false);
EmulatedRoute* out = route.get();
routes_.push_back(std::move(route));
return out;
@ -161,16 +161,50 @@ EmulatedRoute* NetworkEmulationManagerImpl::CreateRoute(
return CreateRoute(from, via_nodes, to);
}
EmulatedRoute* NetworkEmulationManagerImpl::CreateDefaultRoute(
EmulatedEndpoint* from,
const std::vector<EmulatedNetworkNode*>& via_nodes,
EmulatedEndpoint* to) {
// Because endpoint has no send node by default at least one should be
// provided here.
RTC_CHECK(!via_nodes.empty());
static_cast<EmulatedEndpointImpl*>(from)->router()->SetDefaultReceiver(
via_nodes[0]);
EmulatedNetworkNode* cur_node = via_nodes[0];
for (size_t i = 1; i < via_nodes.size(); ++i) {
cur_node->router()->SetDefaultReceiver(via_nodes[i]);
cur_node = via_nodes[i];
}
cur_node->router()->SetDefaultReceiver(to);
std::unique_ptr<EmulatedRoute> route = std::make_unique<EmulatedRoute>(
static_cast<EmulatedEndpointImpl*>(from), std::move(via_nodes),
static_cast<EmulatedEndpointImpl*>(to), /*is_default=*/true);
EmulatedRoute* out = route.get();
routes_.push_back(std::move(route));
return out;
}
void NetworkEmulationManagerImpl::ClearRoute(EmulatedRoute* route) {
RTC_CHECK(route->active) << "Route already cleared";
task_queue_.SendTask(
[route]() {
// Remove receiver from intermediate nodes.
for (auto* node : route->via_nodes) {
node->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
if (route->is_default) {
node->router()->RemoveDefaultReceiver();
} else {
node->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
}
}
// Remove destination endpoint from source endpoint's router.
route->from->router()->RemoveReceiver(route->to->GetPeerLocalAddress());
if (route->is_default) {
route->from->router()->RemoveDefaultReceiver();
} else {
route->from->router()->RemoveReceiver(
route->to->GetPeerLocalAddress());
}
route->active = false;
},

View File

@ -61,6 +61,11 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
EmulatedRoute* CreateRoute(
const std::vector<EmulatedNetworkNode*>& via_nodes) override;
EmulatedRoute* CreateDefaultRoute(
EmulatedEndpoint* from,
const std::vector<EmulatedNetworkNode*>& via_nodes,
EmulatedEndpoint* to) override;
void ClearRoute(EmulatedRoute* route) override;
TcpMessageRoute* CreateTcpRoute(EmulatedRoute* send_route,

View File

@ -587,6 +587,51 @@ TEST(NetworkEmulationManagerTest, EndpointLoopback) {
network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1));
}
TEST(NetworkEmulationManagerTest, EndpointCanSendWithDifferentSourceIp) {
constexpr uint32_t kEndpointIp = 0xC0A80011; // 192.168.0.17
constexpr uint32_t kSourceIp = 0xC0A80012; // 192.168.0.18
NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated);
EmulatedEndpointConfig endpoint_config;
endpoint_config.ip = rtc::IPAddress(kEndpointIp);
endpoint_config.allow_send_packet_with_different_source_ip = true;
auto endpoint = network_manager.CreateEndpoint(endpoint_config);
MockReceiver receiver;
EXPECT_CALL(receiver, OnPacketReceived(::testing::_)).Times(1);
ASSERT_EQ(endpoint->BindReceiver(80, &receiver), 80);
endpoint->SendPacket(rtc::SocketAddress(kSourceIp, 80),
rtc::SocketAddress(endpoint->GetPeerLocalAddress(), 80),
"Hello");
network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1));
}
TEST(NetworkEmulationManagerTest,
EndpointCanReceiveWithDifferentDestIpThroughDefaultRoute) {
constexpr uint32_t kDestEndpointIp = 0xC0A80011; // 192.168.0.17
constexpr uint32_t kDestIp = 0xC0A80012; // 192.168.0.18
NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated);
auto sender_endpoint =
network_manager.CreateEndpoint(EmulatedEndpointConfig());
EmulatedEndpointConfig endpoint_config;
endpoint_config.ip = rtc::IPAddress(kDestEndpointIp);
endpoint_config.allow_receive_packets_with_different_dest_ip = true;
auto receiver_endpoint = network_manager.CreateEndpoint(endpoint_config);
MockReceiver receiver;
EXPECT_CALL(receiver, OnPacketReceived(::testing::_)).Times(1);
ASSERT_EQ(receiver_endpoint->BindReceiver(80, &receiver), 80);
network_manager.CreateDefaultRoute(
sender_endpoint, {network_manager.NodeBuilder().Build().node},
receiver_endpoint);
sender_endpoint->SendPacket(
rtc::SocketAddress(sender_endpoint->GetPeerLocalAddress(), 80),
rtc::SocketAddress(kDestIp, 80), "Hello");
network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1));
}
TEST(NetworkEmulationManagerTURNTest, GetIceServerConfig) {
NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime);
auto turn = network_manager.CreateTURNServer(EmulatedTURNServerConfig());