Source code

Revision control

Copy as Markdown

Other Tools

/*
* Copyright 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 <cstdint>
#include <memory>
#include "api/enable_media_with_defaults.h"
#include "api/peer_connection_interface.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
#include "api/scoped_refptr.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "api/transport/field_trial_based_config.h"
#include "media/engine/webrtc_media_engine.h"
#include "modules/audio_device/include/test_audio_device.h"
#include "p2p/base/basic_packet_socket_factory.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/peer_connection_wrapper.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/gunit.h"
#include "rtc_base/task_queue_for_test.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/network/network_emulation.h"
#include "test/network/network_emulation_manager.h"
#include "test/network/simulated_network.h"
namespace webrtc {
namespace test {
namespace {
constexpr int kDefaultTimeoutMs = 1000;
constexpr int kMaxAptitude = 32000;
constexpr int kSamplingFrequency = 48000;
constexpr char kSignalThreadName[] = "signaling_thread";
bool AddIceCandidates(PeerConnectionWrapper* peer,
std::vector<const IceCandidateInterface*> candidates) {
bool success = true;
for (const auto candidate : candidates) {
if (!peer->pc()->AddIceCandidate(candidate)) {
success = false;
}
}
return success;
}
rtc::scoped_refptr<PeerConnectionFactoryInterface> CreatePeerConnectionFactory(
rtc::Thread* signaling_thread,
rtc::Thread* network_thread) {
PeerConnectionFactoryDependencies pcf_deps;
pcf_deps.task_queue_factory = CreateDefaultTaskQueueFactory();
pcf_deps.event_log_factory = std::make_unique<RtcEventLogFactory>();
pcf_deps.network_thread = network_thread;
pcf_deps.signaling_thread = signaling_thread;
pcf_deps.trials = std::make_unique<FieldTrialBasedConfig>();
pcf_deps.adm = TestAudioDeviceModule::Create(
pcf_deps.task_queue_factory.get(),
TestAudioDeviceModule::CreatePulsedNoiseCapturer(kMaxAptitude,
kSamplingFrequency),
TestAudioDeviceModule::CreateDiscardRenderer(kSamplingFrequency),
/*speed=*/1.f);
EnableMediaWithDefaults(pcf_deps);
return CreateModularPeerConnectionFactory(std::move(pcf_deps));
}
rtc::scoped_refptr<PeerConnectionInterface> CreatePeerConnection(
const rtc::scoped_refptr<PeerConnectionFactoryInterface>& pcf,
PeerConnectionObserver* observer,
rtc::PacketSocketFactory* packet_socket_factory,
rtc::NetworkManager* network_manager,
EmulatedTURNServerInterface* turn_server = nullptr) {
PeerConnectionDependencies pc_deps(observer);
auto port_allocator = std::make_unique<cricket::BasicPortAllocator>(
network_manager, packet_socket_factory);
// This test does not support TCP
int flags = cricket::PORTALLOCATOR_DISABLE_TCP;
port_allocator->set_flags(port_allocator->flags() | flags);
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);
}
auto result =
pcf->CreatePeerConnectionOrError(rtc_configuration, std::move(pc_deps));
if (!result.ok()) {
return nullptr;
}
return result.MoveValue();
}
} // namespace
TEST(NetworkEmulationManagerPCTest, Run) {
std::unique_ptr<rtc::Thread> signaling_thread = rtc::Thread::Create();
signaling_thread->SetName(kSignalThreadName, nullptr);
signaling_thread->Start();
// Setup emulated network
NetworkEmulationManagerImpl emulation({.time_mode = TimeMode::kRealTime});
EmulatedNetworkNode* alice_node = emulation.CreateEmulatedNode(
std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
EmulatedNetworkNode* bob_node = emulation.CreateEmulatedNode(
std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig()));
EmulatedEndpoint* alice_endpoint =
emulation.CreateEndpoint(EmulatedEndpointConfig());
EmulatedEndpoint* bob_endpoint =
emulation.CreateEndpoint(EmulatedEndpointConfig());
emulation.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint);
emulation.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint);
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>();
SendTask(signaling_thread.get(), [&]() {
alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
alice_network->network_thread());
alice_pc = CreatePeerConnection(alice_pcf, alice_observer.get(),
alice_network->packet_socket_factory(),
alice_network->network_manager());
bob_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
bob_network->network_thread());
bob_pc = CreatePeerConnection(bob_pcf, bob_observer.get(),
bob_network->packet_socket_factory(),
bob_network->network_manager());
});
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));
SendTask(signaling_thread.get(), [&]() {
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
alice_pcf->CreateAudioSource(cricket::AudioOptions());
rtc::scoped_refptr<AudioTrackInterface> track =
alice_pcf->CreateAudioTrack("audio", source.get());
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();
});
}
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({.time_mode = 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>();
SendTask(signaling_thread.get(), [&]() {
alice_pcf = CreatePeerConnectionFactory(signaling_thread.get(),
alice_network->network_thread());
alice_pc = CreatePeerConnection(
alice_pcf, alice_observer.get(), alice_network->packet_socket_factory(),
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->packet_socket_factory(),
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));
SendTask(signaling_thread.get(), [&]() {
rtc::scoped_refptr<webrtc::AudioSourceInterface> source =
alice_pcf->CreateAudioSource(cricket::AudioOptions());
rtc::scoped_refptr<AudioTrackInterface> track =
alice_pcf->CreateAudioTrack("audio", source.get());
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