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>(port, handler, ioc.get_executor(), journal, remote_address, buffers)
77 , stream_ptr_(std::make_unique<stream_type>(middle_type(std::move(stream)), *port.context))
78 , stream_(*stream_ptr_)
79 , socket_(stream_.next_layer().socket())
80{
81}
82
83// Called when the acceptor accepts our socket.
84template <class Handler>
85void
87{
88 if (!this->handler_.onAccept(this->session(), this->remote_address_))
89 {
90 util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_close, this->shared_from_this()));
91 return;
92 }
93 if (!socket_.is_open())
94 return;
95 util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_handshake, this->shared_from_this(), std::placeholders::_1));
96}
97
98template <class Handler>
101{
102 auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
103 this->port_,
104 this->handler_,
105 this->remote_address_,
106 std::move(this->message_),
107 std::move(this->stream_ptr_),
108 this->journal_);
109 return ws;
110}
111
112template <class Handler>
113void
115{
116 boost::system::error_code ec;
117 stream_.set_verify_mode(boost::asio::ssl::verify_none);
118 this->start_timer();
119 this->read_buf_.consume(stream_.async_handshake(stream_type::server, this->read_buf_.data(), do_yield[ec]));
120 this->cancel_timer();
121 if (ec == boost::beast::error::timeout)
122 return this->on_timer();
123 if (ec)
124 return this->fail(ec, "handshake");
125 bool const http = this->port().protocol.count("peer") > 0 || this->port().protocol.count("wss") > 0 ||
126 this->port().protocol.count("wss2") > 0 || this->port().protocol.count("https") > 0;
127 if (http)
128 {
129 util::spawn(this->strand_, std::bind(&SSLHTTPPeer::do_read, this->shared_from_this(), std::placeholders::_1));
130 return;
131 }
132 // `this` will be destroyed
133}
134
135template <class Handler>
136void
138{
139 ++this->request_count_;
140 auto const what = this->handler_.onHandoff(
141 this->session(), std::move(stream_ptr_), std::move(this->message_), this->remote_address_);
142 if (what.moved)
143 return;
144 if (what.response)
145 return this->write(what.response, what.keep_alive);
146 // legacy
147 this->handler_.onRequest(this->session());
148}
149
150template <class Handler>
151void
153{
154 this->start_timer();
155 stream_.async_shutdown(bind_executor(
156 this->strand_, std::bind(&SSLHTTPPeer::on_shutdown, this->shared_from_this(), std::placeholders::_1)));
157}
158
159template <class Handler>
160void
162{
163 this->cancel_timer();
164
165 if (ec == boost::asio::error::operation_aborted)
166 return;
167 if (ec)
168 {
169 JLOG(this->journal_.debug()) << "on_shutdown: " << ec.message();
170 }
171
172 // Close socket now in case this->destructor is delayed
173 stream_.next_layer().close();
174}
175
176} // 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:65
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