diff --git a/webrtc/base/fakenetwork.h b/webrtc/base/fakenetwork.h index 60773b4099..4b6bb68a96 100644 --- a/webrtc/base/fakenetwork.h +++ b/webrtc/base/fakenetwork.h @@ -78,6 +78,8 @@ class FakeNetworkManager : public NetworkManagerBase, DoUpdateNetworks(); } + using NetworkManagerBase::set_enumeration_permission; + private: void DoUpdateNetworks() { if (!started_) diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc index 2081c94e2c..8dda89f42c 100644 --- a/webrtc/base/network.cc +++ b/webrtc/base/network.cc @@ -164,7 +164,9 @@ NetworkManager::~NetworkManager() { } NetworkManagerBase::NetworkManagerBase() - : max_ipv6_networks_(kMaxIPv6Networks), ipv6_enabled_(true) { + : enumeration_permission_(NetworkManager::kEnumerationAllowed), + max_ipv6_networks_(kMaxIPv6Networks), + ipv6_enabled_(true) { } NetworkManagerBase::~NetworkManagerBase() { @@ -173,6 +175,11 @@ NetworkManagerBase::~NetworkManagerBase() { } } +NetworkManager::EnumerationPermission +NetworkManagerBase::enumeration_permission() const { + return enumeration_permission_; +} + void NetworkManagerBase::GetAnyAddressNetworks(NetworkList* networks) { if (!ipv4_any_address_network_) { const rtc::IPAddress ipv4_any_address(INADDR_ANY); diff --git a/webrtc/base/network.h b/webrtc/base/network.h index 8e5c8f0fb7..1391572adf 100644 --- a/webrtc/base/network.h +++ b/webrtc/base/network.h @@ -56,6 +56,16 @@ class NetworkManager { public: typedef std::vector NetworkList; + // This enum indicates whether adapter enumeration is allowed. + enum EnumerationPermission { + kEnumerationAllowed, // Adapter enumeration is allowed. Getting 0 + // network from GetNetworks means that there is no + // network available. + kEnumerationDisallowed, // Adapter enumeration is + // disabled. GetAnyAddressNetworks() should be used + // instead. + }; + NetworkManager(); virtual ~NetworkManager(); @@ -73,12 +83,17 @@ class NetworkManager { virtual void StopUpdating() = 0; // Returns the current list of networks available on this machine. - // UpdateNetworks() must be called before this method is called. + // StartUpdating() must be called before this method is called. // It makes sure that repeated calls return the same object for a // given network, so that quality is tracked appropriately. Does not // include ignored networks. virtual void GetNetworks(NetworkList* networks) const = 0; + // return the current permission state of GetNetworks() + virtual EnumerationPermission enumeration_permission() const { + return kEnumerationAllowed; + } + // "AnyAddressNetwork" is a network which only contains single "any address" // IP address. (i.e. INADDR_ANY for IPv4 or in6addr_any for IPv6). This is // useful as binding to such interfaces allow default routing behavior like @@ -113,6 +128,8 @@ class NetworkManagerBase : public NetworkManager { void set_max_ipv6_networks(int networks) { max_ipv6_networks_ = networks; } int max_ipv6_networks() { return max_ipv6_networks_; } + EnumerationPermission enumeration_permission() const override; + protected: typedef std::map NetworkMap; // Updates |networks_| with the networks listed in |list|. If @@ -127,10 +144,16 @@ class NetworkManagerBase : public NetworkManager { bool* changed, NetworkManager::Stats* stats); + void set_enumeration_permission(EnumerationPermission state) { + enumeration_permission_ = state; + } + private: friend class NetworkTest; void DoUpdateNetworks(); + EnumerationPermission enumeration_permission_; + NetworkList networks_; int max_ipv6_networks_; diff --git a/webrtc/base/network_unittest.cc b/webrtc/base/network_unittest.cc index bac57794f9..ec1c637bfb 100644 --- a/webrtc/base/network_unittest.cc +++ b/webrtc/base/network_unittest.cc @@ -177,11 +177,14 @@ TEST_F(NetworkTest, DISABLED_TestCreateNetworks) { } } -// Test that UpdateNetworks succeeds. +// Test StartUpdating() and StopUpdating(). network_permission_state starts with +// ALLOWED. TEST_F(NetworkTest, TestUpdateNetworks) { BasicNetworkManager manager; manager.SignalNetworksChanged.connect( static_cast(this), &NetworkTest::OnNetworksChanged); + EXPECT_EQ(manager.enumeration_permission(), + NetworkManager::kEnumerationAllowed); manager.StartUpdating(); Thread::Current()->ProcessMessages(0); EXPECT_TRUE(callback_called_); @@ -195,6 +198,8 @@ TEST_F(NetworkTest, TestUpdateNetworks) { manager.StopUpdating(); EXPECT_TRUE(manager.started()); manager.StopUpdating(); + EXPECT_EQ(manager.enumeration_permission(), + NetworkManager::kEnumerationAllowed); EXPECT_FALSE(manager.started()); manager.StopUpdating(); EXPECT_FALSE(manager.started()); diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc index c5cfbd94a1..be71876030 100644 --- a/webrtc/p2p/client/basicportallocator.cc +++ b/webrtc/p2p/client/basicportallocator.cc @@ -304,6 +304,13 @@ void BasicPortAllocatorSession::DoAllocate() { bool done_signal_needed = false; std::vector networks; + // If the network permission state is BLOCKED, we just act as if the flag has + // been passed in. + if (allocator_->network_manager()->enumeration_permission() == + rtc::NetworkManager::kEnumerationDisallowed) { + set_flags(flags() | PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION); + } + // If the adapter enumeration is disabled, we'll just bind to any address // instead of specific NIC. This is to ensure the same routing for http // traffic by OS is also used here to avoid any local or public IP leakage diff --git a/webrtc/p2p/client/portallocator_unittest.cc b/webrtc/p2p/client/portallocator_unittest.cc index 5e2c1f8934..73861435e8 100644 --- a/webrtc/p2p/client/portallocator_unittest.cc +++ b/webrtc/p2p/client/portallocator_unittest.cc @@ -1137,6 +1137,32 @@ TEST_F(PortAllocatorTest, TestSharedSocketNoUdpAllowed) { EXPECT_EQ(1U, candidates_.size()); } +// Test that when the NetworkManager doesn't have permission to enumerate +// adapters, the PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified +// automatically. +TEST_F(PortAllocatorTest, TestNetworkPermissionBlocked) { + AddInterface(kClientAddr); + network_manager_.set_enumeration_permission( + rtc::NetworkManager::kEnumerationDisallowed); + allocator().set_flags(allocator().flags() | + cricket::PORTALLOCATOR_DISABLE_RELAY | + cricket::PORTALLOCATOR_DISABLE_TCP | + cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG | + cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET); + EXPECT_EQ( + allocator_->flags() & cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION, + 0U); + EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP)); + EXPECT_EQ( + session_->flags() & cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION, + 0U); + session_->StartGettingPorts(); + EXPECT_EQ_WAIT(1U, ports_.size(), kDefaultAllocationTimeout); + EXPECT_EQ(0U, candidates_.size()); + EXPECT_TRUE((session_->flags() & + cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) != 0); +} + // This test verifies allocator can use IPv6 addresses along with IPv4. TEST_F(PortAllocatorTest, TestEnableIPv6Addresses) { allocator().set_flags(allocator().flags() |