stream.hpp 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045
  1. //
  2. // ssl/stream.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_SSL_STREAM_HPP
  11. #define BOOST_ASIO_SSL_STREAM_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/async_result.hpp>
  17. #include <boost/asio/buffer.hpp>
  18. #include <boost/asio/detail/buffer_sequence_adapter.hpp>
  19. #include <boost/asio/detail/handler_type_requirements.hpp>
  20. #include <boost/asio/detail/non_const_lvalue.hpp>
  21. #include <boost/asio/detail/noncopyable.hpp>
  22. #include <boost/asio/detail/type_traits.hpp>
  23. #include <boost/asio/ssl/context.hpp>
  24. #include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
  25. #include <boost/asio/ssl/detail/handshake_op.hpp>
  26. #include <boost/asio/ssl/detail/io.hpp>
  27. #include <boost/asio/ssl/detail/read_op.hpp>
  28. #include <boost/asio/ssl/detail/shutdown_op.hpp>
  29. #include <boost/asio/ssl/detail/stream_core.hpp>
  30. #include <boost/asio/ssl/detail/write_op.hpp>
  31. #include <boost/asio/ssl/stream_base.hpp>
  32. #include <boost/asio/detail/push_options.hpp>
  33. namespace boost {
  34. namespace asio {
  35. namespace ssl {
  36. /// Provides stream-oriented functionality using SSL.
  37. /**
  38. * The stream class template provides asynchronous and blocking stream-oriented
  39. * functionality using SSL.
  40. *
  41. * @par Thread Safety
  42. * @e Distinct @e objects: Safe.@n
  43. * @e Shared @e objects: Unsafe. The application must also ensure that all
  44. * asynchronous operations are performed within the same implicit or explicit
  45. * strand.
  46. *
  47. * @par Example
  48. * To use the SSL stream template with an ip::tcp::socket, you would write:
  49. * @code
  50. * boost::asio::io_context my_context;
  51. * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
  52. * boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock(my_context, ctx);
  53. * @endcode
  54. *
  55. * @par Concepts:
  56. * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
  57. */
  58. template <typename Stream>
  59. class stream :
  60. public stream_base,
  61. private noncopyable
  62. {
  63. private:
  64. class initiate_async_handshake;
  65. class initiate_async_buffered_handshake;
  66. class initiate_async_shutdown;
  67. class initiate_async_write_some;
  68. class initiate_async_read_some;
  69. public:
  70. /// The native handle type of the SSL stream.
  71. typedef SSL* native_handle_type;
  72. /// Structure for use with deprecated impl_type.
  73. struct impl_struct
  74. {
  75. SSL* ssl;
  76. };
  77. /// The type of the next layer.
  78. typedef remove_reference_t<Stream> next_layer_type;
  79. /// The type of the lowest layer.
  80. typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
  81. /// The type of the executor associated with the object.
  82. typedef typename lowest_layer_type::executor_type executor_type;
  83. /// Construct a stream.
  84. /**
  85. * This constructor creates a stream and initialises the underlying stream
  86. * object.
  87. *
  88. * @param arg The argument to be passed to initialise the underlying stream.
  89. *
  90. * @param ctx The SSL context to be used for the stream.
  91. */
  92. template <typename Arg>
  93. stream(Arg&& arg, context& ctx)
  94. : next_layer_(static_cast<Arg&&>(arg)),
  95. core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())
  96. {
  97. }
  98. /// Construct a stream from an existing native implementation.
  99. /**
  100. * This constructor creates a stream and initialises the underlying stream
  101. * object. On success, ownership of the native implementation is transferred
  102. * to the stream, and it will be cleaned up when the stream is destroyed.
  103. *
  104. * @param arg The argument to be passed to initialise the underlying stream.
  105. *
  106. * @param handle An existing native SSL implementation.
  107. */
  108. template <typename Arg>
  109. stream(Arg&& arg, native_handle_type handle)
  110. : next_layer_(static_cast<Arg&&>(arg)),
  111. core_(handle, next_layer_.lowest_layer().get_executor())
  112. {
  113. }
  114. /// Move-construct a stream from another.
  115. /**
  116. * @param other The other stream object from which the move will occur. Must
  117. * have no outstanding asynchronous operations associated with it. Following
  118. * the move, @c other has a valid but unspecified state where the only safe
  119. * operation is destruction, or use as the target of a move assignment.
  120. */
  121. stream(stream&& other)
  122. : next_layer_(static_cast<Stream&&>(other.next_layer_)),
  123. core_(static_cast<detail::stream_core&&>(other.core_))
  124. {
  125. }
  126. /// Move-assign a stream from another.
  127. /**
  128. * @param other The other stream object from which the move will occur. Must
  129. * have no outstanding asynchronous operations associated with it. Following
  130. * the move, @c other has a valid but unspecified state where the only safe
  131. * operation is destruction, or use as the target of a move assignment.
  132. */
  133. stream& operator=(stream&& other)
  134. {
  135. if (this != &other)
  136. {
  137. next_layer_ = static_cast<Stream&&>(other.next_layer_);
  138. core_ = static_cast<detail::stream_core&&>(other.core_);
  139. }
  140. return *this;
  141. }
  142. /// Destructor.
  143. /**
  144. * @note A @c stream object must not be destroyed while there are pending
  145. * asynchronous operations associated with it.
  146. */
  147. ~stream()
  148. {
  149. }
  150. /// Get the executor associated with the object.
  151. /**
  152. * This function may be used to obtain the executor object that the stream
  153. * uses to dispatch handlers for asynchronous operations.
  154. *
  155. * @return A copy of the executor that stream will use to dispatch handlers.
  156. */
  157. executor_type get_executor() noexcept
  158. {
  159. return next_layer_.lowest_layer().get_executor();
  160. }
  161. /// Get the underlying implementation in the native type.
  162. /**
  163. * This function may be used to obtain the underlying implementation of the
  164. * context. This is intended to allow access to context functionality that is
  165. * not otherwise provided.
  166. *
  167. * @par Example
  168. * The native_handle() function returns a pointer of type @c SSL* that is
  169. * suitable for passing to functions such as @c SSL_get_verify_result and
  170. * @c SSL_get_peer_certificate:
  171. * @code
  172. * boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock(io_ctx, ctx);
  173. *
  174. * // ... establish connection and perform handshake ...
  175. *
  176. * if (X509* cert = SSL_get_peer_certificate(sock.native_handle()))
  177. * {
  178. * if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK)
  179. * {
  180. * // ...
  181. * }
  182. * }
  183. * @endcode
  184. */
  185. native_handle_type native_handle()
  186. {
  187. return core_.engine_.native_handle();
  188. }
  189. /// Get a reference to the next layer.
  190. /**
  191. * This function returns a reference to the next layer in a stack of stream
  192. * layers.
  193. *
  194. * @return A reference to the next layer in the stack of stream layers.
  195. * Ownership is not transferred to the caller.
  196. */
  197. const next_layer_type& next_layer() const
  198. {
  199. return next_layer_;
  200. }
  201. /// Get a reference to the next layer.
  202. /**
  203. * This function returns a reference to the next layer in a stack of stream
  204. * layers.
  205. *
  206. * @return A reference to the next layer in the stack of stream layers.
  207. * Ownership is not transferred to the caller.
  208. */
  209. next_layer_type& next_layer()
  210. {
  211. return next_layer_;
  212. }
  213. /// Get a reference to the lowest layer.
  214. /**
  215. * This function returns a reference to the lowest layer in a stack of
  216. * stream layers.
  217. *
  218. * @return A reference to the lowest layer in the stack of stream layers.
  219. * Ownership is not transferred to the caller.
  220. */
  221. lowest_layer_type& lowest_layer()
  222. {
  223. return next_layer_.lowest_layer();
  224. }
  225. /// Get a reference to the lowest layer.
  226. /**
  227. * This function returns a reference to the lowest layer in a stack of
  228. * stream layers.
  229. *
  230. * @return A reference to the lowest layer in the stack of stream layers.
  231. * Ownership is not transferred to the caller.
  232. */
  233. const lowest_layer_type& lowest_layer() const
  234. {
  235. return next_layer_.lowest_layer();
  236. }
  237. /// Set the peer verification mode.
  238. /**
  239. * This function may be used to configure the peer verification mode used by
  240. * the stream. The new mode will override the mode inherited from the context.
  241. *
  242. * @param v A bitmask of peer verification modes. See @ref verify_mode for
  243. * available values.
  244. *
  245. * @throws boost::system::system_error Thrown on failure.
  246. *
  247. * @note Calls @c SSL_set_verify.
  248. */
  249. void set_verify_mode(verify_mode v)
  250. {
  251. boost::system::error_code ec;
  252. set_verify_mode(v, ec);
  253. boost::asio::detail::throw_error(ec, "set_verify_mode");
  254. }
  255. /// Set the peer verification mode.
  256. /**
  257. * This function may be used to configure the peer verification mode used by
  258. * the stream. The new mode will override the mode inherited from the context.
  259. *
  260. * @param v A bitmask of peer verification modes. See @ref verify_mode for
  261. * available values.
  262. *
  263. * @param ec Set to indicate what error occurred, if any.
  264. *
  265. * @note Calls @c SSL_set_verify.
  266. */
  267. BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
  268. verify_mode v, boost::system::error_code& ec)
  269. {
  270. core_.engine_.set_verify_mode(v, ec);
  271. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  272. }
  273. /// Set the peer verification depth.
  274. /**
  275. * This function may be used to configure the maximum verification depth
  276. * allowed by the stream.
  277. *
  278. * @param depth Maximum depth for the certificate chain verification that
  279. * shall be allowed.
  280. *
  281. * @throws boost::system::system_error Thrown on failure.
  282. *
  283. * @note Calls @c SSL_set_verify_depth.
  284. */
  285. void set_verify_depth(int depth)
  286. {
  287. boost::system::error_code ec;
  288. set_verify_depth(depth, ec);
  289. boost::asio::detail::throw_error(ec, "set_verify_depth");
  290. }
  291. /// Set the peer verification depth.
  292. /**
  293. * This function may be used to configure the maximum verification depth
  294. * allowed by the stream.
  295. *
  296. * @param depth Maximum depth for the certificate chain verification that
  297. * shall be allowed.
  298. *
  299. * @param ec Set to indicate what error occurred, if any.
  300. *
  301. * @note Calls @c SSL_set_verify_depth.
  302. */
  303. BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
  304. int depth, boost::system::error_code& ec)
  305. {
  306. core_.engine_.set_verify_depth(depth, ec);
  307. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  308. }
  309. /// Set the callback used to verify peer certificates.
  310. /**
  311. * This function is used to specify a callback function that will be called
  312. * by the implementation when it needs to verify a peer certificate.
  313. *
  314. * @param callback The function object to be used for verifying a certificate.
  315. * The function signature of the handler must be:
  316. * @code bool verify_callback(
  317. * bool preverified, // True if the certificate passed pre-verification.
  318. * verify_context& ctx // The peer certificate and other context.
  319. * ); @endcode
  320. * The return value of the callback is true if the certificate has passed
  321. * verification, false otherwise.
  322. *
  323. * @throws boost::system::system_error Thrown on failure.
  324. *
  325. * @note Calls @c SSL_set_verify.
  326. */
  327. template <typename VerifyCallback>
  328. void set_verify_callback(VerifyCallback callback)
  329. {
  330. boost::system::error_code ec;
  331. this->set_verify_callback(callback, ec);
  332. boost::asio::detail::throw_error(ec, "set_verify_callback");
  333. }
  334. /// Set the callback used to verify peer certificates.
  335. /**
  336. * This function is used to specify a callback function that will be called
  337. * by the implementation when it needs to verify a peer certificate.
  338. *
  339. * @param callback The function object to be used for verifying a certificate.
  340. * The function signature of the handler must be:
  341. * @code bool verify_callback(
  342. * bool preverified, // True if the certificate passed pre-verification.
  343. * verify_context& ctx // The peer certificate and other context.
  344. * ); @endcode
  345. * The return value of the callback is true if the certificate has passed
  346. * verification, false otherwise.
  347. *
  348. * @param ec Set to indicate what error occurred, if any.
  349. *
  350. * @note Calls @c SSL_set_verify.
  351. */
  352. template <typename VerifyCallback>
  353. BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
  354. boost::system::error_code& ec)
  355. {
  356. core_.engine_.set_verify_callback(
  357. new detail::verify_callback<VerifyCallback>(callback), ec);
  358. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  359. }
  360. /// Perform SSL handshaking.
  361. /**
  362. * This function is used to perform SSL handshaking on the stream. The
  363. * function call will block until handshaking is complete or an error occurs.
  364. *
  365. * @param type The type of handshaking to be performed, i.e. as a client or as
  366. * a server.
  367. *
  368. * @throws boost::system::system_error Thrown on failure.
  369. */
  370. void handshake(handshake_type type)
  371. {
  372. boost::system::error_code ec;
  373. handshake(type, ec);
  374. boost::asio::detail::throw_error(ec, "handshake");
  375. }
  376. /// Perform SSL handshaking.
  377. /**
  378. * This function is used to perform SSL handshaking on the stream. The
  379. * function call will block until handshaking is complete or an error occurs.
  380. *
  381. * @param type The type of handshaking to be performed, i.e. as a client or as
  382. * a server.
  383. *
  384. * @param ec Set to indicate what error occurred, if any.
  385. */
  386. BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
  387. boost::system::error_code& ec)
  388. {
  389. detail::io(next_layer_, core_, detail::handshake_op(type), ec);
  390. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  391. }
  392. /// Perform SSL handshaking.
  393. /**
  394. * This function is used to perform SSL handshaking on the stream. The
  395. * function call will block until handshaking is complete or an error occurs.
  396. *
  397. * @param type The type of handshaking to be performed, i.e. as a client or as
  398. * a server.
  399. *
  400. * @param buffers The buffered data to be reused for the handshake.
  401. *
  402. * @throws boost::system::system_error Thrown on failure.
  403. */
  404. template <typename ConstBufferSequence>
  405. void handshake(handshake_type type, const ConstBufferSequence& buffers)
  406. {
  407. boost::system::error_code ec;
  408. handshake(type, buffers, ec);
  409. boost::asio::detail::throw_error(ec, "handshake");
  410. }
  411. /// Perform SSL handshaking.
  412. /**
  413. * This function is used to perform SSL handshaking on the stream. The
  414. * function call will block until handshaking is complete or an error occurs.
  415. *
  416. * @param type The type of handshaking to be performed, i.e. as a client or as
  417. * a server.
  418. *
  419. * @param buffers The buffered data to be reused for the handshake.
  420. *
  421. * @param ec Set to indicate what error occurred, if any.
  422. */
  423. template <typename ConstBufferSequence>
  424. BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
  425. const ConstBufferSequence& buffers, boost::system::error_code& ec)
  426. {
  427. detail::io(next_layer_, core_,
  428. detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);
  429. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  430. }
  431. /// Start an asynchronous SSL handshake.
  432. /**
  433. * This function is used to asynchronously perform an SSL handshake on the
  434. * stream. It is an initiating function for an @ref asynchronous_operation,
  435. * and always returns immediately.
  436. *
  437. * @param type The type of handshaking to be performed, i.e. as a client or as
  438. * a server.
  439. *
  440. * @param token The @ref completion_token that will be used to produce a
  441. * completion handler, which will be called when the handshake completes.
  442. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  443. * @ref yield_context, or a function object with the correct completion
  444. * signature. The function signature of the completion handler must be:
  445. * @code void handler(
  446. * const boost::system::error_code& error // Result of operation.
  447. * ); @endcode
  448. * Regardless of whether the asynchronous operation completes immediately or
  449. * not, the completion handler will not be invoked from within this function.
  450. * On immediate completion, invocation of the handler will be performed in a
  451. * manner equivalent to using boost::asio::async_immediate().
  452. *
  453. * @par Completion Signature
  454. * @code void(boost::system::error_code) @endcode
  455. *
  456. * @par Per-Operation Cancellation
  457. * This asynchronous operation supports cancellation for the following
  458. * boost::asio::cancellation_type values:
  459. *
  460. * @li @c cancellation_type::terminal
  461. *
  462. * @li @c cancellation_type::partial
  463. *
  464. * if they are also supported by the @c Stream type's @c async_read_some and
  465. * @c async_write_some operations.
  466. */
  467. template <
  468. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
  469. HandshakeToken = default_completion_token_t<executor_type>>
  470. auto async_handshake(handshake_type type,
  471. HandshakeToken&& token = default_completion_token_t<executor_type>())
  472. -> decltype(
  473. async_initiate<HandshakeToken,
  474. void (boost::system::error_code)>(
  475. declval<initiate_async_handshake>(), token, type))
  476. {
  477. return async_initiate<HandshakeToken,
  478. void (boost::system::error_code)>(
  479. initiate_async_handshake(this), token, type);
  480. }
  481. /// Start an asynchronous SSL handshake.
  482. /**
  483. * This function is used to asynchronously perform an SSL handshake on the
  484. * stream. It is an initiating function for an @ref asynchronous_operation,
  485. * and always returns immediately.
  486. *
  487. * @param type The type of handshaking to be performed, i.e. as a client or as
  488. * a server.
  489. *
  490. * @param buffers The buffered data to be reused for the handshake. Although
  491. * the buffers object may be copied as necessary, ownership of the underlying
  492. * buffers is retained by the caller, which must guarantee that they remain
  493. * valid until the completion handler is called.
  494. *
  495. * @param token The @ref completion_token that will be used to produce a
  496. * completion handler, which will be called when the handshake completes.
  497. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  498. * @ref yield_context, or a function object with the correct completion
  499. * signature. The function signature of the completion handler must be:
  500. * @code void handler(
  501. * const boost::system::error_code& error, // Result of operation.
  502. * std::size_t bytes_transferred // Amount of buffers used in handshake.
  503. * ); @endcode
  504. * Regardless of whether the asynchronous operation completes immediately or
  505. * not, the completion handler will not be invoked from within this function.
  506. * On immediate completion, invocation of the handler will be performed in a
  507. * manner equivalent to using boost::asio::async_immediate().
  508. *
  509. * @par Completion Signature
  510. * @code void(boost::system::error_code, std::size_t) @endcode
  511. *
  512. * @par Per-Operation Cancellation
  513. * This asynchronous operation supports cancellation for the following
  514. * boost::asio::cancellation_type values:
  515. *
  516. * @li @c cancellation_type::terminal
  517. *
  518. * @li @c cancellation_type::partial
  519. *
  520. * if they are also supported by the @c Stream type's @c async_read_some and
  521. * @c async_write_some operations.
  522. */
  523. template <typename ConstBufferSequence,
  524. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  525. std::size_t)) BufferedHandshakeToken
  526. = default_completion_token_t<executor_type>>
  527. auto async_handshake(handshake_type type, const ConstBufferSequence& buffers,
  528. BufferedHandshakeToken&& token
  529. = default_completion_token_t<executor_type>(),
  530. constraint_t<
  531. is_const_buffer_sequence<ConstBufferSequence>::value
  532. > = 0)
  533. -> decltype(
  534. async_initiate<BufferedHandshakeToken,
  535. void (boost::system::error_code, std::size_t)>(
  536. declval<initiate_async_buffered_handshake>(), token, type, buffers))
  537. {
  538. return async_initiate<BufferedHandshakeToken,
  539. void (boost::system::error_code, std::size_t)>(
  540. initiate_async_buffered_handshake(this), token, type, buffers);
  541. }
  542. /// Shut down SSL on the stream.
  543. /**
  544. * This function is used to shut down SSL on the stream. The function call
  545. * will block until SSL has been shut down or an error occurs.
  546. *
  547. * @throws boost::system::system_error Thrown on failure.
  548. */
  549. void shutdown()
  550. {
  551. boost::system::error_code ec;
  552. shutdown(ec);
  553. boost::asio::detail::throw_error(ec, "shutdown");
  554. }
  555. /// Shut down SSL on the stream.
  556. /**
  557. * This function is used to shut down SSL on the stream. The function call
  558. * will block until SSL has been shut down or an error occurs.
  559. *
  560. * @param ec Set to indicate what error occurred, if any.
  561. */
  562. BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec)
  563. {
  564. detail::io(next_layer_, core_, detail::shutdown_op(), ec);
  565. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  566. }
  567. /// Asynchronously shut down SSL on the stream.
  568. /**
  569. * This function is used to asynchronously shut down SSL on the stream. It is
  570. * an initiating function for an @ref asynchronous_operation, and always
  571. * returns immediately.
  572. *
  573. * @param token The @ref completion_token that will be used to produce a
  574. * completion handler, which will be called when the shutdown completes.
  575. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  576. * @ref yield_context, or a function object with the correct completion
  577. * signature. The function signature of the completion handler must be:
  578. * @code void handler(
  579. * const boost::system::error_code& error // Result of operation.
  580. * ); @endcode
  581. * Regardless of whether the asynchronous operation completes immediately or
  582. * not, the completion handler will not be invoked from within this function.
  583. * On immediate completion, invocation of the handler will be performed in a
  584. * manner equivalent to using boost::asio::async_immediate().
  585. *
  586. * @par Completion Signature
  587. * @code void(boost::system::error_code) @endcode
  588. *
  589. * @par Per-Operation Cancellation
  590. * This asynchronous operation supports cancellation for the following
  591. * boost::asio::cancellation_type values:
  592. *
  593. * @li @c cancellation_type::terminal
  594. *
  595. * @li @c cancellation_type::partial
  596. *
  597. * if they are also supported by the @c Stream type's @c async_read_some and
  598. * @c async_write_some operations.
  599. */
  600. template <
  601. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code))
  602. ShutdownToken
  603. = default_completion_token_t<executor_type>>
  604. auto async_shutdown(
  605. ShutdownToken&& token = default_completion_token_t<executor_type>())
  606. -> decltype(
  607. async_initiate<ShutdownToken,
  608. void (boost::system::error_code)>(
  609. declval<initiate_async_shutdown>(), token))
  610. {
  611. return async_initiate<ShutdownToken,
  612. void (boost::system::error_code)>(
  613. initiate_async_shutdown(this), token);
  614. }
  615. /// Write some data to the stream.
  616. /**
  617. * This function is used to write data on the stream. The function call will
  618. * block until one or more bytes of data has been written successfully, or
  619. * until an error occurs.
  620. *
  621. * @param buffers The data to be written.
  622. *
  623. * @returns The number of bytes written.
  624. *
  625. * @throws boost::system::system_error Thrown on failure.
  626. *
  627. * @note The write_some operation may not transmit all of the data to the
  628. * peer. Consider using the @ref write function if you need to ensure that all
  629. * data is written before the blocking operation completes.
  630. */
  631. template <typename ConstBufferSequence>
  632. std::size_t write_some(const ConstBufferSequence& buffers)
  633. {
  634. boost::system::error_code ec;
  635. std::size_t n = write_some(buffers, ec);
  636. boost::asio::detail::throw_error(ec, "write_some");
  637. return n;
  638. }
  639. /// Write some data to the stream.
  640. /**
  641. * This function is used to write data on the stream. The function call will
  642. * block until one or more bytes of data has been written successfully, or
  643. * until an error occurs.
  644. *
  645. * @param buffers The data to be written to the stream.
  646. *
  647. * @param ec Set to indicate what error occurred, if any.
  648. *
  649. * @returns The number of bytes written. Returns 0 if an error occurred.
  650. *
  651. * @note The write_some operation may not transmit all of the data to the
  652. * peer. Consider using the @ref write function if you need to ensure that all
  653. * data is written before the blocking operation completes.
  654. */
  655. template <typename ConstBufferSequence>
  656. std::size_t write_some(const ConstBufferSequence& buffers,
  657. boost::system::error_code& ec)
  658. {
  659. return detail::io(next_layer_, core_,
  660. detail::write_op<ConstBufferSequence>(buffers), ec);
  661. }
  662. /// Start an asynchronous write.
  663. /**
  664. * This function is used to asynchronously write one or more bytes of data to
  665. * the stream. It is an initiating function for an @ref
  666. * asynchronous_operation, and always returns immediately.
  667. *
  668. * @param buffers The data to be written to the stream. Although the buffers
  669. * object may be copied as necessary, ownership of the underlying buffers is
  670. * retained by the caller, which must guarantee that they remain valid until
  671. * the completion handler is called.
  672. *
  673. * @param token The @ref completion_token that will be used to produce a
  674. * completion handler, which will be called when the write completes.
  675. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  676. * @ref yield_context, or a function object with the correct completion
  677. * signature. The function signature of the completion handler must be:
  678. * @code void handler(
  679. * const boost::system::error_code& error, // Result of operation.
  680. * std::size_t bytes_transferred // Number of bytes written.
  681. * ); @endcode
  682. * Regardless of whether the asynchronous operation completes immediately or
  683. * not, the completion handler will not be invoked from within this function.
  684. * On immediate completion, invocation of the handler will be performed in a
  685. * manner equivalent to using boost::asio::async_immediate().
  686. *
  687. * @par Completion Signature
  688. * @code void(boost::system::error_code, std::size_t) @endcode
  689. *
  690. * @note The async_write_some operation may not transmit all of the data to
  691. * the peer. Consider using the @ref async_write function if you need to
  692. * ensure that all data is written before the asynchronous operation
  693. * completes.
  694. *
  695. * @par Per-Operation Cancellation
  696. * This asynchronous operation supports cancellation for the following
  697. * boost::asio::cancellation_type values:
  698. *
  699. * @li @c cancellation_type::terminal
  700. *
  701. * @li @c cancellation_type::partial
  702. *
  703. * if they are also supported by the @c Stream type's @c async_read_some and
  704. * @c async_write_some operations.
  705. */
  706. template <typename ConstBufferSequence,
  707. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  708. std::size_t)) WriteToken = default_completion_token_t<executor_type>>
  709. auto async_write_some(const ConstBufferSequence& buffers,
  710. WriteToken&& token = default_completion_token_t<executor_type>())
  711. -> decltype(
  712. async_initiate<WriteToken,
  713. void (boost::system::error_code, std::size_t)>(
  714. declval<initiate_async_write_some>(), token, buffers))
  715. {
  716. return async_initiate<WriteToken,
  717. void (boost::system::error_code, std::size_t)>(
  718. initiate_async_write_some(this), token, buffers);
  719. }
  720. /// Read some data from the stream.
  721. /**
  722. * This function is used to read data from the stream. The function call will
  723. * block until one or more bytes of data has been read successfully, or until
  724. * an error occurs.
  725. *
  726. * @param buffers The buffers into which the data will be read.
  727. *
  728. * @returns The number of bytes read.
  729. *
  730. * @throws boost::system::system_error Thrown on failure.
  731. *
  732. * @note The read_some operation may not read all of the requested number of
  733. * bytes. Consider using the @ref read function if you need to ensure that the
  734. * requested amount of data is read before the blocking operation completes.
  735. */
  736. template <typename MutableBufferSequence>
  737. std::size_t read_some(const MutableBufferSequence& buffers)
  738. {
  739. boost::system::error_code ec;
  740. std::size_t n = read_some(buffers, ec);
  741. boost::asio::detail::throw_error(ec, "read_some");
  742. return n;
  743. }
  744. /// Read some data from the stream.
  745. /**
  746. * This function is used to read data from the stream. The function call will
  747. * block until one or more bytes of data has been read successfully, or until
  748. * an error occurs.
  749. *
  750. * @param buffers The buffers into which the data will be read.
  751. *
  752. * @param ec Set to indicate what error occurred, if any.
  753. *
  754. * @returns The number of bytes read. Returns 0 if an error occurred.
  755. *
  756. * @note The read_some operation may not read all of the requested number of
  757. * bytes. Consider using the @ref read function if you need to ensure that the
  758. * requested amount of data is read before the blocking operation completes.
  759. */
  760. template <typename MutableBufferSequence>
  761. std::size_t read_some(const MutableBufferSequence& buffers,
  762. boost::system::error_code& ec)
  763. {
  764. return detail::io(next_layer_, core_,
  765. detail::read_op<MutableBufferSequence>(buffers), ec);
  766. }
  767. /// Start an asynchronous read.
  768. /**
  769. * This function is used to asynchronously read one or more bytes of data from
  770. * the stream. It is an initiating function for an @ref
  771. * asynchronous_operation, and always returns immediately.
  772. *
  773. * @param buffers The buffers into which the data will be read. Although the
  774. * buffers object may be copied as necessary, ownership of the underlying
  775. * buffers is retained by the caller, which must guarantee that they remain
  776. * valid until the completion handler is called.
  777. *
  778. * @param token The @ref completion_token that will be used to produce a
  779. * completion handler, which will be called when the read completes.
  780. * Potential completion tokens include @ref use_future, @ref use_awaitable,
  781. * @ref yield_context, or a function object with the correct completion
  782. * signature. The function signature of the completion handler must be:
  783. * @code void handler(
  784. * const boost::system::error_code& error, // Result of operation.
  785. * std::size_t bytes_transferred // Number of bytes read.
  786. * ); @endcode
  787. * Regardless of whether the asynchronous operation completes immediately or
  788. * not, the completion handler will not be invoked from within this function.
  789. * On immediate completion, invocation of the handler will be performed in a
  790. * manner equivalent to using boost::asio::async_immediate().
  791. *
  792. * @par Completion Signature
  793. * @code void(boost::system::error_code, std::size_t) @endcode
  794. *
  795. * @note The async_read_some operation may not read all of the requested
  796. * number of bytes. Consider using the @ref async_read function if you need to
  797. * ensure that the requested amount of data is read before the asynchronous
  798. * operation completes.
  799. *
  800. * @par Per-Operation Cancellation
  801. * This asynchronous operation supports cancellation for the following
  802. * boost::asio::cancellation_type values:
  803. *
  804. * @li @c cancellation_type::terminal
  805. *
  806. * @li @c cancellation_type::partial
  807. *
  808. * if they are also supported by the @c Stream type's @c async_read_some and
  809. * @c async_write_some operations.
  810. */
  811. template <typename MutableBufferSequence,
  812. BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
  813. std::size_t)) ReadToken = default_completion_token_t<executor_type>>
  814. auto async_read_some(const MutableBufferSequence& buffers,
  815. ReadToken&& token = default_completion_token_t<executor_type>())
  816. -> decltype(
  817. async_initiate<ReadToken,
  818. void (boost::system::error_code, std::size_t)>(
  819. declval<initiate_async_read_some>(), token, buffers))
  820. {
  821. return async_initiate<ReadToken,
  822. void (boost::system::error_code, std::size_t)>(
  823. initiate_async_read_some(this), token, buffers);
  824. }
  825. private:
  826. class initiate_async_handshake
  827. {
  828. public:
  829. typedef typename stream::executor_type executor_type;
  830. explicit initiate_async_handshake(stream* self)
  831. : self_(self)
  832. {
  833. }
  834. executor_type get_executor() const noexcept
  835. {
  836. return self_->get_executor();
  837. }
  838. template <typename HandshakeHandler>
  839. void operator()(HandshakeHandler&& handler,
  840. handshake_type type) const
  841. {
  842. // If you get an error on the following line it means that your handler
  843. // does not meet the documented type requirements for a HandshakeHandler.
  844. BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
  845. boost::asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler);
  846. detail::async_io(self_->next_layer_, self_->core_,
  847. detail::handshake_op(type), handler2.value);
  848. }
  849. private:
  850. stream* self_;
  851. };
  852. class initiate_async_buffered_handshake
  853. {
  854. public:
  855. typedef typename stream::executor_type executor_type;
  856. explicit initiate_async_buffered_handshake(stream* self)
  857. : self_(self)
  858. {
  859. }
  860. executor_type get_executor() const noexcept
  861. {
  862. return self_->get_executor();
  863. }
  864. template <typename BufferedHandshakeHandler, typename ConstBufferSequence>
  865. void operator()(BufferedHandshakeHandler&& handler,
  866. handshake_type type, const ConstBufferSequence& buffers) const
  867. {
  868. // If you get an error on the following line it means that your
  869. // handler does not meet the documented type requirements for a
  870. // BufferedHandshakeHandler.
  871. BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
  872. BufferedHandshakeHandler, handler) type_check;
  873. boost::asio::detail::non_const_lvalue<
  874. BufferedHandshakeHandler> handler2(handler);
  875. detail::async_io(self_->next_layer_, self_->core_,
  876. detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
  877. handler2.value);
  878. }
  879. private:
  880. stream* self_;
  881. };
  882. class initiate_async_shutdown
  883. {
  884. public:
  885. typedef typename stream::executor_type executor_type;
  886. explicit initiate_async_shutdown(stream* self)
  887. : self_(self)
  888. {
  889. }
  890. executor_type get_executor() const noexcept
  891. {
  892. return self_->get_executor();
  893. }
  894. template <typename ShutdownHandler>
  895. void operator()(ShutdownHandler&& handler) const
  896. {
  897. // If you get an error on the following line it means that your handler
  898. // does not meet the documented type requirements for a ShutdownHandler.
  899. BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;
  900. boost::asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler);
  901. detail::async_io(self_->next_layer_, self_->core_,
  902. detail::shutdown_op(), handler2.value);
  903. }
  904. private:
  905. stream* self_;
  906. };
  907. class initiate_async_write_some
  908. {
  909. public:
  910. typedef typename stream::executor_type executor_type;
  911. explicit initiate_async_write_some(stream* self)
  912. : self_(self)
  913. {
  914. }
  915. executor_type get_executor() const noexcept
  916. {
  917. return self_->get_executor();
  918. }
  919. template <typename WriteHandler, typename ConstBufferSequence>
  920. void operator()(WriteHandler&& handler,
  921. const ConstBufferSequence& buffers) const
  922. {
  923. // If you get an error on the following line it means that your handler
  924. // does not meet the documented type requirements for a WriteHandler.
  925. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  926. boost::asio::detail::non_const_lvalue<WriteHandler> handler2(handler);
  927. detail::async_io(self_->next_layer_, self_->core_,
  928. detail::write_op<ConstBufferSequence>(buffers), handler2.value);
  929. }
  930. private:
  931. stream* self_;
  932. };
  933. class initiate_async_read_some
  934. {
  935. public:
  936. typedef typename stream::executor_type executor_type;
  937. explicit initiate_async_read_some(stream* self)
  938. : self_(self)
  939. {
  940. }
  941. executor_type get_executor() const noexcept
  942. {
  943. return self_->get_executor();
  944. }
  945. template <typename ReadHandler, typename MutableBufferSequence>
  946. void operator()(ReadHandler&& handler,
  947. const MutableBufferSequence& buffers) const
  948. {
  949. // If you get an error on the following line it means that your handler
  950. // does not meet the documented type requirements for a ReadHandler.
  951. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  952. boost::asio::detail::non_const_lvalue<ReadHandler> handler2(handler);
  953. detail::async_io(self_->next_layer_, self_->core_,
  954. detail::read_op<MutableBufferSequence>(buffers), handler2.value);
  955. }
  956. private:
  957. stream* self_;
  958. };
  959. Stream next_layer_;
  960. detail::stream_core core_;
  961. };
  962. } // namespace ssl
  963. } // namespace asio
  964. } // namespace boost
  965. #include <boost/asio/detail/pop_options.hpp>
  966. #endif // BOOST_ASIO_SSL_STREAM_HPP