Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / asio / impl / connect.hpp
1 //
2 // impl/connect.hpp
3 // ~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 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/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>
26 #include <boost/asio/detail/non_const_lvalue.hpp>
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
105 template <typename Protocol, typename Executor, typename EndpointSequence>
106 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
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
117 template <typename Protocol, typename Executor, typename EndpointSequence>
118 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
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)
129 template <typename Protocol, typename Executor, typename Iterator>
130 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
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
139 template <typename Protocol, typename Executor, typename Iterator>
140 inline Iterator connect(basic_socket<Protocol, Executor>& s,
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
148 template <typename Protocol, typename Executor, typename Iterator>
149 Iterator connect(basic_socket<Protocol, Executor>& s,
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
158 template <typename Protocol, typename Executor, typename Iterator>
159 inline Iterator connect(basic_socket<Protocol, Executor>& s,
160     Iterator begin, Iterator end, boost::system::error_code& ec)
161 {
162   return connect(s, begin, end, detail::default_connect_condition(), ec);
163 }
164
165 template <typename Protocol, typename Executor,
166     typename EndpointSequence, typename ConnectCondition>
167 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
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
179 template <typename Protocol, typename Executor,
180     typename EndpointSequence, typename ConnectCondition>
181 typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,
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)
193 template <typename Protocol, typename Executor,
194     typename Iterator, typename ConnectCondition>
195 Iterator connect(basic_socket<Protocol, Executor>& s,
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
205 template <typename Protocol, typename Executor,
206     typename Iterator, typename ConnectCondition>
207 inline Iterator connect(basic_socket<Protocol, Executor>& s,
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
216 template <typename Protocol, typename Executor,
217     typename Iterator, typename ConnectCondition>
218 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
219     Iterator end, ConnectCondition connect_condition)
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
227 template <typename Protocol, typename Executor,
228     typename Iterator, typename ConnectCondition>
229 Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,
230     Iterator end, ConnectCondition connect_condition,
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
295   template <typename Protocol, typename Executor, typename EndpointSequence,
296       typename ConnectCondition, typename RangeConnectHandler>
297   class range_connect_op : base_from_connect_condition<ConnectCondition>
298   {
299   public:
300     range_connect_op(basic_socket<Protocol, Executor>& sock,
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     {
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;
348       std::advance(iter, index_);
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
375           /* fall-through */ default:
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
399     basic_socket<Protocol, Executor>& socket_;
400     EndpointSequence endpoints_;
401     std::size_t index_;
402     int start_;
403     RangeConnectHandler handler_;
404   };
405
406   template <typename Protocol, typename Executor, typename EndpointSequence,
407       typename ConnectCondition, typename RangeConnectHandler>
408   inline void* asio_handler_allocate(std::size_t size,
409       range_connect_op<Protocol, Executor, EndpointSequence,
410         ConnectCondition, RangeConnectHandler>* this_handler)
411   {
412     return boost_asio_handler_alloc_helpers::allocate(
413         size, this_handler->handler_);
414   }
415
416   template <typename Protocol, typename Executor, typename EndpointSequence,
417       typename ConnectCondition, typename RangeConnectHandler>
418   inline void asio_handler_deallocate(void* pointer, std::size_t size,
419       range_connect_op<Protocol, Executor, EndpointSequence,
420         ConnectCondition, RangeConnectHandler>* this_handler)
421   {
422     boost_asio_handler_alloc_helpers::deallocate(
423         pointer, size, this_handler->handler_);
424   }
425
426   template <typename Protocol, typename Executor, typename EndpointSequence,
427       typename ConnectCondition, typename RangeConnectHandler>
428   inline bool asio_handler_is_continuation(
429       range_connect_op<Protocol, Executor, EndpointSequence,
430         ConnectCondition, RangeConnectHandler>* this_handler)
431   {
432     return boost_asio_handler_cont_helpers::is_continuation(
433         this_handler->handler_);
434   }
435
436   template <typename Function, typename Executor, typename Protocol,
437       typename EndpointSequence, typename ConnectCondition,
438       typename RangeConnectHandler>
439   inline void asio_handler_invoke(Function& function,
440       range_connect_op<Protocol, Executor, EndpointSequence,
441         ConnectCondition, RangeConnectHandler>* this_handler)
442   {
443     boost_asio_handler_invoke_helpers::invoke(
444         function, this_handler->handler_);
445   }
446
447   template <typename Function, typename Executor, typename Protocol,
448       typename EndpointSequence, typename ConnectCondition,
449       typename RangeConnectHandler>
450   inline void asio_handler_invoke(const Function& function,
451       range_connect_op<Protocol, Executor, EndpointSequence,
452         ConnectCondition, RangeConnectHandler>* this_handler)
453   {
454     boost_asio_handler_invoke_helpers::invoke(
455         function, this_handler->handler_);
456   }
457
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,
497       typename ConnectCondition, typename IteratorConnectHandler>
498   class iterator_connect_op : base_from_connect_condition<ConnectCondition>
499   {
500   public:
501     iterator_connect_op(basic_socket<Protocol, Executor>& sock,
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
562           /* fall-through */ default:
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:
585     basic_socket<Protocol, Executor>& socket_;
586     Iterator iter_;
587     Iterator end_;
588     int start_;
589     IteratorConnectHandler handler_;
590   };
591
592   template <typename Protocol, typename Executor, typename Iterator,
593       typename ConnectCondition, typename IteratorConnectHandler>
594   inline void* asio_handler_allocate(std::size_t size,
595       iterator_connect_op<Protocol, Executor, Iterator,
596         ConnectCondition, IteratorConnectHandler>* this_handler)
597   {
598     return boost_asio_handler_alloc_helpers::allocate(
599         size, this_handler->handler_);
600   }
601
602   template <typename Protocol, typename Executor, typename Iterator,
603       typename ConnectCondition, typename IteratorConnectHandler>
604   inline void asio_handler_deallocate(void* pointer, std::size_t size,
605       iterator_connect_op<Protocol, Executor, Iterator,
606         ConnectCondition, IteratorConnectHandler>* this_handler)
607   {
608     boost_asio_handler_alloc_helpers::deallocate(
609         pointer, size, this_handler->handler_);
610   }
611
612   template <typename Protocol, typename Executor, typename Iterator,
613       typename ConnectCondition, typename IteratorConnectHandler>
614   inline bool asio_handler_is_continuation(
615       iterator_connect_op<Protocol, Executor, Iterator,
616         ConnectCondition, IteratorConnectHandler>* this_handler)
617   {
618     return boost_asio_handler_cont_helpers::is_continuation(
619         this_handler->handler_);
620   }
621
622   template <typename Function, typename Executor, typename Protocol,
623       typename Iterator, typename ConnectCondition,
624       typename IteratorConnectHandler>
625   inline void asio_handler_invoke(Function& function,
626       iterator_connect_op<Protocol, Executor, Iterator,
627         ConnectCondition, IteratorConnectHandler>* this_handler)
628   {
629     boost_asio_handler_invoke_helpers::invoke(
630         function, this_handler->handler_);
631   }
632
633   template <typename Function, typename Executor, typename Protocol,
634       typename Iterator, typename ConnectCondition,
635       typename IteratorConnectHandler>
636   inline void asio_handler_invoke(const Function& function,
637       iterator_connect_op<Protocol, Executor, Iterator,
638         ConnectCondition, IteratorConnectHandler>* this_handler)
639   {
640     boost_asio_handler_invoke_helpers::invoke(
641         function, this_handler->handler_);
642   }
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   };
682 } // namespace detail
683
684 #if !defined(GENERATING_DOCUMENTATION)
685
686 template <typename Protocol, typename Executor, typename EndpointSequence,
687     typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
688 struct associated_allocator<
689     detail::range_connect_op<Protocol, Executor, EndpointSequence,
690       ConnectCondition, RangeConnectHandler>, Allocator>
691 {
692   typedef typename associated_allocator<
693       RangeConnectHandler, Allocator>::type type;
694
695   static type get(
696       const detail::range_connect_op<Protocol, Executor, EndpointSequence,
697         ConnectCondition, RangeConnectHandler>& h,
698       const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
699   {
700     return associated_allocator<RangeConnectHandler,
701         Allocator>::get(h.handler_, a);
702   }
703 };
704
705 template <typename Protocol, typename Executor, typename EndpointSequence,
706     typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
707 struct associated_executor<
708     detail::range_connect_op<Protocol, Executor, EndpointSequence,
709       ConnectCondition, RangeConnectHandler>, Executor1>
710 {
711   typedef typename associated_executor<
712       RangeConnectHandler, Executor1>::type type;
713
714   static type get(
715       const detail::range_connect_op<Protocol, Executor, EndpointSequence,
716       ConnectCondition, RangeConnectHandler>& h,
717       const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
718   {
719     return associated_executor<RangeConnectHandler,
720         Executor1>::get(h.handler_, ex);
721   }
722 };
723
724 template <typename Protocol, typename Executor, typename Iterator,
725     typename ConnectCondition, typename IteratorConnectHandler,
726     typename Allocator>
727 struct associated_allocator<
728     detail::iterator_connect_op<Protocol, Executor,
729       Iterator, ConnectCondition, IteratorConnectHandler>,
730     Allocator>
731 {
732   typedef typename associated_allocator<
733       IteratorConnectHandler, Allocator>::type type;
734
735   static type get(
736       const detail::iterator_connect_op<Protocol, Executor,
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
745 template <typename Protocol, typename Executor, typename Iterator,
746     typename ConnectCondition, typename IteratorConnectHandler,
747     typename Executor1>
748 struct associated_executor<
749     detail::iterator_connect_op<Protocol, Executor,
750       Iterator, ConnectCondition, IteratorConnectHandler>,
751     Executor1>
752 {
753   typedef typename associated_executor<
754       IteratorConnectHandler, Executor1>::type type;
755
756   static type get(
757       const detail::iterator_connect_op<Protocol, Executor,
758         Iterator, ConnectCondition, IteratorConnectHandler>& h,
759       const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
760   {
761     return associated_executor<IteratorConnectHandler,
762         Executor1>::get(h.handler_, ex);
763   }
764 };
765
766 #endif // !defined(GENERATING_DOCUMENTATION)
767
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,
772     void (boost::system::error_code, typename Protocol::endpoint))
773 async_connect(basic_socket<Protocol, Executor>& s,
774     const EndpointSequence& endpoints,
775     BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
776     typename enable_if<is_endpoint_sequence<
777         EndpointSequence>::value>::type*)
778 {
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());
783 }
784
785 #if !defined(BOOST_ASIO_NO_DEPRECATED)
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,
790     void (boost::system::error_code, Iterator))
791 async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
792     BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
793     typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
794 {
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());
799 }
800 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
801
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,
806     void (boost::system::error_code, Iterator))
807 async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
808     BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
809 {
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());
814 }
815
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,
821     void (boost::system::error_code, typename Protocol::endpoint))
822 async_connect(basic_socket<Protocol, Executor>& s,
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 {
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);
832 }
833
834 #if !defined(BOOST_ASIO_NO_DEPRECATED)
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,
840     void (boost::system::error_code, Iterator))
841 async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
842     ConnectCondition connect_condition,
843     BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
844     typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
845 {
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);
850 }
851 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
852
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,
858     void (boost::system::error_code, Iterator))
859 async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
860     Iterator end, ConnectCondition connect_condition,
861     BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
862 {
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);
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