basic_socket_iostream.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. //
  2. // basic_socket_iostream.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2015 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/stream_socket_service.hpp>
  21. #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  22. # include <boost/asio/detail/variadic_templates.hpp>
  23. // A macro that should expand to:
  24. // template <typename T1, ..., typename Tn>
  25. // explicit basic_socket_iostream(T1 x1, ..., Tn xn)
  26. // : std::basic_iostream<char>(
  27. // &this->detail::socket_iostream_base<
  28. // Protocol, StreamSocketService, Time,
  29. // TimeTraits, TimerService>::streambuf_)
  30. // {
  31. // if (rdbuf()->connect(x1, ..., xn) == 0)
  32. // this->setstate(std::ios_base::failbit);
  33. // }
  34. // This macro should only persist within this file.
  35. # define BOOST_ASIO_PRIVATE_CTR_DEF(n) \
  36. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  37. explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_PARAMS(n)) \
  38. : std::basic_iostream<char>( \
  39. &this->detail::socket_iostream_base< \
  40. Protocol, StreamSocketService, Time, \
  41. TimeTraits, TimerService>::streambuf_) \
  42. { \
  43. this->setf(std::ios_base::unitbuf); \
  44. if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \
  45. this->setstate(std::ios_base::failbit); \
  46. } \
  47. /**/
  48. // A macro that should expand to:
  49. // template <typename T1, ..., typename Tn>
  50. // void connect(T1 x1, ..., Tn xn)
  51. // {
  52. // if (rdbuf()->connect(x1, ..., xn) == 0)
  53. // this->setstate(std::ios_base::failbit);
  54. // }
  55. // This macro should only persist within this file.
  56. # define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
  57. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  58. void connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \
  59. { \
  60. if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \
  61. this->setstate(std::ios_base::failbit); \
  62. } \
  63. /**/
  64. #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  65. #include <boost/asio/detail/push_options.hpp>
  66. namespace boost {
  67. namespace asio {
  68. namespace detail {
  69. // A separate base class is used to ensure that the streambuf is initialised
  70. // prior to the basic_socket_iostream's basic_iostream base class.
  71. template <typename Protocol, typename StreamSocketService,
  72. typename Time, typename TimeTraits, typename TimerService>
  73. class socket_iostream_base
  74. {
  75. protected:
  76. basic_socket_streambuf<Protocol, StreamSocketService,
  77. Time, TimeTraits, TimerService> streambuf_;
  78. };
  79. }
  80. /// Iostream interface for a socket.
  81. template <typename Protocol,
  82. typename StreamSocketService = stream_socket_service<Protocol>,
  83. #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
  84. || defined(GENERATING_DOCUMENTATION)
  85. typename Time = boost::posix_time::ptime,
  86. typename TimeTraits = boost::asio::time_traits<Time>,
  87. typename TimerService = deadline_timer_service<Time, TimeTraits> >
  88. #else
  89. typename Time = steady_timer::clock_type,
  90. typename TimeTraits = steady_timer::traits_type,
  91. typename TimerService = steady_timer::service_type>
  92. #endif
  93. class basic_socket_iostream
  94. : private detail::socket_iostream_base<Protocol,
  95. StreamSocketService, Time, TimeTraits, TimerService>,
  96. public std::basic_iostream<char>
  97. {
  98. private:
  99. // These typedefs are intended keep this class's implementation independent
  100. // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
  101. #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
  102. typedef TimeTraits traits_helper;
  103. #else
  104. typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
  105. #endif
  106. public:
  107. /// The endpoint type.
  108. typedef typename Protocol::endpoint endpoint_type;
  109. #if defined(GENERATING_DOCUMENTATION)
  110. /// The time type.
  111. typedef typename TimeTraits::time_type time_type;
  112. /// The duration type.
  113. typedef typename TimeTraits::duration_type duration_type;
  114. #else
  115. typedef typename traits_helper::time_type time_type;
  116. typedef typename traits_helper::duration_type duration_type;
  117. #endif
  118. /// Construct a basic_socket_iostream without establishing a connection.
  119. basic_socket_iostream()
  120. : std::basic_iostream<char>(
  121. &this->detail::socket_iostream_base<
  122. Protocol, StreamSocketService, Time,
  123. TimeTraits, TimerService>::streambuf_)
  124. {
  125. this->setf(std::ios_base::unitbuf);
  126. }
  127. #if defined(GENERATING_DOCUMENTATION)
  128. /// Establish a connection to an endpoint corresponding to a resolver query.
  129. /**
  130. * This constructor automatically establishes a connection based on the
  131. * supplied resolver query parameters. The arguments are used to construct
  132. * a resolver query object.
  133. */
  134. template <typename T1, ..., typename TN>
  135. explicit basic_socket_iostream(T1 t1, ..., TN tn);
  136. #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  137. template <typename... T>
  138. explicit basic_socket_iostream(T... x)
  139. : std::basic_iostream<char>(
  140. &this->detail::socket_iostream_base<
  141. Protocol, StreamSocketService, Time,
  142. TimeTraits, TimerService>::streambuf_)
  143. {
  144. this->setf(std::ios_base::unitbuf);
  145. if (rdbuf()->connect(x...) == 0)
  146. this->setstate(std::ios_base::failbit);
  147. }
  148. #else
  149. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CTR_DEF)
  150. #endif
  151. #if defined(GENERATING_DOCUMENTATION)
  152. /// Establish a connection to an endpoint corresponding to a resolver query.
  153. /**
  154. * This function automatically establishes a connection based on the supplied
  155. * resolver query parameters. The arguments are used to construct a resolver
  156. * query object.
  157. */
  158. template <typename T1, ..., typename TN>
  159. void connect(T1 t1, ..., TN tn);
  160. #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  161. template <typename... T>
  162. void connect(T... x)
  163. {
  164. if (rdbuf()->connect(x...) == 0)
  165. this->setstate(std::ios_base::failbit);
  166. }
  167. #else
  168. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF)
  169. #endif
  170. /// Close the connection.
  171. void close()
  172. {
  173. if (rdbuf()->close() == 0)
  174. this->setstate(std::ios_base::failbit);
  175. }
  176. /// Return a pointer to the underlying streambuf.
  177. basic_socket_streambuf<Protocol, StreamSocketService,
  178. Time, TimeTraits, TimerService>* rdbuf() const
  179. {
  180. return const_cast<basic_socket_streambuf<Protocol, StreamSocketService,
  181. Time, TimeTraits, TimerService>*>(
  182. &this->detail::socket_iostream_base<
  183. Protocol, StreamSocketService, Time,
  184. TimeTraits, TimerService>::streambuf_);
  185. }
  186. /// Get the last error associated with the stream.
  187. /**
  188. * @return An \c error_code corresponding to the last error from the stream.
  189. *
  190. * @par Example
  191. * To print the error associated with a failure to establish a connection:
  192. * @code tcp::iostream s("www.boost.org", "http");
  193. * if (!s)
  194. * {
  195. * std::cout << "Error: " << s.error().message() << std::endl;
  196. * } @endcode
  197. */
  198. const boost::system::error_code& error() const
  199. {
  200. return rdbuf()->puberror();
  201. }
  202. /// Get the stream's expiry time as an absolute time.
  203. /**
  204. * @return An absolute time value representing the stream's expiry time.
  205. */
  206. time_type expires_at() const
  207. {
  208. return rdbuf()->expires_at();
  209. }
  210. /// Set the stream's expiry time as an absolute time.
  211. /**
  212. * This function sets the expiry time associated with the stream. Stream
  213. * operations performed after this time (where the operations cannot be
  214. * completed using the internal buffers) will fail with the error
  215. * boost::asio::error::operation_aborted.
  216. *
  217. * @param expiry_time The expiry time to be used for the stream.
  218. */
  219. void expires_at(const time_type& expiry_time)
  220. {
  221. rdbuf()->expires_at(expiry_time);
  222. }
  223. /// Get the timer's expiry time relative to now.
  224. /**
  225. * @return A relative time value representing the stream's expiry time.
  226. */
  227. duration_type expires_from_now() const
  228. {
  229. return rdbuf()->expires_from_now();
  230. }
  231. /// Set the stream's expiry time relative to now.
  232. /**
  233. * This function sets the expiry time associated with the stream. Stream
  234. * operations performed after this time (where the operations cannot be
  235. * completed using the internal buffers) will fail with the error
  236. * boost::asio::error::operation_aborted.
  237. *
  238. * @param expiry_time The expiry time to be used for the timer.
  239. */
  240. void expires_from_now(const duration_type& expiry_time)
  241. {
  242. rdbuf()->expires_from_now(expiry_time);
  243. }
  244. };
  245. } // namespace asio
  246. } // namespace boost
  247. #include <boost/asio/detail/pop_options.hpp>
  248. #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  249. # undef BOOST_ASIO_PRIVATE_CTR_DEF
  250. # undef BOOST_ASIO_PRIVATE_CONNECT_DEF
  251. #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  252. #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
  253. #endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP