From a1c303535fe7a29b87879047996efa2952f9701b Mon Sep 17 00:00:00 2001 From: Taylor Brandstetter Date: Fri, 13 May 2016 08:15:11 -0700 Subject: [PATCH] Relanding: Implement RTCConfiguration.iceCandidatePoolSize. Depends on this CL in order to work in Chromium: https://codereview.chromium.org/1976673002/ It works by creating pooled PortAllocatorSessions which can be picked up by a P2PTransportChannel when needed (after a local description is set). This can optimize candidate gathering time when there is some time between creating a PeerConnection and setting a local description. R=pthatcher@webrtc.org Committed: https://chromium.googlesource.com/external/webrtc/+/48e9d05f510b1616c81303944008f75825971802 Review URL: https://codereview.webrtc.org/1956453003 . Cr-Commit-Position: refs/heads/master@{#12729} --- webrtc/api/peerconnection.cc | 127 +++-- webrtc/api/peerconnection.h | 14 +- webrtc/api/peerconnection_unittest.cc | 2 +- webrtc/api/peerconnectionfactory.cc | 4 +- webrtc/api/peerconnectionfactory_unittest.cc | 2 +- webrtc/api/peerconnectioninterface.h | 38 +- .../api/peerconnectioninterface_unittest.cc | 102 +++- webrtc/api/test/peerconnectiontestwrapper.cc | 2 +- webrtc/api/webrtcsession.cc | 25 - webrtc/api/webrtcsession.h | 4 - webrtc/api/webrtcsession_unittest.cc | 50 -- webrtc/p2p/base/candidate.h | 13 + .../p2p/{client => base}/fakeportallocator.h | 107 ++-- webrtc/p2p/base/p2ptransportchannel.cc | 46 +- webrtc/p2p/base/p2ptransportchannel.h | 6 +- .../p2p/base/p2ptransportchannel_unittest.cc | 94 +++- webrtc/p2p/base/port.cc | 13 + webrtc/p2p/base/port.h | 26 +- webrtc/p2p/base/port_unittest.cc | 17 + webrtc/p2p/base/portallocator.cc | 76 ++- webrtc/p2p/base/portallocator.h | 114 ++++- webrtc/p2p/base/portallocator_unittest.cc | 205 ++++++++ .../p2p/base/transportcontroller_unittest.cc | 2 +- webrtc/p2p/client/basicportallocator.cc | 150 ++++-- webrtc/p2p/client/basicportallocator.h | 41 +- ...test.cc => basicportallocator_unittest.cc} | 458 +++++++++++------- webrtc/p2p/p2p.gyp | 5 +- 27 files changed, 1223 insertions(+), 520 deletions(-) rename webrtc/p2p/{client => base}/fakeportallocator.h (65%) create mode 100644 webrtc/p2p/base/portallocator_unittest.cc rename webrtc/p2p/client/{portallocator_unittest.cc => basicportallocator_unittest.cc} (79%) diff --git a/webrtc/api/peerconnection.cc b/webrtc/api/peerconnection.cc index 506a21582f..5284db37fd 100644 --- a/webrtc/api/peerconnection.cc +++ b/webrtc/api/peerconnection.cc @@ -376,6 +376,23 @@ void AddSendStreams( } } +uint32_t ConvertIceTransportTypeToCandidateFilter( + PeerConnectionInterface::IceTransportsType type) { + switch (type) { + case PeerConnectionInterface::kNone: + return cricket::CF_NONE; + case PeerConnectionInterface::kRelay: + return cricket::CF_RELAY; + case PeerConnectionInterface::kNoHost: + return (cricket::CF_ALL & ~cricket::CF_HOST); + case PeerConnectionInterface::kAll: + return cricket::CF_ALL; + default: + ASSERT(false); + } + return cricket::CF_NONE; +} + } // namespace namespace webrtc { @@ -536,6 +553,14 @@ PeerConnection::~PeerConnection() { for (const auto& receiver : receivers_) { receiver->Stop(); } + // Destroy stats_ because it depends on session_. + stats_.reset(nullptr); + // Now destroy session_ before destroying other members, + // because its destruction fires signals (such as VoiceChannelDestroyed) + // which will trigger some final actions in PeerConnection... + session_.reset(nullptr); + // port_allocator_ lives on the worker thread and should be destroyed there. + worker_thread()->Invoke([this] { port_allocator_.reset(nullptr); }); } bool PeerConnection::Initialize( @@ -552,35 +577,12 @@ bool PeerConnection::Initialize( port_allocator_ = std::move(allocator); - cricket::ServerAddresses stun_servers; - std::vector turn_servers; - if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { + // The port allocator lives on the worker thread and should be initialized + // there. + if (!worker_thread()->Invoke(rtc::Bind( + &PeerConnection::InitializePortAllocator_w, this, configuration))) { return false; } - port_allocator_->SetIceServers(stun_servers, turn_servers); - - // To handle both internal and externally created port allocator, we will - // enable BUNDLE here. - int portallocator_flags = port_allocator_->flags(); - portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | - cricket::PORTALLOCATOR_ENABLE_IPV6; - // If the disable-IPv6 flag was specified, we'll not override it - // by experiment. - if (configuration.disable_ipv6) { - portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); - } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == - "Disabled") { - portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); - } - - if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { - portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; - LOG(LS_INFO) << "TCP candidates are disabled."; - } - - port_allocator_->set_flags(portallocator_flags); - // No step delay is used while allocating ports. - port_allocator_->set_step_delay(cricket::kMinimumStepDelay); media_controller_.reset( factory_->CreateMediaController(configuration.media_config)); @@ -1158,18 +1160,19 @@ void PeerConnection::SetRemoteDescription( signaling_thread()->Post(this, MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg); } -bool PeerConnection::SetConfiguration(const RTCConfiguration& config) { +bool PeerConnection::SetConfiguration(const RTCConfiguration& configuration) { TRACE_EVENT0("webrtc", "PeerConnection::SetConfiguration"); if (port_allocator_) { - cricket::ServerAddresses stun_servers; - std::vector turn_servers; - if (!ParseIceServers(config.servers, &stun_servers, &turn_servers)) { + if (!worker_thread()->Invoke( + rtc::Bind(&PeerConnection::ReconfigurePortAllocator_w, this, + configuration))) { return false; } - port_allocator_->SetIceServers(stun_servers, turn_servers); } - session_->SetIceConfig(session_->ParseIceConfig(config)); - return session_->SetIceTransports(config.type); + + // TODO(deadbeef): Shouldn't have to hop to the worker thread twice... + session_->SetIceConfig(session_->ParseIceConfig(configuration)); + return true; } bool PeerConnection::AddIceCandidate( @@ -2084,4 +2087,60 @@ DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { return nullptr; } +bool PeerConnection::InitializePortAllocator_w( + const RTCConfiguration& configuration) { + cricket::ServerAddresses stun_servers; + std::vector turn_servers; + if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { + return false; + } + + // To handle both internal and externally created port allocator, we will + // enable BUNDLE here. + int portallocator_flags = port_allocator_->flags(); + portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | + cricket::PORTALLOCATOR_ENABLE_IPV6; + // If the disable-IPv6 flag was specified, we'll not override it + // by experiment. + if (configuration.disable_ipv6) { + portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); + } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == + "Disabled") { + portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); + } + + if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { + portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; + LOG(LS_INFO) << "TCP candidates are disabled."; + } + + port_allocator_->set_flags(portallocator_flags); + // No step delay is used while allocating ports. + port_allocator_->set_step_delay(cricket::kMinimumStepDelay); + port_allocator_->set_candidate_filter( + ConvertIceTransportTypeToCandidateFilter(configuration.type)); + + // Call this last since it may create pooled allocator sessions using the + // properties set above. + port_allocator_->SetConfiguration(stun_servers, turn_servers, + configuration.ice_candidate_pool_size); + return true; +} + +bool PeerConnection::ReconfigurePortAllocator_w( + const RTCConfiguration& configuration) { + cricket::ServerAddresses stun_servers; + std::vector turn_servers; + if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { + return false; + } + port_allocator_->set_candidate_filter( + ConvertIceTransportTypeToCandidateFilter(configuration.type)); + // Call this last since it may create pooled allocator sessions using the + // candidate filter set above. + port_allocator_->SetConfiguration(stun_servers, turn_servers, + configuration.ice_candidate_pool_size); + return true; +} + } // namespace webrtc diff --git a/webrtc/api/peerconnection.h b/webrtc/api/peerconnection.h index 862c6fb630..15ecc3f4cd 100644 --- a/webrtc/api/peerconnection.h +++ b/webrtc/api/peerconnection.h @@ -131,7 +131,7 @@ class PeerConnection : public PeerConnectionInterface, void SetRemoteDescription(SetSessionDescriptionObserver* observer, SessionDescriptionInterface* desc) override; bool SetConfiguration( - const PeerConnectionInterface::RTCConfiguration& config) override; + const PeerConnectionInterface::RTCConfiguration& configuration) override; bool AddIceCandidate(const IceCandidateInterface* candidate) override; bool RemoveIceCandidates( const std::vector& candidates) override; @@ -210,6 +210,8 @@ class PeerConnection : public PeerConnectionInterface, return factory_->signaling_thread(); } + rtc::Thread* worker_thread() const { return factory_->worker_thread(); } + void PostSetSessionDescriptionFailure(SetSessionDescriptionObserver* observer, const std::string& error); void PostCreateSessionDescriptionFailure( @@ -351,6 +353,12 @@ class PeerConnection : public PeerConnectionInterface, // or nullptr if not found. DataChannel* FindDataChannelBySid(int sid) const; + // Called when first configuring the port allocator. + bool InitializePortAllocator_w(const RTCConfiguration& configuration); + // Called when SetConfiguration is called. Only a subset of the configuration + // is applied. + bool ReconfigurePortAllocator_w(const RTCConfiguration& configuration); + // Storing the factory as a scoped reference pointer ensures that the memory // in the PeerConnectionFactoryImpl remains available as long as the // PeerConnection is running. It is passed to PeerConnection as a raw pointer. @@ -397,11 +405,7 @@ class PeerConnection : public PeerConnectionInterface, std::vector> senders_; std::vector> receivers_; - // The session_ unique_ptr is declared at the bottom of PeerConnection - // because its destruction fires signals (such as VoiceChannelDestroyed) - // which will trigger some final actions in PeerConnection... std::unique_ptr session_; - // ... But stats_ depends on session_ so it should be destroyed even earlier. std::unique_ptr stats_; }; diff --git a/webrtc/api/peerconnection_unittest.cc b/webrtc/api/peerconnection_unittest.cc index 521486f98b..1c3d0731da 100644 --- a/webrtc/api/peerconnection_unittest.cc +++ b/webrtc/api/peerconnection_unittest.cc @@ -37,9 +37,9 @@ #include "webrtc/base/thread.h" #include "webrtc/base/virtualsocketserver.h" #include "webrtc/media/engine/fakewebrtcvideoengine.h" +#include "webrtc/p2p/base/fakeportallocator.h" #include "webrtc/p2p/base/p2pconstants.h" #include "webrtc/p2p/base/sessiondescription.h" -#include "webrtc/p2p/client/fakeportallocator.h" #include "webrtc/pc/mediasession.h" #define MAYBE_SKIP_TEST(feature) \ diff --git a/webrtc/api/peerconnectionfactory.cc b/webrtc/api/peerconnectionfactory.cc index 8c8fb6f8c0..5d8f79c40c 100644 --- a/webrtc/api/peerconnectionfactory.cc +++ b/webrtc/api/peerconnectionfactory.cc @@ -283,7 +283,9 @@ PeerConnectionFactory::CreatePeerConnection( allocator.reset(new cricket::BasicPortAllocator( default_network_manager_.get(), default_socket_factory_.get())); } - allocator->SetNetworkIgnoreMask(options_.network_ignore_mask); + worker_thread_->Invoke( + rtc::Bind(&cricket::PortAllocator::SetNetworkIgnoreMask, allocator.get(), + options_.network_ignore_mask)); rtc::scoped_refptr pc( new rtc::RefCountedObject(this)); diff --git a/webrtc/api/peerconnectionfactory_unittest.cc b/webrtc/api/peerconnectionfactory_unittest.cc index 833242a240..963f1fe7be 100644 --- a/webrtc/api/peerconnectionfactory_unittest.cc +++ b/webrtc/api/peerconnectionfactory_unittest.cc @@ -24,7 +24,7 @@ #include "webrtc/media/base/fakevideocapturer.h" #include "webrtc/media/engine/webrtccommon.h" #include "webrtc/media/engine/webrtcvoe.h" -#include "webrtc/p2p/client/fakeportallocator.h" +#include "webrtc/p2p/base/fakeportallocator.h" using webrtc::DataChannelInterface; using webrtc::DtlsIdentityStoreInterface; diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h index 94d2c001e3..fe0dc1df05 100644 --- a/webrtc/api/peerconnectioninterface.h +++ b/webrtc/api/peerconnectioninterface.h @@ -270,42 +270,30 @@ class PeerConnectionInterface : public rtc::RefCountInterface { static const int kAudioJitterBufferMaxPackets = 50; // TODO(pthatcher): Rename this ice_transport_type, but update // Chromium at the same time. - IceTransportsType type; + IceTransportsType type = kAll; // TODO(pthatcher): Rename this ice_servers, but update Chromium // at the same time. IceServers servers; - BundlePolicy bundle_policy; - RtcpMuxPolicy rtcp_mux_policy; - TcpCandidatePolicy tcp_candidate_policy; - int audio_jitter_buffer_max_packets; - bool audio_jitter_buffer_fast_accelerate; - int ice_connection_receiving_timeout; // ms - int ice_backup_candidate_pair_ping_interval; // ms - ContinualGatheringPolicy continual_gathering_policy; + BundlePolicy bundle_policy = kBundlePolicyBalanced; + RtcpMuxPolicy rtcp_mux_policy = kRtcpMuxPolicyNegotiate; + TcpCandidatePolicy tcp_candidate_policy = kTcpCandidatePolicyEnabled; + int audio_jitter_buffer_max_packets = kAudioJitterBufferMaxPackets; + bool audio_jitter_buffer_fast_accelerate = false; + int ice_connection_receiving_timeout = kUndefined; // ms + int ice_backup_candidate_pair_ping_interval = kUndefined; // ms + ContinualGatheringPolicy continual_gathering_policy = GATHER_ONCE; std::vector> certificates; - bool prioritize_most_likely_ice_candidate_pairs; + bool prioritize_most_likely_ice_candidate_pairs = false; struct cricket::MediaConfig media_config; // Flags corresponding to values set by constraint flags. // rtc::Optional flags can be "missing", in which case the webrtc // default applies. - bool disable_ipv6; - bool enable_rtp_data_channel; + bool disable_ipv6 = false; + bool enable_rtp_data_channel = false; rtc::Optional screencast_min_bitrate; rtc::Optional combined_audio_video_bwe; rtc::Optional enable_dtls_srtp; - RTCConfiguration() - : type(kAll), - bundle_policy(kBundlePolicyBalanced), - rtcp_mux_policy(kRtcpMuxPolicyNegotiate), - tcp_candidate_policy(kTcpCandidatePolicyEnabled), - audio_jitter_buffer_max_packets(kAudioJitterBufferMaxPackets), - audio_jitter_buffer_fast_accelerate(false), - ice_connection_receiving_timeout(kUndefined), - ice_backup_candidate_pair_ping_interval(kUndefined), - continual_gathering_policy(GATHER_ONCE), - prioritize_most_likely_ice_candidate_pairs(false), - disable_ipv6(false), - enable_rtp_data_channel(false) {} + int ice_candidate_pool_size = 0; }; struct RTCOfferAnswerOptions { diff --git a/webrtc/api/peerconnectioninterface_unittest.cc b/webrtc/api/peerconnectioninterface_unittest.cc index 795a66d7f6..68c932b5aa 100644 --- a/webrtc/api/peerconnectioninterface_unittest.cc +++ b/webrtc/api/peerconnectioninterface_unittest.cc @@ -39,7 +39,7 @@ #include "webrtc/base/thread.h" #include "webrtc/media/base/fakevideocapturer.h" #include "webrtc/media/sctp/sctpdataengine.h" -#include "webrtc/p2p/client/fakeportallocator.h" +#include "webrtc/p2p/base/fakeportallocator.h" #include "webrtc/pc/mediasession.h" static const char kStreamLabel1[] = "local_stream_1"; @@ -551,24 +551,33 @@ class PeerConnectionInterfaceTest : public testing::Test { } void CreatePeerConnection() { - CreatePeerConnection("", "", NULL); + CreatePeerConnection(PeerConnectionInterface::RTCConfiguration(), nullptr); } void CreatePeerConnection(webrtc::MediaConstraintsInterface* constraints) { - CreatePeerConnection("", "", constraints); + CreatePeerConnection(PeerConnectionInterface::RTCConfiguration(), + constraints); } - void CreatePeerConnection(const std::string& uri, - const std::string& password, - webrtc::MediaConstraintsInterface* constraints) { + void CreatePeerConnectionWithIceTransportsType( + PeerConnectionInterface::IceTransportsType type) { + PeerConnectionInterface::RTCConfiguration config; + config.type = type; + return CreatePeerConnection(config, nullptr); + } + + void CreatePeerConnectionWithIceServer(const std::string& uri, + const std::string& password) { PeerConnectionInterface::RTCConfiguration config; PeerConnectionInterface::IceServer server; - if (!uri.empty()) { - server.uri = uri; - server.password = password; - config.servers.push_back(server); - } + server.uri = uri; + server.password = password; + config.servers.push_back(server); + CreatePeerConnection(config, nullptr); + } + void CreatePeerConnection(PeerConnectionInterface::RTCConfiguration config, + webrtc::MediaConstraintsInterface* constraints) { std::unique_ptr port_allocator( new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr)); port_allocator_ = port_allocator.get(); @@ -613,7 +622,7 @@ class PeerConnectionInterfaceTest : public testing::Test { } void CreatePeerConnectionWithDifferentConfigurations() { - CreatePeerConnection(kStunAddressOnly, "", NULL); + CreatePeerConnectionWithIceServer(kStunAddressOnly, ""); EXPECT_EQ(1u, port_allocator_->stun_servers().size()); EXPECT_EQ(0u, port_allocator_->turn_servers().size()); EXPECT_EQ("address", port_allocator_->stun_servers().begin()->hostname()); @@ -624,7 +633,7 @@ class PeerConnectionInterfaceTest : public testing::Test { CreatePeerConnectionExpectFail(kStunAddressPortAndMore1); CreatePeerConnectionExpectFail(kStunAddressPortAndMore2); - CreatePeerConnection(kTurnIceServerUri, kTurnPassword, NULL); + CreatePeerConnectionWithIceServer(kTurnIceServerUri, kTurnPassword); EXPECT_EQ(0u, port_allocator_->stun_servers().size()); EXPECT_EQ(1u, port_allocator_->turn_servers().size()); EXPECT_EQ(kTurnUsername, @@ -1014,6 +1023,44 @@ TEST_F(PeerConnectionInterfaceTest, CreatePeerConnectionWithDifferentConfigurations(); } +TEST_F(PeerConnectionInterfaceTest, + CreatePeerConnectionWithDifferentIceTransportsTypes) { + CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kNone); + EXPECT_EQ(cricket::CF_NONE, port_allocator_->candidate_filter()); + CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kRelay); + EXPECT_EQ(cricket::CF_RELAY, port_allocator_->candidate_filter()); + CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kNoHost); + EXPECT_EQ(cricket::CF_ALL & ~cricket::CF_HOST, + port_allocator_->candidate_filter()); + CreatePeerConnectionWithIceTransportsType(PeerConnectionInterface::kAll); + EXPECT_EQ(cricket::CF_ALL, port_allocator_->candidate_filter()); +} + +// Test that when a PeerConnection is created with a nonzero candidate pool +// size, the pooled PortAllocatorSession is created with all the attributes +// in the RTCConfiguration. +TEST_F(PeerConnectionInterfaceTest, CreatePeerConnectionWithPooledCandidates) { + PeerConnectionInterface::RTCConfiguration config; + PeerConnectionInterface::IceServer server; + server.uri = kStunAddressOnly; + config.servers.push_back(server); + config.type = PeerConnectionInterface::kRelay; + config.disable_ipv6 = true; + config.tcp_candidate_policy = + PeerConnectionInterface::kTcpCandidatePolicyDisabled; + config.ice_candidate_pool_size = 1; + CreatePeerConnection(config, nullptr); + + const cricket::FakePortAllocatorSession* session = + static_cast( + port_allocator_->GetPooledSession()); + ASSERT_NE(nullptr, session); + EXPECT_EQ(1UL, session->stun_servers().size()); + EXPECT_EQ(0U, session->flags() & cricket::PORTALLOCATOR_ENABLE_IPV6); + EXPECT_LT(0U, session->flags() & cricket::PORTALLOCATOR_DISABLE_TCP); + EXPECT_EQ(cricket::CF_RELAY, session->candidate_filter()); +} + TEST_F(PeerConnectionInterfaceTest, AddStreams) { CreatePeerConnection(); AddVideoStream(kStreamLabel1); @@ -1907,6 +1954,35 @@ TEST_F(PeerConnectionInterfaceTest, SetConfigurationChangesIceServers) { port_allocator_->stun_servers().begin()->hostname()); } +TEST_F(PeerConnectionInterfaceTest, SetConfigurationChangesCandidateFilter) { + CreatePeerConnection(); + PeerConnectionInterface::RTCConfiguration config; + config.type = PeerConnectionInterface::kRelay; + EXPECT_TRUE(pc_->SetConfiguration(config)); + EXPECT_EQ(cricket::CF_RELAY, port_allocator_->candidate_filter()); +} + +// Test that when SetConfiguration changes both the pool size and other +// attributes, the pooled session is created with the updated attributes. +TEST_F(PeerConnectionInterfaceTest, + SetConfigurationCreatesPooledSessionCorrectly) { + CreatePeerConnection(); + PeerConnectionInterface::RTCConfiguration config; + config.ice_candidate_pool_size = 1; + PeerConnectionInterface::IceServer server; + server.uri = kStunAddressOnly; + config.servers.push_back(server); + config.type = PeerConnectionInterface::kRelay; + CreatePeerConnection(config, nullptr); + + const cricket::FakePortAllocatorSession* session = + static_cast( + port_allocator_->GetPooledSession()); + ASSERT_NE(nullptr, session); + EXPECT_EQ(1UL, session->stun_servers().size()); + EXPECT_EQ(cricket::CF_RELAY, session->candidate_filter()); +} + // Test that PeerConnection::Close changes the states to closed and all remote // tracks change state to ended. TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) { diff --git a/webrtc/api/test/peerconnectiontestwrapper.cc b/webrtc/api/test/peerconnectiontestwrapper.cc index 717c48af13..1ec2b4703e 100644 --- a/webrtc/api/test/peerconnectiontestwrapper.cc +++ b/webrtc/api/test/peerconnectiontestwrapper.cc @@ -15,7 +15,7 @@ #include "webrtc/api/test/mockpeerconnectionobservers.h" #include "webrtc/api/test/peerconnectiontestwrapper.h" #include "webrtc/base/gunit.h" -#include "webrtc/p2p/client/fakeportallocator.h" +#include "webrtc/p2p/base/fakeportallocator.h" static const char kStreamLabelBase[] = "stream_label"; static const char kVideoTrackLabelBase[] = "video_track"; diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc index c3ea1c8379..2b146c6b15 100644 --- a/webrtc/api/webrtcsession.cc +++ b/webrtc/api/webrtcsession.cc @@ -421,22 +421,6 @@ static std::string MakeTdErrorString(const std::string& desc) { return MakeErrorString(kPushDownTDFailed, desc); } -uint32_t ConvertIceTransportTypeToCandidateFilter( - PeerConnectionInterface::IceTransportsType type) { - switch (type) { - case PeerConnectionInterface::kNone: - return cricket::CF_NONE; - case PeerConnectionInterface::kRelay: - return cricket::CF_RELAY; - case PeerConnectionInterface::kNoHost: - return (cricket::CF_ALL & ~cricket::CF_HOST); - case PeerConnectionInterface::kAll: - return cricket::CF_ALL; - default: ASSERT(false); - } - return cricket::CF_NONE; -} - // Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd). bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc, const SessionDescriptionInterface* new_desc, @@ -475,7 +459,6 @@ WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, cricket::PortAllocator* port_allocator) : signaling_thread_(signaling_thread), worker_thread_(worker_thread), - port_allocator_(port_allocator), // RFC 3264: The numeric value of the session id and version in the // o line MUST be representable with a "64 bit signed integer". // Due to this constraint session id |sid_| is max limited to LLONG_MAX. @@ -604,8 +587,6 @@ bool WebRtcSession::Initialize( if (options.disable_encryption) { webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED); } - port_allocator()->set_candidate_filter( - ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type)); return true; } @@ -1145,12 +1126,6 @@ bool WebRtcSession::RemoveRemoteIceCandidates( return true; } -bool WebRtcSession::SetIceTransports( - PeerConnectionInterface::IceTransportsType type) { - return port_allocator()->set_candidate_filter( - ConvertIceTransportTypeToCandidateFilter(type)); -} - cricket::IceConfig WebRtcSession::ParseIceConfig( const PeerConnectionInterface::RTCConfiguration& config) const { cricket::IceConfig ice_config; diff --git a/webrtc/api/webrtcsession.h b/webrtc/api/webrtcsession.h index 1408b22644..8a32d78f5e 100644 --- a/webrtc/api/webrtcsession.h +++ b/webrtc/api/webrtcsession.h @@ -146,7 +146,6 @@ class WebRtcSession : public AudioProviderInterface, // These are const to allow them to be called from const methods. rtc::Thread* signaling_thread() const { return signaling_thread_; } rtc::Thread* worker_thread() const { return worker_thread_; } - cricket::PortAllocator* port_allocator() const { return port_allocator_; } // The ID of this session. const std::string& id() const { return sid_; } @@ -214,8 +213,6 @@ class WebRtcSession : public AudioProviderInterface, bool RemoveRemoteIceCandidates( const std::vector& candidates); - bool SetIceTransports(PeerConnectionInterface::IceTransportsType type); - cricket::IceConfig ParseIceConfig( const PeerConnectionInterface::RTCConfiguration& config) const; @@ -469,7 +466,6 @@ class WebRtcSession : public AudioProviderInterface, rtc::Thread* const signaling_thread_; rtc::Thread* const worker_thread_; - cricket::PortAllocator* const port_allocator_; State state_ = STATE_INIT; Error error_ = ERROR_NONE; diff --git a/webrtc/api/webrtcsession_unittest.cc b/webrtc/api/webrtcsession_unittest.cc index 45ffc36c2e..cd5e784594 100644 --- a/webrtc/api/webrtcsession_unittest.cc +++ b/webrtc/api/webrtcsession_unittest.cc @@ -407,12 +407,6 @@ class WebRtcSessionTest void Init() { Init(nullptr); } - void InitWithIceTransport( - PeerConnectionInterface::IceTransportsType ice_transport_type) { - configuration_.type = ice_transport_type; - Init(); - } - void InitWithBundlePolicy( PeerConnectionInterface::BundlePolicy bundle_policy) { configuration_.bundle_policy = bundle_policy; @@ -1529,50 +1523,6 @@ TEST_F(WebRtcSessionTest, MAYBE_TestStunError) { EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); } -// Test session delivers no candidates gathered when constraint set to "none". -TEST_F(WebRtcSessionTest, TestIceTransportsNone) { - AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); - InitWithIceTransport(PeerConnectionInterface::kNone); - SendAudioVideoStream1(); - InitiateCall(); - EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); - EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); - EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); -} - -// Test session delivers only relay candidates gathered when constaint set to -// "relay". -TEST_F(WebRtcSessionTest, TestIceTransportsRelay) { - AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); - ConfigureAllocatorWithTurn(); - InitWithIceTransport(PeerConnectionInterface::kRelay); - SendAudioVideoStream1(); - InitiateCall(); - EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); - EXPECT_EQ(2u, observer_.mline_0_candidates_.size()); - EXPECT_EQ(2u, observer_.mline_1_candidates_.size()); - for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) { - EXPECT_EQ(cricket::RELAY_PORT_TYPE, - observer_.mline_0_candidates_[i].type()); - } - for (size_t i = 0; i < observer_.mline_1_candidates_.size(); ++i) { - EXPECT_EQ(cricket::RELAY_PORT_TYPE, - observer_.mline_1_candidates_[i].type()); - } -} - -// Test session delivers all candidates gathered when constaint set to "all". -TEST_F(WebRtcSessionTest, TestIceTransportsAll) { - AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); - InitWithIceTransport(PeerConnectionInterface::kAll); - SendAudioVideoStream1(); - InitiateCall(); - EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); - // Host + STUN. By default allocator is disabled to gather relay candidates. - EXPECT_EQ(4u, observer_.mline_0_candidates_.size()); - EXPECT_EQ(4u, observer_.mline_1_candidates_.size()); -} - TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) { Init(); SessionDescriptionInterface* offer = NULL; diff --git a/webrtc/p2p/base/candidate.h b/webrtc/p2p/base/candidate.h index ec758d2aa5..b918344740 100644 --- a/webrtc/p2p/base/candidate.h +++ b/webrtc/p2p/base/candidate.h @@ -241,6 +241,19 @@ class Candidate { (256 - component_); } + bool operator==(const Candidate& o) const { + return id_ == o.id_ && component_ == o.component_ && + protocol_ == o.protocol_ && relay_protocol_ == o.relay_protocol_ && + address_ == o.address_ && priority_ == o.priority_ && + username_ == o.username_ && password_ == o.password_ && + type_ == o.type_ && network_name_ == o.network_name_ && + network_type_ == o.network_type_ && generation_ == o.generation_ && + foundation_ == o.foundation_ && + related_address_ == o.related_address_ && tcptype_ == o.tcptype_ && + transport_name_ == o.transport_name_ && network_id_ == o.network_id_; + } + bool operator!=(const Candidate& o) const { return !(*this == o); } + private: std::string ToStringInternal(bool sensitive) const { std::ostringstream ost; diff --git a/webrtc/p2p/client/fakeportallocator.h b/webrtc/p2p/base/fakeportallocator.h similarity index 65% rename from webrtc/p2p/client/fakeportallocator.h rename to webrtc/p2p/base/fakeportallocator.h index 76357a5ffa..b125dfd80e 100644 --- a/webrtc/p2p/client/fakeportallocator.h +++ b/webrtc/p2p/base/fakeportallocator.h @@ -8,11 +8,12 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_ -#define WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_ +#ifndef WEBRTC_P2P_BASE_FAKEPORTALLOCATOR_H_ +#define WEBRTC_P2P_BASE_FAKEPORTALLOCATOR_H_ #include #include +#include #include "webrtc/p2p/base/basicpacketsocketfactory.h" #include "webrtc/p2p/base/portallocator.h" @@ -84,24 +85,31 @@ class TestUDPPort : public UDPPort { class FakePortAllocatorSession : public PortAllocatorSession { public: - FakePortAllocatorSession(rtc::Thread* worker_thread, + FakePortAllocatorSession(PortAllocator* allocator, + rtc::Thread* worker_thread, rtc::PacketSocketFactory* factory, const std::string& content_name, int component, const std::string& ice_ufrag, const std::string& ice_pwd) - : PortAllocatorSession(content_name, component, ice_ufrag, ice_pwd, - cricket::kDefaultPortAllocatorFlags), + : PortAllocatorSession(content_name, + component, + ice_ufrag, + ice_pwd, + allocator->flags()), worker_thread_(worker_thread), factory_(factory), - network_("network", "unittest", - rtc::IPAddress(INADDR_LOOPBACK), 8), - port_(), running_(false), - port_config_count_(0) { + network_("network", "unittest", rtc::IPAddress(INADDR_LOOPBACK), 8), + port_(), + running_(false), + port_config_count_(0), + stun_servers_(allocator->stun_servers()), + turn_servers_(allocator->turn_servers()), + candidate_filter_(allocator->candidate_filter()) { network_.AddIP(rtc::IPAddress(INADDR_LOOPBACK)); } - virtual void StartGettingPorts() { + void StartGettingPorts() override { if (!port_) { port_.reset(TestUDPPort::Create(worker_thread_, factory_, &network_, network_.GetBestIP(), 0, 0, username(), @@ -112,25 +120,56 @@ class FakePortAllocatorSession : public PortAllocatorSession { running_ = true; } - virtual void StopGettingPorts() { running_ = false; } - virtual bool IsGettingPorts() { return running_; } - virtual void ClearGettingPorts() {} + void StopGettingPorts() override { running_ = false; } + bool IsGettingPorts() override { return running_; } + void ClearGettingPorts() override {} + std::vector ReadyPorts() const override { + return ready_ports_; + } + std::vector ReadyCandidates() const override { + return candidates_; + } + bool CandidatesAllocationDone() const override { return allocation_done_; } int port_config_count() { return port_config_count_; } + const ServerAddresses& stun_servers() const { return stun_servers_; } + + const std::vector& turn_servers() const { + return turn_servers_; + } + + uint32_t candidate_filter() const { return candidate_filter_; } + void AddPort(cricket::Port* port) { - port->set_component(component_); + port->set_component(component()); port->set_generation(generation()); - port->SignalPortComplete.connect( - this, &FakePortAllocatorSession::OnPortComplete); + port->SignalPortComplete.connect(this, + &FakePortAllocatorSession::OnPortComplete); port->PrepareAddress(); + ready_ports_.push_back(port); SignalPortReady(this, port); } void OnPortComplete(cricket::Port* port) { - SignalCandidatesReady(this, port->Candidates()); + const std::vector& candidates = port->Candidates(); + candidates_.insert(candidates_.end(), candidates.begin(), candidates.end()); + SignalCandidatesReady(this, candidates); + + allocation_done_ = true; SignalCandidatesAllocationDone(this); } + int transport_info_update_count() const { + return transport_info_update_count_; + } + + protected: + void UpdateIceParametersInternal() override { + // Since this class is a fake and this method only is overridden for tests, + // we don't need to actually update the transport info. + ++transport_info_update_count_; + } + private: rtc::Thread* worker_thread_; rtc::PacketSocketFactory* factory_; @@ -138,6 +177,13 @@ class FakePortAllocatorSession : public PortAllocatorSession { std::unique_ptr port_; bool running_; int port_config_count_; + std::vector candidates_; + std::vector ready_ports_; + bool allocation_done_ = false; + ServerAddresses stun_servers_; + std::vector turn_servers_; + uint32_t candidate_filter_; + int transport_info_update_count_ = 0; }; class FakePortAllocator : public cricket::PortAllocator { @@ -146,44 +192,29 @@ class FakePortAllocator : public cricket::PortAllocator { rtc::PacketSocketFactory* factory) : worker_thread_(worker_thread), factory_(factory) { if (factory_ == NULL) { - owned_factory_.reset(new rtc::BasicPacketSocketFactory( - worker_thread_)); + owned_factory_.reset(new rtc::BasicPacketSocketFactory(worker_thread_)); factory_ = owned_factory_.get(); } } - void SetIceServers( - const ServerAddresses& stun_servers, - const std::vector& turn_servers) override { - stun_servers_ = stun_servers; - turn_servers_ = turn_servers; - } - void SetNetworkIgnoreMask(int network_ignore_mask) override {} - const ServerAddresses& stun_servers() const { return stun_servers_; } - - const std::vector& turn_servers() const { - return turn_servers_; - } - - virtual cricket::PortAllocatorSession* CreateSessionInternal( + cricket::PortAllocatorSession* CreateSessionInternal( const std::string& content_name, int component, const std::string& ice_ufrag, const std::string& ice_pwd) override { - return new FakePortAllocatorSession( - worker_thread_, factory_, content_name, component, ice_ufrag, ice_pwd); + return new FakePortAllocatorSession(this, worker_thread_, factory_, + content_name, component, ice_ufrag, + ice_pwd); } private: rtc::Thread* worker_thread_; rtc::PacketSocketFactory* factory_; std::unique_ptr owned_factory_; - ServerAddresses stun_servers_; - std::vector turn_servers_; }; } // namespace cricket -#endif // WEBRTC_P2P_CLIENT_FAKEPORTALLOCATOR_H_ +#endif // WEBRTC_P2P_BASE_FAKEPORTALLOCATOR_H_ diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc index 206113c4eb..2801c44646 100644 --- a/webrtc/p2p/base/p2ptransportchannel.cc +++ b/webrtc/p2p/base/p2ptransportchannel.cc @@ -261,30 +261,27 @@ P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, P2PTransportChannel::~P2PTransportChannel() { ASSERT(worker_thread_ == rtc::Thread::Current()); - - for (size_t i = 0; i < allocator_sessions_.size(); ++i) - delete allocator_sessions_[i]; } // Add the allocator session to our list so that we know which sessions // are still active. -void P2PTransportChannel::AddAllocatorSession(PortAllocatorSession* session) { +void P2PTransportChannel::AddAllocatorSession( + std::unique_ptr session) { ASSERT(worker_thread_ == rtc::Thread::Current()); session->set_generation(static_cast(allocator_sessions_.size())); - allocator_sessions_.push_back(session); + session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); + session->SignalCandidatesReady.connect( + this, &P2PTransportChannel::OnCandidatesReady); + session->SignalCandidatesAllocationDone.connect( + this, &P2PTransportChannel::OnCandidatesAllocationDone); // We now only want to apply new candidates that we receive to the ports // created by this new session because these are replacing those of the // previous sessions. ports_.clear(); - session->SignalPortReady.connect(this, &P2PTransportChannel::OnPortReady); - session->SignalCandidatesReady.connect( - this, &P2PTransportChannel::OnCandidatesReady); - session->SignalCandidatesAllocationDone.connect( - this, &P2PTransportChannel::OnCandidatesAllocationDone); - session->StartGettingPorts(); + allocator_sessions_.push_back(std::move(session)); } void P2PTransportChannel::AddConnection(Connection* connection) { @@ -472,9 +469,28 @@ void P2PTransportChannel::MaybeStartGathering() { gathering_state_ = kIceGatheringGathering; SignalGatheringState(this); } - // Time for a new allocator - AddAllocatorSession(allocator_->CreateSession( - SessionId(), transport_name(), component(), ice_ufrag_, ice_pwd_)); + // Time for a new allocator. + std::unique_ptr pooled_session = + allocator_->TakePooledSession(transport_name(), component(), ice_ufrag_, + ice_pwd_); + if (pooled_session) { + AddAllocatorSession(std::move(pooled_session)); + PortAllocatorSession* raw_pooled_session = + allocator_sessions_.back().get(); + // Process the pooled session's existing candidates/ports, if they exist. + OnCandidatesReady(raw_pooled_session, + raw_pooled_session->ReadyCandidates()); + for (PortInterface* port : allocator_sessions_.back()->ReadyPorts()) { + OnPortReady(raw_pooled_session, port); + } + if (allocator_sessions_.back()->CandidatesAllocationDone()) { + OnCandidatesAllocationDone(raw_pooled_session); + } + } else { + AddAllocatorSession(allocator_->CreateSession( + SessionId(), transport_name(), component(), ice_ufrag_, ice_pwd_)); + allocator_sessions_.back()->StartGettingPorts(); + } } } @@ -1213,7 +1229,7 @@ void P2PTransportChannel::MaybeStopPortAllocatorSessions() { return; } - for (PortAllocatorSession* session : allocator_sessions_) { + for (const auto& session : allocator_sessions_) { if (!session->IsGettingPorts()) { continue; } diff --git a/webrtc/p2p/base/p2ptransportchannel.h b/webrtc/p2p/base/p2ptransportchannel.h index 2afe03e004..b002c8bb9f 100644 --- a/webrtc/p2p/base/p2ptransportchannel.h +++ b/webrtc/p2p/base/p2ptransportchannel.h @@ -189,7 +189,7 @@ class P2PTransportChannel : public TransportChannelImpl, // Public for unit tests. PortAllocatorSession* allocator_session() { - return allocator_sessions_.back(); + return allocator_sessions_.back().get(); } // Public for unit tests. @@ -227,7 +227,7 @@ class P2PTransportChannel : public TransportChannelImpl, PortInterface* origin_port); bool IsPingable(Connection* conn, int64_t now); void PingConnection(Connection* conn); - void AddAllocatorSession(PortAllocatorSession* session); + void AddAllocatorSession(std::unique_ptr session); void AddConnection(Connection* connection); void OnPortReady(PortAllocatorSession *session, PortInterface* port); @@ -295,7 +295,7 @@ class P2PTransportChannel : public TransportChannelImpl, rtc::Thread* worker_thread_; bool incoming_only_; int error_; - std::vector allocator_sessions_; + std::vector> allocator_sessions_; std::vector ports_; // |connections_| is a sorted list with the first one always be the diff --git a/webrtc/p2p/base/p2ptransportchannel_unittest.cc b/webrtc/p2p/base/p2ptransportchannel_unittest.cc index 21564e6bab..54ab3196cb 100644 --- a/webrtc/p2p/base/p2ptransportchannel_unittest.cc +++ b/webrtc/p2p/base/p2ptransportchannel_unittest.cc @@ -8,14 +8,15 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include #include +#include "webrtc/p2p/base/fakeportallocator.h" #include "webrtc/p2p/base/p2ptransportchannel.h" #include "webrtc/p2p/base/testrelayserver.h" #include "webrtc/p2p/base/teststunserver.h" #include "webrtc/p2p/base/testturnserver.h" #include "webrtc/p2p/client/basicportallocator.h" -#include "webrtc/p2p/client/fakeportallocator.h" #include "webrtc/base/dscp.h" #include "webrtc/base/fakenetwork.h" #include "webrtc/base/firewallsocketserver.h" @@ -287,6 +288,8 @@ class P2PTransportChannelTestBase : public testing::Test, 1, cricket::ICE_CANDIDATE_COMPONENT_DEFAULT, ice_ufrag_ep2_cd1_ch, ice_pwd_ep2_cd1_ch, ice_ufrag_ep1_cd1_ch, ice_pwd_ep1_cd1_ch)); + ep1_.cd1_.ch_->MaybeStartGathering(); + ep2_.cd1_.ch_->MaybeStartGathering(); if (num == 2) { std::string ice_ufrag_ep1_cd2_ch = kIceUfrag[2]; std::string ice_pwd_ep1_cd2_ch = kIcePwd[2]; @@ -300,6 +303,8 @@ class P2PTransportChannelTestBase : public testing::Test, 1, cricket::ICE_CANDIDATE_COMPONENT_DEFAULT, ice_ufrag_ep2_cd2_ch, ice_pwd_ep2_cd2_ch, ice_ufrag_ep1_cd2_ch, ice_pwd_ep1_cd2_ch)); + ep1_.cd2_.ch_->MaybeStartGathering(); + ep2_.cd2_.ch_->MaybeStartGathering(); } } cricket::P2PTransportChannel* CreateChannel( @@ -328,7 +333,6 @@ class P2PTransportChannelTestBase : public testing::Test, channel->SetIceRole(GetEndpoint(endpoint)->ice_role()); channel->SetIceTiebreaker(GetEndpoint(endpoint)->GetIceTiebreaker()); channel->Connect(); - channel->MaybeStartGathering(); return channel; } void DestroyChannels() { @@ -1547,6 +1551,92 @@ TEST_F(P2PTransportChannelTest, TestContinualGathering) { DestroyChannels(); } +// Test that a connection succeeds when the P2PTransportChannel uses a pooled +// PortAllocatorSession that has not yet finished gathering candidates. +TEST_F(P2PTransportChannelTest, TestUsingPooledSessionBeforeDoneGathering) { + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + // First create a pooled session for each endpoint. + auto& allocator_1 = GetEndpoint(0)->allocator_; + auto& allocator_2 = GetEndpoint(1)->allocator_; + int pool_size = 1; + allocator_1->SetConfiguration(allocator_1->stun_servers(), + allocator_1->turn_servers(), pool_size); + allocator_2->SetConfiguration(allocator_2->stun_servers(), + allocator_2->turn_servers(), pool_size); + const cricket::PortAllocatorSession* pooled_session_1 = + allocator_1->GetPooledSession(); + const cricket::PortAllocatorSession* pooled_session_2 = + allocator_2->GetPooledSession(); + ASSERT_NE(nullptr, pooled_session_1); + ASSERT_NE(nullptr, pooled_session_2); + // Sanity check that pooled sessions haven't gathered anything yet. + EXPECT_TRUE(pooled_session_1->ReadyPorts().empty()); + EXPECT_TRUE(pooled_session_1->ReadyCandidates().empty()); + EXPECT_TRUE(pooled_session_2->ReadyPorts().empty()); + EXPECT_TRUE(pooled_session_2->ReadyCandidates().empty()); + // Now let the endpoints connect and try exchanging some data. + CreateChannels(1); + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1() != NULL && ep2_ch1() != NULL && + ep1_ch1()->receiving() && ep1_ch1()->writable() && + ep2_ch1()->receiving() && ep2_ch1()->writable(), + 1000, 1000); + TestSendRecv(1); + // Make sure the P2PTransportChannels are actually using ports from the + // pooled sessions. + auto pooled_ports_1 = pooled_session_1->ReadyPorts(); + auto pooled_ports_2 = pooled_session_2->ReadyPorts(); + EXPECT_NE(pooled_ports_1.end(), + std::find(pooled_ports_1.begin(), pooled_ports_1.end(), + ep1_ch1()->best_connection()->port())); + EXPECT_NE(pooled_ports_2.end(), + std::find(pooled_ports_2.begin(), pooled_ports_2.end(), + ep2_ch1()->best_connection()->port())); +} + +// Test that a connection succeeds when the P2PTransportChannel uses a pooled +// PortAllocatorSession that already finished gathering candidates. +TEST_F(P2PTransportChannelTest, TestUsingPooledSessionAfterDoneGathering) { + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + // First create a pooled session for each endpoint. + auto& allocator_1 = GetEndpoint(0)->allocator_; + auto& allocator_2 = GetEndpoint(1)->allocator_; + int pool_size = 1; + allocator_1->SetConfiguration(allocator_1->stun_servers(), + allocator_1->turn_servers(), pool_size); + allocator_2->SetConfiguration(allocator_2->stun_servers(), + allocator_2->turn_servers(), pool_size); + const cricket::PortAllocatorSession* pooled_session_1 = + allocator_1->GetPooledSession(); + const cricket::PortAllocatorSession* pooled_session_2 = + allocator_2->GetPooledSession(); + ASSERT_NE(nullptr, pooled_session_1); + ASSERT_NE(nullptr, pooled_session_2); + // Wait for the pooled sessions to finish gathering before the + // P2PTransportChannels try to use them. + EXPECT_TRUE_WAIT(pooled_session_1->CandidatesAllocationDone() && + pooled_session_2->CandidatesAllocationDone(), + kDefaultTimeout); + // Now let the endpoints connect and try exchanging some data. + CreateChannels(1); + EXPECT_TRUE_WAIT_MARGIN(ep1_ch1() != NULL && ep2_ch1() != NULL && + ep1_ch1()->receiving() && ep1_ch1()->writable() && + ep2_ch1()->receiving() && ep2_ch1()->writable(), + 1000, 1000); + TestSendRecv(1); + // Make sure the P2PTransportChannels are actually using ports from the + // pooled sessions. + auto pooled_ports_1 = pooled_session_1->ReadyPorts(); + auto pooled_ports_2 = pooled_session_2->ReadyPorts(); + EXPECT_NE(pooled_ports_1.end(), + std::find(pooled_ports_1.begin(), pooled_ports_1.end(), + ep1_ch1()->best_connection()->port())); + EXPECT_NE(pooled_ports_2.end(), + std::find(pooled_ports_2.begin(), pooled_ports_2.end(), + ep2_ch1()->best_connection()->port())); +} + // Test what happens when we have 2 users behind the same NAT. This can lead // to interesting behavior because the STUN server will only give out the // address of the outermost NAT. diff --git a/webrtc/p2p/base/port.cc b/webrtc/p2p/base/port.cc index a353dc2a2f..fbc64f2e0a 100644 --- a/webrtc/p2p/base/port.cc +++ b/webrtc/p2p/base/port.cc @@ -219,6 +219,19 @@ Port::~Port() { delete list[i]; } +void Port::SetIceParameters(int component, + const std::string& username_fragment, + const std::string& password) { + component_ = component; + ice_username_fragment_ = username_fragment; + password_ = password; + for (Candidate& c : candidates_) { + c.set_component(component); + c.set_username(username_fragment); + c.set_password(password); + } +} + Connection* Port::GetConnection(const rtc::SocketAddress& remote_addr) { AddressMap::const_iterator iter = connections_.find(remote_addr); if (iter != connections_.end()) diff --git a/webrtc/p2p/base/port.h b/webrtc/p2p/base/port.h index 7ec33bcd0b..937f3cd028 100644 --- a/webrtc/p2p/base/port.h +++ b/webrtc/p2p/base/port.h @@ -107,6 +107,11 @@ struct ProtocolAddress { : address(a), proto(p), secure(false) { } ProtocolAddress(const rtc::SocketAddress& a, ProtocolType p, bool sec) : address(a), proto(p), secure(sec) { } + + bool operator==(const ProtocolAddress& o) const { + return address == o.address && proto == o.proto && secure == o.secure; + } + bool operator!=(const ProtocolAddress& o) const { return !(*this == o); } }; typedef std::set ServerAddresses; @@ -176,23 +181,16 @@ class Port : public PortInterface, public rtc::MessageHandler, uint32_t generation() { return generation_; } void set_generation(uint32_t generation) { generation_ = generation; } - // ICE requires a single username/password per content/media line. So the - // |ice_username_fragment_| of the ports that belongs to the same content will - // be the same. However this causes a small complication with our relay - // server, which expects different username for RTP and RTCP. - // - // To resolve this problem, we implemented the username_fragment(), - // which returns a different username (calculated from - // |ice_username_fragment_|) for RTCP in the case of ICEPROTO_GOOGLE. And the - // username_fragment() simply returns |ice_username_fragment_| when running - // in ICEPROTO_RFC5245. - // - // As a result the ICEPROTO_GOOGLE will use different usernames for RTP and - // RTCP. And the ICEPROTO_RFC5245 will use same username for both RTP and - // RTCP. const std::string username_fragment() const; const std::string& password() const { return password_; } + // May be called when this port was initially created by a pooled + // PortAllocatorSession, and is now being assigned to an ICE transport. + // Updates the information for candidates as well. + void SetIceParameters(int component, + const std::string& username_fragment, + const std::string& password); + // Fired when candidates are discovered by the port. When all candidates // are discovered that belong to port SignalAddressReady is fired. sigslot::signal2 SignalCandidateReady; diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc index ab48ec9af5..efc2609401 100644 --- a/webrtc/p2p/base/port_unittest.cc +++ b/webrtc/p2p/base/port_unittest.cc @@ -2586,3 +2586,20 @@ TEST_F(PortTest, TestSupportsProtocol) { EXPECT_TRUE(turn_port->SupportsProtocol(UDP_PROTOCOL_NAME)); EXPECT_FALSE(turn_port->SupportsProtocol(TCP_PROTOCOL_NAME)); } + +// Test that SetIceParameters updates the component, ufrag and password +// on both the port itself and its candidates. +TEST_F(PortTest, TestSetIceParameters) { + std::unique_ptr port( + CreateTestPort(kLocalAddr1, "ufrag1", "password1")); + port->PrepareAddress(); + EXPECT_EQ(1UL, port->Candidates().size()); + port->SetIceParameters(1, "ufrag2", "password2"); + EXPECT_EQ(1, port->component()); + EXPECT_EQ("ufrag2", port->username_fragment()); + EXPECT_EQ("password2", port->password()); + const Candidate& candidate = port->Candidates()[0]; + EXPECT_EQ(1, candidate.component()); + EXPECT_EQ("ufrag2", candidate.username()); + EXPECT_EQ("password2", candidate.password()); +} diff --git a/webrtc/p2p/base/portallocator.cc b/webrtc/p2p/base/portallocator.cc index 5c4243abf6..fdf213b311 100644 --- a/webrtc/p2p/base/portallocator.cc +++ b/webrtc/p2p/base/portallocator.cc @@ -18,23 +18,85 @@ PortAllocatorSession::PortAllocatorSession(const std::string& content_name, const std::string& ice_ufrag, const std::string& ice_pwd, uint32_t flags) - : content_name_(content_name), - component_(component), - flags_(flags), + : flags_(flags), generation_(0), + content_name_(content_name), + component_(component), ice_ufrag_(ice_ufrag), ice_pwd_(ice_pwd) { - RTC_DCHECK(!ice_ufrag.empty()); - RTC_DCHECK(!ice_pwd.empty()); + // Pooled sessions are allowed to be created with empty content name, + // component, ufrag and password. + RTC_DCHECK(ice_ufrag.empty() == ice_pwd.empty()); } -PortAllocatorSession* PortAllocator::CreateSession( +void PortAllocator::SetConfiguration( + const ServerAddresses& stun_servers, + const std::vector& turn_servers, + int candidate_pool_size) { + bool ice_servers_changed = + (stun_servers != stun_servers_ || turn_servers != turn_servers_); + stun_servers_ = stun_servers; + turn_servers_ = turn_servers; + + // If ICE servers changed, throw away any existing pooled sessions and create + // new ones. + if (ice_servers_changed) { + pooled_sessions_.clear(); + allocated_pooled_session_count_ = 0; + } + + // If |size| is less than the number of allocated sessions, get rid of the + // extras. + while (allocated_pooled_session_count_ > candidate_pool_size && + !pooled_sessions_.empty()) { + pooled_sessions_.front().reset(nullptr); + pooled_sessions_.pop_front(); + --allocated_pooled_session_count_; + } + // If |size| is greater than the number of allocated sessions, create new + // sessions. + while (allocated_pooled_session_count_ < candidate_pool_size) { + PortAllocatorSession* pooled_session = CreateSessionInternal("", 0, "", ""); + pooled_session->StartGettingPorts(); + pooled_sessions_.push_back( + std::unique_ptr(pooled_session)); + ++allocated_pooled_session_count_; + } + target_pooled_session_count_ = candidate_pool_size; +} + +std::unique_ptr PortAllocator::CreateSession( const std::string& sid, const std::string& content_name, int component, const std::string& ice_ufrag, const std::string& ice_pwd) { - return CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd); + return std::unique_ptr( + CreateSessionInternal(content_name, component, ice_ufrag, ice_pwd)); +} + +std::unique_ptr PortAllocator::TakePooledSession( + const std::string& content_name, + int component, + const std::string& ice_ufrag, + const std::string& ice_pwd) { + RTC_DCHECK(!ice_ufrag.empty()); + RTC_DCHECK(!ice_pwd.empty()); + if (pooled_sessions_.empty()) { + return nullptr; + } + std::unique_ptr ret = + std::move(pooled_sessions_.front()); + ret->SetIceParameters(content_name, component, ice_ufrag, ice_pwd); + pooled_sessions_.pop_front(); + return ret; +} + +const PortAllocatorSession* PortAllocator::GetPooledSession() const { + if (pooled_sessions_.empty()) { + return nullptr; + } + return pooled_sessions_.front().get(); } } // namespace cricket diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h index 6fb79b065e..879657081a 100644 --- a/webrtc/p2p/base/portallocator.h +++ b/webrtc/p2p/base/portallocator.h @@ -11,6 +11,8 @@ #ifndef WEBRTC_P2P_BASE_PORTALLOCATOR_H_ #define WEBRTC_P2P_BASE_PORTALLOCATOR_H_ +#include +#include #include #include @@ -19,6 +21,7 @@ #include "webrtc/base/helpers.h" #include "webrtc/base/proxyinfo.h" #include "webrtc/base/sigslot.h" +#include "webrtc/base/thread.h" namespace cricket { @@ -82,6 +85,11 @@ struct RelayCredentials { RelayCredentials(const std::string& username, const std::string& password) : username(username), password(password) {} + bool operator==(const RelayCredentials& o) const { + return username == o.username && password == o.password; + } + bool operator!=(const RelayCredentials& o) const { return !(*this == o); } + std::string username; std::string password; }; @@ -89,7 +97,7 @@ struct RelayCredentials { typedef std::vector PortList; // TODO(deadbeef): Rename to TurnServerConfig. struct RelayServerConfig { - RelayServerConfig(RelayType type) : type(type), priority(0) {} + RelayServerConfig(RelayType type) : type(type) {} RelayServerConfig(const std::string& address, int port, @@ -102,10 +110,16 @@ struct RelayServerConfig { ProtocolAddress(rtc::SocketAddress(address, port), proto, secure)); } + bool operator==(const RelayServerConfig& o) const { + return type == o.type && ports == o.ports && credentials == o.credentials && + priority == o.priority; + } + bool operator!=(const RelayServerConfig& o) const { return !(*this == o); } + RelayType type; PortList ports; RelayCredentials credentials; - int priority; + int priority = 0; }; class PortAllocatorSession : public sigslot::has_slots<> { @@ -124,6 +138,9 @@ class PortAllocatorSession : public sigslot::has_slots<> { void set_flags(uint32_t flags) { flags_ = flags; } std::string content_name() const { return content_name_; } int component() const { return component_; } + const std::string& ice_ufrag() const { return ice_ufrag_; } + const std::string& ice_pwd() const { return ice_pwd_; } + bool pooled() const { return ice_ufrag_.empty(); } // Starts gathering STUN and Relay configurations. virtual void StartGettingPorts() = 0; @@ -133,6 +150,14 @@ class PortAllocatorSession : public sigslot::has_slots<> { // Whether the process of getting ports has been stopped. virtual bool IsGettingPorts() = 0; + // Another way of getting the information provided by the signals below. + // + // Ports and candidates are not guaranteed to be in the same order as the + // signals were emitted in. + virtual std::vector ReadyPorts() const = 0; + virtual std::vector ReadyCandidates() const = 0; + virtual bool CandidatesAllocationDone() const = 0; + sigslot::signal2 SignalPortReady; sigslot::signal2&> SignalCandidatesReady; @@ -142,25 +167,46 @@ class PortAllocatorSession : public sigslot::has_slots<> { virtual void set_generation(uint32_t generation) { generation_ = generation; } sigslot::signal1 SignalDestroyed; - const std::string& ice_ufrag() const { return ice_ufrag_; } - const std::string& ice_pwd() const { return ice_pwd_; } - protected: + // This method is called when a pooled session (which doesn't have these + // properties initially) is returned by PortAllocator::TakePooledSession, + // and the content name, component, and ICE ufrag/pwd are updated. + // + // A subclass may need to override this method to perform additional actions, + // such as applying the updated information to ports and candidates. + virtual void UpdateIceParametersInternal() {} + // TODO(deadbeef): Get rid of these when everyone switches to ice_ufrag and // ice_pwd. const std::string& username() const { return ice_ufrag_; } const std::string& password() const { return ice_pwd_; } - std::string content_name_; - int component_; - private: + void SetIceParameters(const std::string& content_name, + int component, + const std::string& ice_ufrag, + const std::string& ice_pwd) { + content_name_ = content_name; + component_ = component; + ice_ufrag_ = ice_ufrag; + ice_pwd_ = ice_pwd; + UpdateIceParametersInternal(); + } + uint32_t flags_; uint32_t generation_; + std::string content_name_; + int component_; std::string ice_ufrag_; std::string ice_pwd_; + + // SetIceParameters is an implementation detail which only PortAllocator + // should be able to call. + friend class PortAllocator; }; +// Note that this class should only be used on one thread. +// This includes calling the destructor. class PortAllocator : public sigslot::has_slots<> { public: PortAllocator() : @@ -174,10 +220,25 @@ class PortAllocator : public sigslot::has_slots<> { } virtual ~PortAllocator() {} - // Set STUN and TURN servers to be used in future sessions. - virtual void SetIceServers( - const ServerAddresses& stun_servers, - const std::vector& turn_servers) = 0; + // Set STUN and TURN servers to be used in future sessions, and set + // candidate pool size, as described in JSEP. + // + // If the servers are changing and the candidate pool size is nonzero, + // existing pooled sessions will be destroyed and new ones created. + // + // If the servers are not changing but the candidate pool size is, + // pooled sessions will be either created or destroyed as necessary. + void SetConfiguration(const ServerAddresses& stun_servers, + const std::vector& turn_servers, + int candidate_pool_size); + + const ServerAddresses& stun_servers() const { return stun_servers_; } + + const std::vector& turn_servers() const { + return turn_servers_; + } + + int candidate_pool_size() const { return target_pooled_session_count_; } // Sets the network types to ignore. // Values are defined by the AdapterType enum. @@ -186,13 +247,27 @@ class PortAllocator : public sigslot::has_slots<> { // loopback interfaces. virtual void SetNetworkIgnoreMask(int network_ignore_mask) = 0; - PortAllocatorSession* CreateSession( + std::unique_ptr CreateSession( const std::string& sid, const std::string& content_name, int component, const std::string& ice_ufrag, const std::string& ice_pwd); + // Get an available pooled session and set the transport information on it. + // + // Caller takes ownership of the returned session. + // + // If no pooled sessions are available, returns null. + std::unique_ptr TakePooledSession( + const std::string& content_name, + int component, + const std::string& ice_ufrag, + const std::string& ice_pwd); + + // Returns the next session that would be returned by TakePooledSession. + const PortAllocatorSession* GetPooledSession() const; + uint32_t flags() const { return flags_; } void set_flags(uint32_t flags) { flags_ = flags; } @@ -225,10 +300,9 @@ class PortAllocator : public sigslot::has_slots<> { } uint32_t candidate_filter() { return candidate_filter_; } - bool set_candidate_filter(uint32_t filter) { + void set_candidate_filter(uint32_t filter) { // TODO(mallinath) - Do transition check? candidate_filter_ = filter; - return true; } // Gets/Sets the Origin value used for WebRTC STUN requests. @@ -251,6 +325,16 @@ class PortAllocator : public sigslot::has_slots<> { bool allow_tcp_listen_; uint32_t candidate_filter_; std::string origin_; + + private: + ServerAddresses stun_servers_; + std::vector turn_servers_; + // The last size passed into SetConfiguration. + int target_pooled_session_count_ = 0; + // This variable represents the total number of pooled sessions + // both owned by this class and taken by TakePooledSession. + int allocated_pooled_session_count_ = 0; + std::deque> pooled_sessions_; }; } // namespace cricket diff --git a/webrtc/p2p/base/portallocator_unittest.cc b/webrtc/p2p/base/portallocator_unittest.cc new file mode 100644 index 0000000000..2e16725de4 --- /dev/null +++ b/webrtc/p2p/base/portallocator_unittest.cc @@ -0,0 +1,205 @@ +/* + * Copyright 2016 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 + +#include "webrtc/base/gunit.h" +#include "webrtc/base/thread.h" +#include "webrtc/p2p/base/fakeportallocator.h" +#include "webrtc/p2p/base/portallocator.h" + +static const char kContentName[] = "test content"; +// Based on ICE_UFRAG_LENGTH +static const char kIceUfrag[] = "TESTICEUFRAG0000"; +// Based on ICE_PWD_LENGTH +static const char kIcePwd[] = "TESTICEPWD00000000000000"; +static const char kTurnUsername[] = "test"; +static const char kTurnPassword[] = "test"; + +class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { + public: + PortAllocatorTest() { + allocator_.reset( + new cricket::FakePortAllocator(rtc::Thread::Current(), nullptr)); + } + + protected: + void SetConfigurationWithPoolSize(int candidate_pool_size) { + allocator_->SetConfiguration(cricket::ServerAddresses(), + std::vector(), + candidate_pool_size); + } + + const cricket::FakePortAllocatorSession* GetPooledSession() const { + return static_cast( + allocator_->GetPooledSession()); + } + + std::unique_ptr TakePooledSession() { + return std::unique_ptr( + static_cast( + allocator_->TakePooledSession(kContentName, 0, kIceUfrag, kIcePwd) + .release())); + } + + int GetAllPooledSessionsReturnCount() { + int count = 0; + while (GetPooledSession()) { + TakePooledSession(); + ++count; + } + return count; + } + + std::unique_ptr allocator_; + rtc::SocketAddress stun_server_1{"11.11.11.11", 3478}; + rtc::SocketAddress stun_server_2{"22.22.22.22", 3478}; + cricket::RelayServerConfig turn_server_1{"11.11.11.11", 3478, + kTurnUsername, kTurnPassword, + cricket::PROTO_UDP, false}; + cricket::RelayServerConfig turn_server_2{"22.22.22.22", 3478, + kTurnUsername, kTurnPassword, + cricket::PROTO_UDP, false}; +}; + +TEST_F(PortAllocatorTest, TestDefaults) { + EXPECT_EQ(0UL, allocator_->stun_servers().size()); + EXPECT_EQ(0UL, allocator_->turn_servers().size()); + EXPECT_EQ(0, allocator_->candidate_pool_size()); + EXPECT_EQ(0, GetAllPooledSessionsReturnCount()); +} + +TEST_F(PortAllocatorTest, SetConfigurationUpdatesIceServers) { + cricket::ServerAddresses stun_servers_1 = {stun_server_1}; + std::vector turn_servers_1 = {turn_server_1}; + allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 0); + EXPECT_EQ(stun_servers_1, allocator_->stun_servers()); + EXPECT_EQ(turn_servers_1, allocator_->turn_servers()); + + // Update with a different set of servers. + cricket::ServerAddresses stun_servers_2 = {stun_server_2}; + std::vector turn_servers_2 = {turn_server_2}; + allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 0); + EXPECT_EQ(stun_servers_2, allocator_->stun_servers()); + EXPECT_EQ(turn_servers_2, allocator_->turn_servers()); +} + +TEST_F(PortAllocatorTest, SetConfigurationUpdatesCandidatePoolSize) { + SetConfigurationWithPoolSize(2); + EXPECT_EQ(2, allocator_->candidate_pool_size()); + SetConfigurationWithPoolSize(3); + EXPECT_EQ(3, allocator_->candidate_pool_size()); + SetConfigurationWithPoolSize(1); + EXPECT_EQ(1, allocator_->candidate_pool_size()); + SetConfigurationWithPoolSize(4); + EXPECT_EQ(4, allocator_->candidate_pool_size()); +} + +// A negative pool size should just be treated as zero. +TEST_F(PortAllocatorTest, SetConfigurationWithNegativePoolSizeDoesntCrash) { + SetConfigurationWithPoolSize(-1); + // No asserts; we're just testing that this doesn't crash. +} + +// Test that if the candidate pool size is nonzero, pooled sessions are +// created, and StartGettingPorts is called on them. +TEST_F(PortAllocatorTest, SetConfigurationCreatesPooledSessions) { + SetConfigurationWithPoolSize(2); + auto session_1 = TakePooledSession(); + auto session_2 = TakePooledSession(); + ASSERT_NE(nullptr, session_1.get()); + ASSERT_NE(nullptr, session_2.get()); + EXPECT_EQ(1, session_1->port_config_count()); + EXPECT_EQ(1, session_2->port_config_count()); + EXPECT_EQ(0, GetAllPooledSessionsReturnCount()); +} + +// Test that if the candidate pool size is increased, pooled sessions are +// created as necessary. +TEST_F(PortAllocatorTest, SetConfigurationCreatesMorePooledSessions) { + SetConfigurationWithPoolSize(1); + SetConfigurationWithPoolSize(2); + EXPECT_EQ(2, GetAllPooledSessionsReturnCount()); +} + +// Test that if the candidate pool size is reduced, extra sessions are +// destroyed. +TEST_F(PortAllocatorTest, SetConfigurationDestroysPooledSessions) { + SetConfigurationWithPoolSize(2); + SetConfigurationWithPoolSize(1); + EXPECT_EQ(1, GetAllPooledSessionsReturnCount()); +} + +// Test that if the candidate pool size is reduced and increased, but reducing +// didn't actually destroy any sessions (because they were already given away), +// increasing the size to its initial value doesn't create a new session. +TEST_F(PortAllocatorTest, SetConfigurationDoesntCreateExtraSessions) { + SetConfigurationWithPoolSize(1); + TakePooledSession(); + SetConfigurationWithPoolSize(0); + SetConfigurationWithPoolSize(1); + EXPECT_EQ(0, GetAllPooledSessionsReturnCount()); +} + +// According to JSEP, exising pooled sessions should be destroyed and new +// ones created when the ICE servers change. +TEST_F(PortAllocatorTest, + SetConfigurationRecreatesPooledSessionsWhenIceServersChange) { + cricket::ServerAddresses stun_servers_1 = {stun_server_1}; + std::vector turn_servers_1 = {turn_server_1}; + allocator_->SetConfiguration(stun_servers_1, turn_servers_1, 1); + EXPECT_EQ(stun_servers_1, allocator_->stun_servers()); + EXPECT_EQ(turn_servers_1, allocator_->turn_servers()); + + // Update with a different set of servers (and also change pool size). + cricket::ServerAddresses stun_servers_2 = {stun_server_2}; + std::vector turn_servers_2 = {turn_server_2}; + allocator_->SetConfiguration(stun_servers_2, turn_servers_2, 2); + EXPECT_EQ(stun_servers_2, allocator_->stun_servers()); + EXPECT_EQ(turn_servers_2, allocator_->turn_servers()); + auto session_1 = TakePooledSession(); + auto session_2 = TakePooledSession(); + ASSERT_NE(nullptr, session_1.get()); + ASSERT_NE(nullptr, session_2.get()); + EXPECT_EQ(stun_servers_2, session_1->stun_servers()); + EXPECT_EQ(turn_servers_2, session_1->turn_servers()); + EXPECT_EQ(stun_servers_2, session_2->stun_servers()); + EXPECT_EQ(turn_servers_2, session_2->turn_servers()); + EXPECT_EQ(0, GetAllPooledSessionsReturnCount()); +} + +TEST_F(PortAllocatorTest, GetPooledSessionReturnsNextSession) { + SetConfigurationWithPoolSize(2); + auto peeked_session_1 = GetPooledSession(); + auto session_1 = TakePooledSession(); + EXPECT_EQ(session_1.get(), peeked_session_1); + auto peeked_session_2 = GetPooledSession(); + auto session_2 = TakePooledSession(); + EXPECT_EQ(session_2.get(), peeked_session_2); +} + +// Verify that subclasses of PortAllocatorSession are given a chance to update +// ICE parameters when TakePooledSession is called, and the base class updates +// the info itself. +TEST_F(PortAllocatorTest, TakePooledSessionUpdatesIceParameters) { + SetConfigurationWithPoolSize(1); + auto peeked_session = GetPooledSession(); + ASSERT_NE(nullptr, peeked_session); + EXPECT_EQ(0, peeked_session->transport_info_update_count()); + std::unique_ptr session( + static_cast( + allocator_->TakePooledSession(kContentName, 1, kIceUfrag, kIcePwd) + .release())); + EXPECT_EQ(1, session->transport_info_update_count()); + EXPECT_EQ(kContentName, session->content_name()); + EXPECT_EQ(1, session->component()); + EXPECT_EQ(kIceUfrag, session->ice_ufrag()); + EXPECT_EQ(kIcePwd, session->ice_pwd()); +} diff --git a/webrtc/p2p/base/transportcontroller_unittest.cc b/webrtc/p2p/base/transportcontroller_unittest.cc index 6b64912136..627975c90c 100644 --- a/webrtc/p2p/base/transportcontroller_unittest.cc +++ b/webrtc/p2p/base/transportcontroller_unittest.cc @@ -17,11 +17,11 @@ #include "webrtc/base/sslidentity.h" #include "webrtc/base/thread.h" #include "webrtc/p2p/base/dtlstransportchannel.h" +#include "webrtc/p2p/base/fakeportallocator.h" #include "webrtc/p2p/base/faketransportcontroller.h" #include "webrtc/p2p/base/p2ptransportchannel.h" #include "webrtc/p2p/base/portallocator.h" #include "webrtc/p2p/base/transportcontroller.h" -#include "webrtc/p2p/client/fakeportallocator.h" static const int kTimeout = 100; static const char kIceUfrag1[] = "TESTICEUFRAG0001"; diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc index edfd0219d0..143b036183 100644 --- a/webrtc/p2p/client/basicportallocator.cc +++ b/webrtc/p2p/client/basicportallocator.cc @@ -64,33 +64,26 @@ const uint32_t DISABLE_ALL_PHASES = PORTALLOCATOR_DISABLE_STUN | PORTALLOCATOR_DISABLE_RELAY; // BasicPortAllocator -BasicPortAllocator::BasicPortAllocator( - rtc::NetworkManager* network_manager, - rtc::PacketSocketFactory* socket_factory) - : network_manager_(network_manager), - socket_factory_(socket_factory), - stun_servers_() { +BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory) + : network_manager_(network_manager), socket_factory_(socket_factory) { ASSERT(network_manager_ != nullptr); ASSERT(socket_factory_ != nullptr); Construct(); } BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager) - : network_manager_(network_manager), - socket_factory_(nullptr), - stun_servers_() { + : network_manager_(network_manager), socket_factory_(nullptr) { ASSERT(network_manager_ != nullptr); Construct(); } -BasicPortAllocator::BasicPortAllocator( - rtc::NetworkManager* network_manager, - rtc::PacketSocketFactory* socket_factory, - const ServerAddresses& stun_servers) - : network_manager_(network_manager), - socket_factory_(socket_factory), - stun_servers_(stun_servers) { +BasicPortAllocator::BasicPortAllocator(rtc::NetworkManager* network_manager, + rtc::PacketSocketFactory* socket_factory, + const ServerAddresses& stun_servers) + : network_manager_(network_manager), socket_factory_(socket_factory) { ASSERT(socket_factory_ != NULL); + SetConfiguration(stun_servers, std::vector(), 0); Construct(); } @@ -100,10 +93,8 @@ BasicPortAllocator::BasicPortAllocator( const rtc::SocketAddress& relay_address_udp, const rtc::SocketAddress& relay_address_tcp, const rtc::SocketAddress& relay_address_ssl) - : network_manager_(network_manager), - socket_factory_(NULL), - stun_servers_(stun_servers) { - + : network_manager_(network_manager), socket_factory_(NULL) { + std::vector turn_servers; RelayServerConfig config(RELAY_GTURN); if (!relay_address_udp.IsNil()) { config.ports.push_back(ProtocolAddress(relay_address_udp, PROTO_UDP)); @@ -116,9 +107,10 @@ BasicPortAllocator::BasicPortAllocator( } if (!config.ports.empty()) { - AddTurnServer(config); + turn_servers.push_back(config); } + SetConfiguration(stun_servers, turn_servers, 0); Construct(); } @@ -136,6 +128,11 @@ PortAllocatorSession* BasicPortAllocator::CreateSessionInternal( this, content_name, component, ice_ufrag, ice_pwd); } +void BasicPortAllocator::AddTurnServer(const RelayServerConfig& turn_server) { + std::vector new_turn_servers = turn_servers(); + new_turn_servers.push_back(turn_server); + SetConfiguration(stun_servers(), new_turn_servers, candidate_pool_size()); +} // BasicPortAllocatorSession BasicPortAllocatorSession::BasicPortAllocatorSession( @@ -207,6 +204,61 @@ void BasicPortAllocatorSession::ClearGettingPorts() { sequences_[i]->Stop(); } +std::vector BasicPortAllocatorSession::ReadyPorts() const { + std::vector ret; + for (const PortData& port : ports_) { + if (port.ready() || port.complete()) { + ret.push_back(port.port()); + } + } + return ret; +} + +std::vector BasicPortAllocatorSession::ReadyCandidates() const { + std::vector candidates; + for (const PortData& data : ports_) { + for (const Candidate& candidate : data.port()->Candidates()) { + if (!CheckCandidateFilter(candidate)) { + continue; + } + ProtocolType pvalue; + if (!StringToProto(candidate.protocol().c_str(), &pvalue) || + !data.sequence()->ProtocolEnabled(pvalue)) { + continue; + } + candidates.push_back(candidate); + } + } + return candidates; +} + +bool BasicPortAllocatorSession::CandidatesAllocationDone() const { + // Done only if all required AllocationSequence objects + // are created. + if (!allocation_sequences_created_) { + return false; + } + + // Check that all port allocation sequences are complete (not running). + if (std::any_of(sequences_.begin(), sequences_.end(), + [](const AllocationSequence* sequence) { + return sequence->state() == AllocationSequence::kRunning; + })) { + return false; + } + + // If all allocated ports are in complete state, session must have got all + // expected candidates. Session will trigger candidates allocation complete + // signal. + if (!std::all_of(ports_.begin(), ports_.end(), [](const PortData& port) { + return (port.complete() || port.error()); + })) { + return false; + } + + return true; +} + void BasicPortAllocatorSession::OnMessage(rtc::Message *message) { switch (message->message_id) { case MSG_CONFIG_START: @@ -241,6 +293,13 @@ void BasicPortAllocatorSession::OnMessage(rtc::Message *message) { } } +void BasicPortAllocatorSession::UpdateIceParametersInternal() { + for (PortData& port : ports_) { + port.port()->set_content_name(content_name()); + port.port()->SetIceParameters(component(), ice_ufrag(), ice_pwd()); + } +} + void BasicPortAllocatorSession::GetPortConfigurations() { PortConfiguration* config = new PortConfiguration(allocator_->stun_servers(), username(), @@ -274,7 +333,7 @@ void BasicPortAllocatorSession::OnConfigStop() { bool send_signal = false; for (std::vector::iterator it = ports_.begin(); it != ports_.end(); ++it) { - if (!it->complete()) { + if (!it->complete() && !it->error()) { // Updating port state to error, which didn't finish allocating candidates // yet. it->set_error(); @@ -436,12 +495,12 @@ void BasicPortAllocatorSession::AddAllocatedPort(Port* port, LOG(LS_INFO) << "Adding allocated port for " << content_name(); port->set_content_name(content_name()); - port->set_component(component_); + port->set_component(component()); port->set_generation(generation()); if (allocator_->proxy().type != rtc::PROXY_NONE) port->set_proxy(allocator_->user_agent(), allocator_->proxy()); - port->set_send_retransmit_count_attribute((allocator_->flags() & - PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0); + port->set_send_retransmit_count_attribute( + (flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0); // Push down the candidate_filter to individual port. uint32_t candidate_filter = allocator_->candidate_filter(); @@ -484,8 +543,9 @@ void BasicPortAllocatorSession::OnCandidateReady( ASSERT(data != NULL); // Discarding any candidate signal if port allocation status is // already in completed state. - if (data->complete()) + if (data->complete() || data->error()) { return; + } ProtocolType pvalue; bool candidate_signalable = CheckCandidateFilter(c); @@ -536,8 +596,9 @@ void BasicPortAllocatorSession::OnPortComplete(Port* port) { ASSERT(data != NULL); // Ignore any late signals. - if (data->complete()) + if (data->complete() || data->error()) { return; + } // Moving to COMPLETE state. data->set_complete(); @@ -550,8 +611,9 @@ void BasicPortAllocatorSession::OnPortError(Port* port) { PortData* data = FindPort(port); ASSERT(data != NULL); // We might have already given up on this port and stopped it. - if (data->complete()) + if (data->complete() || data->error()) { return; + } // SignalAddressError is currently sent from StunPort/TurnPort. // But this signal itself is generic. @@ -587,7 +649,7 @@ void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence* seq, } } -bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) { +bool BasicPortAllocatorSession::CheckCandidateFilter(const Candidate& c) const { uint32_t filter = allocator_->candidate_filter(); // When binding to any address, before sending packets out, the getsockname @@ -625,29 +687,15 @@ void BasicPortAllocatorSession::OnPortAllocationComplete( } void BasicPortAllocatorSession::MaybeSignalCandidatesAllocationDone() { - // Send signal only if all required AllocationSequence objects - // are created. - if (!allocation_sequences_created_) - return; - - // Check that all port allocation sequences are complete. - for (std::vector::iterator it = sequences_.begin(); - it != sequences_.end(); ++it) { - if ((*it)->state() == AllocationSequence::kRunning) - return; + if (CandidatesAllocationDone()) { + if (pooled()) { + LOG(LS_INFO) << "All candidates gathered for pooled session."; + } else { + LOG(LS_INFO) << "All candidates gathered for " << content_name() << ":" + << component() << ":" << generation(); + } + SignalCandidatesAllocationDone(this); } - - // If all allocated ports are in complete state, session must have got all - // expected candidates. Session will trigger candidates allocation complete - // signal. - for (std::vector::iterator it = ports_.begin(); - it != ports_.end(); ++it) { - if (!it->complete()) - return; - } - LOG(LS_INFO) << "All candidates gathered for " << content_name_ << ":" - << component_ << ":" << generation(); - SignalCandidatesAllocationDone(this); } void BasicPortAllocatorSession::OnPortDestroyed( diff --git a/webrtc/p2p/client/basicportallocator.h b/webrtc/p2p/client/basicportallocator.h index c66ae596c8..ec1fcb54f8 100644 --- a/webrtc/p2p/client/basicportallocator.h +++ b/webrtc/p2p/client/basicportallocator.h @@ -38,13 +38,6 @@ class BasicPortAllocator : public PortAllocator { const rtc::SocketAddress& relay_server_ssl); virtual ~BasicPortAllocator(); - void SetIceServers( - const ServerAddresses& stun_servers, - const std::vector& turn_servers) override { - stun_servers_ = stun_servers; - turn_servers_ = turn_servers; - } - // Set to kDefaultNetworkIgnoreMask by default. void SetNetworkIgnoreMask(int network_ignore_mask) override { // TODO(phoglund): implement support for other types than loopback. @@ -61,30 +54,20 @@ class BasicPortAllocator : public PortAllocator { // creates its own socket factory. rtc::PacketSocketFactory* socket_factory() { return socket_factory_; } - const ServerAddresses& stun_servers() const { - return stun_servers_; - } - - const std::vector& turn_servers() const { - return turn_servers_; - } - virtual void AddTurnServer(const RelayServerConfig& turn_server) { - turn_servers_.push_back(turn_server); - } - PortAllocatorSession* CreateSessionInternal( const std::string& content_name, int component, const std::string& ice_ufrag, const std::string& ice_pwd) override; + // Convenience method that adds a TURN server to the configuration. + void AddTurnServer(const RelayServerConfig& turn_server); + private: void Construct(); rtc::NetworkManager* network_manager_; rtc::PacketSocketFactory* socket_factory_; - ServerAddresses stun_servers_; - std::vector turn_servers_; bool allow_tcp_listen_; int network_ignore_mask_ = rtc::kDefaultNetworkIgnoreMask; }; @@ -110,8 +93,14 @@ class BasicPortAllocatorSession : public PortAllocatorSession, void StopGettingPorts() override; void ClearGettingPorts() override; bool IsGettingPorts() override { return running_; } + // These will all be cricket::Ports. + std::vector ReadyPorts() const override; + std::vector ReadyCandidates() const override; + bool CandidatesAllocationDone() const override; protected: + void UpdateIceParametersInternal() override; + // Starts the process of getting the port configurations. virtual void GetPortConfigurations(); @@ -130,13 +119,11 @@ class BasicPortAllocatorSession : public PortAllocatorSession, : port_(port), sequence_(seq), state_(STATE_INIT) { } - Port* port() { return port_; } - AllocationSequence* sequence() { return sequence_; } + Port* port() const { return port_; } + AllocationSequence* sequence() const { return sequence_; } bool ready() const { return state_ == STATE_READY; } - bool complete() const { - // Returns true if candidate allocation has completed one way or another. - return ((state_ == STATE_COMPLETE) || (state_ == STATE_ERROR)); - } + bool complete() const { return state_ == STATE_COMPLETE; } + bool error() const { return state_ == STATE_ERROR; } void set_ready() { ASSERT(state_ == STATE_INIT); state_ = STATE_READY; } void set_complete() { @@ -182,7 +169,7 @@ class BasicPortAllocatorSession : public PortAllocatorSession, PortData* FindPort(Port* port); void GetNetworks(std::vector* networks); - bool CheckCandidateFilter(const Candidate& c); + bool CheckCandidateFilter(const Candidate& c) const; BasicPortAllocator* allocator_; rtc::Thread* network_thread_; diff --git a/webrtc/p2p/client/portallocator_unittest.cc b/webrtc/p2p/client/basicportallocator_unittest.cc similarity index 79% rename from webrtc/p2p/client/portallocator_unittest.cc rename to webrtc/p2p/client/basicportallocator_unittest.cc index 2181903377..83d904f181 100644 --- a/webrtc/p2p/client/portallocator_unittest.cc +++ b/webrtc/p2p/client/basicportallocator_unittest.cc @@ -8,6 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include #include #include "webrtc/p2p/base/basicpacketsocketfactory.h" @@ -42,8 +43,8 @@ static const SocketAddress kClientAddr("11.11.11.11", 0); static const SocketAddress kLoopbackAddr("127.0.0.1", 0); static const SocketAddress kPrivateAddr("192.168.1.11", 0); static const SocketAddress kPrivateAddr2("192.168.1.12", 0); -static const SocketAddress kClientIPv6Addr( - "2401:fa00:4:1000:be30:5bff:fee5:c3", 0); +static const SocketAddress kClientIPv6Addr("2401:fa00:4:1000:be30:5bff:fee5:c3", + 0); static const SocketAddress kClientAddr2("22.22.22.22", 0); static const SocketAddress kNatUdpAddr("77.77.77.77", rtc::NAT_SERVER_UDP_PORT); static const SocketAddress kNatTcpAddr("77.77.77.77", rtc::NAT_SERVER_TCP_PORT); @@ -84,20 +85,25 @@ std::ostream& operator<<(std::ostream& os, const cricket::Candidate& c) { } // namespace cricket -class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { +class BasicPortAllocatorTest : public testing::Test, + public sigslot::has_slots<> { public: - PortAllocatorTest() + BasicPortAllocatorTest() : pss_(new rtc::PhysicalSocketServer), vss_(new rtc::VirtualSocketServer(pss_.get())), fss_(new rtc::FirewallSocketServer(vss_.get())), ss_scope_(fss_.get()), nat_factory_(vss_.get(), kNatUdpAddr, kNatTcpAddr), nat_socket_factory_(new rtc::BasicPacketSocketFactory(&nat_factory_)), - stun_server_(cricket::TestStunServer::Create(Thread::Current(), - kStunAddr)), - relay_server_(Thread::Current(), kRelayUdpIntAddr, kRelayUdpExtAddr, - kRelayTcpIntAddr, kRelayTcpExtAddr, - kRelaySslTcpIntAddr, kRelaySslTcpExtAddr), + stun_server_( + cricket::TestStunServer::Create(Thread::Current(), kStunAddr)), + relay_server_(Thread::Current(), + kRelayUdpIntAddr, + kRelayUdpExtAddr, + kRelayTcpIntAddr, + kRelayTcpExtAddr, + kRelaySslTcpIntAddr, + kRelaySslTcpExtAddr), turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr), candidate_allocation_done_(false) { cricket::ServerAddresses stun_servers; @@ -105,9 +111,8 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { // Passing the addresses of GTURN servers will enable GTURN in // Basicportallocator. allocator_.reset(new cricket::BasicPortAllocator( - &network_manager_, - stun_servers, - kRelayUdpIntAddr, kRelayTcpIntAddr, kRelaySslTcpIntAddr)); + &network_manager_, stun_servers, kRelayUdpIntAddr, kRelayTcpIntAddr, + kRelaySslTcpIntAddr)); allocator_->set_step_delay(cricket::kMinimumStepDelay); } @@ -178,55 +183,65 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { } bool CreateSession(int component) { - session_.reset(CreateSession("session", component)); - if (!session_) + session_ = CreateSession("session", component); + if (!session_) { return false; + } return true; } bool CreateSession(int component, const std::string& content_name) { - session_.reset(CreateSession("session", content_name, component)); - if (!session_) + session_ = CreateSession("session", content_name, component); + if (!session_) { return false; + } return true; } - cricket::PortAllocatorSession* CreateSession( - const std::string& sid, int component) { + std::unique_ptr CreateSession( + const std::string& sid, + int component) { return CreateSession(sid, kContentName, component); } - cricket::PortAllocatorSession* CreateSession( - const std::string& sid, const std::string& content_name, int component) { + std::unique_ptr CreateSession( + const std::string& sid, + const std::string& content_name, + int component) { return CreateSession(sid, content_name, component, kIceUfrag0, kIcePwd0); } - cricket::PortAllocatorSession* CreateSession( - const std::string& sid, const std::string& content_name, int component, - const std::string& ice_ufrag, const std::string& ice_pwd) { - cricket::PortAllocatorSession* session = - allocator_->CreateSession( - sid, content_name, component, ice_ufrag, ice_pwd); + std::unique_ptr CreateSession( + const std::string& sid, + const std::string& content_name, + int component, + const std::string& ice_ufrag, + const std::string& ice_pwd) { + std::unique_ptr session = + allocator_->CreateSession(sid, content_name, component, ice_ufrag, + ice_pwd); session->SignalPortReady.connect(this, - &PortAllocatorTest::OnPortReady); - session->SignalCandidatesReady.connect(this, - &PortAllocatorTest::OnCandidatesReady); - session->SignalCandidatesAllocationDone.connect(this, - &PortAllocatorTest::OnCandidatesAllocationDone); + &BasicPortAllocatorTest::OnPortReady); + session->SignalCandidatesReady.connect( + this, &BasicPortAllocatorTest::OnCandidatesReady); + session->SignalCandidatesAllocationDone.connect( + this, &BasicPortAllocatorTest::OnCandidatesAllocationDone); return session; } static bool CheckCandidate(const cricket::Candidate& c, - int component, const std::string& type, + int component, + const std::string& type, const std::string& proto, const SocketAddress& addr) { return (c.component() == component && c.type() == type && - c.protocol() == proto && c.address().ipaddr() == addr.ipaddr() && - ((addr.port() == 0 && (c.address().port() != 0)) || - (c.address().port() == addr.port()))); + c.protocol() == proto && c.address().ipaddr() == addr.ipaddr() && + ((addr.port() == 0 && (c.address().port() != 0)) || + (c.address().port() == addr.port()))); } static bool CheckPort(const rtc::SocketAddress& addr, - int min_port, int max_port) { + int min_port, + int max_port) { return (addr.port() >= min_port && addr.port() <= max_port); } @@ -237,6 +252,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { ASSERT_FALSE(candidate_allocation_done_); candidate_allocation_done_ = true; } + EXPECT_TRUE(session->CandidatesAllocationDone()); } // Check if all ports allocated have send-buffer size |expected|. If @@ -247,11 +263,10 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { int send_buffer_size; if (expected == -1) { EXPECT_EQ(SOCKET_ERROR, - (*it)->GetOption(rtc::Socket::OPT_SNDBUF, - &send_buffer_size)); + (*it)->GetOption(rtc::Socket::OPT_SNDBUF, &send_buffer_size)); } else { - EXPECT_EQ(0, (*it)->GetOption(rtc::Socket::OPT_SNDBUF, - &send_buffer_size)); + EXPECT_EQ(0, + (*it)->GetOption(rtc::Socket::OPT_SNDBUF, &send_buffer_size)); ASSERT_EQ(expected, send_buffer_size); } } @@ -322,14 +337,16 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { } protected: - cricket::BasicPortAllocator& allocator() { - return *allocator_; - } + cricket::BasicPortAllocator& allocator() { return *allocator_; } void OnPortReady(cricket::PortAllocatorSession* ses, cricket::PortInterface* port) { LOG(LS_INFO) << "OnPortReady: " << port->ToString(); ports_.push_back(port); + // Make sure the new port is added to ReadyPorts. + auto ready_ports = ses->ReadyPorts(); + EXPECT_NE(ready_ports.end(), + std::find(ready_ports.begin(), ready_ports.end(), port)); } void OnCandidatesReady(cricket::PortAllocatorSession* ses, const std::vector& candidates) { @@ -337,6 +354,13 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { LOG(LS_INFO) << "OnCandidatesReady: " << candidates[i].ToString(); candidates_.push_back(candidates[i]); } + // Make sure the new candidates are added to Candidates. + auto ses_candidates = ses->ReadyCandidates(); + for (const cricket::Candidate& candidate : candidates) { + EXPECT_NE( + ses_candidates.end(), + std::find(ses_candidates.begin(), ses_candidates.end(), candidate)); + } } bool HasRelayAddress(const cricket::ProtocolAddress& proto_addr) { @@ -344,7 +368,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { cricket::RelayServerConfig server_config = allocator_->turn_servers()[i]; cricket::PortList::const_iterator relay_port; for (relay_port = server_config.ports.begin(); - relay_port != server_config.ports.end(); ++relay_port) { + relay_port != server_config.ports.end(); ++relay_port) { if (proto_addr.address == relay_port->address && proto_addr.proto == relay_port->proto) return true; @@ -391,7 +415,7 @@ class PortAllocatorTest : public testing::Test, public sigslot::has_slots<> { }; // Tests that we can init the port allocator and create a session. -TEST_F(PortAllocatorTest, TestBasic) { +TEST_F(BasicPortAllocatorTest, TestBasic) { EXPECT_EQ(&network_manager_, allocator().network_manager()); EXPECT_EQ(kStunAddr, *allocator().stun_servers().begin()); ASSERT_EQ(1u, allocator().turn_servers().size()); @@ -399,17 +423,18 @@ TEST_F(PortAllocatorTest, TestBasic) { // Empty relay credentials are used for GTURN. EXPECT_TRUE(allocator().turn_servers()[0].credentials.username.empty()); EXPECT_TRUE(allocator().turn_servers()[0].credentials.password.empty()); - EXPECT_TRUE(HasRelayAddress(cricket::ProtocolAddress( - kRelayUdpIntAddr, cricket::PROTO_UDP))); - EXPECT_TRUE(HasRelayAddress(cricket::ProtocolAddress( - kRelayTcpIntAddr, cricket::PROTO_TCP))); - EXPECT_TRUE(HasRelayAddress(cricket::ProtocolAddress( - kRelaySslTcpIntAddr, cricket::PROTO_SSLTCP))); + EXPECT_TRUE(HasRelayAddress( + cricket::ProtocolAddress(kRelayUdpIntAddr, cricket::PROTO_UDP))); + EXPECT_TRUE(HasRelayAddress( + cricket::ProtocolAddress(kRelayTcpIntAddr, cricket::PROTO_TCP))); + EXPECT_TRUE(HasRelayAddress( + cricket::ProtocolAddress(kRelaySslTcpIntAddr, cricket::PROTO_SSLTCP))); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); + EXPECT_FALSE(session_->CandidatesAllocationDone()); } // Tests that our network filtering works properly. -TEST_F(PortAllocatorTest, TestIgnoreOnlyLoopbackNetworkByDefault) { +TEST_F(BasicPortAllocatorTest, TestIgnoreOnlyLoopbackNetworkByDefault) { AddInterface(SocketAddress(IPAddress(0x12345600U), 0), "test_eth0", rtc::ADAPTER_TYPE_ETHERNET); AddInterface(SocketAddress(IPAddress(0x12345601U), 0), "test_wlan0", @@ -432,7 +457,7 @@ TEST_F(PortAllocatorTest, TestIgnoreOnlyLoopbackNetworkByDefault) { } } -TEST_F(PortAllocatorTest, TestIgnoreNetworksAccordingToIgnoreMask) { +TEST_F(BasicPortAllocatorTest, TestIgnoreNetworksAccordingToIgnoreMask) { AddInterface(SocketAddress(IPAddress(0x12345600U), 0), "test_eth0", rtc::ADAPTER_TYPE_ETHERNET); AddInterface(SocketAddress(IPAddress(0x12345601U), 0), "test_wlan0", @@ -453,7 +478,7 @@ TEST_F(PortAllocatorTest, TestIgnoreNetworksAccordingToIgnoreMask) { } // Tests that we allocator session not trying to allocate ports for every 250ms. -TEST_F(PortAllocatorTest, TestNoNetworkInterface) { +TEST_F(BasicPortAllocatorTest, TestNoNetworkInterface) { EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); // Waiting for one second to make sure BasicPortAllocatorSession has not @@ -466,7 +491,7 @@ TEST_F(PortAllocatorTest, TestNoNetworkInterface) { } // Test that we could use loopback interface as host candidate. -TEST_F(PortAllocatorTest, TestLoopbackNetworkInterface) { +TEST_F(BasicPortAllocatorTest, TestLoopbackNetworkInterface) { AddInterface(kLoopbackAddr, "test_loopback", rtc::ADAPTER_TYPE_LOOPBACK); allocator_->SetNetworkIgnoreMask(0); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -479,34 +504,40 @@ TEST_F(PortAllocatorTest, TestLoopbackNetworkInterface) { } // Tests that we can get all the desired addresses successfully. -TEST_F(PortAllocatorTest, TestGetAllPortsWithMinimumStepDelay) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsWithMinimumStepDelay) { AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(4U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[3], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpExtAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpExtAddr); EXPECT_PRED5(CheckCandidate, candidates_[4], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", kRelayTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", + kRelayTcpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[5], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[6], - cricket::ICE_CANDIDATE_COMPONENT_RTP, - "relay", "ssltcp", kRelaySslTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "ssltcp", + kRelaySslTcpIntAddr); EXPECT_TRUE(candidate_allocation_done_); } // Test that when the same network interface is brought down and up, the // port allocator session will restart a new allocation sequence if // it is not stopped. -TEST_F(PortAllocatorTest, TestSameNetworkDownAndUpWhenSessionNotStopped) { +TEST_F(BasicPortAllocatorTest, TestSameNetworkDownAndUpWhenSessionNotStopped) { std::string if_name("test_net0"); AddInterface(kClientAddr, if_name); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -534,7 +565,7 @@ TEST_F(PortAllocatorTest, TestSameNetworkDownAndUpWhenSessionNotStopped) { // Test that when the same network interface is brought down and up, the // port allocator session will not restart a new allocation sequence if // it is stopped. -TEST_F(PortAllocatorTest, TestSameNetworkDownAndUpWhenSessionStopped) { +TEST_F(BasicPortAllocatorTest, TestSameNetworkDownAndUpWhenSessionStopped) { std::string if_name("test_net0"); AddInterface(kClientAddr, if_name); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -559,7 +590,7 @@ TEST_F(PortAllocatorTest, TestSameNetworkDownAndUpWhenSessionStopped) { } // Verify candidates with default step delay of 1sec. -TEST_F(PortAllocatorTest, TestGetAllPortsWithOneSecondStepDelay) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsWithOneSecondStepDelay) { AddInterface(kClientAddr); allocator_->set_step_delay(cricket::kDefaultStepDelay); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -569,29 +600,33 @@ TEST_F(PortAllocatorTest, TestGetAllPortsWithOneSecondStepDelay) { ASSERT_EQ_WAIT(4U, candidates_.size(), 2000); EXPECT_EQ(3U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[3], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpExtAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpExtAddr); ASSERT_EQ_WAIT(6U, candidates_.size(), 1500); EXPECT_PRED5(CheckCandidate, candidates_[4], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", kRelayTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", + kRelayTcpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[5], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); EXPECT_EQ(4U, ports_.size()); ASSERT_EQ_WAIT(7U, candidates_.size(), 2000); EXPECT_PRED5(CheckCandidate, candidates_[6], - cricket::ICE_CANDIDATE_COMPONENT_RTP, - "relay", "ssltcp", kRelaySslTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "ssltcp", + kRelaySslTcpIntAddr); EXPECT_EQ(4U, ports_.size()); EXPECT_TRUE(candidate_allocation_done_); // If we Stop gathering now, we shouldn't get a second "done" callback. session_->StopGettingPorts(); } -TEST_F(PortAllocatorTest, TestSetupVideoRtpPortsWithNormalSendBuffers) { +TEST_F(BasicPortAllocatorTest, TestSetupVideoRtpPortsWithNormalSendBuffers) { AddInterface(kClientAddr); - EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP, - cricket::CN_VIDEO)); + EXPECT_TRUE( + CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP, cricket::CN_VIDEO)); session_->StartGettingPorts(); ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_TRUE(candidate_allocation_done_); @@ -603,7 +638,7 @@ TEST_F(PortAllocatorTest, TestSetupVideoRtpPortsWithNormalSendBuffers) { } // Tests that we can get callback after StopGetAllPorts. -TEST_F(PortAllocatorTest, TestStopGetAllPorts) { +TEST_F(BasicPortAllocatorTest, TestStopGetAllPorts) { AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); @@ -616,7 +651,7 @@ TEST_F(PortAllocatorTest, TestStopGetAllPorts) { // Test that we restrict client ports appropriately when a port range is set. // We check the candidates for udp/stun/tcp ports, and the from address // for relay ports. -TEST_F(PortAllocatorTest, TestGetAllPortsPortRange) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsPortRange) { AddInterface(kClientAddr); // Check that an invalid port range fails. EXPECT_FALSE(SetPortRange(kMaxPort, kMinPort)); @@ -633,15 +668,15 @@ TEST_F(PortAllocatorTest, TestGetAllPortsPortRange) { // Check the port number for the STUN port object. EXPECT_PRED3(CheckPort, candidates_[1].address(), kMinPort, kMaxPort); // Check the port number used to connect to the relay server. - EXPECT_PRED3(CheckPort, relay_server_.GetConnection(0).source(), - kMinPort, kMaxPort); + EXPECT_PRED3(CheckPort, relay_server_.GetConnection(0).source(), kMinPort, + kMaxPort); // Check the port number for the TCP port object. EXPECT_PRED3(CheckPort, candidates_[5].address(), kMinPort, kMaxPort); EXPECT_TRUE(candidate_allocation_done_); } // Test that we don't crash or malfunction if we have no network adapters. -TEST_F(PortAllocatorTest, TestGetAllPortsNoAdapters) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoAdapters) { EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); rtc::Thread::Current()->ProcessMessages(100); @@ -652,7 +687,7 @@ TEST_F(PortAllocatorTest, TestGetAllPortsNoAdapters) { // Test that when enumeration is disabled, we should not have any ports when // candidate_filter() is set to CF_RELAY and no relay is specified. -TEST_F(PortAllocatorTest, +TEST_F(BasicPortAllocatorTest, TestDisableAdapterEnumerationWithoutNatRelayTransportOnly) { ResetWithStunServerNoNat(kStunAddr); allocator().set_candidate_filter(cricket::CF_RELAY); @@ -664,7 +699,7 @@ TEST_F(PortAllocatorTest, // Test that even with multiple interfaces, the result should still be a single // default private, one STUN and one TURN candidate since we bind to any address // (i.e. all 0s). -TEST_F(PortAllocatorTest, +TEST_F(BasicPortAllocatorTest, TestDisableAdapterEnumerationBehindNatMultipleInterfaces) { AddInterface(kPrivateAddr); AddInterface(kPrivateAddr2); @@ -687,7 +722,7 @@ TEST_F(PortAllocatorTest, // Test that we should get a default private, STUN, TURN/UDP and TURN/TCP // candidates when both TURN/UDP and TURN/TCP servers are specified. -TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationBehindNatWithTcp) { +TEST_F(BasicPortAllocatorTest, TestDisableAdapterEnumerationBehindNatWithTcp) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); AddInterface(kPrivateAddr); ResetWithStunServerAndNat(kStunAddr); @@ -701,7 +736,8 @@ TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationBehindNatWithTcp) { // Test that when adapter enumeration is disabled, for endpoints without // STUN/TURN specified, a default private candidate is still generated. -TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) { +TEST_F(BasicPortAllocatorTest, + TestDisableAdapterEnumerationWithoutNatOrServers) { ResetWithNoServersOrNat(); // Expect to see 2 ports: STUN and TCP ports, one default private candidate. CheckDisableAdapterEnumeration(2U, kPrivateAddr.ipaddr(), rtc::IPAddress(), @@ -711,7 +747,7 @@ TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) { // Test that when adapter enumeration is disabled, with // PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind // a NAT, there is no local candidate. -TEST_F(PortAllocatorTest, +TEST_F(BasicPortAllocatorTest, TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabled) { ResetWithStunServerNoNat(kStunAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -728,7 +764,7 @@ TEST_F(PortAllocatorTest, // (kClientAddr) which was discovered when sending STUN requests, will become // the srflx addresses. TEST_F( - PortAllocatorTest, + BasicPortAllocatorTest, TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabledWithDifferentDefaultRoute) { ResetWithStunServerNoNat(kStunAddr); AddInterfaceAsDefaultRoute(kClientAddr); @@ -743,7 +779,7 @@ TEST_F( // Test that when adapter enumeration is disabled, with // PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints behind a // NAT, there is only one STUN candidate. -TEST_F(PortAllocatorTest, +TEST_F(BasicPortAllocatorTest, TestDisableAdapterEnumerationWithNatLocalhostCandidateDisabled) { ResetWithStunServerAndNat(kStunAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -755,7 +791,7 @@ TEST_F(PortAllocatorTest, // Test that we disable relay over UDP, and only TCP is used when connecting to // the relay server. -TEST_F(PortAllocatorTest, TestDisableUdpTurn) { +TEST_F(BasicPortAllocatorTest, TestDisableUdpTurn) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); AddInterface(kClientAddr); ResetWithStunServerAndNat(kStunAddr); @@ -789,7 +825,7 @@ TEST_F(PortAllocatorTest, TestDisableUdpTurn) { // Test that we can get OnCandidatesAllocationDone callback when all the ports // are disabled. -TEST_F(PortAllocatorTest, TestDisableAllPorts) { +TEST_F(BasicPortAllocatorTest, TestDisableAllPorts) { AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->set_flags(cricket::PORTALLOCATOR_DISABLE_UDP | @@ -803,7 +839,7 @@ TEST_F(PortAllocatorTest, TestDisableAllPorts) { } // Test that we don't crash or malfunction if we can't create UDP sockets. -TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSockets) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoUdpSockets) { AddInterface(kClientAddr); fss_->set_udp_sockets_enabled(false); EXPECT_TRUE(CreateSession(1)); @@ -811,25 +847,29 @@ TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSockets) { ASSERT_EQ_WAIT(5U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(2U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpExtAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpExtAddr); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", kRelayTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", + kRelayTcpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[3], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[4], - cricket::ICE_CANDIDATE_COMPONENT_RTP, - "relay", "ssltcp", kRelaySslTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "ssltcp", + kRelaySslTcpIntAddr); EXPECT_TRUE(candidate_allocation_done_); } -#endif // if !defined(ADDRESS_SANITIZER) +#endif // if !defined(ADDRESS_SANITIZER) // Test that we don't crash or malfunction if we can't create UDP sockets or // listen on TCP sockets. We still give out a local TCP address, since // apparently this is needed for the remote side to accept our connection. -TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSocketsNoTcpListen) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoUdpSocketsNoTcpListen) { AddInterface(kClientAddr); fss_->set_udp_sockets_enabled(false); fss_->set_tcp_listen_enabled(false); @@ -837,35 +877,34 @@ TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpSocketsNoTcpListen) { session_->StartGettingPorts(); ASSERT_EQ_WAIT(5U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(2U, ports_.size()); - EXPECT_PRED5(CheckCandidate, candidates_[0], - 1, "relay", "udp", kRelayUdpIntAddr); - EXPECT_PRED5(CheckCandidate, candidates_[1], - 1, "relay", "udp", kRelayUdpExtAddr); - EXPECT_PRED5(CheckCandidate, candidates_[2], - 1, "relay", "tcp", kRelayTcpIntAddr); - EXPECT_PRED5(CheckCandidate, candidates_[3], - 1, "local", "tcp", kClientAddr); - EXPECT_PRED5(CheckCandidate, candidates_[4], - 1, "relay", "ssltcp", kRelaySslTcpIntAddr); + EXPECT_PRED5(CheckCandidate, candidates_[0], 1, "relay", "udp", + kRelayUdpIntAddr); + EXPECT_PRED5(CheckCandidate, candidates_[1], 1, "relay", "udp", + kRelayUdpExtAddr); + EXPECT_PRED5(CheckCandidate, candidates_[2], 1, "relay", "tcp", + kRelayTcpIntAddr); + EXPECT_PRED5(CheckCandidate, candidates_[3], 1, "local", "tcp", kClientAddr); + EXPECT_PRED5(CheckCandidate, candidates_[4], 1, "relay", "ssltcp", + kRelaySslTcpIntAddr); EXPECT_TRUE(candidate_allocation_done_); } // Test that we don't crash or malfunction if we can't create any sockets. -// TODO: Find a way to exit early here. -TEST_F(PortAllocatorTest, TestGetAllPortsNoSockets) { +// TODO(deadbeef): Find a way to exit early here. +TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoSockets) { AddInterface(kClientAddr); fss_->set_tcp_sockets_enabled(false); fss_->set_udp_sockets_enabled(false); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); WAIT(candidates_.size() > 0, 2000); - // TODO - Check candidate_allocation_done signal. + // TODO(deadbeef): Check candidate_allocation_done signal. // In case of Relay, ports creation will succeed but sockets will fail. // There is no error reporting from RelayEntry to handle this failure. } // Testing STUN timeout. -TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpAllowed) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsNoUdpAllowed) { fss_->AddRule(false, rtc::FP_UDP, rtc::FD_ANY, kClientAddr); AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -873,27 +912,32 @@ TEST_F(PortAllocatorTest, TestGetAllPortsNoUdpAllowed) { EXPECT_EQ_WAIT(2U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(2U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); // RelayPort connection timeout is 3sec. TCP connection with RelayServer // will be tried after 3 seconds. EXPECT_EQ_WAIT(6U, candidates_.size(), 4000); EXPECT_EQ(3U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[3], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", kRelayTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "tcp", + kRelayTcpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[4], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "ssltcp", - kRelaySslTcpIntAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "ssltcp", + kRelaySslTcpIntAddr); EXPECT_PRED5(CheckCandidate, candidates_[5], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", kRelayUdpExtAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + kRelayUdpExtAddr); // Stun Timeout is 9sec. EXPECT_TRUE_WAIT(candidate_allocation_done_, 9000); } -TEST_F(PortAllocatorTest, TestCandidatePriorityOfMultipleInterfaces) { +TEST_F(BasicPortAllocatorTest, TestCandidatePriorityOfMultipleInterfaces) { AddInterface(kClientAddr); AddInterface(kClientAddr2); // Allocating only host UDP ports. This is done purely for testing @@ -911,14 +955,14 @@ TEST_F(PortAllocatorTest, TestCandidatePriorityOfMultipleInterfaces) { } // Test to verify ICE restart process. -TEST_F(PortAllocatorTest, TestGetAllPortsRestarts) { +TEST_F(BasicPortAllocatorTest, TestGetAllPortsRestarts) { AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); EXPECT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(4U, ports_.size()); EXPECT_TRUE(candidate_allocation_done_); - // TODO - Extend this to verify ICE restart. + // TODO(deadbeef): Extend this to verify ICE restart. } // Test ICE candidate filter mechanism with options Relay/Host/Reflexive. @@ -926,7 +970,7 @@ TEST_F(PortAllocatorTest, TestGetAllPortsRestarts) { // relay (i.e. IceTransportsType is relay), the raddr is an empty // address with the correct family. This is to prevent any local // reflective address leakage in the sdp line. -TEST_F(PortAllocatorTest, TestCandidateFilterWithRelayOnly) { +TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithRelayOnly) { AddInterface(kClientAddr); // GTURN is not configured here. ResetWithTurnServersNoNat(kTurnUdpIntAddr, rtc::SocketAddress()); @@ -934,11 +978,8 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithRelayOnly) { EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); - EXPECT_PRED5(CheckCandidate, - candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, - "relay", - "udp", + EXPECT_PRED5(CheckCandidate, candidates_[0], + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); EXPECT_EQ(1U, candidates_.size()); @@ -951,22 +992,22 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithRelayOnly) { } } -TEST_F(PortAllocatorTest, TestCandidateFilterWithHostOnly) { +TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithHostOnly) { AddInterface(kClientAddr); allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET); allocator().set_candidate_filter(cricket::CF_HOST); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); - EXPECT_EQ(2U, candidates_.size()); // Host UDP/TCP candidates only. - EXPECT_EQ(2U, ports_.size()); // UDP/TCP ports only. + EXPECT_EQ(2U, candidates_.size()); // Host UDP/TCP candidates only. + EXPECT_EQ(2U, ports_.size()); // UDP/TCP ports only. for (size_t i = 0; i < candidates_.size(); ++i) { EXPECT_EQ(std::string(cricket::LOCAL_PORT_TYPE), candidates_[i].type()); } } // Host is behind the NAT. -TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnly) { +TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithReflexiveOnly) { AddInterface(kPrivateAddr); ResetWithStunServerAndNat(kStunAddr); @@ -977,8 +1018,8 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnly) { EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); // Host is behind NAT, no private address will be exposed. Hence only UDP // port with STUN candidate will be sent outside. - EXPECT_EQ(1U, candidates_.size()); // Only STUN candidate. - EXPECT_EQ(1U, ports_.size()); // Only UDP port will be in ready state. + EXPECT_EQ(1U, candidates_.size()); // Only STUN candidate. + EXPECT_EQ(1U, ports_.size()); // Only UDP port will be in ready state. for (size_t i = 0; i < candidates_.size(); ++i) { EXPECT_EQ(std::string(cricket::STUN_PORT_TYPE), candidates_[i].type()); EXPECT_EQ( @@ -988,7 +1029,7 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnly) { } // Host is not behind the NAT. -TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) { +TEST_F(BasicPortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) { AddInterface(kClientAddr); allocator().set_flags(cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET); allocator().set_candidate_filter(cricket::CF_REFLEXIVE); @@ -996,7 +1037,7 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) { session_->StartGettingPorts(); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); // Host has a public address, both UDP and TCP candidates will be exposed. - EXPECT_EQ(2U, candidates_.size()); // Local UDP + TCP candidate. + EXPECT_EQ(2U, candidates_.size()); // Local UDP + TCP candidate. EXPECT_EQ(2U, ports_.size()); // UDP and TCP ports will be in ready state. for (size_t i = 0; i < candidates_.size(); ++i) { EXPECT_EQ(std::string(cricket::LOCAL_PORT_TYPE), candidates_[i].type()); @@ -1004,17 +1045,20 @@ TEST_F(PortAllocatorTest, TestCandidateFilterWithReflexiveOnlyAndNoNAT) { } // Test that we get the same ufrag and pwd for all candidates. -TEST_F(PortAllocatorTest, TestEnableSharedUfrag) { +TEST_F(BasicPortAllocatorTest, TestEnableSharedUfrag) { AddInterface(kClientAddr); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); session_->StartGettingPorts(); ASSERT_EQ_WAIT(7U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[5], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); EXPECT_EQ(4U, ports_.size()); EXPECT_EQ(kIceUfrag0, candidates_[0].username()); EXPECT_EQ(kIceUfrag0, candidates_[1].username()); @@ -1028,7 +1072,7 @@ TEST_F(PortAllocatorTest, TestEnableSharedUfrag) { // is allocated for udp and stun. Also verify there is only one candidate // (local) if stun candidate is same as local candidate, which will be the case // in a public network like the below test. -TEST_F(PortAllocatorTest, TestSharedSocketWithoutNat) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithoutNat) { AddInterface(kClientAddr); allocator_->set_flags(allocator().flags() | cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET); @@ -1037,14 +1081,15 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithoutNat) { ASSERT_EQ_WAIT(6U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_EQ(3U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); } // Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled only one port // is allocated for udp and stun. In this test we should expect both stun and // local candidates as client behind a nat. -TEST_F(PortAllocatorTest, TestSharedSocketWithNat) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithNat) { AddInterface(kClientAddr); ResetWithStunServerAndNat(kStunAddr); @@ -1055,16 +1100,17 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNat) { ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout); ASSERT_EQ(2U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", - rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", + rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); EXPECT_EQ(3U, candidates_.size()); } // Test TURN port in shared socket mode with UDP and TCP TURN server addresses. -TEST_F(PortAllocatorTest, TestSharedSocketWithoutNatUsingTurn) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithoutNatUsingTurn) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); AddInterface(kClientAddr); allocator_.reset(new cricket::BasicPortAllocator(&network_manager_)); @@ -1082,20 +1128,21 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithoutNatUsingTurn) { ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout); ASSERT_EQ(3U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", - rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", - rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); EXPECT_EQ(3U, candidates_.size()); } // Testing DNS resolve for the TURN server, this will test AllocationSequence // handling the unresolved address signal from TurnPort. -TEST_F(PortAllocatorTest, TestSharedSocketWithServerAddressResolve) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithServerAddressResolve) { turn_server_.AddInternalSocket(rtc::SocketAddress("127.0.0.1", 3478), cricket::PROTO_UDP); AddInterface(kClientAddr); @@ -1121,7 +1168,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithServerAddressResolve) { // Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled only one port // is allocated for udp/stun/turn. In this test we should expect all local, // stun and turn candidates. -TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithNatUsingTurn) { AddInterface(kClientAddr); ResetWithStunServerAndNat(kStunAddr); @@ -1137,13 +1184,14 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) { ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout); ASSERT_EQ(2U, ports_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", - rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", + rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", - rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); EXPECT_EQ(3U, candidates_.size()); // Local port will be created first and then TURN port. @@ -1154,7 +1202,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurn) { // Test that when PORTALLOCATOR_ENABLE_SHARED_SOCKET is enabled and the TURN // server is also used as the STUN server, we should get 'local', 'stun', and // 'relay' candidates. -TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAsStun) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithNatUsingTurnAsStun) { AddInterface(kClientAddr); // Use an empty SocketAddress to add a NAT without STUN server. ResetWithStunServerAndNat(SocketAddress()); @@ -1174,13 +1222,14 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAsStun) { ASSERT_EQ_WAIT(3U, candidates_.size(), kDefaultAllocationTimeout); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", - rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp", + rtc::SocketAddress(kNatUdpAddr.ipaddr(), 0)); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", - rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "relay", "udp", + rtc::SocketAddress(kTurnUdpExtAddr.ipaddr(), 0)); EXPECT_EQ(candidates_[2].related_address(), candidates_[1].address()); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); @@ -1193,7 +1242,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAsStun) { // Test that when only a TCP TURN server is available, we do NOT use it as // a UDP STUN server, as this could leak our IP address. Thus we should only // expect two ports, a UDPPort and TurnPort. -TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnTcpOnly) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithNatUsingTurnTcpOnly) { turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP); AddInterface(kClientAddr); ResetWithStunServerAndNat(rtc::SocketAddress()); @@ -1225,7 +1274,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnTcpOnly) { // 'relay' candidates. // TODO(deadbeef): Remove this test when support for non-shared socket mode // is removed. -TEST_F(PortAllocatorTest, TestNonSharedSocketWithNatUsingTurnAsStun) { +TEST_F(BasicPortAllocatorTest, TestNonSharedSocketWithNatUsingTurnAsStun) { AddInterface(kClientAddr); // Use an empty SocketAddress to add a NAT without STUN server. ResetWithStunServerAndNat(SocketAddress()); @@ -1261,7 +1310,7 @@ TEST_F(PortAllocatorTest, TestNonSharedSocketWithNatUsingTurnAsStun) { // Test that even when both a STUN and TURN server are configured, the TURN // server is used as a STUN server and we get a 'stun' candidate. -TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAndStun) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketWithNatUsingTurnAndStun) { AddInterface(kClientAddr); // Configure with STUN server but destroy it, so we can ensure that it's // the TURN server actually being used as a STUN server. @@ -1295,7 +1344,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketWithNatUsingTurnAndStun) { // This test verifies when PORTALLOCATOR_ENABLE_SHARED_SOCKET flag is enabled // and fail to generate STUN candidate, local UDP candidate is generated // properly. -TEST_F(PortAllocatorTest, TestSharedSocketNoUdpAllowed) { +TEST_F(BasicPortAllocatorTest, TestSharedSocketNoUdpAllowed) { allocator().set_flags(allocator().flags() | cricket::PORTALLOCATOR_DISABLE_RELAY | cricket::PORTALLOCATOR_DISABLE_TCP | @@ -1307,7 +1356,8 @@ TEST_F(PortAllocatorTest, TestSharedSocketNoUdpAllowed) { ASSERT_EQ_WAIT(1U, ports_.size(), kDefaultAllocationTimeout); EXPECT_EQ(1U, candidates_.size()); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); // STUN timeout is 9sec. We need to wait to get candidate done signal. EXPECT_TRUE_WAIT(candidate_allocation_done_, 10000); EXPECT_EQ(1U, candidates_.size()); @@ -1316,7 +1366,7 @@ TEST_F(PortAllocatorTest, TestSharedSocketNoUdpAllowed) { // Test that when the NetworkManager doesn't have permission to enumerate // adapters, the PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified // automatically. -TEST_F(PortAllocatorTest, TestNetworkPermissionBlocked) { +TEST_F(BasicPortAllocatorTest, TestNetworkPermissionBlocked) { network_manager_.set_default_local_addresses(kPrivateAddr.ipaddr(), rtc::IPAddress()); network_manager_.set_enumeration_permission( @@ -1336,12 +1386,12 @@ TEST_F(PortAllocatorTest, TestNetworkPermissionBlocked) { EXPECT_PRED5(CheckCandidate, candidates_[0], cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", kPrivateAddr); - EXPECT_TRUE((session_->flags() & - cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) != 0); + EXPECT_NE(0U, session_->flags() & + cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION); } // This test verifies allocator can use IPv6 addresses along with IPv4. -TEST_F(PortAllocatorTest, TestEnableIPv6Addresses) { +TEST_F(BasicPortAllocatorTest, TestEnableIPv6Addresses) { allocator().set_flags(allocator().flags() | cricket::PORTALLOCATOR_DISABLE_RELAY | cricket::PORTALLOCATOR_ENABLE_IPV6 | @@ -1355,21 +1405,21 @@ TEST_F(PortAllocatorTest, TestEnableIPv6Addresses) { EXPECT_EQ(4U, candidates_.size()); EXPECT_TRUE_WAIT(candidate_allocation_done_, kDefaultAllocationTimeout); EXPECT_PRED5(CheckCandidate, candidates_[0], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", - kClientIPv6Addr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientIPv6Addr); EXPECT_PRED5(CheckCandidate, candidates_[1], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", - kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp", + kClientAddr); EXPECT_PRED5(CheckCandidate, candidates_[2], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", - kClientIPv6Addr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientIPv6Addr); EXPECT_PRED5(CheckCandidate, candidates_[3], - cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", - kClientAddr); + cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "tcp", + kClientAddr); EXPECT_EQ(4U, candidates_.size()); } -TEST_F(PortAllocatorTest, TestStopGettingPorts) { +TEST_F(BasicPortAllocatorTest, TestStopGettingPorts) { AddInterface(kClientAddr); allocator_->set_step_delay(cricket::kDefaultStepDelay); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -1390,7 +1440,7 @@ TEST_F(PortAllocatorTest, TestStopGettingPorts) { EXPECT_EQ(0U, ports_.size()); } -TEST_F(PortAllocatorTest, TestClearGettingPorts) { +TEST_F(BasicPortAllocatorTest, TestClearGettingPorts) { AddInterface(kClientAddr); allocator_->set_step_delay(cricket::kDefaultStepDelay); EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); @@ -1410,3 +1460,41 @@ TEST_F(PortAllocatorTest, TestClearGettingPorts) { ASSERT_EQ_WAIT(2U, candidates_.size(), 1000); EXPECT_EQ(2U, ports_.size()); } + +// Test that the ports and candidates are updated with new ufrag/pwd/etc. when +// a pooled session is taken out of the pool. +TEST_F(BasicPortAllocatorTest, TestTransportInformationUpdated) { + AddInterface(kClientAddr); + int pool_size = 1; + allocator_->SetConfiguration(allocator_->stun_servers(), + allocator_->turn_servers(), pool_size); + const cricket::PortAllocatorSession* peeked_session = + allocator_->GetPooledSession(); + ASSERT_NE(nullptr, peeked_session); + EXPECT_EQ_WAIT(true, peeked_session->CandidatesAllocationDone(), + kDefaultAllocationTimeout); + // Expect that when TakePooledSession is called, + // UpdateTransportInformationInternal will be called and the + // BasicPortAllocatorSession will update the ufrag/pwd of ports and + // candidates. + session_ = + allocator_->TakePooledSession(kContentName, 1, kIceUfrag0, kIcePwd0); + ASSERT_NE(nullptr, session_.get()); + auto ready_ports = session_->ReadyPorts(); + auto candidates = session_->ReadyCandidates(); + EXPECT_FALSE(ready_ports.empty()); + EXPECT_FALSE(candidates.empty()); + for (const cricket::PortInterface* port_interface : ready_ports) { + const cricket::Port* port = + static_cast(port_interface); + EXPECT_EQ(kContentName, port->content_name()); + EXPECT_EQ(1, port->component()); + EXPECT_EQ(kIceUfrag0, port->username_fragment()); + EXPECT_EQ(kIcePwd0, port->password()); + } + for (const cricket::Candidate& candidate : candidates) { + EXPECT_EQ(1, candidate.component()); + EXPECT_EQ(kIceUfrag0, candidate.username()); + EXPECT_EQ(kIcePwd0, candidate.password()); + } +} diff --git a/webrtc/p2p/p2p.gyp b/webrtc/p2p/p2p.gyp index a15fa52bb5..b8ef090587 100644 --- a/webrtc/p2p/p2p.gyp +++ b/webrtc/p2p/p2p.gyp @@ -146,9 +146,11 @@ 'direct_dependent_settings': { 'sources': [ 'base/dtlstransportchannel_unittest.cc', + 'base/fakeportallocator.h', 'base/faketransportcontroller.h', 'base/p2ptransportchannel_unittest.cc', 'base/port_unittest.cc', + 'base/portallocator_unittest.cc', 'base/pseudotcp_unittest.cc', 'base/relayport_unittest.cc', 'base/relayserver_unittest.cc', @@ -163,8 +165,7 @@ 'base/transportcontroller_unittest.cc', 'base/transportdescriptionfactory_unittest.cc', 'base/turnport_unittest.cc', - 'client/fakeportallocator.h', - 'client/portallocator_unittest.cc', + 'client/basicportallocator_unittest.cc', 'stunprober/stunprober_unittest.cc', ], 'conditions': [