stream.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. //
  2. // ssl/old/stream.hpp
  3. // ~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
  6. // Copyright (c) 2005-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. #ifndef BOOST_ASIO_SSL_OLD_STREAM_HPP
  12. #define BOOST_ASIO_SSL_OLD_STREAM_HPP
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. # pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include <boost/asio/detail/config.hpp>
  17. #include <cstddef>
  18. #include <boost/noncopyable.hpp>
  19. #include <boost/asio/detail/throw_error.hpp>
  20. #include <boost/asio/detail/type_traits.hpp>
  21. #include <boost/asio/error.hpp>
  22. #include <boost/asio/ssl/basic_context.hpp>
  23. #include <boost/asio/ssl/stream_base.hpp>
  24. #include <boost/asio/ssl/stream_service.hpp>
  25. #include <boost/asio/detail/push_options.hpp>
  26. namespace boost {
  27. namespace asio {
  28. namespace ssl {
  29. namespace old {
  30. /// Provides stream-oriented functionality using SSL.
  31. /**
  32. * The stream class template provides asynchronous and blocking stream-oriented
  33. * functionality using SSL.
  34. *
  35. * @par Thread Safety
  36. * @e Distinct @e objects: Safe.@n
  37. * @e Shared @e objects: Unsafe.
  38. *
  39. * @par Example
  40. * To use the SSL stream template with an ip::tcp::socket, you would write:
  41. * @code
  42. * boost::asio::io_service io_service;
  43. * boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
  44. * boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock(io_service, context);
  45. * @endcode
  46. *
  47. * @par Concepts:
  48. * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream.
  49. */
  50. template <typename Stream, typename Service = old::stream_service>
  51. class stream
  52. : public stream_base,
  53. private boost::noncopyable
  54. {
  55. public:
  56. /// The type of the next layer.
  57. typedef typename remove_reference<Stream>::type next_layer_type;
  58. /// The type of the lowest layer.
  59. typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
  60. /// The type of the service that will be used to provide stream operations.
  61. typedef Service service_type;
  62. /// The native implementation type of the stream.
  63. typedef typename service_type::impl_type impl_type;
  64. /// Construct a stream.
  65. /**
  66. * This constructor creates a stream and initialises the underlying stream
  67. * object.
  68. *
  69. * @param arg The argument to be passed to initialise the underlying stream.
  70. *
  71. * @param context The SSL context to be used for the stream.
  72. */
  73. template <typename Arg, typename Context_Service>
  74. explicit stream(Arg& arg, basic_context<Context_Service>& context)
  75. : next_layer_(arg),
  76. service_(boost::asio::use_service<Service>(next_layer_.get_io_service())),
  77. impl_(service_.null())
  78. {
  79. service_.create(impl_, next_layer_, context);
  80. }
  81. /// Destructor.
  82. ~stream()
  83. {
  84. service_.destroy(impl_, next_layer_);
  85. }
  86. /// Get the io_service associated with the object.
  87. /**
  88. * This function may be used to obtain the io_service object that the stream
  89. * uses to dispatch handlers for asynchronous operations.
  90. *
  91. * @return A reference to the io_service object that stream will use to
  92. * dispatch handlers. Ownership is not transferred to the caller.
  93. */
  94. boost::asio::io_service& get_io_service()
  95. {
  96. return next_layer_.get_io_service();
  97. }
  98. /// Get a reference to the next layer.
  99. /**
  100. * This function returns a reference to the next layer in a stack of stream
  101. * layers.
  102. *
  103. * @return A reference to the next layer in the stack of stream layers.
  104. * Ownership is not transferred to the caller.
  105. */
  106. next_layer_type& next_layer()
  107. {
  108. return next_layer_;
  109. }
  110. /// Get a reference to the lowest layer.
  111. /**
  112. * This function returns a reference to the lowest layer in a stack of
  113. * stream layers.
  114. *
  115. * @return A reference to the lowest layer in the stack of stream layers.
  116. * Ownership is not transferred to the caller.
  117. */
  118. lowest_layer_type& lowest_layer()
  119. {
  120. return next_layer_.lowest_layer();
  121. }
  122. /// Get a const reference to the lowest layer.
  123. /**
  124. * This function returns a const reference to the lowest layer in a stack of
  125. * stream layers.
  126. *
  127. * @return A const reference to the lowest layer in the stack of stream
  128. * layers. Ownership is not transferred to the caller.
  129. */
  130. const lowest_layer_type& lowest_layer() const
  131. {
  132. return next_layer_.lowest_layer();
  133. }
  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 stream functionality that is
  138. * not otherwise provided.
  139. */
  140. impl_type impl()
  141. {
  142. return impl_;
  143. }
  144. /// Perform SSL handshaking.
  145. /**
  146. * This function is used to perform SSL handshaking on the stream. The
  147. * function call will block until handshaking is complete or an error occurs.
  148. *
  149. * @param type The type of handshaking to be performed, i.e. as a client or as
  150. * a server.
  151. *
  152. * @throws boost::system::system_error Thrown on failure.
  153. */
  154. void handshake(handshake_type type)
  155. {
  156. boost::system::error_code ec;
  157. service_.handshake(impl_, next_layer_, type, ec);
  158. boost::asio::detail::throw_error(ec);
  159. }
  160. /// Perform SSL handshaking.
  161. /**
  162. * This function is used to perform SSL handshaking on the stream. The
  163. * function call will block until handshaking is complete or an error occurs.
  164. *
  165. * @param type The type of handshaking to be performed, i.e. as a client or as
  166. * a server.
  167. *
  168. * @param ec Set to indicate what error occurred, if any.
  169. */
  170. boost::system::error_code handshake(handshake_type type,
  171. boost::system::error_code& ec)
  172. {
  173. return service_.handshake(impl_, next_layer_, type, ec);
  174. }
  175. /// Start an asynchronous SSL handshake.
  176. /**
  177. * This function is used to asynchronously perform an SSL handshake on the
  178. * stream. This function call always returns immediately.
  179. *
  180. * @param type The type of handshaking to be performed, i.e. as a client or as
  181. * a server.
  182. *
  183. * @param handler The handler to be called when the handshake operation
  184. * completes. Copies will be made of the handler as required. The equivalent
  185. * function signature of the handler must be:
  186. * @code void handler(
  187. * const boost::system::error_code& error // Result of operation.
  188. * ); @endcode
  189. */
  190. template <typename HandshakeHandler>
  191. void async_handshake(handshake_type type, HandshakeHandler handler)
  192. {
  193. service_.async_handshake(impl_, next_layer_, type, handler);
  194. }
  195. /// Shut down SSL on the stream.
  196. /**
  197. * This function is used to shut down SSL on the stream. The function call
  198. * will block until SSL has been shut down or an error occurs.
  199. *
  200. * @throws boost::system::system_error Thrown on failure.
  201. */
  202. void shutdown()
  203. {
  204. boost::system::error_code ec;
  205. service_.shutdown(impl_, next_layer_, ec);
  206. boost::asio::detail::throw_error(ec);
  207. }
  208. /// Shut down SSL on the stream.
  209. /**
  210. * This function is used to shut down SSL on the stream. The function call
  211. * will block until SSL has been shut down or an error occurs.
  212. *
  213. * @param ec Set to indicate what error occurred, if any.
  214. */
  215. boost::system::error_code shutdown(boost::system::error_code& ec)
  216. {
  217. return service_.shutdown(impl_, next_layer_, ec);
  218. }
  219. /// Asynchronously shut down SSL on the stream.
  220. /**
  221. * This function is used to asynchronously shut down SSL on the stream. This
  222. * function call always returns immediately.
  223. *
  224. * @param handler The handler to be called when the handshake operation
  225. * completes. Copies will be made of the handler as required. The equivalent
  226. * function signature of the handler must be:
  227. * @code void handler(
  228. * const boost::system::error_code& error // Result of operation.
  229. * ); @endcode
  230. */
  231. template <typename ShutdownHandler>
  232. void async_shutdown(ShutdownHandler handler)
  233. {
  234. service_.async_shutdown(impl_, next_layer_, handler);
  235. }
  236. /// Write some data to the stream.
  237. /**
  238. * This function is used to write data on the stream. The function call will
  239. * block until one or more bytes of data has been written successfully, or
  240. * until an error occurs.
  241. *
  242. * @param buffers The data to be written.
  243. *
  244. * @returns The number of bytes written.
  245. *
  246. * @throws boost::system::system_error Thrown on failure.
  247. *
  248. * @note The write_some operation may not transmit all of the data to the
  249. * peer. Consider using the @ref write function if you need to ensure that all
  250. * data is written before the blocking operation completes.
  251. */
  252. template <typename ConstBufferSequence>
  253. std::size_t write_some(const ConstBufferSequence& buffers)
  254. {
  255. boost::system::error_code ec;
  256. std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec);
  257. boost::asio::detail::throw_error(ec);
  258. return s;
  259. }
  260. /// Write some data to the stream.
  261. /**
  262. * This function is used to write data on the stream. The function call will
  263. * block until one or more bytes of data has been written successfully, or
  264. * until an error occurs.
  265. *
  266. * @param buffers The data to be written to the stream.
  267. *
  268. * @param ec Set to indicate what error occurred, if any.
  269. *
  270. * @returns The number of bytes written. Returns 0 if an error occurred.
  271. *
  272. * @note The write_some operation may not transmit all of the data to the
  273. * peer. Consider using the @ref write function if you need to ensure that all
  274. * data is written before the blocking operation completes.
  275. */
  276. template <typename ConstBufferSequence>
  277. std::size_t write_some(const ConstBufferSequence& buffers,
  278. boost::system::error_code& ec)
  279. {
  280. return service_.write_some(impl_, next_layer_, buffers, ec);
  281. }
  282. /// Start an asynchronous write.
  283. /**
  284. * This function is used to asynchronously write one or more bytes of data to
  285. * the stream. The function call always returns immediately.
  286. *
  287. * @param buffers The data to be written to the stream. Although the buffers
  288. * object may be copied as necessary, ownership of the underlying buffers is
  289. * retained by the caller, which must guarantee that they remain valid until
  290. * the handler is called.
  291. *
  292. * @param handler The handler to be called when the write operation completes.
  293. * Copies will be made of the handler as required. The equivalent function
  294. * signature of the handler must be:
  295. * @code void handler(
  296. * const boost::system::error_code& error, // Result of operation.
  297. * std::size_t bytes_transferred // Number of bytes written.
  298. * ); @endcode
  299. *
  300. * @note The async_write_some operation may not transmit all of the data to
  301. * the peer. Consider using the @ref async_write function if you need to
  302. * ensure that all data is written before the blocking operation completes.
  303. */
  304. template <typename ConstBufferSequence, typename WriteHandler>
  305. void async_write_some(const ConstBufferSequence& buffers,
  306. WriteHandler handler)
  307. {
  308. service_.async_write_some(impl_, next_layer_, buffers, handler);
  309. }
  310. /// Read some data from the stream.
  311. /**
  312. * This function is used to read data from the stream. The function call will
  313. * block until one or more bytes of data has been read successfully, or until
  314. * an error occurs.
  315. *
  316. * @param buffers The buffers into which the data will be read.
  317. *
  318. * @returns The number of bytes read.
  319. *
  320. * @throws boost::system::system_error Thrown on failure.
  321. *
  322. * @note The read_some operation may not read all of the requested number of
  323. * bytes. Consider using the @ref read function if you need to ensure that the
  324. * requested amount of data is read before the blocking operation completes.
  325. */
  326. template <typename MutableBufferSequence>
  327. std::size_t read_some(const MutableBufferSequence& buffers)
  328. {
  329. boost::system::error_code ec;
  330. std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec);
  331. boost::asio::detail::throw_error(ec);
  332. return s;
  333. }
  334. /// Read some data from the stream.
  335. /**
  336. * This function is used to read data from the stream. The function call will
  337. * block until one or more bytes of data has been read successfully, or until
  338. * an error occurs.
  339. *
  340. * @param buffers The buffers into which the data will be read.
  341. *
  342. * @param ec Set to indicate what error occurred, if any.
  343. *
  344. * @returns The number of bytes read. Returns 0 if an error occurred.
  345. *
  346. * @note The read_some operation may not read all of the requested number of
  347. * bytes. Consider using the @ref read function if you need to ensure that the
  348. * requested amount of data is read before the blocking operation completes.
  349. */
  350. template <typename MutableBufferSequence>
  351. std::size_t read_some(const MutableBufferSequence& buffers,
  352. boost::system::error_code& ec)
  353. {
  354. return service_.read_some(impl_, next_layer_, buffers, ec);
  355. }
  356. /// Start an asynchronous read.
  357. /**
  358. * This function is used to asynchronously read one or more bytes of data from
  359. * the stream. The function call always returns immediately.
  360. *
  361. * @param buffers The buffers into which the data will be read. Although the
  362. * buffers object may be copied as necessary, ownership of the underlying
  363. * buffers is retained by the caller, which must guarantee that they remain
  364. * valid until the handler is called.
  365. *
  366. * @param handler The handler to be called when the read operation completes.
  367. * Copies will be made of the handler as required. The equivalent function
  368. * signature of the handler must be:
  369. * @code void handler(
  370. * const boost::system::error_code& error, // Result of operation.
  371. * std::size_t bytes_transferred // Number of bytes read.
  372. * ); @endcode
  373. *
  374. * @note The async_read_some operation may not read all of the requested
  375. * number of bytes. Consider using the @ref async_read function if you need to
  376. * ensure that the requested amount of data is read before the asynchronous
  377. * operation completes.
  378. */
  379. template <typename MutableBufferSequence, typename ReadHandler>
  380. void async_read_some(const MutableBufferSequence& buffers,
  381. ReadHandler handler)
  382. {
  383. service_.async_read_some(impl_, next_layer_, buffers, handler);
  384. }
  385. /// Peek at the incoming data on the stream.
  386. /**
  387. * This function is used to peek at the incoming data on the stream, without
  388. * removing it from the input queue. The function call will block until data
  389. * has been read successfully or an error occurs.
  390. *
  391. * @param buffers The buffers into which the data will be read.
  392. *
  393. * @returns The number of bytes read.
  394. *
  395. * @throws boost::system::system_error Thrown on failure.
  396. */
  397. template <typename MutableBufferSequence>
  398. std::size_t peek(const MutableBufferSequence& buffers)
  399. {
  400. boost::system::error_code ec;
  401. std::size_t s = service_.peek(impl_, next_layer_, buffers, ec);
  402. boost::asio::detail::throw_error(ec);
  403. return s;
  404. }
  405. /// Peek at the incoming data on the stream.
  406. /**
  407. * This function is used to peek at the incoming data on the stream, withoutxi
  408. * removing it from the input queue. The function call will block until data
  409. * has been read successfully or an error occurs.
  410. *
  411. * @param buffers The buffers into which the data will be read.
  412. *
  413. * @param ec Set to indicate what error occurred, if any.
  414. *
  415. * @returns The number of bytes read. Returns 0 if an error occurred.
  416. */
  417. template <typename MutableBufferSequence>
  418. std::size_t peek(const MutableBufferSequence& buffers,
  419. boost::system::error_code& ec)
  420. {
  421. return service_.peek(impl_, next_layer_, buffers, ec);
  422. }
  423. /// Determine the amount of data that may be read without blocking.
  424. /**
  425. * This function is used to determine the amount of data, in bytes, that may
  426. * be read from the stream without blocking.
  427. *
  428. * @returns The number of bytes of data that can be read without blocking.
  429. *
  430. * @throws boost::system::system_error Thrown on failure.
  431. */
  432. std::size_t in_avail()
  433. {
  434. boost::system::error_code ec;
  435. std::size_t s = service_.in_avail(impl_, next_layer_, ec);
  436. boost::asio::detail::throw_error(ec);
  437. return s;
  438. }
  439. /// Determine the amount of data that may be read without blocking.
  440. /**
  441. * This function is used to determine the amount of data, in bytes, that may
  442. * be read from the stream without blocking.
  443. *
  444. * @param ec Set to indicate what error occurred, if any.
  445. *
  446. * @returns The number of bytes of data that can be read without blocking.
  447. */
  448. std::size_t in_avail(boost::system::error_code& ec)
  449. {
  450. return service_.in_avail(impl_, next_layer_, ec);
  451. }
  452. private:
  453. /// The next layer.
  454. Stream next_layer_;
  455. /// The backend service implementation.
  456. service_type& service_;
  457. /// The underlying native implementation.
  458. impl_type impl_;
  459. };
  460. } // namespace old
  461. } // namespace ssl
  462. } // namespace asio
  463. } // namespace boost
  464. #include <boost/asio/detail/pop_options.hpp>
  465. #endif // BOOST_ASIO_SSL_OLD_STREAM_HPP