Extending UsagePattern and private IP addresses.

Adding additional usage bits to the UsagePattern to:
- Track whether a mDNS candidate was collected
- Track whether a mDNS candidate was received from the remote peer
- Track whether a private IP address was received from the remote peer

The definition of a private IP address is extended to include 100.64/10 addresses.


Bug: None
Change-Id: I77182685120413d5c13c5f67e480d33fdcaefc6a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/134000
Commit-Queue: Jeroen de Borst <jeroendb@webrtc.org>
Reviewed-by: Justin Uberti <juberti@google.com>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Qingsi Wang <qingsi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27747}
This commit is contained in:
Jeroen de Borst 2019-04-24 13:13:48 -07:00 committed by Commit Bot
parent 7d3780f347
commit af242c8645
6 changed files with 285 additions and 30 deletions

View File

@ -76,9 +76,9 @@ using cricket::StreamParams;
using cricket::TransportInfo;
using cricket::LOCAL_PORT_TYPE;
using cricket::STUN_PORT_TYPE;
using cricket::RELAY_PORT_TYPE;
using cricket::PRFLX_PORT_TYPE;
using cricket::RELAY_PORT_TYPE;
using cricket::STUN_PORT_TYPE;
namespace webrtc {
@ -3584,6 +3584,12 @@ bool PeerConnection::AddIceCandidate(
bool result = UseCandidate(ice_candidate);
if (result) {
NoteUsageEvent(UsageEvent::REMOTE_CANDIDATE_ADDED);
if (ice_candidate->candidate().address().IsUnresolvedIP()) {
NoteUsageEvent(UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED);
}
if (ice_candidate->candidate().address().IsPrivateIP()) {
NoteUsageEvent(UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED);
}
NoteAddIceCandidateResult(kAddIceCandidateSuccess);
} else {
NoteAddIceCandidateResult(kAddIceCandidateFailNotUsable);
@ -4154,6 +4160,10 @@ void PeerConnection::OnIceCandidate(
candidate->candidate().address().IsPrivateIP()) {
NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED);
}
if (candidate->candidate().type() == LOCAL_PORT_TYPE &&
candidate->candidate().address().IsUnresolvedIP()) {
NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED);
}
Observer()->OnIceCandidate(candidate.get());
}

View File

@ -73,7 +73,10 @@ class PeerConnection : public PeerConnectionInternal,
ICE_STATE_CONNECTED = 0x200,
CLOSE_CALLED = 0x400,
PRIVATE_CANDIDATE_COLLECTED = 0x800,
MAX_VALUE = 0x1000,
REMOTE_PRIVATE_CANDIDATE_ADDED = 0x1000,
MDNS_CANDIDATE_COLLECTED = 0x2000,
REMOTE_MDNS_CANDIDATE_ADDED = 0x4000,
MAX_VALUE = 0x8000,
};
explicit PeerConnection(PeerConnectionFactory* factory,

View File

@ -23,6 +23,7 @@
#include "api/rtc_error.h"
#include "api/scoped_refptr.h"
#include "media/base/fake_media_engine.h"
#include "p2p/base/mock_async_resolver.h"
#include "p2p/base/port_allocator.h"
#include "p2p/client/basic_port_allocator.h"
#include "pc/peer_connection.h"
@ -30,6 +31,7 @@
#include "pc/peer_connection_wrapper.h"
#include "pc/sdp_utils.h"
#include "pc/test/mock_peer_connection_observers.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
#include "rtc_base/fake_network.h"
#include "rtc_base/gunit.h"
@ -39,17 +41,19 @@
#include "rtc_base/thread.h"
#include "rtc_base/virtual_socket_server.h"
#include "system_wrappers/include/metrics.h"
#include "test/gtest.h"
#include "test/gmock.h"
namespace webrtc {
using RTCConfiguration = PeerConnectionInterface::RTCConfiguration;
using RTCOfferAnswerOptions = PeerConnectionInterface::RTCOfferAnswerOptions;
using ::testing::NiceMock;
using ::testing::Values;
static const char kUsagePatternMetric[] = "WebRTC.PeerConnection.UsagePattern";
static constexpr int kDefaultTimeout = 10000;
static const rtc::SocketAddress kDefaultLocalAddress("1.1.1.1", 0);
static const rtc::SocketAddress kLocalAddrs[2] = {
rtc::SocketAddress("1.1.1.1", 0), rtc::SocketAddress("2.2.2.2", 0)};
static const rtc::SocketAddress kPrivateLocalAddress("10.1.1.1", 0);
int MakeUsageFingerprint(std::set<PeerConnection::UsageEvent> events) {
@ -234,6 +238,27 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
config, PeerConnectionFactoryInterface::Options(), nullptr, false);
}
WrapperPtr CreatePeerConnectionWithMdns(const RTCConfiguration& config) {
auto resolver_factory =
absl::make_unique<NiceMock<webrtc::MockAsyncResolverFactory>>();
webrtc::PeerConnectionDependencies deps(nullptr /* observer_in */);
auto fake_network = NewFakeNetwork();
fake_network->CreateMdnsResponder(rtc::Thread::Current());
fake_network->AddInterface(NextLocalAddress());
std::unique_ptr<cricket::BasicPortAllocator> port_allocator(
new cricket::BasicPortAllocator(fake_network));
deps.async_resolver_factory = std::move(resolver_factory);
deps.allocator = std::move(port_allocator);
return CreatePeerConnection(config,
PeerConnectionFactoryInterface::Options(),
std::move(deps), false);
}
WrapperPtr CreatePeerConnectionWithImmediateReport() {
return CreatePeerConnection(RTCConfiguration(),
PeerConnectionFactoryInterface::Options(),
@ -241,11 +266,13 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
}
WrapperPtr CreatePeerConnectionWithPrivateLocalAddresses() {
fake_network_manager_.reset(new rtc::FakeNetworkManager());
fake_network_manager_->AddInterface(kDefaultLocalAddress);
fake_network_manager_->AddInterface(kPrivateLocalAddress);
std::unique_ptr<cricket::BasicPortAllocator> port_allocator(
new cricket::BasicPortAllocator(fake_network_manager_.get()));
auto* fake_network = NewFakeNetwork();
fake_network->AddInterface(NextLocalAddress());
fake_network->AddInterface(kPrivateLocalAddress);
auto port_allocator =
absl::make_unique<cricket::BasicPortAllocator>(fake_network);
return CreatePeerConnection(RTCConfiguration(),
PeerConnectionFactoryInterface::Options(),
std::move(port_allocator), false);
@ -256,6 +283,18 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
const PeerConnectionFactoryInterface::Options factory_options,
std::unique_ptr<cricket::PortAllocator> allocator,
bool immediate_report) {
PeerConnectionDependencies deps(nullptr);
deps.allocator = std::move(allocator);
return CreatePeerConnection(config, factory_options, std::move(deps),
immediate_report);
}
WrapperPtr CreatePeerConnection(
const RTCConfiguration& config,
const PeerConnectionFactoryInterface::Options factory_options,
PeerConnectionDependencies deps,
bool immediate_report) {
rtc::scoped_refptr<PeerConnectionFactoryForUsageHistogramTest> pc_factory(
new PeerConnectionFactoryForUsageHistogramTest());
pc_factory->SetOptions(factory_options);
@ -263,9 +302,20 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
if (immediate_report) {
pc_factory->ReturnHistogramVeryQuickly();
}
// If no allocator is provided, one will be created using a network manager
// that uses the host network. This doesn't work on all trybots.
if (!deps.allocator) {
auto fake_network = NewFakeNetwork();
fake_network->AddInterface(NextLocalAddress());
deps.allocator =
absl::make_unique<cricket::BasicPortAllocator>(fake_network);
}
auto observer = absl::make_unique<ObserverForUsageHistogramTest>();
auto pc = pc_factory->CreatePeerConnection(config, std::move(allocator),
nullptr, observer.get());
deps.observer = observer.get();
auto pc = pc_factory->CreatePeerConnection(config, std::move(deps));
if (!pc) {
return nullptr;
}
@ -284,7 +334,23 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test {
return webrtc::metrics::MinSample(kUsagePatternMetric);
}
std::unique_ptr<rtc::FakeNetworkManager> fake_network_manager_;
// The PeerConnection's port allocator is tied to the PeerConnection's
// lifetime and expects the underlying NetworkManager to outlive it. That
// prevents us from having the PeerConnectionWrapper own the fake network.
// Therefore, the test fixture will own all the fake networks even though
// tests should access the fake network through the PeerConnectionWrapper.
rtc::FakeNetworkManager* NewFakeNetwork() {
fake_networks_.emplace_back(absl::make_unique<rtc::FakeNetworkManager>());
return fake_networks_.back().get();
}
rtc::SocketAddress NextLocalAddress() {
RTC_DCHECK(next_local_address_ < (int)arraysize(kLocalAddrs));
return kLocalAddrs[next_local_address_++];
}
std::vector<std::unique_ptr<rtc::FakeNetworkManager>> fake_networks_;
int next_local_address_ = 0;
std::unique_ptr<rtc::VirtualSocketServer> vss_;
rtc::AutoSocketServerThread main_;
};
@ -343,12 +409,7 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithNoHostCandidates) {
auto callee = CreatePeerConnection(config);
caller->AddAudioTrack("audio");
caller->AddVideoTrack("video");
// Under some bot configurations, this will fail - presumably bots where
// no working non-host addresses exist.
if (!caller->ConnectTo(callee.get())) {
return;
}
// If we manage to connect, we should get this precise fingerprint.
ASSERT_TRUE(caller->ConnectTo(callee.get()));
caller->pc()->Close();
callee->pc()->Close();
int expected_fingerprint = MakeUsageFingerprint(
@ -365,6 +426,91 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithNoHostCandidates) {
2, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
}
// Test getting the usage fingerprint when there are no host candidates.
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCaller) {
RTCConfiguration config;
// Enable hostname candidates with mDNS names.
auto caller = CreatePeerConnectionWithMdns(config);
auto callee = CreatePeerConnection(config);
caller->AddAudioTrack("audio");
caller->AddVideoTrack("video");
ASSERT_TRUE(caller->ConnectTo(callee.get()));
caller->pc()->Close();
callee->pc()->Close();
int expected_fingerprint_caller = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::VIDEO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::MDNS_CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
int expected_fingerprint_callee = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::VIDEO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_caller));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_callee));
}
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCallee) {
RTCConfiguration config;
// Enable hostname candidates with mDNS names.
auto caller = CreatePeerConnection(config);
auto callee = CreatePeerConnectionWithMdns(config);
caller->AddAudioTrack("audio");
caller->AddVideoTrack("video");
ASSERT_TRUE(caller->ConnectTo(callee.get()));
caller->pc()->Close();
callee->pc()->Close();
int expected_fingerprint_caller = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::VIDEO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
int expected_fingerprint_callee = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::VIDEO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::MDNS_CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_caller));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_callee));
}
#ifdef HAVE_SCTP
TEST_F(PeerConnectionUsageHistogramTest, FingerprintDataOnly) {
auto caller = CreatePeerConnection();
@ -441,20 +587,74 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintStunTurnInReconfiguration) {
1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
}
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIP) {
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCaller) {
auto caller = CreatePeerConnectionWithPrivateLocalAddresses();
auto callee = CreatePeerConnection();
caller->AddAudioTrack("audio");
ASSERT_TRUE(caller->GenerateOfferAndCollectCandidates());
ASSERT_TRUE(caller->ConnectTo(callee.get()));
caller->pc()->Close();
int expected_fingerprint = MakeUsageFingerprint(
callee->pc()->Close();
int expected_fingerprint_caller = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::CLOSE_CALLED,
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED});
EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_EQ(
1, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint));
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
int expected_fingerprint_callee = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_caller));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_callee));
}
TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCallee) {
auto caller = CreatePeerConnection();
auto callee = CreatePeerConnectionWithPrivateLocalAddresses();
caller->AddAudioTrack("audio");
ASSERT_TRUE(caller->ConnectTo(callee.get()));
caller->pc()->Close();
callee->pc()->Close();
int expected_fingerprint_caller = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
int expected_fingerprint_callee = MakeUsageFingerprint(
{PeerConnection::UsageEvent::AUDIO_ADDED,
PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED,
PeerConnection::UsageEvent::CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED,
PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED,
PeerConnection::UsageEvent::ICE_STATE_CONNECTED,
PeerConnection::UsageEvent::CLOSE_CALLED});
EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_caller));
EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric,
expected_fingerprint_callee));
}
#ifndef WEBRTC_ANDROID

View File

@ -235,6 +235,18 @@ bool IPIsPrivateNetwork(const IPAddress& ip) {
return false;
}
static bool IPIsSharedNetworkV4(const IPAddress& ip) {
uint32_t ip_in_host_order = ip.v4AddressAsHostOrderInteger();
return (ip_in_host_order >> 22) == ((100 << 2) | 1);
}
bool IPIsSharedNetwork(const IPAddress& ip) {
if (ip.family() == AF_INET) {
return IPIsSharedNetworkV4(ip);
}
return false;
}
in_addr ExtractMappedAddress(const in6_addr& in6) {
in_addr ipv4;
::memcpy(&ipv4.s_addr, &in6.s6_addr[12], sizeof(ipv4.s_addr));
@ -319,7 +331,8 @@ bool IPIsLoopback(const IPAddress& ip) {
}
bool IPIsPrivate(const IPAddress& ip) {
return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip);
return IPIsLinkLocal(ip) || IPIsLoopback(ip) || IPIsPrivateNetwork(ip) ||
IPIsSharedNetwork(ip);
}
bool IPIsUnspec(const IPAddress& ip) {
@ -407,7 +420,9 @@ int CountIPMaskBits(IPAddress mask) {
bits = (i * 32);
break;
}
default: { return 0; }
default: {
return 0;
}
}
if (word_to_count == 0) {
return bits;

View File

@ -22,6 +22,7 @@
#include <ws2tcpip.h>
#endif
#include <string.h>
#include <string>
#include "rtc_base/byte_order.h"
@ -157,8 +158,12 @@ bool IPIsLinkLocal(const IPAddress& ip);
// Identify a private network address like "192.168.111.222"
// (see https://en.wikipedia.org/wiki/Private_network )
bool IPIsPrivateNetwork(const IPAddress& ip);
// Identify a shared network address like "100.72.16.122"
// (see RFC6598)
bool IPIsSharedNetwork(const IPAddress& ip);
// Identify if an IP is "private", that is a loopback
// or an address belonging to a link-local or a private network.
// or an address belonging to a link-local, a private network or a shared
// network.
bool IPIsPrivate(const IPAddress& ip);
bool IPIsUnspec(const IPAddress& ip);
size_t HashIP(const IPAddress& ip);

View File

@ -18,6 +18,7 @@ static const unsigned int kIPv4AddrSize = 4;
static const unsigned int kIPv6AddrSize = 16;
static const unsigned int kIPv4RFC1918Addr = 0xC0A80701;
static const unsigned int kIPv4PublicAddr = 0x01020304;
static const unsigned int kIPv4RFC6598Addr = 0x64410801;
static const unsigned int kIPv4LinkLocalAddr = 0xA9FE10C1; // 169.254.16.193
static const in6_addr kIPv6LinkLocalAddr = {
{{0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0x30, 0x5b, 0xff,
@ -41,6 +42,7 @@ static const in6_addr kIPv4MappedPublicAddr = {
static const std::string kIPv4AnyAddrString = "0.0.0.0";
static const std::string kIPv4LoopbackAddrString = "127.0.0.1";
static const std::string kIPv4RFC1918AddrString = "192.168.7.1";
static const std::string kIPv4RFC6598AddrString = "100.65.8.1";
static const std::string kIPv4PublicAddrString = "1.2.3.4";
static const std::string kIPv4PublicAddrAnonymizedString = "1.2.3.x";
static const std::string kIPv6AnyAddrString = "::";
@ -179,6 +181,7 @@ TEST(IPAddressTest, TestInAddrCtor) {
addr = IPAddress(v4addr);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_TRUE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv4AddrSize, addr.Size());
EXPECT_EQ(kIPv4LoopbackAddrString, addr.ToString());
@ -188,10 +191,21 @@ TEST(IPAddressTest, TestInAddrCtor) {
addr = IPAddress(v4addr);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_FALSE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv4AddrSize, addr.Size());
EXPECT_EQ(kIPv4RFC1918AddrString, addr.ToString());
// Test an shared (RFC6598) address.
v4addr.s_addr = htonl(kIPv4RFC6598Addr);
addr = IPAddress(v4addr);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_FALSE(IPIsLoopback(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_TRUE(IPIsSharedNetwork(addr));
EXPECT_EQ(kIPv4AddrSize, addr.Size());
EXPECT_EQ(kIPv4RFC6598AddrString, addr.ToString());
// Test a 'normal' v4 address.
v4addr.s_addr = htonl(kIPv4PublicAddr);
addr = IPAddress(v4addr);
@ -215,6 +229,7 @@ TEST(IPAddressTest, TestInAddr6Ctor) {
addr = IPAddress(in6addr_loopback);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_TRUE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv6AddrSize, addr.Size());
EXPECT_EQ(kIPv6LoopbackAddrString, addr.ToString());
@ -223,6 +238,7 @@ TEST(IPAddressTest, TestInAddr6Ctor) {
addr = IPAddress(kIPv6LinkLocalAddr);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_FALSE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv6AddrSize, addr.Size());
EXPECT_EQ(kIPv6LinkLocalAddrString, addr.ToString());
@ -249,6 +265,7 @@ TEST(IPAddressTest, TestUint32Ctor) {
addr = IPAddress(INADDR_LOOPBACK);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_TRUE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv4AddrSize, addr.Size());
EXPECT_EQ(kIPv4LoopbackAddrString, addr.ToString());
@ -257,6 +274,7 @@ TEST(IPAddressTest, TestUint32Ctor) {
addr = IPAddress(kIPv4RFC1918Addr);
EXPECT_FALSE(IPIsAny(addr));
EXPECT_FALSE(IPIsLoopback(addr));
EXPECT_FALSE(IPIsSharedNetwork(addr));
EXPECT_TRUE(IPIsPrivate(addr));
EXPECT_EQ(kIPv4AddrSize, addr.Size());
EXPECT_EQ(kIPv4RFC1918AddrString, addr.ToString());
@ -537,6 +555,7 @@ TEST(IPAddressTest, TestIsPrivate) {
EXPECT_FALSE(IPIsPrivate(IPAddress(kIPv4MappedPublicAddr)));
EXPECT_TRUE(IPIsPrivate(IPAddress(kIPv4RFC1918Addr)));
EXPECT_TRUE(IPIsPrivate(IPAddress(kIPv4RFC6598Addr)));
EXPECT_TRUE(IPIsPrivate(IPAddress(INADDR_LOOPBACK)));
EXPECT_TRUE(IPIsPrivate(IPAddress(in6addr_loopback)));
EXPECT_TRUE(IPIsPrivate(IPAddress(kIPv6LinkLocalAddr)));
@ -559,6 +578,7 @@ TEST(IPAddressTest, TestIsLoopback) {
EXPECT_FALSE(IPIsLoopback(IPAddress(INADDR_ANY)));
EXPECT_FALSE(IPIsLoopback(IPAddress(kIPv4PublicAddr)));
EXPECT_FALSE(IPIsLoopback(IPAddress(in6addr_any)));
EXPECT_FALSE(IPIsLoopback(IPAddress(kIPv4RFC6598Addr)));
EXPECT_FALSE(IPIsLoopback(IPAddress(kIPv6PublicAddr)));
EXPECT_FALSE(IPIsLoopback(IPAddress(kIPv4MappedAnyAddr)));
EXPECT_FALSE(IPIsLoopback(IPAddress(kIPv4MappedPublicAddr)));
@ -577,6 +597,8 @@ TEST(IPAddressTest, TestIsLinkLocal) {
// loopback addresses
EXPECT_FALSE(IPIsLinkLocal(IPAddress(INADDR_LOOPBACK)));
EXPECT_FALSE(IPIsLinkLocal(IPAddress(in6addr_loopback)));
// shared addresses
EXPECT_FALSE(IPIsLinkLocal(IPAddress(kIPv4RFC6598Addr)));
// public addresses
EXPECT_FALSE(IPIsLinkLocal(IPAddress(kIPv4PublicAddr)));
EXPECT_FALSE(IPIsLinkLocal(IPAddress(kIPv6PublicAddr)));