basic_socket_iostream.hpp 10 KB

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