stream.hpp 37 KB

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