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. |
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> |
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. |
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, |
203 | 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 | */ |
224 | 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 | */ |
233 | 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 | */ |
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 | */ |
256 | 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 | */ |
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 | |