stream.hpp 17 KB

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