basic_stream.hpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/beast
  8. //
  9. #ifndef BOOST_BEAST_CORE_IMPL_BASIC_STREAM_HPP
  10. #define BOOST_BEAST_CORE_IMPL_BASIC_STREAM_HPP
  11. #include <boost/beast/core/async_base.hpp>
  12. #include <boost/beast/core/buffer_traits.hpp>
  13. #include <boost/beast/core/buffers_prefix.hpp>
  14. #include <boost/beast/websocket/teardown.hpp>
  15. #include <boost/asio/coroutine.hpp>
  16. #include <boost/assert.hpp>
  17. #include <boost/make_shared.hpp>
  18. #include <boost/core/exchange.hpp>
  19. #include <cstdlib>
  20. #include <type_traits>
  21. #include <utility>
  22. namespace boost {
  23. namespace beast {
  24. //------------------------------------------------------------------------------
  25. template<class Protocol, class Executor, class RatePolicy>
  26. template<class... Args>
  27. basic_stream<Protocol, Executor, RatePolicy>::
  28. impl_type::
  29. impl_type(std::false_type, Args&&... args)
  30. : socket(std::forward<Args>(args)...)
  31. , read(ex())
  32. , write(ex())
  33. , timer(ex())
  34. {
  35. reset();
  36. }
  37. template<class Protocol, class Executor, class RatePolicy>
  38. template<class RatePolicy_, class... Args>
  39. basic_stream<Protocol, Executor, RatePolicy>::
  40. impl_type::
  41. impl_type(std::true_type,
  42. RatePolicy_&& policy, Args&&... args)
  43. : boost::empty_value<RatePolicy>(
  44. boost::empty_init_t{},
  45. std::forward<RatePolicy_>(policy))
  46. , socket(std::forward<Args>(args)...)
  47. , read(ex())
  48. , write(ex())
  49. , timer(ex())
  50. {
  51. reset();
  52. }
  53. template<class Protocol, class Executor, class RatePolicy>
  54. template<class Executor2>
  55. void
  56. basic_stream<Protocol, Executor, RatePolicy>::
  57. impl_type::
  58. on_timer(Executor2 const& ex2)
  59. {
  60. BOOST_ASSERT(waiting > 0);
  61. // the last waiter starts the new slice
  62. if(--waiting > 0)
  63. return;
  64. // update the expiration time
  65. BOOST_VERIFY(timer.expires_after(
  66. std::chrono::seconds(1)) == 0);
  67. rate_policy_access::on_timer(policy());
  68. struct handler : boost::empty_value<Executor2>
  69. {
  70. boost::weak_ptr<impl_type> wp;
  71. using executor_type = Executor2;
  72. executor_type
  73. get_executor() const noexcept
  74. {
  75. return this->get();
  76. }
  77. handler(
  78. Executor2 const& ex2,
  79. boost::shared_ptr<impl_type> const& sp)
  80. : boost::empty_value<Executor2>(
  81. boost::empty_init_t{}, ex2)
  82. , wp(sp)
  83. {
  84. }
  85. void
  86. operator()(error_code ec)
  87. {
  88. auto sp = wp.lock();
  89. if(! sp)
  90. return;
  91. if(ec == net::error::operation_aborted)
  92. return;
  93. BOOST_ASSERT(! ec);
  94. if(ec)
  95. return;
  96. sp->on_timer(this->get());
  97. }
  98. };
  99. // wait on the timer again
  100. ++waiting;
  101. timer.async_wait(handler(ex2, this->shared_from_this()));
  102. }
  103. template<class Protocol, class Executor, class RatePolicy>
  104. void
  105. basic_stream<Protocol, Executor, RatePolicy>::
  106. impl_type::
  107. reset()
  108. {
  109. // If assert goes off, it means that there are
  110. // already read or write (or connect) operations
  111. // outstanding, so there is nothing to apply
  112. // the expiration time to!
  113. //
  114. BOOST_ASSERT(! read.pending || ! write.pending);
  115. if(! read.pending)
  116. BOOST_VERIFY(
  117. read.timer.expires_at(never()) == 0);
  118. if(! write.pending)
  119. BOOST_VERIFY(
  120. write.timer.expires_at(never()) == 0);
  121. }
  122. template<class Protocol, class Executor, class RatePolicy>
  123. void
  124. basic_stream<Protocol, Executor, RatePolicy>::
  125. impl_type::
  126. close()
  127. {
  128. {
  129. error_code ec;
  130. socket.close(ec);
  131. }
  132. timer.cancel();
  133. // have to let the read/write ops cancel the timer,
  134. // otherwise we will get error::timeout on close when
  135. // we actually want net::error::operation_aborted.
  136. //
  137. //read.timer.cancel();
  138. //write.timer.cancel();
  139. }
  140. //------------------------------------------------------------------------------
  141. template<class Protocol, class Executor, class RatePolicy>
  142. template<class Executor2>
  143. struct basic_stream<Protocol, Executor, RatePolicy>::
  144. timeout_handler
  145. {
  146. using executor_type = Executor2;
  147. op_state& state;
  148. boost::weak_ptr<impl_type> wp;
  149. tick_type tick;
  150. executor_type ex;
  151. executor_type get_executor() const noexcept
  152. {
  153. return ex;
  154. }
  155. void
  156. operator()(error_code ec)
  157. {
  158. // timer canceled
  159. if(ec == net::error::operation_aborted)
  160. return;
  161. BOOST_ASSERT(! ec);
  162. auto sp = wp.lock();
  163. // stream destroyed
  164. if(! sp)
  165. return;
  166. // stale timer
  167. if(tick < state.tick)
  168. return;
  169. BOOST_ASSERT(tick == state.tick);
  170. // timeout
  171. BOOST_ASSERT(! state.timeout);
  172. sp->close();
  173. state.timeout = true;
  174. }
  175. };
  176. //------------------------------------------------------------------------------
  177. template<class Protocol, class Executor, class RatePolicy>
  178. struct basic_stream<Protocol, Executor, RatePolicy>::ops
  179. {
  180. template<bool isRead, class Buffers, class Handler>
  181. class transfer_op
  182. : public async_base<Handler, Executor>
  183. , public boost::asio::coroutine
  184. {
  185. boost::shared_ptr<impl_type> impl_;
  186. pending_guard pg_;
  187. Buffers b_;
  188. using is_read = std::integral_constant<bool, isRead>;
  189. op_state&
  190. state()
  191. {
  192. if (isRead)
  193. return impl_->read;
  194. else
  195. return impl_->write;
  196. }
  197. std::size_t
  198. available_bytes()
  199. {
  200. if (isRead)
  201. return rate_policy_access::
  202. available_read_bytes(impl_->policy());
  203. else
  204. return rate_policy_access::
  205. available_write_bytes(impl_->policy());
  206. }
  207. void
  208. transfer_bytes(std::size_t n)
  209. {
  210. if (isRead)
  211. rate_policy_access::
  212. transfer_read_bytes(impl_->policy(), n);
  213. else
  214. rate_policy_access::
  215. transfer_write_bytes(impl_->policy(), n);
  216. }
  217. void
  218. async_perform(
  219. std::size_t amount, std::true_type)
  220. {
  221. impl_->socket.async_read_some(
  222. beast::buffers_prefix(amount, b_),
  223. std::move(*this));
  224. }
  225. void
  226. async_perform(
  227. std::size_t amount, std::false_type)
  228. {
  229. impl_->socket.async_write_some(
  230. beast::buffers_prefix(amount, b_),
  231. std::move(*this));
  232. }
  233. public:
  234. template<class Handler_>
  235. transfer_op(
  236. Handler_&& h,
  237. basic_stream& s,
  238. Buffers const& b)
  239. : async_base<Handler, Executor>(
  240. std::forward<Handler_>(h), s.get_executor())
  241. , impl_(s.impl_)
  242. , pg_(state().pending)
  243. , b_(b)
  244. {
  245. (*this)({});
  246. }
  247. void
  248. operator()(
  249. error_code ec,
  250. std::size_t bytes_transferred = 0)
  251. {
  252. BOOST_ASIO_CORO_REENTER(*this)
  253. {
  254. // handle empty buffers
  255. if(detail::buffers_empty(b_))
  256. {
  257. // make sure we perform the no-op
  258. BOOST_ASIO_CORO_YIELD
  259. async_perform(0, is_read{});
  260. // apply the timeout manually, otherwise
  261. // behavior varies across platforms.
  262. if(state().timer.expiry() <= clock_type::now())
  263. {
  264. impl_->close();
  265. ec = beast::error::timeout;
  266. }
  267. goto upcall;
  268. }
  269. // if a timeout is active, wait on the timer
  270. if(state().timer.expiry() != never())
  271. state().timer.async_wait(
  272. timeout_handler<decltype(this->get_executor())>{
  273. state(),
  274. impl_,
  275. state().tick,
  276. this->get_executor()});
  277. // check rate limit, maybe wait
  278. std::size_t amount;
  279. amount = available_bytes();
  280. if(amount == 0)
  281. {
  282. ++impl_->waiting;
  283. BOOST_ASIO_CORO_YIELD
  284. impl_->timer.async_wait(std::move(*this));
  285. if(ec)
  286. {
  287. // socket was closed, or a timeout
  288. BOOST_ASSERT(ec ==
  289. net::error::operation_aborted);
  290. // timeout handler invoked?
  291. if(state().timeout)
  292. {
  293. // yes, socket already closed
  294. ec = beast::error::timeout;
  295. state().timeout = false;
  296. }
  297. goto upcall;
  298. }
  299. impl_->on_timer(this->get_executor());
  300. // Allow at least one byte, otherwise
  301. // bytes_transferred could be 0.
  302. amount = std::max<std::size_t>(
  303. available_bytes(), 1);
  304. }
  305. BOOST_ASIO_CORO_YIELD
  306. async_perform(amount, is_read{});
  307. if(state().timer.expiry() != never())
  308. {
  309. ++state().tick;
  310. // try cancelling timer
  311. auto const n =
  312. state().timer.cancel();
  313. if(n == 0)
  314. {
  315. // timeout handler invoked?
  316. if(state().timeout)
  317. {
  318. // yes, socket already closed
  319. ec = beast::error::timeout;
  320. state().timeout = false;
  321. }
  322. }
  323. else
  324. {
  325. BOOST_ASSERT(n == 1);
  326. BOOST_ASSERT(! state().timeout);
  327. }
  328. }
  329. upcall:
  330. pg_.reset();
  331. transfer_bytes(bytes_transferred);
  332. this->complete_now(ec, bytes_transferred);
  333. }
  334. }
  335. };
  336. template<class Handler>
  337. class connect_op
  338. : public async_base<Handler, Executor>
  339. {
  340. boost::shared_ptr<impl_type> impl_;
  341. pending_guard pg0_;
  342. pending_guard pg1_;
  343. op_state&
  344. state() noexcept
  345. {
  346. return impl_->write;
  347. }
  348. public:
  349. template<class Handler_>
  350. connect_op(
  351. Handler_&& h,
  352. basic_stream& s,
  353. endpoint_type ep)
  354. : async_base<Handler, Executor>(
  355. std::forward<Handler_>(h), s.get_executor())
  356. , impl_(s.impl_)
  357. , pg0_(impl_->read.pending)
  358. , pg1_(impl_->write.pending)
  359. {
  360. if(state().timer.expiry() != stream_base::never())
  361. impl_->write.timer.async_wait(
  362. timeout_handler<decltype(this->get_executor())>{
  363. state(),
  364. impl_,
  365. state().tick,
  366. this->get_executor()});
  367. impl_->socket.async_connect(
  368. ep, std::move(*this));
  369. // *this is now moved-from
  370. }
  371. template<
  372. class Endpoints, class Condition,
  373. class Handler_>
  374. connect_op(
  375. Handler_&& h,
  376. basic_stream& s,
  377. Endpoints const& eps,
  378. Condition const& cond)
  379. : async_base<Handler, Executor>(
  380. std::forward<Handler_>(h), s.get_executor())
  381. , impl_(s.impl_)
  382. , pg0_(impl_->read.pending)
  383. , pg1_(impl_->write.pending)
  384. {
  385. if(state().timer.expiry() != stream_base::never())
  386. impl_->write.timer.async_wait(
  387. timeout_handler<decltype(this->get_executor())>{
  388. state(),
  389. impl_,
  390. state().tick,
  391. this->get_executor()});
  392. net::async_connect(impl_->socket,
  393. eps, cond, std::move(*this));
  394. // *this is now moved-from
  395. }
  396. template<
  397. class Iterator, class Condition,
  398. class Handler_>
  399. connect_op(
  400. Handler_&& h,
  401. basic_stream& s,
  402. Iterator begin, Iterator end,
  403. Condition const& cond)
  404. : async_base<Handler, Executor>(
  405. std::forward<Handler_>(h), s.get_executor())
  406. , impl_(s.impl_)
  407. , pg0_(impl_->read.pending)
  408. , pg1_(impl_->write.pending)
  409. {
  410. if(state().timer.expiry() != stream_base::never())
  411. impl_->write.timer.async_wait(
  412. timeout_handler<decltype(this->get_executor())>{
  413. state(),
  414. impl_,
  415. state().tick,
  416. this->get_executor()});
  417. net::async_connect(impl_->socket,
  418. begin, end, cond, std::move(*this));
  419. // *this is now moved-from
  420. }
  421. template<class... Args>
  422. void
  423. operator()(error_code ec, Args&&... args)
  424. {
  425. if(state().timer.expiry() != stream_base::never())
  426. {
  427. ++state().tick;
  428. // try cancelling timer
  429. auto const n =
  430. impl_->write.timer.cancel();
  431. if(n == 0)
  432. {
  433. // timeout handler invoked?
  434. if(state().timeout)
  435. {
  436. // yes, socket already closed
  437. ec = beast::error::timeout;
  438. state().timeout = false;
  439. }
  440. }
  441. else
  442. {
  443. BOOST_ASSERT(n == 1);
  444. BOOST_ASSERT(! state().timeout);
  445. }
  446. }
  447. pg0_.reset();
  448. pg1_.reset();
  449. this->complete_now(ec, std::forward<Args>(args)...);
  450. }
  451. };
  452. struct run_read_op
  453. {
  454. template<class ReadHandler, class Buffers>
  455. void
  456. operator()(
  457. ReadHandler&& h,
  458. basic_stream* s,
  459. Buffers const& b)
  460. {
  461. // If you get an error on the following line it means
  462. // that your handler does not meet the documented type
  463. // requirements for the handler.
  464. static_assert(
  465. detail::is_invocable<ReadHandler,
  466. void(error_code, std::size_t)>::value,
  467. "ReadHandler type requirements not met");
  468. transfer_op<
  469. true,
  470. Buffers,
  471. typename std::decay<ReadHandler>::type>(
  472. std::forward<ReadHandler>(h), *s, b);
  473. }
  474. };
  475. struct run_write_op
  476. {
  477. template<class WriteHandler, class Buffers>
  478. void
  479. operator()(
  480. WriteHandler&& h,
  481. basic_stream* s,
  482. Buffers const& b)
  483. {
  484. // If you get an error on the following line it means
  485. // that your handler does not meet the documented type
  486. // requirements for the handler.
  487. static_assert(
  488. detail::is_invocable<WriteHandler,
  489. void(error_code, std::size_t)>::value,
  490. "WriteHandler type requirements not met");
  491. transfer_op<
  492. false,
  493. Buffers,
  494. typename std::decay<WriteHandler>::type>(
  495. std::forward<WriteHandler>(h), *s, b);
  496. }
  497. };
  498. struct run_connect_op
  499. {
  500. template<class ConnectHandler>
  501. void
  502. operator()(
  503. ConnectHandler&& h,
  504. basic_stream* s,
  505. endpoint_type const& ep)
  506. {
  507. // If you get an error on the following line it means
  508. // that your handler does not meet the documented type
  509. // requirements for the handler.
  510. static_assert(
  511. detail::is_invocable<ConnectHandler,
  512. void(error_code)>::value,
  513. "ConnectHandler type requirements not met");
  514. connect_op<typename std::decay<ConnectHandler>::type>(
  515. std::forward<ConnectHandler>(h), *s, ep);
  516. }
  517. };
  518. struct run_connect_range_op
  519. {
  520. template<
  521. class RangeConnectHandler,
  522. class EndpointSequence,
  523. class Condition>
  524. void
  525. operator()(
  526. RangeConnectHandler&& h,
  527. basic_stream* s,
  528. EndpointSequence const& eps,
  529. Condition const& cond)
  530. {
  531. // If you get an error on the following line it means
  532. // that your handler does not meet the documented type
  533. // requirements for the handler.
  534. static_assert(
  535. detail::is_invocable<RangeConnectHandler,
  536. void(error_code, typename Protocol::endpoint)>::value,
  537. "RangeConnectHandler type requirements not met");
  538. connect_op<typename std::decay<RangeConnectHandler>::type>(
  539. std::forward<RangeConnectHandler>(h), *s, eps, cond);
  540. }
  541. };
  542. struct run_connect_iter_op
  543. {
  544. template<
  545. class IteratorConnectHandler,
  546. class Iterator,
  547. class Condition>
  548. void
  549. operator()(
  550. IteratorConnectHandler&& h,
  551. basic_stream* s,
  552. Iterator begin, Iterator end,
  553. Condition const& cond)
  554. {
  555. // If you get an error on the following line it means
  556. // that your handler does not meet the documented type
  557. // requirements for the handler.
  558. static_assert(
  559. detail::is_invocable<IteratorConnectHandler,
  560. void(error_code, Iterator)>::value,
  561. "IteratorConnectHandler type requirements not met");
  562. connect_op<typename std::decay<IteratorConnectHandler>::type>(
  563. std::forward<IteratorConnectHandler>(h), *s, begin, end, cond);
  564. }
  565. };
  566. };
  567. //------------------------------------------------------------------------------
  568. template<class Protocol, class Executor, class RatePolicy>
  569. basic_stream<Protocol, Executor, RatePolicy>::
  570. ~basic_stream()
  571. {
  572. // the shared object can outlive *this,
  573. // cancel any operations so the shared
  574. // object is destroyed as soon as possible.
  575. impl_->close();
  576. }
  577. template<class Protocol, class Executor, class RatePolicy>
  578. template<class Arg0, class... Args, class>
  579. basic_stream<Protocol, Executor, RatePolicy>::
  580. basic_stream(Arg0&& arg0, Args&&... args)
  581. : impl_(boost::make_shared<impl_type>(
  582. std::false_type{},
  583. std::forward<Arg0>(arg0),
  584. std::forward<Args>(args)...))
  585. {
  586. }
  587. template<class Protocol, class Executor, class RatePolicy>
  588. template<class RatePolicy_, class Arg0, class... Args, class>
  589. basic_stream<Protocol, Executor, RatePolicy>::
  590. basic_stream(
  591. RatePolicy_&& policy, Arg0&& arg0, Args&&... args)
  592. : impl_(boost::make_shared<impl_type>(
  593. std::true_type{},
  594. std::forward<RatePolicy_>(policy),
  595. std::forward<Arg0>(arg0),
  596. std::forward<Args>(args)...))
  597. {
  598. }
  599. template<class Protocol, class Executor, class RatePolicy>
  600. basic_stream<Protocol, Executor, RatePolicy>::
  601. basic_stream(basic_stream&& other)
  602. : impl_(boost::make_shared<impl_type>(
  603. std::move(*other.impl_)))
  604. {
  605. // VFALCO I'm not sure this implementation is correct...
  606. }
  607. //------------------------------------------------------------------------------
  608. template<class Protocol, class Executor, class RatePolicy>
  609. auto
  610. basic_stream<Protocol, Executor, RatePolicy>::
  611. release_socket() ->
  612. socket_type
  613. {
  614. this->cancel();
  615. return std::move(impl_->socket);
  616. }
  617. template<class Protocol, class Executor, class RatePolicy>
  618. void
  619. basic_stream<Protocol, Executor, RatePolicy>::
  620. expires_after(std::chrono::nanoseconds expiry_time)
  621. {
  622. // If assert goes off, it means that there are
  623. // already read or write (or connect) operations
  624. // outstanding, so there is nothing to apply
  625. // the expiration time to!
  626. //
  627. BOOST_ASSERT(
  628. ! impl_->read.pending ||
  629. ! impl_->write.pending);
  630. if(! impl_->read.pending)
  631. BOOST_VERIFY(
  632. impl_->read.timer.expires_after(
  633. expiry_time) == 0);
  634. if(! impl_->write.pending)
  635. BOOST_VERIFY(
  636. impl_->write.timer.expires_after(
  637. expiry_time) == 0);
  638. }
  639. template<class Protocol, class Executor, class RatePolicy>
  640. void
  641. basic_stream<Protocol, Executor, RatePolicy>::
  642. expires_at(
  643. net::steady_timer::time_point expiry_time)
  644. {
  645. // If assert goes off, it means that there are
  646. // already read or write (or connect) operations
  647. // outstanding, so there is nothing to apply
  648. // the expiration time to!
  649. //
  650. BOOST_ASSERT(
  651. ! impl_->read.pending ||
  652. ! impl_->write.pending);
  653. if(! impl_->read.pending)
  654. BOOST_VERIFY(
  655. impl_->read.timer.expires_at(
  656. expiry_time) == 0);
  657. if(! impl_->write.pending)
  658. BOOST_VERIFY(
  659. impl_->write.timer.expires_at(
  660. expiry_time) == 0);
  661. }
  662. template<class Protocol, class Executor, class RatePolicy>
  663. void
  664. basic_stream<Protocol, Executor, RatePolicy>::
  665. expires_never()
  666. {
  667. impl_->reset();
  668. }
  669. template<class Protocol, class Executor, class RatePolicy>
  670. void
  671. basic_stream<Protocol, Executor, RatePolicy>::
  672. cancel()
  673. {
  674. error_code ec;
  675. impl_->socket.cancel(ec);
  676. impl_->timer.cancel();
  677. }
  678. template<class Protocol, class Executor, class RatePolicy>
  679. void
  680. basic_stream<Protocol, Executor, RatePolicy>::
  681. close()
  682. {
  683. impl_->close();
  684. }
  685. //------------------------------------------------------------------------------
  686. template<class Protocol, class Executor, class RatePolicy>
  687. template<class ConnectHandler>
  688. BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
  689. basic_stream<Protocol, Executor, RatePolicy>::
  690. async_connect(
  691. endpoint_type const& ep,
  692. ConnectHandler&& handler)
  693. {
  694. return net::async_initiate<
  695. ConnectHandler,
  696. void(error_code)>(
  697. typename ops::run_connect_op{},
  698. handler,
  699. this,
  700. ep);
  701. }
  702. template<class Protocol, class Executor, class RatePolicy>
  703. template<
  704. class EndpointSequence,
  705. class RangeConnectHandler,
  706. class>
  707. BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,void(error_code, typename Protocol::endpoint))
  708. basic_stream<Protocol, Executor, RatePolicy>::
  709. async_connect(
  710. EndpointSequence const& endpoints,
  711. RangeConnectHandler&& handler)
  712. {
  713. return net::async_initiate<
  714. RangeConnectHandler,
  715. void(error_code, typename Protocol::endpoint)>(
  716. typename ops::run_connect_range_op{},
  717. handler,
  718. this,
  719. endpoints,
  720. detail::any_endpoint{});
  721. }
  722. template<class Protocol, class Executor, class RatePolicy>
  723. template<
  724. class EndpointSequence,
  725. class ConnectCondition,
  726. class RangeConnectHandler,
  727. class>
  728. BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,void (error_code, typename Protocol::endpoint))
  729. basic_stream<Protocol, Executor, RatePolicy>::
  730. async_connect(
  731. EndpointSequence const& endpoints,
  732. ConnectCondition connect_condition,
  733. RangeConnectHandler&& handler)
  734. {
  735. return net::async_initiate<
  736. RangeConnectHandler,
  737. void(error_code, typename Protocol::endpoint)>(
  738. typename ops::run_connect_range_op{},
  739. handler,
  740. this,
  741. endpoints,
  742. connect_condition);
  743. }
  744. template<class Protocol, class Executor, class RatePolicy>
  745. template<
  746. class Iterator,
  747. class IteratorConnectHandler>
  748. BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,void (error_code, Iterator))
  749. basic_stream<Protocol, Executor, RatePolicy>::
  750. async_connect(
  751. Iterator begin, Iterator end,
  752. IteratorConnectHandler&& handler)
  753. {
  754. return net::async_initiate<
  755. IteratorConnectHandler,
  756. void(error_code, Iterator)>(
  757. typename ops::run_connect_iter_op{},
  758. handler,
  759. this,
  760. begin, end,
  761. detail::any_endpoint{});
  762. }
  763. template<class Protocol, class Executor, class RatePolicy>
  764. template<
  765. class Iterator,
  766. class ConnectCondition,
  767. class IteratorConnectHandler>
  768. BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,void (error_code, Iterator))
  769. basic_stream<Protocol, Executor, RatePolicy>::
  770. async_connect(
  771. Iterator begin, Iterator end,
  772. ConnectCondition connect_condition,
  773. IteratorConnectHandler&& handler)
  774. {
  775. return net::async_initiate<
  776. IteratorConnectHandler,
  777. void(error_code, Iterator)>(
  778. typename ops::run_connect_iter_op{},
  779. handler,
  780. this,
  781. begin, end,
  782. connect_condition);
  783. }
  784. //------------------------------------------------------------------------------
  785. template<class Protocol, class Executor, class RatePolicy>
  786. template<class MutableBufferSequence, class ReadHandler>
  787. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  788. basic_stream<Protocol, Executor, RatePolicy>::
  789. async_read_some(
  790. MutableBufferSequence const& buffers,
  791. ReadHandler&& handler)
  792. {
  793. static_assert(net::is_mutable_buffer_sequence<
  794. MutableBufferSequence>::value,
  795. "MutableBufferSequence type requirements not met");
  796. return net::async_initiate<
  797. ReadHandler,
  798. void(error_code, std::size_t)>(
  799. typename ops::run_read_op{},
  800. handler,
  801. this,
  802. buffers);
  803. }
  804. template<class Protocol, class Executor, class RatePolicy>
  805. template<class ConstBufferSequence, class WriteHandler>
  806. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  807. basic_stream<Protocol, Executor, RatePolicy>::
  808. async_write_some(
  809. ConstBufferSequence const& buffers,
  810. WriteHandler&& handler)
  811. {
  812. static_assert(net::is_const_buffer_sequence<
  813. ConstBufferSequence>::value,
  814. "ConstBufferSequence type requirements not met");
  815. return net::async_initiate<
  816. WriteHandler,
  817. void(error_code, std::size_t)>(
  818. typename ops::run_write_op{},
  819. handler,
  820. this,
  821. buffers);
  822. }
  823. //------------------------------------------------------------------------------
  824. //
  825. // Customization points
  826. //
  827. #if ! BOOST_BEAST_DOXYGEN
  828. template<
  829. class Protocol, class Executor, class RatePolicy>
  830. void
  831. beast_close_socket(
  832. basic_stream<Protocol, Executor, RatePolicy>& stream)
  833. {
  834. error_code ec;
  835. stream.socket().close(ec);
  836. }
  837. template<
  838. class Protocol, class Executor, class RatePolicy>
  839. void
  840. teardown(
  841. role_type role,
  842. basic_stream<Protocol, Executor, RatePolicy>& stream,
  843. error_code& ec)
  844. {
  845. using beast::websocket::teardown;
  846. teardown(role, stream.socket(), ec);
  847. }
  848. template<
  849. class Protocol, class Executor, class RatePolicy,
  850. class TeardownHandler>
  851. void
  852. async_teardown(
  853. role_type role,
  854. basic_stream<Protocol, Executor, RatePolicy>& stream,
  855. TeardownHandler&& handler)
  856. {
  857. using beast::websocket::async_teardown;
  858. async_teardown(role, stream.socket(),
  859. std::forward<TeardownHandler>(handler));
  860. }
  861. #endif
  862. } // beast
  863. } // boost
  864. #endif