WebRTC should generate default private address even when adapter enumeration is disabled.
Introduce a DefaultAddressProvider such that rtc::Network can't access other part of NetworkManager.
This also removes the hack of generating the loopback address. The dependency has been removed by https://codereview.chromium.org/1417023003/
BUG=webrtc:5061
R=pthatcher@webrtc.org
Review URL: https://codereview.webrtc.org/1411253008 .
Cr-Commit-Position: refs/heads/master@{#10590}
diff --git a/talk/app/webrtc/peerconnectioninterface.h b/talk/app/webrtc/peerconnectioninterface.h
index 77caa9d..b7814e5 100644
--- a/talk/app/webrtc/peerconnectioninterface.h
+++ b/talk/app/webrtc/peerconnectioninterface.h
@@ -248,9 +248,6 @@
// TODO(pthatcher): Rename this ice_servers, but update Chromium
// at the same time.
IceServers servers;
- // A localhost candidate is signaled whenever a candidate with the any
- // address is allocated.
- bool enable_localhost_ice_candidate;
BundlePolicy bundle_policy;
RtcpMuxPolicy rtcp_mux_policy;
TcpCandidatePolicy tcp_candidate_policy;
@@ -262,7 +259,6 @@
RTCConfiguration()
: type(kAll),
- enable_localhost_ice_candidate(false),
bundle_policy(kBundlePolicyBalanced),
rtcp_mux_policy(kRtcpMuxPolicyNegotiate),
tcp_candidate_policy(kTcpCandidatePolicyEnabled),
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 11b2d60..1fc2a37 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -743,12 +743,6 @@
port_allocator()->set_candidate_filter(
ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type));
- if (rtc_configuration.enable_localhost_ice_candidate) {
- port_allocator()->set_flags(
- port_allocator()->flags() |
- cricket::PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
- }
-
return true;
}
diff --git a/webrtc/base/fakenetwork.h b/webrtc/base/fakenetwork.h
index fb99d59..4d98c6c6 100644
--- a/webrtc/base/fakenetwork.h
+++ b/webrtc/base/fakenetwork.h
@@ -76,6 +76,7 @@
}
using NetworkManagerBase::set_enumeration_permission;
+ using NetworkManagerBase::set_default_local_addresses;
private:
void DoUpdateNetworks() {
@@ -95,6 +96,7 @@
it->hostname(),
prefix,
prefix_length));
+ net->set_default_local_address_provider(this);
net->AddIP(it->ipaddr());
networks.push_back(net.release());
}
@@ -111,6 +113,9 @@
int next_index_ = 0;
int start_count_ = 0;
bool sent_first_update_ = false;
+
+ IPAddress default_local_ipv4_address_;
+ IPAddress default_local_ipv6_address_;
};
} // namespace rtc
diff --git a/webrtc/base/ipaddress.cc b/webrtc/base/ipaddress.cc
index 316207f..f0698e5 100644
--- a/webrtc/base/ipaddress.cc
+++ b/webrtc/base/ipaddress.cc
@@ -506,4 +506,15 @@
}
return rtc::IPAddress();
}
+
+IPAddress GetAnyIP(int family) {
+ if (family == AF_INET) {
+ return rtc::IPAddress(INADDR_ANY);
+ }
+ if (family == AF_INET6) {
+ return rtc::IPAddress(in6addr_any);
+ }
+ return rtc::IPAddress();
+}
+
} // Namespace rtc
diff --git a/webrtc/base/ipaddress.h b/webrtc/base/ipaddress.h
index fe2d6e2..0789017 100644
--- a/webrtc/base/ipaddress.h
+++ b/webrtc/base/ipaddress.h
@@ -180,6 +180,7 @@
IPAddress TruncateIP(const IPAddress& ip, int length);
IPAddress GetLoopbackIP(int family);
+IPAddress GetAnyIP(int family);
// Returns the number of contiguously set bits, counting from the MSB in network
// byte order, in this IPAddress. Bits after the first 0 encountered are not
diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc
index 32b2a91..f35dcba 100644
--- a/webrtc/base/network.cc
+++ b/webrtc/base/network.cc
@@ -151,6 +151,12 @@
} // namespace
+// These addresses are used as the targets to find out the default local address
+// on a multi-homed endpoint. They are actually DNS servers.
+const char kPublicIPv4Host[] = "8.8.8.8";
+const char kPublicIPv6Host[] = "2001:4860:4860::8888";
+const int kPublicPort = 53; // DNS port.
+
std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
int prefix_length) {
std::ostringstream ost;
@@ -169,6 +175,10 @@
return ENUMERATION_ALLOWED;
}
+bool NetworkManager::GetDefaultLocalAddress(int family, IPAddress* addr) const {
+ return false;
+}
+
NetworkManagerBase::NetworkManagerBase()
: enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED),
max_ipv6_networks_(kMaxIPv6Networks),
@@ -191,6 +201,7 @@
const rtc::IPAddress ipv4_any_address(INADDR_ANY);
ipv4_any_address_network_.reset(
new rtc::Network("any", "any", ipv4_any_address, 0));
+ ipv4_any_address_network_->set_default_local_address_provider(this);
ipv4_any_address_network_->AddIP(ipv4_any_address);
}
networks->push_back(ipv4_any_address_network_.get());
@@ -200,6 +211,7 @@
const rtc::IPAddress ipv6_any_address(in6addr_any);
ipv6_any_address_network_.reset(
new rtc::Network("any", "any", ipv6_any_address, 0));
+ ipv6_any_address_network_->set_default_local_address_provider(this);
ipv6_any_address_network_->AddIP(ipv6_any_address);
}
networks->push_back(ipv6_any_address_network_.get());
@@ -321,6 +333,28 @@
}
}
+void NetworkManagerBase::set_default_local_addresses(const IPAddress& ipv4,
+ const IPAddress& ipv6) {
+ if (ipv4.family() == AF_INET) {
+ default_local_ipv4_address_ = ipv4;
+ }
+ if (ipv6.family() == AF_INET6) {
+ default_local_ipv6_address_ = ipv6;
+ }
+}
+
+bool NetworkManagerBase::GetDefaultLocalAddress(int family,
+ IPAddress* ipaddr) const {
+ if (family == AF_INET) {
+ *ipaddr = default_local_ipv4_address_;
+ return true;
+ } else if (family == AF_INET6) {
+ *ipaddr = default_local_ipv6_address_;
+ return true;
+ }
+ return false;
+}
+
BasicNetworkManager::BasicNetworkManager()
: thread_(NULL), sent_first_update_(false), start_count_(0),
network_ignore_mask_(kDefaultNetworkIgnoreMask),
@@ -409,10 +443,9 @@
#endif
// TODO(phoglund): Need to recognize other types as well.
scoped_ptr<Network> network(new Network(cursor->ifa_name,
- cursor->ifa_name,
- prefix,
- prefix_length,
- adapter_type));
+ cursor->ifa_name, prefix,
+ prefix_length, adapter_type));
+ network->set_default_local_address_provider(this);
network->set_scope_id(scope_id);
network->AddIP(ip);
network->set_ignored(IsIgnoredNetwork(*network));
@@ -563,11 +596,9 @@
// TODO(phoglund): Need to recognize other types as well.
adapter_type = ADAPTER_TYPE_LOOPBACK;
}
- scoped_ptr<Network> network(new Network(name,
- description,
- prefix,
- prefix_length,
- adapter_type));
+ scoped_ptr<Network> network(new Network(name, description, prefix,
+ prefix_length, adapter_type));
+ network->set_default_local_address_provider(this);
network->set_scope_id(scope_id);
network->AddIP(ip);
bool ignored = IsIgnoredNetwork(*network);
@@ -724,6 +755,25 @@
}
}
+IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {
+ ASSERT(thread_ == Thread::Current());
+ ASSERT(thread_->socketserver() != nullptr);
+ ASSERT(family == AF_INET || family == AF_INET6);
+
+ scoped_ptr<AsyncSocket> socket(
+ thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
+ if (!socket) {
+ return IPAddress();
+ }
+
+ if (!socket->Connect(
+ SocketAddress(family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host,
+ kPublicPort))) {
+ return IPAddress();
+ }
+ return socket->GetLocalAddress().ipaddr();
+}
+
void BasicNetworkManager::UpdateNetworksOnce() {
if (!start_count_)
return;
@@ -735,7 +785,10 @@
SignalError();
} else {
bool changed;
- MergeNetworkList(list, &changed);
+ NetworkManager::Stats stats;
+ MergeNetworkList(list, &changed, &stats);
+ set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),
+ QueryDefaultLocalAddress(AF_INET6));
if (changed || !sent_first_update_) {
SignalNetworksChanged();
sent_first_update_ = true;
@@ -766,21 +819,34 @@
}
}
-Network::Network(const std::string& name, const std::string& desc,
- const IPAddress& prefix, int prefix_length)
- : name_(name), description_(desc), prefix_(prefix),
+Network::Network(const std::string& name,
+ const std::string& desc,
+ const IPAddress& prefix,
+ int prefix_length)
+ : name_(name),
+ description_(desc),
+ prefix_(prefix),
prefix_length_(prefix_length),
- key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
- ignored_(false), type_(ADAPTER_TYPE_UNKNOWN), preference_(0) {
-}
+ key_(MakeNetworkKey(name, prefix, prefix_length)),
+ scope_id_(0),
+ ignored_(false),
+ type_(ADAPTER_TYPE_UNKNOWN),
+ preference_(0) {}
-Network::Network(const std::string& name, const std::string& desc,
- const IPAddress& prefix, int prefix_length, AdapterType type)
- : name_(name), description_(desc), prefix_(prefix),
+Network::Network(const std::string& name,
+ const std::string& desc,
+ const IPAddress& prefix,
+ int prefix_length,
+ AdapterType type)
+ : name_(name),
+ description_(desc),
+ prefix_(prefix),
prefix_length_(prefix_length),
- key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
- ignored_(false), type_(type), preference_(0) {
-}
+ key_(MakeNetworkKey(name, prefix, prefix_length)),
+ scope_id_(0),
+ ignored_(false),
+ type_(type),
+ preference_(0) {}
Network::~Network() = default;
diff --git a/webrtc/base/network.h b/webrtc/base/network.h
index ab3a88d..ccd205e 100644
--- a/webrtc/base/network.h
+++ b/webrtc/base/network.h
@@ -28,6 +28,9 @@
namespace rtc {
+extern const char kPublicIPv4Host[];
+extern const char kPublicIPv6Host[];
+
class Network;
class NetworkMonitorInterface;
class Thread;
@@ -51,9 +54,17 @@
std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
int prefix_length);
+class DefaultLocalAddressProvider {
+ public:
+ virtual ~DefaultLocalAddressProvider() = default;
+ // The default local address is the local address used in multi-homed endpoint
+ // when the any address (0.0.0.0 or ::) is used as the local address.
+ virtual bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const = 0;
+};
+
// Generic network manager interface. It provides list of local
// networks.
-class NetworkManager {
+class NetworkManager : public DefaultLocalAddressProvider {
public:
typedef std::vector<Network*> NetworkList;
@@ -67,7 +78,7 @@
};
NetworkManager();
- virtual ~NetworkManager();
+ ~NetworkManager() override;
// Called when network list is updated.
sigslot::signal0<> SignalNetworksChanged;
@@ -99,6 +110,8 @@
// TODO(guoweis): remove this body when chromium implements this.
virtual void GetAnyAddressNetworks(NetworkList* networks) {}
+ bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override;
+
// Dumps a list of networks available to LS_INFO.
virtual void DumpNetworks(bool include_ignored) {}
@@ -128,6 +141,8 @@
EnumerationPermission enumeration_permission() const override;
+ bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override;
+
protected:
typedef std::map<std::string, Network*> NetworkMap;
// Updates |networks_| with the networks listed in |list|. If
@@ -146,6 +161,9 @@
enumeration_permission_ = state;
}
+ void set_default_local_addresses(const IPAddress& ipv4,
+ const IPAddress& ipv6);
+
private:
friend class NetworkTest;
@@ -159,6 +177,9 @@
rtc::scoped_ptr<rtc::Network> ipv4_any_address_network_;
rtc::scoped_ptr<rtc::Network> ipv6_any_address_network_;
+
+ IPAddress default_local_ipv4_address_;
+ IPAddress default_local_ipv6_address_;
};
// Basic implementation of the NetworkManager interface that gets list
@@ -220,6 +241,11 @@
// based on the network's property instead of any individual IP.
bool IsIgnoredNetwork(const Network& network) const;
+ // This function connects a UDP socket to a public address and returns the
+ // local address associated it. Since it binds to the "any" address
+ // internally, it returns the default local address on a multi-homed endpoint.
+ IPAddress QueryDefaultLocalAddress(int family) const;
+
private:
friend class NetworkTest;
@@ -247,13 +273,26 @@
// Represents a Unix-type network interface, with a name and single address.
class Network {
public:
- Network(const std::string& name, const std::string& description,
- const IPAddress& prefix, int prefix_length);
+ Network(const std::string& name,
+ const std::string& description,
+ const IPAddress& prefix,
+ int prefix_length);
- Network(const std::string& name, const std::string& description,
- const IPAddress& prefix, int prefix_length, AdapterType type);
+ Network(const std::string& name,
+ const std::string& description,
+ const IPAddress& prefix,
+ int prefix_length,
+ AdapterType type);
~Network();
+ const DefaultLocalAddressProvider* default_local_address_provider() {
+ return default_local_address_provider_;
+ }
+ void set_default_local_address_provider(
+ const DefaultLocalAddressProvider* provider) {
+ default_local_address_provider_ = provider;
+ }
+
// Returns the name of the interface this network is associated wtih.
const std::string& name() const { return name_; }
@@ -323,6 +362,7 @@
std::string ToString() const;
private:
+ const DefaultLocalAddressProvider* default_local_address_provider_ = nullptr;
std::string name_;
std::string description_;
IPAddress prefix_;
diff --git a/webrtc/base/network_unittest.cc b/webrtc/base/network_unittest.cc
index 4362221..5324e86 100644
--- a/webrtc/base/network_unittest.cc
+++ b/webrtc/base/network_unittest.cc
@@ -10,6 +10,7 @@
#include "webrtc/base/network.h"
+#include "webrtc/base/nethelpers.h"
#include "webrtc/base/networkmonitor.h"
#include <vector>
#if defined(WEBRTC_POSIX)
@@ -96,6 +97,11 @@
bool callback_called_;
};
+class TestBasicNetworkManager : public BasicNetworkManager {
+ public:
+ using BasicNetworkManager::QueryDefaultLocalAddress;
+};
+
// Test that the Network ctor works properly.
TEST_F(NetworkTest, TestNetworkConstruct) {
Network ipv4_network1("test_eth0", "Test Network Adapter 1",
@@ -842,4 +848,19 @@
NetworkMonitorFactory::ReleaseFactory(factory);
}
+TEST_F(NetworkTest, DefaultPrivateAddress) {
+ TestBasicNetworkManager manager;
+ manager.StartUpdating();
+ std::vector<Network*> networks;
+ manager.GetNetworks(&networks);
+ for (auto& network : networks) {
+ if (network->GetBestIP().family() == AF_INET) {
+ EXPECT_TRUE(manager.QueryDefaultLocalAddress(AF_INET) != IPAddress());
+ } else if (network->GetBestIP().family() == AF_INET6) {
+ EXPECT_TRUE(manager.QueryDefaultLocalAddress(AF_INET6) != IPAddress());
+ }
+ }
+ manager.StopUpdating();
+}
+
} // namespace rtc
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index 4a4ed32..c3e5df6 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -456,9 +456,8 @@
}
UDPPort* CreateUdpPort(const SocketAddress& addr,
PacketSocketFactory* socket_factory) {
- return UDPPort::Create(main_, socket_factory, &network_,
- addr.ipaddr(), 0, 0, username_, password_,
- std::string(), false);
+ return UDPPort::Create(main_, socket_factory, &network_, addr.ipaddr(), 0,
+ 0, username_, password_, std::string(), true);
}
TCPPort* CreateTcpPort(const SocketAddress& addr) {
return CreateTcpPort(addr, &socket_factory_);
diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h
index 4f8ec2f..38650a5 100644
--- a/webrtc/p2p/base/portallocator.h
+++ b/webrtc/p2p/base/portallocator.h
@@ -46,10 +46,14 @@
PORTALLOCATOR_ENABLE_SHARED_UFRAG = 0x80,
PORTALLOCATOR_ENABLE_SHARED_SOCKET = 0x100,
PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE = 0x200,
+ // When specified, we'll only allocate the STUN candidate for the public
+ // interface as seen by regular http traffic and the HOST candidate associated
+ // with the default local interface.
PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION = 0x400,
- // When specified, a loopback candidate will be generated if
- // PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified.
- PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE = 0x800,
+ // When specified along with PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION, the
+ // default local candidate mentioned above will not be allocated. Only the
+ // STUN candidate will be.
+ PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE = 0x800,
// Disallow use of UDP when connecting to a relay server. Since proxy servers
// usually don't handle UDP, using UDP will leak the IP address.
PORTALLOCATOR_DISABLE_UDP_RELAY = 0x1000,
diff --git a/webrtc/p2p/base/stunport.cc b/webrtc/p2p/base/stunport.cc
index 86eaf65..ab8b2bf 100644
--- a/webrtc/p2p/base/stunport.cc
+++ b/webrtc/p2p/base/stunport.cc
@@ -13,6 +13,7 @@
#include "webrtc/p2p/base/common.h"
#include "webrtc/p2p/base/portallocator.h"
#include "webrtc/p2p/base/stun.h"
+#include "webrtc/base/checks.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/ipaddress.h"
@@ -169,15 +170,19 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress)
- : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
- username, password),
+ bool emit_local_for_anyaddress)
+ : Port(thread,
+ factory,
+ network,
+ socket->GetLocalAddress().ipaddr(),
+ username,
+ password),
requests_(thread),
socket_(socket),
error_(0),
ready_(false),
stun_keepalive_delay_(KEEPALIVE_DELAY),
- emit_localhost_for_anyaddress_(emit_localhost_for_anyaddress) {
+ emit_local_for_anyaddress_(emit_local_for_anyaddress) {
requests_.set_origin(origin);
}
@@ -190,7 +195,7 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress)
+ bool emit_local_for_anyaddress)
: Port(thread,
LOCAL_PORT_TYPE,
factory,
@@ -205,7 +210,7 @@
error_(0),
ready_(false),
stun_keepalive_delay_(KEEPALIVE_DELAY),
- emit_localhost_for_anyaddress_(emit_localhost_for_anyaddress) {
+ emit_local_for_anyaddress_(emit_local_for_anyaddress) {
requests_.set_origin(origin);
}
@@ -297,13 +302,11 @@
void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
const rtc::SocketAddress& address) {
// When adapter enumeration is disabled and binding to the any address, the
- // loopback address will be issued as a candidate instead if
- // |emit_localhost_for_anyaddress| is true. This is to allow connectivity on
- // demo pages without STUN/TURN to work.
+ // default local address will be issued as a candidate instead if
+ // |emit_local_for_anyaddress| is true. This is to allow connectivity for
+ // applications which absolutely requires a HOST candidate.
rtc::SocketAddress addr = address;
- if (addr.IsAnyIP() && emit_localhost_for_anyaddress_) {
- addr.SetIP(rtc::GetLoopbackIP(addr.family()));
- }
+ MaybeSetDefaultLocalAddress(&addr);
AddAddress(addr, addr, rtc::SocketAddress(), UDP_PROTOCOL_NAME, "", "",
LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST, 0, false);
@@ -401,6 +404,19 @@
}
}
+void UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const {
+ if (!addr->IsAnyIP() || !emit_local_for_anyaddress_ ||
+ !Network()->default_local_address_provider()) {
+ return;
+ }
+ rtc::IPAddress default_address;
+ bool result =
+ Network()->default_local_address_provider()->GetDefaultLocalAddress(
+ addr->family(), &default_address);
+ RTC_DCHECK(result && !default_address.IsNil());
+ addr->SetIP(default_address);
+}
+
void UDPPort::OnStunBindingRequestSucceeded(
const rtc::SocketAddress& stun_server_addr,
const rtc::SocketAddress& stun_reflected_addr) {
@@ -418,6 +434,7 @@
!HasCandidateWithAddress(stun_reflected_addr)) {
rtc::SocketAddress related_address = socket_->GetLocalAddress();
+ MaybeSetDefaultLocalAddress(&related_address);
if (!(candidate_filter() & CF_HOST)) {
// If candidate filter doesn't have CF_HOST specified, empty raddr to
// avoid local address leakage.
diff --git a/webrtc/p2p/base/stunport.h b/webrtc/p2p/base/stunport.h
index 62b23cf..6e7a239 100644
--- a/webrtc/p2p/base/stunport.h
+++ b/webrtc/p2p/base/stunport.h
@@ -35,10 +35,9 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress) {
- UDPPort* port = new UDPPort(thread, factory, network, socket,
- username, password, origin,
- emit_localhost_for_anyaddress);
+ bool emit_local_for_anyaddress) {
+ UDPPort* port = new UDPPort(thread, factory, network, socket, username,
+ password, origin, emit_local_for_anyaddress);
if (!port->Init()) {
delete port;
port = NULL;
@@ -55,11 +54,10 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress) {
- UDPPort* port = new UDPPort(thread, factory, network,
- ip, min_port, max_port,
- username, password, origin,
- emit_localhost_for_anyaddress);
+ bool emit_local_for_anyaddress) {
+ UDPPort* port =
+ new UDPPort(thread, factory, network, ip, min_port, max_port, username,
+ password, origin, emit_local_for_anyaddress);
if (!port->Init()) {
delete port;
port = NULL;
@@ -115,7 +113,7 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress);
+ bool emit_local_for_anyaddress);
UDPPort(rtc::Thread* thread,
rtc::PacketSocketFactory* factory,
@@ -124,7 +122,7 @@
const std::string& username,
const std::string& password,
const std::string& origin,
- bool emit_localhost_for_anyaddress);
+ bool emit_local_for_anyaddress);
bool Init();
@@ -150,6 +148,10 @@
void SendStunBindingRequests();
+ // Helper function which will set |addr|'s IP to the default local address if
+ // |addr| is the "any" address and |emit_local_for_anyaddress_| is true.
+ void MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const;
+
private:
// A helper class which can be called repeatedly to resolve multiple
// addresses, as opposed to rtc::AsyncResolverInterface, which can only
@@ -211,8 +213,9 @@
bool ready_;
int stun_keepalive_delay_;
- // This is true when PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE is specified.
- bool emit_localhost_for_anyaddress_;
+ // This is true by default and false when
+ // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified.
+ bool emit_local_for_anyaddress_;
friend class StunBindingRequest;
};
diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc
index 21c8921..865fbbb 100644
--- a/webrtc/p2p/client/basicportallocator.cc
+++ b/webrtc/p2p/client/basicportallocator.cc
@@ -436,7 +436,8 @@
// When adapter enumeration is disabled, disable CF_HOST at port level so
// local address is not leaked by stunport in the candidate's related address.
- if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
+ if ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
+ (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) {
candidate_filter &= ~CF_HOST;
}
port->set_candidate_filter(candidate_filter);
@@ -600,25 +601,6 @@
return true;
}
- // If PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE is specified and it's
- // loopback address, we should allow it as it's for demo page connectivity
- // when no TURN/STUN specified.
- if (c.address().IsLoopbackIP() &&
- (flags() & PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE) != 0) {
- return true;
- }
-
- // This is just to prevent the case when binding to any address (all 0s), if
- // somehow the host candidate address is not all 0s. Either because local
- // installed proxy changes the address or a packet has been sent for any
- // reason before getsockname is called.
- if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
- LOG(LS_WARNING) << "Received non-0 host address: "
- << c.address().ToString()
- << " when adapter enumeration is disabled";
- return false;
- }
-
return ((filter & CF_HOST) != 0);
}
return false;
@@ -882,19 +864,19 @@
// TODO(mallinath) - Remove UDPPort creating socket after shared socket
// is enabled completely.
UDPPort* port = NULL;
- bool emit_localhost_for_anyaddress =
- IsFlagSet(PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
+ bool emit_local_candidate_for_anyaddress =
+ !IsFlagSet(PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
port = UDPPort::Create(
session_->network_thread(), session_->socket_factory(), network_,
udp_socket_.get(), session_->username(), session_->password(),
- session_->allocator()->origin(), emit_localhost_for_anyaddress);
+ session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
} else {
port = UDPPort::Create(
session_->network_thread(), session_->socket_factory(), network_, ip_,
session_->allocator()->min_port(), session_->allocator()->max_port(),
session_->username(), session_->password(),
- session_->allocator()->origin(), emit_localhost_for_anyaddress);
+ session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
}
if (port) {
diff --git a/webrtc/p2p/client/portallocator_unittest.cc b/webrtc/p2p/client/portallocator_unittest.cc
index 9617688..45545f5 100644
--- a/webrtc/p2p/client/portallocator_unittest.cc
+++ b/webrtc/p2p/client/portallocator_unittest.cc
@@ -114,6 +114,12 @@
void AddInterface(const SocketAddress& addr, const std::string& if_name) {
network_manager_.AddInterface(addr, if_name);
}
+ // The default route is the public address that STUN server will observe when
+ // the endpoint is sitting on the public internet and the local port is bound
+ // to the "any" address. This may be different from the default local address
+ // which the endpoint observes. This can occur if the route to the public
+ // endpoint like 8.8.8.8 (specified as the default local address) is
+ // different from the route to the STUN server (the default route).
void AddInterfaceAsDefaultRoute(const SocketAddress& addr) {
AddInterface(addr);
// When a binding comes from the any address, the |addr| will be used as the
@@ -254,6 +260,8 @@
const rtc::IPAddress& stun_candidate_addr,
const rtc::IPAddress& relay_candidate_udp_transport_addr,
const rtc::IPAddress& relay_candidate_tcp_transport_addr) {
+ network_manager_.set_default_local_addresses(kPrivateAddr.ipaddr(),
+ rtc::IPAddress());
if (!session_) {
EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
}
@@ -268,16 +276,20 @@
if (!host_candidate_addr.IsNil()) {
EXPECT_PRED5(CheckCandidate, candidates_[total_candidates],
cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
- rtc::SocketAddress(host_candidate_addr, 0));
+ rtc::SocketAddress(kPrivateAddr.ipaddr(), 0));
++total_candidates;
}
if (!stun_candidate_addr.IsNil()) {
EXPECT_PRED5(CheckCandidate, candidates_[total_candidates],
cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp",
rtc::SocketAddress(stun_candidate_addr, 0));
- EXPECT_EQ(rtc::EmptySocketAddressWithFamily(
- candidates_[total_candidates].address().family()),
- candidates_[total_candidates].related_address());
+ rtc::IPAddress related_address = host_candidate_addr;
+ if (host_candidate_addr.IsNil()) {
+ related_address =
+ rtc::GetAnyIP(candidates_[total_candidates].address().family());
+ }
+ EXPECT_EQ(related_address,
+ candidates_[total_candidates].related_address().ipaddr());
++total_candidates;
}
if (!relay_candidate_udp_transport_addr.IsNil()) {
@@ -589,7 +601,6 @@
// candidate_filter() is set to CF_RELAY and no relay is specified.
TEST_F(PortAllocatorTest,
TestDisableAdapterEnumerationWithoutNatRelayTransportOnly) {
- AddInterfaceAsDefaultRoute(kClientAddr);
ResetWithStunServerNoNat(kStunAddr);
allocator().set_candidate_filter(cricket::CF_RELAY);
// Expect to see no ports and no candidates.
@@ -597,86 +608,88 @@
rtc::IPAddress(), rtc::IPAddress());
}
-// Test that we should only get STUN and TURN candidates when adapter
-// enumeration is disabled.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationBehindNat) {
- AddInterface(kClientAddr);
- // GTURN is not configured here.
- ResetWithStunServerAndNat(kStunAddr);
- AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
- // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and both STUN and
- // TURN/UDP candidates.
- CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
- kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
-}
-
-// Test that even with multiple interfaces, the result should still be one STUN
-// and one TURN candidate since we bind to any address (i.e. all 0s).
+// 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,
TestDisableAdapterEnumerationBehindNatMultipleInterfaces) {
AddInterface(kPrivateAddr);
AddInterface(kPrivateAddr2);
ResetWithStunServerAndNat(kStunAddr);
AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
- // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and both STUN and
- // TURN/UDP candidates.
- CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
- kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
+ // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and a default private,
+ // STUN and TURN/UDP candidates.
+ CheckDisableAdapterEnumeration(3U, kPrivateAddr.ipaddr(),
+ kNatUdpAddr.ipaddr(), kTurnUdpExtAddr.ipaddr(),
+ rtc::IPAddress());
}
-// Test that we should get STUN, TURN/UDP and TURN/TCP candidates when a
-// TURN/TCP server is specified.
+// 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) {
turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
- AddInterface(kClientAddr);
- // GTURN is not configured here.
+ AddInterface(kPrivateAddr);
ResetWithStunServerAndNat(kStunAddr);
AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
- // Expect to see 4 ports - STUN, TURN/UDP, TURN/TCP and TCP port. STUN,
- // TURN/UDP, and TURN/TCP candidates.
- CheckDisableAdapterEnumeration(4U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
- kTurnUdpExtAddr.ipaddr(),
+ // Expect to see 4 ports - STUN, TURN/UDP, TURN/TCP and TCP port. A default
+ // private, STUN, TURN/UDP, and TURN/TCP candidates.
+ CheckDisableAdapterEnumeration(4U, kPrivateAddr.ipaddr(),
+ kNatUdpAddr.ipaddr(), kTurnUdpExtAddr.ipaddr(),
kTurnUdpExtAddr.ipaddr());
}
-// Test that we should only get STUN and TURN candidates when adapter
-// enumeration is disabled. Since the endpoint is not behind NAT, the srflx
-// address should be the public client interface.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNat) {
- AddInterfaceAsDefaultRoute(kClientAddr);
- ResetWithStunServerNoNat(kStunAddr);
- AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
- // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, but only both STUN and
- // TURN candidates. The STUN candidate should have kClientAddr as srflx
- // address, and TURN candidate with kClientAddr as the related address.
- CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kClientAddr.ipaddr(),
- kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
+// Test that when adapter enumeration is disabled, for endpoints without
+// STUN/TURN specified, a default private candidate is still generated.
+TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) {
+ ResetWithNoServersOrNat();
+ // Expect to see 2 ports: STUN and TCP ports, one default private candidate.
+ CheckDisableAdapterEnumeration(2U, kPrivateAddr.ipaddr(), rtc::IPAddress(),
+ rtc::IPAddress(), rtc::IPAddress());
}
-// Test that when adapter enumeration is disabled, for endpoints without
-// STUN/TURN specified, no candidate is generated.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) {
- AddInterfaceAsDefaultRoute(kClientAddr);
- ResetWithNoServersOrNat();
- // Expect to see 2 ports: STUN and TCP ports, but no candidate.
+// 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,
+ TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabled) {
+ ResetWithStunServerNoNat(kStunAddr);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
+ // Expect to see 2 ports: STUN and TCP ports, localhost candidate and STUN
+ // candidate.
CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), rtc::IPAddress(),
rtc::IPAddress(), rtc::IPAddress());
}
// Test that when adapter enumeration is disabled, with
-// PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind
-// a NAT, there are a localhost candidate in addition to a STUN candidate.
-TEST_F(PortAllocatorTest,
- TestDisableAdapterEnumerationWithoutNatLocalhostCandidateRequested) {
- AddInterfaceAsDefaultRoute(kClientAddr);
+// PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind
+// a NAT, there is no local candidate. However, this specified default route
+// (kClientAddr) which was discovered when sending STUN requests, will become
+// the srflx addresses.
+TEST_F(
+ PortAllocatorTest,
+ TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabledWithDifferentDefaultRoute) {
ResetWithStunServerNoNat(kStunAddr);
+ AddInterfaceAsDefaultRoute(kClientAddr);
EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
- session_->set_flags(cricket::PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
+ session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
// Expect to see 2 ports: STUN and TCP ports, localhost candidate and STUN
// candidate.
- CheckDisableAdapterEnumeration(2U, rtc::GetLoopbackIP(AF_INET),
- kClientAddr.ipaddr(), rtc::IPAddress(),
- rtc::IPAddress());
+ CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), kClientAddr.ipaddr(),
+ rtc::IPAddress(), rtc::IPAddress());
+}
+
+// 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,
+ TestDisableAdapterEnumerationWithNatLocalhostCandidateDisabled) {
+ ResetWithStunServerAndNat(kStunAddr);
+ EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+ session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
+ // Expect to see 2 ports: STUN and TCP ports, and single STUN candidate.
+ CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
+ rtc::IPAddress(), rtc::IPAddress());
}
// Test that we disable relay over UDP, and only TCP is used when connecting to
@@ -1244,7 +1257,8 @@
// adapters, the PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified
// automatically.
TEST_F(PortAllocatorTest, TestNetworkPermissionBlocked) {
- AddInterface(kClientAddr);
+ network_manager_.set_default_local_addresses(kPrivateAddr.ipaddr(),
+ rtc::IPAddress());
network_manager_.set_enumeration_permission(
rtc::NetworkManager::ENUMERATION_BLOCKED);
allocator().set_flags(allocator().flags() |
@@ -1258,7 +1272,10 @@
cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
session_->StartGettingPorts();
EXPECT_EQ_WAIT(1U, ports_.size(), kDefaultAllocationTimeout);
- EXPECT_EQ(0U, candidates_.size());
+ EXPECT_EQ(1U, candidates_.size());
+ EXPECT_PRED5(CheckCandidate, candidates_[0],
+ cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
+ kPrivateAddr);
EXPECT_TRUE((session_->flags() &
cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) != 0);
}