mirror of
https://github.com/wownero/wownero.git
synced 2026-10-17 23:51:37 +02:00
p2p: group outbound IPv6 peers by /32
This commit is contained in:
+32
-3
@@ -38,6 +38,7 @@
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
@@ -126,6 +127,21 @@ namespace nodetool
|
||||
}
|
||||
}
|
||||
|
||||
using ipv6_peer_group = std::array<unsigned char, 4>;
|
||||
|
||||
inline boost::optional<ipv6_peer_group> get_ipv6_peer_group(const epee::net_utils::network_address& address)
|
||||
{
|
||||
if (address.get_type_id() != epee::net_utils::ipv6_network_address::get_type_id())
|
||||
return boost::none;
|
||||
|
||||
const boost::asio::ip::address_v6 ip = address.as<const epee::net_utils::ipv6_network_address>().ip();
|
||||
if (ip.is_v4_mapped())
|
||||
return boost::none;
|
||||
|
||||
const boost::asio::ip::address_v6::bytes_type bytes = ip.to_bytes();
|
||||
return ipv6_peer_group{{bytes[0], bytes[1], bytes[2], bytes[3]}};
|
||||
}
|
||||
//-----------------------------------------------------------------------------------
|
||||
template<class t_payload_net_handler>
|
||||
node_server<t_payload_net_handler>::~node_server()
|
||||
{
|
||||
@@ -1687,9 +1703,10 @@ namespace nodetool
|
||||
|
||||
const uint32_t next_needed_pruning_stripe = m_payload_handler.get_next_needed_pruning_stripe().second;
|
||||
|
||||
// Build a list of all distinct /24 subnets we are connected to now right now; to catch
|
||||
// Build a list of all distinct IPv4 /24 and IPv6 /32 groups we are connected to right now; to catch
|
||||
// any connection changes, re-build the list for every outer try loop pass
|
||||
std::set<uint32_t> connected_subnets;
|
||||
std::set<ipv6_peer_group> connected_ipv6_groups;
|
||||
const uint32_t subnet_mask = ntohl(0xffffff00);
|
||||
const bool is_public_zone = &zone == &m_network_zones.at(epee::net_utils::zone::public_);
|
||||
if (is_public_zone)
|
||||
@@ -1713,6 +1730,12 @@ namespace nodetool
|
||||
memcpy(&actual_ipv4, v4ip.to_bytes().data(), sizeof(actual_ipv4));
|
||||
connected_subnets.insert(actual_ipv4 & subnet_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
const boost::optional<ipv6_peer_group> group = get_ipv6_peer_group(na);
|
||||
if (group)
|
||||
connected_ipv6_groups.insert(*group);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
@@ -1742,8 +1765,9 @@ namespace nodetool
|
||||
std::shuffle(shuffled_indexes.begin(), shuffled_indexes.end(), crypto::random_device{});
|
||||
|
||||
// Step 2: Deduplicate by only taking 1 candidate from each /24 subnet that occurs, the FIRST
|
||||
// candidate seen from each subnet within the now random order
|
||||
// candidate seen from each subnet within the now random order. Native IPv6 peers use /32 groups.
|
||||
std::set<uint32_t> subnets = connected_subnets;
|
||||
std::set<ipv6_peer_group> ipv6_groups = connected_ipv6_groups;
|
||||
for (size_t index : shuffled_indexes)
|
||||
{
|
||||
const peerlist_entry &peer = peers.at(index);
|
||||
@@ -1772,7 +1796,12 @@ namespace nodetool
|
||||
if (take)
|
||||
subnets.insert(subnet);
|
||||
}
|
||||
// else 'take' stays true, we will take an IPv6 address that is not V4 mapped
|
||||
else
|
||||
{
|
||||
const boost::optional<ipv6_peer_group> group = get_ipv6_peer_group(na);
|
||||
if (group)
|
||||
take = ipv6_groups.insert(*group).second;
|
||||
}
|
||||
}
|
||||
if (take)
|
||||
subnet_peers.push_back(peer);
|
||||
|
||||
@@ -119,6 +119,27 @@ public:
|
||||
|
||||
typedef nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<test_core>> Server;
|
||||
|
||||
TEST(node_server, ipv6_peer_group)
|
||||
{
|
||||
const auto make_ipv6 = [](const char* ip) {
|
||||
return epee::net_utils::network_address{
|
||||
epee::net_utils::ipv6_network_address{boost::asio::ip::make_address_v6(ip), 18080}
|
||||
};
|
||||
};
|
||||
|
||||
const boost::optional<nodetool::ipv6_peer_group> first = nodetool::get_ipv6_peer_group(make_ipv6("2001:db8:1::1"));
|
||||
const boost::optional<nodetool::ipv6_peer_group> same = nodetool::get_ipv6_peer_group(make_ipv6("2001:db8:ffff::1"));
|
||||
const boost::optional<nodetool::ipv6_peer_group> different = nodetool::get_ipv6_peer_group(make_ipv6("2001:db9::1"));
|
||||
|
||||
ASSERT_TRUE(first);
|
||||
ASSERT_TRUE(same);
|
||||
ASSERT_TRUE(different);
|
||||
EXPECT_EQ(*first, *same);
|
||||
EXPECT_NE(*first, *different);
|
||||
EXPECT_FALSE(nodetool::get_ipv6_peer_group(make_ipv6("::ffff:192.0.2.1")));
|
||||
EXPECT_FALSE(nodetool::get_ipv6_peer_group(MAKE_IPV4_ADDRESS(192, 0, 2, 1)));
|
||||
}
|
||||
|
||||
static bool is_blocked(Server &server, const epee::net_utils::network_address &address, time_t *t = NULL)
|
||||
{
|
||||
std::map<std::string, time_t> hosts = server.get_blocked_hosts();
|
||||
|
||||
Reference in New Issue
Block a user