xrpld
Loading...
Searching...
No Matches
WorkBase.h
1#pragma once
2
3#include <xrpld/app/misc/detail/Work.h>
4
5#include <xrpl/basics/random.h>
6#include <xrpl/protocol/BuildInfo.h>
7
8#include <boost/asio.hpp>
9#include <boost/asio/strand.hpp>
10#include <boost/beast/core/multi_buffer.hpp>
11#include <boost/beast/http/empty_body.hpp>
12#include <boost/beast/http/read.hpp>
13#include <boost/beast/http/write.hpp>
14
15#include <utility>
16
17namespace xrpl::detail {
18
19template <class Impl>
20class WorkBase : public Work
21{
22protected:
23 using error_code = boost::system::error_code;
24 using endpoint_type = boost::asio::ip::tcp::endpoint;
25
26public:
28 std::function<void(error_code const&, endpoint_type const&, response_type&&)>;
29
30protected:
31 using socket_type = boost::asio::ip::tcp::socket;
32 using resolver_type = boost::asio::ip::tcp::resolver;
33 using results_type = boost::asio::ip::tcp::resolver::results_type;
34 using request_type = boost::beast::http::request<boost::beast::http::empty_body>;
35
40 boost::asio::io_context& ios_;
41 boost::asio::strand<boost::asio::io_context::executor_type> strand_;
46 boost::beast::multi_buffer readBuf_;
49
50private:
52 std::string host,
54 std::string port,
55 boost::asio::io_context& ios,
56 endpoint_type lastEndpoint,
57 bool lastStatus,
58 callback_type cb);
59
60public:
61 ~WorkBase() override;
62
63 Impl&
65 {
66 return *static_cast<Impl*>(this);
67 }
68
69 void
70 run() override;
71
72 void
73 cancel() override;
74
75 void
76 fail(error_code const& ec);
77
78 void
79 onResolve(error_code const& ec, results_type results);
80
81 void
82 onConnect(error_code const& ec, endpoint_type const& endpoint);
83
84 void
86
87 void
89
90 void
92
93private:
94 void
96
97 friend Impl;
98};
99
100//------------------------------------------------------------------------------
101
102template <class Impl>
104 std::string host,
106 std::string port,
107 boost::asio::io_context& ios,
108 endpoint_type lastEndpoint,
109 bool lastStatus,
110 callback_type cb)
111 : host_(std::move(host))
112 , path_(std::move(path))
113 , port_(std::move(port))
114 , cb_(std::move(cb))
115 , ios_(ios)
116 , strand_(boost::asio::make_strand(ios))
117 , resolver_(ios)
118 , socket_(ios)
119 , lastEndpoint_{std::move(lastEndpoint)}
120 , lastStatus_(lastStatus)
121{
122}
123
124template <class Impl>
126{
127 if (cb_)
128 cb_(make_error_code(boost::system::errc::not_a_socket), lastEndpoint_, std::move(res_));
129 close();
130}
131
132template <class Impl>
133void
135{
136 if (!strand_.running_in_this_thread())
137 {
138 return boost::asio::post(
139 ios_,
140 boost::asio::bind_executor(
141 strand_, std::bind(&WorkBase::run, impl().shared_from_this())));
142 }
143
144 resolver_.async_resolve(
145 host_,
146 port_,
147 boost::asio::bind_executor(
148 strand_,
149 std::bind(
151 impl().shared_from_this(),
152 std::placeholders::_1,
153 std::placeholders::_2)));
154}
155
156template <class Impl>
157void
159{
160 if (!strand_.running_in_this_thread())
161 {
162 return boost::asio::post(
163 ios_,
164
165 boost::asio::bind_executor(
166 strand_, std::bind(&WorkBase::cancel, impl().shared_from_this())));
167 }
168
169 error_code ec;
170 resolver_.cancel();
171 socket_.cancel(ec);
172}
173
174template <class Impl>
175void
177{
178 if (cb_)
179 {
180 cb_(ec, lastEndpoint_, std::move(res_));
181 cb_ = nullptr;
182 }
183}
184
185template <class Impl>
186void
188{
189 if (ec)
190 return fail(ec);
191
192 boost::asio::async_connect(
193 socket_,
194 results,
195 boost::asio::bind_executor(
196 strand_,
197 std::bind(
199 impl().shared_from_this(),
200 std::placeholders::_1,
201 std::placeholders::_2)));
202}
203
204template <class Impl>
205void
207{
208 lastEndpoint_ = endpoint;
209
210 if (ec)
211 return fail(ec);
212
213 impl().onConnect(ec);
214}
215
216template <class Impl>
217void
219{
220 req_.method(boost::beast::http::verb::get);
221 req_.target(path_.empty() ? "/" : path_);
222 req_.version(11);
223 req_.set("Host", host_ + ":" + port_);
224 req_.set("User-Agent", BuildInfo::getFullVersionString());
225 req_.prepare_payload();
226 boost::beast::http::async_write(
227 impl().stream(),
228 req_,
229 boost::asio::bind_executor(
230 strand_,
231 std::bind(&WorkBase::onRequest, impl().shared_from_this(), std::placeholders::_1)));
232}
233
234template <class Impl>
235void
237{
238 if (ec)
239 return fail(ec);
240
241 boost::beast::http::async_read(
242 impl().stream(),
243 readBuf_,
244 res_,
245 boost::asio::bind_executor(
246 strand_,
247 std::bind(&WorkBase::onResponse, impl().shared_from_this(), std::placeholders::_1)));
248}
249
250template <class Impl>
251void
253{
254 if (ec)
255 return fail(ec);
256
257 close();
258 XRPL_ASSERT(cb_, "xrpl::detail::WorkBase::onResponse : callback is set");
259 cb_(ec, lastEndpoint_, std::move(res_));
260 cb_ = nullptr;
261}
262
263template <class Impl>
264void
266{
267 if (socket_.is_open())
268 {
269 error_code ec;
270 socket_.shutdown(boost::asio::socket_base::shutdown_send, ec);
271 if (ec)
272 return;
273 socket_.close(ec);
274 }
275}
276
277} // namespace xrpl::detail
T bind(T... args)
void fail(error_code const &ec)
Definition WorkBase.h:176
void cancel() override
Definition WorkBase.h:158
endpoint_type lastEndpoint_
Definition WorkBase.h:47
std::function< void(error_code const &, endpoint_type const &, response_type &&)> callback_type
Definition WorkBase.h:27
boost::beast::http::request< boost::beast::http::empty_body > request_type
Definition WorkBase.h:34
request_type req_
Definition WorkBase.h:44
response_type res_
Definition WorkBase.h:45
void onResolve(error_code const &ec, results_type results)
Definition WorkBase.h:187
std::string port_
Definition WorkBase.h:38
socket_type socket_
Definition WorkBase.h:43
callback_type cb_
Definition WorkBase.h:39
std::string path_
Definition WorkBase.h:37
boost::asio::ip::tcp::endpoint endpoint_type
Definition WorkBase.h:24
boost::system::error_code error_code
Definition WorkBase.h:23
boost::asio::ip::tcp::resolver::results_type results_type
Definition WorkBase.h:33
void onRequest(error_code const &ec)
Definition WorkBase.h:236
boost::asio::ip::tcp::socket socket_type
Definition WorkBase.h:31
void onConnect(error_code const &ec, endpoint_type const &endpoint)
Definition WorkBase.h:206
boost::asio::strand< boost::asio::io_context::executor_type > strand_
Definition WorkBase.h:41
void onResponse(error_code const &ec)
Definition WorkBase.h:252
boost::beast::multi_buffer readBuf_
Definition WorkBase.h:46
resolver_type resolver_
Definition WorkBase.h:42
boost::asio::io_context & ios_
Definition WorkBase.h:40
std::string host_
Definition WorkBase.h:36
void run() override
Definition WorkBase.h:134
boost::asio::ip::tcp::resolver resolver_type
Definition WorkBase.h:32
WorkBase(std::string host, std::string path, std::string port, boost::asio::io_context &ios, endpoint_type lastEndpoint, bool lastStatus, callback_type cb)
Definition WorkBase.h:103
STL namespace.
std::string const & getFullVersionString()
Full server version string.
Definition BuildInfo.cpp:82
boost::beast::http::response< boost::beast::http::string_body > response_type
Definition Work.h:8
std::error_code make_error_code(xrpl::TokenCodecErrc e)