basic_socket_iostream.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. //
  2. // basic_socket_iostream.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2025 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_BASIC_SOCKET_IOSTREAM_HPP
  11. #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_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. #if !defined(BOOST_ASIO_NO_IOSTREAM)
  17. #include <istream>
  18. #include <ostream>
  19. #include <boost/asio/basic_socket_streambuf.hpp>
  20. #include <boost/asio/detail/push_options.hpp>
  21. namespace boost {
  22. namespace asio {
  23. namespace detail {
  24. // A separate base class is used to ensure that the streambuf is initialised
  25. // prior to the basic_socket_iostream's basic_iostream base class.
  26. template <typename Protocol, typename Clock, typename WaitTraits>
  27. class socket_iostream_base
  28. {
  29. protected:
  30. socket_iostream_base()
  31. {
  32. }
  33. socket_iostream_base(socket_iostream_base&& other)
  34. : streambuf_(std::move(other.streambuf_))
  35. {
  36. }
  37. socket_iostream_base(basic_stream_socket<Protocol> s)
  38. : streambuf_(std::move(s))
  39. {
  40. }
  41. socket_iostream_base& operator=(socket_iostream_base&& other)
  42. {
  43. streambuf_ = std::move(other.streambuf_);
  44. return *this;
  45. }
  46. basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_;
  47. };
  48. } // namespace detail
  49. #if !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
  50. #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
  51. // Forward declaration with defaulted arguments.
  52. template <typename Protocol,
  53. typename Clock = chrono::steady_clock,
  54. typename WaitTraits = wait_traits<Clock>>
  55. class basic_socket_iostream;
  56. #endif // !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
  57. /// Iostream interface for a socket.
  58. #if defined(GENERATING_DOCUMENTATION)
  59. template <typename Protocol,
  60. typename Clock = chrono::steady_clock,
  61. typename WaitTraits = wait_traits<Clock>>
  62. #else // defined(GENERATING_DOCUMENTATION)
  63. template <typename Protocol, typename Clock, typename WaitTraits>
  64. #endif // defined(GENERATING_DOCUMENTATION)
  65. class basic_socket_iostream
  66. : private detail::socket_iostream_base<Protocol, Clock, WaitTraits>,
  67. public std::basic_iostream<char>
  68. {
  69. private:
  70. typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
  71. public:
  72. /// The protocol type.
  73. typedef Protocol protocol_type;
  74. /// The endpoint type.
  75. typedef typename Protocol::endpoint endpoint_type;
  76. /// The clock type.
  77. typedef Clock clock_type;
  78. #if defined(GENERATING_DOCUMENTATION)
  79. /// The time type.
  80. typedef typename WaitTraits::time_point time_point;
  81. /// The duration type.
  82. typedef typename WaitTraits::duration duration;
  83. #else
  84. typedef typename traits_helper::time_type time_point;
  85. typedef typename traits_helper::duration_type duration;
  86. #endif
  87. /// Construct a basic_socket_iostream without establishing a connection.
  88. basic_socket_iostream()
  89. : std::basic_iostream<char>(
  90. &this->detail::socket_iostream_base<
  91. Protocol, Clock, WaitTraits>::streambuf_)
  92. {
  93. this->setf(std::ios_base::unitbuf);
  94. }
  95. /// Construct a basic_socket_iostream from the supplied socket.
  96. explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
  97. : detail::socket_iostream_base<
  98. Protocol, Clock, WaitTraits>(std::move(s)),
  99. std::basic_iostream<char>(
  100. &this->detail::socket_iostream_base<
  101. Protocol, Clock, WaitTraits>::streambuf_)
  102. {
  103. this->setf(std::ios_base::unitbuf);
  104. }
  105. /// Move-construct a basic_socket_iostream from another.
  106. basic_socket_iostream(basic_socket_iostream&& other)
  107. : detail::socket_iostream_base<
  108. Protocol, Clock, WaitTraits>(std::move(other)),
  109. std::basic_iostream<char>(std::move(other))
  110. {
  111. this->set_rdbuf(&this->detail::socket_iostream_base<
  112. Protocol, Clock, WaitTraits>::streambuf_);
  113. }
  114. /// Move-assign a basic_socket_iostream from another.
  115. basic_socket_iostream& operator=(basic_socket_iostream&& other)
  116. {
  117. std::basic_iostream<char>::operator=(std::move(other));
  118. detail::socket_iostream_base<
  119. Protocol, Clock, WaitTraits>::operator=(std::move(other));
  120. return *this;
  121. }
  122. /// Establish a connection to an endpoint corresponding to a resolver query.
  123. /**
  124. * This constructor automatically establishes a connection based on the
  125. * supplied resolver query parameters. The arguments are used to construct
  126. * a resolver query object.
  127. */
  128. template <typename... T>
  129. explicit basic_socket_iostream(T... x)
  130. : std::basic_iostream<char>(
  131. &this->detail::socket_iostream_base<
  132. Protocol, Clock, WaitTraits>::streambuf_)
  133. {
  134. this->setf(std::ios_base::unitbuf);
  135. if (rdbuf()->connect(x...) == 0)
  136. this->setstate(std::ios_base::failbit);
  137. }
  138. /// Establish a connection to an endpoint corresponding to a resolver query.
  139. /**
  140. * This function automatically establishes a connection based on the supplied
  141. * resolver query parameters. The arguments are used to construct a resolver
  142. * query object.
  143. */
  144. template <typename... T>
  145. void connect(T... x)
  146. {
  147. if (rdbuf()->connect(x...) == 0)
  148. this->setstate(std::ios_base::failbit);
  149. }
  150. /// Close the connection.
  151. void close()
  152. {
  153. if (rdbuf()->close() == 0)
  154. this->setstate(std::ios_base::failbit);
  155. }
  156. /// Return a pointer to the underlying streambuf.
  157. basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const
  158. {
  159. return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(
  160. &this->detail::socket_iostream_base<
  161. Protocol, Clock, WaitTraits>::streambuf_);
  162. }
  163. /// Get a reference to the underlying socket.
  164. basic_socket<Protocol>& socket()
  165. {
  166. return rdbuf()->socket();
  167. }
  168. /// Get the last error associated with the stream.
  169. /**
  170. * @return An \c error_code corresponding to the last error from the stream.
  171. *
  172. * @par Example
  173. * To print the error associated with a failure to establish a connection:
  174. * @code tcp::iostream s("www.boost.org", "http");
  175. * if (!s)
  176. * {
  177. * std::cout << "Error: " << s.error().message() << std::endl;
  178. * } @endcode
  179. */
  180. const boost::system::error_code& error() const
  181. {
  182. return rdbuf()->error();
  183. }
  184. /// Get the stream's expiry time as an absolute time.
  185. /**
  186. * @return An absolute time value representing the stream's expiry time.
  187. */
  188. time_point expiry() const
  189. {
  190. return rdbuf()->expiry();
  191. }
  192. /// Set the stream's expiry time as an absolute time.
  193. /**
  194. * This function sets the expiry time associated with the stream. Stream
  195. * operations performed after this time (where the operations cannot be
  196. * completed using the internal buffers) will fail with the error
  197. * boost::asio::error::operation_aborted.
  198. *
  199. * @param expiry_time The expiry time to be used for the stream.
  200. */
  201. void expires_at(const time_point& expiry_time)
  202. {
  203. rdbuf()->expires_at(expiry_time);
  204. }
  205. /// Set the stream's expiry time relative to now.
  206. /**
  207. * This function sets the expiry time associated with the stream. Stream
  208. * operations performed after this time (where the operations cannot be
  209. * completed using the internal buffers) will fail with the error
  210. * boost::asio::error::operation_aborted.
  211. *
  212. * @param expiry_time The expiry time to be used for the timer.
  213. */
  214. void expires_after(const duration& expiry_time)
  215. {
  216. rdbuf()->expires_after(expiry_time);
  217. }
  218. private:
  219. // Disallow copying and assignment.
  220. basic_socket_iostream(const basic_socket_iostream&) = delete;
  221. basic_socket_iostream& operator=(
  222. const basic_socket_iostream&) = delete;
  223. };
  224. } // namespace asio
  225. } // namespace boost
  226. #include <boost/asio/detail/pop_options.hpp>
  227. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  228. #endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP