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