Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ include_bitcoin_network_impl_messages_rpc_HEADERS = \
include/bitcoin/network/impl/messages/rpc/broadcaster.ipp \
include/bitcoin/network/impl/messages/rpc/dispatcher.ipp

include_bitcoin_network_impl_protocolsdir = ${includedir}/bitcoin/network/impl/protocols
include_bitcoin_network_impl_protocols_HEADERS = \
include/bitcoin/network/impl/protocols/protocol_rpc.ipp

include_bitcoin_network_interfacesdir = ${includedir}/bitcoin/network/interfaces
include_bitcoin_network_interfaces_HEADERS = \
include/bitcoin/network/interfaces/http.hpp \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\json_body.ipp" />
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\broadcaster.ipp" />
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\dispatcher.ipp" />
<None Include="..\..\..\..\include\bitcoin\network\impl\protocols\protocol_rpc.ipp" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000C1}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\impl\async\races">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000F1}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000002}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\impl\channels">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000D1}</UniqueIdentifier>
Expand All @@ -44,7 +44,10 @@
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000E1}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\impl\messages\rpc">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000002}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000003}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\impl\protocols">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000F1}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\interfaces">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
Expand All @@ -56,25 +59,25 @@
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\http">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000003}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000004}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\http\enums">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000007}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\peer">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000004}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000005}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\peer\detail">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000007}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\peer\enums">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\rpc">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000005}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\messages\rpc\enums">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000010}</UniqueIdentifier>
</Filter>
<Filter Include="include\bitcoin\network\net">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
Expand All @@ -86,7 +89,7 @@
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000A1}</UniqueIdentifier>
</Filter>
<Filter Include="resource">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000010}</UniqueIdentifier>
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000011}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000000}</UniqueIdentifier>
Expand Down Expand Up @@ -892,6 +895,9 @@
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\dispatcher.ipp">
<Filter>include\bitcoin\network\impl\messages\rpc</Filter>
</None>
<None Include="..\..\..\..\include\bitcoin\network\impl\protocols\protocol_rpc.ipp">
<Filter>include\bitcoin\network\impl\protocols</Filter>
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
Expand Down
28 changes: 20 additions & 8 deletions include/bitcoin/network/channels/channel_rpc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,20 @@ class channel_rpc
{
}

/// Serialize and write response to client (requires strand).
/// Completion handler is always invoked on the channel strand.
inline void send(rpc::response_t&& message, size_t size_hint,
result_handler&& handler) NOEXCEPT;
/// 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;

/// Resume reading from the socket (requires strand).
inline void resume() NOEXCEPT override;

/// Must call after successful message handling if no stop.
virtual inline void receive() NOEXCEPT;

protected:
/// Serialize and write response to client (requires strand).
/// Completion handler is always invoked on the channel strand.
inline void send(rpc::response_t&& message, size_t size_hint,
result_handler&& handler) NOEXCEPT;

/// Stranded handler invoked from stop().
inline void stopping(const code& ec) NOEXCEPT override;

Expand All @@ -82,20 +84,30 @@ class channel_rpc
virtual inline rpc::response_ptr assign_message(rpc::response_t&& message,
size_t size_hint) NOEXCEPT;

/// Handlers.
/// Must call after successful message handling if no stop.
virtual inline void receive() NOEXCEPT;

/// Handle incoming messages.
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.
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;
void log_message(const rpc::response& response,
size_t bytes) const NOEXCEPT;

// These are protected by strand.
rpc::version version_;
rpc::id_option identity_;
http::flat_buffer_ptr response_buffer_;
http::flat_buffer request_buffer_;
dispatcher dispatcher_{};
Expand Down
58 changes: 52 additions & 6 deletions include/bitcoin/network/impl/channels/channel_rpc.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ inline void CLASS::handle_receive(const code& ec, size_t bytes,
return;
}

// Save response state.
identity_ = request->message.id;
version_ = request->message.jsonrpc;

reading_ = false;
log_message(*request, bytes);
dispatch(request);
Expand All @@ -109,29 +113,58 @@ inline void CLASS::handle_receive(const code& ec, size_t bytes,
TEMPLATE
inline void CLASS::dispatch(const rpc::request_cptr& request) NOEXCEPT
{
BC_ASSERT(stranded());
if (const auto code = dispatcher_.notify(request->message))
stop(code);
}

TEMPLATE
inline http::flat_buffer& CLASS::request_buffer() NOEXCEPT
{
BC_ASSERT(stranded());
return request_buffer_;
}

// Send.
// ----------------------------------------------------------------------------

TEMPLATE
void CLASS::send_code(const code& ec) NOEXCEPT
{
BC_ASSERT(stranded());
send_error({ .code = ec.value(), .message = ec.message() });
}

TEMPLATE
void CLASS::send_error(rpc::result_t&& error) 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<CLASS>(), _1));
}

TEMPLATE
void CLASS::send_result(rpc::value_t&& result, size_t size_hint) 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<CLASS>(), _1));
}

// protected
TEMPLATE
inline void CLASS::send(rpc::response_t&& model, size_t size_hint,
result_handler&& handler) NOEXCEPT
{
BC_ASSERT(stranded());

using namespace std::placeholders;
const auto out = assign_message(std::move(model), size_hint);
count_handler complete = std::bind(&channel_rpc::handle_send,
shared_from_base<channel_rpc>(), _1, _2, out, std::move(handler));
count_handler complete = std::bind(&CLASS::handle_send,
shared_from_base<CLASS>(), _1, _2, out, std::move(handler));

if (!out)
{
Expand All @@ -142,22 +175,35 @@ inline void CLASS::send(rpc::response_t&& model, size_t size_hint,
write(*out, std::move(complete));
}

// protected
TEMPLATE
inline void CLASS::handle_send(const code& ec, size_t bytes,
const rpc::response_cptr& response, const result_handler& handler) NOEXCEPT
{
if (ec)
stop(ec);

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;

// Continue read loop.
receive();
}

// private
TEMPLATE
inline rpc::response_ptr CLASS::assign_message(rpc::response_t&& message,
size_t size_hint) NOEXCEPT
{
BC_ASSERT(stranded());
response_buffer_->max_size(size_hint);
const auto ptr = system::to_shared<rpc::response>();
ptr->message = std::move(message);
Expand Down
50 changes: 50 additions & 0 deletions include/bitcoin/network/impl/protocols/protocol_rpc.ipp
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef LIBBITCOIN_NETWORK_PROTOCOL_RPC_IPP
#define LIBBITCOIN_NETWORK_PROTOCOL_RPC_IPP

#include <bitcoin/network/define.hpp>
#include <bitcoin/network/messages/messages.hpp>

namespace libbitcoin {
namespace network {

TEMPLATE
inline void CLASS::send_code(const code& ec) NOEXCEPT
{
channel_->send_code(ec);
}

TEMPLATE
inline void CLASS::send_error(rpc::result_t&& error) NOEXCEPT
{
channel_->send_error(std::move(error));
}

TEMPLATE
inline void CLASS::send_result(rpc::value_t&& result,
size_t size_hint) NOEXCEPT
{
channel_->send_result(std::move(result), size_hint);
}

} // namespace network
} // namespace libbitcoin

#endif
Loading
Loading