stream.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. //
  2. // ssl/stream.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2018 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/noncopyable.hpp>
  20. #include <boost/asio/detail/type_traits.hpp>
  21. #include <boost/asio/ssl/context.hpp>
  22. #include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
  23. #include <boost/asio/ssl/detail/handshake_op.hpp>
  24. #include <boost/asio/ssl/detail/io.hpp>
  25. #include <boost/asio/ssl/detail/read_op.hpp>
  26. #include <boost/asio/ssl/detail/shutdown_op.hpp>
  27. #include <boost/asio/ssl/detail/stream_core.hpp>
  28. #include <boost/asio/ssl/detail/write_op.hpp>
  29. #include <boost/asio/ssl/stream_base.hpp>
  30. #include <boost/asio/detail/push_options.hpp>
  31. namespace boost {
  32. namespace asio {
  33. namespace ssl {
  34. /// Provides stream-oriented functionality using SSL.
  35. /**
  36. * The stream class template provides asynchronous and blocking stream-oriented
  37. * functionality using SSL.
  38. *
  39. * @par Thread Safety
  40. * @e Distinct @e objects: Safe.@n
  41. * @e Shared @e objects: Unsafe. The application must also ensure that all
  42. * asynchronous operations are performed within the same implicit or explicit
  43. * strand.
  44. *
  45. * @par Example
  46. * To use the SSL stream template with an ip::tcp::socket, you would write:
  47. * @code
  48. * boost::asio::io_context io_context;
  49. * boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
  50. * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
  51. * @endcode
  52. *
  53. * @par Concepts:
  54. * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
  55. */
  56. template <typename Stream>
  57. class stream :
  58. public stream_base,
  59. private noncopyable
  60. {
  61. public:
  62. /// The native handle type of the SSL stream.
  63. typedef SSL* native_handle_type;
  64. /// Structure for use with deprecated impl_type.
  65. struct impl_struct
  66. {
  67. SSL* ssl;
  68. };
  69. /// The type of the next layer.
  70. typedef typename remove_reference<Stream>::type next_layer_type;
  71. /// The type of the lowest layer.
  72. typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
  73. /// The type of the executor associated with the object.
  74. typedef typename lowest_layer_type::executor_type executor_type;
  75. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  76. /// Construct a stream.
  77. /**
  78. * This constructor creates a stream and initialises the underlying stream
  79. * object.
  80. *
  81. * @param arg The argument to be passed to initialise the underlying stream.
  82. *
  83. * @param ctx The SSL context to be used for the stream.
  84. */
  85. template <typename Arg>
  86. stream(Arg&& arg, context& ctx)
  87. : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)),
  88. core_(ctx.native_handle(),
  89. next_layer_.lowest_layer().get_executor().context())
  90. {
  91. }
  92. #else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  93. template <typename Arg>
  94. stream(Arg& arg, context& ctx)
  95. : next_layer_(arg),
  96. core_(ctx.native_handle(),
  97. next_layer_.lowest_layer().get_executor().context())
  98. {
  99. }
  100. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  101. /// Destructor.
  102. /**
  103. * @note A @c stream object must not be destroyed while there are pending
  104. * asynchronous operations associated with it.
  105. */
  106. ~stream()
  107. {
  108. }
  109. /// Get the executor associated with the object.
  110. /**
  111. * This function may be used to obtain the executor object that the stream
  112. * uses to dispatch handlers for asynchronous operations.
  113. *
  114. * @return A copy of the executor that stream will use to dispatch handlers.
  115. */
  116. executor_type get_executor() BOOST_ASIO_NOEXCEPT
  117. {
  118. return next_layer_.lowest_layer().get_executor();
  119. }
  120. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  121. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  122. /// object.
  123. boost::asio::io_context& get_io_context()
  124. {
  125. return next_layer_.lowest_layer().get_io_context();
  126. }
  127. /// (Deprecated: Use get_executor().) Get the io_context associated with the
  128. /// object.
  129. boost::asio::io_context& get_io_service()
  130. {
  131. return next_layer_.lowest_layer().get_io_service();
  132. }
  133. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  134. /// Get the underlying implementation in the native type.
  135. /**
  136. * This function may be used to obtain the underlying implementation of the
  137. * context. This is intended to allow access to context functionality that is
  138. * not otherwise provided.
  139. *
  140. * @par Example
  141. * The native_handle() function returns a pointer of type @c SSL* that is
  142. * suitable for passing to functions such as @c SSL_get_verify_result and
  143. * @c SSL_get_peer_certificate:
  144. * @code
  145. * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
  146. *
  147. * // ... establish connection and perform handshake ...
  148. *
  149. * if (X509* cert = SSL_get_peer_certificate(sock.native_handle()))
  150. * {
  151. * if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK)
  152. * {
  153. * // ...
  154. * }
  155. * }
  156. * @endcode
  157. */
  158. native_handle_type native_handle()
  159. {
  160. return core_.engine_.native_handle();
  161. }
  162. /// Get a reference to the next layer.
  163. /**
  164. * This function returns a reference to the next layer in a stack of stream
  165. * layers.
  166. *
  167. * @return A reference to the next layer in the stack of stream layers.
  168. * Ownership is not transferred to the caller.
  169. */
  170. const next_layer_type& next_layer() const
  171. {
  172. return next_layer_;
  173. }
  174. /// Get a reference to the next layer.
  175. /**
  176. * This function returns a reference to the next layer in a stack of stream
  177. * layers.
  178. *
  179. * @return A reference to the next layer in the stack of stream layers.
  180. * Ownership is not transferred to the caller.
  181. */
  182. next_layer_type& next_layer()
  183. {
  184. return next_layer_;
  185. }
  186. /// Get a reference to the lowest layer.
  187. /**
  188. * This function returns a reference to the lowest layer in a stack of
  189. * stream layers.
  190. *
  191. * @return A reference to the lowest layer in the stack of stream layers.
  192. * Ownership is not transferred to the caller.
  193. */
  194. lowest_layer_type& lowest_layer()
  195. {
  196. return next_layer_.lowest_layer();
  197. }
  198. /// Get a reference to the lowest layer.
  199. /**
  200. * This function returns a reference to the lowest layer in a stack of
  201. * stream layers.
  202. *
  203. * @return A reference to the lowest layer in the stack of stream layers.
  204. * Ownership is not transferred to the caller.
  205. */
  206. const lowest_layer_type& lowest_layer() const
  207. {
  208. return next_layer_.lowest_layer();
  209. }
  210. /// Set the peer verification mode.
  211. /**
  212. * This function may be used to configure the peer verification mode used by
  213. * the stream. The new mode will override the mode inherited from the context.
  214. *
  215. * @param v A bitmask of peer verification modes. See @ref verify_mode for
  216. * available values.
  217. *
  218. * @throws boost::system::system_error Thrown on failure.
  219. *
  220. * @note Calls @c SSL_set_verify.
  221. */
  222. void set_verify_mode(verify_mode v)
  223. {
  224. boost::system::error_code ec;
  225. set_verify_mode(v, ec);
  226. boost::asio::detail::throw_error(ec, "set_verify_mode");
  227. }
  228. /// Set the peer verification mode.
  229. /**
  230. * This function may be used to configure the peer verification mode used by
  231. * the stream. The new mode will override the mode inherited from the context.
  232. *
  233. * @param v A bitmask of peer verification modes. See @ref verify_mode for
  234. * available values.
  235. *
  236. * @param ec Set to indicate what error occurred, if any.
  237. *
  238. * @note Calls @c SSL_set_verify.
  239. */
  240. BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
  241. verify_mode v, boost::system::error_code& ec)
  242. {
  243. core_.engine_.set_verify_mode(v, ec);
  244. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  245. }
  246. /// Set the peer verification depth.
  247. /**
  248. * This function may be used to configure the maximum verification depth
  249. * allowed by the stream.
  250. *
  251. * @param depth Maximum depth for the certificate chain verification that
  252. * shall be allowed.
  253. *
  254. * @throws boost::system::system_error Thrown on failure.
  255. *
  256. * @note Calls @c SSL_set_verify_depth.
  257. */
  258. void set_verify_depth(int depth)
  259. {
  260. boost::system::error_code ec;
  261. set_verify_depth(depth, ec);
  262. boost::asio::detail::throw_error(ec, "set_verify_depth");
  263. }
  264. /// Set the peer verification depth.
  265. /**
  266. * This function may be used to configure the maximum verification depth
  267. * allowed by the stream.
  268. *
  269. * @param depth Maximum depth for the certificate chain verification that
  270. * shall be allowed.
  271. *
  272. * @param ec Set to indicate what error occurred, if any.
  273. *
  274. * @note Calls @c SSL_set_verify_depth.
  275. */
  276. BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
  277. int depth, boost::system::error_code& ec)
  278. {
  279. core_.engine_.set_verify_depth(depth, ec);
  280. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  281. }
  282. /// Set the callback used to verify peer certificates.
  283. /**
  284. * This function is used to specify a callback function that will be called
  285. * by the implementation when it needs to verify a peer certificate.
  286. *
  287. * @param callback The function object to be used for verifying a certificate.
  288. * The function signature of the handler must be:
  289. * @code bool verify_callback(
  290. * bool preverified, // True if the certificate passed pre-verification.
  291. * verify_context& ctx // The peer certificate and other context.
  292. * ); @endcode
  293. * The return value of the callback is true if the certificate has passed
  294. * verification, false otherwise.
  295. *
  296. * @throws boost::system::system_error Thrown on failure.
  297. *
  298. * @note Calls @c SSL_set_verify.
  299. */
  300. template <typename VerifyCallback>
  301. void set_verify_callback(VerifyCallback callback)
  302. {
  303. boost::system::error_code ec;
  304. this->set_verify_callback(callback, ec);
  305. boost::asio::detail::throw_error(ec, "set_verify_callback");
  306. }
  307. /// Set the callback used to verify peer certificates.
  308. /**
  309. * This function is used to specify a callback function that will be called
  310. * by the implementation when it needs to verify a peer certificate.
  311. *
  312. * @param callback The function object to be used for verifying a certificate.
  313. * The function signature of the handler must be:
  314. * @code bool verify_callback(
  315. * bool preverified, // True if the certificate passed pre-verification.
  316. * verify_context& ctx // The peer certificate and other context.
  317. * ); @endcode
  318. * The return value of the callback is true if the certificate has passed
  319. * verification, false otherwise.
  320. *
  321. * @param ec Set to indicate what error occurred, if any.
  322. *
  323. * @note Calls @c SSL_set_verify.
  324. */
  325. template <typename VerifyCallback>
  326. BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
  327. boost::system::error_code& ec)
  328. {
  329. core_.engine_.set_verify_callback(
  330. new detail::verify_callback<VerifyCallback>(callback), ec);
  331. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  332. }
  333. /// Perform SSL handshaking.
  334. /**
  335. * This function is used to perform SSL handshaking on the stream. The
  336. * function call will block until handshaking is complete or an error occurs.
  337. *
  338. * @param type The type of handshaking to be performed, i.e. as a client or as
  339. * a server.
  340. *
  341. * @throws boost::system::system_error Thrown on failure.
  342. */
  343. void handshake(handshake_type type)
  344. {
  345. boost::system::error_code ec;
  346. handshake(type, ec);
  347. boost::asio::detail::throw_error(ec, "handshake");
  348. }
  349. /// Perform SSL handshaking.
  350. /**
  351. * This function is used to perform SSL handshaking on the stream. The
  352. * function call will block until handshaking is complete or an error occurs.
  353. *
  354. * @param type The type of handshaking to be performed, i.e. as a client or as
  355. * a server.
  356. *
  357. * @param ec Set to indicate what error occurred, if any.
  358. */
  359. BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
  360. boost::system::error_code& ec)
  361. {
  362. detail::io(next_layer_, core_, detail::handshake_op(type), ec);
  363. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  364. }
  365. /// Perform SSL handshaking.
  366. /**
  367. * This function is used to perform SSL handshaking on the stream. The
  368. * function call will block until handshaking is complete or an error occurs.
  369. *
  370. * @param type The type of handshaking to be performed, i.e. as a client or as
  371. * a server.
  372. *
  373. * @param buffers The buffered data to be reused for the handshake.
  374. *
  375. * @throws boost::system::system_error Thrown on failure.
  376. */
  377. template <typename ConstBufferSequence>
  378. void handshake(handshake_type type, const ConstBufferSequence& buffers)
  379. {
  380. boost::system::error_code ec;
  381. handshake(type, buffers, ec);
  382. boost::asio::detail::throw_error(ec, "handshake");
  383. }
  384. /// Perform SSL handshaking.
  385. /**
  386. * This function is used to perform SSL handshaking on the stream. The
  387. * function call will block until handshaking is complete or an error occurs.
  388. *
  389. * @param type The type of handshaking to be performed, i.e. as a client or as
  390. * a server.
  391. *
  392. * @param buffers The buffered data to be reused for the handshake.
  393. *
  394. * @param ec Set to indicate what error occurred, if any.
  395. */
  396. template <typename ConstBufferSequence>
  397. BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
  398. const ConstBufferSequence& buffers, boost::system::error_code& ec)
  399. {
  400. detail::io(next_layer_, core_,
  401. detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);
  402. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  403. }
  404. /// Start an asynchronous SSL handshake.
  405. /**
  406. * This function is used to asynchronously perform an SSL handshake on the
  407. * stream. This function call always returns immediately.
  408. *
  409. * @param type The type of handshaking to be performed, i.e. as a client or as
  410. * a server.
  411. *
  412. * @param handler The handler to be called when the handshake operation
  413. * completes. Copies will be made of the handler as required. The equivalent
  414. * function signature of the handler must be:
  415. * @code void handler(
  416. * const boost::system::error_code& error // Result of operation.
  417. * ); @endcode
  418. */
  419. template <typename HandshakeHandler>
  420. BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler,
  421. void (boost::system::error_code))
  422. async_handshake(handshake_type type,
  423. BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
  424. {
  425. // If you get an error on the following line it means that your handler does
  426. // not meet the documented type requirements for a HandshakeHandler.
  427. BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
  428. boost::asio::async_completion<HandshakeHandler,
  429. void (boost::system::error_code)> init(handler);
  430. detail::async_io(next_layer_, core_,
  431. detail::handshake_op(type), init.completion_handler);
  432. return init.result.get();
  433. }
  434. /// Start an asynchronous SSL handshake.
  435. /**
  436. * This function is used to asynchronously perform an SSL handshake on the
  437. * stream. This function call always returns immediately.
  438. *
  439. * @param type The type of handshaking to be performed, i.e. as a client or as
  440. * a server.
  441. *
  442. * @param buffers The buffered data to be reused for the handshake. Although
  443. * the buffers object may be copied as necessary, ownership of the underlying
  444. * buffers is retained by the caller, which must guarantee that they remain
  445. * valid until the handler is called.
  446. *
  447. * @param handler The handler to be called when the handshake operation
  448. * completes. Copies will be made of the handler as required. The equivalent
  449. * function signature of the handler must be:
  450. * @code void handler(
  451. * const boost::system::error_code& error, // Result of operation.
  452. * std::size_t bytes_transferred // Amount of buffers used in handshake.
  453. * ); @endcode
  454. */
  455. template <typename ConstBufferSequence, typename BufferedHandshakeHandler>
  456. BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler,
  457. void (boost::system::error_code, std::size_t))
  458. async_handshake(handshake_type type, const ConstBufferSequence& buffers,
  459. BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
  460. {
  461. // If you get an error on the following line it means that your handler does
  462. // not meet the documented type requirements for a BufferedHandshakeHandler.
  463. BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
  464. BufferedHandshakeHandler, handler) type_check;
  465. boost::asio::async_completion<BufferedHandshakeHandler,
  466. void (boost::system::error_code, std::size_t)> init(handler);
  467. detail::async_io(next_layer_, core_,
  468. detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
  469. init.completion_handler);
  470. return init.result.get();
  471. }
  472. /// Shut down SSL on the stream.
  473. /**
  474. * This function is used to shut down SSL on the stream. The function call
  475. * will block until SSL has been shut down or an error occurs.
  476. *
  477. * @throws boost::system::system_error Thrown on failure.
  478. */
  479. void shutdown()
  480. {
  481. boost::system::error_code ec;
  482. shutdown(ec);
  483. boost::asio::detail::throw_error(ec, "shutdown");
  484. }
  485. /// Shut down SSL on the stream.
  486. /**
  487. * This function is used to shut down SSL on the stream. The function call
  488. * will block until SSL has been shut down or an error occurs.
  489. *
  490. * @param ec Set to indicate what error occurred, if any.
  491. */
  492. BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec)
  493. {
  494. detail::io(next_layer_, core_, detail::shutdown_op(), ec);
  495. BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
  496. }
  497. /// Asynchronously shut down SSL on the stream.
  498. /**
  499. * This function is used to asynchronously shut down SSL on the stream. This
  500. * function call always returns immediately.
  501. *
  502. * @param handler The handler to be called when the handshake operation
  503. * completes. Copies will be made of the handler as required. The equivalent
  504. * function signature of the handler must be:
  505. * @code void handler(
  506. * const boost::system::error_code& error // Result of operation.
  507. * ); @endcode
  508. */
  509. template <typename ShutdownHandler>
  510. BOOST_ASIO_INITFN_RESULT_TYPE(ShutdownHandler,
  511. void (boost::system::error_code))
  512. async_shutdown(BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
  513. {
  514. // If you get an error on the following line it means that your handler does
  515. // not meet the documented type requirements for a ShutdownHandler.
  516. BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check;
  517. boost::asio::async_completion<ShutdownHandler,
  518. void (boost::system::error_code)> init(handler);
  519. detail::async_io(next_layer_, core_, detail::shutdown_op(),
  520. init.completion_handler);
  521. return init.result.get();
  522. }
  523. /// Write some data to the stream.
  524. /**
  525. * This function is used to write data on the stream. The function call will
  526. * block until one or more bytes of data has been written successfully, or
  527. * until an error occurs.
  528. *
  529. * @param buffers The data to be written.
  530. *
  531. * @returns The number of bytes written.
  532. *
  533. * @throws boost::system::system_error Thrown on failure.
  534. *
  535. * @note The write_some operation may not transmit all of the data to the
  536. * peer. Consider using the @ref write function if you need to ensure that all
  537. * data is written before the blocking operation completes.
  538. */
  539. template <typename ConstBufferSequence>
  540. std::size_t write_some(const ConstBufferSequence& buffers)
  541. {
  542. boost::system::error_code ec;
  543. std::size_t n = write_some(buffers, ec);
  544. boost::asio::detail::throw_error(ec, "write_some");
  545. return n;
  546. }
  547. /// Write some data to the stream.
  548. /**
  549. * This function is used to write data on the stream. The function call will
  550. * block until one or more bytes of data has been written successfully, or
  551. * until an error occurs.
  552. *
  553. * @param buffers The data to be written to the stream.
  554. *
  555. * @param ec Set to indicate what error occurred, if any.
  556. *
  557. * @returns The number of bytes written. Returns 0 if an error occurred.
  558. *
  559. * @note The write_some operation may not transmit all of the data to the
  560. * peer. Consider using the @ref write function if you need to ensure that all
  561. * data is written before the blocking operation completes.
  562. */
  563. template <typename ConstBufferSequence>
  564. std::size_t write_some(const ConstBufferSequence& buffers,
  565. boost::system::error_code& ec)
  566. {
  567. return detail::io(next_layer_, core_,
  568. detail::write_op<ConstBufferSequence>(buffers), ec);
  569. }
  570. /// Start an asynchronous write.
  571. /**
  572. * This function is used to asynchronously write one or more bytes of data to
  573. * the stream. The function call always returns immediately.
  574. *
  575. * @param buffers The data to be written to the stream. Although the buffers
  576. * object may be copied as necessary, ownership of the underlying buffers is
  577. * retained by the caller, which must guarantee that they remain valid until
  578. * the handler is called.
  579. *
  580. * @param handler The handler to be called when the write operation completes.
  581. * Copies will be made of the handler as required. The equivalent function
  582. * signature of the handler must be:
  583. * @code void handler(
  584. * const boost::system::error_code& error, // Result of operation.
  585. * std::size_t bytes_transferred // Number of bytes written.
  586. * ); @endcode
  587. *
  588. * @note The async_write_some operation may not transmit all of the data to
  589. * the peer. Consider using the @ref async_write function if you need to
  590. * ensure that all data is written before the blocking operation completes.
  591. */
  592. template <typename ConstBufferSequence, typename WriteHandler>
  593. BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
  594. void (boost::system::error_code, std::size_t))
  595. async_write_some(const ConstBufferSequence& buffers,
  596. BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
  597. {
  598. // If you get an error on the following line it means that your handler does
  599. // not meet the documented type requirements for a WriteHandler.
  600. BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
  601. boost::asio::async_completion<WriteHandler,
  602. void (boost::system::error_code, std::size_t)> init(handler);
  603. detail::async_io(next_layer_, core_,
  604. detail::write_op<ConstBufferSequence>(buffers),
  605. init.completion_handler);
  606. return init.result.get();
  607. }
  608. /// Read some data from the stream.
  609. /**
  610. * This function is used to read data from the stream. The function call will
  611. * block until one or more bytes of data has been read successfully, or until
  612. * an error occurs.
  613. *
  614. * @param buffers The buffers into which the data will be read.
  615. *
  616. * @returns The number of bytes read.
  617. *
  618. * @throws boost::system::system_error Thrown on failure.
  619. *
  620. * @note The read_some operation may not read all of the requested number of
  621. * bytes. Consider using the @ref read function if you need to ensure that the
  622. * requested amount of data is read before the blocking operation completes.
  623. */
  624. template <typename MutableBufferSequence>
  625. std::size_t read_some(const MutableBufferSequence& buffers)
  626. {
  627. boost::system::error_code ec;
  628. std::size_t n = read_some(buffers, ec);
  629. boost::asio::detail::throw_error(ec, "read_some");
  630. return n;
  631. }
  632. /// Read some data from the stream.
  633. /**
  634. * This function is used to read data from the stream. The function call will
  635. * block until one or more bytes of data has been read successfully, or until
  636. * an error occurs.
  637. *
  638. * @param buffers The buffers into which the data will be read.
  639. *
  640. * @param ec Set to indicate what error occurred, if any.
  641. *
  642. * @returns The number of bytes read. Returns 0 if an error occurred.
  643. *
  644. * @note The read_some operation may not read all of the requested number of
  645. * bytes. Consider using the @ref read function if you need to ensure that the
  646. * requested amount of data is read before the blocking operation completes.
  647. */
  648. template <typename MutableBufferSequence>
  649. std::size_t read_some(const MutableBufferSequence& buffers,
  650. boost::system::error_code& ec)
  651. {
  652. return detail::io(next_layer_, core_,
  653. detail::read_op<MutableBufferSequence>(buffers), ec);
  654. }
  655. /// Start an asynchronous read.
  656. /**
  657. * This function is used to asynchronously read one or more bytes of data from
  658. * the stream. The function call always returns immediately.
  659. *
  660. * @param buffers The buffers into which the data will be read. Although the
  661. * buffers object may be copied as necessary, ownership of the underlying
  662. * buffers is retained by the caller, which must guarantee that they remain
  663. * valid until the handler is called.
  664. *
  665. * @param handler The handler to be called when the read operation completes.
  666. * Copies will be made of the handler as required. The equivalent function
  667. * signature of the handler must be:
  668. * @code void handler(
  669. * const boost::system::error_code& error, // Result of operation.
  670. * std::size_t bytes_transferred // Number of bytes read.
  671. * ); @endcode
  672. *
  673. * @note The async_read_some operation may not read all of the requested
  674. * number of bytes. Consider using the @ref async_read function if you need to
  675. * ensure that the requested amount of data is read before the asynchronous
  676. * operation completes.
  677. */
  678. template <typename MutableBufferSequence, typename ReadHandler>
  679. BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
  680. void (boost::system::error_code, std::size_t))
  681. async_read_some(const MutableBufferSequence& buffers,
  682. BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
  683. {
  684. // If you get an error on the following line it means that your handler does
  685. // not meet the documented type requirements for a ReadHandler.
  686. BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
  687. boost::asio::async_completion<ReadHandler,
  688. void (boost::system::error_code, std::size_t)> init(handler);
  689. detail::async_io(next_layer_, core_,
  690. detail::read_op<MutableBufferSequence>(buffers),
  691. init.completion_handler);
  692. return init.result.get();
  693. }
  694. private:
  695. Stream next_layer_;
  696. detail::stream_core core_;
  697. };
  698. } // namespace ssl
  699. } // namespace asio
  700. } // namespace boost
  701. #include <boost/asio/detail/pop_options.hpp>
  702. #endif // BOOST_ASIO_SSL_STREAM_HPP