2 // basic_socket_iostream.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~
5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #ifndef BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
12 #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18 #include <boost/asio/detail/config.hpp>
20 #if !defined(BOOST_ASIO_NO_IOSTREAM)
24 #include <boost/asio/basic_socket_streambuf.hpp>
26 #if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
27 # include <boost/asio/stream_socket_service.hpp>
28 #endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
30 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
32 # include <boost/asio/detail/variadic_templates.hpp>
34 // A macro that should expand to:
35 // template <typename T1, ..., typename Tn>
36 // explicit basic_socket_iostream(T1 x1, ..., Tn xn)
37 // : std::basic_iostream<char>(
38 // &this->detail::socket_iostream_base<
39 // Protocol BOOST_ASIO_SVC_TARG, Clock,
40 // WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
42 // if (rdbuf()->connect(x1, ..., xn) == 0)
43 // this->setstate(std::ios_base::failbit);
45 // This macro should only persist within this file.
47 # define BOOST_ASIO_PRIVATE_CTR_DEF(n) \
48 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
49 explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
50 : std::basic_iostream<char>( \
51 &this->detail::socket_iostream_base< \
52 Protocol BOOST_ASIO_SVC_TARG, Clock, \
53 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) \
55 this->setf(std::ios_base::unitbuf); \
56 if (rdbuf()->connect(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
57 this->setstate(std::ios_base::failbit); \
61 // A macro that should expand to:
62 // template <typename T1, ..., typename Tn>
63 // void connect(T1 x1, ..., Tn xn)
65 // if (rdbuf()->connect(x1, ..., xn) == 0)
66 // this->setstate(std::ios_base::failbit);
68 // This macro should only persist within this file.
70 # define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
71 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
72 void connect(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
74 if (rdbuf()->connect(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
75 this->setstate(std::ios_base::failbit); \
79 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
81 #include <boost/asio/detail/push_options.hpp>
87 // A separate base class is used to ensure that the streambuf is initialised
88 // prior to the basic_socket_iostream's basic_iostream base class.
89 template <typename Protocol BOOST_ASIO_SVC_TPARAM,
90 typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1>
91 class socket_iostream_base
94 socket_iostream_base()
98 #if defined(BOOST_ASIO_HAS_MOVE)
99 socket_iostream_base(socket_iostream_base&& other)
100 : streambuf_(std::move(other.streambuf_))
104 socket_iostream_base(basic_stream_socket<Protocol> s)
105 : streambuf_(std::move(s))
109 socket_iostream_base& operator=(socket_iostream_base&& other)
111 streambuf_ = std::move(other.streambuf_);
114 #endif // defined(BOOST_ASIO_HAS_MOVE)
116 basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
117 Clock, WaitTraits BOOST_ASIO_SVC_TARG1> streambuf_;
120 } // namespace detail
122 #if !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
123 #define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
125 // Forward declaration with defaulted arguments.
126 template <typename Protocol
127 BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
128 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
129 typename Clock = boost::posix_time::ptime,
130 typename WaitTraits = time_traits<Clock>
131 BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
133 typename Clock = chrono::steady_clock,
134 typename WaitTraits = wait_traits<Clock>
135 BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
137 class basic_socket_iostream;
139 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
141 /// Iostream interface for a socket.
142 #if defined(GENERATING_DOCUMENTATION)
143 template <typename Protocol,
144 typename Clock = chrono::steady_clock,
145 typename WaitTraits = wait_traits<Clock> >
146 #else // defined(GENERATING_DOCUMENTATION)
147 template <typename Protocol BOOST_ASIO_SVC_TPARAM,
148 typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1>
149 #endif // defined(GENERATING_DOCUMENTATION)
150 class basic_socket_iostream
151 : private detail::socket_iostream_base<Protocol
152 BOOST_ASIO_SVC_TARG, Clock, WaitTraits BOOST_ASIO_SVC_TARG1>,
153 public std::basic_iostream<char>
156 // These typedefs are intended keep this class's implementation independent
157 // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
158 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
159 typedef WaitTraits traits_helper;
161 typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
165 /// The protocol type.
166 typedef Protocol protocol_type;
168 /// The endpoint type.
169 typedef typename Protocol::endpoint endpoint_type;
172 typedef Clock clock_type;
174 #if defined(GENERATING_DOCUMENTATION)
175 /// (Deprecated: Use time_point.) The time type.
176 typedef typename WaitTraits::time_type time_type;
179 typedef typename WaitTraits::time_point time_point;
181 /// (Deprecated: Use duration.) The duration type.
182 typedef typename WaitTraits::duration_type duration_type;
184 /// The duration type.
185 typedef typename WaitTraits::duration duration;
187 # if !defined(BOOST_ASIO_NO_DEPRECATED)
188 typedef typename traits_helper::time_type time_type;
189 typedef typename traits_helper::duration_type duration_type;
190 # endif // !defined(BOOST_ASIO_NO_DEPRECATED)
191 typedef typename traits_helper::time_type time_point;
192 typedef typename traits_helper::duration_type duration;
195 /// Construct a basic_socket_iostream without establishing a connection.
196 basic_socket_iostream()
197 : std::basic_iostream<char>(
198 &this->detail::socket_iostream_base<
199 Protocol BOOST_ASIO_SVC_TARG, Clock,
200 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
202 this->setf(std::ios_base::unitbuf);
205 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
206 /// Construct a basic_socket_iostream from the supplied socket.
207 explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
208 : detail::socket_iostream_base<
209 Protocol BOOST_ASIO_SVC_TARG, Clock,
210 WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(s)),
211 std::basic_iostream<char>(
212 &this->detail::socket_iostream_base<
213 Protocol BOOST_ASIO_SVC_TARG, Clock,
214 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
216 this->setf(std::ios_base::unitbuf);
219 #if defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE) \
220 || defined(GENERATING_DOCUMENTATION)
221 /// Move-construct a basic_socket_iostream from another.
222 basic_socket_iostream(basic_socket_iostream&& other)
223 : detail::socket_iostream_base<
224 Protocol BOOST_ASIO_SVC_TARG, Clock,
225 WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(other)),
226 std::basic_iostream<char>(std::move(other))
228 this->set_rdbuf(&this->detail::socket_iostream_base<
229 Protocol BOOST_ASIO_SVC_TARG, Clock,
230 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_);
233 /// Move-assign a basic_socket_iostream from another.
234 basic_socket_iostream& operator=(basic_socket_iostream&& other)
236 std::basic_iostream<char>::operator=(std::move(other));
237 detail::socket_iostream_base<
238 Protocol BOOST_ASIO_SVC_TARG, Clock,
239 WaitTraits BOOST_ASIO_SVC_TARG1>::operator=(std::move(other));
242 #endif // defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
243 // || defined(GENERATING_DOCUMENTATION)
244 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
246 #if defined(GENERATING_DOCUMENTATION)
247 /// Establish a connection to an endpoint corresponding to a resolver query.
249 * This constructor automatically establishes a connection based on the
250 * supplied resolver query parameters. The arguments are used to construct
251 * a resolver query object.
253 template <typename T1, ..., typename TN>
254 explicit basic_socket_iostream(T1 t1, ..., TN tn);
255 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
256 template <typename... T>
257 explicit basic_socket_iostream(T... x)
258 : std::basic_iostream<char>(
259 &this->detail::socket_iostream_base<
260 Protocol BOOST_ASIO_SVC_TARG, Clock,
261 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
263 this->setf(std::ios_base::unitbuf);
264 if (rdbuf()->connect(x...) == 0)
265 this->setstate(std::ios_base::failbit);
268 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CTR_DEF)
271 #if defined(GENERATING_DOCUMENTATION)
272 /// Establish a connection to an endpoint corresponding to a resolver query.
274 * This function automatically establishes a connection based on the supplied
275 * resolver query parameters. The arguments are used to construct a resolver
278 template <typename T1, ..., typename TN>
279 void connect(T1 t1, ..., TN tn);
280 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
281 template <typename... T>
284 if (rdbuf()->connect(x...) == 0)
285 this->setstate(std::ios_base::failbit);
288 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF)
291 /// Close the connection.
294 if (rdbuf()->close() == 0)
295 this->setstate(std::ios_base::failbit);
298 /// Return a pointer to the underlying streambuf.
299 basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
300 Clock, WaitTraits BOOST_ASIO_SVC_TARG1>* rdbuf() const
302 return const_cast<basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
303 Clock, WaitTraits BOOST_ASIO_SVC_TARG1>*>(
304 &this->detail::socket_iostream_base<
305 Protocol BOOST_ASIO_SVC_TARG, Clock,
306 WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_);
309 /// Get a reference to the underlying socket.
310 basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket()
312 return rdbuf()->socket();
315 /// Get the last error associated with the stream.
317 * @return An \c error_code corresponding to the last error from the stream.
320 * To print the error associated with a failure to establish a connection:
321 * @code tcp::iostream s("www.boost.org", "http");
324 * std::cout << "Error: " << s.error().message() << std::endl;
327 const boost::system::error_code& error() const
329 return rdbuf()->error();
332 #if !defined(BOOST_ASIO_NO_DEPRECATED)
333 /// (Deprecated: Use expiry().) Get the stream's expiry time as an absolute
336 * @return An absolute time value representing the stream's expiry time.
338 time_point expires_at() const
340 return rdbuf()->expires_at();
342 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
344 /// Get the stream's expiry time as an absolute time.
346 * @return An absolute time value representing the stream's expiry time.
348 time_point expiry() const
350 return rdbuf()->expiry();
353 /// Set the stream's expiry time as an absolute time.
355 * This function sets the expiry time associated with the stream. Stream
356 * operations performed after this time (where the operations cannot be
357 * completed using the internal buffers) will fail with the error
358 * boost::asio::error::operation_aborted.
360 * @param expiry_time The expiry time to be used for the stream.
362 void expires_at(const time_point& expiry_time)
364 rdbuf()->expires_at(expiry_time);
367 /// Set the stream's expiry time relative to now.
369 * This function sets the expiry time associated with the stream. Stream
370 * operations performed after this time (where the operations cannot be
371 * completed using the internal buffers) will fail with the error
372 * boost::asio::error::operation_aborted.
374 * @param expiry_time The expiry time to be used for the timer.
376 void expires_after(const duration& expiry_time)
378 rdbuf()->expires_after(expiry_time);
381 #if !defined(BOOST_ASIO_NO_DEPRECATED)
382 /// (Deprecated: Use expiry().) Get the stream's expiry time relative to now.
384 * @return A relative time value representing the stream's expiry time.
386 duration expires_from_now() const
388 return rdbuf()->expires_from_now();
391 /// (Deprecated: Use expires_after().) Set the stream's expiry time relative
394 * This function sets the expiry time associated with the stream. Stream
395 * operations performed after this time (where the operations cannot be
396 * completed using the internal buffers) will fail with the error
397 * boost::asio::error::operation_aborted.
399 * @param expiry_time The expiry time to be used for the timer.
401 void expires_from_now(const duration& expiry_time)
403 rdbuf()->expires_from_now(expiry_time);
405 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
408 // Disallow copying and assignment.
409 basic_socket_iostream(const basic_socket_iostream&) BOOST_ASIO_DELETED;
410 basic_socket_iostream& operator=(
411 const basic_socket_iostream&) BOOST_ASIO_DELETED;
417 #include <boost/asio/detail/pop_options.hpp>
419 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
420 # undef BOOST_ASIO_PRIVATE_CTR_DEF
421 # undef BOOST_ASIO_PRIVATE_CONNECT_DEF
422 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
424 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
426 #endif // BOOST_ASIO_BASIC_SOCKET_IOSTREAM_HPP