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