Skip to content

Commit 7a01aaf

Browse files
committed
Echo rpc version and id from request to response.
1 parent a50cc79 commit 7a01aaf

File tree

7 files changed

+163
-85
lines changed

7 files changed

+163
-85
lines changed

Makefile.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ include_bitcoin_network_impl_messages_rpc_HEADERS = \
343343
include/bitcoin/network/impl/messages/rpc/broadcaster.ipp \
344344
include/bitcoin/network/impl/messages/rpc/dispatcher.ipp
345345

346+
include_bitcoin_network_impl_protocolsdir = ${includedir}/bitcoin/network/impl/protocols
347+
include_bitcoin_network_impl_protocols_HEADERS = \
348+
include/bitcoin/network/impl/protocols/protocol_rpc.ipp
349+
346350
include_bitcoin_network_interfacesdir = ${includedir}/bitcoin/network/interfaces
347351
include_bitcoin_network_interfaces_HEADERS = \
348352
include/bitcoin/network/interfaces/http.hpp \

builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@
381381
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\json_body.ipp" />
382382
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\broadcaster.ipp" />
383383
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\dispatcher.ipp" />
384+
<None Include="..\..\..\..\include\bitcoin\network\impl\protocols\protocol_rpc.ipp" />
384385
<None Include="packages.config" />
385386
</ItemGroup>
386387
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

builds/msvc/vs2022/libbitcoin-network/libbitcoin-network.vcxproj.filters

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000C1}</UniqueIdentifier>
3636
</Filter>
3737
<Filter Include="include\bitcoin\network\impl\async\races">
38-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000F1}</UniqueIdentifier>
38+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000002}</UniqueIdentifier>
3939
</Filter>
4040
<Filter Include="include\bitcoin\network\impl\channels">
4141
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000D1}</UniqueIdentifier>
@@ -44,7 +44,10 @@
4444
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000E1}</UniqueIdentifier>
4545
</Filter>
4646
<Filter Include="include\bitcoin\network\impl\messages\rpc">
47-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000002}</UniqueIdentifier>
47+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000003}</UniqueIdentifier>
48+
</Filter>
49+
<Filter Include="include\bitcoin\network\impl\protocols">
50+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000F1}</UniqueIdentifier>
4851
</Filter>
4952
<Filter Include="include\bitcoin\network\interfaces">
5053
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
@@ -56,25 +59,25 @@
5659
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
5760
</Filter>
5861
<Filter Include="include\bitcoin\network\messages\http">
59-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000003}</UniqueIdentifier>
62+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000004}</UniqueIdentifier>
6063
</Filter>
6164
<Filter Include="include\bitcoin\network\messages\http\enums">
62-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
65+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000007}</UniqueIdentifier>
6366
</Filter>
6467
<Filter Include="include\bitcoin\network\messages\peer">
65-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000004}</UniqueIdentifier>
68+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000005}</UniqueIdentifier>
6669
</Filter>
6770
<Filter Include="include\bitcoin\network\messages\peer\detail">
68-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000007}</UniqueIdentifier>
71+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
6972
</Filter>
7073
<Filter Include="include\bitcoin\network\messages\peer\enums">
71-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000008}</UniqueIdentifier>
74+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
7275
</Filter>
7376
<Filter Include="include\bitcoin\network\messages\rpc">
74-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000005}</UniqueIdentifier>
77+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000006}</UniqueIdentifier>
7578
</Filter>
7679
<Filter Include="include\bitcoin\network\messages\rpc\enums">
77-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
80+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000010}</UniqueIdentifier>
7881
</Filter>
7982
<Filter Include="include\bitcoin\network\net">
8083
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000009}</UniqueIdentifier>
@@ -86,7 +89,7 @@
8689
<UniqueIdentifier>{564EB540-D6B6-425C-0000-0000000000A1}</UniqueIdentifier>
8790
</Filter>
8891
<Filter Include="resource">
89-
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000010}</UniqueIdentifier>
92+
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000011}</UniqueIdentifier>
9093
</Filter>
9194
<Filter Include="src">
9295
<UniqueIdentifier>{564EB540-D6B6-425C-0000-000000000000}</UniqueIdentifier>
@@ -892,6 +895,9 @@
892895
<None Include="..\..\..\..\include\bitcoin\network\impl\messages\rpc\dispatcher.ipp">
893896
<Filter>include\bitcoin\network\impl\messages\rpc</Filter>
894897
</None>
898+
<None Include="..\..\..\..\include\bitcoin\network\impl\protocols\protocol_rpc.ipp">
899+
<Filter>include\bitcoin\network\impl\protocols</Filter>
900+
</None>
895901
<None Include="packages.config" />
896902
</ItemGroup>
897903
<ItemGroup>

include/bitcoin/network/channels/channel_rpc.hpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,20 @@ class channel_rpc
5757
{
5858
}
5959

60-
/// Serialize and write response to client (requires strand).
61-
/// Completion handler is always invoked on the channel strand.
62-
inline void send(rpc::response_t&& message, size_t size_hint,
63-
result_handler&& handler) NOEXCEPT;
60+
/// Public senders, rpc version and identity added to responses.
61+
inline void send_code(const code& ec) NOEXCEPT;
62+
inline void send_error(rpc::result_t&& error) NOEXCEPT;
63+
inline void send_result(rpc::value_t&& result, size_t size_hint) NOEXCEPT;
6464

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

68-
/// Must call after successful message handling if no stop.
69-
virtual inline void receive() NOEXCEPT;
70-
7168
protected:
69+
/// Serialize and write response to client (requires strand).
70+
/// Completion handler is always invoked on the channel strand.
71+
inline void send(rpc::response_t&& message, size_t size_hint,
72+
result_handler&& handler) NOEXCEPT;
73+
7274
/// Stranded handler invoked from stop().
7375
inline void stopping(const code& ec) NOEXCEPT override;
7476

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

85-
/// Handlers.
87+
/// Must call after successful message handling if no stop.
88+
virtual inline void receive() NOEXCEPT;
89+
90+
/// Handle incoming messages.
8691
virtual inline void handle_receive(const code& ec, size_t bytes,
8792
const rpc::request_cptr& request) NOEXCEPT;
93+
94+
/// Handle send complation, handler must invoke receive() unless stopping.
8895
virtual inline void handle_send(const code& ec, size_t bytes,
8996
const rpc::response_cptr& response,
9097
const result_handler& handler) NOEXCEPT;
9198

99+
/// Invoked upon handle_send completion to restart receive().
100+
virtual void handle_complete(const code& ec) NOEXCEPT;
101+
92102
private:
93103
void log_message(const rpc::request& request,
94104
size_t bytes) const NOEXCEPT;
95105
void log_message(const rpc::response& response,
96106
size_t bytes) const NOEXCEPT;
97107

98108
// These are protected by strand.
109+
rpc::version version_;
110+
rpc::id_option identity_;
99111
http::flat_buffer_ptr response_buffer_;
100112
http::flat_buffer request_buffer_;
101113
dispatcher dispatcher_{};

include/bitcoin/network/impl/channels/channel_rpc.ipp

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ inline void CLASS::handle_receive(const code& ec, size_t bytes,
101101
return;
102102
}
103103

104+
// Save response state.
105+
identity_ = request->message.id;
106+
version_ = request->message.jsonrpc;
107+
104108
reading_ = false;
105109
log_message(*request, bytes);
106110
dispatch(request);
@@ -109,25 +113,61 @@ inline void CLASS::handle_receive(const code& ec, size_t bytes,
109113
TEMPLATE
110114
inline void CLASS::dispatch(const rpc::request_cptr& request) NOEXCEPT
111115
{
116+
BC_ASSERT(stranded());
112117
if (const auto code = dispatcher_.notify(request->message))
113118
stop(code);
114119
}
115120

116121
TEMPLATE
117122
inline http::flat_buffer& CLASS::request_buffer() NOEXCEPT
118123
{
124+
BC_ASSERT(stranded());
119125
return request_buffer_;
120126
}
121127

122128
// Send.
123129
// ----------------------------------------------------------------------------
124130

131+
TEMPLATE
132+
void CLASS::send_code(const code& ec) NOEXCEPT
133+
{
134+
BC_ASSERT(stranded());
135+
send_error({ .code = ec.value(), .message = ec.message() });
136+
}
137+
138+
TEMPLATE
139+
void CLASS::send_error(rpc::result_t&& error) NOEXCEPT
140+
{
141+
BC_ASSERT(stranded());
142+
using namespace std::placeholders;
143+
const auto size_hint = two * error.message.size();
144+
send({
145+
.jsonrpc = version_,
146+
.id = identity_,
147+
.error = std::move(error)
148+
},
149+
size_hint, std::bind(&CLASS::handle_complete, _1));
150+
}
151+
152+
TEMPLATE
153+
void CLASS::send_result(rpc::value_t&& result, size_t size_hint) NOEXCEPT
154+
{
155+
BC_ASSERT(stranded());
156+
using namespace std::placeholders;
157+
send({
158+
.jsonrpc = version_,
159+
.id = identity_,
160+
.result = std::move(result)
161+
},
162+
size_hint, std::bind(&CLASS::handle_complete, _1));
163+
}
164+
165+
// protected
125166
TEMPLATE
126167
inline void CLASS::send(rpc::response_t&& model, size_t size_hint,
127168
result_handler&& handler) NOEXCEPT
128169
{
129170
BC_ASSERT(stranded());
130-
131171
using namespace std::placeholders;
132172
const auto out = assign_message(std::move(model), size_hint);
133173
count_handler complete = std::bind(&channel_rpc::handle_send,
@@ -142,22 +182,35 @@ inline void CLASS::send(rpc::response_t&& model, size_t size_hint,
142182
write(*out, std::move(complete));
143183
}
144184

185+
// protected
145186
TEMPLATE
146187
inline void CLASS::handle_send(const code& ec, size_t bytes,
147188
const rpc::response_cptr& response, const result_handler& handler) NOEXCEPT
148189
{
149-
if (ec)
150-
stop(ec);
151-
190+
BC_ASSERT(stranded());
191+
if (ec) stop(ec);
152192
log_message(*response, bytes);
153193
handler(ec);
154194
}
155195

196+
// protected
197+
TEMPLATE
198+
void CLASS::handle_complete(const code&) NOEXCEPT
199+
{
200+
BC_ASSERT(stranded());
201+
if (stopped())
202+
return;
203+
204+
// Continue read loop.
205+
receive();
206+
}
207+
156208
// private
157209
TEMPLATE
158210
inline rpc::response_ptr CLASS::assign_message(rpc::response_t&& message,
159211
size_t size_hint) NOEXCEPT
160212
{
213+
BC_ASSERT(stranded());
161214
response_buffer_->max_size(size_hint);
162215
const auto ptr = system::to_shared<rpc::response>();
163216
ptr->message = std::move(message);
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Copyright (c) 2011-2025 libbitcoin developers (see AUTHORS)
3+
*
4+
* This file is part of libbitcoin.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#ifndef LIBBITCOIN_NETWORK_PROTOCOL_RPC_IPP
20+
#define LIBBITCOIN_NETWORK_PROTOCOL_RPC_IPP
21+
22+
#include <bitcoin/network/define.hpp>
23+
#include <bitcoin/network/messages/messages.hpp>
24+
25+
namespace libbitcoin {
26+
namespace network {
27+
28+
TEMPLATE
29+
inline void CLASS::send_code(const code& ec) NOEXCEPT
30+
{
31+
channel_->send_code(ec);
32+
}
33+
34+
TEMPLATE
35+
inline void CLASS::send_error(rpc::result_t&& error) NOEXCEPT
36+
{
37+
channel_->send_error(std::move(error));
38+
}
39+
40+
TEMPLATE
41+
inline void CLASS::send_result(rpc::value_t&& result,
42+
size_t size_hint) NOEXCEPT
43+
{
44+
channel_->send_result(std::move(result), size_hint);
45+
}
46+
47+
} // namespace network
48+
} // namespace libbitcoin
49+
50+
#endif

0 commit comments

Comments
 (0)