connect.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  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. 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. struct initiate_async_range_connect
  405. {
  406. template <typename RangeConnectHandler, typename Protocol,
  407. typename Executor, typename EndpointSequence, typename ConnectCondition>
  408. void operator()(BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  409. basic_socket<Protocol, Executor>* s, const EndpointSequence& endpoints,
  410. const ConnectCondition& connect_condition) const
  411. {
  412. // If you get an error on the following line it means that your
  413. // handler does not meet the documented type requirements for an
  414. // RangeConnectHandler.
  415. BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,
  416. handler, typename Protocol::endpoint) type_check;
  417. non_const_lvalue<RangeConnectHandler> handler2(handler);
  418. range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,
  419. typename decay<RangeConnectHandler>::type>(*s, endpoints,
  420. connect_condition, handler2.value)(boost::system::error_code(), 1);
  421. }
  422. };
  423. template <typename Protocol, typename Executor, typename Iterator,
  424. typename ConnectCondition, typename IteratorConnectHandler>
  425. class iterator_connect_op : base_from_connect_condition<ConnectCondition>
  426. {
  427. public:
  428. iterator_connect_op(basic_socket<Protocol, Executor>& sock,
  429. const Iterator& begin, const Iterator& end,
  430. const ConnectCondition& connect_condition,
  431. IteratorConnectHandler& handler)
  432. : base_from_connect_condition<ConnectCondition>(connect_condition),
  433. socket_(sock),
  434. iter_(begin),
  435. end_(end),
  436. start_(0),
  437. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(handler))
  438. {
  439. }
  440. #if defined(BOOST_ASIO_HAS_MOVE)
  441. iterator_connect_op(const iterator_connect_op& other)
  442. : base_from_connect_condition<ConnectCondition>(other),
  443. socket_(other.socket_),
  444. iter_(other.iter_),
  445. end_(other.end_),
  446. start_(other.start_),
  447. handler_(other.handler_)
  448. {
  449. }
  450. iterator_connect_op(iterator_connect_op&& other)
  451. : base_from_connect_condition<ConnectCondition>(other),
  452. socket_(other.socket_),
  453. iter_(other.iter_),
  454. end_(other.end_),
  455. start_(other.start_),
  456. handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))
  457. {
  458. }
  459. #endif // defined(BOOST_ASIO_HAS_MOVE)
  460. void operator()(boost::system::error_code ec, int start = 0)
  461. {
  462. switch (start_ = start)
  463. {
  464. case 1:
  465. for (;;)
  466. {
  467. this->check_condition(ec, iter_, end_);
  468. if (iter_ != end_)
  469. {
  470. socket_.close(ec);
  471. socket_.async_connect(*iter_,
  472. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this));
  473. return;
  474. }
  475. if (start)
  476. {
  477. ec = boost::asio::error::not_found;
  478. boost::asio::post(socket_.get_executor(),
  479. detail::bind_handler(
  480. BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
  481. return;
  482. }
  483. default:
  484. if (iter_ == end_)
  485. break;
  486. if (!socket_.is_open())
  487. {
  488. ec = boost::asio::error::operation_aborted;
  489. break;
  490. }
  491. if (!ec)
  492. break;
  493. ++iter_;
  494. }
  495. handler_(static_cast<const boost::system::error_code&>(ec),
  496. static_cast<const Iterator&>(iter_));
  497. }
  498. }
  499. //private:
  500. basic_socket<Protocol, Executor>& socket_;
  501. Iterator iter_;
  502. Iterator end_;
  503. int start_;
  504. IteratorConnectHandler handler_;
  505. };
  506. template <typename Protocol, typename Executor, typename Iterator,
  507. typename ConnectCondition, typename IteratorConnectHandler>
  508. inline void* asio_handler_allocate(std::size_t size,
  509. iterator_connect_op<Protocol, Executor, Iterator,
  510. ConnectCondition, IteratorConnectHandler>* this_handler)
  511. {
  512. return boost_asio_handler_alloc_helpers::allocate(
  513. size, this_handler->handler_);
  514. }
  515. template <typename Protocol, typename Executor, typename Iterator,
  516. typename ConnectCondition, typename IteratorConnectHandler>
  517. inline void asio_handler_deallocate(void* pointer, std::size_t size,
  518. iterator_connect_op<Protocol, Executor, Iterator,
  519. ConnectCondition, IteratorConnectHandler>* this_handler)
  520. {
  521. boost_asio_handler_alloc_helpers::deallocate(
  522. pointer, size, this_handler->handler_);
  523. }
  524. template <typename Protocol, typename Executor, typename Iterator,
  525. typename ConnectCondition, typename IteratorConnectHandler>
  526. inline bool asio_handler_is_continuation(
  527. iterator_connect_op<Protocol, Executor, Iterator,
  528. ConnectCondition, IteratorConnectHandler>* this_handler)
  529. {
  530. return boost_asio_handler_cont_helpers::is_continuation(
  531. this_handler->handler_);
  532. }
  533. template <typename Function, typename Executor, typename Protocol,
  534. typename Iterator, typename ConnectCondition,
  535. typename IteratorConnectHandler>
  536. inline void asio_handler_invoke(Function& function,
  537. iterator_connect_op<Protocol, Executor, Iterator,
  538. ConnectCondition, IteratorConnectHandler>* this_handler)
  539. {
  540. boost_asio_handler_invoke_helpers::invoke(
  541. function, this_handler->handler_);
  542. }
  543. template <typename Function, typename Executor, typename Protocol,
  544. typename Iterator, typename ConnectCondition,
  545. typename IteratorConnectHandler>
  546. inline void asio_handler_invoke(const Function& function,
  547. iterator_connect_op<Protocol, Executor, Iterator,
  548. ConnectCondition, IteratorConnectHandler>* this_handler)
  549. {
  550. boost_asio_handler_invoke_helpers::invoke(
  551. function, this_handler->handler_);
  552. }
  553. struct initiate_async_iterator_connect
  554. {
  555. template <typename IteratorConnectHandler, typename Protocol,
  556. typename Executor, typename Iterator, typename ConnectCondition>
  557. void operator()(BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  558. basic_socket<Protocol, Executor>* s, Iterator begin,
  559. Iterator end, const ConnectCondition& connect_condition) const
  560. {
  561. // If you get an error on the following line it means that your
  562. // handler does not meet the documented type requirements for an
  563. // IteratorConnectHandler.
  564. BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
  565. IteratorConnectHandler, handler, Iterator) type_check;
  566. non_const_lvalue<IteratorConnectHandler> handler2(handler);
  567. iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,
  568. typename decay<IteratorConnectHandler>::type>(*s, begin, end,
  569. connect_condition, handler2.value)(boost::system::error_code(), 1);
  570. }
  571. };
  572. } // namespace detail
  573. #if !defined(GENERATING_DOCUMENTATION)
  574. template <typename Protocol, typename Executor, typename EndpointSequence,
  575. typename ConnectCondition, typename RangeConnectHandler, typename Allocator>
  576. struct associated_allocator<
  577. detail::range_connect_op<Protocol, Executor, EndpointSequence,
  578. ConnectCondition, RangeConnectHandler>, Allocator>
  579. {
  580. typedef typename associated_allocator<
  581. RangeConnectHandler, Allocator>::type type;
  582. static type get(
  583. const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  584. ConnectCondition, RangeConnectHandler>& h,
  585. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  586. {
  587. return associated_allocator<RangeConnectHandler,
  588. Allocator>::get(h.handler_, a);
  589. }
  590. };
  591. template <typename Protocol, typename Executor, typename EndpointSequence,
  592. typename ConnectCondition, typename RangeConnectHandler, typename Executor1>
  593. struct associated_executor<
  594. detail::range_connect_op<Protocol, Executor, EndpointSequence,
  595. ConnectCondition, RangeConnectHandler>, Executor1>
  596. {
  597. typedef typename associated_executor<
  598. RangeConnectHandler, Executor1>::type type;
  599. static type get(
  600. const detail::range_connect_op<Protocol, Executor, EndpointSequence,
  601. ConnectCondition, RangeConnectHandler>& h,
  602. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  603. {
  604. return associated_executor<RangeConnectHandler,
  605. Executor1>::get(h.handler_, ex);
  606. }
  607. };
  608. template <typename Protocol, typename Executor, typename Iterator,
  609. typename ConnectCondition, typename IteratorConnectHandler,
  610. typename Allocator>
  611. struct associated_allocator<
  612. detail::iterator_connect_op<Protocol, Executor,
  613. Iterator, ConnectCondition, IteratorConnectHandler>,
  614. Allocator>
  615. {
  616. typedef typename associated_allocator<
  617. IteratorConnectHandler, Allocator>::type type;
  618. static type get(
  619. const detail::iterator_connect_op<Protocol, Executor,
  620. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  621. const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
  622. {
  623. return associated_allocator<IteratorConnectHandler,
  624. Allocator>::get(h.handler_, a);
  625. }
  626. };
  627. template <typename Protocol, typename Executor, typename Iterator,
  628. typename ConnectCondition, typename IteratorConnectHandler,
  629. typename Executor1>
  630. struct associated_executor<
  631. detail::iterator_connect_op<Protocol, Executor,
  632. Iterator, ConnectCondition, IteratorConnectHandler>,
  633. Executor1>
  634. {
  635. typedef typename associated_executor<
  636. IteratorConnectHandler, Executor1>::type type;
  637. static type get(
  638. const detail::iterator_connect_op<Protocol, Executor,
  639. Iterator, ConnectCondition, IteratorConnectHandler>& h,
  640. const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
  641. {
  642. return associated_executor<IteratorConnectHandler,
  643. Executor1>::get(h.handler_, ex);
  644. }
  645. };
  646. #endif // !defined(GENERATING_DOCUMENTATION)
  647. template <typename Protocol, typename Executor,
  648. typename EndpointSequence, typename RangeConnectHandler>
  649. inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
  650. void (boost::system::error_code, typename Protocol::endpoint))
  651. async_connect(basic_socket<Protocol, Executor>& s,
  652. const EndpointSequence& endpoints,
  653. BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  654. typename enable_if<is_endpoint_sequence<
  655. EndpointSequence>::value>::type*)
  656. {
  657. return async_initiate<RangeConnectHandler,
  658. void (boost::system::error_code, typename Protocol::endpoint)>(
  659. detail::initiate_async_range_connect(), handler,
  660. &s, endpoints, detail::default_connect_condition());
  661. }
  662. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  663. template <typename Protocol, typename Executor,
  664. typename Iterator, typename IteratorConnectHandler>
  665. inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
  666. void (boost::system::error_code, Iterator))
  667. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  668. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  669. typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
  670. {
  671. return async_initiate<IteratorConnectHandler,
  672. void (boost::system::error_code, Iterator)>(
  673. detail::initiate_async_iterator_connect(), handler,
  674. &s, begin, Iterator(), detail::default_connect_condition());
  675. }
  676. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  677. template <typename Protocol, typename Executor,
  678. typename Iterator, typename IteratorConnectHandler>
  679. inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
  680. void (boost::system::error_code, Iterator))
  681. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,
  682. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
  683. {
  684. return async_initiate<IteratorConnectHandler,
  685. void (boost::system::error_code, Iterator)>(
  686. detail::initiate_async_iterator_connect(), handler,
  687. &s, begin, end, detail::default_connect_condition());
  688. }
  689. template <typename Protocol, typename Executor, typename EndpointSequence,
  690. typename ConnectCondition, typename RangeConnectHandler>
  691. inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
  692. void (boost::system::error_code, typename Protocol::endpoint))
  693. async_connect(basic_socket<Protocol, Executor>& s,
  694. const EndpointSequence& endpoints, ConnectCondition connect_condition,
  695. BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
  696. typename enable_if<is_endpoint_sequence<
  697. EndpointSequence>::value>::type*)
  698. {
  699. return async_initiate<RangeConnectHandler,
  700. void (boost::system::error_code, typename Protocol::endpoint)>(
  701. detail::initiate_async_range_connect(),
  702. handler, &s, endpoints, connect_condition);
  703. }
  704. #if !defined(BOOST_ASIO_NO_DEPRECATED)
  705. template <typename Protocol, typename Executor, typename Iterator,
  706. typename ConnectCondition, typename IteratorConnectHandler>
  707. inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
  708. void (boost::system::error_code, Iterator))
  709. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  710. ConnectCondition connect_condition,
  711. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
  712. typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
  713. {
  714. return async_initiate<IteratorConnectHandler,
  715. void (boost::system::error_code, Iterator)>(
  716. detail::initiate_async_iterator_connect(),
  717. handler, &s, begin, Iterator(), connect_condition);
  718. }
  719. #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
  720. template <typename Protocol, typename Executor, typename Iterator,
  721. typename ConnectCondition, typename IteratorConnectHandler>
  722. inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
  723. void (boost::system::error_code, Iterator))
  724. async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,
  725. Iterator end, ConnectCondition connect_condition,
  726. BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
  727. {
  728. return async_initiate<IteratorConnectHandler,
  729. void (boost::system::error_code, Iterator)>(
  730. detail::initiate_async_iterator_connect(),
  731. handler, &s, begin, end, connect_condition);
  732. }
  733. } // namespace asio
  734. } // namespace boost
  735. #include <boost/asio/detail/pop_options.hpp>
  736. #endif // BOOST_ASIO_IMPL_CONNECT_HPP