File indexing completed on 2025-07-05 08:27:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_CORE_IMPL_BASIC_STREAM_HPP
0011 #define BOOST_BEAST_CORE_IMPL_BASIC_STREAM_HPP
0012
0013 #include <boost/beast/core/async_base.hpp>
0014 #include <boost/beast/core/buffer_traits.hpp>
0015 #include <boost/beast/core/buffers_prefix.hpp>
0016 #include <boost/beast/websocket/teardown.hpp>
0017 #include <boost/asio/append.hpp>
0018 #include <boost/asio/coroutine.hpp>
0019 #include <boost/assert.hpp>
0020 #include <boost/make_shared.hpp>
0021 #include <boost/core/exchange.hpp>
0022 #include <cstdlib>
0023 #include <type_traits>
0024 #include <utility>
0025
0026 namespace boost {
0027 namespace beast {
0028
0029
0030
0031 template<class Protocol, class Executor, class RatePolicy>
0032 template<class... Args>
0033 basic_stream<Protocol, Executor, RatePolicy>::
0034 impl_type::
0035 impl_type(std::false_type, Args&&... args)
0036 : socket(std::forward<Args>(args)...)
0037 , read(ex())
0038 , write(ex())
0039 , timer(ex())
0040 {
0041 reset();
0042 }
0043
0044 template<class Protocol, class Executor, class RatePolicy>
0045 template<class RatePolicy_, class... Args>
0046 basic_stream<Protocol, Executor, RatePolicy>::
0047 impl_type::
0048 impl_type(std::true_type,
0049 RatePolicy_&& policy, Args&&... args)
0050 : boost::empty_value<RatePolicy>(
0051 boost::empty_init_t{},
0052 std::forward<RatePolicy_>(policy))
0053 , socket(std::forward<Args>(args)...)
0054 , read(ex())
0055 , write(ex())
0056 , timer(ex())
0057 {
0058 reset();
0059 }
0060
0061 template<class Protocol, class Executor, class RatePolicy>
0062 template<class Executor2>
0063 void
0064 basic_stream<Protocol, Executor, RatePolicy>::
0065 impl_type::
0066 on_timer(Executor2 const& ex2)
0067 {
0068 BOOST_ASSERT(waiting > 0);
0069
0070
0071 if(--waiting > 0)
0072 return;
0073
0074
0075 BOOST_VERIFY(timer.expires_after(
0076 std::chrono::seconds(1)) == 0);
0077
0078 rate_policy_access::on_timer(policy());
0079
0080 struct handler : boost::empty_value<Executor2>
0081 {
0082 boost::weak_ptr<impl_type> wp;
0083
0084 using executor_type = Executor2;
0085
0086 executor_type
0087 get_executor() const noexcept
0088 {
0089 return this->get();
0090 }
0091
0092 handler(
0093 Executor2 const& ex2,
0094 boost::shared_ptr<impl_type> const& sp)
0095 : boost::empty_value<Executor2>(
0096 boost::empty_init_t{}, ex2)
0097 , wp(sp)
0098 {
0099 }
0100
0101 void
0102 operator()(error_code ec)
0103 {
0104 auto sp = wp.lock();
0105 if(! sp)
0106 return;
0107 if(ec == net::error::operation_aborted)
0108 return;
0109 BOOST_ASSERT(! ec);
0110 if(ec)
0111 return;
0112 sp->on_timer(this->get());
0113 }
0114 };
0115
0116
0117 ++waiting;
0118 timer.async_wait(handler(ex2, this->shared_from_this()));
0119 }
0120
0121 template<class Protocol, class Executor, class RatePolicy>
0122 void
0123 basic_stream<Protocol, Executor, RatePolicy>::
0124 impl_type::
0125 reset()
0126 {
0127
0128
0129
0130
0131
0132 BOOST_ASSERT(! read.pending || ! write.pending);
0133
0134 if(! read.pending)
0135 BOOST_VERIFY(
0136 read.timer.expires_at(never()) == 0);
0137
0138 if(! write.pending)
0139 BOOST_VERIFY(
0140 write.timer.expires_at(never()) == 0);
0141 }
0142
0143 template<class Protocol, class Executor, class RatePolicy>
0144 void
0145 basic_stream<Protocol, Executor, RatePolicy>::
0146 impl_type::
0147 close() noexcept
0148 {
0149 {
0150 error_code ec;
0151 socket.close(ec);
0152 }
0153 #if !defined(BOOST_NO_EXCEPTIONS)
0154 try
0155 {
0156 timer.cancel();
0157 }
0158 catch(...)
0159 {
0160 }
0161 #else
0162 timer.cancel();
0163 #endif
0164 }
0165
0166
0167
0168 template<class Protocol, class Executor, class RatePolicy>
0169 template<class Executor2>
0170 struct basic_stream<Protocol, Executor, RatePolicy>::
0171 timeout_handler
0172 {
0173 using executor_type = Executor2;
0174
0175 op_state& state;
0176 boost::weak_ptr<impl_type> wp;
0177 tick_type tick;
0178 executor_type ex;
0179
0180 executor_type get_executor() const noexcept
0181 {
0182 return ex;
0183 }
0184
0185 void
0186 operator()(error_code ec)
0187 {
0188
0189 if(ec == net::error::operation_aborted)
0190 return;
0191 BOOST_ASSERT(! ec);
0192
0193 auto sp = wp.lock();
0194
0195
0196 if(! sp)
0197 return;
0198
0199
0200 if(tick < state.tick)
0201 return;
0202 BOOST_ASSERT(tick == state.tick);
0203
0204
0205 BOOST_ASSERT(! state.timeout);
0206 sp->close();
0207 state.timeout = true;
0208 }
0209 };
0210
0211
0212
0213 template<class Protocol, class Executor, class RatePolicy>
0214 struct basic_stream<Protocol, Executor, RatePolicy>::ops
0215 {
0216
0217 template<bool isRead, class Buffers, class Handler>
0218 class transfer_op
0219 : public async_base<Handler, Executor>
0220 , public boost::asio::coroutine
0221 {
0222 boost::shared_ptr<impl_type> impl_;
0223 pending_guard pg_;
0224 Buffers b_;
0225
0226 using is_read = std::integral_constant<bool, isRead>;
0227
0228 op_state&
0229 state()
0230 {
0231 if (isRead)
0232 return impl_->read;
0233 else
0234 return impl_->write;
0235 }
0236
0237 std::size_t
0238 available_bytes()
0239 {
0240 if (isRead)
0241 return rate_policy_access::
0242 available_read_bytes(impl_->policy());
0243 else
0244 return rate_policy_access::
0245 available_write_bytes(impl_->policy());
0246 }
0247
0248 void
0249 transfer_bytes(std::size_t n)
0250 {
0251 if (isRead)
0252 rate_policy_access::
0253 transfer_read_bytes(impl_->policy(), n);
0254 else
0255 rate_policy_access::
0256 transfer_write_bytes(impl_->policy(), n);
0257 }
0258
0259 void
0260 async_perform(
0261 std::size_t amount, std::true_type)
0262 {
0263 impl_->socket.async_read_some(
0264 beast::buffers_prefix(amount, b_),
0265 std::move(*this));
0266 }
0267
0268 void
0269 async_perform(
0270 std::size_t amount, std::false_type)
0271 {
0272 impl_->socket.async_write_some(
0273 beast::buffers_prefix(amount, b_),
0274 std::move(*this));
0275 }
0276
0277 static bool never_pending_;
0278
0279 public:
0280 template<class Handler_>
0281 transfer_op(
0282 Handler_&& h,
0283 basic_stream& s,
0284 Buffers const& b)
0285 : async_base<Handler, Executor>(
0286 std::forward<Handler_>(h), s.get_executor())
0287 , impl_(s.impl_)
0288 , pg_()
0289 , b_(b)
0290 {
0291 this->set_allowed_cancellation(net::cancellation_type::all);
0292 if (buffer_bytes(b_) == 0 && state().pending)
0293 {
0294
0295
0296
0297
0298
0299
0300
0301 this->complete(false, error_code(), std::size_t{0});
0302 }
0303 else
0304 {
0305 pg_.assign(state().pending);
0306 (*this)({});
0307 }
0308 }
0309
0310 void
0311 operator()(
0312 error_code ec,
0313 std::size_t bytes_transferred = 0)
0314 {
0315 BOOST_ASIO_CORO_REENTER(*this)
0316 {
0317
0318
0319 if(state().timer.expiry() <= now())
0320 {
0321 BOOST_ASIO_CORO_YIELD
0322 {
0323 BOOST_ASIO_HANDLER_LOCATION((
0324 __FILE__, __LINE__,
0325 (isRead ? "basic_stream::async_read_some"
0326 : "basic_stream::async_write_some")));
0327
0328 net::dispatch(this->get_immediate_executor(),
0329 net::append(std::move(*this), ec, 0));
0330 }
0331
0332 impl_->close();
0333 BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout);
0334 goto upcall;
0335 }
0336
0337
0338 if(detail::buffers_empty(b_))
0339 {
0340
0341 BOOST_ASIO_CORO_YIELD
0342 {
0343 BOOST_ASIO_HANDLER_LOCATION((
0344 __FILE__, __LINE__,
0345 (isRead ? "basic_stream::async_read_some"
0346 : "basic_stream::async_write_some")));
0347
0348 async_perform(0, is_read{});
0349 }
0350 goto upcall;
0351 }
0352
0353
0354 if(state().timer.expiry() != never())
0355 {
0356 BOOST_ASIO_HANDLER_LOCATION((
0357 __FILE__, __LINE__,
0358 (isRead ? "basic_stream::async_read_some"
0359 : "basic_stream::async_write_some")));
0360
0361 state().timer.async_wait(
0362 timeout_handler<decltype(this->get_executor())>{
0363 state(),
0364 impl_,
0365 state().tick,
0366 this->get_executor()});
0367 }
0368
0369
0370 std::size_t amount;
0371 amount = available_bytes();
0372 if(amount == 0)
0373 {
0374 ++impl_->waiting;
0375 BOOST_ASIO_CORO_YIELD
0376 {
0377 BOOST_ASIO_HANDLER_LOCATION((
0378 __FILE__, __LINE__,
0379 (isRead ? "basic_stream::async_read_some"
0380 : "basic_stream::async_write_some")));
0381
0382 impl_->timer.async_wait(std::move(*this));
0383 }
0384 if(ec)
0385 {
0386
0387 BOOST_ASSERT(ec ==
0388 net::error::operation_aborted);
0389
0390 if(state().timeout)
0391 {
0392
0393 BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout);
0394 state().timeout = false;
0395 }
0396 goto upcall;
0397 }
0398 impl_->on_timer(this->get_executor());
0399
0400
0401
0402 amount = std::max<std::size_t>(
0403 available_bytes(), 1);
0404 }
0405
0406 BOOST_ASIO_CORO_YIELD
0407 {
0408 BOOST_ASIO_HANDLER_LOCATION((
0409 __FILE__, __LINE__,
0410 (isRead ? "basic_stream::async_read_some"
0411 : "basic_stream::async_write_some")));
0412
0413 async_perform(amount, is_read{});
0414 }
0415
0416 if(state().timer.expiry() != never())
0417 {
0418 ++state().tick;
0419
0420
0421 auto const n =
0422 state().timer.cancel();
0423 if(n == 0)
0424 {
0425
0426 if(state().timeout)
0427 {
0428
0429 BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout);
0430 state().timeout = false;
0431 }
0432 }
0433 else
0434 {
0435 BOOST_ASSERT(n == 1);
0436 BOOST_ASSERT(! state().timeout);
0437 }
0438 }
0439
0440 upcall:
0441 pg_.reset();
0442 transfer_bytes(bytes_transferred);
0443 this->complete_now(ec, bytes_transferred);
0444 }
0445 }
0446 };
0447
0448 template<class Handler>
0449 class connect_op
0450 : public async_base<Handler, Executor>
0451 {
0452 boost::shared_ptr<impl_type> impl_;
0453 pending_guard pg0_;
0454 pending_guard pg1_;
0455
0456 op_state&
0457 state() noexcept
0458 {
0459 return impl_->write;
0460 }
0461
0462 public:
0463 template<class Handler_>
0464 connect_op(
0465 Handler_&& h,
0466 basic_stream& s,
0467 endpoint_type ep)
0468 : async_base<Handler, Executor>(
0469 std::forward<Handler_>(h), s.get_executor())
0470 , impl_(s.impl_)
0471 , pg0_(impl_->read.pending)
0472 , pg1_(impl_->write.pending)
0473 {
0474 this->set_allowed_cancellation(net::cancellation_type::all);
0475 if(state().timer.expiry() != stream_base::never())
0476 {
0477 BOOST_ASIO_HANDLER_LOCATION((
0478 __FILE__, __LINE__,
0479 "basic_stream::async_connect"));
0480
0481 impl_->write.timer.async_wait(
0482 timeout_handler<decltype(this->get_executor())>{
0483 state(),
0484 impl_,
0485 state().tick,
0486 this->get_executor()});
0487 }
0488
0489 BOOST_ASIO_HANDLER_LOCATION((
0490 __FILE__, __LINE__,
0491 "basic_stream::async_connect"));
0492
0493 impl_->socket.async_connect(
0494 ep, std::move(*this));
0495
0496 }
0497
0498 template<
0499 class Endpoints, class Condition,
0500 class Handler_>
0501 connect_op(
0502 Handler_&& h,
0503 basic_stream& s,
0504 Endpoints const& eps,
0505 Condition const& cond)
0506 : async_base<Handler, Executor>(
0507 std::forward<Handler_>(h), s.get_executor())
0508 , impl_(s.impl_)
0509 , pg0_(impl_->read.pending)
0510 , pg1_(impl_->write.pending)
0511 {
0512 this->set_allowed_cancellation(net::cancellation_type::all);
0513 if(state().timer.expiry() != stream_base::never())
0514 {
0515 BOOST_ASIO_HANDLER_LOCATION((
0516 __FILE__, __LINE__,
0517 "basic_stream::async_connect"));
0518
0519 impl_->write.timer.async_wait(
0520 timeout_handler<decltype(this->get_executor())>{
0521 state(),
0522 impl_,
0523 state().tick,
0524 this->get_executor()});
0525 }
0526
0527 BOOST_ASIO_HANDLER_LOCATION((
0528 __FILE__, __LINE__,
0529 "basic_stream::async_connect"));
0530
0531 net::async_connect(impl_->socket,
0532 eps, cond, std::move(*this));
0533
0534 }
0535
0536 template<
0537 class Iterator, class Condition,
0538 class Handler_>
0539 connect_op(
0540 Handler_&& h,
0541 basic_stream& s,
0542 Iterator begin, Iterator end,
0543 Condition const& cond)
0544 : async_base<Handler, Executor>(
0545 std::forward<Handler_>(h), s.get_executor())
0546 , impl_(s.impl_)
0547 , pg0_(impl_->read.pending)
0548 , pg1_(impl_->write.pending)
0549 {
0550 this->set_allowed_cancellation(net::cancellation_type::all);
0551 if(state().timer.expiry() != stream_base::never())
0552 {
0553 BOOST_ASIO_HANDLER_LOCATION((
0554 __FILE__, __LINE__,
0555 "basic_stream::async_connect"));
0556
0557 impl_->write.timer.async_wait(
0558 timeout_handler<decltype(this->get_executor())>{
0559 state(),
0560 impl_,
0561 state().tick,
0562 this->get_executor()});
0563 }
0564
0565 BOOST_ASIO_HANDLER_LOCATION((
0566 __FILE__, __LINE__,
0567 "basic_stream::async_connect"));
0568
0569 net::async_connect(impl_->socket,
0570 begin, end, cond, std::move(*this));
0571
0572 }
0573
0574 template<class... Args>
0575 void
0576 operator()(error_code ec, Args&&... args)
0577 {
0578 if(state().timer.expiry() != stream_base::never())
0579 {
0580 ++state().tick;
0581
0582
0583 auto const n =
0584 impl_->write.timer.cancel();
0585 if(n == 0)
0586 {
0587
0588 if(state().timeout)
0589 {
0590
0591 BOOST_BEAST_ASSIGN_EC(ec, beast::error::timeout);
0592 state().timeout = false;
0593 }
0594 }
0595 else
0596 {
0597 BOOST_ASSERT(n == 1);
0598 BOOST_ASSERT(! state().timeout);
0599 }
0600 }
0601
0602 pg0_.reset();
0603 pg1_.reset();
0604 this->complete_now(ec, std::forward<Args>(args)...);
0605 }
0606 };
0607
0608 struct run_read_op
0609 {
0610 basic_stream* self;
0611
0612 using executor_type = typename basic_stream::executor_type;
0613
0614 executor_type
0615 get_executor() const noexcept
0616 {
0617 return self->get_executor();
0618 }
0619
0620 template<class ReadHandler, class Buffers>
0621 void
0622 operator()(
0623 ReadHandler&& h,
0624 Buffers const& b)
0625 {
0626
0627
0628
0629
0630 static_assert(
0631 detail::is_invocable<ReadHandler,
0632 void(error_code, std::size_t)>::value,
0633 "ReadHandler type requirements not met");
0634
0635 transfer_op<
0636 true,
0637 Buffers,
0638 typename std::decay<ReadHandler>::type>(
0639 std::forward<ReadHandler>(h), *self, b);
0640 }
0641 };
0642
0643 struct run_write_op
0644 {
0645 basic_stream* self;
0646
0647 using executor_type = typename basic_stream::executor_type;
0648
0649 executor_type
0650 get_executor() const noexcept
0651 {
0652 return self->get_executor();
0653 }
0654
0655 template<class WriteHandler, class Buffers>
0656 void
0657 operator()(
0658 WriteHandler&& h,
0659 Buffers const& b)
0660 {
0661
0662
0663
0664
0665 static_assert(
0666 detail::is_invocable<WriteHandler,
0667 void(error_code, std::size_t)>::value,
0668 "WriteHandler type requirements not met");
0669
0670 transfer_op<
0671 false,
0672 Buffers,
0673 typename std::decay<WriteHandler>::type>(
0674 std::forward<WriteHandler>(h), *self, b);
0675 }
0676 };
0677
0678 struct run_connect_op
0679 {
0680 basic_stream* self;
0681
0682 using executor_type = typename basic_stream::executor_type;
0683
0684 executor_type
0685 get_executor() const noexcept
0686 {
0687 return self->get_executor();
0688 }
0689
0690 template<class ConnectHandler>
0691 void
0692 operator()(
0693 ConnectHandler&& h,
0694 endpoint_type const& ep)
0695 {
0696
0697
0698
0699
0700 static_assert(
0701 detail::is_invocable<ConnectHandler,
0702 void(error_code)>::value,
0703 "ConnectHandler type requirements not met");
0704
0705 connect_op<typename std::decay<ConnectHandler>::type>(
0706 std::forward<ConnectHandler>(h), *self, ep);
0707 }
0708 };
0709
0710 struct run_connect_range_op
0711 {
0712 basic_stream* self;
0713
0714 using executor_type = typename basic_stream::executor_type;
0715
0716 executor_type
0717 get_executor() const noexcept
0718 {
0719 return self->get_executor();
0720 }
0721
0722 template<
0723 class RangeConnectHandler,
0724 class EndpointSequence,
0725 class Condition>
0726 void
0727 operator()(
0728 RangeConnectHandler&& h,
0729 EndpointSequence const& eps,
0730 Condition const& cond)
0731 {
0732
0733
0734
0735
0736 static_assert(
0737 detail::is_invocable<RangeConnectHandler,
0738 void(error_code, typename Protocol::endpoint)>::value,
0739 "RangeConnectHandler type requirements not met");
0740
0741 connect_op<typename std::decay<RangeConnectHandler>::type>(
0742 std::forward<RangeConnectHandler>(h), *self, eps, cond);
0743 }
0744 };
0745
0746 struct run_connect_iter_op
0747 {
0748 basic_stream* self;
0749
0750 using executor_type = typename basic_stream::executor_type;
0751
0752 executor_type
0753 get_executor() const noexcept
0754 {
0755 return self->get_executor();
0756 }
0757
0758 template<
0759 class IteratorConnectHandler,
0760 class Iterator,
0761 class Condition>
0762 void
0763 operator()(
0764 IteratorConnectHandler&& h,
0765 Iterator begin, Iterator end,
0766 Condition const& cond)
0767 {
0768
0769
0770
0771
0772 static_assert(
0773 detail::is_invocable<IteratorConnectHandler,
0774 void(error_code, Iterator)>::value,
0775 "IteratorConnectHandler type requirements not met");
0776
0777 connect_op<typename std::decay<IteratorConnectHandler>::type>(
0778 std::forward<IteratorConnectHandler>(h), *self, begin, end, cond);
0779 }
0780 };
0781
0782 };
0783
0784
0785
0786 template<class Protocol, class Executor, class RatePolicy>
0787 basic_stream<Protocol, Executor, RatePolicy>::
0788 ~basic_stream()
0789 {
0790
0791
0792
0793 impl_->close();
0794 }
0795
0796 template<class Protocol, class Executor, class RatePolicy>
0797 template<class Arg0, class... Args, class>
0798 basic_stream<Protocol, Executor, RatePolicy>::
0799 basic_stream(Arg0&& arg0, Args&&... args)
0800 : impl_(boost::make_shared<impl_type>(
0801 std::false_type{},
0802 std::forward<Arg0>(arg0),
0803 std::forward<Args>(args)...))
0804 {
0805 }
0806
0807 template<class Protocol, class Executor, class RatePolicy>
0808 template<class RatePolicy_, class Arg0, class... Args, class>
0809 basic_stream<Protocol, Executor, RatePolicy>::
0810 basic_stream(
0811 RatePolicy_&& policy, Arg0&& arg0, Args&&... args)
0812 : impl_(boost::make_shared<impl_type>(
0813 std::true_type{},
0814 std::forward<RatePolicy_>(policy),
0815 std::forward<Arg0>(arg0),
0816 std::forward<Args>(args)...))
0817 {
0818 }
0819
0820 template<class Protocol, class Executor, class RatePolicy>
0821 basic_stream<Protocol, Executor, RatePolicy>::
0822 basic_stream(basic_stream&& other)
0823 : impl_(boost::make_shared<impl_type>(
0824 std::move(*other.impl_)))
0825 {
0826
0827
0828
0829
0830
0831
0832 }
0833
0834 template<class Protocol, class Executor, class RatePolicy>
0835 template<class Executor_>
0836 basic_stream<Protocol, Executor, RatePolicy>::
0837 basic_stream(basic_stream<Protocol, Executor_, RatePolicy> && other)
0838 : impl_(boost::make_shared<impl_type>(std::false_type{}, std::move(other.impl_->socket)))
0839 {
0840 }
0841
0842
0843
0844 template<class Protocol, class Executor, class RatePolicy>
0845 auto
0846 basic_stream<Protocol, Executor, RatePolicy>::
0847 release_socket() ->
0848 socket_type
0849 {
0850 this->cancel();
0851 return std::move(impl_->socket);
0852 }
0853
0854 template<class Protocol, class Executor, class RatePolicy>
0855 void
0856 basic_stream<Protocol, Executor, RatePolicy>::
0857 expires_after(net::steady_timer::duration expiry_time)
0858 {
0859
0860
0861
0862
0863
0864 BOOST_ASSERT(
0865 ! impl_->read.pending ||
0866 ! impl_->write.pending);
0867
0868 if(! impl_->read.pending)
0869 BOOST_VERIFY(
0870 impl_->read.timer.expires_after(
0871 expiry_time) == 0);
0872
0873 if(! impl_->write.pending)
0874 BOOST_VERIFY(
0875 impl_->write.timer.expires_after(
0876 expiry_time) == 0);
0877 }
0878
0879 template<class Protocol, class Executor, class RatePolicy>
0880 void
0881 basic_stream<Protocol, Executor, RatePolicy>::
0882 expires_at(
0883 net::steady_timer::time_point expiry_time)
0884 {
0885
0886
0887
0888
0889
0890 BOOST_ASSERT(
0891 ! impl_->read.pending ||
0892 ! impl_->write.pending);
0893
0894 if(! impl_->read.pending)
0895 BOOST_VERIFY(
0896 impl_->read.timer.expires_at(
0897 expiry_time) == 0);
0898
0899 if(! impl_->write.pending)
0900 BOOST_VERIFY(
0901 impl_->write.timer.expires_at(
0902 expiry_time) == 0);
0903 }
0904
0905 template<class Protocol, class Executor, class RatePolicy>
0906 void
0907 basic_stream<Protocol, Executor, RatePolicy>::
0908 expires_never()
0909 {
0910 impl_->reset();
0911 }
0912
0913 template<class Protocol, class Executor, class RatePolicy>
0914 void
0915 basic_stream<Protocol, Executor, RatePolicy>::
0916 cancel()
0917 {
0918 error_code ec;
0919 impl_->socket.cancel(ec);
0920 impl_->timer.cancel();
0921 }
0922
0923 template<class Protocol, class Executor, class RatePolicy>
0924 void
0925 basic_stream<Protocol, Executor, RatePolicy>::
0926 close()
0927 {
0928 impl_->close();
0929 }
0930
0931
0932
0933 template<class Protocol, class Executor, class RatePolicy>
0934 template<BOOST_BEAST_ASYNC_TPARAM1 ConnectHandler>
0935 BOOST_BEAST_ASYNC_RESULT1(ConnectHandler)
0936 basic_stream<Protocol, Executor, RatePolicy>::
0937 async_connect(
0938 endpoint_type const& ep,
0939 ConnectHandler&& handler)
0940 {
0941 return net::async_initiate<
0942 ConnectHandler,
0943 void(error_code)>(
0944 typename ops::run_connect_op{this},
0945 handler,
0946 ep);
0947 }
0948
0949 template<class Protocol, class Executor, class RatePolicy>
0950 template<
0951 class EndpointSequence,
0952 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, typename Protocol::endpoint)) RangeConnectHandler,
0953 class,
0954 class>
0955 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,void(error_code, typename Protocol::endpoint))
0956 basic_stream<Protocol, Executor, RatePolicy>::
0957 async_connect(
0958 EndpointSequence const& endpoints,
0959 RangeConnectHandler&& handler)
0960 {
0961 return net::async_initiate<
0962 RangeConnectHandler,
0963 void(error_code, typename Protocol::endpoint)>(
0964 typename ops::run_connect_range_op{this},
0965 handler,
0966 endpoints,
0967 detail::any_endpoint{});
0968 }
0969
0970 template<class Protocol, class Executor, class RatePolicy>
0971 template<
0972 class EndpointSequence,
0973 class ConnectCondition,
0974 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, typename Protocol::endpoint)) RangeConnectHandler,
0975 class,
0976 class>
0977 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,void (error_code, typename Protocol::endpoint))
0978 basic_stream<Protocol, Executor, RatePolicy>::
0979 async_connect(
0980 EndpointSequence const& endpoints,
0981 ConnectCondition connect_condition,
0982 RangeConnectHandler&& handler)
0983 {
0984 return net::async_initiate<
0985 RangeConnectHandler,
0986 void(error_code, typename Protocol::endpoint)>(
0987 typename ops::run_connect_range_op{this},
0988 handler,
0989 endpoints,
0990 connect_condition);
0991 }
0992
0993 template<class Protocol, class Executor, class RatePolicy>
0994 template<
0995 class Iterator,
0996 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, Iterator)) IteratorConnectHandler,
0997 class>
0998 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,void (error_code, Iterator))
0999 basic_stream<Protocol, Executor, RatePolicy>::
1000 async_connect(
1001 Iterator begin, Iterator end,
1002 IteratorConnectHandler&& handler)
1003 {
1004 return net::async_initiate<
1005 IteratorConnectHandler,
1006 void(error_code, Iterator)>(
1007 typename ops::run_connect_iter_op{this},
1008 handler,
1009 begin, end,
1010 detail::any_endpoint{});
1011 }
1012
1013 template<class Protocol, class Executor, class RatePolicy>
1014 template<
1015 class Iterator,
1016 class ConnectCondition,
1017 BOOST_ASIO_COMPLETION_TOKEN_FOR(void(error_code, Iterator)) IteratorConnectHandler,
1018 class>
1019 BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,void (error_code, Iterator))
1020 basic_stream<Protocol, Executor, RatePolicy>::
1021 async_connect(
1022 Iterator begin, Iterator end,
1023 ConnectCondition connect_condition,
1024 IteratorConnectHandler&& handler)
1025 {
1026 return net::async_initiate<
1027 IteratorConnectHandler,
1028 void(error_code, Iterator)>(
1029 typename ops::run_connect_iter_op{this},
1030 handler,
1031 begin, end,
1032 connect_condition);
1033 }
1034
1035
1036
1037 template<class Protocol, class Executor, class RatePolicy>
1038 template<class MutableBufferSequence, BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
1039 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
1040 basic_stream<Protocol, Executor, RatePolicy>::
1041 async_read_some(
1042 MutableBufferSequence const& buffers,
1043 ReadHandler&& handler)
1044 {
1045 static_assert(net::is_mutable_buffer_sequence<
1046 MutableBufferSequence>::value,
1047 "MutableBufferSequence type requirements not met");
1048 return net::async_initiate<
1049 ReadHandler,
1050 void(error_code, std::size_t)>(
1051 typename ops::run_read_op{this},
1052 handler,
1053 buffers);
1054 }
1055
1056 template<class Protocol, class Executor, class RatePolicy>
1057 template<class ConstBufferSequence, BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
1058 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
1059 basic_stream<Protocol, Executor, RatePolicy>::
1060 async_write_some(
1061 ConstBufferSequence const& buffers,
1062 WriteHandler&& handler)
1063 {
1064 static_assert(net::is_const_buffer_sequence<
1065 ConstBufferSequence>::value,
1066 "ConstBufferSequence type requirements not met");
1067 return net::async_initiate<
1068 WriteHandler,
1069 void(error_code, std::size_t)>(
1070 typename ops::run_write_op{this},
1071 handler,
1072 buffers);
1073 }
1074
1075
1076
1077
1078
1079
1080 #if ! BOOST_BEAST_DOXYGEN
1081
1082 template<
1083 class Protocol, class Executor, class RatePolicy>
1084 void
1085 beast_close_socket(
1086 basic_stream<Protocol, Executor, RatePolicy>& stream)
1087 {
1088 error_code ec;
1089 stream.socket().close(ec);
1090 }
1091
1092 template<
1093 class Protocol, class Executor, class RatePolicy>
1094 void
1095 teardown(
1096 role_type role,
1097 basic_stream<Protocol, Executor, RatePolicy>& stream,
1098 error_code& ec)
1099 {
1100 using beast::websocket::teardown;
1101 teardown(role, stream.socket(), ec);
1102 }
1103
1104 template<
1105 class Protocol, class Executor, class RatePolicy,
1106 class TeardownHandler>
1107 void
1108 async_teardown(
1109 role_type role,
1110 basic_stream<Protocol, Executor, RatePolicy>& stream,
1111 TeardownHandler&& handler)
1112 {
1113 using beast::websocket::async_teardown;
1114 async_teardown(role, stream.socket(),
1115 std::forward<TeardownHandler>(handler));
1116 }
1117
1118 #endif
1119
1120 }
1121 }
1122
1123 #endif