From 6dc4593db1ccfb8745b2daa42f457981ae08dba9 Mon Sep 17 00:00:00 2001
From: marcaiaf <mmachicao@m19r.de>
Date: Fri, 28 Dec 2018 16:20:30 +0100
Subject: [PATCH] IsReachable is the inverse of IsLimited (DRY). Includes unit
 tests

---
 src/net.cpp            |  6 +--
 src/test/net_tests.cpp | 89 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 4 deletions(-)

diff --git a/src/net.cpp b/src/net.cpp
index e595fb0b0..a0f66d06d 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -286,15 +286,13 @@ bool IsLocal(const CService& addr)
 /** check whether a given network is one we can probably connect to */
 bool IsReachable(enum Network net)
 {
-    LOCK(cs_mapLocalHost);
-    return !vfLimited[net];
+    return !IsLimited(net);
 }
 
 /** check whether a given address is in a network we can probably connect to */
 bool IsReachable(const CNetAddr& addr)
 {
-    enum Network net = addr.GetNetwork();
-    return IsReachable(net);
+    return IsReachable(addr.GetNetwork());
 }
 
 
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index e7a3c9634..4dc394b86 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -227,4 +227,93 @@ BOOST_AUTO_TEST_CASE(ipv4_peer_with_ipv6_addrMe_test)
     BOOST_CHECK(1);
 }
 
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_Network)
+{
+    SetLimited(NET_IPV4, true);
+    SetLimited(NET_IPV6, true);
+    SetLimited(NET_ONION, true);
+
+    BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), true);
+    BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), true);
+    BOOST_CHECK_EQUAL(IsLimited(NET_ONION), true);
+
+    BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), false);
+    BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), false);
+    BOOST_CHECK_EQUAL(IsReachable(NET_ONION), false);
+
+
+    SetLimited(NET_IPV4, false);
+    SetLimited(NET_IPV6, false);
+    SetLimited(NET_ONION, false);
+
+    BOOST_CHECK_EQUAL(IsLimited(NET_IPV4), false);
+    BOOST_CHECK_EQUAL(IsLimited(NET_IPV6), false);
+    BOOST_CHECK_EQUAL(IsLimited(NET_ONION), false);
+
+    BOOST_CHECK_EQUAL(IsReachable(NET_IPV4), true);
+    BOOST_CHECK_EQUAL(IsReachable(NET_IPV6), true);
+    BOOST_CHECK_EQUAL(IsReachable(NET_ONION), true);
+}
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_NetworkCaseUnroutableAndInternal)
+{
+    BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false);
+    BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
+
+    BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
+    BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+
+    SetLimited(NET_UNROUTABLE, true);
+    SetLimited(NET_INTERNAL, true);
+
+    BOOST_CHECK_EQUAL(IsLimited(NET_UNROUTABLE), false); // Ignored for both networks
+    BOOST_CHECK_EQUAL(IsLimited(NET_INTERNAL), false);
+
+    BOOST_CHECK_EQUAL(IsReachable(NET_UNROUTABLE), true);
+    BOOST_CHECK_EQUAL(IsReachable(NET_INTERNAL), true);
+}
+
+CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)
+{
+    unsigned char ip[] = {p1, p2, p3, p4};
+
+    struct sockaddr_in sa;
+    memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block
+    memcpy(&(sa.sin_addr), &ip, sizeof(ip));
+    return CNetAddr(sa.sin_addr);
+}
+
+
+BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)
+{
+    CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1
+
+    SetLimited(NET_IPV4, false);
+    BOOST_CHECK_EQUAL(IsLimited(addr), false);
+    BOOST_CHECK_EQUAL(IsReachable(addr), true);
+
+    SetLimited(NET_IPV4, true);
+    BOOST_CHECK_EQUAL(IsLimited(addr), true);
+    BOOST_CHECK_EQUAL(IsReachable(addr), false);
+
+    SetLimited(NET_IPV4, false); // have to reset this, because this is stateful.
+}
+
+
+BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)
+{
+    CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000
+
+    SetLimited(NET_IPV4, false);
+
+    BOOST_CHECK_EQUAL(IsLocal(addr), false);
+    BOOST_CHECK_EQUAL(AddLocal(addr, 1000), true);
+    BOOST_CHECK_EQUAL(IsLocal(addr), true);
+
+    RemoveLocal(addr);
+    BOOST_CHECK_EQUAL(IsLocal(addr), false);
+}
+
+
 BOOST_AUTO_TEST_SUITE_END()