aboutsummaryrefslogtreecommitdiff
path: root/src/p2p
diff options
context:
space:
mode:
Diffstat (limited to 'src/p2p')
-rw-r--r--src/p2p/net_node.h6
-rw-r--r--src/p2p/net_node.inl101
-rw-r--r--src/p2p/net_peerlist.h52
3 files changed, 157 insertions, 2 deletions
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index cc6a486d3..f5309b1c3 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -227,6 +227,11 @@ namespace nodetool
bool set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit);
bool set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit);
+ 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()
_info("Killing the net_node");
is_closing = true;
@@ -287,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<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> m_gray_peerlist_housekeeping_interval;
std::string m_bind_ip;
std::string m_port;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 3bde6dfb7..7e3c0213a 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -926,6 +926,50 @@ namespace nodetool
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_DEBUG_CC(con, "CONNECTION HANDSHAKED OK AND CLOSED.");
+
+ return true;
+ }
+
#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_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));
return true;
}
@@ -1456,6 +1501,14 @@ namespace nodetool
drop_connection(context);
return 1;
}
+
+ if(has_too_many_connections(context.m_remote_ip))
+ {
+ LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << " REFUSED, too many connections from the same address");
+ drop_connection(context);
+ return 1;
+ }
+
//associate peer_id with this connection
context.peer_id = arg.node_data.peer_id;
@@ -1674,4 +1727,52 @@ namespace nodetool
return true;
}
+
+ template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::has_too_many_connections(const uint32_t ip)
+ {
+ const uint8_t max_connections = 1;
+ uint8_t count = 0;
+
+ m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
+ {
+ if (cntxt.m_is_income && cntxt.m_remote_ip == ip) {
+ count++;
+
+ if (count > max_connections) {
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ 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_random_gray_peer(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.set_peer_just_seen(pe.id, pe.adr);
+
+ 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;
+ }
}
diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h
index fa69abd6e..4797eb82b 100644
--- a/src/p2p/net_peerlist.h
+++ b/src/p2p/net_peerlist.h
@@ -81,6 +81,8 @@ namespace nodetool
bool set_peer_just_seen(peerid_type peer, const net_address& addr);
bool set_peer_unreachable(const peerlist_entry& pr);
bool is_ip_allowed(uint32_t ip);
+ bool get_random_gray_peer(peerlist_entry& pe);
+ bool remove_from_peer_gray(const peerlist_entry& pe);
private:
@@ -285,9 +287,11 @@ namespace nodetool
{
if(!vl.last_seen)
continue;
- bs_head.push_back(vl);
- if(cnt++ > depth)
+
+ if(cnt++ >= depth)
break;
+
+ bs_head.push_back(vl);
}
return true;
}
@@ -394,6 +398,50 @@ namespace nodetool
return true;
}
//--------------------------------------------------------------------------------------------------
+ inline
+ bool peerlist_manager::get_random_gray_peer(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_random_gray_peer()", 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)