aboutsummaryrefslogtreecommitdiff
path: root/src/p2p/net_node.inl
diff options
context:
space:
mode:
Diffstat (limited to 'src/p2p/net_node.inl')
-rw-r--r--src/p2p/net_node.inl1136
1 files changed, 703 insertions, 433 deletions
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index c594984d4..f32b9e990 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2018, The Monero Project
+// Copyright (c) 2014-2019, The Monero Project
//
// All rights reserved.
//
@@ -31,25 +31,34 @@
// IP blocking adapted from Boolberry
#include <algorithm>
+#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/filesystem/operations.hpp>
+#include <boost/optional/optional.hpp>
#include <boost/thread/thread.hpp>
#include <boost/uuid/uuid_io.hpp>
-#include <boost/bind.hpp>
#include <atomic>
+#include <functional>
+#include <limits>
+#include <memory>
+#include <tuple>
+#include <vector>
#include "version.h"
#include "string_tools.h"
#include "common/util.h"
#include "common/dns_utils.h"
#include "common/pruning.h"
+#include "net/error.h"
#include "net/net_helper.h"
#include "math_helper.h"
+#include "misc_log_ex.h"
#include "p2p_protocol_defs.h"
-#include "net_peerlist_boost_serialization.h"
#include "net/local_ip.h"
#include "crypto/crypto.h"
#include "storages/levin_abstract_invoke2.h"
#include "cryptonote_core/cryptonote_core.h"
+#include "net/parse.h"
#include <miniupnp/miniupnpc/miniupnpc.h>
#include <miniupnp/miniupnpc/upnpcommands.h>
@@ -64,6 +73,20 @@
namespace nodetool
{
+ template<class t_payload_net_handler>
+ node_server<t_payload_net_handler>::~node_server()
+ {
+ // tcp server uses io_service in destructor, and every zone uses
+ // io_service from public zone.
+ for (auto current = m_network_zones.begin(); current != m_network_zones.end(); /* below */)
+ {
+ if (current->first != epee::net_utils::zone::public_)
+ current = m_network_zones.erase(current);
+ else
+ ++current;
+ }
+ }
+ //-----------------------------------------------------------------------------------
inline bool append_net_address(std::vector<epee::net_utils::network_address> & seed_nodes, std::string const & addr, uint16_t default_port);
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -77,6 +100,8 @@ namespace nodetool
command_line::add_arg(desc, arg_p2p_add_priority_node);
command_line::add_arg(desc, arg_p2p_add_exclusive_node);
command_line::add_arg(desc, arg_p2p_seed_node);
+ command_line::add_arg(desc, arg_proxy);
+ command_line::add_arg(desc, arg_anonymous_inbound);
command_line::add_arg(desc, arg_p2p_hide_my_port);
command_line::add_arg(desc, arg_no_igd);
command_line::add_arg(desc, arg_out_peers);
@@ -91,84 +116,14 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::init_config()
{
- //
TRY_ENTRY();
- std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME;
- std::ifstream p2p_data;
- p2p_data.open( state_file_path , std::ios_base::binary | std::ios_base::in);
- if(!p2p_data.fail())
- {
- try
- {
- // first try reading in portable mode
- boost::archive::portable_binary_iarchive a(p2p_data);
- a >> *this;
- }
- catch (...)
- {
- // if failed, try reading in unportable mode
- boost::filesystem::copy_file(state_file_path, state_file_path + ".unportable", boost::filesystem::copy_option::overwrite_if_exists);
- p2p_data.close();
- p2p_data.open( state_file_path , std::ios_base::binary | std::ios_base::in);
- if(!p2p_data.fail())
- {
- try
- {
- boost::archive::binary_iarchive a(p2p_data);
- a >> *this;
- }
- catch (const std::exception &e)
- {
- MWARNING("Failed to load p2p config file, falling back to default config");
- m_peerlist = peerlist_manager(); // it was probably half clobbered by the failed load
- make_default_config();
- }
- }
- else
- {
- make_default_config();
- }
- }
- }else
- {
- make_default_config();
- }
-
-#ifdef CRYPTONOTE_PRUNING_DEBUG_SPOOF_SEED
- std::list<peerlist_entry> plw;
- while (m_peerlist.get_white_peers_count())
- {
- plw.push_back(peerlist_entry());
- m_peerlist.get_white_peer_by_index(plw.back(), 0);
- m_peerlist.remove_from_peer_white(plw.back());
- }
- for (auto &e:plw)
- m_peerlist.append_with_peer_white(e);
-
- std::list<peerlist_entry> plg;
- while (m_peerlist.get_gray_peers_count())
- {
- plg.push_back(peerlist_entry());
- m_peerlist.get_gray_peer_by_index(plg.back(), 0);
- m_peerlist.remove_from_peer_gray(plg.back());
- }
- for (auto &e:plg)
- m_peerlist.append_with_peer_gray(e);
-#endif
-
- // always recreate a new peer id
- make_default_peer_id();
-
- //at this moment we have hardcoded config
- m_config.m_net_config.handshake_interval = P2P_DEFAULT_HANDSHAKE_INTERVAL;
- m_config.m_net_config.packet_max_size = P2P_DEFAULT_PACKET_MAX_SIZE; //20 MB limit
- m_config.m_net_config.config_id = 0; // initial config
- m_config.m_net_config.connection_timeout = P2P_DEFAULT_CONNECTION_TIMEOUT;
- m_config.m_net_config.ping_connection_timeout = P2P_DEFAULT_PING_CONNECTION_TIMEOUT;
- m_config.m_net_config.send_peerlist_sz = P2P_DEFAULT_PEERS_IN_HANDSHAKE;
- m_config.m_support_flags = P2P_SUPPORT_FLAGS;
+ auto storage = peerlist_storage::open(m_config_folder + "/" + P2P_NET_DATA_FILENAME);
+ if (storage)
+ m_peerlist_storage = std::move(*storage);
+ m_network_zones[epee::net_utils::zone::public_].m_config.m_support_flags = P2P_SUPPORT_FLAGS;
m_first_connection_maker_call = true;
+
CATCH_ENTRY_L0("node_server::init_config", false);
return true;
}
@@ -176,17 +131,26 @@ namespace nodetool
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f)
{
- m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){
- return f(cntx, cntx.peer_id, cntx.support_flags);
- });
+ for(auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntx){
+ return f(cntx, cntx.peer_id, cntx.support_flags);
+ });
+ }
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::for_connection(const boost::uuids::uuid &connection_id, std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f)
{
- return m_net_server.get_config_object().for_connection(connection_id, [&](p2p_connection_context& cntx){
- return f(cntx, cntx.peer_id, cntx.support_flags);
- });
+ for(auto& zone : m_network_zones)
+ {
+ const bool result = zone.second.m_net_server.get_config_object().for_connection(connection_id, [&](p2p_connection_context& cntx){
+ return f(cntx, cntx.peer_id, cntx.support_flags);
+ });
+ if (result)
+ return true;
+ }
+ return false;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
@@ -206,36 +170,33 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::make_default_peer_id()
- {
- m_config.m_peer_id = crypto::rand<uint64_t>();
- return true;
- }
- //-----------------------------------------------------------------------------------
- template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::make_default_config()
- {
- return make_default_peer_id();
- }
- //-----------------------------------------------------------------------------------
- template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::block_host(const epee::net_utils::network_address &addr, time_t seconds)
{
+ if(!addr.is_blockable())
+ return false;
+
CRITICAL_REGION_LOCAL(m_blocked_hosts_lock);
m_blocked_hosts[addr.host_str()] = time(nullptr) + seconds;
- // drop any connection to that IP
- std::list<boost::uuids::uuid> conns;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ // drop any connection to that address. This should only have to look into
+ // the zone related to the connection, but really make sure everything is
+ // swept ...
+ std::vector<boost::uuids::uuid> conns;
+ for(auto& zone : m_network_zones)
{
- if (cntxt.m_remote_address.is_same_host(addr))
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- conns.push_back(cntxt.m_connection_id);
- }
- return true;
- });
- for (const auto &c: conns)
- m_net_server.get_config_object().close(c);
+ if (cntxt.m_remote_address.is_same_host(addr))
+ {
+ conns.push_back(cntxt.m_connection_id);
+ }
+ return true;
+ });
+ for (const auto &c: conns)
+ zone.second.m_net_server.get_config_object().close(c);
+
+ conns.clear();
+ }
MCLOG_CYAN(el::Level::Info, "global", "Host " << addr.host_str() << " blocked.");
return true;
@@ -256,6 +217,9 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address)
{
+ if(!address.is_blockable())
+ return false;
+
CRITICAL_REGION_LOCAL(m_host_fails_score_lock);
uint64_t fails = ++m_host_fails_score[address.host_str()];
MDEBUG("Host " << address.host_str() << " fail score=" << fails);
@@ -270,12 +234,6 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::parse_peer_from_string(epee::net_utils::network_address& pe, const std::string& node_addr, uint16_t default_port)
- {
- return epee::net_utils::create_network_address(pe, node_addr, default_port);
- }
- //-----------------------------------------------------------------------------------
- template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::handle_command_line(
const boost::program_options::variables_map& vm
)
@@ -284,8 +242,11 @@ namespace nodetool
bool stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
m_nettype = testnet ? cryptonote::TESTNET : stagenet ? cryptonote::STAGENET : cryptonote::MAINNET;
- m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip);
- m_port = command_line::get_arg(vm, arg_p2p_bind_port);
+ network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_];
+ public_zone.m_connect = &public_connect;
+ public_zone.m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip);
+ public_zone.m_port = command_line::get_arg(vm, arg_p2p_bind_port);
+ public_zone.m_can_pingback = true;
m_external_port = command_line::get_arg(vm, arg_p2p_external_port);
m_allow_local_ip = command_line::get_arg(vm, arg_p2p_allow_local_ip);
m_no_igd = command_line::get_arg(vm, arg_no_igd);
@@ -299,14 +260,20 @@ namespace nodetool
nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe);
pe.id = crypto::rand<uint64_t>();
const uint16_t default_port = cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT;
- bool r = parse_peer_from_string(pe.adr, pr_str, default_port);
- if (r)
+ expect<epee::net_utils::network_address> adr = net::get_network_address(pr_str, default_port);
+ if (adr)
{
- m_command_line_peers.push_back(pe);
+ add_zone(adr->get_zone());
+ pe.adr = std::move(*adr);
+ m_command_line_peers.push_back(std::move(pe));
continue;
}
+ CHECK_AND_ASSERT_MES(
+ adr == net::error::unsupported_address, false, "Bad address (\"" << pr_str << "\"): " << adr.error().message()
+ );
+
std::vector<epee::net_utils::network_address> resolved_addrs;
- r = append_net_address(resolved_addrs, pr_str, default_port);
+ bool r = append_net_address(resolved_addrs, pr_str, default_port);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse or resolve address from string: " << pr_str);
for (const epee::net_utils::network_address& addr : resolved_addrs)
{
@@ -343,10 +310,13 @@ namespace nodetool
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
m_hide_my_port = true;
- if ( !set_max_out_peers(vm, command_line::get_arg(vm, arg_out_peers) ) )
+ if ( !set_max_out_peers(public_zone, command_line::get_arg(vm, arg_out_peers) ) )
return false;
+ else
+ m_payload_handler.set_max_out_peers(public_zone.m_config.m_net_config.max_out_connection_count);
+
- if ( !set_max_in_peers(vm, command_line::get_arg(vm, arg_in_peers) ) )
+ if ( !set_max_in_peers(public_zone, command_line::get_arg(vm, arg_in_peers) ) )
return false;
if ( !set_tos_flag(vm, command_line::get_arg(vm, arg_tos_flag) ) )
@@ -361,6 +331,58 @@ namespace nodetool
if ( !set_rate_limit(vm, command_line::get_arg(vm, arg_limit_rate) ) )
return false;
+
+ auto proxies = get_proxies(vm);
+ if (!proxies)
+ return false;
+
+ for (auto& proxy : *proxies)
+ {
+ network_zone& zone = add_zone(proxy.zone);
+ if (zone.m_connect != nullptr)
+ {
+ MERROR("Listed --" << arg_proxy.name << " twice with " << epee::net_utils::zone_to_string(proxy.zone));
+ return false;
+ }
+ zone.m_connect = &socks_connect;
+ zone.m_proxy_address = std::move(proxy.address);
+
+ if (!set_max_out_peers(zone, proxy.max_connections))
+ return false;
+ }
+
+ for (const auto& zone : m_network_zones)
+ {
+ if (zone.second.m_connect == nullptr)
+ {
+ MERROR("Set outgoing peer for " << epee::net_utils::zone_to_string(zone.first) << " but did not set --" << arg_proxy.name);
+ return false;
+ }
+ }
+
+ auto inbounds = get_anonymous_inbounds(vm);
+ if (!inbounds)
+ return false;
+
+ for (auto& inbound : *inbounds)
+ {
+ network_zone& zone = add_zone(inbound.our_address.get_zone());
+
+ if (!zone.m_bind_ip.empty())
+ {
+ MERROR("Listed --" << arg_anonymous_inbound.name << " twice with " << epee::net_utils::zone_to_string(inbound.our_address.get_zone()) << " network");
+ return false;
+ }
+
+ zone.m_bind_ip = std::move(inbound.local_ip);
+ zone.m_port = std::move(inbound.local_port);
+ zone.m_net_server.set_default_remote(std::move(inbound.default_remote));
+ zone.m_our_address = std::move(inbound.our_address);
+
+ if (!set_max_in_peers(zone, inbound.max_connections))
+ return false;
+ }
+
return true;
}
//-----------------------------------------------------------------------------------
@@ -442,7 +464,17 @@ namespace nodetool
}
return full_addrs;
}
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ typename node_server<t_payload_net_handler>::network_zone& node_server<t_payload_net_handler>::add_zone(const epee::net_utils::zone zone)
+ {
+ const auto zone_ = m_network_zones.lower_bound(zone);
+ if (zone_ != m_network_zones.end() && zone_->first == zone)
+ return zone_->second;
+ network_zone& public_zone = m_network_zones[epee::net_utils::zone::public_];
+ return m_network_zones.emplace_hint(zone_, std::piecewise_construct, std::make_tuple(zone), std::tie(public_zone.m_net_server.get_io_service()))->second;
+ }
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
@@ -559,45 +591,82 @@ namespace nodetool
MDEBUG("Number of seed nodes: " << m_seed_nodes.size());
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
+ network_zone& public_zone = m_network_zones.at(epee::net_utils::zone::public_);
- if ((m_nettype == cryptonote::MAINNET && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
- || (m_nettype == cryptonote::TESTNET && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))
- || (m_nettype == cryptonote::STAGENET && m_port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) {
- m_config_folder = m_config_folder + "/" + m_port;
+ if ((m_nettype == cryptonote::MAINNET && public_zone.m_port != std::to_string(::config::P2P_DEFAULT_PORT))
+ || (m_nettype == cryptonote::TESTNET && public_zone.m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))
+ || (m_nettype == cryptonote::STAGENET && public_zone.m_port != std::to_string(::config::stagenet::P2P_DEFAULT_PORT))) {
+ m_config_folder = m_config_folder + "/" + public_zone.m_port;
}
res = init_config();
CHECK_AND_ASSERT_MES(res, false, "Failed to init config.");
- res = m_peerlist.init(m_allow_local_ip);
- CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist.");
+ for (auto& zone : m_network_zones)
+ {
+ res = zone.second.m_peerlist.init(m_peerlist_storage.take_zone(zone.first), m_allow_local_ip);
+ CHECK_AND_ASSERT_MES(res, false, "Failed to init peerlist.");
+ }
+ for(const auto& p: m_command_line_peers)
+ m_network_zones.at(p.adr.get_zone()).m_peerlist.append_with_peer_white(p);
- for(auto& p: m_command_line_peers)
- m_peerlist.append_with_peer_white(p);
+// all peers are now setup
+#ifdef CRYPTONOTE_PRUNING_DEBUG_SPOOF_SEED
+ for (auto& zone : m_network_zones)
+ {
+ std::list<peerlist_entry> plw;
+ while (zone.second.m_peerlist.get_white_peers_count())
+ {
+ plw.push_back(peerlist_entry());
+ zone.second.m_peerlist.get_white_peer_by_index(plw.back(), 0);
+ zone.second.m_peerlist.remove_from_peer_white(plw.back());
+ }
+ for (auto &e:plw)
+ zone.second.m_peerlist.append_with_peer_white(e);
+
+ std::list<peerlist_entry> plg;
+ while (zone.second.m_peerlist.get_gray_peers_count())
+ {
+ plg.push_back(peerlist_entry());
+ zone.second.m_peerlist.get_gray_peer_by_index(plg.back(), 0);
+ zone.second.m_peerlist.remove_from_peer_gray(plg.back());
+ }
+ for (auto &e:plg)
+ zone.second.m_peerlist.append_with_peer_gray(e);
+ }
+#endif
//only in case if we really sure that we have external visible ip
m_have_address = true;
- m_ip_address = 0;
m_last_stat_request_time = 0;
//configure self
- m_net_server.set_threads_prefix("P2P");
- m_net_server.get_config_object().set_handler(this);
- m_net_server.get_config_object().m_invoke_timeout = P2P_DEFAULT_INVOKE_TIMEOUT;
- m_net_server.set_connection_filter(this);
+
+ public_zone.m_net_server.set_threads_prefix("P2P"); // all zones use these threads/asio::io_service
// from here onwards, it's online stuff
if (m_offline)
return res;
//try to bind
- MINFO("Binding on " << m_bind_ip << ":" << m_port);
- res = m_net_server.init_server(m_port, m_bind_ip);
- CHECK_AND_ASSERT_MES(res, false, "Failed to bind server");
+ m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_disabled;
+ for (auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.get_config_object().set_handler(this);
+ zone.second.m_net_server.get_config_object().m_invoke_timeout = P2P_DEFAULT_INVOKE_TIMEOUT;
+
+ if (!zone.second.m_bind_ip.empty())
+ {
+ zone.second.m_net_server.set_connection_filter(this);
+ MINFO("Binding on " << zone.second.m_bind_ip << ":" << zone.second.m_port);
+ res = zone.second.m_net_server.init_server(zone.second.m_port, zone.second.m_bind_ip, epee::net_utils::ssl_support_t::e_ssl_support_disabled);
+ CHECK_AND_ASSERT_MES(res, false, "Failed to bind server");
+ }
+ }
- m_listening_port = m_net_server.get_binded_port();
- MLOG_GREEN(el::Level::Info, "Net service bound to " << m_bind_ip << ":" << m_listening_port);
+ m_listening_port = public_zone.m_net_server.get_binded_port();
+ MLOG_GREEN(el::Level::Info, "Net service bound to " << public_zone.m_bind_ip << ":" << m_listening_port);
if(m_external_port)
MDEBUG("External port defined as " << m_external_port);
@@ -621,44 +690,45 @@ namespace nodetool
mPeersLoggerThread.reset(new boost::thread([&]()
{
_note("Thread monitor number of peers - start");
- while (!is_closing && !m_net_server.is_stop_signal_sent())
+ const network_zone& public_zone = m_network_zones.at(epee::net_utils::zone::public_);
+ while (!is_closing && !public_zone.m_net_server.is_stop_signal_sent())
{ // main loop of thread
//number_of_peers = m_net_server.get_config_object().get_connections_count();
- unsigned int number_of_in_peers = 0;
- unsigned int number_of_out_peers = 0;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ for (auto& zone : m_network_zones)
{
- if (cntxt.m_is_income)
- {
- ++number_of_in_peers;
- }
- else
+ unsigned int number_of_in_peers = 0;
+ unsigned int number_of_out_peers = 0;
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- ++number_of_out_peers;
- }
- return true;
- }); // lambda
-
- m_current_number_of_in_peers = number_of_in_peers;
- m_current_number_of_out_peers = number_of_out_peers;
-
+ if (cntxt.m_is_income)
+ {
+ ++number_of_in_peers;
+ }
+ else
+ {
+ ++number_of_out_peers;
+ }
+ return true;
+ }); // lambda
+ zone.second.m_current_number_of_in_peers = number_of_in_peers;
+ zone.second.m_current_number_of_out_peers = number_of_out_peers;
+ }
boost::this_thread::sleep_for(boost::chrono::seconds(1));
} // main loop of thread
_note("Thread monitor number of peers - done");
})); // lambda
+ network_zone& public_zone = m_network_zones.at(epee::net_utils::zone::public_);
+ public_zone.m_net_server.add_idle_handler(boost::bind(&node_server<t_payload_net_handler>::idle_worker, this), 1000);
+ public_zone.m_net_server.add_idle_handler(boost::bind(&t_payload_net_handler::on_idle, &m_payload_handler), 1000);
+
//here you can set worker threads count
int thrds_count = 10;
-
- m_net_server.add_idle_handler(boost::bind(&node_server<t_payload_net_handler>::idle_worker, this), 1000);
- m_net_server.add_idle_handler(boost::bind(&t_payload_net_handler::on_idle, &m_payload_handler), 1000);
-
boost::thread::attributes attrs;
attrs.set_stack_size(THREAD_STACK_SIZE);
-
//go to loop
MINFO("Run net_service loop( " << thrds_count << " threads)...");
- if(!m_net_server.run_server(thrds_count, true, attrs))
+ if(!public_zone.m_net_server.run_server(thrds_count, true, attrs))
{
LOG_ERROR("Failed to run net tcp server!");
}
@@ -666,23 +736,34 @@ namespace nodetool
MINFO("net_service loop stopped.");
return true;
}
-
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ uint64_t node_server<t_payload_net_handler>::get_public_connections_count()
+ {
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone == m_network_zones.end())
+ return 0;
+ return public_zone->second.m_net_server.get_config_object().get_connections_count();
+ }
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
uint64_t node_server<t_payload_net_handler>::get_connections_count()
{
- return m_net_server.get_config_object().get_connections_count();
+ std::uint64_t count = 0;
+ for (auto& zone : m_network_zones)
+ count += zone.second.m_net_server.get_config_object().get_connections_count();
+ return count;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::deinit()
{
kill();
- m_peerlist.deinit();
if (!m_offline)
{
- m_net_server.deinit_server();
+ for(auto& zone : m_network_zones)
+ zone.second.m_net_server.deinit_server();
// remove UPnP port mapping
if(!m_no_igd)
delete_upnp_port_mapping(m_listening_port);
@@ -693,28 +774,25 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::store_config()
{
-
TRY_ENTRY();
+
if (!tools::create_directories_if_necessary(m_config_folder))
{
- MWARNING("Failed to create data directory: " << m_config_folder);
+ MWARNING("Failed to create data directory \"" << m_config_folder);
return false;
}
- std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME;
- std::ofstream p2p_data;
- p2p_data.open( state_file_path , std::ios_base::binary | std::ios_base::out| std::ios::trunc);
- if(p2p_data.fail())
+ peerlist_types active{};
+ for (auto& zone : m_network_zones)
+ zone.second.m_peerlist.get_peerlist(active);
+
+ const std::string state_file_path = m_config_folder + "/" + P2P_NET_DATA_FILENAME;
+ if (!m_peerlist_storage.store(state_file_path, active))
{
MWARNING("Failed to save config to file " << state_file_path);
return false;
- };
-
- boost::archive::portable_binary_oarchive a(p2p_data);
- a << *this;
- return true;
- CATCH_ENTRY_L0("blockchain_storage::save", false);
-
+ }
+ CATCH_ENTRY_L0("node_server::store", false);
return true;
}
//-----------------------------------------------------------------------------------
@@ -722,36 +800,38 @@ namespace nodetool
bool node_server<t_payload_net_handler>::send_stop_signal()
{
MDEBUG("[node] sending stop signal");
- m_net_server.send_stop_signal();
+ for (auto& zone : m_network_zones)
+ zone.second.m_net_server.send_stop_signal();
MDEBUG("[node] Stop signal sent");
- std::list<boost::uuids::uuid> connection_ids;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) {
- connection_ids.push_back(cntxt.m_connection_id);
- return true;
- });
- for (const auto &connection_id: connection_ids)
- m_net_server.get_config_object().close(connection_id);
-
+ for (auto& zone : m_network_zones)
+ {
+ std::list<boost::uuids::uuid> connection_ids;
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) {
+ connection_ids.push_back(cntxt.m_connection_id);
+ return true;
+ });
+ for (const auto &connection_id: connection_ids)
+ zone.second.m_net_server.get_config_object().close(connection_id);
+ }
m_payload_handler.stop();
-
return true;
}
//-----------------------------------------------------------------------------------
-
-
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context_, bool just_take_peerlist)
{
+ network_zone& zone = m_network_zones.at(context_.m_remote_address.get_zone());
+
typename COMMAND_HANDSHAKE::request arg;
typename COMMAND_HANDSHAKE::response rsp;
- get_local_node_data(arg.node_data);
+ get_local_node_data(arg.node_data, zone);
m_payload_handler.get_payload_sync_data(arg.payload_data);
epee::simple_event ev;
std::atomic<bool> hsh_result(false);
- bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(),
+ bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, zone.m_net_server.get_config_object(),
[this, &pi, &ev, &hsh_result, &just_take_peerlist, &context_](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
{
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();});
@@ -785,13 +865,17 @@ namespace nodetool
}
pi = context.peer_id = rsp.node_data.peer_id;
- m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address, context.m_pruning_seed);
+ m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address, context.m_pruning_seed);
- if(rsp.node_data.peer_id == m_config.m_peer_id)
+ // move
+ for (auto const& zone : m_network_zones)
{
- LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
- hsh_result = false;
- return;
+ if(rsp.node_data.peer_id == zone.second.m_config.m_peer_id)
+ {
+ LOG_DEBUG_CC(context, "Connection to self detected, dropping connection");
+ hsh_result = false;
+ return;
+ }
}
LOG_INFO_CC(context, "New connection handshaked, pruning seed " << epee::string_tools::to_string_hex(context.m_pruning_seed));
LOG_DEBUG_CC(context, " COMMAND_HANDSHAKE INVOKED OK");
@@ -810,7 +894,7 @@ namespace nodetool
if(!hsh_result)
{
LOG_WARNING_CC(context_, "COMMAND_HANDSHAKE Failed");
- m_net_server.get_config_object().close(context_.m_connection_id);
+ m_network_zones.at(context_.m_remote_address.get_zone()).m_net_server.get_config_object().close(context_.m_connection_id);
}
else
{
@@ -829,7 +913,8 @@ namespace nodetool
typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg);
m_payload_handler.get_payload_sync_data(arg.payload_data);
- bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(),
+ network_zone& zone = m_network_zones.at(context_.m_remote_address.get_zone());
+ bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, zone.m_net_server.get_config_object(),
[this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
{
context.m_in_timedsync = false;
@@ -842,11 +927,11 @@ namespace nodetool
if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.local_time, context))
{
LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection.");
- m_net_server.get_config_object().close(context.m_connection_id );
+ m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id );
add_host_fail(context.m_remote_address);
}
if(!context.m_is_income)
- m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed);
+ m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address, context.m_pruning_seed);
m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false);
});
@@ -874,53 +959,61 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::is_peer_used(const peerlist_entry& peer)
{
-
- if(m_config.m_peer_id == peer.id)
- return true;//dont make connections to ourself
+ for(const auto& zone : m_network_zones)
+ if(zone.second.m_config.m_peer_id == peer.id)
+ return true;//dont make connections to ourself
bool used = false;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ for(auto& zone : m_network_zones)
{
- if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- used = true;
- return false;//stop enumerating
- }
- return true;
- });
+ if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
+ {
+ used = true;
+ return false;//stop enumerating
+ }
+ return true;
+ });
- return used;
+ if(used)
+ return true;
+ }
+ return false;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::is_peer_used(const anchor_peerlist_entry& peer)
{
- if(m_config.m_peer_id == peer.id) {
- return true;//dont make connections to ourself
- }
-
- bool used = false;
-
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
- {
- if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
- {
- used = true;
-
- return false;//stop enumerating
+ for(auto& zone : m_network_zones) {
+ if(zone.second.m_config.m_peer_id == peer.id) {
+ return true;//dont make connections to ourself
}
-
- return true;
- });
-
- return used;
+ bool used = false;
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address))
+ {
+ used = true;
+ return false;//stop enumerating
+ }
+ return true;
+ });
+ if (used)
+ return true;
+ }
+ return false;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::is_addr_connected(const epee::net_utils::network_address& peer)
{
+ const auto zone = m_network_zones.find(peer.get_zone());
+ if (zone == m_network_zones.end())
+ return false;
+
bool connected = false;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ zone->second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
if(!cntxt.m_is_income && peer == cntxt.m_remote_address)
{
@@ -945,47 +1038,44 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp)
{
- if (m_current_number_of_out_peers == m_config.m_net_config.max_out_connection_count) // out peers limit
+ network_zone& zone = m_network_zones.at(na.get_zone());
+ if (zone.m_connect == nullptr) // outgoing connections in zone not possible
+ return false;
+
+ if (zone.m_current_number_of_out_peers == zone.m_config.m_net_config.max_out_connection_count) // out peers limit
{
return false;
}
- else if (m_current_number_of_out_peers > m_config.m_net_config.max_out_connection_count)
+ else if (zone.m_current_number_of_out_peers > zone.m_config.m_net_config.max_out_connection_count)
{
- m_net_server.get_config_object().del_out_connections(1);
- m_current_number_of_out_peers --; // atomic variable, update time = 1s
+ zone.m_net_server.get_config_object().del_out_connections(1);
+ --(zone.m_current_number_of_out_peers); // atomic variable, update time = 1s
return false;
}
+
+
MDEBUG("Connecting to " << na.str() << "(peer_type=" << peer_type << ", last_seen: "
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
<< ")...");
- CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false,
- "Only IPv4 addresses are supported here");
- const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>();
-
- typename net_server::t_connection_context con = AUTO_VAL_INIT(con);
- con.m_anchor = peer_type == anchor;
- bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
- epee::string_tools::num_to_string_fast(ipv4.port()),
- m_config.m_net_config.connection_timeout,
- con);
-
- if(!res)
+ auto con = zone.m_connect(zone, na, m_ssl_support);
+ if(!con)
{
bool is_priority = is_priority_node(na);
- LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str()
+ LOG_PRINT_CC_PRIORITY_NODE(is_priority, bool(con), "Connect failed to " << na.str()
/*<< ", try " << try_count*/);
//m_peerlist.set_peer_unreachable(pe);
return false;
}
+ con->m_anchor = peer_type == anchor;
peerid_type pi = AUTO_VAL_INIT(pi);
- res = do_handshake_with_peer(pi, con, just_take_peerlist);
+ bool res = do_handshake_with_peer(pi, *con, just_take_peerlist);
if(!res)
{
bool is_priority = is_priority_node(na);
- LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer "
+ LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer "
<< na.str()
/*<< ", try " << try_count*/);
return false;
@@ -993,8 +1083,8 @@ namespace nodetool
if(just_take_peerlist)
{
- m_net_server.get_config_object().close(con.m_connection_id);
- LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK AND CLOSED.");
+ zone.m_net_server.get_config_object().close(con->m_connection_id);
+ LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -1004,8 +1094,8 @@ namespace nodetool
time_t last_seen;
time(&last_seen);
pe_local.last_seen = static_cast<int64_t>(last_seen);
- pe_local.pruning_seed = con.m_pruning_seed;
- m_peerlist.append_with_peer_white(pe_local);
+ pe_local.pruning_seed = con->m_pruning_seed;
+ zone.m_peerlist.append_with_peer_white(pe_local);
//update last seen and push it to peerlist manager
anchor_peerlist_entry ape = AUTO_VAL_INIT(ape);
@@ -1013,52 +1103,46 @@ namespace nodetool
ape.id = pi;
ape.first_seen = first_seen_stamp ? first_seen_stamp : time(nullptr);
- m_peerlist.append_with_peer_anchor(ape);
+ zone.m_peerlist.append_with_peer_anchor(ape);
- LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK.");
+ LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK.");
return true;
}
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::check_connection_and_handshake_with_peer(const epee::net_utils::network_address& na, uint64_t last_seen_stamp)
{
+ network_zone& zone = m_network_zones.at(na.get_zone());
+ if (zone.m_connect == nullptr)
+ return false;
+
LOG_PRINT_L1("Connecting to " << na.str() << "(last_seen: "
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
<< ")...");
- CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::ID, false,
- "Only IPv4 addresses are supported here");
- const epee::net_utils::ipv4_network_address &ipv4 = na.as<epee::net_utils::ipv4_network_address>();
-
- typename net_server::t_connection_context con = AUTO_VAL_INIT(con);
- con.m_anchor = false;
- bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
- epee::string_tools::num_to_string_fast(ipv4.port()),
- m_config.m_net_config.connection_timeout,
- con);
-
- if (!res) {
+ auto con = zone.m_connect(zone, na, m_ssl_support);
+ if (!con) {
bool is_priority = is_priority_node(na);
- LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str());
+ LOG_PRINT_CC_PRIORITY_NODE(is_priority, p2p_connection_context{}, "Connect failed to " << na.str());
return false;
}
+ con->m_anchor = false;
peerid_type pi = AUTO_VAL_INIT(pi);
- res = do_handshake_with_peer(pi, con, true);
-
+ const bool res = do_handshake_with_peer(pi, *con, true);
if (!res) {
bool is_priority = is_priority_node(na);
- LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " << na.str());
+ LOG_PRINT_CC_PRIORITY_NODE(is_priority, *con, "Failed to HANDSHAKE with peer " << na.str());
return false;
}
- m_net_server.get_config_object().close(con.m_connection_id);
+ zone.m_net_server.get_config_object().close(con->m_connection_id);
- LOG_DEBUG_CC(con, "CONNECTION HANDSHAKED OK AND CLOSED.");
+ LOG_DEBUG_CC(*con, "CONNECTION HANDSHAKED OK AND CLOSED.");
return true;
}
@@ -1115,7 +1199,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(bool use_white_list)
+ bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(network_zone& zone, bool use_white_list)
{
size_t max_random_index = 0;
@@ -1123,7 +1207,7 @@ namespace nodetool
size_t try_count = 0;
size_t rand_count = 0;
- while(rand_count < (max_random_index+1)*3 && try_count < 10 && !m_net_server.is_stop_signal_sent())
+ while(rand_count < (max_random_index+1)*3 && try_count < 10 && !zone.m_net_server.is_stop_signal_sent())
{
++rand_count;
size_t random_index;
@@ -1132,7 +1216,7 @@ namespace nodetool
std::deque<size_t> filtered;
const size_t limit = use_white_list ? 20 : std::numeric_limits<size_t>::max();
size_t idx = 0;
- m_peerlist.foreach (use_white_list, [&filtered, &idx, limit, next_needed_pruning_stripe](const peerlist_entry &pe){
+ zone.m_peerlist.foreach (use_white_list, [&filtered, &idx, limit, next_needed_pruning_stripe](const peerlist_entry &pe){
if (filtered.size() >= limit)
return false;
if (next_needed_pruning_stripe == 0 || pe.pruning_seed == 0)
@@ -1159,7 +1243,7 @@ namespace nodetool
for (size_t i = 0; i < filtered.size(); ++i)
{
peerlist_entry pe;
- if (m_peerlist.get_white_peer_by_index(pe, filtered[i]) && pe.adr == na)
+ if (zone.m_peerlist.get_white_peer_by_index(pe, filtered[i]) && pe.adr == na)
{
MDEBUG("Reusing stripe " << next_needed_pruning_stripe << " peer " << pe.adr.str());
random_index = i;
@@ -1173,7 +1257,7 @@ namespace nodetool
CHECK_AND_ASSERT_MES(random_index < filtered.size(), false, "random_index < filtered.size() failed!!");
random_index = filtered[random_index];
- CHECK_AND_ASSERT_MES(random_index < (use_white_list ? m_peerlist.get_white_peers_count() : m_peerlist.get_gray_peers_count()),
+ CHECK_AND_ASSERT_MES(random_index < (use_white_list ? zone.m_peerlist.get_white_peers_count() : zone.m_peerlist.get_gray_peers_count()),
false, "random_index < peers size failed!!");
if(tried_peers.count(random_index))
@@ -1181,7 +1265,7 @@ namespace nodetool
tried_peers.insert(random_index);
peerlist_entry pe = AUTO_VAL_INIT(pe);
- bool r = use_white_list ? m_peerlist.get_white_peer_by_index(pe, random_index):m_peerlist.get_gray_peer_by_index(pe, random_index);
+ bool r = use_white_list ? zone.m_peerlist.get_white_peer_by_index(pe, random_index):zone.m_peerlist.get_gray_peer_by_index(pe, random_index);
CHECK_AND_ASSERT_MES(r, false, "Failed to get random peer from peerlist(white:" << use_white_list << ")");
++try_count;
@@ -1224,9 +1308,10 @@ namespace nodetool
size_t try_count = 0;
size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size();
+ const net_server& server = m_network_zones.at(epee::net_utils::zone::public_).m_net_server;
while(true)
{
- if(m_net_server.is_stop_signal_sent())
+ if(server.is_stop_signal_sent())
return false;
if(try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true))
@@ -1265,13 +1350,17 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::connections_maker()
{
+ using zone_type = epee::net_utils::zone;
+
if (m_offline) return true;
if (!connect_to_peerlist(m_exclusive_peers)) return false;
if (!m_exclusive_peers.empty()) return true;
- size_t start_conn_count = get_outgoing_connections_count();
- if(!m_peerlist.get_white_peers_count() && m_seed_nodes.size())
+ // Only have seeds in the public zone right now.
+
+ size_t start_conn_count = get_public_outgoing_connections_count();
+ if(!get_public_white_peers_count() && m_seed_nodes.size())
{
if (!connect_to_seed())
return false;
@@ -1279,38 +1368,49 @@ namespace nodetool
if (!connect_to_peerlist(m_priority_peers)) return false;
- size_t base_expected_white_connections = (m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
-
- size_t conn_count = get_outgoing_connections_count();
- while(conn_count < m_config.m_net_config.max_out_connection_count)
+ for(auto& zone : m_network_zones)
{
- const size_t expected_white_connections = m_payload_handler.get_next_needed_pruning_stripe().second ? m_config.m_net_config.max_out_connection_count : base_expected_white_connections;
- if(conn_count < expected_white_connections)
- {
- //start from anchor list
- while (get_outgoing_connections_count() < P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT
- && make_expected_connections_count(anchor, P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT));
- //then do white list
- while (get_outgoing_connections_count() < expected_white_connections
- && make_expected_connections_count(white, expected_white_connections));
- //then do grey list
- while (get_outgoing_connections_count() < m_config.m_net_config.max_out_connection_count
- && make_expected_connections_count(gray, m_config.m_net_config.max_out_connection_count));
- }else
+ size_t base_expected_white_connections = (zone.second.m_config.m_net_config.max_out_connection_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
+
+ size_t conn_count = get_outgoing_connections_count(zone.second);
+ while(conn_count < zone.second.m_config.m_net_config.max_out_connection_count)
{
- //start from grey list
- while (get_outgoing_connections_count() < m_config.m_net_config.max_out_connection_count
- && make_expected_connections_count(gray, m_config.m_net_config.max_out_connection_count));
- //and then do white list
- while (get_outgoing_connections_count() < m_config.m_net_config.max_out_connection_count
- && make_expected_connections_count(white, m_config.m_net_config.max_out_connection_count));
+ const size_t expected_white_connections = m_payload_handler.get_next_needed_pruning_stripe().second ? zone.second.m_config.m_net_config.max_out_connection_count : base_expected_white_connections;
+ if(conn_count < expected_white_connections)
+ {
+ //start from anchor list
+ while (get_outgoing_connections_count(zone.second) < P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT
+ && make_expected_connections_count(zone.second, anchor, P2P_DEFAULT_ANCHOR_CONNECTIONS_COUNT));
+ //then do white list
+ while (get_outgoing_connections_count(zone.second) < expected_white_connections
+ && make_expected_connections_count(zone.second, white, expected_white_connections));
+ //then do grey list
+ while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
+ && make_expected_connections_count(zone.second, gray, zone.second.m_config.m_net_config.max_out_connection_count));
+ }else
+ {
+ //start from grey list
+ while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
+ && make_expected_connections_count(zone.second, gray, zone.second.m_config.m_net_config.max_out_connection_count));
+ //and then do white list
+ while (get_outgoing_connections_count(zone.second) < zone.second.m_config.m_net_config.max_out_connection_count
+ && make_expected_connections_count(zone.second, white, zone.second.m_config.m_net_config.max_out_connection_count));
+ }
+ if(zone.second.m_net_server.is_stop_signal_sent())
+ return false;
+ size_t new_conn_count = get_outgoing_connections_count(zone.second);
+ if (new_conn_count <= conn_count)
+ {
+ // we did not make any connection, sleep a bit to avoid a busy loop in case we don't have
+ // any peers to try, then break so we will try seeds to get more peers
+ boost::this_thread::sleep_for(boost::chrono::seconds(1));
+ break;
+ }
+ conn_count = new_conn_count;
}
- if(m_net_server.is_stop_signal_sent())
- return false;
- conn_count = get_outgoing_connections_count();
}
- if (start_conn_count == get_outgoing_connections_count() && start_conn_count < m_config.m_net_config.max_out_connection_count)
+ if (start_conn_count == get_public_outgoing_connections_count() && start_conn_count < m_network_zones.at(zone_type::public_).m_config.m_net_config.max_out_connection_count)
{
MINFO("Failed to connect to any, trying seeds");
if (!connect_to_seed())
@@ -1321,7 +1421,7 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::make_expected_connections_count(PeerType peer_type, size_t expected_connections)
+ bool node_server<t_payload_net_handler>::make_expected_connections_count(network_zone& zone, PeerType peer_type, size_t expected_connections)
{
if (m_offline)
return false;
@@ -1329,14 +1429,14 @@ namespace nodetool
std::vector<anchor_peerlist_entry> apl;
if (peer_type == anchor) {
- m_peerlist.get_and_empty_anchor_peerlist(apl);
+ zone.m_peerlist.get_and_empty_anchor_peerlist(apl);
}
- size_t conn_count = get_outgoing_connections_count();
+ size_t conn_count = get_outgoing_connections_count(zone);
//add new connections from white peers
if(conn_count < expected_connections)
{
- if(m_net_server.is_stop_signal_sent())
+ if(zone.m_net_server.is_stop_signal_sent())
return false;
MDEBUG("Making expected connection, type " << peer_type << ", " << conn_count << "/" << expected_connections << " connections");
@@ -1345,47 +1445,104 @@ namespace nodetool
return false;
}
- if (peer_type == white && !make_new_connection_from_peerlist(true)) {
+ if (peer_type == white && !make_new_connection_from_peerlist(zone, true)) {
return false;
}
- if (peer_type == gray && !make_new_connection_from_peerlist(false)) {
+ if (peer_type == gray && !make_new_connection_from_peerlist(zone, false)) {
return false;
}
}
return true;
}
-
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- size_t node_server<t_payload_net_handler>::get_outgoing_connections_count()
+ size_t node_server<t_payload_net_handler>::get_public_outgoing_connections_count()
+ {
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone == m_network_zones.end())
+ return 0;
+ return get_outgoing_connections_count(public_zone->second);
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ size_t node_server<t_payload_net_handler>::get_incoming_connections_count(network_zone& zone)
{
size_t count = 0;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ zone.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- if(!cntxt.m_is_income)
+ if(cntxt.m_is_income)
++count;
return true;
});
-
return count;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- size_t node_server<t_payload_net_handler>::get_incoming_connections_count()
+ size_t node_server<t_payload_net_handler>::get_outgoing_connections_count(network_zone& zone)
{
size_t count = 0;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ zone.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
- if(cntxt.m_is_income)
+ if(!cntxt.m_is_income)
++count;
return true;
});
-
return count;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
+ size_t node_server<t_payload_net_handler>::get_outgoing_connections_count()
+ {
+ size_t count = 0;
+ for(auto& zone : m_network_zones)
+ count += get_outgoing_connections_count(zone.second);
+ return count;
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ size_t node_server<t_payload_net_handler>::get_incoming_connections_count()
+ {
+ size_t count = 0;
+ for (auto& zone : m_network_zones)
+ {
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ if(cntxt.m_is_income)
+ ++count;
+ return true;
+ });
+ }
+ return count;
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ size_t node_server<t_payload_net_handler>::get_public_white_peers_count()
+ {
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone == m_network_zones.end())
+ return 0;
+ return public_zone->second.m_peerlist.get_white_peers_count();
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ size_t node_server<t_payload_net_handler>::get_public_gray_peers_count()
+ {
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone == m_network_zones.end())
+ return 0;
+ return public_zone->second.m_peerlist.get_gray_peers_count();
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ void node_server<t_payload_net_handler>::get_public_peerlist(std::vector<peerlist_entry>& gray, std::vector<peerlist_entry>& white)
+ {
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone != m_network_zones.end())
+ public_zone->second.m_peerlist.get_peerlist(gray, white);
+ }
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::idle_worker()
{
m_peer_handshake_idle_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::peer_sync_idle_maker, this));
@@ -1401,9 +1558,11 @@ namespace nodetool
{
if (m_offline)
return true;
- if (get_incoming_connections_count() == 0)
+
+ const auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone != m_network_zones.end() && get_incoming_connections_count(public_zone->second) == 0)
{
- if (m_hide_my_port || m_config.m_net_config.max_in_connection_count == 0)
+ if (m_hide_my_port || public_zone->second.m_config.m_net_config.max_in_connection_count == 0)
{
MGINFO("Incoming connections disabled, enable them for full connectivity");
}
@@ -1422,15 +1581,18 @@ namespace nodetool
MDEBUG("STARTED PEERLIST IDLE HANDSHAKE");
typedef std::list<std::pair<epee::net_utils::connection_context_base, peerid_type> > local_connects_type;
local_connects_type cncts;
- m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntxt)
+ for(auto& zone : m_network_zones)
{
- if(cntxt.peer_id && !cntxt.m_in_timedsync)
+ zone.second.m_net_server.get_config_object().foreach_connection([&](p2p_connection_context& cntxt)
{
- cntxt.m_in_timedsync = true;
- cncts.push_back(local_connects_type::value_type(cntxt, cntxt.peer_id));//do idle sync only with handshaked connections
- }
- return true;
- });
+ if(cntxt.peer_id && !cntxt.m_in_timedsync)
+ {
+ cntxt.m_in_timedsync = true;
+ cncts.push_back(local_connects_type::value_type(cntxt, cntxt.peer_id));//do idle sync only with handshaked connections
+ }
+ return true;
+ });
+ }
std::for_each(cncts.begin(), cncts.end(), [&](const typename local_connects_type::value_type& vl){do_peer_timed_sync(vl.first, vl.second);});
@@ -1468,19 +1630,30 @@ namespace nodetool
std::vector<peerlist_entry> peerlist_ = peerlist;
if(!fix_time_delta(peerlist_, local_time, delta))
return false;
+
+ const epee::net_utils::zone zone = context.m_remote_address.get_zone();
+ for(const auto& peer : peerlist_)
+ {
+ if(peer.adr.get_zone() != zone)
+ {
+ MWARNING(context << " sent peerlist from another zone, dropping");
+ return false;
+ }
+ }
+
LOG_DEBUG_CC(context, "REMOTE PEERLIST: TIME_DELTA: " << delta << ", remote peerlist size=" << peerlist_.size());
LOG_DEBUG_CC(context, "REMOTE PEERLIST: " << print_peerlist_to_string(peerlist_));
- return m_peerlist.merge_peerlist(peerlist_);
+ return m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.merge_peerlist(peerlist_);
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::get_local_node_data(basic_node_data& node_data)
+ bool node_server<t_payload_net_handler>::get_local_node_data(basic_node_data& node_data, const network_zone& zone)
{
time_t local_time;
time(&local_time);
- node_data.local_time = local_time;
- node_data.peer_id = m_config.m_peer_id;
- if(!m_hide_my_port)
+ node_data.local_time = local_time; // \TODO This can be an identifying value across zones (public internet to tor/i2p) ...
+ node_data.peer_id = zone.m_config.m_peer_id;
+ if(!m_hide_my_port && zone.m_can_pingback)
node_data.my_port = m_external_port ? m_external_port : m_listening_port;
else
node_data.my_port = 0;
@@ -1490,7 +1663,7 @@ namespace nodetool
//-----------------------------------------------------------------------------------
#ifdef ALLOW_DEBUG_COMMANDS
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::check_trust(const proof_of_trust& tr)
+ bool node_server<t_payload_net_handler>::check_trust(const proof_of_trust& tr, const epee::net_utils::zone zone_type)
{
uint64_t local_time = time(NULL);
uint64_t time_delata = local_time > tr.time ? local_time - tr.time: tr.time - local_time;
@@ -1504,9 +1677,11 @@ namespace nodetool
MWARNING("check_trust failed to check time conditions, last_stat_request_time=" << m_last_stat_request_time << ", proof_time=" << tr.time);
return false;
}
- if(m_config.m_peer_id != tr.peer_id)
+
+ const network_zone& zone = m_network_zones.at(zone_type);
+ if(zone.m_config.m_peer_id != tr.peer_id)
{
- MWARNING("check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << m_config.m_peer_id<< ")");
+ MWARNING("check_trust failed: peer_id mismatch (passed " << tr.peer_id << ", expected " << zone.m_config.m_peer_id<< ")");
return false;
}
crypto::public_key pk = AUTO_VAL_INIT(pk);
@@ -1525,12 +1700,12 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_get_stat_info(int command, typename COMMAND_REQUEST_STAT_INFO::request& arg, typename COMMAND_REQUEST_STAT_INFO::response& rsp, p2p_connection_context& context)
{
- if(!check_trust(arg.tr))
+ if(!check_trust(arg.tr, context.m_remote_address.get_zone()))
{
drop_connection(context);
return 1;
}
- rsp.connections_count = m_net_server.get_config_object().get_connections_count();
+ rsp.connections_count = get_connections_count();
rsp.incoming_connections_count = rsp.connections_count - get_outgoing_connections_count();
rsp.version = MONERO_VERSION_FULL;
rsp.os_version = tools::get_os_version_string();
@@ -1541,12 +1716,12 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_get_network_state(int command, COMMAND_REQUEST_NETWORK_STATE::request& arg, COMMAND_REQUEST_NETWORK_STATE::response& rsp, p2p_connection_context& context)
{
- if(!check_trust(arg.tr))
+ if(!check_trust(arg.tr, context.m_remote_address.get_zone()))
{
drop_connection(context);
return 1;
}
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
connection_entry ce;
ce.adr = cntxt.m_remote_address;
@@ -1556,8 +1731,9 @@ namespace nodetool
return true;
});
- m_peerlist.get_peerlist_full(rsp.local_peerlist_gray, rsp.local_peerlist_white);
- rsp.my_id = m_config.m_peer_id;
+ network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
+ zone.m_peerlist.get_peerlist(rsp.local_peerlist_gray, rsp.local_peerlist_white);
+ rsp.my_id = zone.m_config.m_peer_id;
rsp.local_time = time(NULL);
return 1;
}
@@ -1565,7 +1741,7 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_get_peer_id(int command, COMMAND_REQUEST_PEER_ID::request& arg, COMMAND_REQUEST_PEER_ID::response& rsp, p2p_connection_context& context)
{
- rsp.my_id = m_config.m_peer_id;
+ rsp.my_id = m_network_zones.at(context.m_remote_address.get_zone()).m_config.m_peer_id;
return 1;
}
#endif
@@ -1573,40 +1749,42 @@ namespace nodetool
template<class t_payload_net_handler>
int node_server<t_payload_net_handler>::handle_get_support_flags(int command, COMMAND_REQUEST_SUPPORT_FLAGS::request& arg, COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context)
{
- rsp.support_flags = m_config.m_support_flags;
+ rsp.support_flags = m_network_zones.at(context.m_remote_address.get_zone()).m_config.m_support_flags;
return 1;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::request_callback(const epee::net_utils::connection_context_base& context)
{
- m_net_server.get_config_object().request_callback(context.m_connection_id);
+ m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().request_callback(context.m_connection_id);
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, const std::list<boost::uuids::uuid> &connections)
+ bool node_server<t_payload_net_handler>::relay_notify_to_list(int command, const epee::span<const uint8_t> data_buff, std::vector<std::pair<epee::net_utils::zone, boost::uuids::uuid>> connections)
{
+ std::sort(connections.begin(), connections.end());
+ auto zone = m_network_zones.begin();
for(const auto& c_id: connections)
{
- m_net_server.get_config_object().notify(command, data_buff, c_id);
+ for (;;)
+ {
+ if (zone == m_network_zones.end())
+ {
+ MWARNING("Unable to relay all messages, " << epee::net_utils::zone_to_string(c_id.first) << " not available");
+ return false;
+ }
+ if (c_id.first <= zone->first)
+ break;
+
+ ++zone;
+ }
+ if (zone->first == c_id.first)
+ zone->second.m_net_server.get_config_object().notify(command, data_buff, c_id.second);
}
return true;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::relay_notify_to_all(int command, const epee::span<const uint8_t> data_buff, const epee::net_utils::connection_context_base& context)
- {
- std::list<boost::uuids::uuid> connections;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
- {
- if(cntxt.peer_id && context.m_connection_id != cntxt.m_connection_id)
- connections.push_back(cntxt.m_connection_id);
- return true;
- });
- return relay_notify_to_list(command, data_buff, connections);
- }
- //-----------------------------------------------------------------------------------
- template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::callback(p2p_connection_context& context)
{
m_payload_handler.on_callback(context);
@@ -1615,21 +1793,29 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::invoke_notify_to_peer(int command, const epee::span<const uint8_t> req_buff, const epee::net_utils::connection_context_base& context)
{
- int res = m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id);
+ if(is_filtered_command(context.m_remote_address, command))
+ return false;
+
+ network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
+ int res = zone.m_net_server.get_config_object().notify(command, req_buff, context.m_connection_id);
return res > 0;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::invoke_command_to_peer(int command, const epee::span<const uint8_t> req_buff, std::string& resp_buff, const epee::net_utils::connection_context_base& context)
{
- int res = m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id);
+ if(is_filtered_command(context.m_remote_address, command))
+ return false;
+
+ network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
+ int res = zone.m_net_server.get_config_object().invoke(command, req_buff, resp_buff, context.m_connection_id);
return res > 0;
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::drop_connection(const epee::net_utils::connection_context_base& context)
{
- m_net_server.get_config_object().close(context.m_connection_id);
+ m_network_zones.at(context.m_remote_address.get_zone()).m_net_server.get_config_object().close(context.m_connection_id);
return true;
}
//-----------------------------------------------------------------------------------
@@ -1639,18 +1825,21 @@ namespace nodetool
if(!node_data.my_port)
return false;
- CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, false,
+ CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), false,
"Only IPv4 addresses are supported here");
const epee::net_utils::network_address na = context.m_remote_address;
uint32_t actual_ip = na.as<const epee::net_utils::ipv4_network_address>().ip();
- if(!m_peerlist.is_host_allowed(context.m_remote_address))
+ network_zone& zone = m_network_zones.at(na.get_zone());
+
+ if(!zone.m_peerlist.is_host_allowed(context.m_remote_address))
return false;
+
std::string ip = epee::string_tools::get_ip_string_from_int32(actual_ip);
std::string port = epee::string_tools::num_to_string_fast(node_data.my_port);
epee::net_utils::network_address address{epee::net_utils::ipv4_network_address(actual_ip, node_data.my_port)};
peerid_type pr = node_data.peer_id;
- bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ address, pr, this](
+ bool r = zone.m_net_server.connect_async(ip, port, zone.m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ address, pr, this](
const typename net_server::t_connection_context& ping_context,
const boost::system::error_code& ec)->bool
{
@@ -1670,7 +1859,9 @@ namespace nodetool
// GCC 5.1.0 gives error with second use of uint64_t (peerid_type) variable.
peerid_type pr_ = pr;
- bool inv_call_res = epee::net_utils::async_invoke_remote_command2<COMMAND_PING::response>(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(),
+ network_zone& zone = m_network_zones.at(address.get_zone());
+
+ bool inv_call_res = epee::net_utils::async_invoke_remote_command2<COMMAND_PING::response>(ping_context.m_connection_id, COMMAND_PING::ID, req, zone.m_net_server.get_config_object(),
[=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context)
{
if(code <= 0)
@@ -1679,20 +1870,21 @@ namespace nodetool
return;
}
+ network_zone& zone = m_network_zones.at(address.get_zone());
if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id)
{
LOG_WARNING_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << address.str() << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << rsp.peer_id);
- m_net_server.get_config_object().close(ping_context.m_connection_id);
+ zone.m_net_server.get_config_object().close(ping_context.m_connection_id);
return;
}
- m_net_server.get_config_object().close(ping_context.m_connection_id);
+ zone.m_net_server.get_config_object().close(ping_context.m_connection_id);
cb();
});
if(!inv_call_res)
{
LOG_WARNING_CC(ping_context, "back ping invoke failed to " << address.str());
- m_net_server.get_config_object().close(ping_context.m_connection_id);
+ zone.m_net_server.get_config_object().close(ping_context.m_connection_id);
return false;
}
return true;
@@ -1707,13 +1899,16 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f)
{
+ if(context.m_remote_address.get_zone() != epee::net_utils::zone::public_)
+ return false;
+
COMMAND_REQUEST_SUPPORT_FLAGS::request support_flags_request;
bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_REQUEST_SUPPORT_FLAGS::response>
(
context.m_connection_id,
COMMAND_REQUEST_SUPPORT_FLAGS::ID,
support_flags_request,
- m_net_server.get_config_object(),
+ m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object(),
[=](int code, const typename COMMAND_REQUEST_SUPPORT_FLAGS::response& rsp, p2p_connection_context& context_)
{
if(code < 0)
@@ -1742,8 +1937,24 @@ namespace nodetool
//fill response
rsp.local_time = time(NULL);
- m_peerlist.get_peerlist_head(rsp.local_peerlist_new);
+
+ const epee::net_utils::zone zone_type = context.m_remote_address.get_zone();
+ network_zone& zone = m_network_zones.at(zone_type);
+
+ zone.m_peerlist.get_peerlist_head(rsp.local_peerlist_new);
m_payload_handler.get_payload_sync_data(rsp.payload_data);
+
+ /* Tor/I2P nodes receiving connections via forwarding (from tor/i2p daemon)
+ do not know the address of the connecting peer. This is relayed to them,
+ iff the node has setup an inbound hidden service. The other peer will have
+ to use the random peer_id value to link the two. My initial thought is that
+ the inbound peer should leave the other side marked as `<unknown tor host>`,
+ etc., because someone could give faulty addresses over Tor/I2P to get the
+ real peer with that identity banned/blacklisted. */
+
+ if(!context.m_is_income && zone.m_our_address.get_zone() == zone_type)
+ rsp.local_peerlist_new.push_back(peerlist_entry{zone.m_our_address, zone.m_config.m_peer_id, std::time(nullptr)});
+
LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC");
return 1;
}
@@ -1775,7 +1986,9 @@ namespace nodetool
return 1;
}
- if (m_current_number_of_in_peers >= m_config.m_net_config.max_in_connection_count) // in peers limit
+ network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
+
+ if (zone.m_current_number_of_in_peers >= zone.m_config.m_net_config.max_in_connection_count) // in peers limit
{
LOG_WARNING_CC(context, "COMMAND_HANDSHAKE came, but already have max incoming connections, so dropping this one.");
drop_connection(context);
@@ -1800,14 +2013,14 @@ namespace nodetool
context.peer_id = arg.node_data.peer_id;
context.m_in_timedsync = false;
- if(arg.node_data.peer_id != m_config.m_peer_id && arg.node_data.my_port)
+ if(arg.node_data.peer_id != zone.m_config.m_peer_id && arg.node_data.my_port && zone.m_can_pingback)
{
peerid_type peer_id_l = arg.node_data.peer_id;
uint32_t port_l = arg.node_data.my_port;
//try ping to be sure that we can add this peer to peer_list
try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]()
{
- CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::ID, void(),
+ CHECK_AND_ASSERT_MES(context.m_remote_address.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), void(),
"Only IPv4 addresses are supported here");
//called only(!) if success pinged, update local peerlist
peerlist_entry pe;
@@ -1818,7 +2031,7 @@ namespace nodetool
pe.last_seen = static_cast<int64_t>(last_seen);
pe.id = peer_id_l;
pe.pruning_seed = context.m_pruning_seed;
- this->m_peerlist.append_with_peer_white(pe);
+ this->m_network_zones.at(context.m_remote_address.get_zone()).m_peerlist.append_with_peer_white(pe);
LOG_DEBUG_CC(context, "PING SUCCESS " << context.m_remote_address.host_str() << ":" << port_l);
});
}
@@ -1829,8 +2042,8 @@ namespace nodetool
});
//fill response
- m_peerlist.get_peerlist_head(rsp.local_peerlist_new);
- get_local_node_data(rsp.node_data);
+ zone.m_peerlist.get_peerlist_head(rsp.local_peerlist_new);
+ get_local_node_data(rsp.node_data, zone);
m_payload_handler.get_payload_sync_data(rsp.payload_data);
LOG_DEBUG_CC(context, "COMMAND_HANDSHAKE");
return 1;
@@ -1841,7 +2054,7 @@ namespace nodetool
{
LOG_DEBUG_CC(context, "COMMAND_PING");
rsp.status = PING_OK_RESPONSE_STATUS_TEXT;
- rsp.peer_id = m_config.m_peer_id;
+ rsp.peer_id = m_network_zones.at(context.m_remote_address.get_zone()).m_config.m_peer_id;
return 1;
}
//-----------------------------------------------------------------------------------
@@ -1850,7 +2063,8 @@ namespace nodetool
{
std::vector<peerlist_entry> pl_white;
std::vector<peerlist_entry> pl_gray;
- m_peerlist.get_peerlist_full(pl_gray, pl_white);
+ for (auto& zone : m_network_zones)
+ zone.second.m_peerlist.get_peerlist(pl_gray, pl_white);
MINFO(ENDL << "Peerlist white:" << ENDL << print_peerlist_to_string(pl_white) << ENDL << "Peerlist gray:" << ENDL << print_peerlist_to_string(pl_gray) );
return true;
}
@@ -1867,14 +2081,17 @@ namespace nodetool
{
std::stringstream ss;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ for (auto& zone : m_network_zones)
{
- ss << cntxt.m_remote_address.str()
- << " \t\tpeer_id " << cntxt.peer_id
- << " \t\tconn_id " << cntxt.m_connection_id << (cntxt.m_is_income ? " INC":" OUT")
- << std::endl;
- return true;
- });
+ zone.second.m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ ss << cntxt.m_remote_address.str()
+ << " \t\tpeer_id " << cntxt.peer_id
+ << " \t\tconn_id " << cntxt.m_connection_id << (cntxt.m_is_income ? " INC":" OUT")
+ << std::endl;
+ return true;
+ });
+ }
std::string s = ss.str();
return s;
}
@@ -1888,11 +2105,12 @@ namespace nodetool
template<class t_payload_net_handler>
void node_server<t_payload_net_handler>::on_connection_close(p2p_connection_context& context)
{
- if (!m_net_server.is_stop_signal_sent() && !context.m_is_income) {
+ network_zone& zone = m_network_zones.at(context.m_remote_address.get_zone());
+ if (!zone.m_net_server.is_stop_signal_sent() && !context.m_is_income) {
epee::net_utils::network_address na = AUTO_VAL_INIT(na);
na = context.m_remote_address;
- m_peerlist.remove_from_peer_anchor(na);
+ zone.m_peerlist.remove_from_peer_anchor(na);
}
m_payload_handler.on_connection_close(context);
@@ -1909,9 +2127,10 @@ namespace nodetool
template<class t_payload_net_handler> template <class Container>
bool node_server<t_payload_net_handler>::connect_to_peerlist(const Container& peers)
{
+ const network_zone& public_zone = m_network_zones.at(epee::net_utils::zone::public_);
for(const epee::net_utils::network_address& na: peers)
{
- if(m_net_server.is_stop_signal_sent())
+ if(public_zone.m_net_server.is_stop_signal_sent())
return false;
if(is_addr_connected(na))
@@ -1930,16 +2149,16 @@ namespace nodetool
for(const std::string& pr_str: perrs)
{
- epee::net_utils::network_address na = AUTO_VAL_INIT(na);
const uint16_t default_port = cryptonote::get_config(m_nettype).P2P_DEFAULT_PORT;
- bool r = parse_peer_from_string(na, pr_str, default_port);
- if (r)
+ expect<epee::net_utils::network_address> adr = net::get_network_address(pr_str, default_port);
+ if (adr)
{
- container.push_back(na);
+ add_zone(adr->get_zone());
+ container.push_back(std::move(*adr));
continue;
}
std::vector<epee::net_utils::network_address> resolved_addrs;
- r = append_net_address(resolved_addrs, pr_str, default_port);
+ bool r = append_net_address(resolved_addrs, pr_str, default_port);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse or resolve address from string: " << pr_str);
for (const epee::net_utils::network_address& addr : resolved_addrs)
{
@@ -1951,32 +2170,47 @@ namespace nodetool
}
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::set_max_out_peers(const boost::program_options::variables_map& vm, int64_t max)
+ bool node_server<t_payload_net_handler>::set_max_out_peers(network_zone& zone, int64_t max)
{
- if(max == -1)
- max = P2P_DEFAULT_CONNECTIONS_COUNT;
- m_config.m_net_config.max_out_connection_count = max;
- m_payload_handler.set_max_out_peers(max);
+ if(max == -1) {
+ zone.m_config.m_net_config.max_out_connection_count = P2P_DEFAULT_CONNECTIONS_COUNT;
+ return true;
+ }
+ zone.m_config.m_net_config.max_out_connection_count = max;
return true;
}
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::set_max_in_peers(const boost::program_options::variables_map& vm, int64_t max)
+ bool node_server<t_payload_net_handler>::set_max_in_peers(network_zone& zone, int64_t max)
{
- m_config.m_net_config.max_in_connection_count = max;
+ zone.m_config.m_net_config.max_in_connection_count = max;
return true;
}
template<class t_payload_net_handler>
- void node_server<t_payload_net_handler>::delete_out_connections(size_t count)
+ void node_server<t_payload_net_handler>::change_max_out_public_peers(size_t count)
{
- m_net_server.get_config_object().del_out_connections(count);
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone != m_network_zones.end())
+ {
+ const auto current = public_zone->second.m_config.m_net_config.max_out_connection_count;
+ public_zone->second.m_config.m_net_config.max_out_connection_count = count;
+ if(current > count)
+ public_zone->second.m_net_server.get_config_object().del_out_connections(current - count);
+ }
}
template<class t_payload_net_handler>
- void node_server<t_payload_net_handler>::delete_in_connections(size_t count)
+ void node_server<t_payload_net_handler>::change_max_in_public_peers(size_t count)
{
- m_net_server.get_config_object().del_in_connections(count);
+ auto public_zone = m_network_zones.find(epee::net_utils::zone::public_);
+ if (public_zone != m_network_zones.end())
+ {
+ const auto current = public_zone->second.m_config.m_net_config.max_in_connection_count;
+ public_zone->second.m_config.m_net_config.max_in_connection_count = count;
+ if(current > count)
+ public_zone->second.m_net_server.get_config_object().del_in_connections(current - count);
+ }
}
template<class t_payload_net_handler>
@@ -2049,10 +2283,13 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::has_too_many_connections(const epee::net_utils::network_address &address)
{
+ if (address.get_zone() != epee::net_utils::zone::public_)
+ return false; // Unable to determine how many connections from host
+
const size_t max_connections = 1;
size_t count = 0;
- m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ m_network_zones.at(epee::net_utils::zone::public_).m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
{
if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) {
count++;
@@ -2075,29 +2312,29 @@ namespace nodetool
if (!m_exclusive_peers.empty()) return true;
if (m_payload_handler.needs_new_sync_connections()) return true;
- peerlist_entry pe = AUTO_VAL_INIT(pe);
-
- if (m_net_server.is_stop_signal_sent())
- return false;
-
- if (!m_peerlist.get_random_gray_peer(pe)) {
- return true;
- }
-
- bool success = check_connection_and_handshake_with_peer(pe.adr, pe.last_seen);
+ for (auto& zone : m_network_zones)
+ {
+ if (zone.second.m_net_server.is_stop_signal_sent())
+ return false;
- if (!success) {
- m_peerlist.remove_from_peer_gray(pe);
+ if (zone.second.m_connect == nullptr)
+ continue;
- LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id));
+ peerlist_entry pe{};
+ if (!zone.second.m_peerlist.get_random_gray_peer(pe))
+ continue;
- return true;
+ if (!check_connection_and_handshake_with_peer(pe.adr, pe.last_seen))
+ {
+ zone.second.m_peerlist.remove_from_peer_gray(pe);
+ LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id));
+ }
+ else
+ {
+ zone.second.m_peerlist.set_peer_just_seen(pe.id, pe.adr, pe.pruning_seed);
+ LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id));
+ }
}
-
- m_peerlist.set_peer_just_seen(pe.id, pe.adr, pe.pruning_seed);
-
- LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << peerid_type(pe.id));
-
return true;
}
@@ -2225,4 +2462,37 @@ namespace nodetool
MINFO("No IGD was found.");
}
}
+
+ template<typename t_payload_net_handler>
+ boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
+ node_server<t_payload_net_handler>::socks_connect(network_zone& zone, const epee::net_utils::network_address& remote, epee::net_utils::ssl_support_t ssl_support)
+ {
+ auto result = socks_connect_internal(zone.m_net_server.get_stop_signal(), zone.m_net_server.get_io_service(), zone.m_proxy_address, remote);
+ if (result) // if no error
+ {
+ p2p_connection_context context{};
+ if (zone.m_net_server.add_connection(context, std::move(*result), remote, ssl_support))
+ return {std::move(context)};
+ }
+ return boost::none;
+ }
+
+ template<typename t_payload_net_handler>
+ boost::optional<p2p_connection_context_t<typename t_payload_net_handler::connection_context>>
+ node_server<t_payload_net_handler>::public_connect(network_zone& zone, epee::net_utils::network_address const& na, epee::net_utils::ssl_support_t ssl_support)
+ {
+ CHECK_AND_ASSERT_MES(na.get_type_id() == epee::net_utils::ipv4_network_address::get_type_id(), boost::none,
+ "Only IPv4 addresses are supported here");
+ const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>();
+
+ typename net_server::t_connection_context con{};
+ const bool res = zone.m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()),
+ epee::string_tools::num_to_string_fast(ipv4.port()),
+ zone.m_config.m_net_config.connection_timeout,
+ con, "0.0.0.0", ssl_support);
+
+ if (res)
+ return {std::move(con)};
+ return boost::none;
+ }
}