basic_socket_iostream.hpp 8.7 KB

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