]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // |
2 | // impl/connect.hpp | |
3 | // ~~~~~~~~~~~~~~~~ | |
4 | // | |
92f5a8d4 | 5 | // Copyright (c) 2003-2019 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_IMPL_CONNECT_HPP | |
12 | #define BOOST_ASIO_IMPL_CONNECT_HPP | |
13 | ||
14 | #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 | # pragma once | |
16 | #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | ||
18 | #include <algorithm> | |
19 | #include <boost/asio/associated_allocator.hpp> | |
20 | #include <boost/asio/associated_executor.hpp> | |
21 | #include <boost/asio/detail/bind_handler.hpp> | |
22 | #include <boost/asio/detail/handler_alloc_helpers.hpp> | |
23 | #include <boost/asio/detail/handler_cont_helpers.hpp> | |
24 | #include <boost/asio/detail/handler_invoke_helpers.hpp> | |
25 | #include <boost/asio/detail/handler_type_requirements.hpp> | |
92f5a8d4 | 26 | #include <boost/asio/detail/non_const_lvalue.hpp> |
b32b8144 FG |
27 | #include <boost/asio/detail/throw_error.hpp> |
28 | #include <boost/asio/error.hpp> | |
29 | #include <boost/asio/post.hpp> | |
30 | ||
31 | #include <boost/asio/detail/push_options.hpp> | |
32 | ||
33 | namespace boost { | |
34 | namespace asio { | |
35 | ||
36 | namespace detail | |
37 | { | |
38 | struct default_connect_condition | |
39 | { | |
40 | template <typename Endpoint> | |
41 | bool operator()(const boost::system::error_code&, const Endpoint&) | |
42 | { | |
43 | return true; | |
44 | } | |
45 | }; | |
46 | ||
47 | template <typename Protocol, typename Iterator> | |
48 | inline typename Protocol::endpoint deref_connect_result( | |
49 | Iterator iter, boost::system::error_code& ec) | |
50 | { | |
51 | return ec ? typename Protocol::endpoint() : *iter; | |
52 | } | |
53 | ||
54 | template <typename T, typename Iterator> | |
55 | struct legacy_connect_condition_helper : T | |
56 | { | |
57 | typedef char (*fallback_func_type)(...); | |
58 | operator fallback_func_type() const; | |
59 | }; | |
60 | ||
61 | template <typename R, typename Arg1, typename Arg2, typename Iterator> | |
62 | struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator> | |
63 | { | |
64 | R operator()(Arg1, Arg2) const; | |
65 | char operator()(...) const; | |
66 | }; | |
67 | ||
68 | template <typename T, typename Iterator> | |
69 | struct is_legacy_connect_condition | |
70 | { | |
71 | static char asio_connect_condition_check(char); | |
72 | static char (&asio_connect_condition_check(Iterator))[2]; | |
73 | ||
74 | static const bool value = | |
75 | sizeof(asio_connect_condition_check( | |
76 | (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))( | |
77 | *static_cast<const boost::system::error_code*>(0), | |
78 | *static_cast<const Iterator*>(0)))) != 1; | |
79 | }; | |
80 | ||
81 | template <typename ConnectCondition, typename Iterator> | |
82 | inline Iterator call_connect_condition(ConnectCondition& connect_condition, | |
83 | const boost::system::error_code& ec, Iterator next, Iterator end, | |
84 | typename enable_if<is_legacy_connect_condition< | |
85 | ConnectCondition, Iterator>::value>::type* = 0) | |
86 | { | |
87 | if (next != end) | |
88 | return connect_condition(ec, next); | |
89 | return end; | |
90 | } | |
91 | ||
92 | template <typename ConnectCondition, typename Iterator> | |
93 | inline Iterator call_connect_condition(ConnectCondition& connect_condition, | |
94 | const boost::system::error_code& ec, Iterator next, Iterator end, | |
95 | typename enable_if<!is_legacy_connect_condition< | |
96 | ConnectCondition, Iterator>::value>::type* = 0) | |
97 | { | |
98 | for (;next != end; ++next) | |
99 | if (connect_condition(ec, *next)) | |
100 | return next; | |
101 | return end; | |
102 | } | |
103 | } | |
104 | ||
92f5a8d4 TL |
105 | template <typename Protocol, typename Executor, typename EndpointSequence> |
106 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, | |
b32b8144 FG |
107 | const EndpointSequence& endpoints, |
108 | typename enable_if<is_endpoint_sequence< | |
109 | EndpointSequence>::value>::type*) | |
110 | { | |
111 | boost::system::error_code ec; | |
112 | typename Protocol::endpoint result = connect(s, endpoints, ec); | |
113 | boost::asio::detail::throw_error(ec, "connect"); | |
114 | return result; | |
115 | } | |
116 | ||
92f5a8d4 TL |
117 | template <typename Protocol, typename Executor, typename EndpointSequence> |
118 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, | |
b32b8144 FG |
119 | const EndpointSequence& endpoints, boost::system::error_code& ec, |
120 | typename enable_if<is_endpoint_sequence< | |
121 | EndpointSequence>::value>::type*) | |
122 | { | |
123 | return detail::deref_connect_result<Protocol>( | |
124 | connect(s, endpoints.begin(), endpoints.end(), | |
125 | detail::default_connect_condition(), ec), ec); | |
126 | } | |
127 | ||
128 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
92f5a8d4 TL |
129 | template <typename Protocol, typename Executor, typename Iterator> |
130 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, | |
b32b8144 FG |
131 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) |
132 | { | |
133 | boost::system::error_code ec; | |
134 | Iterator result = connect(s, begin, ec); | |
135 | boost::asio::detail::throw_error(ec, "connect"); | |
136 | return result; | |
137 | } | |
138 | ||
92f5a8d4 TL |
139 | template <typename Protocol, typename Executor, typename Iterator> |
140 | inline Iterator connect(basic_socket<Protocol, Executor>& s, | |
b32b8144 FG |
141 | Iterator begin, boost::system::error_code& ec, |
142 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) | |
143 | { | |
144 | return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); | |
145 | } | |
146 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
147 | ||
92f5a8d4 TL |
148 | template <typename Protocol, typename Executor, typename Iterator> |
149 | Iterator connect(basic_socket<Protocol, Executor>& s, | |
b32b8144 FG |
150 | Iterator begin, Iterator end) |
151 | { | |
152 | boost::system::error_code ec; | |
153 | Iterator result = connect(s, begin, end, ec); | |
154 | boost::asio::detail::throw_error(ec, "connect"); | |
155 | return result; | |
156 | } | |
157 | ||
92f5a8d4 TL |
158 | template <typename Protocol, typename Executor, typename Iterator> |
159 | inline Iterator connect(basic_socket<Protocol, Executor>& s, | |
b32b8144 FG |
160 | Iterator begin, Iterator end, boost::system::error_code& ec) |
161 | { | |
162 | return connect(s, begin, end, detail::default_connect_condition(), ec); | |
163 | } | |
164 | ||
92f5a8d4 | 165 | template <typename Protocol, typename Executor, |
b32b8144 | 166 | typename EndpointSequence, typename ConnectCondition> |
92f5a8d4 | 167 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
168 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
169 | typename enable_if<is_endpoint_sequence< | |
170 | EndpointSequence>::value>::type*) | |
171 | { | |
172 | boost::system::error_code ec; | |
173 | typename Protocol::endpoint result = connect( | |
174 | s, endpoints, connect_condition, ec); | |
175 | boost::asio::detail::throw_error(ec, "connect"); | |
176 | return result; | |
177 | } | |
178 | ||
92f5a8d4 | 179 | template <typename Protocol, typename Executor, |
b32b8144 | 180 | typename EndpointSequence, typename ConnectCondition> |
92f5a8d4 | 181 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
182 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
183 | boost::system::error_code& ec, | |
184 | typename enable_if<is_endpoint_sequence< | |
185 | EndpointSequence>::value>::type*) | |
186 | { | |
187 | return detail::deref_connect_result<Protocol>( | |
188 | connect(s, endpoints.begin(), endpoints.end(), | |
189 | connect_condition, ec), ec); | |
190 | } | |
191 | ||
192 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
92f5a8d4 | 193 | template <typename Protocol, typename Executor, |
b32b8144 | 194 | typename Iterator, typename ConnectCondition> |
92f5a8d4 | 195 | Iterator connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
196 | Iterator begin, ConnectCondition connect_condition, |
197 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) | |
198 | { | |
199 | boost::system::error_code ec; | |
200 | Iterator result = connect(s, begin, connect_condition, ec); | |
201 | boost::asio::detail::throw_error(ec, "connect"); | |
202 | return result; | |
203 | } | |
204 | ||
92f5a8d4 | 205 | template <typename Protocol, typename Executor, |
b32b8144 | 206 | typename Iterator, typename ConnectCondition> |
92f5a8d4 | 207 | inline Iterator connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
208 | Iterator begin, ConnectCondition connect_condition, |
209 | boost::system::error_code& ec, | |
210 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) | |
211 | { | |
212 | return connect(s, begin, Iterator(), connect_condition, ec); | |
213 | } | |
214 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
215 | ||
92f5a8d4 | 216 | template <typename Protocol, typename Executor, |
b32b8144 | 217 | typename Iterator, typename ConnectCondition> |
92f5a8d4 TL |
218 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
219 | Iterator end, ConnectCondition connect_condition) | |
b32b8144 FG |
220 | { |
221 | boost::system::error_code ec; | |
222 | Iterator result = connect(s, begin, end, connect_condition, ec); | |
223 | boost::asio::detail::throw_error(ec, "connect"); | |
224 | return result; | |
225 | } | |
226 | ||
92f5a8d4 | 227 | template <typename Protocol, typename Executor, |
b32b8144 | 228 | typename Iterator, typename ConnectCondition> |
92f5a8d4 TL |
229 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
230 | Iterator end, ConnectCondition connect_condition, | |
b32b8144 FG |
231 | boost::system::error_code& ec) |
232 | { | |
233 | ec = boost::system::error_code(); | |
234 | ||
235 | for (Iterator iter = begin; iter != end; ++iter) | |
236 | { | |
237 | iter = (detail::call_connect_condition(connect_condition, ec, iter, end)); | |
238 | if (iter != end) | |
239 | { | |
240 | s.close(ec); | |
241 | s.connect(*iter, ec); | |
242 | if (!ec) | |
243 | return iter; | |
244 | } | |
245 | else | |
246 | break; | |
247 | } | |
248 | ||
249 | if (!ec) | |
250 | ec = boost::asio::error::not_found; | |
251 | ||
252 | return end; | |
253 | } | |
254 | ||
255 | namespace detail | |
256 | { | |
257 | // Enable the empty base class optimisation for the connect condition. | |
258 | template <typename ConnectCondition> | |
259 | class base_from_connect_condition | |
260 | { | |
261 | protected: | |
262 | explicit base_from_connect_condition( | |
263 | const ConnectCondition& connect_condition) | |
264 | : connect_condition_(connect_condition) | |
265 | { | |
266 | } | |
267 | ||
268 | template <typename Iterator> | |
269 | void check_condition(const boost::system::error_code& ec, | |
270 | Iterator& iter, Iterator& end) | |
271 | { | |
272 | iter = detail::call_connect_condition(connect_condition_, ec, iter, end); | |
273 | } | |
274 | ||
275 | private: | |
276 | ConnectCondition connect_condition_; | |
277 | }; | |
278 | ||
279 | // The default_connect_condition implementation is essentially a no-op. This | |
280 | // template specialisation lets us eliminate all costs associated with it. | |
281 | template <> | |
282 | class base_from_connect_condition<default_connect_condition> | |
283 | { | |
284 | protected: | |
285 | explicit base_from_connect_condition(const default_connect_condition&) | |
286 | { | |
287 | } | |
288 | ||
289 | template <typename Iterator> | |
290 | void check_condition(const boost::system::error_code&, Iterator&, Iterator&) | |
291 | { | |
292 | } | |
293 | }; | |
294 | ||
92f5a8d4 TL |
295 | template <typename Protocol, typename Executor, typename EndpointSequence, |
296 | typename ConnectCondition, typename RangeConnectHandler> | |
b32b8144 FG |
297 | class range_connect_op : base_from_connect_condition<ConnectCondition> |
298 | { | |
299 | public: | |
92f5a8d4 | 300 | range_connect_op(basic_socket<Protocol, Executor>& sock, |
b32b8144 FG |
301 | const EndpointSequence& endpoints, |
302 | const ConnectCondition& connect_condition, | |
303 | RangeConnectHandler& handler) | |
304 | : base_from_connect_condition<ConnectCondition>(connect_condition), | |
305 | socket_(sock), | |
306 | endpoints_(endpoints), | |
307 | index_(0), | |
308 | start_(0), | |
309 | handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(handler)) | |
310 | { | |
311 | } | |
312 | ||
313 | #if defined(BOOST_ASIO_HAS_MOVE) | |
314 | range_connect_op(const range_connect_op& other) | |
315 | : base_from_connect_condition<ConnectCondition>(other), | |
316 | socket_(other.socket_), | |
317 | endpoints_(other.endpoints_), | |
318 | index_(other.index_), | |
319 | start_(other.start_), | |
320 | handler_(other.handler_) | |
321 | { | |
322 | } | |
323 | ||
324 | range_connect_op(range_connect_op&& other) | |
325 | : base_from_connect_condition<ConnectCondition>(other), | |
326 | socket_(other.socket_), | |
327 | endpoints_(other.endpoints_), | |
328 | index_(other.index_), | |
329 | start_(other.start_), | |
330 | handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_)) | |
331 | { | |
332 | } | |
333 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
334 | ||
335 | void operator()(boost::system::error_code ec, int start = 0) | |
336 | { | |
92f5a8d4 TL |
337 | this->process(ec, start, |
338 | const_cast<const EndpointSequence&>(endpoints_).begin(), | |
339 | const_cast<const EndpointSequence&>(endpoints_).end()); | |
340 | } | |
341 | ||
342 | //private: | |
343 | template <typename Iterator> | |
344 | void process(boost::system::error_code ec, | |
345 | int start, Iterator begin, Iterator end) | |
346 | { | |
347 | Iterator iter = begin; | |
b32b8144 | 348 | std::advance(iter, index_); |
b32b8144 FG |
349 | |
350 | switch (start_ = start) | |
351 | { | |
352 | case 1: | |
353 | for (;;) | |
354 | { | |
355 | this->check_condition(ec, iter, end); | |
356 | index_ = std::distance(begin, iter); | |
357 | ||
358 | if (iter != end) | |
359 | { | |
360 | socket_.close(ec); | |
361 | socket_.async_connect(*iter, | |
362 | BOOST_ASIO_MOVE_CAST(range_connect_op)(*this)); | |
363 | return; | |
364 | } | |
365 | ||
366 | if (start) | |
367 | { | |
368 | ec = boost::asio::error::not_found; | |
369 | boost::asio::post(socket_.get_executor(), | |
370 | detail::bind_handler( | |
371 | BOOST_ASIO_MOVE_CAST(range_connect_op)(*this), ec)); | |
372 | return; | |
373 | } | |
374 | ||
92f5a8d4 | 375 | /* fall-through */ default: |
b32b8144 FG |
376 | |
377 | if (iter == end) | |
378 | break; | |
379 | ||
380 | if (!socket_.is_open()) | |
381 | { | |
382 | ec = boost::asio::error::operation_aborted; | |
383 | break; | |
384 | } | |
385 | ||
386 | if (!ec) | |
387 | break; | |
388 | ||
389 | ++iter; | |
390 | ++index_; | |
391 | } | |
392 | ||
393 | handler_(static_cast<const boost::system::error_code&>(ec), | |
394 | static_cast<const typename Protocol::endpoint&>( | |
395 | ec || iter == end ? typename Protocol::endpoint() : *iter)); | |
396 | } | |
397 | } | |
398 | ||
92f5a8d4 | 399 | basic_socket<Protocol, Executor>& socket_; |
b32b8144 FG |
400 | EndpointSequence endpoints_; |
401 | std::size_t index_; | |
402 | int start_; | |
403 | RangeConnectHandler handler_; | |
404 | }; | |
405 | ||
92f5a8d4 TL |
406 | template <typename Protocol, typename Executor, typename EndpointSequence, |
407 | typename ConnectCondition, typename RangeConnectHandler> | |
b32b8144 | 408 | inline void* asio_handler_allocate(std::size_t size, |
92f5a8d4 | 409 | range_connect_op<Protocol, Executor, EndpointSequence, |
b32b8144 FG |
410 | ConnectCondition, RangeConnectHandler>* this_handler) |
411 | { | |
412 | return boost_asio_handler_alloc_helpers::allocate( | |
413 | size, this_handler->handler_); | |
414 | } | |
415 | ||
92f5a8d4 TL |
416 | template <typename Protocol, typename Executor, typename EndpointSequence, |
417 | typename ConnectCondition, typename RangeConnectHandler> | |
b32b8144 | 418 | inline void asio_handler_deallocate(void* pointer, std::size_t size, |
92f5a8d4 | 419 | range_connect_op<Protocol, Executor, EndpointSequence, |
b32b8144 FG |
420 | ConnectCondition, RangeConnectHandler>* this_handler) |
421 | { | |
422 | boost_asio_handler_alloc_helpers::deallocate( | |
423 | pointer, size, this_handler->handler_); | |
424 | } | |
425 | ||
92f5a8d4 TL |
426 | template <typename Protocol, typename Executor, typename EndpointSequence, |
427 | typename ConnectCondition, typename RangeConnectHandler> | |
b32b8144 | 428 | inline bool asio_handler_is_continuation( |
92f5a8d4 | 429 | range_connect_op<Protocol, Executor, EndpointSequence, |
b32b8144 FG |
430 | ConnectCondition, RangeConnectHandler>* this_handler) |
431 | { | |
432 | return boost_asio_handler_cont_helpers::is_continuation( | |
433 | this_handler->handler_); | |
434 | } | |
435 | ||
92f5a8d4 TL |
436 | template <typename Function, typename Executor, typename Protocol, |
437 | typename EndpointSequence, typename ConnectCondition, | |
438 | typename RangeConnectHandler> | |
b32b8144 | 439 | inline void asio_handler_invoke(Function& function, |
92f5a8d4 | 440 | range_connect_op<Protocol, Executor, EndpointSequence, |
b32b8144 FG |
441 | ConnectCondition, RangeConnectHandler>* this_handler) |
442 | { | |
443 | boost_asio_handler_invoke_helpers::invoke( | |
444 | function, this_handler->handler_); | |
445 | } | |
446 | ||
92f5a8d4 TL |
447 | template <typename Function, typename Executor, typename Protocol, |
448 | typename EndpointSequence, typename ConnectCondition, | |
449 | typename RangeConnectHandler> | |
b32b8144 | 450 | inline void asio_handler_invoke(const Function& function, |
92f5a8d4 | 451 | range_connect_op<Protocol, Executor, EndpointSequence, |
b32b8144 FG |
452 | ConnectCondition, RangeConnectHandler>* this_handler) |
453 | { | |
454 | boost_asio_handler_invoke_helpers::invoke( | |
455 | function, this_handler->handler_); | |
456 | } | |
457 | ||
92f5a8d4 TL |
458 | template <typename Protocol, typename Executor> |
459 | class initiate_async_range_connect | |
460 | { | |
461 | public: | |
462 | typedef Executor executor_type; | |
463 | ||
464 | explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s) | |
465 | : socket_(s) | |
466 | { | |
467 | } | |
468 | ||
469 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
470 | { | |
471 | return socket_.get_executor(); | |
472 | } | |
473 | ||
474 | template <typename RangeConnectHandler, | |
475 | typename EndpointSequence, typename ConnectCondition> | |
476 | void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, | |
477 | const EndpointSequence& endpoints, | |
478 | const ConnectCondition& connect_condition) const | |
479 | { | |
480 | // If you get an error on the following line it means that your | |
481 | // handler does not meet the documented type requirements for an | |
482 | // RangeConnectHandler. | |
483 | BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler, | |
484 | handler, typename Protocol::endpoint) type_check; | |
485 | ||
486 | non_const_lvalue<RangeConnectHandler> handler2(handler); | |
487 | range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, | |
488 | typename decay<RangeConnectHandler>::type>(socket_, endpoints, | |
489 | connect_condition, handler2.value)(boost::system::error_code(), 1); | |
490 | } | |
491 | ||
492 | private: | |
493 | basic_socket<Protocol, Executor>& socket_; | |
494 | }; | |
495 | ||
496 | template <typename Protocol, typename Executor, typename Iterator, | |
b32b8144 FG |
497 | typename ConnectCondition, typename IteratorConnectHandler> |
498 | class iterator_connect_op : base_from_connect_condition<ConnectCondition> | |
499 | { | |
500 | public: | |
92f5a8d4 | 501 | iterator_connect_op(basic_socket<Protocol, Executor>& sock, |
b32b8144 FG |
502 | const Iterator& begin, const Iterator& end, |
503 | const ConnectCondition& connect_condition, | |
504 | IteratorConnectHandler& handler) | |
505 | : base_from_connect_condition<ConnectCondition>(connect_condition), | |
506 | socket_(sock), | |
507 | iter_(begin), | |
508 | end_(end), | |
509 | start_(0), | |
510 | handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(handler)) | |
511 | { | |
512 | } | |
513 | ||
514 | #if defined(BOOST_ASIO_HAS_MOVE) | |
515 | iterator_connect_op(const iterator_connect_op& other) | |
516 | : base_from_connect_condition<ConnectCondition>(other), | |
517 | socket_(other.socket_), | |
518 | iter_(other.iter_), | |
519 | end_(other.end_), | |
520 | start_(other.start_), | |
521 | handler_(other.handler_) | |
522 | { | |
523 | } | |
524 | ||
525 | iterator_connect_op(iterator_connect_op&& other) | |
526 | : base_from_connect_condition<ConnectCondition>(other), | |
527 | socket_(other.socket_), | |
528 | iter_(other.iter_), | |
529 | end_(other.end_), | |
530 | start_(other.start_), | |
531 | handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_)) | |
532 | { | |
533 | } | |
534 | #endif // defined(BOOST_ASIO_HAS_MOVE) | |
535 | ||
536 | void operator()(boost::system::error_code ec, int start = 0) | |
537 | { | |
538 | switch (start_ = start) | |
539 | { | |
540 | case 1: | |
541 | for (;;) | |
542 | { | |
543 | this->check_condition(ec, iter_, end_); | |
544 | ||
545 | if (iter_ != end_) | |
546 | { | |
547 | socket_.close(ec); | |
548 | socket_.async_connect(*iter_, | |
549 | BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this)); | |
550 | return; | |
551 | } | |
552 | ||
553 | if (start) | |
554 | { | |
555 | ec = boost::asio::error::not_found; | |
556 | boost::asio::post(socket_.get_executor(), | |
557 | detail::bind_handler( | |
558 | BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec)); | |
559 | return; | |
560 | } | |
561 | ||
92f5a8d4 | 562 | /* fall-through */ default: |
b32b8144 FG |
563 | |
564 | if (iter_ == end_) | |
565 | break; | |
566 | ||
567 | if (!socket_.is_open()) | |
568 | { | |
569 | ec = boost::asio::error::operation_aborted; | |
570 | break; | |
571 | } | |
572 | ||
573 | if (!ec) | |
574 | break; | |
575 | ||
576 | ++iter_; | |
577 | } | |
578 | ||
579 | handler_(static_cast<const boost::system::error_code&>(ec), | |
580 | static_cast<const Iterator&>(iter_)); | |
581 | } | |
582 | } | |
583 | ||
584 | //private: | |
92f5a8d4 | 585 | basic_socket<Protocol, Executor>& socket_; |
b32b8144 FG |
586 | Iterator iter_; |
587 | Iterator end_; | |
588 | int start_; | |
589 | IteratorConnectHandler handler_; | |
590 | }; | |
591 | ||
92f5a8d4 | 592 | template <typename Protocol, typename Executor, typename Iterator, |
b32b8144 FG |
593 | typename ConnectCondition, typename IteratorConnectHandler> |
594 | inline void* asio_handler_allocate(std::size_t size, | |
92f5a8d4 | 595 | iterator_connect_op<Protocol, Executor, Iterator, |
b32b8144 FG |
596 | ConnectCondition, IteratorConnectHandler>* this_handler) |
597 | { | |
598 | return boost_asio_handler_alloc_helpers::allocate( | |
599 | size, this_handler->handler_); | |
600 | } | |
601 | ||
92f5a8d4 | 602 | template <typename Protocol, typename Executor, typename Iterator, |
b32b8144 FG |
603 | typename ConnectCondition, typename IteratorConnectHandler> |
604 | inline void asio_handler_deallocate(void* pointer, std::size_t size, | |
92f5a8d4 | 605 | iterator_connect_op<Protocol, Executor, Iterator, |
b32b8144 FG |
606 | ConnectCondition, IteratorConnectHandler>* this_handler) |
607 | { | |
608 | boost_asio_handler_alloc_helpers::deallocate( | |
609 | pointer, size, this_handler->handler_); | |
610 | } | |
611 | ||
92f5a8d4 | 612 | template <typename Protocol, typename Executor, typename Iterator, |
b32b8144 FG |
613 | typename ConnectCondition, typename IteratorConnectHandler> |
614 | inline bool asio_handler_is_continuation( | |
92f5a8d4 | 615 | iterator_connect_op<Protocol, Executor, Iterator, |
b32b8144 FG |
616 | ConnectCondition, IteratorConnectHandler>* this_handler) |
617 | { | |
618 | return boost_asio_handler_cont_helpers::is_continuation( | |
619 | this_handler->handler_); | |
620 | } | |
621 | ||
92f5a8d4 TL |
622 | template <typename Function, typename Executor, typename Protocol, |
623 | typename Iterator, typename ConnectCondition, | |
624 | typename IteratorConnectHandler> | |
b32b8144 | 625 | inline void asio_handler_invoke(Function& function, |
92f5a8d4 | 626 | iterator_connect_op<Protocol, Executor, Iterator, |
b32b8144 FG |
627 | ConnectCondition, IteratorConnectHandler>* this_handler) |
628 | { | |
629 | boost_asio_handler_invoke_helpers::invoke( | |
630 | function, this_handler->handler_); | |
631 | } | |
632 | ||
92f5a8d4 TL |
633 | template <typename Function, typename Executor, typename Protocol, |
634 | typename Iterator, typename ConnectCondition, | |
635 | typename IteratorConnectHandler> | |
b32b8144 | 636 | inline void asio_handler_invoke(const Function& function, |
92f5a8d4 | 637 | iterator_connect_op<Protocol, Executor, Iterator, |
b32b8144 FG |
638 | ConnectCondition, IteratorConnectHandler>* this_handler) |
639 | { | |
640 | boost_asio_handler_invoke_helpers::invoke( | |
641 | function, this_handler->handler_); | |
642 | } | |
92f5a8d4 TL |
643 | |
644 | template <typename Protocol, typename Executor> | |
645 | class initiate_async_iterator_connect | |
646 | { | |
647 | public: | |
648 | typedef Executor executor_type; | |
649 | ||
650 | explicit initiate_async_iterator_connect( | |
651 | basic_socket<Protocol, Executor>& s) | |
652 | : socket_(s) | |
653 | { | |
654 | } | |
655 | ||
656 | executor_type get_executor() const BOOST_ASIO_NOEXCEPT | |
657 | { | |
658 | return socket_.get_executor(); | |
659 | } | |
660 | ||
661 | template <typename IteratorConnectHandler, | |
662 | typename Iterator, typename ConnectCondition> | |
663 | void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, | |
664 | Iterator begin, Iterator end, | |
665 | const ConnectCondition& connect_condition) const | |
666 | { | |
667 | // If you get an error on the following line it means that your | |
668 | // handler does not meet the documented type requirements for an | |
669 | // IteratorConnectHandler. | |
670 | BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( | |
671 | IteratorConnectHandler, handler, Iterator) type_check; | |
672 | ||
673 | non_const_lvalue<IteratorConnectHandler> handler2(handler); | |
674 | iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, | |
675 | typename decay<IteratorConnectHandler>::type>(socket_, begin, end, | |
676 | connect_condition, handler2.value)(boost::system::error_code(), 1); | |
677 | } | |
678 | ||
679 | private: | |
680 | basic_socket<Protocol, Executor>& socket_; | |
681 | }; | |
b32b8144 FG |
682 | } // namespace detail |
683 | ||
684 | #if !defined(GENERATING_DOCUMENTATION) | |
685 | ||
92f5a8d4 TL |
686 | template <typename Protocol, typename Executor, typename EndpointSequence, |
687 | typename ConnectCondition, typename RangeConnectHandler, typename Allocator> | |
b32b8144 | 688 | struct associated_allocator< |
92f5a8d4 TL |
689 | detail::range_connect_op<Protocol, Executor, EndpointSequence, |
690 | ConnectCondition, RangeConnectHandler>, Allocator> | |
b32b8144 FG |
691 | { |
692 | typedef typename associated_allocator< | |
693 | RangeConnectHandler, Allocator>::type type; | |
694 | ||
695 | static type get( | |
92f5a8d4 TL |
696 | const detail::range_connect_op<Protocol, Executor, EndpointSequence, |
697 | ConnectCondition, RangeConnectHandler>& h, | |
b32b8144 FG |
698 | const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT |
699 | { | |
700 | return associated_allocator<RangeConnectHandler, | |
701 | Allocator>::get(h.handler_, a); | |
702 | } | |
703 | }; | |
704 | ||
92f5a8d4 TL |
705 | template <typename Protocol, typename Executor, typename EndpointSequence, |
706 | typename ConnectCondition, typename RangeConnectHandler, typename Executor1> | |
b32b8144 | 707 | struct associated_executor< |
92f5a8d4 TL |
708 | detail::range_connect_op<Protocol, Executor, EndpointSequence, |
709 | ConnectCondition, RangeConnectHandler>, Executor1> | |
b32b8144 FG |
710 | { |
711 | typedef typename associated_executor< | |
92f5a8d4 | 712 | RangeConnectHandler, Executor1>::type type; |
b32b8144 FG |
713 | |
714 | static type get( | |
92f5a8d4 TL |
715 | const detail::range_connect_op<Protocol, Executor, EndpointSequence, |
716 | ConnectCondition, RangeConnectHandler>& h, | |
717 | const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT | |
b32b8144 FG |
718 | { |
719 | return associated_executor<RangeConnectHandler, | |
92f5a8d4 | 720 | Executor1>::get(h.handler_, ex); |
b32b8144 FG |
721 | } |
722 | }; | |
723 | ||
92f5a8d4 TL |
724 | template <typename Protocol, typename Executor, typename Iterator, |
725 | typename ConnectCondition, typename IteratorConnectHandler, | |
726 | typename Allocator> | |
b32b8144 | 727 | struct associated_allocator< |
92f5a8d4 TL |
728 | detail::iterator_connect_op<Protocol, Executor, |
729 | Iterator, ConnectCondition, IteratorConnectHandler>, | |
b32b8144 FG |
730 | Allocator> |
731 | { | |
732 | typedef typename associated_allocator< | |
733 | IteratorConnectHandler, Allocator>::type type; | |
734 | ||
735 | static type get( | |
92f5a8d4 | 736 | const detail::iterator_connect_op<Protocol, Executor, |
b32b8144 FG |
737 | Iterator, ConnectCondition, IteratorConnectHandler>& h, |
738 | const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT | |
739 | { | |
740 | return associated_allocator<IteratorConnectHandler, | |
741 | Allocator>::get(h.handler_, a); | |
742 | } | |
743 | }; | |
744 | ||
92f5a8d4 TL |
745 | template <typename Protocol, typename Executor, typename Iterator, |
746 | typename ConnectCondition, typename IteratorConnectHandler, | |
747 | typename Executor1> | |
b32b8144 | 748 | struct associated_executor< |
92f5a8d4 TL |
749 | detail::iterator_connect_op<Protocol, Executor, |
750 | Iterator, ConnectCondition, IteratorConnectHandler>, | |
751 | Executor1> | |
b32b8144 FG |
752 | { |
753 | typedef typename associated_executor< | |
92f5a8d4 | 754 | IteratorConnectHandler, Executor1>::type type; |
b32b8144 FG |
755 | |
756 | static type get( | |
92f5a8d4 | 757 | const detail::iterator_connect_op<Protocol, Executor, |
b32b8144 | 758 | Iterator, ConnectCondition, IteratorConnectHandler>& h, |
92f5a8d4 | 759 | const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT |
b32b8144 FG |
760 | { |
761 | return associated_executor<IteratorConnectHandler, | |
92f5a8d4 | 762 | Executor1>::get(h.handler_, ex); |
b32b8144 FG |
763 | } |
764 | }; | |
765 | ||
766 | #endif // !defined(GENERATING_DOCUMENTATION) | |
767 | ||
92f5a8d4 TL |
768 | template <typename Protocol, typename Executor, typename EndpointSequence, |
769 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
770 | typename Protocol::endpoint)) RangeConnectHandler> | |
771 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, | |
b32b8144 | 772 | void (boost::system::error_code, typename Protocol::endpoint)) |
92f5a8d4 | 773 | async_connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
774 | const EndpointSequence& endpoints, |
775 | BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, | |
776 | typename enable_if<is_endpoint_sequence< | |
777 | EndpointSequence>::value>::type*) | |
778 | { | |
92f5a8d4 TL |
779 | return async_initiate<RangeConnectHandler, |
780 | void (boost::system::error_code, typename Protocol::endpoint)>( | |
781 | detail::initiate_async_range_connect<Protocol, Executor>(s), | |
782 | handler, endpoints, detail::default_connect_condition()); | |
b32b8144 FG |
783 | } |
784 | ||
785 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
92f5a8d4 TL |
786 | template <typename Protocol, typename Executor, typename Iterator, |
787 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
788 | Iterator)) IteratorConnectHandler> | |
789 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, | |
b32b8144 | 790 | void (boost::system::error_code, Iterator)) |
92f5a8d4 TL |
791 | async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
792 | BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, | |
b32b8144 FG |
793 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) |
794 | { | |
92f5a8d4 TL |
795 | return async_initiate<IteratorConnectHandler, |
796 | void (boost::system::error_code, Iterator)>( | |
797 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), | |
798 | handler, begin, Iterator(), detail::default_connect_condition()); | |
b32b8144 FG |
799 | } |
800 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
801 | ||
92f5a8d4 TL |
802 | template <typename Protocol, typename Executor, typename Iterator, |
803 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
804 | Iterator)) IteratorConnectHandler> | |
805 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, | |
b32b8144 | 806 | void (boost::system::error_code, Iterator)) |
92f5a8d4 | 807 | async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, |
b32b8144 FG |
808 | BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler) |
809 | { | |
92f5a8d4 TL |
810 | return async_initiate<IteratorConnectHandler, |
811 | void (boost::system::error_code, Iterator)>( | |
812 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), | |
813 | handler, begin, end, detail::default_connect_condition()); | |
b32b8144 FG |
814 | } |
815 | ||
92f5a8d4 TL |
816 | template <typename Protocol, typename Executor, |
817 | typename EndpointSequence, typename ConnectCondition, | |
818 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
819 | typename Protocol::endpoint)) RangeConnectHandler> | |
820 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, | |
b32b8144 | 821 | void (boost::system::error_code, typename Protocol::endpoint)) |
92f5a8d4 | 822 | async_connect(basic_socket<Protocol, Executor>& s, |
b32b8144 FG |
823 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
824 | BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler, | |
825 | typename enable_if<is_endpoint_sequence< | |
826 | EndpointSequence>::value>::type*) | |
827 | { | |
92f5a8d4 TL |
828 | return async_initiate<RangeConnectHandler, |
829 | void (boost::system::error_code, typename Protocol::endpoint)>( | |
830 | detail::initiate_async_range_connect<Protocol, Executor>(s), | |
831 | handler, endpoints, connect_condition); | |
b32b8144 FG |
832 | } |
833 | ||
834 | #if !defined(BOOST_ASIO_NO_DEPRECATED) | |
92f5a8d4 TL |
835 | template <typename Protocol, typename Executor, |
836 | typename Iterator, typename ConnectCondition, | |
837 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
838 | Iterator)) IteratorConnectHandler> | |
839 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, | |
b32b8144 | 840 | void (boost::system::error_code, Iterator)) |
92f5a8d4 TL |
841 | async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
842 | ConnectCondition connect_condition, | |
b32b8144 FG |
843 | BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler, |
844 | typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*) | |
845 | { | |
92f5a8d4 TL |
846 | return async_initiate<IteratorConnectHandler, |
847 | void (boost::system::error_code, Iterator)>( | |
848 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), | |
849 | handler, begin, Iterator(), connect_condition); | |
b32b8144 FG |
850 | } |
851 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) | |
852 | ||
92f5a8d4 TL |
853 | template <typename Protocol, typename Executor, |
854 | typename Iterator, typename ConnectCondition, | |
855 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, | |
856 | Iterator)) IteratorConnectHandler> | |
857 | inline BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, | |
b32b8144 | 858 | void (boost::system::error_code, Iterator)) |
92f5a8d4 TL |
859 | async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
860 | Iterator end, ConnectCondition connect_condition, | |
b32b8144 FG |
861 | BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler) |
862 | { | |
92f5a8d4 TL |
863 | return async_initiate<IteratorConnectHandler, |
864 | void (boost::system::error_code, Iterator)>( | |
865 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), | |
866 | handler, begin, end, connect_condition); | |
b32b8144 FG |
867 | } |
868 | ||
869 | } // namespace asio | |
870 | } // namespace boost | |
871 | ||
872 | #include <boost/asio/detail/pop_options.hpp> | |
873 | ||
874 | #endif // BOOST_ASIO_IMPL_CONNECT_HPP |