Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

connect.hpp 27KB

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