stream.hpp 17 KB

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