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
33namespace boost {
34namespace asio {
35
36namespace 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
105template <typename Protocol, typename Executor, typename EndpointSequence>
106typename 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
116template <typename Protocol, typename Executor, typename EndpointSequence>
117typename 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)
127template <typename Protocol, typename Executor, typename Iterator>
128Iterator 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
137template <typename Protocol, typename Executor, typename Iterator>
138inline 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
146template <typename Protocol, typename Executor, typename Iterator>
147Iterator 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
156template <typename Protocol, typename Executor, typename Iterator>
157inline 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
163template <typename Protocol, typename Executor,
164 typename EndpointSequence, typename ConnectCondition>
165typename 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
176template <typename Protocol, typename Executor,
177 typename EndpointSequence, typename ConnectCondition>
178typename 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)
189template <typename Protocol, typename Executor,
190 typename Iterator, typename ConnectCondition>
191Iterator 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
201template <typename Protocol, typename Executor,
202 typename Iterator, typename ConnectCondition>
203inline 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
212template <typename Protocol, typename Executor,
213 typename Iterator, typename ConnectCondition>
214Iterator 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
223template <typename Protocol, typename Executor,
224 typename Iterator, typename ConnectCondition>
225Iterator 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
251namespace 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
628template <template <typename, typename> class Associator,
629 typename Protocol, typename Executor, typename EndpointSequence,
630 typename ConnectCondition, typename RangeConnectHandler,
631 typename DefaultCandidate>
632struct 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
658template <template <typename, typename> class Associator,
659 typename Protocol, typename Executor, typename Iterator,
660 typename ConnectCondition, typename IteratorConnectHandler,
661 typename DefaultCandidate>
662struct 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
691template <typename Protocol, typename Executor, typename EndpointSequence,
692 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
693 typename Protocol::endpoint)) RangeConnectToken>
694inline 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)
710template <typename Protocol, typename Executor, typename Iterator,
711 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
712 Iterator)) IteratorConnectToken>
713inline 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
729template <typename Protocol, typename Executor, typename Iterator,
730 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
731 Iterator)) IteratorConnectToken>
732inline 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
746template <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>
750inline 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)
767template <typename Protocol, typename Executor,
768 typename Iterator, typename ConnectCondition,
769 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
770 Iterator)) IteratorConnectToken>
771inline 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
787template <typename Protocol, typename Executor,
788 typename Iterator, typename ConnectCondition,
789 BOOST_ASIO_COMPLETION_TOKEN_FOR(void (boost::system::error_code,
790 Iterator)) IteratorConnectToken>
791inline 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

source code of boost/libs/asio/include/boost/asio/impl/connect.hpp