From 302d1724596f250ff0d619e8a688756ddf2fb681 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 31 Dec 2025 18:00:29 -0500 Subject: [PATCH] Update rpc senders to accept optional completion handler. --- .../bitcoin/network/channels/channel_rpc.hpp | 16 +++++----- .../network/impl/channels/channel_rpc.ipp | 30 ++++++++----------- .../network/impl/protocols/protocol_rpc.ipp | 15 +++++----- .../network/protocols/protocol_rpc.hpp | 10 ++++--- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/include/bitcoin/network/channels/channel_rpc.hpp b/include/bitcoin/network/channels/channel_rpc.hpp index 921c8a17e..024d9bca9 100644 --- a/include/bitcoin/network/channels/channel_rpc.hpp +++ b/include/bitcoin/network/channels/channel_rpc.hpp @@ -57,10 +57,13 @@ class channel_rpc { } - /// Public senders, rpc version and identity added to responses. - inline void send_code(const code& ec) NOEXCEPT; - inline void send_error(rpc::result_t&& error) NOEXCEPT; - inline void send_result(rpc::value_t&& result, size_t size_hint) NOEXCEPT; + /// Senders, rpc version and identity added to responses (requires strand). + inline void send_code(const code& ec, + result_handler&& handler={}) NOEXCEPT; + inline void send_error(rpc::result_t&& error, + result_handler&& handler={}) NOEXCEPT; + inline void send_result(rpc::value_t&& result, size_t size_hint, + result_handler&& handler={}) NOEXCEPT; /// Resume reading from the socket (requires strand). inline void resume() NOEXCEPT override; @@ -91,14 +94,11 @@ class channel_rpc virtual inline void handle_receive(const code& ec, size_t bytes, const rpc::request_cptr& request) NOEXCEPT; - /// Handle send complation, handler must invoke receive() unless stopping. + /// Handle send completion, invokes receive(). virtual inline void handle_send(const code& ec, size_t bytes, const rpc::response_cptr& response, const result_handler& handler) NOEXCEPT; - /// Invoked upon handle_send completion to restart receive(). - virtual void handle_complete(const code& ec) NOEXCEPT; - private: void log_message(const rpc::request& request, size_t bytes) const NOEXCEPT; diff --git a/include/bitcoin/network/impl/channels/channel_rpc.ipp b/include/bitcoin/network/impl/channels/channel_rpc.ipp index d0d807f0f..5382326bb 100644 --- a/include/bitcoin/network/impl/channels/channel_rpc.ipp +++ b/include/bitcoin/network/impl/channels/channel_rpc.ipp @@ -129,30 +129,31 @@ inline http::flat_buffer& CLASS::request_buffer() NOEXCEPT // ---------------------------------------------------------------------------- TEMPLATE -void CLASS::send_code(const code& ec) NOEXCEPT +void CLASS::send_code(const code& ec, result_handler&& handler) NOEXCEPT { BC_ASSERT(stranded()); - send_error({ .code = ec.value(), .message = ec.message() }); + send_error({ .code = ec.value(), .message = ec.message() }, + std::move(handler)); } TEMPLATE -void CLASS::send_error(rpc::result_t&& error) NOEXCEPT +void CLASS::send_error(rpc::result_t&& error, + result_handler&& handler) NOEXCEPT { BC_ASSERT(stranded()); using namespace std::placeholders; send({ .jsonrpc = version_, .id = identity_, .error = std::move(error) }, - two * error.message.size(), std::bind(&CLASS::handle_complete, - shared_from_base(), _1)); + two * error.message.size(), std::move(handler)); } TEMPLATE -void CLASS::send_result(rpc::value_t&& result, size_t size_hint) NOEXCEPT +void CLASS::send_result(rpc::value_t&& result, size_t size_hint, + result_handler&& handler) NOEXCEPT { BC_ASSERT(stranded()); using namespace std::placeholders; send({ .jsonrpc = version_, .id = identity_, .result = std::move(result) }, - size_hint, std::bind(&CLASS::handle_complete, - shared_from_base(), _1)); + size_hint, std::move(handler)); } // protected @@ -183,18 +184,11 @@ inline void CLASS::handle_send(const code& ec, size_t bytes, BC_ASSERT(stranded()); if (ec) stop(ec); log_message(*response, bytes); - handler(ec); -} -// protected -TEMPLATE -void CLASS::handle_complete(const code&) NOEXCEPT -{ - BC_ASSERT(stranded()); - if (stopped()) - return; + // Typically a noop, but handshake may pause channel here. + handler(ec); - // Continue read loop. + // Continue read loop (does not unpause or restart channel). receive(); } diff --git a/include/bitcoin/network/impl/protocols/protocol_rpc.ipp b/include/bitcoin/network/impl/protocols/protocol_rpc.ipp index 7d92f2b21..e01750f33 100644 --- a/include/bitcoin/network/impl/protocols/protocol_rpc.ipp +++ b/include/bitcoin/network/impl/protocols/protocol_rpc.ipp @@ -26,22 +26,23 @@ namespace libbitcoin { namespace network { TEMPLATE -inline void CLASS::send_code(const code& ec) NOEXCEPT +inline void CLASS::send_code(const code& ec, result_handler&& handler) NOEXCEPT { - channel_->send_code(ec); + channel_->send_code(ec, std::move(handler)); } TEMPLATE -inline void CLASS::send_error(rpc::result_t&& error) NOEXCEPT +inline void CLASS::send_error(rpc::result_t&& error, + result_handler&& handler) NOEXCEPT { - channel_->send_error(std::move(error)); + channel_->send_error(std::move(error), std::move(handler)); } TEMPLATE -inline void CLASS::send_result(rpc::value_t&& result, - size_t size_hint) NOEXCEPT +inline void CLASS::send_result(rpc::value_t&& result, size_t size_hint, + result_handler&& handler) NOEXCEPT { - channel_->send_result(std::move(result), size_hint); + channel_->send_result(std::move(result), size_hint, std::move(handler)); } } // namespace network diff --git a/include/bitcoin/network/protocols/protocol_rpc.hpp b/include/bitcoin/network/protocols/protocol_rpc.hpp index b9e9a7778..dfbaefc87 100644 --- a/include/bitcoin/network/protocols/protocol_rpc.hpp +++ b/include/bitcoin/network/protocols/protocol_rpc.hpp @@ -49,10 +49,12 @@ class protocol_rpc DECLARE_SUBSCRIBE_CHANNEL() /// Senders (requires strand). - virtual inline void send_code(const code& ec) NOEXCEPT; - virtual inline void send_error(rpc::result_t&& error) NOEXCEPT; - virtual inline void send_result(rpc::value_t&& result, - size_t size_hint) NOEXCEPT; + virtual inline void send_code(const code& ec, + result_handler&& handler={}) NOEXCEPT; + virtual inline void send_error(rpc::result_t&& error, + result_handler&& handler={}) NOEXCEPT; + virtual inline void send_result(rpc::value_t&& result, size_t size_hint, + result_handler&& handler={}) NOEXCEPT; private: // This is mostly thread safe, and used in a thread safe manner.