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