1 | // |
2 | // impl/connect.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_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/associator.hpp> |
20 | #include <boost/asio/detail/base_from_cancellation_state.hpp> |
21 | #include <boost/asio/detail/bind_handler.hpp> |
22 | #include <boost/asio/detail/handler_cont_helpers.hpp> |
23 | #include <boost/asio/detail/handler_tracking.hpp> |
24 | #include <boost/asio/detail/handler_type_requirements.hpp> |
25 | #include <boost/asio/detail/non_const_lvalue.hpp> |
26 | #include <boost/asio/detail/throw_error.hpp> |
27 | #include <boost/asio/detail/type_traits.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 | (declval<legacy_connect_condition_helper<T, Iterator>>())( |
77 | declval<const boost::system::error_code>(), |
78 | declval<const Iterator>()))) != 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 | enable_if_t<is_legacy_connect_condition< |
85 | ConnectCondition, Iterator>::value>* = 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 | enable_if_t<!is_legacy_connect_condition< |
96 | ConnectCondition, Iterator>::value>* = 0) |
97 | { |
98 | for (;next != end; ++next) |
99 | if (connect_condition(ec, *next)) |
100 | return next; |
101 | return end; |
102 | } |
103 | } |
104 | |
105 | template <typename Protocol, typename Executor, typename EndpointSequence> |
106 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
107 | const EndpointSequence& endpoints, |
108 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
109 | { |
110 | boost::system::error_code ec; |
111 | typename Protocol::endpoint result = connect(s, endpoints, ec); |
112 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
113 | return result; |
114 | } |
115 | |
116 | template <typename Protocol, typename Executor, typename EndpointSequence> |
117 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
118 | const EndpointSequence& endpoints, boost::system::error_code& ec, |
119 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
120 | { |
121 | return detail::deref_connect_result<Protocol>( |
122 | connect(s, endpoints.begin(), endpoints.end(), |
123 | detail::default_connect_condition(), ec), ec); |
124 | } |
125 | |
126 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
127 | template <typename Protocol, typename Executor, typename Iterator> |
128 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
129 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
130 | { |
131 | boost::system::error_code ec; |
132 | Iterator result = connect(s, begin, ec); |
133 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
134 | return result; |
135 | } |
136 | |
137 | template <typename Protocol, typename Executor, typename Iterator> |
138 | inline Iterator connect(basic_socket<Protocol, Executor>& s, |
139 | Iterator begin, boost::system::error_code& ec, |
140 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
141 | { |
142 | return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); |
143 | } |
144 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) |
145 | |
146 | template <typename Protocol, typename Executor, typename Iterator> |
147 | Iterator connect(basic_socket<Protocol, Executor>& s, |
148 | Iterator begin, Iterator end) |
149 | { |
150 | boost::system::error_code ec; |
151 | Iterator result = connect(s, begin, end, ec); |
152 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
153 | return result; |
154 | } |
155 | |
156 | template <typename Protocol, typename Executor, typename Iterator> |
157 | inline Iterator connect(basic_socket<Protocol, Executor>& s, |
158 | Iterator begin, Iterator end, boost::system::error_code& ec) |
159 | { |
160 | return connect(s, begin, end, detail::default_connect_condition(), ec); |
161 | } |
162 | |
163 | template <typename Protocol, typename Executor, |
164 | typename EndpointSequence, typename ConnectCondition> |
165 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
166 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
167 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
168 | { |
169 | boost::system::error_code ec; |
170 | typename Protocol::endpoint result = connect( |
171 | s, endpoints, connect_condition, ec); |
172 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
173 | return result; |
174 | } |
175 | |
176 | template <typename Protocol, typename Executor, |
177 | typename EndpointSequence, typename ConnectCondition> |
178 | typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, |
179 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
180 | boost::system::error_code& ec, |
181 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
182 | { |
183 | return detail::deref_connect_result<Protocol>( |
184 | connect(s, endpoints.begin(), endpoints.end(), |
185 | connect_condition, ec), ec); |
186 | } |
187 | |
188 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
189 | template <typename Protocol, typename Executor, |
190 | typename Iterator, typename ConnectCondition> |
191 | Iterator connect(basic_socket<Protocol, Executor>& s, |
192 | Iterator begin, ConnectCondition connect_condition, |
193 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
194 | { |
195 | boost::system::error_code ec; |
196 | Iterator result = connect(s, begin, connect_condition, ec); |
197 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
198 | return result; |
199 | } |
200 | |
201 | template <typename Protocol, typename Executor, |
202 | typename Iterator, typename ConnectCondition> |
203 | inline Iterator connect(basic_socket<Protocol, Executor>& s, |
204 | Iterator begin, ConnectCondition connect_condition, |
205 | boost::system::error_code& ec, |
206 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
207 | { |
208 | return connect(s, begin, Iterator(), connect_condition, ec); |
209 | } |
210 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) |
211 | |
212 | template <typename Protocol, typename Executor, |
213 | typename Iterator, typename ConnectCondition> |
214 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
215 | Iterator end, ConnectCondition connect_condition) |
216 | { |
217 | boost::system::error_code ec; |
218 | Iterator result = connect(s, begin, end, connect_condition, ec); |
219 | boost::asio::detail::throw_error(err: ec, location: "connect" ); |
220 | return result; |
221 | } |
222 | |
223 | template <typename Protocol, typename Executor, |
224 | typename Iterator, typename ConnectCondition> |
225 | Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
226 | Iterator end, ConnectCondition connect_condition, |
227 | boost::system::error_code& ec) |
228 | { |
229 | ec = boost::system::error_code(); |
230 | |
231 | for (Iterator iter = begin; iter != end; ++iter) |
232 | { |
233 | iter = (detail::call_connect_condition(connect_condition, ec, iter, end)); |
234 | if (iter != end) |
235 | { |
236 | s.close(ec); |
237 | s.connect(*iter, ec); |
238 | if (!ec) |
239 | return iter; |
240 | } |
241 | else |
242 | break; |
243 | } |
244 | |
245 | if (!ec) |
246 | ec = boost::asio::error::not_found; |
247 | |
248 | return end; |
249 | } |
250 | |
251 | namespace detail |
252 | { |
253 | // Enable the empty base class optimisation for the connect condition. |
254 | template <typename ConnectCondition> |
255 | class base_from_connect_condition |
256 | { |
257 | protected: |
258 | explicit base_from_connect_condition( |
259 | const ConnectCondition& connect_condition) |
260 | : connect_condition_(connect_condition) |
261 | { |
262 | } |
263 | |
264 | template <typename Iterator> |
265 | void check_condition(const boost::system::error_code& ec, |
266 | Iterator& iter, Iterator& end) |
267 | { |
268 | iter = detail::call_connect_condition(connect_condition_, ec, iter, end); |
269 | } |
270 | |
271 | private: |
272 | ConnectCondition connect_condition_; |
273 | }; |
274 | |
275 | // The default_connect_condition implementation is essentially a no-op. This |
276 | // template specialisation lets us eliminate all costs associated with it. |
277 | template <> |
278 | class base_from_connect_condition<default_connect_condition> |
279 | { |
280 | protected: |
281 | explicit base_from_connect_condition(const default_connect_condition&) |
282 | { |
283 | } |
284 | |
285 | template <typename Iterator> |
286 | void check_condition(const boost::system::error_code&, Iterator&, Iterator&) |
287 | { |
288 | } |
289 | }; |
290 | |
291 | template <typename Protocol, typename Executor, typename EndpointSequence, |
292 | typename ConnectCondition, typename RangeConnectHandler> |
293 | class range_connect_op |
294 | : public base_from_cancellation_state<RangeConnectHandler>, |
295 | base_from_connect_condition<ConnectCondition> |
296 | { |
297 | public: |
298 | range_connect_op(basic_socket<Protocol, Executor>& sock, |
299 | const EndpointSequence& endpoints, |
300 | const ConnectCondition& connect_condition, |
301 | RangeConnectHandler& handler) |
302 | : base_from_cancellation_state<RangeConnectHandler>( |
303 | handler, enable_partial_cancellation()), |
304 | base_from_connect_condition<ConnectCondition>(connect_condition), |
305 | socket_(sock), |
306 | endpoints_(endpoints), |
307 | index_(0), |
308 | start_(0), |
309 | handler_(static_cast<RangeConnectHandler&&>(handler)) |
310 | { |
311 | } |
312 | |
313 | range_connect_op(const range_connect_op& other) |
314 | : base_from_cancellation_state<RangeConnectHandler>(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_cancellation_state<RangeConnectHandler>( |
326 | static_cast<base_from_cancellation_state<RangeConnectHandler>&&>( |
327 | other)), |
328 | base_from_connect_condition<ConnectCondition>(other), |
329 | socket_(other.socket_), |
330 | endpoints_(other.endpoints_), |
331 | index_(other.index_), |
332 | start_(other.start_), |
333 | handler_(static_cast<RangeConnectHandler&&>(other.handler_)) |
334 | { |
335 | } |
336 | |
337 | void operator()(boost::system::error_code ec, int start = 0) |
338 | { |
339 | this->process(ec, start, |
340 | const_cast<const EndpointSequence&>(endpoints_).begin(), |
341 | const_cast<const EndpointSequence&>(endpoints_).end()); |
342 | } |
343 | |
344 | //private: |
345 | template <typename Iterator> |
346 | void process(boost::system::error_code ec, |
347 | int start, Iterator begin, Iterator end) |
348 | { |
349 | Iterator iter = begin; |
350 | std::advance(iter, index_); |
351 | |
352 | switch (start_ = start) |
353 | { |
354 | case 1: |
355 | for (;;) |
356 | { |
357 | this->check_condition(ec, iter, end); |
358 | index_ = std::distance(begin, iter); |
359 | |
360 | if (iter != end) |
361 | { |
362 | socket_.close(ec); |
363 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect" )); |
364 | socket_.async_connect(*iter, |
365 | static_cast<range_connect_op&&>(*this)); |
366 | return; |
367 | } |
368 | |
369 | if (start) |
370 | { |
371 | ec = boost::asio::error::not_found; |
372 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect" )); |
373 | boost::asio::post(socket_.get_executor(), |
374 | detail::bind_handler( |
375 | static_cast<range_connect_op&&>(*this), ec)); |
376 | return; |
377 | } |
378 | |
379 | /* fall-through */ default: |
380 | |
381 | if (iter == end) |
382 | break; |
383 | |
384 | if (!socket_.is_open()) |
385 | { |
386 | ec = boost::asio::error::operation_aborted; |
387 | break; |
388 | } |
389 | |
390 | if (!ec) |
391 | break; |
392 | |
393 | if (this->cancelled() != cancellation_type::none) |
394 | { |
395 | ec = boost::asio::error::operation_aborted; |
396 | break; |
397 | } |
398 | |
399 | ++iter; |
400 | ++index_; |
401 | } |
402 | |
403 | static_cast<RangeConnectHandler&&>(handler_)( |
404 | static_cast<const boost::system::error_code&>(ec), |
405 | static_cast<const typename Protocol::endpoint&>( |
406 | ec || iter == end ? typename Protocol::endpoint() : *iter)); |
407 | } |
408 | } |
409 | |
410 | basic_socket<Protocol, Executor>& socket_; |
411 | EndpointSequence endpoints_; |
412 | std::size_t index_; |
413 | int start_; |
414 | RangeConnectHandler handler_; |
415 | }; |
416 | |
417 | template <typename Protocol, typename Executor, typename EndpointSequence, |
418 | typename ConnectCondition, typename RangeConnectHandler> |
419 | inline bool asio_handler_is_continuation( |
420 | range_connect_op<Protocol, Executor, EndpointSequence, |
421 | ConnectCondition, RangeConnectHandler>* this_handler) |
422 | { |
423 | return boost_asio_handler_cont_helpers::is_continuation( |
424 | this_handler->handler_); |
425 | } |
426 | |
427 | template <typename Protocol, typename Executor> |
428 | class initiate_async_range_connect |
429 | { |
430 | public: |
431 | typedef Executor executor_type; |
432 | |
433 | explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s) |
434 | : socket_(s) |
435 | { |
436 | } |
437 | |
438 | executor_type get_executor() const noexcept |
439 | { |
440 | return socket_.get_executor(); |
441 | } |
442 | |
443 | template <typename RangeConnectHandler, |
444 | typename EndpointSequence, typename ConnectCondition> |
445 | void operator()(RangeConnectHandler&& handler, |
446 | const EndpointSequence& endpoints, |
447 | const ConnectCondition& connect_condition) const |
448 | { |
449 | // If you get an error on the following line it means that your |
450 | // handler does not meet the documented type requirements for an |
451 | // RangeConnectHandler. |
452 | BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler, |
453 | handler, typename Protocol::endpoint) type_check; |
454 | |
455 | non_const_lvalue<RangeConnectHandler> handler2(handler); |
456 | range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, |
457 | decay_t<RangeConnectHandler>>(socket_, endpoints, |
458 | connect_condition, handler2.value)(boost::system::error_code(), 1); |
459 | } |
460 | |
461 | private: |
462 | basic_socket<Protocol, Executor>& socket_; |
463 | }; |
464 | |
465 | template <typename Protocol, typename Executor, typename Iterator, |
466 | typename ConnectCondition, typename IteratorConnectHandler> |
467 | class iterator_connect_op |
468 | : public base_from_cancellation_state<IteratorConnectHandler>, |
469 | base_from_connect_condition<ConnectCondition> |
470 | { |
471 | public: |
472 | iterator_connect_op(basic_socket<Protocol, Executor>& sock, |
473 | const Iterator& begin, const Iterator& end, |
474 | const ConnectCondition& connect_condition, |
475 | IteratorConnectHandler& handler) |
476 | : base_from_cancellation_state<IteratorConnectHandler>( |
477 | handler, enable_partial_cancellation()), |
478 | base_from_connect_condition<ConnectCondition>(connect_condition), |
479 | socket_(sock), |
480 | iter_(begin), |
481 | end_(end), |
482 | start_(0), |
483 | handler_(static_cast<IteratorConnectHandler&&>(handler)) |
484 | { |
485 | } |
486 | |
487 | iterator_connect_op(const iterator_connect_op& other) |
488 | : base_from_cancellation_state<IteratorConnectHandler>(other), |
489 | base_from_connect_condition<ConnectCondition>(other), |
490 | socket_(other.socket_), |
491 | iter_(other.iter_), |
492 | end_(other.end_), |
493 | start_(other.start_), |
494 | handler_(other.handler_) |
495 | { |
496 | } |
497 | |
498 | iterator_connect_op(iterator_connect_op&& other) |
499 | : base_from_cancellation_state<IteratorConnectHandler>( |
500 | static_cast<base_from_cancellation_state<IteratorConnectHandler>&&>( |
501 | other)), |
502 | base_from_connect_condition<ConnectCondition>(other), |
503 | socket_(other.socket_), |
504 | iter_(other.iter_), |
505 | end_(other.end_), |
506 | start_(other.start_), |
507 | handler_(static_cast<IteratorConnectHandler&&>(other.handler_)) |
508 | { |
509 | } |
510 | |
511 | void operator()(boost::system::error_code ec, int start = 0) |
512 | { |
513 | switch (start_ = start) |
514 | { |
515 | case 1: |
516 | for (;;) |
517 | { |
518 | this->check_condition(ec, iter_, end_); |
519 | |
520 | if (iter_ != end_) |
521 | { |
522 | socket_.close(ec); |
523 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect" )); |
524 | socket_.async_connect(*iter_, |
525 | static_cast<iterator_connect_op&&>(*this)); |
526 | return; |
527 | } |
528 | |
529 | if (start) |
530 | { |
531 | ec = boost::asio::error::not_found; |
532 | BOOST_ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect" )); |
533 | boost::asio::post(socket_.get_executor(), |
534 | detail::bind_handler( |
535 | static_cast<iterator_connect_op&&>(*this), ec)); |
536 | return; |
537 | } |
538 | |
539 | /* fall-through */ default: |
540 | |
541 | if (iter_ == end_) |
542 | break; |
543 | |
544 | if (!socket_.is_open()) |
545 | { |
546 | ec = boost::asio::error::operation_aborted; |
547 | break; |
548 | } |
549 | |
550 | if (!ec) |
551 | break; |
552 | |
553 | if (this->cancelled() != cancellation_type::none) |
554 | { |
555 | ec = boost::asio::error::operation_aborted; |
556 | break; |
557 | } |
558 | |
559 | ++iter_; |
560 | } |
561 | |
562 | static_cast<IteratorConnectHandler&&>(handler_)( |
563 | static_cast<const boost::system::error_code&>(ec), |
564 | static_cast<const Iterator&>(iter_)); |
565 | } |
566 | } |
567 | |
568 | //private: |
569 | basic_socket<Protocol, Executor>& socket_; |
570 | Iterator iter_; |
571 | Iterator end_; |
572 | int start_; |
573 | IteratorConnectHandler handler_; |
574 | }; |
575 | |
576 | template <typename Protocol, typename Executor, typename Iterator, |
577 | typename ConnectCondition, typename IteratorConnectHandler> |
578 | inline bool asio_handler_is_continuation( |
579 | iterator_connect_op<Protocol, Executor, Iterator, |
580 | ConnectCondition, IteratorConnectHandler>* this_handler) |
581 | { |
582 | return boost_asio_handler_cont_helpers::is_continuation( |
583 | this_handler->handler_); |
584 | } |
585 | |
586 | template <typename Protocol, typename Executor> |
587 | class initiate_async_iterator_connect |
588 | { |
589 | public: |
590 | typedef Executor executor_type; |
591 | |
592 | explicit initiate_async_iterator_connect( |
593 | basic_socket<Protocol, Executor>& s) |
594 | : socket_(s) |
595 | { |
596 | } |
597 | |
598 | executor_type get_executor() const noexcept |
599 | { |
600 | return socket_.get_executor(); |
601 | } |
602 | |
603 | template <typename IteratorConnectHandler, |
604 | typename Iterator, typename ConnectCondition> |
605 | void operator()(IteratorConnectHandler&& handler, |
606 | Iterator begin, Iterator end, |
607 | const ConnectCondition& connect_condition) const |
608 | { |
609 | // If you get an error on the following line it means that your |
610 | // handler does not meet the documented type requirements for an |
611 | // IteratorConnectHandler. |
612 | BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( |
613 | IteratorConnectHandler, handler, Iterator) type_check; |
614 | |
615 | non_const_lvalue<IteratorConnectHandler> handler2(handler); |
616 | iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, |
617 | decay_t<IteratorConnectHandler>>(socket_, begin, end, |
618 | connect_condition, handler2.value)(boost::system::error_code(), 1); |
619 | } |
620 | |
621 | private: |
622 | basic_socket<Protocol, Executor>& socket_; |
623 | }; |
624 | } // namespace detail |
625 | |
626 | #if !defined(GENERATING_DOCUMENTATION) |
627 | |
628 | template <template <typename, typename> class Associator, |
629 | typename Protocol, typename Executor, typename EndpointSequence, |
630 | typename ConnectCondition, typename RangeConnectHandler, |
631 | typename DefaultCandidate> |
632 | struct associator<Associator, |
633 | detail::range_connect_op<Protocol, Executor, |
634 | EndpointSequence, ConnectCondition, RangeConnectHandler>, |
635 | DefaultCandidate> |
636 | : Associator<RangeConnectHandler, DefaultCandidate> |
637 | { |
638 | static typename Associator<RangeConnectHandler, DefaultCandidate>::type get( |
639 | const detail::range_connect_op<Protocol, Executor, EndpointSequence, |
640 | ConnectCondition, RangeConnectHandler>& h) noexcept |
641 | { |
642 | return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_); |
643 | } |
644 | |
645 | static auto get( |
646 | const detail::range_connect_op<Protocol, Executor, |
647 | EndpointSequence, ConnectCondition, RangeConnectHandler>& h, |
648 | const DefaultCandidate& c) noexcept |
649 | -> decltype( |
650 | Associator<RangeConnectHandler, DefaultCandidate>::get( |
651 | h.handler_, c)) |
652 | { |
653 | return Associator<RangeConnectHandler, DefaultCandidate>::get( |
654 | h.handler_, c); |
655 | } |
656 | }; |
657 | |
658 | template <template <typename, typename> class Associator, |
659 | typename Protocol, typename Executor, typename Iterator, |
660 | typename ConnectCondition, typename IteratorConnectHandler, |
661 | typename DefaultCandidate> |
662 | struct associator<Associator, |
663 | detail::iterator_connect_op<Protocol, Executor, |
664 | Iterator, ConnectCondition, IteratorConnectHandler>, |
665 | DefaultCandidate> |
666 | : Associator<IteratorConnectHandler, DefaultCandidate> |
667 | { |
668 | static typename Associator<IteratorConnectHandler, DefaultCandidate>::type |
669 | get(const detail::iterator_connect_op<Protocol, Executor, Iterator, |
670 | ConnectCondition, IteratorConnectHandler>& h) noexcept |
671 | { |
672 | return Associator<IteratorConnectHandler, DefaultCandidate>::get( |
673 | h.handler_); |
674 | } |
675 | |
676 | static auto get( |
677 | const detail::iterator_connect_op<Protocol, Executor, |
678 | Iterator, ConnectCondition, IteratorConnectHandler>& h, |
679 | const DefaultCandidate& c) noexcept |
680 | -> decltype( |
681 | Associator<IteratorConnectHandler, DefaultCandidate>::get( |
682 | h.handler_, c)) |
683 | { |
684 | return Associator<IteratorConnectHandler, DefaultCandidate>::get( |
685 | h.handler_, c); |
686 | } |
687 | }; |
688 | |
689 | #endif // !defined(GENERATING_DOCUMENTATION) |
690 | |
691 | template <typename Protocol, typename Executor, typename EndpointSequence, |
692 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
693 | typename Protocol::endpoint)) RangeConnectToken> |
694 | inline auto async_connect(basic_socket<Protocol, Executor>& s, |
695 | const EndpointSequence& endpoints, RangeConnectToken&& token, |
696 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
697 | -> decltype( |
698 | async_initiate<RangeConnectToken, |
699 | void (boost::system::error_code, typename Protocol::endpoint)>( |
700 | declval<detail::initiate_async_range_connect<Protocol, Executor>>(), |
701 | token, endpoints, declval<detail::default_connect_condition>())) |
702 | { |
703 | return async_initiate<RangeConnectToken, |
704 | void (boost::system::error_code, typename Protocol::endpoint)>( |
705 | detail::initiate_async_range_connect<Protocol, Executor>(s), |
706 | token, endpoints, detail::default_connect_condition()); |
707 | } |
708 | |
709 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
710 | template <typename Protocol, typename Executor, typename Iterator, |
711 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
712 | Iterator)) IteratorConnectToken> |
713 | inline auto async_connect(basic_socket<Protocol, Executor>& s, |
714 | Iterator begin, IteratorConnectToken&& token, |
715 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
716 | -> decltype( |
717 | async_initiate<IteratorConnectToken, |
718 | void (boost::system::error_code, Iterator)>( |
719 | declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), |
720 | token, begin, Iterator(), declval<detail::default_connect_condition>())) |
721 | { |
722 | return async_initiate<IteratorConnectToken, |
723 | void (boost::system::error_code, Iterator)>( |
724 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), |
725 | token, begin, Iterator(), detail::default_connect_condition()); |
726 | } |
727 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) |
728 | |
729 | template <typename Protocol, typename Executor, typename Iterator, |
730 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
731 | Iterator)) IteratorConnectToken> |
732 | inline auto async_connect(basic_socket<Protocol, Executor>& s, |
733 | Iterator begin, Iterator end, IteratorConnectToken&& token) |
734 | -> decltype( |
735 | async_initiate<IteratorConnectToken, |
736 | void (boost::system::error_code, Iterator)>( |
737 | declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), |
738 | token, begin, end, declval<detail::default_connect_condition>())) |
739 | { |
740 | return async_initiate<IteratorConnectToken, |
741 | void (boost::system::error_code, Iterator)>( |
742 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), |
743 | token, begin, end, detail::default_connect_condition()); |
744 | } |
745 | |
746 | template <typename Protocol, typename Executor, |
747 | typename EndpointSequence, typename ConnectCondition, |
748 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
749 | typename Protocol::endpoint)) RangeConnectToken> |
750 | inline auto async_connect(basic_socket<Protocol, Executor>& s, |
751 | const EndpointSequence& endpoints, ConnectCondition connect_condition, |
752 | RangeConnectToken&& token, |
753 | constraint_t<is_endpoint_sequence<EndpointSequence>::value>) |
754 | -> decltype( |
755 | async_initiate<RangeConnectToken, |
756 | void (boost::system::error_code, typename Protocol::endpoint)>( |
757 | declval<detail::initiate_async_range_connect<Protocol, Executor>>(), |
758 | token, endpoints, connect_condition)) |
759 | { |
760 | return async_initiate<RangeConnectToken, |
761 | void (boost::system::error_code, typename Protocol::endpoint)>( |
762 | detail::initiate_async_range_connect<Protocol, Executor>(s), |
763 | token, endpoints, connect_condition); |
764 | } |
765 | |
766 | #if !defined(BOOST_ASIO_NO_DEPRECATED) |
767 | template <typename Protocol, typename Executor, |
768 | typename Iterator, typename ConnectCondition, |
769 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
770 | Iterator)) IteratorConnectToken> |
771 | inline auto async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, |
772 | ConnectCondition connect_condition, IteratorConnectToken&& token, |
773 | constraint_t<!is_endpoint_sequence<Iterator>::value>) |
774 | -> decltype( |
775 | async_initiate<IteratorConnectToken, |
776 | void (boost::system::error_code, Iterator)>( |
777 | declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), |
778 | token, begin, Iterator(), connect_condition)) |
779 | { |
780 | return async_initiate<IteratorConnectToken, |
781 | void (boost::system::error_code, Iterator)>( |
782 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), |
783 | token, begin, Iterator(), connect_condition); |
784 | } |
785 | #endif // !defined(BOOST_ASIO_NO_DEPRECATED) |
786 | |
787 | template <typename Protocol, typename Executor, |
788 | typename Iterator, typename ConnectCondition, |
789 | BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code, |
790 | Iterator)) IteratorConnectToken> |
791 | inline auto async_connect(basic_socket<Protocol, Executor>& s, |
792 | Iterator begin, Iterator end, ConnectCondition connect_condition, |
793 | IteratorConnectToken&& token) |
794 | -> decltype( |
795 | async_initiate<IteratorConnectToken, |
796 | void (boost::system::error_code, Iterator)>( |
797 | declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), |
798 | token, begin, end, connect_condition)) |
799 | { |
800 | return async_initiate<IteratorConnectToken, |
801 | void (boost::system::error_code, Iterator)>( |
802 | detail::initiate_async_iterator_connect<Protocol, Executor>(s), |
803 | token, begin, end, connect_condition); |
804 | } |
805 | |
806 | } // namespace asio |
807 | } // namespace boost |
808 | |
809 | #include <boost/asio/detail/pop_options.hpp> |
810 | |
811 | #endif // BOOST_ASIO_IMPL_CONNECT_HPP |
812 | |