rippled
Loading...
Searching...
No Matches
SSLHTTPPeer.h
1#pragma once
2
3#include <xrpl/server/detail/BaseHTTPPeer.h>
4#include <xrpl/server/detail/SSLWSPeer.h>
5
6#include <boost/asio/ip/tcp.hpp>
7#include <boost/asio/ssl/context.hpp>
8#include <boost/asio/ssl/stream.hpp>
9#include <boost/beast/core/tcp_stream.hpp>
10#include <boost/beast/ssl/ssl_stream.hpp>
11
12#include <memory>
13
14namespace xrpl {
15
16template <class Handler>
17class SSLHTTPPeer : public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>,
18 public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
19{
20private:
21 friend class BaseHTTPPeer<Handler, SSLHTTPPeer>;
22 using socket_type = boost::asio::ip::tcp::socket;
23 using middle_type = boost::beast::tcp_stream;
24 using stream_type = boost::beast::ssl_stream<middle_type>;
25 using endpoint_type = boost::asio::ip::tcp::endpoint;
26 using yield_context = boost::asio::yield_context;
27 using error_code = boost::system::error_code;
28
32
33public:
34 template <class ConstBufferSequence>
36 Port const& port,
37 Handler& handler,
38 boost::asio::io_context& ioc,
40 endpoint_type remote_address,
41 ConstBufferSequence const& buffers,
42 middle_type&& stream);
43
44 void
45 run();
46
48 websocketUpgrade() override;
49
50private:
51 void
53
54 void
55 do_request() override;
56
57 void
58 do_close() override;
59
60 void
62};
63
64//------------------------------------------------------------------------------
65
66template <class Handler>
67template <class ConstBufferSequence>
69 Port const& port,
70 Handler& handler,
71 boost::asio::io_context& ioc,
72 beast::Journal journal,
73 endpoint_type remote_address,
74 ConstBufferSequence const& buffers,
75 middle_type&& stream)
76 : BaseHTTPPeer<Handler, SSLHTTPPeer>(
77 port,
78 handler,
79 ioc.get_executor(),
80 journal,
81 remote_address,
82 buffers)
83 , stream_ptr_(std::make_unique<stream_type>(middle_type(std::move(stream)), *port.context))
84 , stream_(*stream_ptr_)
85 , socket_(stream_.next_layer().socket())
86{
87}
88
89// Called when the acceptor accepts our socket.
90template <class Handler>
91void
93{
94 if (!this->handler_.onAccept(this->session(), this->remote_address_))
95 {
96 util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_close, this->shared_from_this()));
97 return;
98 }
99 if (!socket_.is_open())
100 return;
102 this->strand_,
103 std::bind(&SSLHTTPPeer::do_handshake, this->shared_from_this(), std::placeholders::_1));
104}
105
106template <class Handler>
109{
110 auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
111 this->port_,
112 this->handler_,
113 this->remote_address_,
114 std::move(this->message_),
115 std::move(this->stream_ptr_),
116 this->journal_);
117 return ws;
118}
119
120template <class Handler>
121void
123{
124 boost::system::error_code ec;
125 stream_.set_verify_mode(boost::asio::ssl::verify_none);
126 this->start_timer();
127 this->read_buf_.consume(
128 stream_.async_handshake(stream_type::server, this->read_buf_.data(), do_yield[ec]));
129 this->cancel_timer();
130 if (ec == boost::beast::error::timeout)
131 return this->on_timer();
132 if (ec)
133 return this->fail(ec, "handshake");
134 bool const http = this->port().protocol.count("peer") > 0 ||
135 this->port().protocol.count("wss") > 0 || this->port().protocol.count("wss2") > 0 ||
136 this->port().protocol.count("https") > 0;
137 if (http)
138 {
140 this->strand_,
141 std::bind(&SSLHTTPPeer::do_read, this->shared_from_this(), std::placeholders::_1));
142 return;
143 }
144 // `this` will be destroyed
145}
146
147template <class Handler>
148void
150{
151 ++this->request_count_;
152 auto const what = this->handler_.onHandoff(
153 this->session(), std::move(stream_ptr_), std::move(this->message_), this->remote_address_);
154 if (what.moved)
155 return;
156 if (what.response)
157 return this->write(what.response, what.keep_alive);
158 // legacy
159 this->handler_.onRequest(this->session());
160}
161
162template <class Handler>
163void
165{
166 this->start_timer();
167 stream_.async_shutdown(bind_executor(
168 this->strand_,
169 std::bind(&SSLHTTPPeer::on_shutdown, this->shared_from_this(), std::placeholders::_1)));
170}
171
172template <class Handler>
173void
175{
176 this->cancel_timer();
177
178 if (ec == boost::asio::error::operation_aborted)
179 return;
180 if (ec)
181 {
182 JLOG(this->journal_.debug()) << "on_shutdown: " << ec.message();
183 }
184
185 // Close socket now in case this->destructor is delayed
186 stream_.next_layer().close();
187}
188
189} // namespace xrpl
T bind(T... args)
A generic endpoint for log messages.
Definition Journal.h:40
Represents an active connection.
boost::system::error_code error_code
Definition SSLHTTPPeer.h:27
void do_close() override
void do_request() override
void do_handshake(yield_context do_yield)
boost::beast::ssl_stream< middle_type > stream_type
Definition SSLHTTPPeer.h:24
boost::asio::ip::tcp::endpoint endpoint_type
Definition SSLHTTPPeer.h:25
boost::asio::yield_context yield_context
Definition SSLHTTPPeer.h:26
boost::beast::tcp_stream middle_type
Definition SSLHTTPPeer.h:23
std::unique_ptr< stream_type > stream_ptr_
Definition SSLHTTPPeer.h:29
SSLHTTPPeer(Port const &port, Handler &handler, boost::asio::io_context &ioc, beast::Journal journal, endpoint_type remote_address, ConstBufferSequence const &buffers, middle_type &&stream)
Definition SSLHTTPPeer.h:68
void on_shutdown(error_code ec)
stream_type & stream_
Definition SSLHTTPPeer.h:30
boost::asio::ip::tcp::socket socket_type
Definition SSLHTTPPeer.h:22
std::shared_ptr< WSSession > websocketUpgrade() override
Convert the connection to WebSocket.
socket_type & socket_
Definition SSLHTTPPeer.h:31
STL namespace.
void spawn(Ctx &&ctx, F &&func)
Spawns a coroutine using boost::asio::spawn
Definition Spawn.h:66
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
Configuration information for a Server listening port.
Definition Port.h:30