rippled
Loading...
Searching...
No Matches
WorkBase.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2016 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_APP_MISC_DETAIL_WORKBASE_H_INCLUDED
21#define RIPPLE_APP_MISC_DETAIL_WORKBASE_H_INCLUDED
22
23#include <xrpld/app/misc/detail/Work.h>
24
25#include <xrpl/basics/random.h>
26#include <xrpl/protocol/BuildInfo.h>
27
28#include <boost/asio.hpp>
29#include <boost/asio/strand.hpp>
30#include <boost/beast/core/multi_buffer.hpp>
31#include <boost/beast/http/empty_body.hpp>
32#include <boost/beast/http/read.hpp>
33#include <boost/beast/http/write.hpp>
34
35namespace ripple {
36
37namespace detail {
38
39template <class Impl>
40class WorkBase : public Work
41{
42protected:
43 using error_code = boost::system::error_code;
44 using endpoint_type = boost::asio::ip::tcp::endpoint;
45
46public:
48 void(error_code const&, endpoint_type const&, response_type&&)>;
49
50protected:
51 using socket_type = boost::asio::ip::tcp::socket;
52 using resolver_type = boost::asio::ip::tcp::resolver;
53 using results_type = boost::asio::ip::tcp::resolver::results_type;
55 boost::beast::http::request<boost::beast::http::empty_body>;
56
61 boost::asio::io_context& ios_;
62 boost::asio::strand<boost::asio::io_context::executor_type> strand_;
67 boost::beast::multi_buffer readBuf_;
70
71public:
73 std::string const& host,
74 std::string const& path,
75 std::string const& port,
76 boost::asio::io_context& ios,
77 endpoint_type const& lastEndpoint,
78 bool lastStatus,
79 callback_type cb);
81
82 Impl&
84 {
85 return *static_cast<Impl*>(this);
86 }
87
88 void
89 run() override;
90
91 void
92 cancel() override;
93
94 void
95 fail(error_code const& ec);
96
97 void
99
100 void
101 onConnect(error_code const& ec, endpoint_type const& endpoint);
102
103 void
105
106 void
108
109 void
111
112private:
113 void
115};
116
117//------------------------------------------------------------------------------
118
119template <class Impl>
121 std::string const& host,
122 std::string const& path,
123 std::string const& port,
124 boost::asio::io_context& ios,
125 endpoint_type const& lastEndpoint,
126 bool lastStatus,
127 callback_type cb)
128 : host_(host)
129 , path_(path)
130 , port_(port)
131 , cb_(std::move(cb))
132 , ios_(ios)
133 , strand_(boost::asio::make_strand(ios))
134 , resolver_(ios)
135 , socket_(ios)
136 , lastEndpoint_{lastEndpoint}
137 , lastStatus_(lastStatus)
138{
139}
140
141template <class Impl>
143{
144 if (cb_)
145 cb_(make_error_code(boost::system::errc::not_a_socket),
146 lastEndpoint_,
147 std::move(res_));
148 close();
149}
150
151template <class Impl>
152void
154{
155 if (!strand_.running_in_this_thread())
156 return boost::asio::post(
157 ios_,
158 boost::asio::bind_executor(
159 strand_, std::bind(&WorkBase::run, impl().shared_from_this())));
160
161 resolver_.async_resolve(
162 host_,
163 port_,
164 boost::asio::bind_executor(
165 strand_,
166 std::bind(
168 impl().shared_from_this(),
169 std::placeholders::_1,
170 std::placeholders::_2)));
171}
172
173template <class Impl>
174void
176{
177 if (!strand_.running_in_this_thread())
178 {
179 return boost::asio::post(
180 ios_,
181
182 boost::asio::bind_executor(
183 strand_,
184 std::bind(&WorkBase::cancel, impl().shared_from_this())));
185 }
186
187 error_code ec;
188 resolver_.cancel();
189 socket_.cancel(ec);
190}
191
192template <class Impl>
193void
195{
196 if (cb_)
197 {
198 cb_(ec, lastEndpoint_, std::move(res_));
199 cb_ = nullptr;
200 }
201}
202
203template <class Impl>
204void
206{
207 if (ec)
208 return fail(ec);
209
210 boost::asio::async_connect(
211 socket_,
212 results,
213 boost::asio::bind_executor(
214 strand_,
215 std::bind(
217 impl().shared_from_this(),
218 std::placeholders::_1,
219 std::placeholders::_2)));
220}
221
222template <class Impl>
223void
225{
226 lastEndpoint_ = endpoint;
227
228 if (ec)
229 return fail(ec);
230
231 impl().onConnect(ec);
232}
233
234template <class Impl>
235void
237{
238 req_.method(boost::beast::http::verb::get);
239 req_.target(path_.empty() ? "/" : path_);
240 req_.version(11);
241 req_.set("Host", host_ + ":" + port_);
242 req_.set("User-Agent", BuildInfo::getFullVersionString());
243 req_.prepare_payload();
244 boost::beast::http::async_write(
245 impl().stream(),
246 req_,
247 boost::asio::bind_executor(
248 strand_,
249 std::bind(
251 impl().shared_from_this(),
252 std::placeholders::_1)));
253}
254
255template <class Impl>
256void
258{
259 if (ec)
260 return fail(ec);
261
262 boost::beast::http::async_read(
263 impl().stream(),
264 readBuf_,
265 res_,
266 boost::asio::bind_executor(
267 strand_,
268 std::bind(
270 impl().shared_from_this(),
271 std::placeholders::_1)));
272}
273
274template <class Impl>
275void
277{
278 if (ec)
279 return fail(ec);
280
281 close();
282 XRPL_ASSERT(cb_, "ripple::detail::WorkBase::onResponse : callback is set");
283 cb_(ec, lastEndpoint_, std::move(res_));
284 cb_ = nullptr;
285}
286
287template <class Impl>
288void
290{
291 if (socket_.is_open())
292 {
293 error_code ec;
294 socket_.shutdown(boost::asio::socket_base::shutdown_send, ec);
295 if (ec)
296 return;
297 socket_.close(ec);
298 }
299}
300
301} // namespace detail
302
303} // namespace ripple
304
305#endif
T bind(T... args)
endpoint_type lastEndpoint_
Definition WorkBase.h:68
callback_type cb_
Definition WorkBase.h:60
boost::asio::ip::tcp::resolver::results_type results_type
Definition WorkBase.h:53
boost::asio::io_context & ios_
Definition WorkBase.h:61
response_type res_
Definition WorkBase.h:66
boost::beast::http::request< boost::beast::http::empty_body > request_type
Definition WorkBase.h:55
void onResolve(error_code const &ec, results_type results)
Definition WorkBase.h:205
void onRequest(error_code const &ec)
Definition WorkBase.h:257
boost::asio::ip::tcp::socket socket_type
Definition WorkBase.h:51
void cancel() override
Definition WorkBase.h:175
void onResponse(error_code const &ec)
Definition WorkBase.h:276
boost::asio::ip::tcp::endpoint endpoint_type
Definition WorkBase.h:44
boost::asio::ip::tcp::resolver resolver_type
Definition WorkBase.h:52
boost::system::error_code error_code
Definition WorkBase.h:43
boost::asio::strand< boost::asio::io_context::executor_type > strand_
Definition WorkBase.h:62
boost::beast::multi_buffer readBuf_
Definition WorkBase.h:67
WorkBase(std::string const &host, std::string const &path, std::string const &port, boost::asio::io_context &ios, endpoint_type const &lastEndpoint, bool lastStatus, callback_type cb)
Definition WorkBase.h:120
void onConnect(error_code const &ec, endpoint_type const &endpoint)
Definition WorkBase.h:224
void fail(error_code const &ec)
Definition WorkBase.h:194
void run() override
Definition WorkBase.h:153
resolver_type resolver_
Definition WorkBase.h:63
std::string const & getFullVersionString()
Full server version string.
Definition BuildInfo.cpp:81
boost::beast::http::response< boost::beast::http::string_body > response_type
Definition Work.h:31
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::error_code make_error_code(ripple::TokenCodecErrc e)
STL namespace.