Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:32

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_SSL_STREAM_HPP
0011 #define BOOST_BEAST_CORE_SSL_STREAM_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 
0015 // This include is necessary to work with `ssl::stream` and `boost::beast::websocket::stream`
0016 #include <boost/beast/websocket/ssl.hpp>
0017 
0018 #include <boost/beast/core/flat_stream.hpp>
0019 
0020 // VFALCO We include this because anyone who uses ssl will
0021 //        very likely need to check for ssl::error::stream_truncated
0022 #include <boost/asio/ssl/error.hpp>
0023 
0024 #include <boost/asio/ssl/stream.hpp>
0025 #include <cstddef>
0026 #include <memory>
0027 #include <type_traits>
0028 #include <utility>
0029 
0030 namespace boost {
0031 namespace beast {
0032 
0033 /** Provides stream-oriented functionality using OpenSSL
0034 
0035     The stream class template provides asynchronous and blocking
0036     stream-oriented functionality using SSL.
0037 
0038     @par Thread Safety
0039     @e Distinct @e objects: Safe.@n
0040     @e Shared @e objects: Unsafe. The application must also ensure that all
0041     asynchronous operations are performed within the same implicit or explicit
0042     strand.
0043 
0044     @par Example
0045     To use this template with a @ref tcp_stream, you would write:
0046     @code
0047         net::io_context ioc;
0048         net::ssl::context ctx{net::ssl::context::tlsv12};
0049         beast::ssl_stream<beast::tcp_stream> sock{ioc, ctx};
0050     @endcode
0051 
0052     In addition to providing an interface identical to `net::ssl::stream`,
0053     the wrapper has the following additional properties:
0054 
0055     @li Satisfies @b MoveConstructible
0056 
0057     @li Satisfies @b MoveAssignable
0058 
0059     @li Constructible from a moved socket.
0060 
0061     @li Uses @ref flat_stream internally, as a performance work-around for a
0062         limitation of `net::ssl::stream` when writing buffer sequences
0063         having length greater than one.
0064 
0065     @par Concepts:
0066         @li AsyncReadStream
0067         @li AsyncWriteStream
0068         @li Stream
0069         @li SyncReadStream
0070         @li SyncWriteStream
0071 */
0072 template<class NextLayer>
0073 class ssl_stream
0074     : public net::ssl::stream_base
0075 {
0076     using ssl_stream_type = net::ssl::stream<NextLayer>;
0077     using stream_type = boost::beast::flat_stream<ssl_stream_type>;
0078 
0079     std::unique_ptr<stream_type> p_;
0080 
0081 public:
0082     /// The native handle type of the SSL stream.
0083     using native_handle_type =
0084         typename ssl_stream_type::native_handle_type;
0085 
0086     /// Structure for use with deprecated impl_type.
0087     using impl_struct = typename ssl_stream_type::impl_struct;
0088 
0089     /// The type of the next layer.
0090     using next_layer_type = typename ssl_stream_type::next_layer_type;
0091 
0092     /// The type of the executor associated with the object.
0093     using executor_type = typename stream_type::executor_type;
0094 
0095     /// Rebinds the stream type to another executor.
0096     template<class Executor1>
0097     struct rebind_executor
0098     {
0099         /// The stream type when rebound to the specified executor.
0100         using other = ssl_stream<
0101                 typename stream_type::template rebind_executor<Executor1>::other
0102                 >;
0103     };
0104 
0105 
0106     /** Construct a stream.
0107 
0108         This constructor creates a stream and initialises the underlying stream
0109         object.
0110 
0111         @param arg The argument to be passed to initialise the underlying stream.
0112 
0113         @param ctx The SSL context to be used for the stream.
0114     */
0115     template<class Arg>
0116     ssl_stream(
0117         Arg&& arg,
0118         net::ssl::context& ctx)
0119         : p_(new stream_type{
0120             std::forward<Arg>(arg), ctx})
0121     {
0122     }
0123 
0124     /** Get the executor associated with the object.
0125 
0126         This function may be used to obtain the executor object that the stream
0127         uses to dispatch handlers for asynchronous operations.
0128 
0129         @return A copy of the executor that stream will use to dispatch handlers.
0130     */
0131     executor_type
0132     get_executor() noexcept
0133     {
0134         return p_->get_executor();
0135     }
0136 
0137     /** Get the underlying implementation in the native type.
0138 
0139         This function may be used to obtain the underlying implementation of the
0140         context. This is intended to allow access to context functionality that is
0141         not otherwise provided.
0142 
0143         @par Example
0144         The native_handle() function returns a pointer of type @c SSL* that is
0145         suitable for passing to functions such as @c SSL_get_verify_result and
0146         @c SSL_get_peer_certificate:
0147         @code
0148         boost::beast::ssl_stream<net::ip::tcp::socket> ss{ioc, ctx};
0149 
0150         // ... establish connection and perform handshake ...
0151 
0152         if (X509* cert = SSL_get_peer_certificate(ss.native_handle()))
0153         {
0154           if (SSL_get_verify_result(ss.native_handle()) == X509_V_OK)
0155           {
0156             // ...
0157           }
0158         }
0159         @endcode
0160     */
0161     native_handle_type
0162     native_handle() noexcept
0163     {
0164         return p_->next_layer().native_handle();
0165     }
0166 
0167     /** Get a reference to the next layer.
0168 
0169         This function returns a reference to the next layer in a stack of stream
0170         layers.
0171 
0172         @note The next layer is the wrapped stream and not the @ref flat_stream
0173         used in the implementation.
0174 
0175         @return A reference to the next layer in the stack of stream layers.
0176         Ownership is not transferred to the caller.
0177     */
0178     next_layer_type const&
0179     next_layer() const noexcept
0180     {
0181         return p_->next_layer().next_layer();
0182     }
0183 
0184     /** Get a reference to the next layer.
0185 
0186         This function returns a reference to the next layer in a stack of stream
0187         layers.
0188 
0189         @note The next layer is the wrapped stream and not the @ref flat_stream
0190         used in the implementation.
0191 
0192         @return A reference to the next layer in the stack of stream layers.
0193         Ownership is not transferred to the caller.
0194     */
0195     next_layer_type&
0196     next_layer() noexcept
0197     {
0198         return p_->next_layer().next_layer();
0199     }
0200 
0201     /** Set the peer verification mode.
0202 
0203         This function may be used to configure the peer verification mode used by
0204         the stream. The new mode will override the mode inherited from the context.
0205 
0206         @param v A bitmask of peer verification modes.
0207 
0208         @throws boost::system::system_error Thrown on failure.
0209 
0210         @note Calls @c SSL_set_verify.
0211     */
0212     void
0213     set_verify_mode(net::ssl::verify_mode v)
0214     {
0215         p_->next_layer().set_verify_mode(v);
0216     }
0217 
0218     /** Set the peer verification mode.
0219 
0220         This function may be used to configure the peer verification mode used by
0221         the stream. The new mode will override the mode inherited from the context.
0222 
0223         @param v A bitmask of peer verification modes. See `verify_mode` for
0224         available values.
0225 
0226         @param ec Set to indicate what error occurred, if any.
0227 
0228         @note Calls @c SSL_set_verify.
0229     */
0230     void
0231     set_verify_mode(net::ssl::verify_mode v,
0232         boost::system::error_code& ec)
0233     {
0234         p_->next_layer().set_verify_mode(v, ec);
0235     }
0236 
0237     /** Set the peer verification depth.
0238 
0239         This function may be used to configure the maximum verification depth
0240         allowed by the stream.
0241 
0242         @param depth Maximum depth for the certificate chain verification that
0243         shall be allowed.
0244 
0245         @throws boost::system::system_error Thrown on failure.
0246 
0247         @note Calls @c SSL_set_verify_depth.
0248     */
0249     void
0250     set_verify_depth(int depth)
0251     {
0252         p_->next_layer().set_verify_depth(depth);
0253     }
0254 
0255     /** Set the peer verification depth.
0256 
0257         This function may be used to configure the maximum verification depth
0258         allowed by the stream.
0259 
0260         @param depth Maximum depth for the certificate chain verification that
0261         shall be allowed.
0262 
0263         @param ec Set to indicate what error occurred, if any.
0264 
0265         @note Calls @c SSL_set_verify_depth.
0266     */
0267     void
0268     set_verify_depth(
0269         int depth, boost::system::error_code& ec)
0270     {
0271         p_->next_layer().set_verify_depth(depth, ec);
0272     }
0273 
0274     /** Set the callback used to verify peer certificates.
0275 
0276         This function is used to specify a callback function that will be called
0277         by the implementation when it needs to verify a peer certificate.
0278 
0279         @param callback The function object to be used for verifying a certificate.
0280         The function signature of the handler must be:
0281         @code bool verify_callback(
0282           bool preverified, // True if the certificate passed pre-verification.
0283           verify_context& ctx // The peer certificate and other context.
0284         ); @endcode
0285         The return value of the callback is true if the certificate has passed
0286         verification, false otherwise.
0287 
0288         @throws boost::system::system_error Thrown on failure.
0289 
0290         @note Calls @c SSL_set_verify.
0291     */
0292     template<class VerifyCallback>
0293     void
0294     set_verify_callback(VerifyCallback callback)
0295     {
0296         p_->next_layer().set_verify_callback(callback);
0297     }
0298 
0299     /** Set the callback used to verify peer certificates.
0300 
0301         This function is used to specify a callback function that will be called
0302         by the implementation when it needs to verify a peer certificate.
0303 
0304         @param callback The function object to be used for verifying a certificate.
0305         The function signature of the handler must be:
0306         @code bool verify_callback(
0307           bool preverified, // True if the certificate passed pre-verification.
0308           net::verify_context& ctx // The peer certificate and other context.
0309         ); @endcode
0310         The return value of the callback is true if the certificate has passed
0311         verification, false otherwise.
0312 
0313         @param ec Set to indicate what error occurred, if any.
0314 
0315         @note Calls @c SSL_set_verify.
0316     */
0317     template<class VerifyCallback>
0318     void
0319     set_verify_callback(VerifyCallback callback,
0320         boost::system::error_code& ec)
0321     {
0322         p_->next_layer().set_verify_callback(callback, ec);
0323     }
0324 
0325     /** Perform SSL handshaking.
0326 
0327         This function is used to perform SSL handshaking on the stream. The
0328         function call will block until handshaking is complete or an error occurs.
0329 
0330         @param type The type of handshaking to be performed, i.e. as a client or as
0331         a server.
0332 
0333         @throws boost::system::system_error Thrown on failure.
0334     */
0335     void
0336     handshake(handshake_type type)
0337     {
0338         p_->next_layer().handshake(type);
0339     }
0340 
0341     /** Perform SSL handshaking.
0342 
0343         This function is used to perform SSL handshaking on the stream. The
0344         function call will block until handshaking is complete or an error occurs.
0345 
0346         @param type The type of handshaking to be performed, i.e. as a client or as
0347         a server.
0348 
0349         @param ec Set to indicate what error occurred, if any.
0350     */
0351     void
0352     handshake(handshake_type type,
0353         boost::system::error_code& ec)
0354     {
0355         p_->next_layer().handshake(type, ec);
0356     }
0357 
0358     /** Perform SSL handshaking.
0359 
0360         This function is used to perform SSL handshaking on the stream. The
0361         function call will block until handshaking is complete or an error occurs.
0362 
0363         @param type The type of handshaking to be performed, i.e. as a client or as
0364         a server.
0365 
0366         @param buffers The buffered data to be reused for the handshake.
0367 
0368         @throws boost::system::system_error Thrown on failure.
0369     */
0370     template<class ConstBufferSequence>
0371     void
0372     handshake(
0373         handshake_type type, ConstBufferSequence const& buffers)
0374     {
0375         p_->next_layer().handshake(type, buffers);
0376     }
0377 
0378     /** Perform SSL handshaking.
0379 
0380         This function is used to perform SSL handshaking on the stream. The
0381         function call will block until handshaking is complete or an error occurs.
0382 
0383         @param type The type of handshaking to be performed, i.e. as a client or as
0384         a server.
0385 
0386         @param buffers The buffered data to be reused for the handshake.
0387 
0388         @param ec Set to indicate what error occurred, if any.
0389     */
0390     template<class ConstBufferSequence>
0391     void
0392     handshake(handshake_type type,
0393         ConstBufferSequence const& buffers,
0394             boost::system::error_code& ec)
0395     {
0396         p_->next_layer().handshake(type, buffers, ec);
0397     }
0398 
0399     /** Start an asynchronous SSL handshake.
0400 
0401         This function is used to asynchronously perform an SSL handshake on the
0402         stream. This function call always returns immediately.
0403 
0404         @param type The type of handshaking to be performed, i.e. as a client or as
0405         a server.
0406 
0407         @param handler The handler to be called when the handshake operation
0408         completes. Copies will be made of the handler as required. The equivalent
0409         function signature of the handler must be:
0410         @code void handler(
0411           const boost::system::error_code& error // Result of operation.
0412         ); @endcode
0413     */
0414     template<BOOST_BEAST_ASYNC_TPARAM1 HandshakeHandler = net::default_completion_token_t<executor_type>>
0415     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code))
0416     async_handshake(handshake_type type,
0417         BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler = net::default_completion_token_t<executor_type>{})
0418     {
0419         return p_->next_layer().async_handshake(type,
0420             BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
0421     }
0422 
0423     /** Start an asynchronous SSL handshake.
0424 
0425         This function is used to asynchronously perform an SSL handshake on the
0426         stream. This function call always returns immediately.
0427 
0428         @param type The type of handshaking to be performed, i.e. as a client or as
0429         a server.
0430 
0431         @param buffers The buffered data to be reused for the handshake. Although
0432         the buffers object may be copied as necessary, ownership of the underlying
0433         buffers is retained by the caller, which must guarantee that they remain
0434         valid until the handler is called.
0435 
0436         @param handler The handler to be called when the handshake operation
0437         completes. Copies will be made of the handler as required. The equivalent
0438         function signature of the handler must be:
0439         @code void handler(
0440           const boost::system::error_code& error, // Result of operation.
0441           std::size_t bytes_transferred // Amount of buffers used in handshake.
0442         ); @endcode
0443     */
0444     template<class ConstBufferSequence,
0445              BOOST_BEAST_ASYNC_TPARAM2 BufferedHandshakeHandler = net::default_completion_token_t<executor_type>>
0446     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler, void(boost::system::error_code, std::size_t))
0447     async_handshake(handshake_type type, ConstBufferSequence const& buffers,
0448         BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler
0449             = net::default_completion_token_t<executor_type>{})
0450     {
0451         return p_->next_layer().async_handshake(type, buffers,
0452             BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
0453     }
0454 
0455     /** Shut down SSL on the stream.
0456 
0457         This function is used to shut down SSL on the stream. The function call
0458         will block until SSL has been shut down or an error occurs.
0459 
0460         @throws boost::system::system_error Thrown on failure.
0461     */
0462     void
0463     shutdown()
0464     {
0465         p_->next_layer().shutdown();
0466     }
0467 
0468     /** Shut down SSL on the stream.
0469 
0470         This function is used to shut down SSL on the stream. The function call
0471         will block until SSL has been shut down or an error occurs.
0472 
0473         @param ec Set to indicate what error occurred, if any.
0474     */
0475     void
0476     shutdown(boost::system::error_code& ec)
0477     {
0478         p_->next_layer().shutdown(ec);
0479     }
0480 
0481     /** Asynchronously shut down SSL on the stream.
0482 
0483         This function is used to asynchronously shut down SSL on the stream. This
0484         function call always returns immediately.
0485 
0486         @param handler The handler to be called when the handshake operation
0487         completes. Copies will be made of the handler as required. The equivalent
0488         function signature of the handler must be:
0489         @code void handler(
0490           const boost::system::error_code& error // Result of operation.
0491         ); @endcode
0492     */
0493     template<BOOST_BEAST_ASYNC_TPARAM1 ShutdownHandler = net::default_completion_token_t<executor_type>>
0494     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler, void(boost::system::error_code))
0495     async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler = net::default_completion_token_t<executor_type>{})
0496     {
0497         return p_->next_layer().async_shutdown(
0498             BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
0499     }
0500 
0501     /** Write some data to the stream.
0502 
0503         This function is used to write data on the stream. The function call will
0504         block until one or more bytes of data has been written successfully, or
0505         until an error occurs.
0506 
0507         @param buffers The data to be written.
0508 
0509         @returns The number of bytes written.
0510 
0511         @throws boost::system::system_error Thrown on failure.
0512 
0513         @note The `write_some` operation may not transmit all of the data to the
0514         peer. Consider using the `net::write` function if you need to
0515         ensure that all data is written before the blocking operation completes.
0516     */
0517     template<class ConstBufferSequence>
0518     std::size_t
0519     write_some(ConstBufferSequence const& buffers)
0520     {
0521         return p_->write_some(buffers);
0522     }
0523 
0524     /** Write some data to the stream.
0525 
0526         This function is used to write data on the stream. The function call will
0527         block until one or more bytes of data has been written successfully, or
0528         until an error occurs.
0529 
0530         @param buffers The data to be written to the stream.
0531 
0532         @param ec Set to indicate what error occurred, if any.
0533 
0534         @returns The number of bytes written. Returns 0 if an error occurred.
0535 
0536         @note The `write_some` operation may not transmit all of the data to the
0537         peer. Consider using the `net::write` function if you need to
0538         ensure that all data is written before the blocking operation completes.
0539     */
0540     template<class ConstBufferSequence>
0541     std::size_t
0542     write_some(ConstBufferSequence const& buffers,
0543         boost::system::error_code& ec)
0544     {
0545         return p_->write_some(buffers, ec);
0546     }
0547 
0548     /** Start an asynchronous write.
0549 
0550         This function is used to asynchronously write one or more bytes of data to
0551         the stream. The function call always returns immediately.
0552 
0553         @param buffers The data to be written to the stream. Although the buffers
0554         object may be copied as necessary, ownership of the underlying buffers is
0555         retained by the caller, which must guarantee that they remain valid until
0556         the handler is called.
0557 
0558         @param handler The handler to be called when the write operation completes.
0559         Copies will be made of the handler as required. The equivalent function
0560         signature of the handler must be:
0561         @code void handler(
0562           const boost::system::error_code& error, // Result of operation.
0563           std::size_t bytes_transferred           // Number of bytes written.
0564         ); @endcode
0565 
0566         @note The `async_write_some` operation may not transmit all of the data to
0567         the peer. Consider using the `net::async_write` function if you
0568         need to ensure that all data is written before the asynchronous operation
0569         completes.
0570     */
0571     template<class ConstBufferSequence,
0572              BOOST_BEAST_ASYNC_TPARAM2 WriteHandler = net::default_completion_token_t<executor_type>>
0573     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, void(boost::system::error_code, std::size_t))
0574     async_write_some(ConstBufferSequence const& buffers,
0575         BOOST_ASIO_MOVE_ARG(WriteHandler) handler= net::default_completion_token_t<executor_type>{})
0576     {
0577         return p_->async_write_some(buffers,
0578             BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
0579     }
0580 
0581     /** Read some data from the stream.
0582 
0583         This function is used to read data from the stream. The function call will
0584         block until one or more bytes of data has been read successfully, or until
0585         an error occurs.
0586 
0587         @param buffers The buffers into which the data will be read.
0588 
0589         @returns The number of bytes read.
0590 
0591         @throws boost::system::system_error Thrown on failure.
0592 
0593         @note The `read_some` operation may not read all of the requested number of
0594         bytes. Consider using the `net::read` function if you need to ensure
0595         that the requested amount of data is read before the blocking operation
0596         completes.
0597     */
0598     template<class MutableBufferSequence>
0599     std::size_t
0600     read_some(MutableBufferSequence const& buffers)
0601     {
0602         return p_->read_some(buffers);
0603     }
0604 
0605     /** Read some data from the stream.
0606 
0607         This function is used to read data from the stream. The function call will
0608         block until one or more bytes of data has been read successfully, or until
0609         an error occurs.
0610 
0611         @param buffers The buffers into which the data will be read.
0612 
0613         @param ec Set to indicate what error occurred, if any.
0614 
0615         @returns The number of bytes read. Returns 0 if an error occurred.
0616 
0617         @note The `read_some` operation may not read all of the requested number of
0618         bytes. Consider using the `net::read` function if you need to ensure
0619         that the requested amount of data is read before the blocking operation
0620         completes.
0621     */
0622     template<class MutableBufferSequence>
0623     std::size_t
0624     read_some(MutableBufferSequence const& buffers,
0625         boost::system::error_code& ec)
0626     {
0627         return p_->read_some(buffers, ec);
0628     }
0629 
0630     /** Start an asynchronous read.
0631 
0632         This function is used to asynchronously read one or more bytes of data from
0633         the stream. The function call always returns immediately.
0634 
0635         @param buffers The buffers into which the data will be read. Although the
0636         buffers object may be copied as necessary, ownership of the underlying
0637         buffers is retained by the caller, which must guarantee that they remain
0638         valid until the handler is called.
0639 
0640         @param handler The handler to be called when the read operation completes.
0641         Copies will be made of the handler as required. The equivalent function
0642         signature of the handler must be:
0643         @code void handler(
0644           const boost::system::error_code& error, // Result of operation.
0645           std::size_t bytes_transferred           // Number of bytes read.
0646         ); @endcode
0647 
0648         @note The `async_read_some` operation may not read all of the requested
0649         number of bytes. Consider using the `net::async_read` function
0650         if you need to ensure that the requested amount of data is read before
0651         the asynchronous operation completes.
0652     */
0653     template<class MutableBufferSequence,
0654              BOOST_BEAST_ASYNC_TPARAM2 ReadHandler = net::default_completion_token_t<executor_type>>
0655     BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, void(boost::system::error_code, std::size_t))
0656     async_read_some(MutableBufferSequence const& buffers,
0657         BOOST_ASIO_MOVE_ARG(ReadHandler) handler
0658             = net::default_completion_token_t<executor_type>{})
0659     {
0660         return p_->async_read_some(buffers,
0661             BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
0662     }
0663 
0664     // These hooks are used to inform boost::beast::websocket::stream on
0665     // how to tear down the connection as part of the WebSocket
0666     // protocol specifications
0667     #if ! BOOST_BEAST_DOXYGEN
0668     template<class SyncStream>
0669     friend
0670     void
0671     teardown(
0672         boost::beast::role_type role,
0673         ssl_stream<SyncStream>& stream,
0674         boost::system::error_code& ec);
0675 
0676     template<class AsyncStream, typename TeardownHandler>
0677     friend
0678     void
0679     async_teardown(
0680         boost::beast::role_type role,
0681         ssl_stream<AsyncStream>& stream,
0682         TeardownHandler&& handler);
0683     #endif
0684 };
0685 
0686 #if ! BOOST_BEAST_DOXYGEN
0687 template<class SyncStream>
0688 void
0689 teardown(
0690     boost::beast::role_type role,
0691     ssl_stream<SyncStream>& stream,
0692     boost::system::error_code& ec)
0693 {
0694     // Just forward it to the underlying ssl::stream
0695     using boost::beast::websocket::teardown;
0696     teardown(role, *stream.p_, ec);
0697 }
0698 
0699 template<class AsyncStream,
0700         typename TeardownHandler = net::default_completion_token_t<beast::executor_type<AsyncStream>>>
0701 void
0702 async_teardown(
0703     boost::beast::role_type role,
0704     ssl_stream<AsyncStream>& stream,
0705     TeardownHandler&& handler = net::default_completion_token_t<beast::executor_type<AsyncStream>>{})
0706 {
0707     // Just forward it to the underlying ssl::stream
0708     using boost::beast::websocket::async_teardown;
0709     async_teardown(role, *stream.p_,
0710         std::forward<TeardownHandler>(handler));
0711 }
0712 #endif
0713 
0714 } // beast
0715 } // boost
0716 
0717 #endif