xrpld
Loading...
Searching...
No Matches
SSLHTTPPeer.h
1#pragma once
2
3#include <xrpl/basics/Log.h>
4#include <xrpl/beast/utility/Journal.h>
5#include <xrpl/server/Port.h>
6#include <xrpl/server/WSSession.h>
7#include <xrpl/server/detail/BaseHTTPPeer.h>
8#include <xrpl/server/detail/SSLWSPeer.h>
9
10#include <boost/asio/ip/tcp.hpp>
11#include <boost/asio/ssl/context.hpp>
12#include <boost/asio/ssl/stream.hpp>
13#include <boost/beast/core/tcp_stream.hpp>
14#include <boost/beast/ssl/ssl_stream.hpp>
15
16#include <memory>
17#include <utility>
18
19namespace xrpl {
20
21template <class Handler>
22class SSLHTTPPeer : public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>,
23 public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
24{
25private:
26 friend class BaseHTTPPeer<Handler, SSLHTTPPeer>;
27 using socket_type = boost::asio::ip::tcp::socket;
28 using middle_type = boost::beast::tcp_stream;
29 using stream_type = boost::beast::ssl_stream<middle_type>;
30 using endpoint_type = boost::asio::ip::tcp::endpoint;
31 using yield_context = boost::asio::yield_context;
32 using error_code = boost::system::error_code;
33
37
38public:
39 template <class ConstBufferSequence>
41 Port const& port,
42 Handler& handler,
43 boost::asio::io_context& ioc,
46 ConstBufferSequence const& buffers,
47 middle_type&& stream);
48
49 void
50 run();
51
53 websocketUpgrade() override;
54
55private:
56 void
58
59 void
60 doRequest() override;
61
62 void
63 doClose() override;
64
65 void
67};
68
69//------------------------------------------------------------------------------
70
71template <class Handler>
72template <class ConstBufferSequence>
74 Port const& port,
75 Handler& handler,
76 boost::asio::io_context& ioc,
79 ConstBufferSequence const& buffers,
80 middle_type&& stream)
81 : BaseHTTPPeer<Handler, SSLHTTPPeer>(
82 port,
83 handler,
84 ioc.get_executor(),
85 journal,
87 buffers)
88 , streamPtr_(std::make_unique<stream_type>(middle_type(std::move(stream)), *port.context))
90 , socket_(stream_.next_layer().socket())
91{
92}
93
94// Called when the acceptor accepts our socket.
95template <class Handler>
96void
98{
99 if (!this->handler_.onAccept(this->session(), this->remoteAddress_))
100 {
102 this->strand_, [self = this->shared_from_this()](yield_context) { self->doClose(); });
103 return;
104 }
105 if (!socket_.is_open())
106 return;
107 util::spawn(this->strand_, [self = this->shared_from_this()](yield_context doYield) {
108 self->doHandshake(doYield);
109 });
110}
111
112template <class Handler>
115{
116 auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
117 this->port_,
118 this->handler_,
119 this->remoteAddress_,
120 std::move(this->message_),
121 std::move(this->streamPtr_),
122 this->journal_);
123 return ws;
124}
125
126template <class Handler>
127void
129{
130 boost::system::error_code ec;
131 stream_.set_verify_mode(boost::asio::ssl::verify_none);
132 this->startTimer();
133 this->readBuf_.consume(
134 stream_.async_handshake(stream_type::server, this->readBuf_.data(), doYield[ec]));
135 this->cancelTimer();
136 if (ec == boost::beast::error::timeout)
137 return this->onTimer();
138 if (ec)
139 return this->fail(ec, "handshake");
140 bool const http = this->port().protocol.count("peer") > 0 ||
141 this->port().protocol.count("wss") > 0 || this->port().protocol.count("wss2") > 0 ||
142 this->port().protocol.count("https") > 0;
143 if (http)
144 {
145 util::spawn(this->strand_, [self = this->shared_from_this()](yield_context doYield) {
146 self->doRead(doYield);
147 });
148 return;
149 }
150 // `this` will be destroyed
151}
152
153template <class Handler>
154void
156{
157 ++this->requestCount_;
158 auto const what = this->handler_.onHandoff(
159 this->session(), std::move(streamPtr_), std::move(this->message_), this->remoteAddress_);
160 if (what.moved)
161 return;
162 if (what.response)
163 return this->write(what.response, what.keepAlive);
164 // legacy
165 this->handler_.onRequest(this->session());
166}
167
168template <class Handler>
169void
171{
172 this->startTimer();
173 stream_.async_shutdown(bind_executor(
174 this->strand_,
175 [self = this->shared_from_this()](error_code const& ec) { self->onShutdown(ec); }));
176}
177
178template <class Handler>
179void
181{
182 this->cancelTimer();
183
184 if (ec == boost::asio::error::operation_aborted)
185 return;
186 if (ec)
187 {
188 JLOG(this->journal_.debug()) << "on_shutdown: " << ec.message();
189 }
190
191 // Close socket now in case this->destructor is delayed
192 stream_.next_layer().close();
193}
194
195} // namespace xrpl
A generic endpoint for log messages.
Definition Journal.h:44
BaseHTTPPeer(Port const &port, Handler &handler, boost::asio::executor const &executor, beast::Journal journal, endpoint_type remoteAddress, ConstBufferSequence const &buffers)
void write(void const *buffer, std::size_t bytes) override
void fail(error_code ec, char const *what)
boost::asio::strand< boost::asio::executor > strand_
boost::system::error_code error_code
Definition SSLHTTPPeer.h:32
boost::beast::ssl_stream< middle_type > stream_type
Definition SSLHTTPPeer.h:29
boost::asio::ip::tcp::endpoint endpoint_type
Definition SSLHTTPPeer.h:30
void doClose() override
boost::asio::yield_context yield_context
Definition SSLHTTPPeer.h:31
boost::beast::tcp_stream middle_type
Definition SSLHTTPPeer.h:28
void doRequest() override
stream_type & stream_
Definition SSLHTTPPeer.h:35
boost::asio::ip::tcp::socket socket_type
Definition SSLHTTPPeer.h:27
SSLHTTPPeer(Port const &port, Handler &handler, boost::asio::io_context &ioc, beast::Journal journal, endpoint_type remoteAddress, ConstBufferSequence const &buffers, middle_type &&stream)
Definition SSLHTTPPeer.h:73
std::shared_ptr< WSSession > websocketUpgrade() override
Convert the connection to WebSocket.
socket_type & socket_
Definition SSLHTTPPeer.h:36
void onShutdown(error_code ec)
std::unique_ptr< stream_type > streamPtr_
Definition SSLHTTPPeer.h:34
void doHandshake(yield_context doYield)
STL namespace.
void spawn(Ctx &&ctx, F &&func)
Spawns a coroutine using boost::asio::spawn.
Definition Spawn.h:67
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:29