rippled
Loading...
Searching...
No Matches
AutoSocket.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 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_WEBSOCKET_AUTOSOCKET_AUTOSOCKET_H_INCLUDED
21#define RIPPLE_WEBSOCKET_AUTOSOCKET_AUTOSOCKET_H_INCLUDED
22
23#include <xrpl/basics/Log.h>
24#include <xrpl/beast/net/IPAddressConversion.h>
25
26#include <boost/asio.hpp>
27#include <boost/asio/ip/tcp.hpp>
28#include <boost/asio/ssl.hpp>
29#include <boost/beast/core/bind_handler.hpp>
30
31// Socket wrapper that supports both SSL and non-SSL connections.
32// Generally, handle it as you would an SSL connection.
33// To force a non-SSL connection, just don't call async_handshake.
34// To force SSL only inbound, call setSSLOnly.
35
37{
38public:
39 using ssl_socket = boost::asio::ssl::stream<boost::asio::ip::tcp::socket>;
40 using endpoint_type = boost::asio::ip::tcp::socket::endpoint_type;
42 using plain_socket = ssl_socket::next_layer_type;
43 using lowest_layer_type = ssl_socket::lowest_layer_type;
44 using handshake_type = ssl_socket::handshake_type;
45 using error_code = boost::system::error_code;
47
48public:
50 boost::asio::io_context& s,
51 boost::asio::ssl::context& c,
52 bool secureOnly,
53 bool plainOnly)
54 : mSecure(secureOnly)
55 , mBuffer((plainOnly || secureOnly) ? 0 : 4)
56 , j_{beast::Journal::getNullSink()}
57 {
59 }
60
61 AutoSocket(boost::asio::io_context& s, boost::asio::ssl::context& c)
62 : AutoSocket(s, c, false, false)
63 {
64 }
65
66 bool
68 {
69 return mSecure;
70 }
73 {
74 return *mSocket;
75 }
78 {
79 return mSocket->next_layer();
80 }
81
87
93
96 {
97 return mSocket->lowest_layer();
98 }
99
100 void
101 swap(AutoSocket& s) noexcept
102 {
103 mBuffer.swap(s.mBuffer);
104 mSocket.swap(s.mSocket);
105 std::swap(mSecure, s.mSecure);
106 }
107
108 boost::system::error_code
109 cancel(boost::system::error_code& ec)
110 {
111 return lowest_layer().cancel(ec);
112 }
113
114 void
116 {
117 if ((type == ssl_socket::client) || (mSecure))
118 {
119 // must be ssl
120 mSecure = true;
121 mSocket->async_handshake(type, cbFunc);
122 }
123 else if (mBuffer.empty())
124 {
125 // must be plain
126 mSecure = false;
127 post(
128 mSocket->get_executor(),
129 boost::beast::bind_handler(cbFunc, error_code()));
130 }
131 else
132 {
133 // autodetect
134 mSocket->next_layer().async_receive(
135 boost::asio::buffer(mBuffer),
136 boost::asio::socket_base::message_peek,
137 std::bind(
139 this,
140 cbFunc,
141 std::placeholders::_1,
142 std::placeholders::_2));
143 }
144 }
145
146 template <typename ShutdownHandler>
147 void
148 async_shutdown(ShutdownHandler handler)
149 {
150 if (isSecure())
151 mSocket->async_shutdown(handler);
152 else
153 {
154 error_code ec;
155 try
156 {
157 lowest_layer().shutdown(plain_socket::shutdown_both);
158 }
159 catch (boost::system::system_error& e)
160 {
161 ec = e.code();
162 }
163 post(
164 mSocket->get_executor(),
165 boost::beast::bind_handler(handler, ec));
166 }
167 }
168
169 template <typename Seq, typename Handler>
170 void
171 async_read_some(Seq const& buffers, Handler handler)
172 {
173 if (isSecure())
174 mSocket->async_read_some(buffers, handler);
175 else
176 PlainSocket().async_read_some(buffers, handler);
177 }
178
179 template <typename Seq, typename Condition, typename Handler>
180 void
181 async_read_until(Seq const& buffers, Condition condition, Handler handler)
182 {
183 if (isSecure())
184 boost::asio::async_read_until(
185 *mSocket, buffers, condition, handler);
186 else
187 boost::asio::async_read_until(
188 PlainSocket(), buffers, condition, handler);
189 }
190
191 template <typename Allocator, typename Handler>
192 void
194 boost::asio::basic_streambuf<Allocator>& buffers,
195 std::string const& delim,
196 Handler handler)
197 {
198 if (isSecure())
199 boost::asio::async_read_until(*mSocket, buffers, delim, handler);
200 else
201 boost::asio::async_read_until(
202 PlainSocket(), buffers, delim, handler);
203 }
204
205 template <typename Allocator, typename MatchCondition, typename Handler>
206 void
208 boost::asio::basic_streambuf<Allocator>& buffers,
209 MatchCondition cond,
210 Handler handler)
211 {
212 if (isSecure())
213 boost::asio::async_read_until(*mSocket, buffers, cond, handler);
214 else
215 boost::asio::async_read_until(
216 PlainSocket(), buffers, cond, handler);
217 }
218
219 template <typename Buf, typename Handler>
220 void
221 async_write(Buf const& buffers, Handler handler)
222 {
223 if (isSecure())
224 boost::asio::async_write(*mSocket, buffers, handler);
225 else
226 boost::asio::async_write(PlainSocket(), buffers, handler);
227 }
228
229 template <typename Allocator, typename Handler>
230 void
232 boost::asio::basic_streambuf<Allocator>& buffers,
233 Handler handler)
234 {
235 if (isSecure())
236 boost::asio::async_write(*mSocket, buffers, handler);
237 else
238 boost::asio::async_write(PlainSocket(), buffers, handler);
239 }
240
241 template <typename Buf, typename Condition, typename Handler>
242 void
243 async_read(Buf const& buffers, Condition cond, Handler handler)
244 {
245 if (isSecure())
246 boost::asio::async_read(*mSocket, buffers, cond, handler);
247 else
248 boost::asio::async_read(PlainSocket(), buffers, cond, handler);
249 }
250
251 template <typename Allocator, typename Condition, typename Handler>
252 void
254 boost::asio::basic_streambuf<Allocator>& buffers,
255 Condition cond,
256 Handler handler)
257 {
258 if (isSecure())
259 boost::asio::async_read(*mSocket, buffers, cond, handler);
260 else
261 boost::asio::async_read(PlainSocket(), buffers, cond, handler);
262 }
263
264 template <typename Buf, typename Handler>
265 void
266 async_read(Buf const& buffers, Handler handler)
267 {
268 if (isSecure())
269 boost::asio::async_read(*mSocket, buffers, handler);
270 else
271 boost::asio::async_read(PlainSocket(), buffers, handler);
272 }
273
274 template <typename Seq, typename Handler>
275 void
276 async_write_some(Seq const& buffers, Handler handler)
277 {
278 if (isSecure())
279 mSocket->async_write_some(buffers, handler);
280 else
281 PlainSocket().async_write_some(buffers, handler);
282 }
283
284protected:
285 void
287 callback cbFunc,
288 error_code const& ec,
289 size_t bytesTransferred)
290 {
291 using namespace ripple;
292
293 if (ec)
294 {
295 JLOG(j_.warn()) << "Handle autodetect error: " << ec;
296 cbFunc(ec);
297 }
298 else if (
299 (mBuffer[0] < 127) && (mBuffer[0] > 31) &&
300 ((bytesTransferred < 2) ||
301 ((mBuffer[1] < 127) && (mBuffer[1] > 31))) &&
302 ((bytesTransferred < 3) ||
303 ((mBuffer[2] < 127) && (mBuffer[2] > 31))) &&
304 ((bytesTransferred < 4) ||
305 ((mBuffer[3] < 127) && (mBuffer[3] > 31))))
306 {
307 // not ssl
308 JLOG(j_.trace()) << "non-SSL";
309 mSecure = false;
310 cbFunc(ec);
311 }
312 else
313 {
314 // ssl
315 JLOG(j_.trace()) << "SSL";
316 mSecure = true;
317 mSocket->async_handshake(ssl_socket::server, cbFunc);
318 }
319 }
320
321private:
326};
327
328#endif
T bind(T... args)
socket_ptr mSocket
Definition AutoSocket.h:322
void async_write(boost::asio::basic_streambuf< Allocator > &buffers, Handler handler)
Definition AutoSocket.h:231
AutoSocket(boost::asio::io_context &s, boost::asio::ssl::context &c, bool secureOnly, bool plainOnly)
Definition AutoSocket.h:49
ssl_socket::handshake_type handshake_type
Definition AutoSocket.h:44
ssl_socket::lowest_layer_type lowest_layer_type
Definition AutoSocket.h:43
ssl_socket::next_layer_type plain_socket
Definition AutoSocket.h:42
boost::asio::ip::tcp::socket::endpoint_type endpoint_type
Definition AutoSocket.h:40
beast::IP::Endpoint remote_endpoint()
Definition AutoSocket.h:89
void async_read(boost::asio::basic_streambuf< Allocator > &buffers, Condition cond, Handler handler)
Definition AutoSocket.h:253
void handle_autodetect(callback cbFunc, error_code const &ec, size_t bytesTransferred)
Definition AutoSocket.h:286
beast::Journal j_
Definition AutoSocket.h:325
boost::system::error_code error_code
Definition AutoSocket.h:45
AutoSocket(boost::asio::io_context &s, boost::asio::ssl::context &c)
Definition AutoSocket.h:61
bool isSecure()
Definition AutoSocket.h:67
void async_handshake(handshake_type type, callback cbFunc)
Definition AutoSocket.h:115
void async_read_until(boost::asio::basic_streambuf< Allocator > &buffers, MatchCondition cond, Handler handler)
Definition AutoSocket.h:207
void async_read_until(boost::asio::basic_streambuf< Allocator > &buffers, std::string const &delim, Handler handler)
Definition AutoSocket.h:193
void async_read(Buf const &buffers, Handler handler)
Definition AutoSocket.h:266
void async_write(Buf const &buffers, Handler handler)
Definition AutoSocket.h:221
lowest_layer_type & lowest_layer()
Definition AutoSocket.h:95
beast::IP::Endpoint local_endpoint()
Definition AutoSocket.h:83
void async_read_until(Seq const &buffers, Condition condition, Handler handler)
Definition AutoSocket.h:181
plain_socket & PlainSocket()
Definition AutoSocket.h:77
void async_read(Buf const &buffers, Condition cond, Handler handler)
Definition AutoSocket.h:243
void async_read_some(Seq const &buffers, Handler handler)
Definition AutoSocket.h:171
std::vector< char > mBuffer
Definition AutoSocket.h:324
void swap(AutoSocket &s) noexcept
Definition AutoSocket.h:101
void async_write_some(Seq const &buffers, Handler handler)
Definition AutoSocket.h:276
ssl_socket & SSLSocket()
Definition AutoSocket.h:72
void async_shutdown(ShutdownHandler handler)
Definition AutoSocket.h:148
boost::system::error_code cancel(boost::system::error_code &ec)
Definition AutoSocket.h:109
boost::asio::ssl::stream< boost::asio::ip::tcp::socket > ssl_socket
Definition AutoSocket.h:39
A version-independent IP address and port combination.
Definition IPEndpoint.h:38
A generic endpoint for log messages.
Definition Journal.h:60
Stream trace() const
Severity stream access functions.
Definition Journal.h:322
Stream warn() const
Definition Journal.h:340
T empty(T... args)
T is_same_v
Endpoint from_asio(boost::asio::ip::address const &address)
Convert to Endpoint.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
T swap(T... args)