Add gray peer list housekeeping system
A random peer from the gray peer list is selected and a connection is made to check if the peer is alive. If the connection and handshake are successful the peer is promoted to the white peer list, in case of failure the peer is evicted from the gray peer list. The connection is closed after the check in either case.
This commit is contained in:
parent
39aaea8e62
commit
82dbeedd1b
|
@ -229,6 +229,9 @@ namespace nodetool
|
||||||
|
|
||||||
bool has_too_many_connections(const uint32_t ip);
|
bool has_too_many_connections(const uint32_t ip);
|
||||||
|
|
||||||
|
bool check_connection_and_handshake_with_peer(const net_address& na, uint64_t last_seen_stamp);
|
||||||
|
bool gray_peerlist_housekeeping();
|
||||||
|
|
||||||
void kill() { ///< will be called e.g. from deinit()
|
void kill() { ///< will be called e.g. from deinit()
|
||||||
_info("Killing the net_node");
|
_info("Killing the net_node");
|
||||||
is_closing = true;
|
is_closing = true;
|
||||||
|
@ -289,6 +292,7 @@ namespace nodetool
|
||||||
epee::math_helper::once_a_time_seconds<P2P_DEFAULT_HANDSHAKE_INTERVAL> m_peer_handshake_idle_maker_interval;
|
epee::math_helper::once_a_time_seconds<P2P_DEFAULT_HANDSHAKE_INTERVAL> m_peer_handshake_idle_maker_interval;
|
||||||
epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval;
|
epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval;
|
||||||
epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
|
epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
|
||||||
|
epee::math_helper::once_a_time_seconds<60> m_gray_peerlist_housekeeping_interval;
|
||||||
|
|
||||||
std::string m_bind_ip;
|
std::string m_bind_ip;
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
|
|
|
@ -926,6 +926,50 @@ namespace nodetool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class t_payload_net_handler>
|
||||||
|
bool node_server<t_payload_net_handler>::check_connection_and_handshake_with_peer(const net_address& na, uint64_t last_seen_stamp)
|
||||||
|
{
|
||||||
|
LOG_PRINT_L1("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":"
|
||||||
|
<< epee::string_tools::num_to_string_fast(na.port) << "(last_seen: "
|
||||||
|
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
|
||||||
|
<< ")...");
|
||||||
|
|
||||||
|
typename net_server::t_connection_context con = AUTO_VAL_INIT(con);
|
||||||
|
bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(na.ip),
|
||||||
|
epee::string_tools::num_to_string_fast(na.port),
|
||||||
|
m_config.m_net_config.connection_timeout,
|
||||||
|
con);
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
bool is_priority = is_priority_node(na);
|
||||||
|
|
||||||
|
LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to "
|
||||||
|
<< epee::string_tools::get_ip_string_from_int32(na.ip)
|
||||||
|
<< ":" << epee::string_tools::num_to_string_fast(na.port));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
peerid_type pi = AUTO_VAL_INIT(pi);
|
||||||
|
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 "
|
||||||
|
<< epee::string_tools::get_ip_string_from_int32(na.ip)
|
||||||
|
<< ":" << epee::string_tools::num_to_string_fast(na.port));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_net_server.get_config_object().close(con.m_connection_id);
|
||||||
|
|
||||||
|
LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK AND CLOSED.", LOG_LEVEL_2);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#undef LOG_PRINT_CC_PRIORITY_NODE
|
#undef LOG_PRINT_CC_PRIORITY_NODE
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
@ -1097,6 +1141,7 @@ namespace nodetool
|
||||||
{
|
{
|
||||||
m_peer_handshake_idle_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::peer_sync_idle_maker, this));
|
m_peer_handshake_idle_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::peer_sync_idle_maker, this));
|
||||||
m_connections_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::connections_maker, this));
|
m_connections_maker_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::connections_maker, this));
|
||||||
|
m_gray_peerlist_housekeeping_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::gray_peerlist_housekeeping, this));
|
||||||
m_peerlist_store_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::store_config, this));
|
m_peerlist_store_interval.do_call(boost::bind(&node_server<t_payload_net_handler>::store_config, this));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1704,4 +1749,30 @@ namespace nodetool
|
||||||
|
|
||||||
return count > max_connections;
|
return count > max_connections;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class t_payload_net_handler>
|
||||||
|
bool node_server<t_payload_net_handler>::gray_peerlist_housekeeping()
|
||||||
|
{
|
||||||
|
peerlist_entry pe = AUTO_VAL_INIT(pe);
|
||||||
|
|
||||||
|
if (!m_peerlist.get_gray_peer_random(pe)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = check_connection_and_handshake_with_peer(pe.adr, pe.last_seen);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
|
m_peerlist.remove_from_peer_gray(pe);
|
||||||
|
|
||||||
|
LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << " Peer ID: " << std::hex << pe.id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_peerlist.append_with_peer_white(pe);
|
||||||
|
|
||||||
|
LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << " Peer ID: " << std::hex << pe.id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,8 @@ namespace nodetool
|
||||||
bool set_peer_just_seen(peerid_type peer, const net_address& addr);
|
bool set_peer_just_seen(peerid_type peer, const net_address& addr);
|
||||||
bool set_peer_unreachable(const peerlist_entry& pr);
|
bool set_peer_unreachable(const peerlist_entry& pr);
|
||||||
bool is_ip_allowed(uint32_t ip);
|
bool is_ip_allowed(uint32_t ip);
|
||||||
|
bool get_gray_peer_random(peerlist_entry& pe);
|
||||||
|
bool remove_from_peer_gray(const peerlist_entry& pe);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -396,6 +398,50 @@ namespace nodetool
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
inline
|
||||||
|
bool peerlist_manager::get_gray_peer_random(peerlist_entry& pe)
|
||||||
|
{
|
||||||
|
TRY_ENTRY();
|
||||||
|
|
||||||
|
CRITICAL_REGION_LOCAL(m_peerlist_lock);
|
||||||
|
|
||||||
|
if (m_peers_gray.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t x = crypto::rand<size_t>() % (m_peers_gray.size() + 1);
|
||||||
|
size_t res = (x * x * x) / (m_peers_gray.size() * m_peers_gray.size()); //parabola \/
|
||||||
|
|
||||||
|
LOG_PRINT_L3("Random gray peer index=" << res << "(x="<< x << ", max_index=" << m_peers_gray.size() << ")");
|
||||||
|
|
||||||
|
peers_indexed::index<by_time>::type& by_time_index = m_peers_gray.get<by_time>();
|
||||||
|
pe = *epee::misc_utils::move_it_backward(--by_time_index.end(), res);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CATCH_ENTRY_L0("peerlist_manager::get_gray_peer_random()", false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
inline
|
||||||
|
bool peerlist_manager::remove_from_peer_gray(const peerlist_entry& pe)
|
||||||
|
{
|
||||||
|
TRY_ENTRY();
|
||||||
|
|
||||||
|
CRITICAL_REGION_LOCAL(m_peerlist_lock);
|
||||||
|
|
||||||
|
peers_indexed::index_iterator<by_addr>::type iterator = m_peers_gray.get<by_addr>().find(pe.adr);
|
||||||
|
|
||||||
|
if (iterator != m_peers_gray.get<by_addr>().end()) {
|
||||||
|
m_peers_gray.erase(iterator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CATCH_ENTRY_L0("peerlist_manager::remove_from_peer_gray()", false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER)
|
BOOST_CLASS_VERSION(nodetool::peerlist_manager, CURRENT_PEERLIST_STORAGE_ARCHIVE_VER)
|
||||||
|
|
Loading…
Reference in New Issue