stream.hpp 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. //
  2. // ssl/stream.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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::post().
  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::post().
  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::post().
  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::post().
  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::post().
  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