diff --git a/include/bitcoin/network/channels/channel_rpc.hpp b/include/bitcoin/network/channels/channel_rpc.hpp index 1733d174b..93509b9a2 100644 --- a/include/bitcoin/network/channels/channel_rpc.hpp +++ b/include/bitcoin/network/channels/channel_rpc.hpp @@ -40,7 +40,7 @@ class channel_rpc /// Subscribe to request from client (requires strand). /// Event handler is always invoked on the channel strand. - template + template inline void subscribe(Handler&& handler) NOEXCEPT { BC_ASSERT(stranded()); diff --git a/include/bitcoin/network/messages/http_body.hpp b/include/bitcoin/network/messages/http_body.hpp index a66387cc8..2dc5c0a82 100644 --- a/include/bitcoin/network/messages/http_body.hpp +++ b/include/bitcoin/network/messages/http_body.hpp @@ -81,15 +81,15 @@ using string_value = http::string_body::value_type; using json_value = http::json_body::value_type; using body_value = std::variant < - empty_value, - data_value, - file_value, - span_value, - buffer_value, - string_value, - json_value, - rpc::request, - rpc::response + empty_value, // 1 byte + data_value, // 40 bytes + file_value, // 32 bytes + span_value, // 16 bytes + buffer_value, // 24 bytes + string_value, // 40 bytes + json_value, // 48 bytes + rpc::request, // 248 bytes! + rpc::response // 360 bytes! >; /// body template for all known message types. diff --git a/include/bitcoin/network/protocols/protocol.hpp b/include/bitcoin/network/protocols/protocol.hpp index 8f822c9fe..20f0ca396 100644 --- a/include/bitcoin/network/protocols/protocol.hpp +++ b/include/bitcoin/network/protocols/protocol.hpp @@ -211,12 +211,12 @@ class BCT_API protocol #define DECLARE_SEND() \ template \ - void send(Message&& message, Method&& method, Args&&... args) NOEXCEPT \ + inline void send(Message&& message, Method&& method, Args&&... args) NOEXCEPT \ { channel_->send(std::forward(message), BIND_SHARED(method, args)); } #define DECLARE_SUBSCRIBE_CHANNEL() \ template \ - void subscribe_channel(Method&& method, Args&&... args) NOEXCEPT \ + inline void subscribe_channel(Method&& method, Args&&... args) NOEXCEPT \ { channel_->template subscribe(BIND_SHARED(method, args)); } #define SEND(message, method, ...) \ diff --git a/include/bitcoin/network/protocols/protocol_rpc.hpp b/include/bitcoin/network/protocols/protocol_rpc.hpp index f90aea4a1..8d0ee94d3 100644 --- a/include/bitcoin/network/protocols/protocol_rpc.hpp +++ b/include/bitcoin/network/protocols/protocol_rpc.hpp @@ -20,6 +20,7 @@ #define LIBBITCOIN_NETWORK_PROTOCOL_RPC_HPP #include +#include #include #include #include @@ -33,6 +34,7 @@ class protocol_rpc { public: typedef std::shared_ptr ptr; + using protocol_t = protocol_rpc; using channel_t = channel_rpc; using options_t = channel_t::options_t; @@ -44,9 +46,70 @@ class protocol_rpc { } - DECLARE_SEND() DECLARE_SUBSCRIBE_CHANNEL() + template + inline void send(network::rpc::response_t&& message, size_t size_hint, + Method&& method, Args&&... args) NOEXCEPT + { + channel_->send(std::move(message), size_hint, + std::bind(std::forward(method), + shared_from_base(), std::forward(args)...)); + } + + // TODO: capture and correlate version/id. + inline void send_result(network::rpc::value_t&& value, + size_t size_hint) NOEXCEPT + { + using namespace network::rpc; + using namespace std::placeholders; + send( + { + .jsonrpc = version::v2, + .id = 42, + ////.error = {}, + .result = std::move(value) + }, + size_hint, &protocol_t::handle_complete, _1, error::success); + } + + // TODO: capture and correlate version/id. + inline void send_error(const code& reason) NOEXCEPT + { + using namespace network::rpc; + using namespace std::placeholders; + const auto size_hint = two * reason.message().size(); + send( + { + .jsonrpc = version::v2, + .id = 42, + .error = result_t + { + .code = reason.value(), + .message = reason.message() + } + ////.result = {} + }, + size_hint, &protocol_t::handle_complete, _1, reason); + } + + inline void handle_complete(const code& ec, const code& reason) NOEXCEPT + { + BC_ASSERT(stranded()); + + if (stopped(ec)) + return; + + if (reason) + { + stop(reason); + return; + } + + // Continue read loop. + channel_->receive(); + } + private: // This is mostly thread safe, and used in a thread safe manner. // pause/resume/paused/attach not invoked, setters limited to handshake.