From af242c8645b1d1a920190a777bf51ca4ce44c6eb Mon Sep 17 00:00:00 2001 From: Jeroen de Borst Date: Wed, 24 Apr 2019 13:13:48 -0700 Subject: [PATCH] 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 Reviewed-by: Justin Uberti Reviewed-by: Steve Anton Reviewed-by: Qingsi Wang Cr-Commit-Position: refs/heads/master@{#27747} --- pc/peer_connection.cc | 14 +- pc/peer_connection.h | 5 +- pc/peer_connection_histogram_unittest.cc | 248 ++++++++++++++++++++--- rtc_base/ip_address.cc | 19 +- rtc_base/ip_address.h | 7 +- rtc_base/ip_address_unittest.cc | 22 ++ 6 files changed, 285 insertions(+), 30 deletions(-) diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 1b011a3320..f7cfc9a71a 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -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()); } diff --git a/pc/peer_connection.h b/pc/peer_connection.h index c21261cc11..39cb867406 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -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, diff --git a/pc/peer_connection_histogram_unittest.cc b/pc/peer_connection_histogram_unittest.cc index 78b41d5c30..97555a9b66 100644 --- a/pc/peer_connection_histogram_unittest.cc +++ b/pc/peer_connection_histogram_unittest.cc @@ -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 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>(); + + webrtc::PeerConnectionDependencies deps(nullptr /* observer_in */); + + auto fake_network = NewFakeNetwork(); + fake_network->CreateMdnsResponder(rtc::Thread::Current()); + fake_network->AddInterface(NextLocalAddress()); + + std::unique_ptr 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 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(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 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 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(fake_network); + } + auto observer = absl::make_unique(); - 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 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()); + return fake_networks_.back().get(); + } + + rtc::SocketAddress NextLocalAddress() { + RTC_DCHECK(next_local_address_ < (int)arraysize(kLocalAddrs)); + return kLocalAddrs[next_local_address_++]; + } + + std::vector> fake_networks_; + int next_local_address_ = 0; std::unique_ptr 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 diff --git a/rtc_base/ip_address.cc b/rtc_base/ip_address.cc index ff0be13136..96d100187b 100644 --- a/rtc_base/ip_address.cc +++ b/rtc_base/ip_address.cc @@ -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; diff --git a/rtc_base/ip_address.h b/rtc_base/ip_address.h index 49dea681bf..2a52e1ad1c 100644 --- a/rtc_base/ip_address.h +++ b/rtc_base/ip_address.h @@ -22,6 +22,7 @@ #include #endif #include + #include #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); diff --git a/rtc_base/ip_address_unittest.cc b/rtc_base/ip_address_unittest.cc index c93244dcb6..d79a7b4bd6 100644 --- a/rtc_base/ip_address_unittest.cc +++ b/rtc_base/ip_address_unittest.cc @@ -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)));