diff --git a/Makefile.am b/Makefile.am index 8494a00aa..d14558119 100644 --- a/Makefile.am +++ b/Makefile.am @@ -37,12 +37,12 @@ src_libbitcoin_node_la_LIBADD = ${bitcoin_database_LIBS} ${bitcoin_network_LIBS} src_libbitcoin_node_la_SOURCES = \ src/block_arena.cpp \ src/block_memory.cpp \ - src/channel_peer.cpp \ src/configuration.cpp \ src/error.cpp \ src/full_node.cpp \ src/parser.cpp \ src/settings.cpp \ + src/channels/channel_peer.cpp \ src/chasers/chaser.cpp \ src/chasers/chaser_block.cpp \ src/chasers/chaser_check.cpp \ @@ -65,6 +65,7 @@ src_libbitcoin_node_la_SOURCES = \ src/protocols/protocol_header_out_31800.cpp \ src/protocols/protocol_header_out_70012.cpp \ src/protocols/protocol_observer.cpp \ + src/protocols/protocol_peer.cpp \ src/protocols/protocol_performer.cpp \ src/protocols/protocol_transaction_in_106.cpp \ src/protocols/protocol_transaction_out_106.cpp \ @@ -145,7 +146,6 @@ include_bitcoin_nodedir = ${includedir}/bitcoin/node include_bitcoin_node_HEADERS = \ include/bitcoin/node/block_arena.hpp \ include/bitcoin/node/block_memory.hpp \ - include/bitcoin/node/channel_peer.hpp \ include/bitcoin/node/chase.hpp \ include/bitcoin/node/configuration.hpp \ include/bitcoin/node/define.hpp \ @@ -156,6 +156,13 @@ include_bitcoin_node_HEADERS = \ include/bitcoin/node/settings.hpp \ include/bitcoin/node/version.hpp +include_bitcoin_node_channelsdir = ${includedir}/bitcoin/node/channels +include_bitcoin_node_channels_HEADERS = \ + include/bitcoin/node/channels/channel.hpp \ + include/bitcoin/node/channels/channel_peer.hpp \ + include/bitcoin/node/channels/channel_tcp.hpp \ + include/bitcoin/node/channels/channels.hpp + include_bitcoin_node_chasersdir = ${includedir}/bitcoin/node/chasers include_bitcoin_node_chasers_HEADERS = \ include/bitcoin/node/chasers/chaser.hpp \ @@ -189,7 +196,9 @@ include_bitcoin_node_protocols_HEADERS = \ include/bitcoin/node/protocols/protocol_header_out_31800.hpp \ include/bitcoin/node/protocols/protocol_header_out_70012.hpp \ include/bitcoin/node/protocols/protocol_observer.hpp \ + include/bitcoin/node/protocols/protocol_peer.hpp \ include/bitcoin/node/protocols/protocol_performer.hpp \ + include/bitcoin/node/protocols/protocol_tcp.hpp \ include/bitcoin/node/protocols/protocol_transaction_in_106.hpp \ include/bitcoin/node/protocols/protocol_transaction_out_106.hpp \ include/bitcoin/node/protocols/protocols.hpp diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 215ccec4d..766aa1613 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -249,12 +249,12 @@ add_definitions( add_library( ${CANONICAL_LIB_NAME} "../../src/block_arena.cpp" "../../src/block_memory.cpp" - "../../src/channel_peer.cpp" "../../src/configuration.cpp" "../../src/error.cpp" "../../src/full_node.cpp" "../../src/parser.cpp" "../../src/settings.cpp" + "../../src/channels/channel_peer.cpp" "../../src/chasers/chaser.cpp" "../../src/chasers/chaser_block.cpp" "../../src/chasers/chaser_check.cpp" @@ -277,6 +277,7 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/protocols/protocol_header_out_31800.cpp" "../../src/protocols/protocol_header_out_70012.cpp" "../../src/protocols/protocol_observer.cpp" + "../../src/protocols/protocol_peer.cpp" "../../src/protocols/protocol_performer.cpp" "../../src/protocols/protocol_transaction_in_106.cpp" "../../src/protocols/protocol_transaction_out_106.cpp" diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj index 34767481c..1f600456b 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj @@ -123,7 +123,7 @@ - + @@ -150,6 +150,7 @@ + @@ -164,7 +165,10 @@ - + + + + @@ -196,7 +200,9 @@ + + diff --git a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters index 50b94fc58..cc0278eea 100644 --- a/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters +++ b/builds/msvc/vs2022/libbitcoin-node/libbitcoin-node.vcxproj.filters @@ -8,44 +8,50 @@ - {5FFB5F52-0772-4404-0000-000000000004} + {5FFB5F52-0772-4404-0000-000000000005} - {5FFB5F52-0772-4404-0000-000000000005} + {5FFB5F52-0772-4404-0000-000000000006} - {5FFB5F52-0772-4404-0000-000000000006} + {5FFB5F52-0772-4404-0000-000000000007} + + + {5FFB5F52-0772-4404-0000-000000000008} - {5FFB5F52-0772-4404-0000-000000000007} + {5FFB5F52-0772-4404-0000-000000000009} - {5FFB5F52-0772-4404-0000-000000000008} + {5FFB5F52-0772-4404-0000-00000000000A} - {5FFB5F52-0772-4404-0000-00000000000B} + {5FFB5F52-0772-4404-0000-00000000000D} - {5FFB5F52-0772-4404-0000-000000000009} + {5FFB5F52-0772-4404-0000-00000000000B} - {5FFB5F52-0772-4404-0000-00000000000A} + {5FFB5F52-0772-4404-0000-00000000000C} - {5FFB5F52-0772-4404-0000-00000000000C} + {5FFB5F52-0772-4404-0000-00000000000E} {5FFB5F52-0772-4404-0000-000000000000} - + {5FFB5F52-0772-4404-0000-000000000001} - + {5FFB5F52-0772-4404-0000-000000000002} - + {5FFB5F52-0772-4404-0000-000000000003} + + {5FFB5F52-0772-4404-0000-000000000004} + @@ -54,8 +60,8 @@ src - - src + + src\channels src\chasers @@ -135,6 +141,9 @@ src\protocols + + src\protocols + src\protocols @@ -173,8 +182,17 @@ include\bitcoin\node - - include\bitcoin\node + + include\bitcoin\node\channels + + + include\bitcoin\node\channels + + + include\bitcoin\node\channels + + + include\bitcoin\node\channels include\bitcoin\node @@ -269,9 +287,15 @@ include\bitcoin\node\protocols + + include\bitcoin\node\protocols + include\bitcoin\node\protocols + + include\bitcoin\node\protocols + include\bitcoin\node\protocols diff --git a/include/bitcoin/node.hpp b/include/bitcoin/node.hpp index 848c44558..9bd6b508c 100644 --- a/include/bitcoin/node.hpp +++ b/include/bitcoin/node.hpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -28,6 +27,10 @@ #include #include #include +#include +#include +#include +#include #include #include #include @@ -52,7 +55,9 @@ #include #include #include +#include #include +#include #include #include #include diff --git a/include/bitcoin/node/channels/channel.hpp b/include/bitcoin/node/channels/channel.hpp new file mode 100644 index 000000000..24338e996 --- /dev/null +++ b/include/bitcoin/node/channels/channel.hpp @@ -0,0 +1,50 @@ +/** + * 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_CHANNELS_CHANNEL_HPP +#define LIBBITCOIN_NODE_CHANNELS_CHANNEL_HPP + +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace node { + +/// Abstract base channel state for the node. +class BCN_API channel +{ +public: + typedef std::shared_ptr ptr; + +protected: + channel(const network::logger&, const network::socket::ptr&, + const node::configuration&, uint64_t=zero) NOEXCEPT + { + } + + virtual ~channel() NOEXCEPT {} + +}; + +} // namespace node +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/node/channel_peer.hpp b/include/bitcoin/node/channels/channel_peer.hpp similarity index 89% rename from include/bitcoin/node/channel_peer.hpp rename to include/bitcoin/node/channels/channel_peer.hpp index 35d1eeaa6..220d72c6c 100644 --- a/include/bitcoin/node/channel_peer.hpp +++ b/include/bitcoin/node/channels/channel_peer.hpp @@ -16,11 +16,12 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_NODE_CHANNEL_PEER_HPP -#define LIBBITCOIN_NODE_CHANNEL_PEER_HPP +#ifndef LIBBITCOIN_NODE_CHANNELS_CHANNEL_PEER_HPP +#define LIBBITCOIN_NODE_CHANNELS_CHANNEL_PEER_HPP #include #include +#include #include #include @@ -29,7 +30,7 @@ namespace node { /// Peer channel state for the node. class BCN_API channel_peer - : public network::channel_peer + : public network::channel_peer, node::channel { public: typedef std::shared_ptr ptr; diff --git a/include/bitcoin/node/channels/channel_tcp.hpp b/include/bitcoin/node/channels/channel_tcp.hpp new file mode 100644 index 000000000..d284ce311 --- /dev/null +++ b/include/bitcoin/node/channels/channel_tcp.hpp @@ -0,0 +1,53 @@ +/** + * 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_CHANNELS_CHANNEL_TCP_HPP +#define LIBBITCOIN_NODE_CHANNELS_CHANNEL_TCP_HPP + +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace node { + +/// TCP channel state for the node. +class BCN_API channel_tcp + : public network::channel_tcp, node::channel +{ +public: + typedef std::shared_ptr ptr; + using options_t = network::settings::tcp_server; + + channel_tcp(const network::logger& log, const network::socket::ptr& socket, + const node::configuration& config, uint64_t identifier=zero, + const options_t& options={}) NOEXCEPT + : network::channel_tcp(log, socket, config.network, identifier, options), + node::channel(log, socket, config, identifier) + { + } + + virtual ~channel_tcp() NOEXCEPT {} +}; + +} // namespace node +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/node/channels/channels.hpp b/include/bitcoin/node/channels/channels.hpp new file mode 100644 index 000000000..201d2d062 --- /dev/null +++ b/include/bitcoin/node/channels/channels.hpp @@ -0,0 +1,27 @@ +/** + * 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_CHANNELS_CHANNELS_HPP +#define LIBBITCOIN_NODE_CHANNELS_CHANNELS_HPP + +#include +#include +#include + +#endif + diff --git a/include/bitcoin/node/define.hpp b/include/bitcoin/node/define.hpp index a9cdde479..d2e483806 100644 --- a/include/bitcoin/node/define.hpp +++ b/include/bitcoin/node/define.hpp @@ -121,8 +121,8 @@ using type_id = network::messages::peer::inventory_item::type_id; // configuration : define settings // parser : define configuration // /chasers : define configuration [forward: full_node] +// /channels : define configuration // full_node : define /chasers -// attach : define session [forward: full_node] // session : define [forward: full_node] -// /sessions : define attach /protocols [forward: full_node] -// /protocols : define session \ No newline at end of file +// /protocols : define /channels [session.hpp] +// /sessions : define /protocols [forward: full_node] \ No newline at end of file diff --git a/include/bitcoin/node/full_node.hpp b/include/bitcoin/node/full_node.hpp index 438326b0b..921f66988 100644 --- a/include/bitcoin/node/full_node.hpp +++ b/include/bitcoin/node/full_node.hpp @@ -157,10 +157,20 @@ class BCN_API full_node protected: /// Session attachments. /// ----------------------------------------------------------------------- + + /// Override base net to attach derived peer sessions. 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; + + /// Attach server sessions (base net doesn't specialize or start these). + virtual session_web::ptr attach_web_session() NOEXCEPT; virtual session_explore::ptr attach_explore_session() NOEXCEPT; + virtual session_websocket::ptr attach_websocket_session() NOEXCEPT; + virtual session_bitcoind::ptr attach_bitcoind_session() NOEXCEPT; + virtual session_electrum::ptr attach_electrum_session() NOEXCEPT; + virtual session_stratum_v1::ptr attach_stratum_v1_session() NOEXCEPT; + virtual session_stratum_v2::ptr attach_stratum_v2_session() NOEXCEPT; /// Virtual handlers. /// ----------------------------------------------------------------------- @@ -169,7 +179,13 @@ class BCN_API full_node void do_close() NOEXCEPT override; private: + void start_web(const code& ec, const result_handler& handler) NOEXCEPT; void start_explore(const code& ec, const result_handler& handler) NOEXCEPT; + void start_websocket(const code& ec, const result_handler& handler) NOEXCEPT; + void start_bitcoind(const code& ec, const result_handler& handler) NOEXCEPT; + void start_electrum(const code& ec, const result_handler& handler) NOEXCEPT; + void start_stratum_v1(const code& ec, const result_handler& handler) NOEXCEPT; + void start_stratum_v2(const code& ec, const result_handler& handler) NOEXCEPT; void do_subscribe_events(const event_notifier& handler, const event_completer& complete) NOEXCEPT; diff --git a/include/bitcoin/node/protocols/protocol.hpp b/include/bitcoin/node/protocols/protocol.hpp index 1110bfbda..88ebb819f 100644 --- a/include/bitcoin/node/protocols/protocol.hpp +++ b/include/bitcoin/node/protocols/protocol.hpp @@ -19,105 +19,46 @@ #ifndef LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_HPP #define LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_HPP - // Individual session.hpp inclusion to prevent cycle (can't forward declare). #include #include +#include +#include #include -#include #include namespace libbitcoin { namespace node { -/////////////////////////////////////////////////////////////////////////////// -// TODO: ... -> node::protocol_tcp -> node::protocol -> network::protocol. // -// TODO: ... -> node::protocol_peer -> node::protocol -> network::protocol. // -/////////////////////////////////////////////////////////////////////////////// +// TODO: first split node::protocol -> node::protocol and node::protocol_peer. +// TODO: then create node::protocol_peer -> node::protocol + network::protocol_peer. +// TODO: then create node::protocol_tcp -> node::protocol + network::protocol_tcp. +// TODO: this is the same pattern as joining node::session + network::session_xxxx. +// TODO: node::session_xxx => node::session_peer : node::session. +// TODO: node::protocol_xxx => node::protocol_peer : node::protocol. +// TODO: none of the node classes derive from shared_from_base and instead just +// TODO: rely on the network base class and shared_from_sibling<> to obtain +// TODO: node object methods within protocol_peer and derived, just as in +// TODO: session_peer and derived. This could be normalized using an override +// TODO: of shared_from_base<>() withing the two templates. /// Abstract base for node protocols, thread safe. class BCN_API protocol - : public network::protocol_peer { protected: + typedef std::shared_ptr ptr; + /// Constructors. /// ----------------------------------------------------------------------- - /// static_pointer_cast relies on create_channel(). - // Need template (see session member)? - template - protocol(const SessionPtr& session, + // reinterpret_pointer_cast because channel is abstract. + protocol(const node::session::ptr& session, const network::channel::ptr& channel) NOEXCEPT - : network::protocol_peer(session, channel), session_(session), - channel_(std::static_pointer_cast(channel)) + : channel_(std::reinterpret_pointer_cast(channel)), + session_(session) { } - virtual ~protocol() NOEXCEPT; - - /// Organizers. - /// ----------------------------------------------------------------------- - - /// Organize a validated header. - virtual void organize(const system::chain::header::cptr& header, - organize_handler&& handler) NOEXCEPT; - - /// Organize a checked block. - virtual void organize(const system::chain::block::cptr& block, - organize_handler&& handler) NOEXCEPT; - - /// Get block hashes for blocks to download. - virtual void get_hashes(map_handler&& handler) NOEXCEPT; - - /// Submit block hashes for blocks not downloaded. - virtual void put_hashes(const map_ptr& map, - network::result_handler&& handler) NOEXCEPT; - - /// Methods. - /// ----------------------------------------------------------------------- - - /// Report performance, handler may direct self-terminate. - virtual void performance(uint64_t speed, - network::result_handler&& handler) const NOEXCEPT; - - /// Suspend all existing and future network connections. - /// A race condition could result in an unsuspended connection. - virtual code fault(const code& ec) NOEXCEPT; - - /// Announcements. - /// ----------------------------------------------------------------------- - - /// Set an incoming block or tx hash that peer announced. - virtual void set_announced(const system::hash_digest&) NOEXCEPT; - - /// Determine if outgoing block or tx was previously announced by peer. - virtual bool was_announced(const system::hash_digest&) const NOEXCEPT; - - /// Events notification. - /// ----------------------------------------------------------------------- - - /// Set a chaser event. - virtual void notify(const code& ec, chase event_, - event_value value) const NOEXCEPT; - - /// Set a chaser event. - virtual void notify_one(object_key key, const code& ec, chase event_, - event_value value) const NOEXCEPT; - - /// Events subscription. - /// ----------------------------------------------------------------------- - - /// Subscribe to chaser events (max one active per protocol). - virtual void subscribe_events(event_notifier&& handler) NOEXCEPT; - - /// Override to handle subscription completion (stranded). - virtual void subscribed(const code& ec, object_key key) NOEXCEPT; - - /// Unsubscribe from chaser events. - /// Subscribing protocol must invoke from overridden stopping(). - virtual void unsubscribe_events() NOEXCEPT; - - /// Get the subscription key (for notify_one). - virtual object_key events_key() const NOEXCEPT; + virtual ~protocol() NOEXCEPT {} /// Properties. /// ----------------------------------------------------------------------- @@ -132,18 +73,11 @@ class BCN_API protocol virtual bool is_current(bool confirmed) const NOEXCEPT; private: - void handle_subscribed(const code& ec, object_key key) NOEXCEPT; - void handle_subscribe(const code& ec, object_key key, - const event_completer& complete) NOEXCEPT; + // This channel requires stranded calls, base is thread safe. + const node::channel::ptr channel_; // This is thread safe. - const session::ptr session_; - - // This derived channel requires stranded calls, base is thread safe. - node::channel_peer::ptr channel_; - - // This is protected by singular subscription. - object_key key_{}; + const node::session::ptr session_; }; } // namespace node diff --git a/include/bitcoin/node/protocols/protocol_block_in_106.hpp b/include/bitcoin/node/protocols/protocol_block_in_106.hpp index 10a4e0d6f..321ef9070 100644 --- a/include/bitcoin/node/protocols/protocol_block_in_106.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in_106.hpp @@ -23,12 +23,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_block_in_106 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -36,7 +37,7 @@ class BCN_API protocol_block_in_106 protocol_block_in_106(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), block_type_(session->config().network.witness_node() ? type_id::witness_block : type_id::block), network::tracker(session->log) diff --git a/include/bitcoin/node/protocols/protocol_block_out_106.hpp b/include/bitcoin/node/protocols/protocol_block_out_106.hpp index d3d5e78a5..5c2bf7371 100644 --- a/include/bitcoin/node/protocols/protocol_block_out_106.hpp +++ b/include/bitcoin/node/protocols/protocol_block_out_106.hpp @@ -22,12 +22,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_block_out_106 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -35,7 +36,7 @@ class BCN_API protocol_block_out_106 protocol_block_out_106(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), node_witness_(session->config().network.witness_node()), network::tracker(session->log) { diff --git a/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp b/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp index 18e02ff9f..72d8bb506 100644 --- a/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp +++ b/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp @@ -23,12 +23,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_filter_out_70015 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -36,7 +37,7 @@ class BCN_API protocol_filter_out_70015 protocol_filter_out_70015(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), network::tracker(session->log) { } diff --git a/include/bitcoin/node/protocols/protocol_header_in_31800.hpp b/include/bitcoin/node/protocols/protocol_header_in_31800.hpp index a53799c3f..21a64210e 100644 --- a/include/bitcoin/node/protocols/protocol_header_in_31800.hpp +++ b/include/bitcoin/node/protocols/protocol_header_in_31800.hpp @@ -22,12 +22,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_header_in_31800 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -35,7 +36,7 @@ class BCN_API protocol_header_in_31800 protocol_header_in_31800(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), network::tracker(session->log) { } diff --git a/include/bitcoin/node/protocols/protocol_header_out_31800.hpp b/include/bitcoin/node/protocols/protocol_header_out_31800.hpp index 68faa9a59..f985e2a9f 100644 --- a/include/bitcoin/node/protocols/protocol_header_out_31800.hpp +++ b/include/bitcoin/node/protocols/protocol_header_out_31800.hpp @@ -22,12 +22,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_header_out_31800 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -35,7 +36,7 @@ class BCN_API protocol_header_out_31800 protocol_header_out_31800(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), network::tracker(session->log) { } diff --git a/include/bitcoin/node/protocols/protocol_observer.hpp b/include/bitcoin/node/protocols/protocol_observer.hpp index 34cefdde5..77401b248 100644 --- a/include/bitcoin/node/protocols/protocol_observer.hpp +++ b/include/bitcoin/node/protocols/protocol_observer.hpp @@ -23,12 +23,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_observer - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -38,7 +39,7 @@ class BCN_API protocol_observer // TODO: current network handshake sets relay based on config only. protocol_observer(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), relay_disallowed_ ( std::dynamic_pointer_cast(channel)-> diff --git a/include/bitcoin/node/protocols/protocol_peer.hpp b/include/bitcoin/node/protocols/protocol_peer.hpp new file mode 100644 index 000000000..a7e2e526c --- /dev/null +++ b/include/bitcoin/node/protocols/protocol_peer.hpp @@ -0,0 +1,135 @@ +/** + * 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_PROTOCOLS_PROTOCOL_PEER_HPP +#define LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_PEER_HPP + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace node { + +/// Abstract base for node peer protocols, thread safe. +class BCN_API protocol_peer + : public network::protocol_peer, public node::protocol +{ +protected: + /// Constructors. + /// ----------------------------------------------------------------------- + /// static_pointer_cast relies on create_channel(). + + protocol_peer(const auto& session, + const network::channel::ptr& channel) NOEXCEPT + : network::protocol_peer(session, channel), + node::protocol(session, channel), + channel_(std::static_pointer_cast(channel)), + session_(session) + { + } + + virtual ~protocol_peer() NOEXCEPT {} + + /// Organizers. + /// ----------------------------------------------------------------------- + + /// Organize a validated header. + virtual void organize(const system::chain::header::cptr& header, + organize_handler&& handler) NOEXCEPT; + + /// Organize a checked block. + virtual void organize(const system::chain::block::cptr& block, + organize_handler&& handler) NOEXCEPT; + + /// Get block hashes for blocks to download. + virtual void get_hashes(map_handler&& handler) NOEXCEPT; + + /// Submit block hashes for blocks not downloaded. + virtual void put_hashes(const map_ptr& map, + network::result_handler&& handler) NOEXCEPT; + + /// Methods. + /// ----------------------------------------------------------------------- + + /// Report performance, handler may direct self-terminate. + virtual void performance(uint64_t speed, + network::result_handler&& handler) const NOEXCEPT; + + /// Suspend all existing and future network connections. + /// A race condition could result in an unsuspended connection. + virtual code fault(const code& ec) NOEXCEPT; + + /// Announcements. + /// ----------------------------------------------------------------------- + + /// Set an incoming block or tx hash that peer announced. + virtual void set_announced(const system::hash_digest&) NOEXCEPT; + + /// Determine if outgoing block or tx was previously announced by peer. + virtual bool was_announced(const system::hash_digest&) const NOEXCEPT; + + /// Events notification. + /// ----------------------------------------------------------------------- + + /// Set a chaser event. + virtual void notify(const code& ec, chase event_, + event_value value) const NOEXCEPT; + + /// Set a chaser event. + virtual void notify_one(object_key key, const code& ec, chase event_, + event_value value) const NOEXCEPT; + + /// Events subscription. + /// ----------------------------------------------------------------------- + + /// Subscribe to chaser events (max one active per protocol). + virtual void subscribe_events(event_notifier&& handler) NOEXCEPT; + + /// Override to handle subscription completion (stranded). + virtual void subscribed(const code& ec, object_key key) NOEXCEPT; + + /// Unsubscribe from chaser events. + /// Subscribing protocol must invoke from overridden stopping(). + virtual void unsubscribe_events() NOEXCEPT; + + /// Get the subscription key (for notify_one). + virtual object_key events_key() const NOEXCEPT; + +private: + void handle_subscribed(const code& ec, object_key key) NOEXCEPT; + void handle_subscribe(const code& ec, object_key key, + const event_completer& complete) NOEXCEPT; + + // This derived channel requires stranded calls, base is thread safe. + const node::channel_peer::ptr channel_; + + // This is thread safe. + const session::ptr session_; + + // This is protected by singular subscription. + object_key key_{}; +}; + +} // namespace node +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/node/protocols/protocol_performer.hpp b/include/bitcoin/node/protocols/protocol_performer.hpp index a50ee93ba..7d54c914f 100644 --- a/include/bitcoin/node/protocols/protocol_performer.hpp +++ b/include/bitcoin/node/protocols/protocol_performer.hpp @@ -22,13 +22,14 @@ #include #include #include +#include namespace libbitcoin { namespace node { /// Abstract base protocol for performance standard deviation measurement. class BCN_API protocol_performer - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -40,7 +41,7 @@ class BCN_API protocol_performer protected: protocol_performer(const auto& session, const network::channel::ptr& channel, bool enabled) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), deviation_(session->config().node.allowed_deviation > 0.0), enabled_(enabled && to_bool(session->config().node.sample_period_seconds)), performance_timer_(std::make_shared(session->log, diff --git a/include/bitcoin/node/protocols/protocol_tcp.hpp b/include/bitcoin/node/protocols/protocol_tcp.hpp new file mode 100644 index 000000000..46dc189d9 --- /dev/null +++ b/include/bitcoin/node/protocols/protocol_tcp.hpp @@ -0,0 +1,61 @@ +/** + * 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_PROTOCOLS_PROTOCOL_TCP_HPP +#define LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_TCP_HPP + +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace node { + +/// Abstract base for TCP protocols, thread safe. +class BCN_API protocol_tcp + : public network::protocol_tcp, public node::protocol +{ +protected: + typedef std::shared_ptr ptr; + + protocol_tcp(const auto& session, + const network::channel::ptr& channel) NOEXCEPT + : network::protocol_tcp(session, channel), + node::protocol(session, channel), + channel_(std::static_pointer_cast(channel)), + session_(session) + { + } + + virtual ~protocol_tcp() NOEXCEPT {} + +private: + // This derived channel requires stranded calls, base is thread safe. + const node::channel_tcp::ptr channel_; + + // This is thread safe. + const session::ptr session_; +}; + +} // namespace node +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp b/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp index 60277c98c..5cc9396bd 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp @@ -22,12 +22,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_transaction_in_106 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -35,7 +36,7 @@ class BCN_API protocol_transaction_in_106 protocol_transaction_in_106(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), ////tx_type_(session->config().network.witness_node() ? //// type_id::witness_tx : type_id::transaction), network::tracker(session->log) diff --git a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp index 0678725db..d3f32cf98 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp @@ -22,12 +22,13 @@ #include #include #include +#include namespace libbitcoin { namespace node { class BCN_API protocol_transaction_out_106 - : public node::protocol, + : public node::protocol_peer, protected network::tracker { public: @@ -35,7 +36,7 @@ class BCN_API protocol_transaction_out_106 protocol_transaction_out_106(const auto& session, const network::channel::ptr& channel) NOEXCEPT - : node::protocol(session, channel), + : node::protocol_peer(session, channel), node_witness_(session->config().network.witness_node()), network::tracker(session->log) { diff --git a/include/bitcoin/node/protocols/protocols.hpp b/include/bitcoin/node/protocols/protocols.hpp index 47bdebbd6..3cf6c2989 100644 --- a/include/bitcoin/node/protocols/protocols.hpp +++ b/include/bitcoin/node/protocols/protocols.hpp @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include #include #include diff --git a/include/bitcoin/node/sessions/session_peer.hpp b/include/bitcoin/node/sessions/session_peer.hpp index f74037729..61d0163be 100644 --- a/include/bitcoin/node/sessions/session_peer.hpp +++ b/include/bitcoin/node/sessions/session_peer.hpp @@ -29,9 +29,7 @@ namespace libbitcoin { namespace node { -class full_node; - -/// CRTP base class template for network session multiple derivation. +/// Template for network::session derivation with node::session. /// node::session does not derive from network::session (siblings). /// This avoids the diamond inheritance problem between network/node. template @@ -39,14 +37,25 @@ class session_peer : public Session, public node::session { public: - template - session_peer(full_node& node, uint64_t identifier, Args&&... args) NOEXCEPT - : Session(node, identifier, std::forward(args)...), + template + session_peer(Node& node, Args&&... args) NOEXCEPT + : Session(node, std::forward(args)...), node::session(node) { } protected: + network::channel::ptr create_channel( + const network::socket::ptr& socket) NOEXCEPT override + { + // this-> is required for dependent base access in CRTP. + const auto channel = std::make_shared( + this->get_memory(), this->log, socket, this->config(), + this->create_key()); + + return std::static_pointer_cast(channel); + } + void attach_handshake(const network::channel::ptr& channel, network::result_handler&& handler) NOEXCEPT override { @@ -162,17 +171,6 @@ class session_peer channel->attach(self)->start(); } } - - network::channel::ptr create_channel( - const network::socket::ptr& socket) NOEXCEPT override - { - // this-> is required for dependent base access in CRTP. - const auto channel = std::make_shared( - this->get_memory(), this->log, socket, this->config(), - this->create_key()); - - return std::static_pointer_cast(channel); - } }; } // namespace node diff --git a/include/bitcoin/node/sessions/session_tcp.hpp b/include/bitcoin/node/sessions/session_tcp.hpp index 4e0dcc58e..18aa7fb92 100644 --- a/include/bitcoin/node/sessions/session_tcp.hpp +++ b/include/bitcoin/node/sessions/session_tcp.hpp @@ -39,17 +39,17 @@ class session_tcp const options_t& options) NOEXCEPT; protected: - inline bool enabled() const NOEXCEPT override; + 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; +// TODO: implement specialized protocol instances, like node::protocol_explore. +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 diff --git a/src/channel_peer.cpp b/src/channels/channel_peer.cpp similarity index 94% rename from src/channel_peer.cpp rename to src/channels/channel_peer.cpp index a96fa5d54..f0832a280 100644 --- a/src/channel_peer.cpp +++ b/src/channels/channel_peer.cpp @@ -16,7 +16,7 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include #include @@ -35,6 +35,7 @@ channel_peer::channel_peer(memory& memory, const logger& log, const socket::ptr& socket, const node::configuration& config, uint64_t identifier) NOEXCEPT : network::channel_peer(memory, log, socket, config.network, identifier), + node::channel(log, socket, config, identifier), announced_(config.node.announcement_cache) { } diff --git a/src/full_node.cpp b/src/full_node.cpp index 12515520a..e47f9e69e 100644 --- a/src/full_node.cpp +++ b/src/full_node.cpp @@ -118,7 +118,22 @@ void full_node::do_run(const result_handler& handler) NOEXCEPT do_notify(error::success, chase::start, height_t{}); // Start services after network is running. - net::do_run(std::bind(&full_node::start_explore, this, _1, handler)); + net::do_run(std::bind(&full_node::start_web, this, _1, handler)); +} + +void full_node::start_web(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + attach_web_session()->start( + std::bind(&full_node::start_explore, this, _1, handler)); } void full_node::start_explore(const code& ec, @@ -132,13 +147,82 @@ void full_node::start_explore(const code& ec, return; } - if (!config().network.explore.enabled()) + attach_explore_session()->start( + std::bind(&full_node::start_websocket, this, _1, handler)); +} + +void full_node::start_websocket(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + attach_websocket_session()->start( + std::bind(&full_node::start_bitcoind, this, _1, handler)); +} + +void full_node::start_bitcoind(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + attach_bitcoind_session()->start( + std::bind(&full_node::start_electrum, this, _1, handler)); +} + +void full_node::start_electrum(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) { handler(ec); return; } - attach_explore_session()->start(move_copy(handler)); + attach_electrum_session()->start( + std::bind(&full_node::start_stratum_v1, this, _1, handler)); +} + +void full_node::start_stratum_v1(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + attach_stratum_v1_session()->start( + std::bind(&full_node::start_stratum_v2, this, _1, handler)); +} + +void full_node::start_stratum_v2(const code& ec, + const result_handler& handler) NOEXCEPT +{ + BC_ASSERT_MSG(stranded(), "strand"); + + if (ec) + { + handler(ec); + return; + } + + attach_stratum_v2_session()->start(move_copy(handler)); } void full_node::close() NOEXCEPT @@ -441,17 +525,22 @@ network::memory& full_node::get_memory() NOEXCEPT network::session_manual::ptr full_node::attach_manual_session() NOEXCEPT { - return attach(*this); + return net::attach(*this); } network::session_inbound::ptr full_node::attach_inbound_session() NOEXCEPT { - return attach(*this); + return net::attach(*this); } network::session_outbound::ptr full_node::attach_outbound_session() NOEXCEPT { - return attach(*this); + return net::attach(*this); +} + +session_web::ptr full_node::attach_web_session() NOEXCEPT +{ + return net::attach(*this, config_.network.web); } session_explore::ptr full_node::attach_explore_session() NOEXCEPT @@ -459,6 +548,31 @@ session_explore::ptr full_node::attach_explore_session() NOEXCEPT return net::attach(*this, config_.network.explore); } +session_websocket::ptr full_node::attach_websocket_session() NOEXCEPT +{ + return net::attach(*this, config_.network.websocket); +} + +session_bitcoind::ptr full_node::attach_bitcoind_session() NOEXCEPT +{ + return net::attach(*this, config_.network.bitcoind); +} + +session_electrum::ptr full_node::attach_electrum_session() NOEXCEPT +{ + return net::attach(*this, config_.network.electrum); +} + +session_stratum_v1::ptr full_node::attach_stratum_v1_session() NOEXCEPT +{ + return net::attach(*this, config_.network.stratum_v1); +} + +session_stratum_v2::ptr full_node::attach_stratum_v2_session() NOEXCEPT +{ + return net::attach(*this, config_.network.stratum_v2); +} + BC_POP_WARNING() } // namespace node diff --git a/src/protocols/protocol.cpp b/src/protocols/protocol.cpp index 0115c13b0..4aec0c11c 100644 --- a/src/protocols/protocol.cpp +++ b/src/protocols/protocol.cpp @@ -18,7 +18,6 @@ */ #include -#include #include #include #include @@ -26,146 +25,6 @@ namespace libbitcoin { namespace node { -#define CLASS protocol - -using namespace system; -using namespace system::chain; -using namespace database; -using namespace network; -using namespace std::placeholders; - -protocol::~protocol() NOEXCEPT -{ -} - -// Organizers. -// ---------------------------------------------------------------------------- - -void protocol::organize(const system::chain::header::cptr& header, - organize_handler&& handler) NOEXCEPT -{ - session_->organize(header, std::move(handler)); -} - -void protocol::organize(const system::chain::block::cptr& block, - organize_handler&& handler) NOEXCEPT -{ - session_->organize(block, std::move(handler)); -} - -void protocol::get_hashes(map_handler&& handler) NOEXCEPT -{ - session_->get_hashes(std::move(handler)); -} - -void protocol::put_hashes(const map_ptr& map, - network::result_handler&& handler) NOEXCEPT -{ - session_->put_hashes(map, std::move(handler)); -} - -// Events notification. -// ---------------------------------------------------------------------------- - -void protocol::notify(const code& ec, chase event_, - event_value value) const NOEXCEPT -{ - session_->notify(ec, event_, value); -} - -void protocol::notify_one(object_key key, const code& ec, chase event_, - event_value value) const NOEXCEPT -{ - session_->notify_one(key, ec, event_, value); -} - -// Events subscription. -// ---------------------------------------------------------------------------- - -void protocol::subscribe_events(event_notifier&& handler) NOEXCEPT -{ - event_completer completer = BIND(handle_subscribed, _1, _2); - session_->subscribe_events(std::move(handler), - BIND(handle_subscribe, _1, _2, std::move(completer))); -} - -// private -void protocol::handle_subscribe(const code& ec, object_key key, - const event_completer& complete) NOEXCEPT -{ - // The key member is protected by one event subscription per protocol. - BC_ASSERT_MSG(is_zero(key_), "unsafe access"); - - // Protocol stop is thread safe. - if (ec) - { - stop(ec); - return; - } - - key_ = key; - complete(ec, key_); -} - -void protocol::handle_subscribed(const code& ec, object_key key) NOEXCEPT -{ - POST(subscribed, ec, key); -} - -void protocol::subscribed(const code& ec, object_key) NOEXCEPT -{ - BC_ASSERT(stranded()); - - // Unsubscriber race is ok. - if (stopped(ec)) - unsubscribe_events(); -} - -// As this has no completion handler resubscription is not allowed. -void protocol::unsubscribe_events() NOEXCEPT -{ - session_->unsubscribe_events(key_); - key_ = {}; -} - -object_key protocol::events_key() const NOEXCEPT -{ - return key_; -} - -// Methods. -// ---------------------------------------------------------------------------- - -void protocol::performance(uint64_t speed, - network::result_handler&& handler) const NOEXCEPT -{ - // Passed protocol->session->full_node->check_chaser.post->do_update. - session_->performance(key_, speed, std::move(handler)); -} - -code protocol::fault(const code& ec) NOEXCEPT -{ - // Short-circuit self stop. - stop(ec); - - // Stop all other channels and suspend all connectors/acceptors. - session_->fault(ec); - return ec; -} - -// Announcements. -// ---------------------------------------------------------------------------- - -void protocol::set_announced(const system::hash_digest& hash) NOEXCEPT -{ - channel_->set_announced(hash); -} - -bool protocol::was_announced(const system::hash_digest& hash) const NOEXCEPT -{ - return channel_->was_announced(hash); -} - // Properties. // ---------------------------------------------------------------------------- diff --git a/src/protocols/protocol_block_in_106.cpp b/src/protocols/protocol_block_in_106.cpp index 52f2a7b5e..6d4481e01 100644 --- a/src/protocols/protocol_block_in_106.cpp +++ b/src/protocols/protocol_block_in_106.cpp @@ -58,7 +58,7 @@ void protocol_block_in_106::start() NOEXCEPT SUBSCRIBE_CHANNEL(block, handle_receive_block, _1, _2); SUBSCRIBE_CHANNEL(inventory, handle_receive_inventory, _1, _2); SEND(create_get_inventory(), handle_send, _1); - protocol::start(); + protocol_peer::start(); } // accept inventory diff --git a/src/protocols/protocol_block_in_31800.cpp b/src/protocols/protocol_block_in_31800.cpp index 4a2e11932..1f8ca8750 100644 --- a/src/protocols/protocol_block_in_31800.cpp +++ b/src/protocols/protocol_block_in_31800.cpp @@ -54,7 +54,7 @@ void protocol_block_in_31800::start() NOEXCEPT // Events subscription is asynchronous, events may be missed. subscribe_events(BIND(handle_event, _1, _2, _3)); SUBSCRIBE_CHANNEL(block, handle_receive_block, _1, _2); - protocol::start(); + protocol_performer::start(); } // overridden to add non-current node start. @@ -86,7 +86,7 @@ void protocol_block_in_31800::stopping(const code& ec) NOEXCEPT map_ = chaser_check::empty_map(); stop_performance(); unsubscribe_events(); - protocol::stopping(ec); + protocol_performer::stopping(ec); } // handle events (download, split) diff --git a/src/protocols/protocol_block_out_106.cpp b/src/protocols/protocol_block_out_106.cpp index 16cd11884..d49aee8fe 100644 --- a/src/protocols/protocol_block_out_106.cpp +++ b/src/protocols/protocol_block_out_106.cpp @@ -51,7 +51,7 @@ void protocol_block_out_106::start() NOEXCEPT subscribe_events(BIND(handle_event, _1, _2, _3)); SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); SUBSCRIBE_CHANNEL(get_blocks, handle_receive_get_blocks, _1, _2); - protocol::start(); + protocol_peer::start(); } void protocol_block_out_106::stopping(const code& ec) NOEXCEPT @@ -59,7 +59,7 @@ void protocol_block_out_106::stopping(const code& ec) NOEXCEPT // Unsubscriber race is ok. BC_ASSERT(stranded()); unsubscribe_events(); - protocol::stopping(ec); + protocol_peer::stopping(ec); } // handle events (block) diff --git a/src/protocols/protocol_block_out_70012.cpp b/src/protocols/protocol_block_out_70012.cpp index 6c9f1e371..2d7beb59b 100644 --- a/src/protocols/protocol_block_out_70012.cpp +++ b/src/protocols/protocol_block_out_70012.cpp @@ -46,7 +46,7 @@ void protocol_block_out_70012::start() NOEXCEPT return; SUBSCRIBE_CHANNEL(send_headers, handle_receive_send_headers, _1, _2); - protocol::start(); + protocol_block_out_106::start(); } // Inbound (send_headers). diff --git a/src/protocols/protocol_filter_out_70015.cpp b/src/protocols/protocol_filter_out_70015.cpp index 41830bc01..1a6f4b826 100644 --- a/src/protocols/protocol_filter_out_70015.cpp +++ b/src/protocols/protocol_filter_out_70015.cpp @@ -50,7 +50,7 @@ void protocol_filter_out_70015::start() NOEXCEPT SUBSCRIBE_CHANNEL(get_client_filter_checkpoint, handle_receive_get_filter_checkpoint, _1, _2); SUBSCRIBE_CHANNEL(get_client_filter_headers, handle_receive_get_filter_headers, _1, _2); SUBSCRIBE_CHANNEL(get_client_filters, handle_receive_get_filters, _1, _2); - protocol::start(); + protocol_peer::start(); } // Inbound (get_client_filter_checkpoint). diff --git a/src/protocols/protocol_header_in_31800.cpp b/src/protocols/protocol_header_in_31800.cpp index 9a7d28a28..fbee52738 100644 --- a/src/protocols/protocol_header_in_31800.cpp +++ b/src/protocols/protocol_header_in_31800.cpp @@ -48,7 +48,7 @@ void protocol_header_in_31800::start() NOEXCEPT SUBSCRIBE_CHANNEL(headers, handle_receive_headers, _1, _2); SEND(create_get_headers(), handle_send, _1); - protocol::start(); + protocol_peer::start(); } // Inbound (headers). diff --git a/src/protocols/protocol_header_out_31800.cpp b/src/protocols/protocol_header_out_31800.cpp index 2e80c5ac6..469ca894f 100644 --- a/src/protocols/protocol_header_out_31800.cpp +++ b/src/protocols/protocol_header_out_31800.cpp @@ -47,7 +47,7 @@ void protocol_header_out_31800::start() NOEXCEPT return; SUBSCRIBE_CHANNEL(get_headers, handle_receive_get_headers, _1, _2); - protocol::start(); + protocol_peer::start(); } // Outbound (get_headers). diff --git a/src/protocols/protocol_header_out_70012.cpp b/src/protocols/protocol_header_out_70012.cpp index 97fc2b5fb..4d4710640 100644 --- a/src/protocols/protocol_header_out_70012.cpp +++ b/src/protocols/protocol_header_out_70012.cpp @@ -55,7 +55,7 @@ void protocol_header_out_70012::stopping(const code& ec) NOEXCEPT // Unsubscriber race is ok. BC_ASSERT(stranded()); unsubscribe_events(); - protocol::stopping(ec); + protocol_header_out_31800::stopping(ec); } // handle events (block) diff --git a/src/protocols/protocol_observer.cpp b/src/protocols/protocol_observer.cpp index 564263006..d7b3a509c 100644 --- a/src/protocols/protocol_observer.cpp +++ b/src/protocols/protocol_observer.cpp @@ -52,7 +52,7 @@ void protocol_observer::start() NOEXCEPT } ////SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); - protocol::start(); + protocol_peer::start(); } void protocol_observer::stopping(const code& ec) NOEXCEPT @@ -60,7 +60,7 @@ void protocol_observer::stopping(const code& ec) NOEXCEPT // Unsubscriber race is ok. BC_ASSERT(stranded()); unsubscribe_events(); - protocol::stopping(ec); + protocol_peer::stopping(ec); } // handle events (suspend) diff --git a/src/protocols/protocol_peer.cpp b/src/protocols/protocol_peer.cpp new file mode 100644 index 000000000..023c34989 --- /dev/null +++ b/src/protocols/protocol_peer.cpp @@ -0,0 +1,162 @@ +/** + * 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 +#include + +namespace libbitcoin { +namespace node { + +#define CLASS protocol_peer + +using namespace system; +using namespace network; +using namespace std::placeholders; + +// Organizers. +// ---------------------------------------------------------------------------- + +void protocol_peer::organize(const system::chain::header::cptr& header, + organize_handler&& handler) NOEXCEPT +{ + session_->organize(header, std::move(handler)); +} + +void protocol_peer::organize(const system::chain::block::cptr& block, + organize_handler&& handler) NOEXCEPT +{ + session_->organize(block, std::move(handler)); +} + +void protocol_peer::get_hashes(map_handler&& handler) NOEXCEPT +{ + session_->get_hashes(std::move(handler)); +} + +void protocol_peer::put_hashes(const map_ptr& map, + network::result_handler&& handler) NOEXCEPT +{ + session_->put_hashes(map, std::move(handler)); +} + +// Methods. +// ---------------------------------------------------------------------------- + +void protocol_peer::performance(uint64_t speed, + network::result_handler&& handler) const NOEXCEPT +{ + // Passed protocol->session->full_node->check_chaser.post->do_update. + session_->performance(key_, speed, std::move(handler)); +} + +code protocol_peer::fault(const code& ec) NOEXCEPT +{ + // Short-circuit self stop. + stop(ec); + + // Stop all other channels and suspend all connectors/acceptors. + session_->fault(ec); + return ec; +} + +// Announcements. +// ---------------------------------------------------------------------------- + +void protocol_peer::set_announced(const system::hash_digest& hash) NOEXCEPT +{ + channel_->set_announced(hash); +} + +bool protocol_peer::was_announced(const system::hash_digest& hash) const NOEXCEPT +{ + return channel_->was_announced(hash); +} + +// Events notification. +// ---------------------------------------------------------------------------- + +void protocol_peer::notify(const code& ec, chase event_, + event_value value) const NOEXCEPT +{ + session_->notify(ec, event_, value); +} + +void protocol_peer::notify_one(object_key key, const code& ec, chase event_, + event_value value) const NOEXCEPT +{ + session_->notify_one(key, ec, event_, value); +} + +// Events subscription. +// ---------------------------------------------------------------------------- + +void protocol_peer::subscribe_events(event_notifier&& handler) NOEXCEPT +{ + event_completer completer = BIND(handle_subscribed, _1, _2); + session_->subscribe_events(std::move(handler), + BIND(handle_subscribe, _1, _2, std::move(completer))); +} + +// private +void protocol_peer::handle_subscribe(const code& ec, object_key key, + const event_completer& complete) NOEXCEPT +{ + // The key member is protected by one event subscription per protocol. + BC_ASSERT_MSG(is_zero(key_), "unsafe access"); + + // Protocol stop is thread safe. + if (ec) + { + stop(ec); + return; + } + + key_ = key; + complete(ec, key_); +} + +void protocol_peer::handle_subscribed(const code& ec, object_key key) NOEXCEPT +{ + POST(subscribed, ec, key); +} + +void protocol_peer::subscribed(const code& ec, object_key) NOEXCEPT +{ + BC_ASSERT(stranded()); + + // Unsubscriber race is ok. + if (stopped(ec)) + unsubscribe_events(); +} + +// As this has no completion handler resubscription is not allowed. +void protocol_peer::unsubscribe_events() NOEXCEPT +{ + session_->unsubscribe_events(key_); + key_ = {}; +} + +object_key protocol_peer::events_key() const NOEXCEPT +{ + return key_; +} + +} // namespace node +} // namespace libbitcoin diff --git a/src/protocols/protocol_transaction_in_106.cpp b/src/protocols/protocol_transaction_in_106.cpp index a8fc729b6..b9e0f3f95 100644 --- a/src/protocols/protocol_transaction_in_106.cpp +++ b/src/protocols/protocol_transaction_in_106.cpp @@ -45,7 +45,7 @@ void protocol_transaction_in_106::start() NOEXCEPT return; SUBSCRIBE_CHANNEL(inventory, handle_receive_inventory, _1, _2); - protocol::start(); + protocol_peer::start(); } // Inbound (inv). diff --git a/src/protocols/protocol_transaction_out_106.cpp b/src/protocols/protocol_transaction_out_106.cpp index 5200f1525..4c1777b88 100644 --- a/src/protocols/protocol_transaction_out_106.cpp +++ b/src/protocols/protocol_transaction_out_106.cpp @@ -48,7 +48,7 @@ void protocol_transaction_out_106::start() NOEXCEPT // Events subscription is asynchronous, events may be missed. subscribe_events(BIND(handle_event, _1, _2, _3)); SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); - protocol::start(); + protocol_peer::start(); } void protocol_transaction_out_106::stopping(const code& ec) NOEXCEPT @@ -56,7 +56,7 @@ void protocol_transaction_out_106::stopping(const code& ec) NOEXCEPT // Unsubscriber race is ok. BC_ASSERT(stranded()); unsubscribe_events(); - protocol::stopping(ec); + protocol_peer::stopping(ec); } // handle events (transaction)