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