rippled
Loading...
Searching...
No Matches
SSLHTTPPeer.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_SERVER_SSLHTTPPEER_H_INCLUDED
21#define RIPPLE_SERVER_SSLHTTPPEER_H_INCLUDED
22
23#include <xrpl/server/detail/BaseHTTPPeer.h>
24#include <xrpl/server/detail/SSLWSPeer.h>
25#include <boost/asio/ip/tcp.hpp>
26#include <boost/asio/ssl/context.hpp>
27#include <boost/asio/ssl/stream.hpp>
28#include <boost/beast/core/tcp_stream.hpp>
29#include <boost/beast/ssl/ssl_stream.hpp>
30#include <memory>
31
32namespace ripple {
33
34template <class Handler>
35class SSLHTTPPeer : public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>,
36 public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
37{
38private:
39 friend class BaseHTTPPeer<Handler, SSLHTTPPeer>;
40 using socket_type = boost::asio::ip::tcp::socket;
41 using middle_type = boost::beast::tcp_stream;
42 using stream_type = boost::beast::ssl_stream<middle_type>;
43 using endpoint_type = boost::asio::ip::tcp::endpoint;
44 using yield_context = boost::asio::yield_context;
45 using error_code = boost::system::error_code;
46
50
51public:
52 template <class ConstBufferSequence>
54 Port const& port,
55 Handler& handler,
56 boost::asio::io_context& ioc,
58 endpoint_type remote_address,
59 ConstBufferSequence const& buffers,
60 middle_type&& stream);
61
62 void
63 run();
64
66 websocketUpgrade() override;
67
68private:
69 void
71
72 void
73 do_request() override;
74
75 void
76 do_close() override;
77
78 void
80};
81
82//------------------------------------------------------------------------------
83
84template <class Handler>
85template <class ConstBufferSequence>
87 Port const& port,
88 Handler& handler,
89 boost::asio::io_context& ioc,
90 beast::Journal journal,
91 endpoint_type remote_address,
92 ConstBufferSequence const& buffers,
93 middle_type&& stream)
94 : BaseHTTPPeer<Handler, SSLHTTPPeer>(
95 port,
96 handler,
97 ioc.get_executor(),
98 journal,
99 remote_address,
100 buffers)
101 , stream_ptr_(std::make_unique<stream_type>(
102 middle_type(std::move(stream)),
103 *port.context))
104 , stream_(*stream_ptr_)
105 , socket_(stream_.next_layer().socket())
106{
107}
108
109// Called when the acceptor accepts our socket.
110template <class Handler>
111void
113{
114 if (!this->handler_.onAccept(this->session(), this->remote_address_))
115 {
116 boost::asio::spawn(
117 this->strand_,
118 std::bind(&SSLHTTPPeer::do_close, this->shared_from_this()));
119 return;
120 }
121 if (!socket_.is_open())
122 return;
123 boost::asio::spawn(
124 this->strand_,
125 std::bind(
127 this->shared_from_this(),
128 std::placeholders::_1));
129}
130
131template <class Handler>
134{
135 auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
136 this->port_,
137 this->handler_,
138 this->remote_address_,
139 std::move(this->message_),
140 std::move(this->stream_ptr_),
141 this->journal_);
142 return ws;
143}
144
145template <class Handler>
146void
148{
149 boost::system::error_code ec;
150 stream_.set_verify_mode(boost::asio::ssl::verify_none);
151 this->start_timer();
152 this->read_buf_.consume(stream_.async_handshake(
153 stream_type::server, this->read_buf_.data(), do_yield[ec]));
154 this->cancel_timer();
155 if (ec == boost::beast::error::timeout)
156 return this->on_timer();
157 if (ec)
158 return this->fail(ec, "handshake");
159 bool const http = this->port().protocol.count("peer") > 0 ||
160 this->port().protocol.count("wss") > 0 ||
161 this->port().protocol.count("wss2") > 0 ||
162 this->port().protocol.count("https") > 0;
163 if (http)
164 {
165 boost::asio::spawn(
166 this->strand_,
167 std::bind(
169 this->shared_from_this(),
170 std::placeholders::_1));
171 return;
172 }
173 // `this` will be destroyed
174}
175
176template <class Handler>
177void
179{
180 ++this->request_count_;
181 auto const what = this->handler_.onHandoff(
182 this->session(),
183 std::move(stream_ptr_),
184 std::move(this->message_),
185 this->remote_address_);
186 if (what.moved)
187 return;
188 if (what.response)
189 return this->write(what.response, what.keep_alive);
190 // legacy
191 this->handler_.onRequest(this->session());
192}
193
194template <class Handler>
195void
197{
198 this->start_timer();
199 stream_.async_shutdown(bind_executor(
200 this->strand_,
201 std::bind(
203 this->shared_from_this(),
204 std::placeholders::_1)));
205}
206
207template <class Handler>
208void
210{
211 this->cancel_timer();
212
213 if (ec == boost::asio::error::operation_aborted)
214 return;
215 if (ec)
216 {
217 JLOG(this->journal_.debug()) << "on_shutdown: " << ec.message();
218 }
219
220 // Close socket now in case this->destructor is delayed
221 stream_.next_layer().close();
222}
223
224} // namespace ripple
225
226#endif
T bind(T... args)
A generic endpoint for log messages.
Definition: Journal.h:59
Represents an active connection.
Definition: BaseHTTPPeer.h:50
boost::asio::ip::tcp::socket socket_type
Definition: SSLHTTPPeer.h:40
stream_type & stream_
Definition: SSLHTTPPeer.h:48
void do_request() override
Definition: SSLHTTPPeer.h:178
std::unique_ptr< stream_type > stream_ptr_
Definition: SSLHTTPPeer.h:47
std::shared_ptr< WSSession > websocketUpgrade() override
Convert the connection to WebSocket.
Definition: SSLHTTPPeer.h:133
void on_shutdown(error_code ec)
Definition: SSLHTTPPeer.h:209
boost::system::error_code error_code
Definition: SSLHTTPPeer.h:45
void do_close() override
Definition: SSLHTTPPeer.h:196
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:86
boost::asio::ip::tcp::endpoint endpoint_type
Definition: SSLHTTPPeer.h:43
boost::asio::yield_context yield_context
Definition: SSLHTTPPeer.h:44
void do_handshake(yield_context do_yield)
Definition: SSLHTTPPeer.h:147
socket_type & socket_
Definition: SSLHTTPPeer.h:49
boost::beast::ssl_stream< middle_type > stream_type
Definition: SSLHTTPPeer.h:42
boost::beast::tcp_stream middle_type
Definition: SSLHTTPPeer.h:41
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
STL namespace.
Configuration information for a Server listening port.
Definition: Port.h:49