forked from boostorg/beast
330 lines
8.5 KiB
C++
330 lines
8.5 KiB
C++
//
|
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Official repository: https://github.com/boostorg/beast
|
|
//
|
|
|
|
#ifndef BOOST_BEAST_EXAMPLE_COMMON_SSL_STREAM_HPP
|
|
#define BOOST_BEAST_EXAMPLE_COMMON_SSL_STREAM_HPP
|
|
|
|
// This include is necessary to work with `ssl::stream` and `boost::beast::websocket::stream`
|
|
#include <boost/beast/websocket/ssl.hpp>
|
|
|
|
#include "flat_stream.hpp"
|
|
|
|
#include <boost/asio/ip/tcp.hpp>
|
|
#include <boost/asio/ssl/stream.hpp>
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
/** C++11 enabled SSL socket wrapper
|
|
|
|
This wrapper provides an interface identical to `boost::asio::ssl::stream`,
|
|
with the following additional properties:
|
|
|
|
@li Satisfies @b MoveConstructible
|
|
|
|
@li Satisfies @b MoveAssignable
|
|
|
|
@li Constructible from a moved socket.
|
|
*/
|
|
template<class NextLayer>
|
|
class ssl_stream
|
|
: public boost::asio::ssl::stream_base
|
|
{
|
|
using ssl_stream_type = boost::asio::ssl::stream<NextLayer>;
|
|
using stream_type = flat_stream<ssl_stream_type>;
|
|
|
|
std::unique_ptr<stream_type> p_;
|
|
boost::asio::ssl::context* ctx_;
|
|
|
|
public:
|
|
/// The native handle type of the SSL stream.
|
|
using native_handle_type =
|
|
typename ssl_stream_type::native_handle_type;
|
|
|
|
/// Structure for use with deprecated impl_type.
|
|
using impl_struct = typename ssl_stream_type::impl_struct;
|
|
|
|
/// The type of the next layer.
|
|
using next_layer_type = typename ssl_stream_type::next_layer_type;
|
|
|
|
/// The type of the lowest layer.
|
|
using lowest_layer_type = typename ssl_stream_type::lowest_layer_type;
|
|
|
|
/// The type of the executor associated with the object.
|
|
using executor_type = typename stream_type::executor_type;
|
|
|
|
template<class Arg>
|
|
ssl_stream(
|
|
Arg&& arg,
|
|
boost::asio::ssl::context& ctx)
|
|
: p_(new stream_type{
|
|
std::forward<Arg>(arg), ctx})
|
|
, ctx_(&ctx)
|
|
{
|
|
}
|
|
|
|
ssl_stream(ssl_stream&& other)
|
|
: p_(std::move(other.p_))
|
|
, ctx_(other.ctx_)
|
|
{
|
|
}
|
|
|
|
ssl_stream& operator=(ssl_stream&& other)
|
|
{
|
|
p_ = std::move(other.p_);
|
|
ctx_ = other.ctx_;
|
|
return *this;
|
|
}
|
|
|
|
executor_type
|
|
get_executor() noexcept
|
|
{
|
|
return p_->get_executor();
|
|
}
|
|
|
|
native_handle_type
|
|
native_handle()
|
|
{
|
|
return p_->next_layer().native_handle();
|
|
}
|
|
|
|
next_layer_type const&
|
|
next_layer() const
|
|
{
|
|
return p_->next_layer().next_layer();
|
|
}
|
|
|
|
next_layer_type&
|
|
next_layer()
|
|
{
|
|
return p_->next_layer().next_layer();
|
|
}
|
|
|
|
lowest_layer_type&
|
|
lowest_layer()
|
|
{
|
|
return p_->lowest_layer();
|
|
}
|
|
|
|
lowest_layer_type const&
|
|
lowest_layer() const
|
|
{
|
|
return p_->lowest_layer();
|
|
}
|
|
|
|
void
|
|
set_verify_mode(boost::asio::ssl::verify_mode v)
|
|
{
|
|
p_->next_layer().set_verify_mode(v);
|
|
}
|
|
|
|
boost::system::error_code
|
|
set_verify_mode(boost::asio::ssl::verify_mode v,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().set_verify_mode(v, ec);
|
|
}
|
|
|
|
void
|
|
set_verify_depth(int depth)
|
|
{
|
|
p_->next_layer().set_verify_depth(depth);
|
|
}
|
|
|
|
boost::system::error_code
|
|
set_verify_depth(
|
|
int depth, boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().set_verify_depth(depth, ec);
|
|
}
|
|
|
|
template<class VerifyCallback>
|
|
void
|
|
set_verify_callback(VerifyCallback callback)
|
|
{
|
|
p_->next_layer().set_verify_callback(callback);
|
|
}
|
|
|
|
template<class VerifyCallback>
|
|
boost::system::error_code
|
|
set_verify_callback(VerifyCallback callback,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().set_verify_callback(callback, ec);
|
|
}
|
|
|
|
void
|
|
handshake(handshake_type type)
|
|
{
|
|
p_->next_layer().handshake(type);
|
|
}
|
|
|
|
boost::system::error_code
|
|
handshake(handshake_type type,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().handshake(type, ec);
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
void
|
|
handshake(
|
|
handshake_type type, ConstBufferSequence const& buffers)
|
|
{
|
|
p_->next_layer().handshake(type, buffers);
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
boost::system::error_code
|
|
handshake(handshake_type type,
|
|
ConstBufferSequence const& buffers,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().handshake(type, buffers, ec);
|
|
}
|
|
|
|
template<class HandshakeHandler>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
|
|
void(boost::system::error_code))
|
|
async_handshake(handshake_type type,
|
|
BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
|
|
{
|
|
return p_->next_layer().async_handshake(type,
|
|
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
|
|
}
|
|
|
|
template<class ConstBufferSequence, class BufferedHandshakeHandler>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
|
|
void (boost::system::error_code, std::size_t))
|
|
async_handshake(handshake_type type, ConstBufferSequence const& buffers,
|
|
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
|
|
{
|
|
return p_->next_layer().async_handshake(type, buffers,
|
|
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
|
|
}
|
|
|
|
void
|
|
shutdown()
|
|
{
|
|
p_->next_layer().shutdown();
|
|
}
|
|
|
|
boost::system::error_code
|
|
shutdown(boost::system::error_code& ec)
|
|
{
|
|
return p_->next_layer().shutdown(ec);
|
|
}
|
|
|
|
template<class ShutdownHandler>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
|
|
void (boost::system::error_code))
|
|
async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
|
|
{
|
|
return p_->next_layer().async_shutdown(
|
|
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
std::size_t
|
|
write_some(ConstBufferSequence const& buffers)
|
|
{
|
|
return p_->write_some(buffers);
|
|
}
|
|
|
|
template<class ConstBufferSequence>
|
|
std::size_t
|
|
write_some(ConstBufferSequence const& buffers,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->write_some(buffers, ec);
|
|
}
|
|
|
|
template<class ConstBufferSequence, class WriteHandler>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
|
void (boost::system::error_code, std::size_t))
|
|
async_write_some(ConstBufferSequence const& buffers,
|
|
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
|
|
{
|
|
return p_->async_write_some(buffers,
|
|
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
|
|
}
|
|
|
|
template<class MutableBufferSequence>
|
|
std::size_t
|
|
read_some(MutableBufferSequence const& buffers)
|
|
{
|
|
return p_->read_some(buffers);
|
|
}
|
|
|
|
template<class MutableBufferSequence>
|
|
std::size_t
|
|
read_some(MutableBufferSequence const& buffers,
|
|
boost::system::error_code& ec)
|
|
{
|
|
return p_->read_some(buffers, ec);
|
|
}
|
|
|
|
template<class MutableBufferSequence, class ReadHandler>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
|
void(boost::system::error_code, std::size_t))
|
|
async_read_some(MutableBufferSequence const& buffers,
|
|
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
|
|
{
|
|
return p_->async_read_some(buffers,
|
|
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
|
|
}
|
|
|
|
template<class SyncStream>
|
|
friend
|
|
void
|
|
teardown(boost::beast::websocket::role_type,
|
|
ssl_stream<SyncStream>& stream,
|
|
boost::system::error_code& ec);
|
|
|
|
template<class AsyncStream, class TeardownHandler>
|
|
friend
|
|
void
|
|
async_teardown(boost::beast::websocket::role_type,
|
|
ssl_stream<AsyncStream>& stream, TeardownHandler&& handler);
|
|
};
|
|
|
|
// These hooks are used to inform boost::beast::websocket::stream on
|
|
// how to tear down the connection as part of the WebSocket
|
|
// protocol specifications
|
|
|
|
template<class SyncStream>
|
|
inline
|
|
void
|
|
teardown(
|
|
boost::beast::websocket::role_type role,
|
|
ssl_stream<SyncStream>& stream,
|
|
boost::system::error_code& ec)
|
|
{
|
|
// Just forward it to the wrapped stream
|
|
using boost::beast::websocket::teardown;
|
|
teardown(role, *stream.p_, ec);
|
|
}
|
|
|
|
template<class AsyncStream, class TeardownHandler>
|
|
inline
|
|
void
|
|
async_teardown(
|
|
boost::beast::websocket::role_type role,
|
|
ssl_stream<AsyncStream>& stream,
|
|
TeardownHandler&& handler)
|
|
{
|
|
// Just forward it to the wrapped stream
|
|
using boost::beast::websocket::async_teardown;
|
|
async_teardown(role,
|
|
*stream.p_, std::forward<TeardownHandler>(handler));
|
|
}
|
|
|
|
#endif
|