basic_socket_iostream.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. //
  2. // basic_socket_iostream.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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. #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
  54. && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  55. typename Clock = boost::posix_time::ptime,
  56. typename WaitTraits = time_traits<Clock>>
  57. #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
  58. // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  59. typename Clock = chrono::steady_clock,
  60. typename WaitTraits = wait_traits<Clock>>
  61. #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
  62. // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  63. class basic_socket_iostream;
  64. #endif // !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
  65. /// Iostream interface for a socket.
  66. #if defined(GENERATING_DOCUMENTATION)
  67. template <typename Protocol,
  68. typename Clock = chrono::steady_clock,
  69. typename WaitTraits = wait_traits<Clock>>
  70. #else // defined(GENERATING_DOCUMENTATION)
  71. template <typename Protocol, typename Clock, typename WaitTraits>
  72. #endif // defined(GENERATING_DOCUMENTATION)
  73. class basic_socket_iostream
  74. : private detail::socket_iostream_base<Protocol, Clock, WaitTraits>,
  75. public std::basic_iostream<char>
  76. {
  77. private:
  78. // These typedefs are intended keep this class's implementation independent
  79. // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
  80. #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
  81. && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  82. typedef WaitTraits traits_helper;
  83. #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
  84. // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  85. typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
  86. #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
  87. // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
  88. public:
  89. /// The protocol type.
  90. typedef Protocol protocol_type;
  91. /// The endpoint type.
  92. typedef typename Protocol::endpoint endpoint_type;
  93. /// The clock type.
  94. typedef Clock clock_type;
  95. #if defined(GENERATING_DOCUMENTATION)
  96. /// (Deprecated: Use time_point.) The time type.
  97. typedef typename WaitTraits::time_type time_type;
  98. /// The time type.
  99. typedef typename WaitTraits::time_point time_point;
  100. /// (Deprecated: Use duration.) The duration type.
  101. typedef typename WaitTraits::duration_type duration_type;
  102. /// The duration type.
  103. typedef typename WaitTraits::duration duration;
  104. #else
  105. # if !defined(BOOST_ASIO_NO_DEPRECATED)
  106. typedef typename traits_helper::time_type time_type;
  107. typedef typename traits_helper::duration_type duration_type;
  108. # endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  109. typedef typename traits_helper::time_type time_point;
  110. typedef typename traits_helper::duration_type duration;
  111. #endif
  112. /// Construct a basic_socket_iostream without establishing a connection.
  113. basic_socket_iostream()
  114. : std::basic_iostream<char>(
  115. &this->detail::socket_iostream_base<
  116. Protocol, Clock, WaitTraits>::streambuf_)
  117. {
  118. this->setf(std::ios_base::unitbuf);
  119. }
  120. /// Construct a basic_socket_iostream from the supplied socket.
  121. explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
  122. : detail::socket_iostream_base<
  123. Protocol, Clock, WaitTraits>(std::move(s)),
  124. std::basic_iostream<char>(
  125. &this->detail::socket_iostream_base<
  126. Protocol, Clock, WaitTraits>::streambuf_)
  127. {
  128. this->setf(std::ios_base::unitbuf);
  129. }
  130. /// Move-construct a basic_socket_iostream from another.
  131. basic_socket_iostream(basic_socket_iostream&& other)
  132. : detail::socket_iostream_base<
  133. Protocol, Clock, WaitTraits>(std::move(other)),
  134. std::basic_iostream<char>(std::move(other))
  135. {
  136. this->set_rdbuf(&this->detail::socket_iostream_base<
  137. Protocol, Clock, WaitTraits>::streambuf_);
  138. }
  139. /// Move-assign a basic_socket_iostream from another.
  140. basic_socket_iostream& operator=(basic_socket_iostream&& other)
  141. {
  142. std::basic_iostream<char>::operator=(std::move(other));
  143. detail::socket_iostream_base<
  144. Protocol, Clock, WaitTraits>::operator=(std::move(other));
  145. return *this;
  146. }
  147. /// Establish a connection to an endpoint corresponding to a resolver query.
  148. /**
  149. * This constructor automatically establishes a connection based on the
  150. * supplied resolver query parameters. The arguments are used to construct
  151. * a resolver query object.
  152. */
  153. template <typename... T>
  154. explicit basic_socket_iostream(T... x)
  155. : std::basic_iostream<char>(
  156. &this->detail::socket_iostream_base<
  157. Protocol, Clock, WaitTraits>::streambuf_)
  158. {
  159. this->setf(std::ios_base::unitbuf);
  160. if (rdbuf()->connect(x...) == 0)
  161. this->setstate(std::ios_base::failbit);
  162. }
  163. /// Establish a connection to an endpoint corresponding to a resolver query.
  164. /**
  165. * This function automatically establishes a connection based on the supplied
  166. * resolver query parameters. The arguments are used to construct a resolver
  167. * query object.
  168. */
  169. template <typename... T>
  170. void connect(T... x)
  171. {
  172. if (rdbuf()->connect(x...) == 0)
  173. this->setstate(std::ios_base::failbit);
  174. }
  175. /// Close the connection.
  176. void close()
  177. {
  178. if (rdbuf()->close() == 0)
  179. this->setstate(std::ios_base::failbit);
  180. }
  181. /// Return a pointer to the underlying streambuf.
  182. basic_socket_streambuf<Protocol, Clock, WaitTraits>* rdbuf() const
  183. {
  184. return const_cast<basic_socket_streambuf<Protocol, Clock, WaitTraits>*>(
  185. &this->detail::socket_iostream_base<
  186. Protocol, Clock, WaitTraits>::streambuf_);
  187. }
  188. /// Get a reference to the underlying socket.
  189. basic_socket<Protocol>& socket()
  190. {
  191. return rdbuf()->socket();
  192. }
  193. /// Get the last error associated with the stream.
  194. /**
  195. * @return An \c error_code corresponding to the last error from the stream.
  196. *
  197. * @par Example
  198. * To print the error associated with a failure to establish a connection:
  199. * @code tcp::iostream s("www.boost.org", "http");
  200. * if (!s)
  201. * {
  202. * std::cout << "Error: " << s.error().message() << std::endl;
  203. * } @endcode
  204. */
  205. const boost::system::error_code& error() const
  206. {
  207. return rdbuf()->error();
  208. }
  209. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  210. /// (Deprecated: Use expiry().) Get the stream's expiry time as an absolute
  211. /// time.
  212. /**
  213. * @return An absolute time value representing the stream's expiry time.
  214. */
  215. time_point expires_at() const
  216. {
  217. return rdbuf()->expires_at();
  218. }
  219. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  220. /// Get the stream's expiry time as an absolute time.
  221. /**
  222. * @return An absolute time value representing the stream's expiry time.
  223. */
  224. time_point expiry() const
  225. {
  226. return rdbuf()->expiry();
  227. }
  228. /// Set the stream's expiry time as an absolute time.
  229. /**
  230. * This function sets the expiry time associated with the stream. Stream
  231. * operations performed after this time (where the operations cannot be
  232. * completed using the internal buffers) will fail with the error
  233. * boost::asio::error::operation_aborted.
  234. *
  235. * @param expiry_time The expiry time to be used for the stream.
  236. */
  237. void expires_at(const time_point& expiry_time)
  238. {
  239. rdbuf()->expires_at(expiry_time);
  240. }
  241. /// Set the stream's expiry time relative to now.
  242. /**
  243. * This function sets the expiry time associated with the stream. Stream
  244. * operations performed after this time (where the operations cannot be
  245. * completed using the internal buffers) will fail with the error
  246. * boost::asio::error::operation_aborted.
  247. *
  248. * @param expiry_time The expiry time to be used for the timer.
  249. */
  250. void expires_after(const duration& expiry_time)
  251. {
  252. rdbuf()->expires_after(expiry_time);
  253. }
  254. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  255. /// (Deprecated: Use expiry().) Get the stream's expiry time relative to now.
  256. /**
  257. * @return A relative time value representing the stream's expiry time.
  258. */
  259. duration expires_from_now() const
  260. {
  261. return rdbuf()->expires_from_now();
  262. }
  263. /// (Deprecated: Use expires_after().) Set the stream's expiry time relative
  264. /// to now.
  265. /**
  266. * This function sets the expiry time associated with the stream. Stream
  267. * operations performed after this time (where the operations cannot be
  268. * completed using the internal buffers) will fail with the error
  269. * boost::asio::error::operation_aborted.
  270. *
  271. * @param expiry_time The expiry time to be used for the timer.
  272. */
  273. void expires_from_now(const duration& expiry_time)
  274. {
  275. rdbuf()->expires_from_now(expiry_time);
  276. }
  277. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  278. private:
  279. // Disallow copying and assignment.
  280. basic_socket_iostream(const basic_socket_iostream&) = delete;
  281. basic_socket_iostream& operator=(
  282. const basic_socket_iostream&) = delete;
  283. };
  284. } // namespace asio
  285. } // namespace boost
  286. #include <boost/asio/detail/pop_options.hpp>
  287. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  288. #endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP