]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // basic_socket_iostream.hpp | |
3 | // ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 | // | |
5 | // Copyright (c) 2003-2016 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 |