Add TURN server to Emulated Network infrastructure
This can be used to test ICE behavior. Bug: chromium:1024965 Change-Id: Ie4ba9cd5c3cf3c2f71bab3637f925263dbc6296e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/193701 Commit-Queue: Jonas Oreland <jonaso@webrtc.org> Reviewed-by: Artem Titov <titovartem@webrtc.org> Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32625}
This commit is contained in:
parent
26ce03e469
commit
97050115f0
@ -13,6 +13,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "api/array_view.h"
|
||||
@ -66,6 +67,37 @@ struct EmulatedEndpointConfig {
|
||||
StatsGatheringMode stats_gathering_mode = StatsGatheringMode::kDefault;
|
||||
};
|
||||
|
||||
struct EmulatedTURNServerConfig {
|
||||
EmulatedEndpointConfig client_config;
|
||||
EmulatedEndpointConfig peer_config;
|
||||
};
|
||||
|
||||
// EmulatedTURNServer is an abstraction for a TURN server.
|
||||
class EmulatedTURNServerInterface {
|
||||
public:
|
||||
struct IceServerConfig {
|
||||
std::string username;
|
||||
std::string password;
|
||||
std::string url;
|
||||
};
|
||||
|
||||
virtual ~EmulatedTURNServerInterface() {}
|
||||
|
||||
// Get an IceServer configuration suitable to add to a PeerConnection.
|
||||
virtual IceServerConfig GetIceServerConfig() const = 0;
|
||||
|
||||
// Get non-null client endpoint, an endpoint that accepts TURN allocations.
|
||||
// This shall typically be connected to one or more webrtc endpoint.
|
||||
virtual EmulatedEndpoint* GetClientEndpoint() const = 0;
|
||||
|
||||
// Returns socket address, which client should use to connect to TURN server
|
||||
// and do TURN allocation.
|
||||
virtual rtc::SocketAddress GetClientEndpointAddress() const = 0;
|
||||
|
||||
// Get non-null peer endpoint, that is "connected to the internet".
|
||||
// This shall typically be connected to another TURN server.
|
||||
virtual EmulatedEndpoint* GetPeerEndpoint() const = 0;
|
||||
};
|
||||
|
||||
// Provide interface to obtain all required objects to inject network emulation
|
||||
// layer into PeerConnection. Also contains information about network interfaces
|
||||
@ -210,6 +242,13 @@ class NetworkEmulationManager {
|
||||
rtc::ArrayView<EmulatedEndpoint*> endpoints,
|
||||
std::function<void(std::unique_ptr<EmulatedNetworkStats>)>
|
||||
stats_callback) = 0;
|
||||
|
||||
// Create a EmulatedTURNServer.
|
||||
// The TURN server has 2 endpoints that need to be connected with routes,
|
||||
// - GetClientEndpoint() - the endpoint that accepts TURN allocations.
|
||||
// - GetPeerEndpoint() - the endpoint that is "connected to the internet".
|
||||
virtual EmulatedTURNServerInterface* CreateTURNServer(
|
||||
EmulatedTURNServerConfig config) = 0;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -76,5 +76,8 @@ specific_include_rules = {
|
||||
],
|
||||
"benchmark_main\.cc": [
|
||||
"+benchmark",
|
||||
],
|
||||
"emulated_turn_server\.h": [
|
||||
"+p2p/base/turn_server.h",
|
||||
]
|
||||
}
|
||||
|
||||
@ -25,6 +25,8 @@ rtc_library("emulated_network") {
|
||||
"cross_traffic.h",
|
||||
"emulated_network_manager.cc",
|
||||
"emulated_network_manager.h",
|
||||
"emulated_turn_server.cc",
|
||||
"emulated_turn_server.h",
|
||||
"fake_network_socket_server.cc",
|
||||
"fake_network_socket_server.h",
|
||||
"network_emulation.cc",
|
||||
@ -37,14 +39,17 @@ rtc_library("emulated_network") {
|
||||
deps = [
|
||||
"../../api:array_view",
|
||||
"../../api:network_emulation_manager_api",
|
||||
"../../api:packet_socket_factory",
|
||||
"../../api:simulated_network_api",
|
||||
"../../api:time_controller",
|
||||
"../../api/numerics",
|
||||
"../../api/transport:stun_types",
|
||||
"../../api/units:data_rate",
|
||||
"../../api/units:data_size",
|
||||
"../../api/units:time_delta",
|
||||
"../../api/units:timestamp",
|
||||
"../../call:simulated_network",
|
||||
"../../p2p:p2p_server_utils",
|
||||
"../../rtc_base",
|
||||
"../../rtc_base:rtc_base_tests_utils",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
|
||||
188
test/network/emulated_turn_server.cc
Normal file
188
test/network/emulated_turn_server.cc
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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 "test/network/emulated_turn_server.h"
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "api/packet_socket_factory.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kTestRealm[] = "example.org";
|
||||
static const char kTestSoftware[] = "TestTurnServer";
|
||||
|
||||
// A wrapper class for copying data between an AsyncPacketSocket and a
|
||||
// EmulatedEndpoint. This is used by the cricket::TurnServer when
|
||||
// sending data back into the emulated network.
|
||||
class AsyncPacketSocketWrapper : public rtc::AsyncPacketSocket {
|
||||
public:
|
||||
AsyncPacketSocketWrapper(webrtc::test::EmulatedTURNServer* turn_server,
|
||||
webrtc::EmulatedEndpoint* endpoint,
|
||||
uint16_t port)
|
||||
: turn_server_(turn_server),
|
||||
endpoint_(endpoint),
|
||||
local_address_(
|
||||
rtc::SocketAddress(endpoint_->GetPeerLocalAddress(), port)) {}
|
||||
~AsyncPacketSocketWrapper() { turn_server_->Unbind(local_address_); }
|
||||
|
||||
rtc::SocketAddress GetLocalAddress() const override { return local_address_; }
|
||||
rtc::SocketAddress GetRemoteAddress() const override {
|
||||
return rtc::SocketAddress();
|
||||
}
|
||||
int Send(const void* pv,
|
||||
size_t cb,
|
||||
const rtc::PacketOptions& options) override {
|
||||
RTC_CHECK(false) << "TCP not implemented";
|
||||
return -1;
|
||||
}
|
||||
int SendTo(const void* pv,
|
||||
size_t cb,
|
||||
const rtc::SocketAddress& addr,
|
||||
const rtc::PacketOptions& options) override {
|
||||
// Copy from rtc::AsyncPacketSocket to EmulatedEndpoint.
|
||||
rtc::CopyOnWriteBuffer buf(reinterpret_cast<const char*>(pv), cb);
|
||||
endpoint_->SendPacket(local_address_, addr, buf);
|
||||
return cb;
|
||||
}
|
||||
int Close() override { return 0; }
|
||||
|
||||
rtc::AsyncPacketSocket::State GetState() const override {
|
||||
return rtc::AsyncPacketSocket::STATE_BOUND;
|
||||
}
|
||||
int GetOption(rtc::Socket::Option opt, int* value) override { return 0; }
|
||||
int SetOption(rtc::Socket::Option opt, int value) override { return 0; }
|
||||
int GetError() const override { return 0; }
|
||||
void SetError(int error) override {}
|
||||
|
||||
private:
|
||||
webrtc::test::EmulatedTURNServer* const turn_server_;
|
||||
webrtc::EmulatedEndpoint* const endpoint_;
|
||||
const rtc::SocketAddress local_address_;
|
||||
};
|
||||
|
||||
// A wrapper class for cricket::TurnServer to allocate sockets.
|
||||
class PacketSocketFactoryWrapper : public rtc::PacketSocketFactory {
|
||||
public:
|
||||
explicit PacketSocketFactoryWrapper(
|
||||
webrtc::test::EmulatedTURNServer* turn_server)
|
||||
: turn_server_(turn_server) {}
|
||||
~PacketSocketFactoryWrapper() override {}
|
||||
|
||||
// This method is called from TurnServer when making a TURN ALLOCATION.
|
||||
// It will create a socket on the |peer_| endpoint.
|
||||
rtc::AsyncPacketSocket* CreateUdpSocket(const rtc::SocketAddress& address,
|
||||
uint16_t min_port,
|
||||
uint16_t max_port) override {
|
||||
return turn_server_->CreatePeerSocket();
|
||||
}
|
||||
|
||||
rtc::AsyncPacketSocket* CreateServerTcpSocket(
|
||||
const rtc::SocketAddress& local_address,
|
||||
uint16_t min_port,
|
||||
uint16_t max_port,
|
||||
int opts) override {
|
||||
return nullptr;
|
||||
}
|
||||
rtc::AsyncPacketSocket* CreateClientTcpSocket(
|
||||
const rtc::SocketAddress& local_address,
|
||||
const rtc::SocketAddress& remote_address,
|
||||
const rtc::ProxyInfo& proxy_info,
|
||||
const std::string& user_agent,
|
||||
const rtc::PacketSocketTcpOptions& tcp_options) override {
|
||||
return nullptr;
|
||||
}
|
||||
rtc::AsyncResolverInterface* CreateAsyncResolver() override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
webrtc::test::EmulatedTURNServer* turn_server_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
EmulatedTURNServer::EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread,
|
||||
EmulatedEndpoint* client,
|
||||
EmulatedEndpoint* peer)
|
||||
: thread_(std::move(thread)), client_(client), peer_(peer) {
|
||||
ice_config_.username = "keso";
|
||||
ice_config_.password = "keso";
|
||||
thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
turn_server_ = std::make_unique<cricket::TurnServer>(thread_.get());
|
||||
turn_server_->set_realm(kTestRealm);
|
||||
turn_server_->set_realm(kTestSoftware);
|
||||
turn_server_->set_auth_hook(this);
|
||||
|
||||
auto client_socket = Wrap(client_);
|
||||
turn_server_->AddInternalSocket(client_socket, cricket::PROTO_UDP);
|
||||
turn_server_->SetExternalSocketFactory(new PacketSocketFactoryWrapper(this),
|
||||
rtc::SocketAddress());
|
||||
client_address_ = client_socket->GetLocalAddress();
|
||||
char buf[256];
|
||||
rtc::SimpleStringBuilder str(buf);
|
||||
str.AppendFormat("turn:%s?transport=udp",
|
||||
client_address_.ToString().c_str());
|
||||
ice_config_.url = str.str();
|
||||
});
|
||||
}
|
||||
|
||||
void EmulatedTURNServer::Stop() {
|
||||
thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
sockets_.clear();
|
||||
});
|
||||
}
|
||||
|
||||
EmulatedTURNServer::~EmulatedTURNServer() {
|
||||
thread_->Invoke<void>(RTC_FROM_HERE, [=]() {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
turn_server_.reset(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
rtc::AsyncPacketSocket* EmulatedTURNServer::Wrap(EmulatedEndpoint* endpoint) {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
auto port = endpoint->BindReceiver(0, this).value();
|
||||
auto socket = new AsyncPacketSocketWrapper(this, endpoint, port);
|
||||
sockets_[rtc::SocketAddress(endpoint->GetPeerLocalAddress(), port)] = socket;
|
||||
return socket;
|
||||
}
|
||||
|
||||
void EmulatedTURNServer::OnPacketReceived(webrtc::EmulatedIpPacket packet) {
|
||||
// Copy from EmulatedEndpoint to rtc::AsyncPacketSocket.
|
||||
thread_->PostTask(RTC_FROM_HERE, [this, packet(std::move(packet))]() {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
auto it = sockets_.find(packet.to);
|
||||
if (it != sockets_.end()) {
|
||||
it->second->SignalReadPacket(
|
||||
it->second, reinterpret_cast<const char*>(packet.cdata()),
|
||||
packet.size(), packet.from, packet.arrival_time.ms());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void EmulatedTURNServer::Unbind(rtc::SocketAddress address) {
|
||||
RTC_DCHECK_RUN_ON(thread_.get());
|
||||
if (GetClientEndpoint()->GetPeerLocalAddress() == address.ipaddr()) {
|
||||
GetClientEndpoint()->UnbindReceiver(address.port());
|
||||
} else {
|
||||
GetPeerEndpoint()->UnbindReceiver(address.port());
|
||||
}
|
||||
sockets_.erase(address);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
96
test/network/emulated_turn_server.h
Normal file
96
test/network/emulated_turn_server.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2020 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_EMULATED_TURN_SERVER_H_
|
||||
#define TEST_NETWORK_EMULATED_TURN_SERVER_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "api/test/network_emulation_manager.h"
|
||||
#include "api/transport/stun.h"
|
||||
#include "p2p/base/turn_server.h"
|
||||
#include "rtc_base/async_packet_socket.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
// EmulatedTURNServer wraps cricket::TurnServer to be used inside
|
||||
// a emulated network.
|
||||
//
|
||||
// Packets from EmulatedEndpoint (client or peer) are received in
|
||||
// EmulatedTURNServer::OnPacketReceived which performs a map lookup
|
||||
// and delivers them into cricket::TurnServer using
|
||||
// AsyncPacketSocket::SignalReadPacket
|
||||
//
|
||||
// Packets from cricket::TurnServer to EmulatedEndpoint are sent into
|
||||
// using a wrapper around AsyncPacketSocket (no lookup required as the
|
||||
// wrapper around AsyncPacketSocket keep a pointer to the EmulatedEndpoint).
|
||||
class EmulatedTURNServer : public EmulatedTURNServerInterface,
|
||||
public cricket::TurnAuthInterface,
|
||||
public webrtc::EmulatedNetworkReceiverInterface {
|
||||
public:
|
||||
// Create an EmulatedTURNServer.
|
||||
// |thread| is a thread that will be used to run cricket::TurnServer
|
||||
// that expects all calls to be made from a single thread.
|
||||
EmulatedTURNServer(std::unique_ptr<rtc::Thread> thread,
|
||||
EmulatedEndpoint* client,
|
||||
EmulatedEndpoint* peer);
|
||||
~EmulatedTURNServer() override;
|
||||
|
||||
IceServerConfig GetIceServerConfig() const override { return ice_config_; }
|
||||
|
||||
EmulatedEndpoint* GetClientEndpoint() const override { return client_; }
|
||||
|
||||
rtc::SocketAddress GetClientEndpointAddress() const override {
|
||||
return client_address_;
|
||||
}
|
||||
|
||||
EmulatedEndpoint* GetPeerEndpoint() const override { return peer_; }
|
||||
|
||||
// cricket::TurnAuthInterface
|
||||
bool GetKey(const std::string& username,
|
||||
const std::string& realm,
|
||||
std::string* key) override {
|
||||
return cricket::ComputeStunCredentialHash(username, realm, username, key);
|
||||
}
|
||||
|
||||
rtc::AsyncPacketSocket* CreatePeerSocket() { return Wrap(peer_); }
|
||||
|
||||
// This method is called by network emulation when a packet
|
||||
// comes from an emulated link.
|
||||
void OnPacketReceived(webrtc::EmulatedIpPacket packet) override;
|
||||
|
||||
// This is called when the TURN server deletes a socket.
|
||||
void Unbind(rtc::SocketAddress address);
|
||||
|
||||
// Unbind all sockets.
|
||||
void Stop();
|
||||
|
||||
private:
|
||||
std::unique_ptr<rtc::Thread> thread_;
|
||||
rtc::SocketAddress client_address_;
|
||||
IceServerConfig ice_config_;
|
||||
EmulatedEndpoint* const client_;
|
||||
EmulatedEndpoint* const peer_;
|
||||
std::unique_ptr<cricket::TurnServer> turn_server_ RTC_GUARDED_BY(&thread_);
|
||||
std::map<rtc::SocketAddress, rtc::AsyncPacketSocket*> sockets_
|
||||
RTC_GUARDED_BY(&thread_);
|
||||
|
||||
// Wraps a EmulatedEndpoint in a AsyncPacketSocket to bridge interaction
|
||||
// with TurnServer. cricket::TurnServer gets ownership of the socket.
|
||||
rtc::AsyncPacketSocket* Wrap(EmulatedEndpoint* endpoint);
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // TEST_NETWORK_EMULATED_TURN_SERVER_H_
|
||||
@ -17,6 +17,7 @@
|
||||
#include "api/units/timestamp.h"
|
||||
#include "call/simulated_network.h"
|
||||
#include "rtc_base/fake_network.h"
|
||||
#include "test/network/emulated_turn_server.h"
|
||||
#include "test/time_controller/real_time_controller.h"
|
||||
#include "test/time_controller/simulated_time_controller.h"
|
||||
|
||||
@ -55,7 +56,11 @@ NetworkEmulationManagerImpl::NetworkEmulationManagerImpl(TimeMode mode)
|
||||
// TODO(srte): Ensure that any pending task that must be run for consistency
|
||||
// (such as stats collection tasks) are not cancelled when the task queue is
|
||||
// destroyed.
|
||||
NetworkEmulationManagerImpl::~NetworkEmulationManagerImpl() = default;
|
||||
NetworkEmulationManagerImpl::~NetworkEmulationManagerImpl() {
|
||||
for (auto& turn_server : turn_servers_) {
|
||||
turn_server->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
EmulatedNetworkNode* NetworkEmulationManagerImpl::CreateEmulatedNode(
|
||||
BuiltInNetworkBehaviorConfig config) {
|
||||
@ -332,5 +337,20 @@ Timestamp NetworkEmulationManagerImpl::Now() const {
|
||||
return clock_->CurrentTime();
|
||||
}
|
||||
|
||||
EmulatedTURNServerInterface* NetworkEmulationManagerImpl::CreateTURNServer(
|
||||
EmulatedTURNServerConfig config) {
|
||||
auto* client = CreateEndpoint(config.client_config);
|
||||
auto* peer = CreateEndpoint(config.client_config);
|
||||
char buf[128];
|
||||
rtc::SimpleStringBuilder str(buf);
|
||||
str.AppendFormat("turn_server_%u",
|
||||
static_cast<unsigned>(turn_servers_.size()));
|
||||
auto turn = std::make_unique<EmulatedTURNServer>(
|
||||
time_controller_->CreateThread(str.str()), client, peer);
|
||||
auto out = turn.get();
|
||||
turn_servers_.push_back(std::move(turn));
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "system_wrappers/include/clock.h"
|
||||
#include "test/network/cross_traffic.h"
|
||||
#include "test/network/emulated_network_manager.h"
|
||||
#include "test/network/emulated_turn_server.h"
|
||||
#include "test/network/fake_network_socket_server.h"
|
||||
#include "test/network/network_emulation.h"
|
||||
#include "test/network/traffic_route.h"
|
||||
@ -92,6 +93,9 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
|
||||
|
||||
Timestamp Now() const;
|
||||
|
||||
EmulatedTURNServerInterface* CreateTURNServer(
|
||||
EmulatedTURNServerConfig config) override;
|
||||
|
||||
private:
|
||||
absl::optional<rtc::IPAddress> GetNextIPv4Address();
|
||||
const std::unique_ptr<TimeController> time_controller_;
|
||||
@ -114,6 +118,7 @@ class NetworkEmulationManagerImpl : public NetworkEmulationManager {
|
||||
std::list<std::unique_ptr<TcpMessageRouteImpl>> tcp_message_routes_;
|
||||
std::vector<std::unique_ptr<EndpointsContainer>> endpoints_containers_;
|
||||
std::vector<std::unique_ptr<EmulatedNetworkManager>> network_managers_;
|
||||
std::vector<std::unique_ptr<EmulatedTURNServer>> turn_servers_;
|
||||
|
||||
std::map<EmulatedEndpoint*, EmulatedNetworkManager*>
|
||||
endpoint_to_network_manager_;
|
||||
|
||||
@ -78,7 +78,8 @@ rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
|
||||
rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
|
||||
const rtc::scoped_refptr<PeerConnectionFactoryInterface>& pcf,
|
||||
PeerConnectionObserver* observer,
|
||||
rtc::NetworkManager* network_manager) {
|
||||
rtc::NetworkManager* network_manager,
|
||||
EmulatedTURNServerInterface* turn_server = nullptr) {
|
||||
PeerConnectionDependencies pc_deps(observer);
|
||||
auto port_allocator =
|
||||
std::make_unique<cricket::BasicPortAllocator>(network_manager);
|
||||
@ -90,6 +91,13 @@ rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
|
||||
pc_deps.allocator = std::move(port_allocator);
|
||||
PeerConnectionInterface::RTCConfiguration rtc_configuration;
|
||||
rtc_configuration.sdp_semantics = SdpSemantics::kUnifiedPlan;
|
||||
if (turn_server != nullptr) {
|
||||
webrtc::PeerConnectionInterface::IceServer server;
|
||||
server.username = turn_server->GetIceServerConfig().username;
|
||||
server.password = turn_server->GetIceServerConfig().username;
|
||||
server.urls.push_back(turn_server->GetIceServerConfig().url);
|
||||
rtc_configuration.servers.push_back(server);
|
||||
}
|
||||
|
||||
return pcf->CreatePeerConnection(rtc_configuration, std::move(pc_deps));
|
||||
}
|
||||
@ -185,5 +193,114 @@ TEST(NetworkEmulationManagerPCTest, Run) {
|
||||
});
|
||||
}
|
||||
|
||||
TEST(NetworkEmulationManagerPCTest, RunTURN) {
|
||||
std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
|
||||
signaling_thread->SetName(kSignalThreadName, nullptr);
|
||||
signaling_thread->Start();
|
||||
|
||||
// Setup emulated network
|
||||
NetworkEmulationManagerImpl emulation(TimeMode::kRealTime);
|
||||
|
||||
EmulatedNetworkNode* alice_node = emulation.CreateEmulatedNode(
|
||||
std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
|
||||
EmulatedNetworkNode* bob_node = emulation.CreateEmulatedNode(
|
||||
std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
|
||||
EmulatedNetworkNode* turn_node = emulation.CreateEmulatedNode(
|
||||
std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
|
||||
EmulatedEndpoint* alice_endpoint =
|
||||
emulation.CreateEndpoint(EmulatedEndpointConfig());
|
||||
EmulatedEndpoint* bob_endpoint =
|
||||
emulation.CreateEndpoint(EmulatedEndpointConfig());
|
||||
EmulatedTURNServerInterface* alice_turn =
|
||||
emulation.CreateTURNServer(EmulatedTURNServerConfig());
|
||||
EmulatedTURNServerInterface* bob_turn =
|
||||
emulation.CreateTURNServer(EmulatedTURNServerConfig());
|
||||
|
||||
emulation.CreateRoute(alice_endpoint, {alice_node},
|
||||
alice_turn->GetClientEndpoint());
|
||||
emulation.CreateRoute(alice_turn->GetClientEndpoint(), {alice_node},
|
||||
alice_endpoint);
|
||||
|
||||
emulation.CreateRoute(bob_endpoint, {bob_node},
|
||||
bob_turn->GetClientEndpoint());
|
||||
emulation.CreateRoute(bob_turn->GetClientEndpoint(), {bob_node},
|
||||
bob_endpoint);
|
||||
|
||||
emulation.CreateRoute(alice_turn->GetPeerEndpoint(), {turn_node},
|
||||
bob_turn->GetPeerEndpoint());
|
||||
emulation.CreateRoute(bob_turn->GetPeerEndpoint(), {turn_node},
|
||||
alice_turn->GetPeerEndpoint());
|
||||
|
||||
EmulatedNetworkManagerInterface* alice_network =
|
||||
emulation.CreateEmulatedNetworkManagerInterface({alice_endpoint});
|
||||
EmulatedNetworkManagerInterface* bob_network =
|
||||
emulation.CreateEmulatedNetworkManagerInterface({bob_endpoint});
|
||||
|
||||
// Setup peer connections.
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> alice_pcf;
|
||||
rtc::scoped_refptr<PeerConnectionInterface> alice_pc;
|
||||
std::unique_ptr<MockPeerConnectionObserver> alice_observer =
|
||||
std::make_unique<MockPeerConnectionObserver>();
|
||||
|
||||
rtc::scoped_refptr<PeerConnectionFactoryInterface> bob_pcf;
|
||||
rtc::scoped_refptr<PeerConnectionInterface> bob_pc;
|
||||
std::unique_ptr<MockPeerConnectionObserver> bob_observer =
|
||||
std::make_unique<MockPeerConnectionObserver>();
|
||||
|
||||
signaling_thread->Invoke<void>(RTC_FROM_HERE, [&]() {
|
||||
alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
|
||||
alice_network->network_thread());
|
||||
alice_pc =
|
||||
CreatePeerConnection(alice_pcf, alice_observer.get(),
|
||||
alice_network->network_manager(), alice_turn);
|
||||
|
||||
bob_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
|
||||
bob_network->network_thread());
|
||||
bob_pc = CreatePeerConnection(bob_pcf, bob_observer.get(),
|
||||
bob_network->network_manager(), bob_turn);
|
||||
});
|
||||
|
||||
std::unique_ptr<PeerConnectionWrapper> alice =
|
||||
std::make_unique<PeerConnectionWrapper>(alice_pcf, alice_pc,
|
||||
std::move(alice_observer));
|
||||
std::unique_ptr<PeerConnectionWrapper> bob =
|
||||
std::make_unique<PeerConnectionWrapper>(bob_pcf, bob_pc,
|
||||
std::move(bob_observer));
|
||||
|
||||
signaling_thread->Invoke<void>(RTC_FROM_HERE, [&]() {
|
||||
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
|
||||
alice_pcf->CreateAudioSource(cricket::AudioOptions());
|
||||
rtc::scoped_refptr<AudioTrackInterface> track =
|
||||
alice_pcf->CreateAudioTrack("audio", source);
|
||||
alice->AddTransceiver(track);
|
||||
|
||||
// Connect peers.
|
||||
ASSERT_TRUE(alice->ExchangeOfferAnswerWith(bob.get()));
|
||||
// Do the SDP negotiation, and also exchange ice candidates.
|
||||
ASSERT_TRUE_WAIT(
|
||||
alice->signaling_state() == PeerConnectionInterface::kStable,
|
||||
kDefaultTimeoutMs);
|
||||
ASSERT_TRUE_WAIT(alice->IsIceGatheringDone(), kDefaultTimeoutMs);
|
||||
ASSERT_TRUE_WAIT(bob->IsIceGatheringDone(), kDefaultTimeoutMs);
|
||||
|
||||
// Connect an ICE candidate pairs.
|
||||
ASSERT_TRUE(
|
||||
AddIceCandidates(bob.get(), alice->observer()->GetAllCandidates()));
|
||||
ASSERT_TRUE(
|
||||
AddIceCandidates(alice.get(), bob->observer()->GetAllCandidates()));
|
||||
// This means that ICE and DTLS are connected.
|
||||
ASSERT_TRUE_WAIT(bob->IsIceConnected(), kDefaultTimeoutMs);
|
||||
ASSERT_TRUE_WAIT(alice->IsIceConnected(), kDefaultTimeoutMs);
|
||||
|
||||
// Close peer connections
|
||||
alice->pc()->Close();
|
||||
bob->pc()->Close();
|
||||
|
||||
// Delete peers.
|
||||
alice.reset();
|
||||
bob.reset();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -568,5 +568,42 @@ TEST(NetworkEmulationManagerTest, EndpointLoopback) {
|
||||
network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1));
|
||||
}
|
||||
|
||||
TEST(NetworkEmulationManagerTURNTest, GetIceServerConfig) {
|
||||
NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime);
|
||||
auto turn = network_manager.CreateTURNServer(EmulatedTURNServerConfig());
|
||||
|
||||
EXPECT_GT(turn->GetIceServerConfig().username.size(), 0u);
|
||||
EXPECT_GT(turn->GetIceServerConfig().password.size(), 0u);
|
||||
EXPECT_NE(turn->GetIceServerConfig().url.find(
|
||||
turn->GetClientEndpoint()->GetPeerLocalAddress().ToString()),
|
||||
std::string::npos);
|
||||
}
|
||||
|
||||
TEST(NetworkEmulationManagerTURNTest, ClientTraffic) {
|
||||
NetworkEmulationManagerImpl emulation(TimeMode::kSimulated);
|
||||
auto* ep = emulation.CreateEndpoint(EmulatedEndpointConfig());
|
||||
auto* turn = emulation.CreateTURNServer(EmulatedTURNServerConfig());
|
||||
auto* node = CreateEmulatedNodeWithDefaultBuiltInConfig(&emulation);
|
||||
emulation.CreateRoute(ep, {node}, turn->GetClientEndpoint());
|
||||
emulation.CreateRoute(turn->GetClientEndpoint(), {node}, ep);
|
||||
|
||||
MockReceiver recv;
|
||||
int port = ep->BindReceiver(0, &recv).value();
|
||||
|
||||
// Construct a STUN BINDING.
|
||||
cricket::StunMessage ping;
|
||||
ping.SetType(cricket::STUN_BINDING_REQUEST);
|
||||
rtc::ByteBufferWriter buf;
|
||||
ping.Write(&buf);
|
||||
rtc::CopyOnWriteBuffer packet(buf.Data(), buf.Length());
|
||||
|
||||
// We expect to get a ping reply.
|
||||
EXPECT_CALL(recv, OnPacketReceived(::testing::_)).Times(1);
|
||||
|
||||
ep->SendPacket(rtc::SocketAddress(ep->GetPeerLocalAddress(), port),
|
||||
turn->GetClientEndpointAddress(), packet);
|
||||
emulation.time_controller()->AdvanceTime(TimeDelta::Seconds(1));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user