diff options
author | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2017-05-27 11:35:54 +0100 |
---|---|---|
committer | moneromooo-monero <moneromooo-monero@users.noreply.github.com> | 2017-05-27 11:35:54 +0100 |
commit | 072102cfd23c47d36f4d51875026339a767f22ae (patch) | |
tree | 3005737650989527f71b2c742696e6dfb0a2a7f6 /src/p2p | |
parent | Merge pull request #2015 (diff) | |
download | monero-072102cfd23c47d36f4d51875026339a767f22ae.tar.xz |
abstracted nework addresses
All code which was using ip and port now uses a new IPv4 object,
subclass of a new network_address class. This will allow easy
addition of I2P addresses later (and also IPv6, etc).
Both old style and new style peer lists are now sent in the P2P
protocol, which is inefficient but allows peers using both
codebases to talk to each other. This will be removed in the
future. No other subclasses than IPv4 exist yet.
Diffstat (limited to 'src/p2p')
-rw-r--r-- | src/p2p/net_node.h | 42 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 215 | ||||
-rw-r--r-- | src/p2p/net_node_common.h | 18 | ||||
-rw-r--r-- | src/p2p/net_peerlist.h | 78 | ||||
-rw-r--r-- | src/p2p/net_peerlist_boost_serialization.h | 35 | ||||
-rw-r--r-- | src/p2p/p2p_protocol_defs.h | 121 |
6 files changed, 320 insertions, 189 deletions
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 13cd3f5b0..8798a52e0 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -123,9 +123,9 @@ namespace nodetool size_t get_outgoing_connections_count(); peerlist_manager& get_peerlist_manager(){return m_peerlist;} void delete_connections(size_t count); - virtual bool block_ip(uint32_t adress, time_t seconds = P2P_IP_BLOCKTIME); - virtual bool unblock_ip(uint32_t address); - virtual std::map<uint32_t, time_t> get_blocked_ips() { CRITICAL_REGION_LOCAL(m_blocked_ips_lock); return m_blocked_ips; } + virtual bool block_host(const epee::net_utils::network_address &adress, time_t seconds = P2P_IP_BLOCKTIME); + virtual bool unblock_host(const epee::net_utils::network_address &address); + virtual std::map<std::string, time_t> get_blocked_hosts() { CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); return m_blocked_hosts; } private: const std::vector<std::string> m_seed_nodes_list = { "seeds.moneroseeds.se" @@ -186,11 +186,11 @@ namespace nodetool virtual bool drop_connection(const epee::net_utils::connection_context_base& context); virtual void request_callback(const epee::net_utils::connection_context_base& context); virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f); - virtual bool add_ip_fail(uint32_t address); + virtual bool add_host_fail(const epee::net_utils::network_address &address); //----------------- i_connection_filter -------------------------------------------------------- - virtual bool is_remote_ip_allowed(uint32_t adress); + virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address); //----------------------------------------------------------------------------------------------- - bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr); + bool parse_peer_from_string(epee::net_utils::network_address& pe, const std::string& node_addr, uint16_t default_port = 0); bool handle_command_line( const boost::program_options::variables_map& vm ); @@ -209,18 +209,18 @@ namespace nodetool bool make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist); bool make_new_connection_from_peerlist(bool use_white_list); - bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, PeerType peer_type = white, uint64_t first_seen_stamp = 0); + bool try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, PeerType peer_type = white, uint64_t first_seen_stamp = 0); size_t get_random_index_with_fixed_probability(size_t max_index); bool is_peer_used(const peerlist_entry& peer); bool is_peer_used(const anchor_peerlist_entry& peer); - bool is_addr_connected(const net_address& peer); + bool is_addr_connected(const epee::net_utils::network_address& peer); template<class t_callback> bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb); bool try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f); bool make_expected_connections_count(PeerType peer_type, size_t expected_connections); - void cache_connect_fail_info(const net_address& addr); - bool is_addr_recently_failed(const net_address& addr); - bool is_priority_node(const net_address& na); + void cache_connect_fail_info(const epee::net_utils::network_address& addr); + bool is_addr_recently_failed(const epee::net_utils::network_address& addr); + bool is_priority_node(const epee::net_utils::network_address& na); std::set<std::string> get_seed_nodes(bool testnet) const; template <class Container> @@ -236,9 +236,9 @@ 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 has_too_many_connections(const epee::net_utils::network_address &address); - bool check_connection_and_handshake_with_peer(const net_address& na, uint64_t last_seen_stamp); + bool check_connection_and_handshake_with_peer(const epee::net_utils::network_address& na, uint64_t last_seen_stamp); bool gray_peerlist_housekeeping(); void kill() { ///< will be called e.g. from deinit() @@ -308,23 +308,23 @@ namespace nodetool #ifdef ALLOW_DEBUG_COMMANDS uint64_t m_last_stat_request_time; #endif - std::list<net_address> m_priority_peers; - std::vector<net_address> m_exclusive_peers; - std::vector<net_address> m_seed_nodes; + std::list<epee::net_utils::network_address> m_priority_peers; + std::vector<epee::net_utils::network_address> m_exclusive_peers; + std::vector<epee::net_utils::network_address> m_seed_nodes; std::list<nodetool::peerlist_entry> m_command_line_peers; uint64_t m_peer_livetime; //keep connections to initiate some interactions net_server m_net_server; boost::uuids::uuid m_network_id; - std::map<net_address, time_t> m_conn_fails_cache; + std::map<epee::net_utils::network_address, time_t> m_conn_fails_cache; epee::critical_section m_conn_fails_cache_lock; - epee::critical_section m_blocked_ips_lock; - std::map<uint32_t, time_t> m_blocked_ips; + epee::critical_section m_blocked_hosts_lock; + std::map<std::string, time_t> m_blocked_hosts; - epee::critical_section m_ip_fails_score_lock; - std::map<uint32_t, uint64_t> m_ip_fails_score; + epee::critical_section m_host_fails_score_lock; + std::map<std::string, uint64_t> m_host_fails_score; bool m_testnet; }; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 5c903b1f5..47582cb96 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -200,16 +200,16 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_remote_ip_allowed(uint32_t addr) + bool node_server<t_payload_net_handler>::is_remote_host_allowed(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - auto it = m_blocked_ips.find(addr); - if(it == m_blocked_ips.end()) + CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); + auto it = m_blocked_hosts.find(address.host_str()); + if(it == m_blocked_hosts.end()) return true; if(time(nullptr) >= it->second) { - m_blocked_ips.erase(it); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked."); + m_blocked_hosts.erase(it); + MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); return true; } return false; @@ -229,16 +229,16 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::block_ip(uint32_t addr, time_t seconds) + bool node_server<t_payload_net_handler>::block_host(const epee::net_utils::network_address &addr, time_t seconds) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - m_blocked_ips[addr] = time(nullptr) + seconds; + 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) { - if (cntxt.m_remote_ip == addr) + if (cntxt.m_remote_address.is_same_host(addr)) { conns.push_back(cntxt.m_connection_id); } @@ -247,42 +247,42 @@ namespace nodetool for (const auto &c: conns) m_net_server.get_config_object().close(c); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " blocked."); + MCLOG_CYAN(el::Level::Info, "global", "Host " << addr.host_str() << " blocked."); return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::unblock_ip(uint32_t addr) + bool node_server<t_payload_net_handler>::unblock_host(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - auto i = m_blocked_ips.find(addr); - if (i == m_blocked_ips.end()) + CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); + auto i = m_blocked_hosts.find(address.host_str()); + if (i == m_blocked_hosts.end()) return false; - m_blocked_ips.erase(i); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked."); + m_blocked_hosts.erase(i); + MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::add_ip_fail(uint32_t address) + bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_ip_fails_score_lock); - uint64_t fails = ++m_ip_fails_score[address]; - MDEBUG("IP " << epee::string_tools::get_ip_string_from_int32(address) << " fail score=" << fails); + 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); if(fails > P2P_IP_FAILS_BEFORE_BLOCK) { - auto it = m_ip_fails_score.find(address); - CHECK_AND_ASSERT_MES(it != m_ip_fails_score.end(), false, "internal error"); + auto it = m_host_fails_score.find(address.host_str()); + CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); it->second = P2P_IP_FAILS_BEFORE_BLOCK/2; - block_ip(address); + block_host(address); } return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr) + 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::string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr); + return epee::net_utils::create_network_address(pe, node_addr, default_port); } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> @@ -306,10 +306,9 @@ namespace nodetool { nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe); pe.id = crypto::rand<uint64_t>(); - bool r = parse_peer_from_string(pe.adr, pr_str); + const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + bool r = parse_peer_from_string(pe.adr, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - if (pe.adr.port == 0) - pe.adr.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; m_command_line_peers.push_back(pe); } } @@ -359,7 +358,7 @@ namespace nodetool } //----------------------------------------------------------------------------------- inline void append_net_address( - std::vector<net_address> & seed_nodes + std::vector<epee::net_utils::network_address> & seed_nodes , std::string const & addr ) { @@ -383,15 +382,14 @@ namespace nodetool ip::tcp::endpoint endpoint = *i; if (endpoint.address().is_v4()) { - nodetool::net_address na; - na.ip = boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()); - na.port = endpoint.port(); + epee::net_utils::network_address na(new epee::net_utils::ipv4_network_address(boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()), endpoint.port())); seed_nodes.push_back(na); - MINFO("Added seed node: " << endpoint.address().to_v4().to_string(ec) << ':' << na.port); + MINFO("Added seed node: " << na.str()); } else { - MDEBUG("IPv6 doesn't supported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + MERROR("IPv6 unsupported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + throw std::runtime_error("IPv6 unsupported"); } } } @@ -752,10 +750,10 @@ namespace nodetool return; } - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.node_data.local_time, context)) + if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.node_data.local_time, context)) { LOG_ERROR_CC(context, "COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection."); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return; } hsh_result = true; @@ -769,7 +767,7 @@ 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_ip, context.m_remote_port); + m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address); if(rsp.node_data.peer_id == m_config.m_peer_id) { @@ -820,14 +818,14 @@ namespace nodetool return; } - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.local_time, context)) + 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 ); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); } if(!context.m_is_income) - m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_ip, context.m_remote_port); + m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address); m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false); }); @@ -862,7 +860,7 @@ namespace nodetool 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.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) + if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address)) { used = true; return false;//stop enumerating @@ -884,7 +882,7 @@ namespace nodetool 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.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) + if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address)) { used = true; @@ -898,12 +896,12 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_addr_connected(const net_address& peer) + bool node_server<t_payload_net_handler>::is_addr_connected(const epee::net_utils::network_address& peer) { bool connected = false; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if(!cntxt.m_is_income && peer.ip == cntxt.m_remote_ip && peer.port == cntxt.m_remote_port) + if(!cntxt.m_is_income && peer == cntxt.m_remote_address) { connected = true; return false;//stop enumerating @@ -924,7 +922,7 @@ namespace nodetool } while(0) template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp) + 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.connections_count) // out peers limit { @@ -936,23 +934,24 @@ namespace nodetool m_current_number_of_out_peers --; // atomic variable, update time = 1s return false; } - MDEBUG("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":" - << epee::string_tools::num_to_string_fast(na.port) << "(peer_type=" << peer_type << ", last_seen: " + 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.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << na.type().name()); + 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); - 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), + 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) { 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) + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str() /*<< ", try " << try_count*/); //m_peerlist.set_peer_unreachable(pe); return false; @@ -965,8 +964,7 @@ namespace nodetool { 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) + << na.str() /*<< ", try " << try_count*/); return false; } @@ -999,25 +997,26 @@ namespace nodetool } 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) + 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) { - 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: " + 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.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << na.type().name()); + 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); - 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), + 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) { 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)); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str()); return false; } @@ -1028,9 +1027,7 @@ namespace nodetool 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)); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " << na.str()); return false; } @@ -1046,7 +1043,7 @@ namespace nodetool //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_addr_recently_failed(const net_address& addr) + bool node_server<t_payload_net_handler>::is_addr_recently_failed(const epee::net_utils::network_address& addr) { CRITICAL_REGION_LOCAL(m_conn_fails_cache_lock); auto it = m_conn_fails_cache.find(addr); @@ -1063,14 +1060,14 @@ namespace nodetool bool node_server<t_payload_net_handler>::make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist) { for (const auto& pe: anchor_peerlist) { - _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port)); + _note("Considering connecting (out) to peer: " << pe.id << " " << pe.adr.str()); if(is_peer_used(pe)) { _note("Peer is used"); continue; } - if(!is_remote_ip_allowed(pe.adr.ip)) { + if(!is_remote_host_allowed(pe.adr)) { continue; } @@ -1078,8 +1075,7 @@ namespace nodetool continue; } - MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) - << ":" << boost::lexical_cast<std::string>(pe.adr.port) + MDEBUG("Selected peer: " << pe.id << " " << pe.adr.str() << "[peer_type=" << anchor << "] first_seen: " << epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen)); @@ -1130,21 +1126,20 @@ namespace nodetool ++try_count; - _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port)); + _note("Considering connecting (out) to peer: " << pe.id << " " << pe.adr.str()); if(is_peer_used(pe)) { _note("Peer is used"); continue; } - if(!is_remote_ip_allowed(pe.adr.ip)) + if(!is_remote_host_allowed(pe.adr)) continue; if(is_addr_recently_failed(pe.adr)) continue; - MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) - << ":" << boost::lexical_cast<std::string>(pe.adr.port) + MDEBUG("Selected peer: " << pe.id << " " << pe.adr.str() << "[peer_list=" << (use_white_list ? white : gray) << "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); @@ -1325,7 +1320,7 @@ namespace nodetool { if(be.last_seen > local_time) { - MWARNING("FOUND FUTURE peerlist for entry " << epee::string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); + MWARNING("FOUND FUTURE peerlist for entry " << be.adr.str() << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); return false; } be.last_seen += delta; @@ -1421,8 +1416,7 @@ namespace nodetool m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { connection_entry ce; - ce.adr.ip = cntxt.m_remote_ip; - ce.adr.port = cntxt.m_remote_port; + ce.adr = cntxt.m_remote_address; ce.id = cntxt.peer_id; ce.is_income = cntxt.m_is_income; rsp.connections_list.push_back(ce); @@ -1512,19 +1506,24 @@ namespace nodetool if(!node_data.my_port) return false; - uint32_t actual_ip = context.m_remote_ip; - if(!m_peerlist.is_ip_allowed(actual_ip)) + CHECK_AND_ASSERT_MES(context.m_remote_address.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << context.m_remote_address.type().name()); + + 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)) 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(new 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,*/ ip, port, pr, this]( + bool r = m_net_server.connect_async(ip, port, 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 { if(ec) { - LOG_WARNING_CC(ping_context, "back ping connect failed to " << ip << ":" << port); + LOG_WARNING_CC(ping_context, "back ping connect failed to " << address.str()); return false; } COMMAND_PING::request req; @@ -1543,13 +1542,13 @@ namespace nodetool { if(code <= 0) { - LOG_ERROR_CC(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); + LOG_ERROR_CC(ping_context, "Failed to invoke COMMAND_PING to " << address.str() << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); return; } if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id) { - LOG_ERROR_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << ip << ":" << port << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << rsp.peer_id); + LOG_ERROR_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); return; } @@ -1559,7 +1558,7 @@ namespace nodetool if(!inv_call_res) { - LOG_ERROR_CC(ping_context, "back ping invoke failed to " << ip << ":" << port); + LOG_ERROR_CC(ping_context, "back ping invoke failed to " << address.str()); m_net_server.get_config_object().close(ping_context.m_connection_id); return false; } @@ -1610,7 +1609,7 @@ namespace nodetool //fill response rsp.local_time = time(NULL); - m_peerlist.get_peerlist_head(rsp.local_peerlist); + m_peerlist.get_peerlist_head(rsp.local_peerlist_new); m_payload_handler.get_payload_sync_data(rsp.payload_data); LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC"); return 1; @@ -1624,7 +1623,7 @@ namespace nodetool LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id)); drop_connection(context); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return 1; } @@ -1632,7 +1631,7 @@ namespace nodetool { LOG_ERROR_CC(context, "COMMAND_HANDSHAKE came not from incoming connection"); drop_connection(context); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return 1; } @@ -1650,9 +1649,9 @@ namespace nodetool return 1; } - if(has_too_many_connections(context.m_remote_ip)) + if(has_too_many_connections(context.m_remote_address)) { - 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"); + LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << context.m_remote_address.host_str() << " REFUSED, too many connections from the same address"); drop_connection(context); return 1; } @@ -1667,16 +1666,18 @@ namespace nodetool //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.type() == typeid(epee::net_utils::ipv4_network_address), void(), + "Only IPv4 addresses are supported here, got " << context.m_remote_address.type().name()); //called only(!) if success pinged, update local peerlist peerlist_entry pe; - pe.adr.ip = context.m_remote_ip; - pe.adr.port = port_l; + const epee::net_utils::network_address na = context.m_remote_address; + pe.adr.reset(new epee::net_utils::ipv4_network_address(na.as<epee::net_utils::ipv4_network_address>().ip(), port_l)); time_t last_seen; time(&last_seen); pe.last_seen = static_cast<int64_t>(last_seen); pe.id = peer_id_l; this->m_peerlist.append_with_peer_white(pe); - LOG_DEBUG_CC(context, "PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); + LOG_DEBUG_CC(context, "PING SUCCESS " << context.m_remote_address.host_str() << ":" << port_l); }); } @@ -1686,7 +1687,7 @@ namespace nodetool }); //fill response - m_peerlist.get_peerlist_head(rsp.local_peerlist); + m_peerlist.get_peerlist_head(rsp.local_peerlist_new); get_local_node_data(rsp.node_data); m_payload_handler.get_payload_sync_data(rsp.payload_data); LOG_DEBUG_CC(context, "COMMAND_HANDSHAKE"); @@ -1726,7 +1727,7 @@ namespace nodetool std::stringstream ss; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - ss << epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port + ss << cntxt.m_remote_address.str() << " \t\tpeer_id " << cntxt.peer_id << " \t\tconn_id " << epee::string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT") << std::endl; @@ -1746,9 +1747,8 @@ namespace nodetool 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) { - nodetool::net_address na = AUTO_VAL_INIT(na); - na.ip = context.m_remote_ip; - na.port = context.m_remote_port; + epee::net_utils::network_address na = AUTO_VAL_INIT(na); + na = context.m_remote_address; m_peerlist.remove_from_peer_anchor(na); } @@ -1757,7 +1757,7 @@ namespace nodetool } template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_priority_node(const net_address& na) + bool node_server<t_payload_net_handler>::is_priority_node(const epee::net_utils::network_address& na) { return (std::find(m_priority_peers.begin(), m_priority_peers.end(), na) != m_priority_peers.end()) || (std::find(m_exclusive_peers.begin(), m_exclusive_peers.end(), na) != m_exclusive_peers.end()); } @@ -1765,7 +1765,7 @@ namespace nodetool template<class t_payload_net_handler> template <class Container> bool node_server<t_payload_net_handler>::connect_to_peerlist(const Container& peers) { - for(const net_address& na: peers) + for(const epee::net_utils::network_address& na: peers) { if(m_net_server.is_stop_signal_sent()) return false; @@ -1786,11 +1786,10 @@ namespace nodetool for(const std::string& pr_str: perrs) { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); + epee::net_utils::network_address na = AUTO_VAL_INIT(na); + const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + bool r = parse_peer_from_string(na, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - if (na.port == 0) - na.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; container.push_back(na); } @@ -1884,14 +1883,14 @@ namespace nodetool } template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::has_too_many_connections(const uint32_t ip) + bool node_server<t_payload_net_handler>::has_too_many_connections(const epee::net_utils::network_address &address) { 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) { + if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) { count++; if (count > max_connections) { @@ -1919,14 +1918,14 @@ namespace nodetool 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); + LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << pe.adr.host_str() << " 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); + LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << std::hex << pe.id); return true; } diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index 6aba7aa24..42de2655d 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -51,10 +51,10 @@ namespace nodetool virtual void request_callback(const epee::net_utils::connection_context_base& context)=0; virtual uint64_t get_connections_count()=0; virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0; - virtual bool block_ip(uint32_t adress, time_t seconds = 0)=0; - virtual bool unblock_ip(uint32_t adress)=0; - virtual std::map<uint32_t, time_t> get_blocked_ips()=0; - virtual bool add_ip_fail(uint32_t adress)=0; + virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds = 0)=0; + virtual bool unblock_host(const epee::net_utils::network_address &address)=0; + virtual std::map<std::string, time_t> get_blocked_hosts()=0; + virtual bool add_host_fail(const epee::net_utils::network_address &address)=0; }; template<class t_connection_context> @@ -93,19 +93,19 @@ namespace nodetool { return false; } - virtual bool block_ip(uint32_t adress, time_t seconds) + virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds) { return true; } - virtual bool unblock_ip(uint32_t adress) + virtual bool unblock_host(const epee::net_utils::network_address &address) { return true; } - virtual std::map<uint32_t, time_t> get_blocked_ips() + virtual std::map<std::string, time_t> get_blocked_hosts() { - return std::map<uint32_t, time_t>(); + return std::map<std::string, time_t>(); } - virtual bool add_ip_fail(uint32_t adress) + virtual bool add_host_fail(const epee::net_utils::network_address &address) { return true; } diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index de0f51cc3..a30a05422 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -54,7 +54,7 @@ #include "net_peerlist_boost_serialization.h" -#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 5 +#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 6 namespace nodetool { @@ -78,14 +78,13 @@ namespace nodetool bool append_with_peer_white(const peerlist_entry& pr); bool append_with_peer_gray(const peerlist_entry& pr); bool append_with_peer_anchor(const anchor_peerlist_entry& ple); - bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port); - bool set_peer_just_seen(peerid_type peer, const net_address& addr); + bool set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address& addr); bool set_peer_unreachable(const peerlist_entry& pr); - bool is_ip_allowed(uint32_t ip); + bool is_host_allowed(const epee::net_utils::network_address &address); bool get_random_gray_peer(peerlist_entry& pe); bool remove_from_peer_gray(const peerlist_entry& pe); bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl); - bool remove_from_peer_anchor(const net_address& addr); + bool remove_from_peer_anchor(const epee::net_utils::network_address& addr); private: struct by_time{}; @@ -130,7 +129,7 @@ namespace nodetool peerlist_entry, boost::multi_index::indexed_by< // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,epee::net_utils::network_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > @@ -142,7 +141,7 @@ namespace nodetool // access by peerlist_entry::id< boost::multi_index::ordered_unique<boost::multi_index::tag<by_id>, boost::multi_index::member<peerlist_entry,uint64_t,&peerlist_entry::id> >, // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,epee::net_utils::network_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > @@ -152,16 +151,45 @@ namespace nodetool anchor_peerlist_entry, boost::multi_index::indexed_by< // access by anchor_peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,net_address,&anchor_peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,epee::net_utils::network_address,&anchor_peerlist_entry::adr> >, // sort by anchor_peerlist_entry::first_seen boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<anchor_peerlist_entry,int64_t,&anchor_peerlist_entry::first_seen> > > > anchor_peers_indexed; public: + template <class Archive, class List, class Element, class t_version_type> + void serialize_peers(Archive &a, List &list, Element ple, const t_version_type ver) + { + if (typename Archive::is_saving()) + { + uint64_t size = list.size(); + a & size; + for (auto p: list) + { + a & p; + } + } + else + { + uint64_t size; + a & size; + list.clear(); + while (size--) + { + a & ple; + list.insert(ple); + } + } + } + template <class Archive, class t_version_type> void serialize(Archive &a, const t_version_type ver) { + // at v6, we drop existing peerlists, because annoying change + if (ver < 6) + return; + if(ver < 3) return; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -174,14 +202,25 @@ namespace nodetool return; } +#if 0 + // trouble loading more than one peer, can't find why a & m_peers_white; a & m_peers_gray; +#else + serialize_peers(a, m_peers_white, peerlist_entry(), ver); + serialize_peers(a, m_peers_gray, peerlist_entry(), ver); +#endif if(ver < 5) { return; } +#if 0 + // trouble loading more than one peer, can't find why a & m_peers_anchor; +#else + serialize_peers(a, m_peers_anchor, anchor_peerlist_entry(), ver); +#endif } private: @@ -284,13 +323,13 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::is_ip_allowed(uint32_t ip) + bool peerlist_manager::is_host_allowed(const epee::net_utils::network_address &address) { //never allow loopback ip - if(epee::net_utils::is_ip_loopback(ip)) + if(address.is_loopback()) return false; - if(!m_allow_local_ip && epee::net_utils::is_ip_local(ip)) + if(!m_allow_local_ip && address.is_local()) return false; return true; @@ -336,16 +375,7 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port) - { - net_address addr; - addr.ip = ip; - addr.port = port; - return set_peer_just_seen(peer, addr); - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, const net_address& addr) + bool peerlist_manager::set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address& addr) { TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -362,7 +392,7 @@ namespace nodetool bool peerlist_manager::append_with_peer_white(const peerlist_entry& ple) { TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) + if(!is_host_allowed(ple.adr)) return true; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -392,7 +422,7 @@ namespace nodetool bool peerlist_manager::append_with_peer_gray(const peerlist_entry& ple) { TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) + if(!is_host_allowed(ple.adr)) return true; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -496,7 +526,7 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::remove_from_peer_anchor(const net_address& addr) + bool peerlist_manager::remove_from_peer_anchor(const epee::net_utils::network_address& addr) { TRY_ENTRY(); diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 6891ac80c..0a21895cf 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_boost_serialization.h @@ -30,16 +30,43 @@ #pragma once +#include "net/net_utils_base.h" + namespace boost { namespace serialization { - //BOOST_CLASS_VERSION(odetool::net_adress, 1) + enum { sertype_ipv4_address }; + static inline uint8_t get_type(const epee::net_utils::network_address &na) + { + if (na.type() == typeid(epee::net_utils::ipv4_network_address)) + return sertype_ipv4_address; + throw std::runtime_error("Unsupported network address type"); + return 0; + } + template <class Archive, class ver_type> + inline void serialize(Archive &a, epee::net_utils::network_address& na, const ver_type ver) + { + uint8_t type; + if (typename Archive::is_saving()) + type = get_type(na); + a & type; + switch (type) + { + case sertype_ipv4_address: + if (!typename Archive::is_saving()) + na.reset(new epee::net_utils::ipv4_network_address(0, 0)); + a & na.as<epee::net_utils::ipv4_network_address>(); + break; + default: + throw std::runtime_error("Unsupported network address type"); + } + } template <class Archive, class ver_type> - inline void serialize(Archive &a, nodetool::net_address& na, const ver_type ver) + inline void serialize(Archive &a, epee::net_utils::ipv4_network_address& na, const ver_type ver) { - a & na.ip; - a & na.port; + a & na.m_ip; + a & na.m_port; } diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 5ec012714..d60990f8a 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -32,6 +32,7 @@ #include <boost/uuid/uuid.hpp> #include "serialization/keyvalue_serialization.h" +#include "net/net_utils_base.h" #include "misc_language.h" #include "cryptonote_config.h" #include "crypto/crypto.h" @@ -43,46 +44,64 @@ namespace nodetool #pragma pack (push, 1) - struct net_address + struct network_address_old { uint32_t ip; uint32_t port; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(ip) + KV_SERIALIZE(port) + END_KV_SERIALIZE_MAP() }; - struct peerlist_entry + template<typename AddressType> + struct peerlist_entry_base { - net_address adr; + AddressType adr; peerid_type id; int64_t last_seen; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(last_seen) + END_KV_SERIALIZE_MAP() }; + typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry; - struct anchor_peerlist_entry + template<typename AddressType> + struct anchor_peerlist_entry_base { - net_address adr; + AddressType adr; peerid_type id; int64_t first_seen; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(first_seen) + END_KV_SERIALIZE_MAP() }; + typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry; - struct connection_entry + template<typename AddressType> + struct connection_entry_base { - net_address adr; + AddressType adr; peerid_type id; bool is_income; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(is_income) + END_KV_SERIALIZE_MAP() }; + typedef connection_entry_base<epee::net_utils::network_address> connection_entry; #pragma pack(pop) - inline - bool operator < (const net_address& a, const net_address& b) - { - return epee::misc_utils::is_less_as_pod(a, b); - } - - inline - bool operator == (const net_address& a, const net_address& b) - { - return memcmp(&a, &b, sizeof(a)) == 0; - } inline std::string print_peerlist_to_string(const std::list<peerlist_entry>& pl) { @@ -92,7 +111,7 @@ namespace nodetool ss << std::setfill ('0') << std::setw (8) << std::hex << std::noshowbase; for(const peerlist_entry& pe: pl) { - ss << pe.id << "\t" << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port) << " \tlast_seen: " << epee::misc_utils::get_time_interval_string(now_time - pe.last_seen) << std::endl; + ss << pe.id << "\t" << pe.adr->str() << " \tlast_seen: " << epee::misc_utils::get_time_interval_string(now_time - pe.last_seen) << std::endl; } return ss.str(); } @@ -157,12 +176,40 @@ namespace nodetool { basic_node_data node_data; t_playload_type payload_data; - std::list<peerlist_entry> local_peerlist; + std::list<peerlist_entry> local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(node_data) KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) + if (is_store) + { + // saving: save both, so old and new peers can understand it + KV_SERIALIZE(local_peerlist_new) + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + for (const auto &p: this_ref.local_peerlist_new) + { + if (p.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + { + const epee::net_utils::network_address &na = p.adr; + const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>(); + local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); + } + else + MDEBUG("Not including in legacy peer list: " << p.adr.str()); + } + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + } + else + { + // loading: load old list only if there is no new one + if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) + { + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + for (const auto &p: local_peerlist) + ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({new epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); + } + } END_KV_SERIALIZE_MAP() }; }; @@ -188,12 +235,40 @@ namespace nodetool { uint64_t local_time; t_playload_type payload_data; - std::list<peerlist_entry> local_peerlist; + std::list<peerlist_entry> local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(local_time) KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) + if (is_store) + { + // saving: save both, so old and new peers can understand it + KV_SERIALIZE(local_peerlist_new) + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + for (const auto &p: this_ref.local_peerlist_new) + { + if (p.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + { + const epee::net_utils::network_address &na = p.adr; + const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>(); + local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); + } + else + MDEBUG("Not including in legacy peer list: " << p.adr.str()); + } + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + } + else + { + // loading: load old list only if there is no new one + if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) + { + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + for (const auto &p: local_peerlist) + ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({new epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); + } + } END_KV_SERIALIZE_MAP() }; }; |