basic_socket_iostream.hpp 13 KB

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