|
||||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |