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/beast/core/multi_buffer.hpp>
30#include <boost/beast/http/empty_body.hpp>
31#include <boost/beast/http/read.hpp>
32#include <boost/beast/http/write.hpp>
33
34namespace ripple {
35
36namespace detail {
37
38template <class Impl>
39class WorkBase : public Work
40{
41protected:
42 using error_code = boost::system::error_code;
43 using endpoint_type = boost::asio::ip::tcp::endpoint;
44
45public:
47 void(error_code const&, endpoint_type const&, response_type&&)>;
48
49protected:
50 using socket_type = boost::asio::ip::tcp::socket;
51 using resolver_type = boost::asio::ip::tcp::resolver;
52 using results_type = boost::asio::ip::tcp::resolver::results_type;
54 boost::beast::http::request<boost::beast::http::empty_body>;
55
60 boost::asio::io_service& ios_;
61 boost::asio::io_service::strand strand_;
66 boost::beast::multi_buffer readBuf_;
69
70public:
72 std::string const& host,
73 std::string const& path,
74 std::string const& port,
75 boost::asio::io_service& ios,
76 endpoint_type const& lastEndpoint,
77 bool lastStatus,
78 callback_type cb);
80
81 Impl&
83 {
84 return *static_cast<Impl*>(this);
85 }
86
87 void
88 run() override;
89
90 void
91 cancel() override;
92
93 void
94 fail(error_code const& ec);
95
96 void
97 onResolve(error_code const& ec, results_type results);
98
99 void
100 onConnect(error_code const& ec, endpoint_type const& endpoint);
101
102 void
104
105 void
107
108 void
110
111private:
112 void
114};
115
116//------------------------------------------------------------------------------
117
118template <class Impl>
120 std::string const& host,
121 std::string const& path,
122 std::string const& port,
123 boost::asio::io_service& ios,
124 endpoint_type const& lastEndpoint,
125 bool lastStatus,
126 callback_type cb)
127 : host_(host)
128 , path_(path)
129 , port_(port)
130 , cb_(std::move(cb))
131 , ios_(ios)
132 , strand_(ios)
133 , resolver_(ios)
134 , socket_(ios)
135 , lastEndpoint_{lastEndpoint}
136 , lastStatus_(lastStatus)
137{
138}
139
140template <class Impl>
142{
143 if (cb_)
144 cb_(make_error_code(boost::system::errc::not_a_socket),
145 lastEndpoint_,
146 std::move(res_));
147 close();
148}
149
150template <class Impl>
151void
153{
154 if (!strand_.running_in_this_thread())
155 return ios_.post(
156 strand_.wrap(std::bind(&WorkBase::run, impl().shared_from_this())));
157
158 resolver_.async_resolve(
159 host_,
160 port_,
161 strand_.wrap(std::bind(
163 impl().shared_from_this(),
164 std::placeholders::_1,
165 std::placeholders::_2)));
166}
167
168template <class Impl>
169void
171{
172 if (!strand_.running_in_this_thread())
173 {
174 return ios_.post(strand_.wrap(
175 std::bind(&WorkBase::cancel, impl().shared_from_this())));
176 }
177
178 error_code ec;
179 resolver_.cancel();
180 socket_.cancel(ec);
181}
182
183template <class Impl>
184void
186{
187 if (cb_)
188 {
189 cb_(ec, lastEndpoint_, std::move(res_));
190 cb_ = nullptr;
191 }
192}
193
194template <class Impl>
195void
197{
198 if (ec)
199 return fail(ec);
200
201 boost::asio::async_connect(
202 socket_,
203 results,
204 strand_.wrap(std::bind(
206 impl().shared_from_this(),
207 std::placeholders::_1,
208 std::placeholders::_2)));
209}
210
211template <class Impl>
212void
214{
215 lastEndpoint_ = endpoint;
216
217 if (ec)
218 return fail(ec);
219
220 impl().onConnect(ec);
221}
222
223template <class Impl>
224void
226{
227 req_.method(boost::beast::http::verb::get);
228 req_.target(path_.empty() ? "/" : path_);
229 req_.version(11);
230 req_.set("Host", host_ + ":" + port_);
231 req_.set("User-Agent", BuildInfo::getFullVersionString());
232 req_.prepare_payload();
233 boost::beast::http::async_write(
234 impl().stream(),
235 req_,
236 strand_.wrap(std::bind(
238 impl().shared_from_this(),
239 std::placeholders::_1)));
240}
241
242template <class Impl>
243void
245{
246 if (ec)
247 return fail(ec);
248
249 boost::beast::http::async_read(
250 impl().stream(),
251 readBuf_,
252 res_,
253 strand_.wrap(std::bind(
255 impl().shared_from_this(),
256 std::placeholders::_1)));
257}
258
259template <class Impl>
260void
262{
263 if (ec)
264 return fail(ec);
265
266 close();
267 XRPL_ASSERT(cb_, "ripple::detail::WorkBase::onResponse : callback is set");
268 cb_(ec, lastEndpoint_, std::move(res_));
269 cb_ = nullptr;
270}
271
272template <class Impl>
273void
275{
276 if (socket_.is_open())
277 {
278 error_code ec;
279 socket_.shutdown(boost::asio::socket_base::shutdown_send, ec);
280 if (ec)
281 return;
282 socket_.close(ec);
283 }
284}
285
286} // namespace detail
287
288} // namespace ripple
289
290#endif
T bind(T... args)
boost::asio::io_service & ios_
Definition: WorkBase.h:60
endpoint_type lastEndpoint_
Definition: WorkBase.h:67
callback_type cb_
Definition: WorkBase.h:59
boost::asio::ip::tcp::resolver::results_type results_type
Definition: WorkBase.h:52
response_type res_
Definition: WorkBase.h:65
boost::beast::http::request< boost::beast::http::empty_body > request_type
Definition: WorkBase.h:54
void onResolve(error_code const &ec, results_type results)
Definition: WorkBase.h:196
void onRequest(error_code const &ec)
Definition: WorkBase.h:244
boost::asio::ip::tcp::socket socket_type
Definition: WorkBase.h:50
boost::asio::io_service::strand strand_
Definition: WorkBase.h:61
socket_type socket_
Definition: WorkBase.h:63
void cancel() override
Definition: WorkBase.h:170
request_type req_
Definition: WorkBase.h:64
void onResponse(error_code const &ec)
Definition: WorkBase.h:261
boost::asio::ip::tcp::endpoint endpoint_type
Definition: WorkBase.h:43
boost::asio::ip::tcp::resolver resolver_type
Definition: WorkBase.h:51
boost::system::error_code error_code
Definition: WorkBase.h:42
boost::beast::multi_buffer readBuf_
Definition: WorkBase.h:66
void onConnect(error_code const &ec, endpoint_type const &endpoint)
Definition: WorkBase.h:213
WorkBase(std::string const &host, std::string const &path, std::string const &port, boost::asio::io_service &ios, endpoint_type const &lastEndpoint, bool lastStatus, callback_type cb)
Definition: WorkBase.h:119
void fail(error_code const &ec)
Definition: WorkBase.h:185
void run() override
Definition: WorkBase.h:152
resolver_type resolver_
Definition: WorkBase.h:62
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:26
std::error_code make_error_code(ripple::TokenCodecErrc e)
Definition: token_errors.h:97
STL namespace.