diff --git a/Makefile.am b/Makefile.am index 943eb918a..6dc738bdc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,7 +71,8 @@ src_libbitcoin_node_la_SOURCES = \ src/sessions/session.cpp \ src/sessions/session_inbound.cpp \ src/sessions/session_manual.cpp \ - src/sessions/session_outbound.cpp + src/sessions/session_outbound.cpp \ + src/sessions/session_tcp.cpp # local: test/libbitcoin-node-test #------------------------------------------------------------------------------ @@ -200,6 +201,7 @@ include_bitcoin_node_sessions_HEADERS = \ include/bitcoin/node/sessions/session_inbound.hpp \ include/bitcoin/node/sessions/session_manual.hpp \ include/bitcoin/node/sessions/session_outbound.hpp \ + include/bitcoin/node/sessions/session_tcp.hpp \ include/bitcoin/node/sessions/sessions.hpp # files => ${bash_completiondir} diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 0915effc5..215ccec4d 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -283,7 +283,8 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/sessions/session.cpp" "../../src/sessions/session_inbound.cpp" "../../src/sessions/session_manual.cpp" - "../../src/sessions/session_outbound.cpp" ) + "../../src/sessions/session_outbound.cpp" + "../../src/sessions/session_tcp.cpp" ) # ${CANONICAL_LIB_NAME} project specific include directory normalization for build. #------------------------------------------------------------------------------ diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj index 70940f6e0..b0d09e10c 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj @@ -157,6 +157,7 @@ + @@ -204,6 +205,7 @@ + diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters index 5b350838e..2f73303a8 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters @@ -156,6 +156,9 @@ src\sessions + + src\sessions + src @@ -293,6 +296,9 @@ include\bitcoin\node\sessions + + include\bitcoin\node\sessions + include\bitcoin\node\sessions diff --git a/include/bitcoin/node.hpp b/include/bitcoin/node.hpp index 64146c496..c95f9dc9a 100644 --- a/include/bitcoin/node.hpp +++ b/include/bitcoin/node.hpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #endif diff --git a/include/bitcoin/node/full_node.hpp b/include/bitcoin/node/full_node.hpp index 90fc5833c..438326b0b 100644 --- a/include/bitcoin/node/full_node.hpp +++ b/include/bitcoin/node/full_node.hpp @@ -25,8 +25,7 @@ #include #include #include -////#include -////#include +#include namespace libbitcoin { namespace node { @@ -45,6 +44,7 @@ class BCN_API full_node using store = node::store; using query = node::query; using memory_controller = block_memory; + using result_handler = network::result_handler; typedef std::shared_ptr ptr; /// Constructors. @@ -59,10 +59,10 @@ class BCN_API full_node /// ----------------------------------------------------------------------- /// Start the node (seed and manual services). - void start(network::result_handler&& handler) NOEXCEPT override; + void start(result_handler&& handler) NOEXCEPT override; /// Run the node (inbound/outbound services and blockchain chasers). - void run(network::result_handler&& handler) NOEXCEPT override; + void run(result_handler&& handler) NOEXCEPT override; /// Close the node. void close() NOEXCEPT override; @@ -81,7 +81,7 @@ class BCN_API full_node /// Manage download queue. virtual void get_hashes(map_handler&& handler) NOEXCEPT; virtual void put_hashes(const map_ptr& map, - network::result_handler&& handler) NOEXCEPT; + result_handler&& handler) NOEXCEPT; /// Events. /// ----------------------------------------------------------------------- @@ -149,7 +149,7 @@ class BCN_API full_node /// Handle performance, base returns false (implied terminate). virtual void performance(object_key channel, uint64_t speed, - network::result_handler&& handler) NOEXCEPT; + result_handler&& handler) NOEXCEPT; /// Get the memory resource. virtual network::memory& get_memory() NOEXCEPT; @@ -160,14 +160,17 @@ class BCN_API full_node network::session_manual::ptr attach_manual_session() NOEXCEPT override; network::session_inbound::ptr attach_inbound_session() NOEXCEPT override; network::session_outbound::ptr attach_outbound_session() NOEXCEPT override; + virtual session_explore::ptr attach_explore_session() NOEXCEPT; /// Virtual handlers. /// ----------------------------------------------------------------------- - void do_start(const network::result_handler& handler) NOEXCEPT override; - void do_run(const network::result_handler& handler) NOEXCEPT override; + void do_start(const result_handler& handler) NOEXCEPT override; + void do_run(const result_handler& handler) NOEXCEPT override; void do_close() NOEXCEPT override; private: + void start_explore(const code& ec, const result_handler& handler) NOEXCEPT; + void do_subscribe_events(const event_notifier& handler, const event_completer& complete) NOEXCEPT; void do_notify(const code& ec, chase event_, event_value value) NOEXCEPT; diff --git a/include/bitcoin/node/protocols/protocol.hpp b/include/bitcoin/node/protocols/protocol.hpp index 95e4b010f..1110bfbda 100644 --- a/include/bitcoin/node/protocols/protocol.hpp +++ b/include/bitcoin/node/protocols/protocol.hpp @@ -29,6 +29,11 @@ namespace libbitcoin { namespace node { +/////////////////////////////////////////////////////////////////////////////// +// TODO: ... -> node::protocol_tcp -> node::protocol -> network::protocol. // +// TODO: ... -> node::protocol_peer -> node::protocol -> network::protocol. // +/////////////////////////////////////////////////////////////////////////////// + /// Abstract base for node protocols, thread safe. class BCN_API protocol : public network::protocol_peer diff --git a/include/bitcoin/node/sessions/attach.hpp b/include/bitcoin/node/sessions/attach.hpp index a85f0aab6..da23f4bff 100644 --- a/include/bitcoin/node/sessions/attach.hpp +++ b/include/bitcoin/node/sessions/attach.hpp @@ -20,6 +20,7 @@ #define LIBBITCOIN_NODE_SESSIONS_ATTACH_HPP #include +#include #include #include #include @@ -30,7 +31,7 @@ namespace node { class full_node; -/// Session base class template for protocol attachment. +/// Session base class template for network session attachment. /// node::session does not derive from network::session (siblings). /// This avoids the diamond inheritance problem between network/node. /// Protocol contructors are templatized on Session, obtaining session. @@ -39,8 +40,10 @@ class attach : public Session, public node::session { public: - attach(full_node& node, uint64_t identifier) NOEXCEPT - : Session(node, identifier), session(node) + template + attach(full_node& node, uint64_t identifier, Args&&... args) NOEXCEPT + : Session(node, identifier, std::forward(args)...), + node::session(node) { } @@ -56,21 +59,22 @@ class attach Session::attach_handshake(channel, std::move(handler)); } - void attach_protocols(const network::channel::ptr& channel) NOEXCEPT override + void attach_protocols( + const network::channel::ptr& channel) NOEXCEPT override { using namespace system; using namespace network::messages::peer; - const auto relay = config().network.enable_relay; - const auto delay = config().node.delay_inbound; - const auto headers = config().node.headers_first; + const auto relay = this->config().network.enable_relay; + const auto delay = this->config().node.delay_inbound; + const auto headers = this->config().node.headers_first; const auto node_network = to_bool(bit_and ( - config().network.services_maximum, + this->config().network.services_maximum, network::messages::peer::service::node_network )); const auto node_client_filters = to_bool(bit_and ( - config().network.services_maximum, + this->config().network.services_maximum, network::messages::peer::service::node_client_filters )); @@ -158,12 +162,12 @@ class attach } } - network::channel::ptr create_channel(const network::socket::ptr& socket) NOEXCEPT override + network::channel::ptr create_channel( + const network::socket::ptr& socket) NOEXCEPT override { return std::static_pointer_cast( - std::make_shared(node::session::get_memory(), - network::session::log, socket, node::session::config(), - network::session::create_key())); + std::make_shared(this->get_memory(), this->log, + socket, this->config(), this->create_key())); } }; diff --git a/include/bitcoin/node/sessions/session_tcp.hpp b/include/bitcoin/node/sessions/session_tcp.hpp new file mode 100644 index 000000000..4e0dcc58e --- /dev/null +++ b/include/bitcoin/node/sessions/session_tcp.hpp @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_NODE_SESSIONS_SESSION_TCP_HPP +#define LIBBITCOIN_NODE_SESSIONS_SESSION_TCP_HPP + +#include +#include +#include + +namespace libbitcoin { +namespace node { + +class full_node; + +class session_tcp + : public network::session_tcp, public node::session +{ +public: + typedef std::shared_ptr ptr; + using options_t = network::session_tcp::options_t; + + session_tcp(full_node& node, uint64_t identifier, + const options_t& options) NOEXCEPT; + +protected: + inline bool enabled() const NOEXCEPT override; +}; + +// TODO: move all sessions up from network. +////using session_web = network::session_server; +using session_explore = network::session_server; +////using session_websocket = network::session_server; +////using session_bitcoind = network::session_server; +////using session_electrum = network::session_server; +////using session_stratum_v1 = network::session_server; +////using session_stratum_v2 = network::session_server; + +} // namespace node +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/node/sessions/sessions.hpp b/include/bitcoin/node/sessions/sessions.hpp index 931852b52..dec55b118 100644 --- a/include/bitcoin/node/sessions/sessions.hpp +++ b/include/bitcoin/node/sessions/sessions.hpp @@ -24,5 +24,6 @@ #include #include #include +#include #endif diff --git a/src/full_node.cpp b/src/full_node.cpp index c1756d8a5..12515520a 100644 --- a/src/full_node.cpp +++ b/src/full_node.cpp @@ -23,8 +23,7 @@ #include #include #include -////#include -////#include +#include namespace libbitcoin { namespace node { @@ -32,6 +31,7 @@ namespace node { using namespace system; using namespace database; using namespace network; +using namespace std::placeholders; BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) @@ -117,7 +117,28 @@ void full_node::do_run(const result_handler& handler) NOEXCEPT // This will kick off lagging validations even if not current. do_notify(error::success, chase::start, height_t{}); - net::do_run(handler); + // Start services after network is running. + net::do_run(std::bind(&full_node::start_explore, this, _1, handler)); +} + +void full_node::start_explore(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + if (!config().network.explore.enabled()) + { + handler(ec); + return; + } + + attach_explore_session()->start(move_copy(handler)); } void full_node::close() NOEXCEPT @@ -433,6 +454,11 @@ network::session_outbound::ptr full_node::attach_outbound_session() NOEXCEPT return attach(*this); } +session_explore::ptr full_node::attach_explore_session() NOEXCEPT +{ + return net::attach(*this, config_.network.explore); +} + BC_POP_WARNING() } // namespace node diff --git a/src/sessions/session_tcp.cpp b/src/sessions/session_tcp.cpp new file mode 100644 index 000000000..842a92120 --- /dev/null +++ b/src/sessions/session_tcp.cpp @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include + +namespace libbitcoin { +namespace node { + +session_tcp::session_tcp(full_node& node, uint64_t identifier, + const options_t& options) NOEXCEPT + : network::session_tcp(node, identifier, options), + node::session(node) +{ +} + +// Inbound connection attempts are dropped unless confirmed chain is current. +// Used instead of suspension because suspension has independent start/stop. +bool session_tcp::enabled() const NOEXCEPT +{ + return !config().node.delay_inbound || is_recent(); +} + +} // namespace node +} // namespace libbitcoin