20 #ifndef RIPPLE_APP_MISC_DETAIL_WORKBASE_H_INCLUDED
21 #define RIPPLE_APP_MISC_DETAIL_WORKBASE_H_INCLUDED
23 #include <ripple/app/misc/detail/Work.h>
24 #include <ripple/basics/random.h>
25 #include <ripple/protocol/BuildInfo.h>
27 #include <boost/asio.hpp>
28 #include <boost/beast/core/multi_buffer.hpp>
29 #include <boost/beast/http/empty_body.hpp>
30 #include <boost/beast/http/read.hpp>
31 #include <boost/beast/http/write.hpp>
55 boost::beast::http::request<boost::beast::http::empty_body>;
61 boost::asio::io_service&
ios_;
76 boost::asio::io_service& ios,
85 return *
static_cast<Impl*
>(
this);
116 template <
class Impl>
121 boost::asio::io_service& ios,
133 , lastEndpoint_{lastEndpoint}
134 , lastStatus_(lastStatus)
138 template <
class Impl>
142 cb_(make_error_code(boost::system::errc::not_a_socket),
148 template <
class Impl>
152 if (!strand_.running_in_this_thread())
154 strand_.wrap(
std::bind(&WorkBase::run, impl().shared_from_this())));
156 resolver_.async_resolve(
160 &WorkBase::onResolve,
161 impl().shared_from_this(),
162 std::placeholders::_1,
163 std::placeholders::_2)));
166 template <
class Impl>
170 if (!strand_.running_in_this_thread())
172 return ios_.post(strand_.wrap(
173 std::bind(&WorkBase::cancel, impl().shared_from_this())));
181 template <
class Impl>
187 cb_(ec, lastEndpoint_, std::move(res_));
192 template <
class Impl>
207 results.begin(), results.end(), [&](
endpoint_type const& e) {
208 if (e == lastEndpoint_)
213 if (foundIt != results.end() && lastStatus_)
214 return lastEndpoint_;
215 else if (results.size() == 1)
216 return *results.begin();
217 else if (foundIt == results.end())
227 (results.size() > 2) ?
rand_int(results.size() - 2) : 0;
228 if (randIndex == foundIndex)
229 randIndex = results.size() - 1;
230 return *
std::next(results.begin(), randIndex);
233 socket_.async_connect(
237 impl().shared_from_this(),
238 std::placeholders::_1)));
241 template <
class Impl>
245 req_.method(boost::beast::http::verb::get);
246 req_.target(path_.empty() ?
"/" : path_);
248 req_.set(
"Host", host_ +
":" + port_);
249 req_.set(
"User-Agent", BuildInfo::getFullVersionString());
250 req_.prepare_payload();
251 boost::beast::http::async_write(
255 &WorkBase::onRequest,
256 impl().shared_from_this(),
257 std::placeholders::_1)));
260 template <
class Impl>
267 boost::beast::http::async_read(
272 &WorkBase::onResponse,
273 impl().shared_from_this(),
274 std::placeholders::_1)));
277 template <
class Impl>
286 cb_(ec, lastEndpoint_, std::move(res_));
290 template <
class Impl>
294 if (socket_.is_open())
297 socket_.shutdown(boost::asio::socket_base::shutdown_send, ec);