|
23 | 23 | #include <variant> |
24 | 24 | #include <bitcoin/network/define.hpp> |
25 | 25 | #include <bitcoin/network/messages/messages.hpp> |
26 | | -////#include <bitcoin/network/messages/messages.hpp> |
27 | 26 |
|
28 | 27 | namespace libbitcoin { |
29 | 28 | namespace network { |
@@ -65,46 +64,52 @@ put(const buffer_type& buffer, boost_code& ec) NOEXCEPT |
65 | 64 | if (!terminated_) |
66 | 65 | return parsed; |
67 | 66 |
|
68 | | - // There is no terminator. |
| 67 | + // There is no terminator (terminal). |
69 | 68 | if (is_zero(parsed)) |
70 | 69 | { |
71 | 70 | ec = to_http_code(http_error_t::end_of_stream); |
72 | 71 | return parsed; |
73 | 72 | } |
74 | 73 |
|
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. |
83 | 76 | const auto data = pointer_cast<const char>(buffer.data()); |
84 | | - if (data[sub1(parsed)] == '\n') |
| 77 | + for (auto index = parsed; !is_zero(index);) |
85 | 78 | { |
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 | + } |
88 | 85 | } |
89 | 86 |
|
90 | | - // There is no terminator. |
91 | | - ec = to_http_code(http_error_t::end_of_stream); |
| 87 | + // There is no terminator (yet). |
92 | 88 | return parsed; |
93 | 89 | } |
94 | 90 |
|
| 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 | + |
95 | 99 | template <> |
96 | 100 | void body<rpc::request_t>::reader:: |
97 | 101 | finish(boost_code& ec) NOEXCEPT |
98 | 102 | { |
99 | | - base::reader::finish(ec); |
100 | | - if (ec) return; |
101 | | - |
102 | | - if (terminated_ && !has_terminator_) |
| 103 | + if (!done()) |
103 | 104 | { |
104 | | - ec = to_http_code(http_error_t::end_of_stream); |
| 105 | + ec = to_http_code(http_error_t::partial_message); |
105 | 106 | return; |
106 | 107 | } |
107 | 108 |
|
| 109 | + // Call after !done() since finish() resets the parser. |
| 110 | + base::reader::finish(ec); |
| 111 | + if (ec) return; |
| 112 | + |
108 | 113 | try |
109 | 114 | { |
110 | 115 | value_.message = value_to<rpc::request_t>(value_.model); |
@@ -162,6 +167,14 @@ finish(boost_code&) NOEXCEPT |
162 | 167 | BC_ASSERT(false); |
163 | 168 | } |
164 | 169 |
|
| 170 | +template <> |
| 171 | +bool body<rpc::response_t>::reader:: |
| 172 | +done() const NOEXCEPT |
| 173 | +{ |
| 174 | + BC_ASSERT(false); |
| 175 | + return {}; |
| 176 | +} |
| 177 | + |
165 | 178 | // rpc::body::writer |
166 | 179 | // ---------------------------------------------------------------------------- |
167 | 180 |
|
|
0 commit comments