Skip to content

Commit 564e6bf

Browse files
committed
Fixes to json-rpc parse/read handling in socket/body.
1 parent 6802ae8 commit 564e6bf

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

include/bitcoin/network/messages/rpc/body.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ struct BCT_API body
6666

6767
size_t put(const buffer_type& buffer, boost_code& ec) NOEXCEPT override;
6868
void finish(boost_code& ec) NOEXCEPT override;
69+
bool done() const NOEXCEPT override;
6970

7071
private:
7172
const bool terminated_{};

src/messages/rpc/body.cpp

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
#include <variant>
2424
#include <bitcoin/network/define.hpp>
2525
#include <bitcoin/network/messages/messages.hpp>
26-
////#include <bitcoin/network/messages/messages.hpp>
2726

2827
namespace libbitcoin {
2928
namespace network {
@@ -65,46 +64,52 @@ put(const buffer_type& buffer, boost_code& ec) NOEXCEPT
6564
if (!terminated_)
6665
return parsed;
6766

68-
// There is no terminator.
67+
// There is no terminator (terminal).
6968
if (is_zero(parsed))
7069
{
7170
ec = to_http_code(http_error_t::end_of_stream);
7271
return parsed;
7372
}
7473

75-
// There are extra characters.
76-
if (size > parsed)
77-
{
78-
ec = to_http_code(http_error_t::unexpected_body);
79-
return parsed;
80-
}
81-
82-
// boost::json consumes whitespace, so terminator is always last.
74+
// boost::json consumes whitespace, and leaves any subsequent chars
75+
// unparsed, so terminator must be in the parsed segment of the buffer.
8376
const auto data = pointer_cast<const char>(buffer.data());
84-
if (data[sub1(parsed)] == '\n')
77+
for (auto index = parsed; !is_zero(index);)
8578
{
86-
has_terminator_ = true;
87-
return parsed;
79+
if (data[--index] == '\n')
80+
{
81+
// There may be unparsed characters (ok, next message).
82+
has_terminator_ = true;
83+
return parsed;
84+
}
8885
}
8986

90-
// There is no terminator.
91-
ec = to_http_code(http_error_t::end_of_stream);
87+
// There is no terminator (yet).
9288
return parsed;
9389
}
9490

91+
template <>
92+
bool body<rpc::request_t>::reader::
93+
done() const NOEXCEPT
94+
{
95+
// Parser may be done but with terminator still outstanding.
96+
return parser_.done() && (!terminated_ || has_terminator_);
97+
}
98+
9599
template <>
96100
void body<rpc::request_t>::reader::
97101
finish(boost_code& ec) NOEXCEPT
98102
{
99-
base::reader::finish(ec);
100-
if (ec) return;
101-
102-
if (terminated_ && !has_terminator_)
103+
if (!done())
103104
{
104-
ec = to_http_code(http_error_t::end_of_stream);
105+
ec = to_http_code(http_error_t::partial_message);
105106
return;
106107
}
107108

109+
// Call after !done() since finish() resets the parser.
110+
base::reader::finish(ec);
111+
if (ec) return;
112+
108113
try
109114
{
110115
value_.message = value_to<rpc::request_t>(value_.model);
@@ -162,6 +167,14 @@ finish(boost_code&) NOEXCEPT
162167
BC_ASSERT(false);
163168
}
164169

170+
template <>
171+
bool body<rpc::response_t>::reader::
172+
done() const NOEXCEPT
173+
{
174+
BC_ASSERT(false);
175+
return {};
176+
}
177+
165178
// rpc::body::writer
166179
// ----------------------------------------------------------------------------
167180

src/net/socket.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -686,18 +686,10 @@ void socket::handle_rpc_read(boost_code ec, size_t size, size_t total,
686686
const auto parsed = in->reader.put(data, ec);
687687
if (!ec)
688688
{
689-
if (parsed < data.size())
690-
{
691-
handler(error::unexpected_body, total);
692-
return;
693-
}
694-
695689
in->value.buffer->consume(parsed);
696690
if (in->reader.done())
697691
{
698692
in->reader.finish(ec);
699-
700-
// Finished.
701693
if (!ec)
702694
{
703695
handler(error::success, total);

0 commit comments

Comments
 (0)