From 5c416e3a5b39316eb034f3170bc007036e419fe2 Mon Sep 17 00:00:00 2001 From: Meheboob Khan Date: Wed, 7 Sep 2022 13:57:00 +0000 Subject: [PATCH] Port net library --- libraries/net/core_messages.cpp | 1 - libraries/net/include/graphene/net/config.hpp | 5 + libraries/net/include/graphene/net/node.hpp | 29 ++++- .../include/graphene/net/peer_connection.hpp | 3 +- .../include/graphene/net/peer_database.hpp | 2 +- libraries/net/node.cpp | 117 ++++++++++++++++++ libraries/net/peer_database.cpp | 3 +- 7 files changed, 154 insertions(+), 6 deletions(-) diff --git a/libraries/net/core_messages.cpp b/libraries/net/core_messages.cpp index efff812d..3a4b842c 100644 --- a/libraries/net/core_messages.cpp +++ b/libraries/net/core_messages.cpp @@ -47,4 +47,3 @@ namespace graphene { namespace net { const core_message_type_enum get_current_connections_reply_message::type = core_message_type_enum::get_current_connections_reply_message_type; } } // graphene::net - diff --git a/libraries/net/include/graphene/net/config.hpp b/libraries/net/include/graphene/net/config.hpp index 9edca51c..894850d6 100644 --- a/libraries/net/include/graphene/net/config.hpp +++ b/libraries/net/include/graphene/net/config.hpp @@ -23,6 +23,8 @@ */ #pragma once +#include + #define GRAPHENE_NET_PROTOCOL_VERSION 106 /** @@ -110,3 +112,6 @@ #define GRAPHENE_NET_MAX_NESTED_OBJECTS (250) #define MAXIMUM_PEERDB_SIZE 1000 + +constexpr size_t MAX_BLOCKS_TO_HANDLE_AT_ONCE = 200; +constexpr size_t MAX_SYNC_BLOCKS_TO_PREFETCH = 10 * MAX_BLOCKS_TO_HANDLE_AT_ONCE; diff --git a/libraries/net/include/graphene/net/node.hpp b/libraries/net/include/graphene/net/node.hpp index adbaf262..cbf5c594 100644 --- a/libraries/net/include/graphene/net/node.hpp +++ b/libraries/net/include/graphene/net/node.hpp @@ -61,7 +61,7 @@ namespace graphene { namespace net { class node_delegate { public: - virtual ~node_delegate(){} + virtual ~node_delegate() = default; /** * If delegate has the item, the network has no need to fetch it. @@ -71,7 +71,9 @@ namespace graphene { namespace net { /** * @brief Called when a new block comes in from the network * + * @param blk_msg the message which contains the block * @param sync_mode true if the message was fetched through the sync process, false during normal operation + * @param contained_transaction_msg_ids container for the transactions to write back into * @returns true if this message caused the blockchain to switch forks, false if it did not * * @throws exception if error validating the item, otherwise the item is @@ -195,7 +197,7 @@ namespace graphene { namespace net { { public: node(const std::string& user_agent); - ~node(); + virtual ~node(); void close(); @@ -213,11 +215,34 @@ namespace graphene { namespace net { */ void add_node( const fc::ip::endpoint& ep ); + /***** + * @brief add a list of nodes to seed the p2p network + * @param seeds a vector of url strings + */ + void add_seed_nodes( std::vector seeds ); + + /**** + * @brief add a node to seed the p2p network + * @param in the url as a string + */ + void add_seed_node( const std::string& in); + /** * Attempt to connect to the specified endpoint immediately. */ virtual void connect_to_endpoint( const fc::ip::endpoint& ep ); + /** + * @brief Helper to convert a string to a collection of endpoints + * + * This converts a string (i.e. "bitshares.eu:665535" to a collection of endpoints. + * NOTE: Throws an exception if not in correct format or was unable to resolve URL. + * + * @param in the incoming string + * @returns a vector of endpoints + */ + static std::vector resolve_string_to_ip_endpoints( const std::string& in ); + /** * Specifies the network interface and port upon which incoming * connections should be accepted. diff --git a/libraries/net/include/graphene/net/peer_connection.hpp b/libraries/net/include/graphene/net/peer_connection.hpp index 0cd0288f..58c467a6 100644 --- a/libraries/net/include/graphene/net/peer_connection.hpp +++ b/libraries/net/include/graphene/net/peer_connection.hpp @@ -62,6 +62,7 @@ namespace graphene { namespace net class peer_connection_delegate { public: + virtual ~peer_connection_delegate() = default; virtual void on_message(peer_connection* originating_peer, const message& received_message) = 0; virtual void on_connection_closed(peer_connection* originating_peer) = 0; @@ -125,7 +126,7 @@ namespace graphene { namespace net * it is sitting on the queue */ virtual size_t get_size_in_queue() = 0; - virtual ~queued_message() {} + virtual ~queued_message() = default; }; /* when you queue up a 'real_queued_message', a full copy of the message is diff --git a/libraries/net/include/graphene/net/peer_database.hpp b/libraries/net/include/graphene/net/peer_database.hpp index ff7f4036..3aadf599 100644 --- a/libraries/net/include/graphene/net/peer_database.hpp +++ b/libraries/net/include/graphene/net/peer_database.hpp @@ -97,7 +97,7 @@ namespace graphene { namespace net { { public: peer_database(); - ~peer_database(); + virtual ~peer_database(); void open(const fc::path& databaseFilename); void close(); diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 8b797d4a..85e8c676 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -555,6 +556,10 @@ namespace graphene { namespace net { namespace detail { fc::future _bandwidth_monitor_loop_done; fc::future _dump_node_status_task_done; + /// Used by the task that checks whether addresses of seed nodes have been updated + /// @{ + boost::container::flat_set _seed_nodes; + fc::future _update_seed_nodes_loop_done; /* We have two alternate paths through the schedule_peer_for_deletion code -- one that * uses a mutex to prevent one fiber from adding items to the queue while another is deleting @@ -728,6 +733,11 @@ namespace graphene { namespace net { namespace detail { void listen_to_p2p_network(); void connect_to_p2p_network(); void add_node( const fc::ip::endpoint& ep ); + void add_seed_node( const std::string& in); + void add_seed_nodes( std::vector seeds ); + void resolve_seed_node_and_add( const std::string& seed_string ); + void update_seed_nodes_task(); + void schedule_next_update_seed_nodes_task(); void initiate_connect_to(const peer_connection_ptr& peer); void connect_to_endpoint(const fc::ip::endpoint& ep); void listen_on_endpoint(const fc::ip::endpoint& ep , bool wait_if_not_available); @@ -4757,7 +4767,69 @@ namespace graphene { namespace net { namespace detail { _potential_peer_db.update_entry(updated_peer_record); trigger_p2p_network_connect_loop(); } + void node_impl::add_seed_node(const std::string& endpoint_string) + { + VERIFY_CORRECT_THREAD(); + _seed_nodes.insert( endpoint_string ); + resolve_seed_node_and_add( endpoint_string ); + } + void node_impl::resolve_seed_node_and_add(const std::string& endpoint_string) + { + VERIFY_CORRECT_THREAD(); + std::vector endpoints; + ilog("Resolving seed node ${endpoint}", ("endpoint", endpoint_string)); + try + { + endpoints = graphene::net::node::resolve_string_to_ip_endpoints(endpoint_string); + } + catch(...) + { + wlog( "Unable to resolve endpoint during attempt to add seed node ${ep}", ("ep", endpoint_string) ); + } + for (const fc::ip::endpoint& endpoint : endpoints) + { + ilog("Adding seed node ${endpoint}", ("endpoint", endpoint)); + add_node(endpoint); + } + } + void node_impl::update_seed_nodes_task() + { + VERIFY_CORRECT_THREAD(); + try + { + dlog("Starting an iteration of update_seed_nodes loop."); + for( const std::string& endpoint_string : _seed_nodes ) + { + resolve_seed_node_and_add( endpoint_string ); + } + dlog("Done an iteration of update_seed_nodes loop."); + } + catch (const fc::canceled_exception&) + { + ilog( "update_seed_nodes_task canceled" ); + throw; + } + FC_CAPTURE_AND_LOG( (_seed_nodes) ) + + schedule_next_update_seed_nodes_task(); + } + + void node_impl::schedule_next_update_seed_nodes_task() + { + VERIFY_CORRECT_THREAD(); + + if( _node_is_shutting_down ) + return; + + if( _update_seed_nodes_loop_done.valid() && _update_seed_nodes_loop_done.canceled() ) + return; + + _update_seed_nodes_loop_done = fc::schedule( [this]() { update_seed_nodes_task(); }, + fc::time_point::now() + fc::hours(3), + "update_seed_nodes_loop" ); + } + void node_impl::initiate_connect_to(const peer_connection_ptr& new_peer) { new_peer->get_socket().open(); @@ -5296,6 +5368,11 @@ namespace graphene { namespace net { namespace detail { INVOKE_IN_IMPL(add_node, ep); } + void node::add_seed_node(const std::string& in) + { + INVOKE_IN_IMPL(add_seed_node, in); + } + void node::connect_to_endpoint( const fc::ip::endpoint& remote_endpoint ) { INVOKE_IN_IMPL(connect_to_endpoint, remote_endpoint); @@ -5677,5 +5754,45 @@ namespace graphene { namespace net { namespace detail { #undef INVOKE_AND_COLLECT_STATISTICS } // end namespace detail + std::vector node::resolve_string_to_ip_endpoints(const std::string& in) + { + try + { + std::string::size_type colon_pos = in.find(':'); + if (colon_pos == std::string::npos) + FC_THROW("Missing required port number in endpoint string \"${endpoint_string}\"", + ("endpoint_string", in)); + std::string port_string = in.substr(colon_pos + 1); + try + { + uint16_t port = boost::lexical_cast(port_string); + + std::string hostname = in.substr(0, colon_pos); + std::vector endpoints = fc::resolve(hostname, port); + if (endpoints.empty()) + FC_THROW_EXCEPTION( fc::unknown_host_exception, + "The host name can not be resolved: ${hostname}", + ("hostname", hostname) ); + return endpoints; + } + catch (const boost::bad_lexical_cast&) + { + FC_THROW("Bad port: ${port}", ("port", port_string)); + } + } + FC_CAPTURE_AND_RETHROW((in)) + } + void node::add_seed_nodes(std::vector seeds) + { + for(const std::string& endpoint_string : seeds ) + { + try { + add_seed_node(endpoint_string); + } catch( const fc::exception& e ) { + wlog( "caught exception ${e} while adding seed node ${endpoint}", + ("e", e.to_detail_string())("endpoint", endpoint_string) ); + } + } + } } } // end namespace graphene::net diff --git a/libraries/net/peer_database.cpp b/libraries/net/peer_database.cpp index 76ae9c8c..20bc5da9 100644 --- a/libraries/net/peer_database.cpp +++ b/libraries/net/peer_database.cpp @@ -50,7 +50,8 @@ namespace graphene { namespace net { indexed_by, member >, + &potential_peer_record::last_seen_time>, + std::greater >, hashed_unique, member