20 #ifndef RIPPLE_SERVER_DOOR_H_INCLUDED
21 #define RIPPLE_SERVER_DOOR_H_INCLUDED
23 #include <ripple/server/impl/io_list.h>
24 #include <ripple/basics/contract.h>
25 #include <ripple/basics/Log.h>
26 #include <ripple/server/impl/PlainHTTPPeer.h>
27 #include <ripple/server/impl/SSLHTTPPeer.h>
28 #include <boost/beast/core/detect_ssl.hpp>
29 #include <boost/beast/core/multi_buffer.hpp>
30 #include <boost/beast/core/tcp_stream.hpp>
31 #include <boost/asio/basic_waitable_timer.hpp>
32 #include <boost/asio/buffer.hpp>
33 #include <boost/asio/io_context.hpp>
34 #include <boost/asio/ip/tcp.hpp>
35 #include <boost/asio/spawn.hpp>
36 #include <boost/container/flat_map.hpp>
46 template<
class Handler>
53 using timer_type = boost::asio::basic_waitable_timer<clock_type>;
70 boost::asio::io_context&
ioc_;
81 boost::asio::io_context& ioc,
86 void close()
override;
95 boost::asio::io_context&
ioc_;
102 Door(Handler& handler, boost::asio::io_context& io_context,
114 void close()
override;
122 template <
class ConstBufferSequence>
123 void create (
bool ssl, ConstBufferSequence
const& buffers,
129 template <
class Handler>
133 boost::asio::io_context& ioc,
140 , stream_(
std::move(stream))
141 , socket_(stream_.socket())
142 , remote_address_(remote_address)
148 template<
class Handler>
157 template<
class Handler>
165 template<
class Handler>
170 boost::beast::multi_buffer buf(16);
172 boost::system::error_code ec;
173 bool const ssl = async_detect_ssl(stream_, buf, do_yield[ec]);
174 stream_.expires_never();
181 buf.data(), std::move(stream_)))
187 buf.data(), std::move(stream_)))
191 if (ec != boost::asio::error::operation_aborted)
194 "Error detecting ssl: " << ec.message() <<
195 " from " << remote_address_;
201 template<
class Handler>
203 Door(Handler& handler, boost::asio::io_context& io_context,
212 port_.protocol.count(
"https") > 0 ||
213 port_.protocol.count(
"wss") > 0 ||
214 port_.protocol.count(
"wss2") > 0 ||
215 port_.protocol.count(
"peer") > 0)
217 port_.protocol.count(
"http") > 0 ||
218 port_.protocol.count(
"ws") > 0 ||
219 port_.protocol.count(
"ws2"))
225 acceptor_.open(local_address.protocol(), ec);
229 "Open port '" << port.
name <<
"' failed:" << ec.message();
230 Throw<std::exception> ();
234 boost::asio::ip::tcp::acceptor::reuse_address(
true), ec);
238 "Option for port '" << port.
name <<
"' failed:" << ec.message();
239 Throw<std::exception> ();
246 "Bind port '" << port.
name <<
"' failed:" << ec.message();
247 Throw<std::exception> ();
250 acceptor_.listen(boost::asio::socket_base::max_connections, ec);
254 "Listen on port '" << port.
name <<
"' failed:" << ec.message();
255 Throw<std::exception> ();
262 template<
class Handler>
268 this->shared_from_this(), std::placeholders::_1));
271 template<
class Handler>
276 if (! strand_.running_in_this_thread())
285 template<
class Handler>
286 template<
class ConstBufferSequence>
289 create(
bool ssl, ConstBufferSequence
const& buffers,
295 port_, handler_, ioc_, j_, remote_address,
296 buffers, std::move(stream)))
301 port_, handler_, ioc_, j_, remote_address,
302 buffers, std::move(stream)))
306 template<
class Handler>
311 while (acceptor_.is_open())
317 acceptor_.async_accept (socket, remote_address, do_yield[ec]);
318 if (ec && ec != boost::asio::error::operation_aborted)
321 "accept: " << ec.message();
323 if (ec == boost::asio::error::operation_aborted)
330 if (
auto sp = ios().
template emplace<Detector>(
331 port_, handler_, ioc_, std::move(stream),
335 else if (ssl_ || plain_)
337 create(ssl_, boost::asio::null_buffers{},
338 std::move(stream), remote_address);