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