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>
36  : public BaseHTTPPeer<Handler, SSLHTTPPeer<Handler>>
37  , public std::enable_shared_from_this<SSLHTTPPeer<Handler>>
38 {
39 private:
40  friend class BaseHTTPPeer<Handler, SSLHTTPPeer>;
41  using socket_type = boost::asio::ip::tcp::socket;
42  using middle_type = boost::beast::tcp_stream;
43  using stream_type = boost::beast::ssl_stream <middle_type>;
44  using endpoint_type = boost::asio::ip::tcp::endpoint;
45  using yield_context = boost::asio::yield_context;
46  using error_code = boost::system::error_code;
47 
51 
52 public:
53  template <class ConstBufferSequence>
55  Port const& port,
56  Handler& handler,
57  boost::asio::io_context& ioc,
59  endpoint_type remote_address,
60  ConstBufferSequence const& buffers,
61  middle_type&& stream);
62 
63  void
64  run();
65 
67  websocketUpgrade() override;
68 
69 private:
70  void
71  do_handshake(yield_context do_yield);
72 
73  void
74  do_request() override;
75 
76  void
77  do_close() override;
78 
79  void
81 };
82 
83 //------------------------------------------------------------------------------
84 
85 template <class Handler>
86 template <class ConstBufferSequence>
88  Port const& port,
89  Handler& handler,
90  boost::asio::io_context& ioc,
91  beast::Journal journal,
92  endpoint_type remote_address,
93  ConstBufferSequence const& buffers,
94  middle_type&& stream)
95  : BaseHTTPPeer<Handler, SSLHTTPPeer>(
96  port,
97  handler,
98  ioc.get_executor(),
99  journal,
100  remote_address,
101  buffers)
102  , stream_ptr_(std::make_unique<stream_type>(
103  middle_type(std::move(stream)), *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
114 {
115  if(! this->handler_.onAccept(this->session(), this->remote_address_))
116  {
117  boost::asio::spawn(this->strand_,
119  this->shared_from_this()));
120  return;
121  }
122  if (! socket_.is_open())
123  return;
124  boost::asio::spawn(this->strand_, std::bind(
125  &SSLHTTPPeer::do_handshake, this->shared_from_this(),
126  std::placeholders::_1));
127 }
128 
129 template<class Handler>
133 {
134  auto ws = this->ios().template emplace<SSLWSPeer<Handler>>(
135  this->port_, this->handler_, this->remote_address_,
136  std::move(this->message_), std::move(this->stream_ptr_),
137  this->journal_);
138  return ws;
139 }
140 
141 template<class Handler>
142 void
145 {
146  boost::system::error_code ec;
147  stream_.set_verify_mode(boost::asio::ssl::verify_none);
148  this->start_timer();
149  this->read_buf_.consume(stream_.async_handshake(
150  stream_type::server, this->read_buf_.data(), do_yield[ec]));
151  this->cancel_timer();
152  if(ec == boost::beast::error::timeout)
153  return this->on_timer();
154  if (ec)
155  return this->fail(ec, "handshake");
156  bool const http =
157  this->port().protocol.count("peer") > 0 ||
158  this->port().protocol.count("wss") > 0 ||
159  this->port().protocol.count("wss2") > 0 ||
160  this->port().protocol.count("https") > 0;
161  if(http)
162  {
163  boost::asio::spawn(this->strand_,
165  this->shared_from_this(), std::placeholders::_1));
166  return;
167  }
168  // `this` will be destroyed
169 }
170 
171 template<class Handler>
172 void
175 {
176  ++this->request_count_;
177  auto const what = this->handler_.onHandoff(this->session(),
178  std::move(stream_ptr_), std::move(this->message_),
179  this->remote_address_);
180  if(what.moved)
181  return;
182  if(what.response)
183  return this->write(what.response, what.keep_alive);
184  // legacy
185  this->handler_.onRequest(this->session());
186 }
187 
188 template<class Handler>
189 void
192 {
193  this->start_timer();
194  stream_.async_shutdown(bind_executor(
195  this->strand_,
196  std::bind(
198  this->shared_from_this(),
199  std::placeholders::_1)));
200 }
201 
202 template<class Handler>
203 void
206 {
207  this->cancel_timer();
208 
209  if (ec == boost::asio::error::operation_aborted)
210  return;
211  if (ec)
212  {
213  JLOG(this->journal_.debug()) <<
214  "on_shutdown: " << ec.message();
215  }
216 
217  // Close socket now in case this->destructor is delayed
218  stream_.next_layer().close();
219 }
220 
221 } // ripple
222 
223 #endif
ripple::SSLHTTPPeer
Definition: SSLHTTPPeer.h:35
ripple::SSLHTTPPeer::stream_
stream_type & stream_
Definition: SSLHTTPPeer.h:49
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:46
ripple::SSLHTTPPeer::endpoint_type
boost::asio::ip::tcp::endpoint endpoint_type
Definition: SSLHTTPPeer.h:44
ripple::SSLHTTPPeer::socket_
socket_type & socket_
Definition: SSLHTTPPeer.h:50
ripple::SSLHTTPPeer::do_request
void do_request() override
Definition: SSLHTTPPeer.h:174
ripple::SSLHTTPPeer::yield_context
boost::asio::yield_context yield_context
Definition: SSLHTTPPeer.h:45
ripple::SSLHTTPPeer::socket_type
boost::asio::ip::tcp::socket socket_type
Definition: SSLHTTPPeer.h:41
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:87
ripple::SSLHTTPPeer::run
void run()
Definition: SSLHTTPPeer.h:113
ripple::SSLHTTPPeer::stream_type
boost::beast::ssl_stream< middle_type > stream_type
Definition: SSLHTTPPeer.h:43
ripple::SSLHTTPPeer::middle_type
boost::beast::tcp_stream middle_type
Definition: SSLHTTPPeer.h:42
std::enable_shared_from_this
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:60
ripple::Port
Configuration information for a Server listening port.
Definition: Port.h:38
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::journal
beast::Journal journal() override
Definition: BaseHTTPPeer.h:171
memory
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::port
Port const & port() override
Definition: BaseHTTPPeer.h:177
ripple::SSLHTTPPeer::websocketUpgrade
std::shared_ptr< WSSession > websocketUpgrade() override
Convert the connection to WebSocket.
Definition: SSLHTTPPeer.h:132
ripple::BaseHTTPPeer< Handler, SSLHTTPPeer< Handler > >::do_read
void do_read(yield_context do_yield)
Definition: BaseHTTPPeer.h:316
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:191
std
STL namespace.
ripple::SSLHTTPPeer::stream_ptr_
std::unique_ptr< stream_type > stream_ptr_
Definition: SSLHTTPPeer.h:48
ripple::SSLHTTPPeer::do_handshake
void do_handshake(yield_context do_yield)
Definition: SSLHTTPPeer.h:144
std::unique_ptr< stream_type >
ripple::SSLHTTPPeer::on_shutdown
void on_shutdown(error_code ec)
Definition: SSLHTTPPeer.h:205