rippled
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 <ripple/server/impl/BaseHTTPPeer.h>
24 #include <ripple/server/impl/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 
32 namespace ripple {
33 
34 template <class Handler>
35 class SSLHTTPPeer : public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>,
36  public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
37 {
38 private:
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 
51 public:
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 
68 private:
69  void
70  do_handshake(yield_context do_yield);
71 
72  void
73  do_request() override;
74 
75  void
76  do_close() override;
77 
78  void
80 };
81 
82 //------------------------------------------------------------------------------
83 
84 template <class Handler>
85 template <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.
110 template <class Handler>
111 void
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 
131 template <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 
145 template <class Handler>
146 void
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 
176 template <class Handler>
177 void
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 
194 template <class Handler>
195 void
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 
207 template <class Handler>
208 void
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
ripple::SSLHTTPPeer
Definition: SSLHTTPPeer.h:35
ripple::SSLHTTPPeer::stream_
stream_type & stream_
Definition: SSLHTTPPeer.h:48
std::bind
T bind(T... args)
std::shared_ptr
STL class.
ripple::BaseHTTPPeer
Represents an active connection.
Definition: BaseHTTPPeer.h:49
ripple::SSLHTTPPeer::error_code
boost::system::error_code error_code
Definition: SSLHTTPPeer.h:45
ripple::SSLHTTPPeer::endpoint_type
boost::asio::ip::tcp::endpoint endpoint_type
Definition: SSLHTTPPeer.h:43
ripple::SSLHTTPPeer::socket_
socket_type & socket_
Definition: SSLHTTPPeer.h:49
ripple::SSLHTTPPeer::do_request
void do_request() override
Definition: SSLHTTPPeer.h:178
ripple::SSLHTTPPeer::yield_context
boost::asio::yield_context yield_context
Definition: SSLHTTPPeer.h:44
ripple::SSLHTTPPeer::socket_type
boost::asio::ip::tcp::socket socket_type
Definition: SSLHTTPPeer.h:40
ripple::SSLHTTPPeer::SSLHTTPPeer
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
ripple::SSLHTTPPeer::run
void run()
Definition: SSLHTTPPeer.h:112
ripple::SSLHTTPPeer::middle_type
boost::beast::tcp_stream middle_type
Definition: SSLHTTPPeer.h:41
ripple::SSLHTTPPeer::stream_type
boost::beast::ssl_stream< middle_type > stream_type
Definition: SSLHTTPPeer.h:42
std::enable_shared_from_this
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:48
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::journal
beast::Journal journal() override
Definition: BaseHTTPPeer.h:165
memory
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::port
Port const & port() override
Definition: BaseHTTPPeer.h:171
ripple::SSLHTTPPeer::websocketUpgrade
std::shared_ptr< WSSession > websocketUpgrade() override
Convert the connection to WebSocket.
Definition: SSLHTTPPeer.h:133
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::do_read
void do_read(yield_context do_yield)
Definition: BaseHTTPPeer.h:299
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::SSLHTTPPeer::do_close
void do_close() override
Definition: SSLHTTPPeer.h:196
std
STL namespace.
ripple::SSLHTTPPeer::stream_ptr_
std::unique_ptr< stream_type > stream_ptr_
Definition: SSLHTTPPeer.h:47
ripple::SSLHTTPPeer::do_handshake
void do_handshake(yield_context do_yield)
Definition: SSLHTTPPeer.h:147
std::unique_ptr< stream_type >
ripple::SSLHTTPPeer::on_shutdown
void on_shutdown(error_code ec)
Definition: SSLHTTPPeer.h:209