connect.hpp 29 KB

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