2 // Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_EXAMPLE_COMMON_SSL_STREAM_HPP
11 #define BOOST_BEAST_EXAMPLE_COMMON_SSL_STREAM_HPP
13 // This include is necessary to work with `ssl::stream` and `boost::beast::websocket::stream`
14 #include <boost/beast/websocket/ssl.hpp>
16 #include <boost/asio/ip/tcp.hpp>
17 #include <boost/asio/ssl/stream.hpp>
20 #include <type_traits>
23 /** C++11 enabled SSL socket wrapper
25 This wrapper provides an interface identical to `boost::asio::ssl::stream`,
26 with the following additional properties:
28 @li Satisfies @b MoveConstructible
30 @li Satisfies @b MoveAssignable
32 @li Constructible from a moved socket.
34 template<class NextLayer>
36 : public boost::asio::ssl::stream_base
38 // only works for boost::asio::ip::tcp::socket
39 // for now because of the move limitations
40 static_assert(std::is_same<NextLayer, boost::asio::ip::tcp::socket>::value,
41 "NextLayer requirements not met");
43 using stream_type = boost::asio::ssl::stream<NextLayer>;
45 std::unique_ptr<stream_type> p_;
46 boost::asio::ssl::context* ctx_;
49 /// The native handle type of the SSL stream.
50 using native_handle_type = typename stream_type::native_handle_type;
52 /// Structure for use with deprecated impl_type.
53 using impl_struct = typename stream_type::impl_struct;
55 /// The type of the next layer.
56 using next_layer_type = typename stream_type::next_layer_type;
58 /// The type of the lowest layer.
59 using lowest_layer_type = typename stream_type::lowest_layer_type;
61 /// The type of the executor associated with the object.
62 using executor_type = typename stream_type::executor_type;
65 boost::asio::ip::tcp::socket socket,
66 boost::asio::ssl::context& ctx)
68 socket.get_executor().context(), ctx})
71 p_->next_layer() = std::move(socket);
74 ssl_stream(ssl_stream&& other)
76 other.get_executor().context(), *other.ctx_))
83 ssl_stream& operator=(ssl_stream&& other)
85 std::unique_ptr<stream_type> p(new stream_type{
86 other.get_executor().context(), other.ctx_});
95 get_executor() noexcept
97 return p_->get_executor();
103 return p_->native_handle();
106 next_layer_type const&
109 return p_->next_layer();
115 return p_->next_layer();
121 return p_->lowest_layer();
124 lowest_layer_type const&
127 return p_->lowest_layer();
131 set_verify_mode(boost::asio::ssl::verify_mode v)
133 p_->set_verify_mode(v);
136 boost::system::error_code
137 set_verify_mode(boost::asio::ssl::verify_mode v,
138 boost::system::error_code& ec)
140 return p_->set_verify_mode(v, ec);
144 set_verify_depth(int depth)
146 p_->set_verify_depth(depth);
149 boost::system::error_code
151 int depth, boost::system::error_code& ec)
153 return p_->set_verify_depth(depth, ec);
156 template<class VerifyCallback>
158 set_verify_callback(VerifyCallback callback)
160 p_->set_verify_callback(callback);
163 template<class VerifyCallback>
164 boost::system::error_code
165 set_verify_callback(VerifyCallback callback,
166 boost::system::error_code& ec)
168 return p_->set_verify_callback(callback, ec);
172 handshake(handshake_type type)
177 boost::system::error_code
178 handshake(handshake_type type,
179 boost::system::error_code& ec)
181 return p_->handshake(type, ec);
184 template<class ConstBufferSequence>
187 handshake_type type, ConstBufferSequence const& buffers)
189 p_->handshake(type, buffers);
192 template<class ConstBufferSequence>
193 boost::system::error_code
194 handshake(handshake_type type,
195 ConstBufferSequence const& buffers,
196 boost::system::error_code& ec)
198 return p_->handshake(type, buffers, ec);
201 template<class HandshakeHandler>
202 BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
203 void(boost::system::error_code))
204 async_handshake(handshake_type type,
205 BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
207 return p_->async_handshake(type,
208 BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
211 template<class ConstBufferSequence, class BufferedHandshakeHandler>
212 BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
213 void (boost::system::error_code, std::size_t))
214 async_handshake(handshake_type type, ConstBufferSequence const& buffers,
215 BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
217 return p_->async_handshake(type, buffers,
218 BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
227 boost::system::error_code
228 shutdown(boost::system::error_code& ec)
230 return p_->shutdown(ec);
233 template<class ShutdownHandler>
234 BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
235 void (boost::system::error_code))
236 async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
238 return p_->async_shutdown(
239 BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
242 template<class ConstBufferSequence>
244 write_some(ConstBufferSequence const& buffers)
246 return p_->write_some(buffers);
249 template<class ConstBufferSequence>
251 write_some(ConstBufferSequence const& buffers,
252 boost::system::error_code& ec)
254 return p_->write_some(buffers, ec);
257 template<class ConstBufferSequence, class WriteHandler>
258 BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
259 void (boost::system::error_code, std::size_t))
260 async_write_some(ConstBufferSequence const& buffers,
261 BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
263 return p_->async_write_some(buffers,
264 BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
267 template<class MutableBufferSequence>
269 read_some(MutableBufferSequence const& buffers)
271 return p_->read_some(buffers);
274 template<class MutableBufferSequence>
276 read_some(MutableBufferSequence const& buffers,
277 boost::system::error_code& ec)
279 return p_->read_some(buffers, ec);
282 template<class MutableBufferSequence, class ReadHandler>
283 BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
284 void(boost::system::error_code, std::size_t))
285 async_read_some(MutableBufferSequence const& buffers,
286 BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
288 return p_->async_read_some(buffers,
289 BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
292 template<class SyncStream>
295 teardown(boost::beast::websocket::role_type,
296 ssl_stream<SyncStream>& stream,
297 boost::system::error_code& ec);
299 template<class AsyncStream, class TeardownHandler>
302 async_teardown(boost::beast::websocket::role_type,
303 ssl_stream<AsyncStream>& stream, TeardownHandler&& handler);
306 // These hooks are used to inform boost::beast::websocket::stream on
307 // how to tear down the connection as part of the WebSocket
308 // protocol specifications
310 template<class SyncStream>
314 boost::beast::websocket::role_type role,
315 ssl_stream<SyncStream>& stream,
316 boost::system::error_code& ec)
318 // Just forward it to the wrapped ssl::stream
319 using boost::beast::websocket::teardown;
320 teardown(role, *stream.p_, ec);
323 template<class AsyncStream, class TeardownHandler>
327 boost::beast::websocket::role_type role,
328 ssl_stream<AsyncStream>& stream,
329 TeardownHandler&& handler)
331 // Just forward it to the wrapped ssl::stream
332 using boost::beast::websocket::async_teardown;
334 *stream.p_, std::forward<TeardownHandler>(handler));