mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 12:57:31 +02:00
Add RatePolicy to basic_stream
This commit is contained in:
@ -4,6 +4,7 @@ Version 216:
|
|||||||
* Add websocket::stream timeouts
|
* Add websocket::stream timeouts
|
||||||
* Use suggested timeouts in Websocket examples
|
* Use suggested timeouts in Websocket examples
|
||||||
* Add make_strand
|
* Add make_strand
|
||||||
|
* Add RatePolicy to basic_stream
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__handler_ptr">handler_ptr</link></member>
|
<member><link linkend="beast.ref.boost__beast__handler_ptr">handler_ptr</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iequal">iequal</link></member>
|
<member><link linkend="beast.ref.boost__beast__iequal">iequal</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iless">iless</link></member>
|
<member><link linkend="beast.ref.boost__beast__iless">iless</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__rate_policy_access">rate_policy_access</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
@ -44,11 +45,13 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__saved_handler">saved_handler</link> <emphasis role="green">🞲</emphasis></member>
|
<member><link linkend="beast.ref.boost__beast__saved_handler">saved_handler</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__span">span</link></member>
|
<member><link linkend="beast.ref.boost__beast__span">span</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__simple_rate_policy">simple_rate_policy</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__static_string">static_string</link></member>
|
<member><link linkend="beast.ref.boost__beast__static_string">static_string</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__stable_async_op_base">stable_async_op_base</link> <emphasis role="green">🞲</emphasis></member>
|
<member><link linkend="beast.ref.boost__beast__stable_async_op_base">stable_async_op_base</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__string_param">string_param</link></member>
|
<member><link linkend="beast.ref.boost__beast__string_param">string_param</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__string_view">string_view</link></member>
|
<member><link linkend="beast.ref.boost__beast__string_view">string_view</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__tcp_stream">tcp_stream</link> <emphasis role="green">🞲</emphasis></member>
|
<member><link linkend="beast.ref.boost__beast__tcp_stream">tcp_stream</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__unlimited_rate_policy">unlimited_rate_policy</link> <emphasis role="green">🞲</emphasis></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/core/detail/stream_base.hpp>
|
#include <boost/beast/core/detail/stream_base.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/beast/core/rate_policy.hpp>
|
||||||
#include <boost/beast/core/stream_traits.hpp>
|
#include <boost/beast/core/stream_traits.hpp>
|
||||||
#include <boost/beast/websocket/role.hpp> // VFALCO This is unfortunate
|
#include <boost/beast/websocket/role.hpp> // VFALCO This is unfortunate
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
@ -25,6 +26,8 @@
|
|||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <limits>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace asio {
|
namespace asio {
|
||||||
@ -37,9 +40,7 @@ template<typename> class stream;
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
/** A stream socket wrapper with timeouts, bandwidth limits, and associated executor.
|
||||||
|
|
||||||
/** A stream socket wrapper with timeouts and associated executor.
|
|
||||||
|
|
||||||
This stream wraps a `net::basic_stream_socket` to provide
|
This stream wraps a `net::basic_stream_socket` to provide
|
||||||
the following features:
|
the following features:
|
||||||
@ -193,7 +194,9 @@ namespace beast {
|
|||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Protocol,
|
class Protocol,
|
||||||
class Executor = net::executor>
|
class Executor = net::executor,
|
||||||
|
class RatePolicy = unlimited_rate_policy
|
||||||
|
>
|
||||||
class basic_stream
|
class basic_stream
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
: private detail::stream_base
|
: private detail::stream_base
|
||||||
@ -228,6 +231,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
struct impl_type
|
struct impl_type
|
||||||
: boost::enable_shared_from_this<impl_type>
|
: boost::enable_shared_from_this<impl_type>
|
||||||
|
, boost::empty_value<RatePolicy>
|
||||||
{
|
{
|
||||||
// must come first
|
// must come first
|
||||||
net::basic_stream_socket<
|
net::basic_stream_socket<
|
||||||
@ -235,6 +239,8 @@ public:
|
|||||||
|
|
||||||
op_state read;
|
op_state read;
|
||||||
op_state write;
|
op_state write;
|
||||||
|
net::steady_timer timer; // rate timer
|
||||||
|
int waiting = 0;
|
||||||
|
|
||||||
impl_type(impl_type&&) = default;
|
impl_type(impl_type&&) = default;
|
||||||
|
|
||||||
@ -250,6 +256,21 @@ public:
|
|||||||
return this->socket.get_executor();
|
return this->socket.get_executor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RatePolicy&
|
||||||
|
policy() noexcept
|
||||||
|
{
|
||||||
|
return this->boost::empty_value<RatePolicy>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
RatePolicy const&
|
||||||
|
policy() const noexcept
|
||||||
|
{
|
||||||
|
return this->boost::empty_value<RatePolicy>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Executor2>
|
||||||
|
void on_timer(Executor2 const& ex2);
|
||||||
|
|
||||||
void reset(); // set timeouts to never
|
void reset(); // set timeouts to never
|
||||||
void close(); // cancel everything
|
void close(); // cancel everything
|
||||||
};
|
};
|
||||||
@ -265,10 +286,10 @@ private:
|
|||||||
|
|
||||||
template<bool, class, class> class async_op;
|
template<bool, class, class> class async_op;
|
||||||
|
|
||||||
template<class, class, class>
|
template<class, class, class, class>
|
||||||
friend class detail::basic_stream_connect_op;
|
friend class detail::basic_stream_connect_op;
|
||||||
|
|
||||||
template<class, class>
|
template<class, class, class>
|
||||||
friend class basic_stream;
|
friend class basic_stream;
|
||||||
|
|
||||||
struct timeout_handler;
|
struct timeout_handler;
|
||||||
@ -354,6 +375,20 @@ public:
|
|||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/// Returns the rate policy associated with the object
|
||||||
|
RatePolicy&
|
||||||
|
rate_policy() noexcept
|
||||||
|
{
|
||||||
|
return impl_->policy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the rate policy associated with the object
|
||||||
|
RatePolicy const&
|
||||||
|
rate_policy() const noexcept
|
||||||
|
{
|
||||||
|
return impl_->policy();
|
||||||
|
}
|
||||||
|
|
||||||
/** Set the timeout for the next logical operation.
|
/** Set the timeout for the next logical operation.
|
||||||
|
|
||||||
This sets either the read timer, the write timer, or
|
This sets either the read timer, the write timer, or
|
||||||
@ -1148,7 +1183,7 @@ connect(
|
|||||||
to using `net::post`.
|
to using `net::post`.
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class EndpointSequence,
|
class EndpointSequence,
|
||||||
class RangeConnectHandler
|
class RangeConnectHandler
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
@ -1160,7 +1195,7 @@ template<
|
|||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||||
void (error_code, typename Protocol::endpoint))
|
void (error_code, typename Protocol::endpoint))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
EndpointSequence const& endpoints,
|
EndpointSequence const& endpoints,
|
||||||
RangeConnectHandler&& handler);
|
RangeConnectHandler&& handler);
|
||||||
|
|
||||||
@ -1236,7 +1271,7 @@ async_connect(
|
|||||||
@endcode
|
@endcode
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class EndpointSequence,
|
class EndpointSequence,
|
||||||
class ConnectCondition,
|
class ConnectCondition,
|
||||||
class RangeConnectHandler
|
class RangeConnectHandler
|
||||||
@ -1249,7 +1284,7 @@ template<
|
|||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||||
void (error_code, typename Protocol::endpoint))
|
void (error_code, typename Protocol::endpoint))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
EndpointSequence const& endpoints,
|
EndpointSequence const& endpoints,
|
||||||
ConnectCondition connect_condition,
|
ConnectCondition connect_condition,
|
||||||
RangeConnectHandler&& handler);
|
RangeConnectHandler&& handler);
|
||||||
@ -1296,13 +1331,13 @@ async_connect(
|
|||||||
to using `net::post`.
|
to using `net::post`.
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class Iterator,
|
class Iterator,
|
||||||
class IteratorConnectHandler>
|
class IteratorConnectHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||||
void (error_code, Iterator))
|
void (error_code, Iterator))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
Iterator begin, Iterator end,
|
Iterator begin, Iterator end,
|
||||||
IteratorConnectHandler&& handler);
|
IteratorConnectHandler&& handler);
|
||||||
|
|
||||||
@ -1355,14 +1390,14 @@ async_connect(
|
|||||||
to using `net::post`.
|
to using `net::post`.
|
||||||
*/
|
*/
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class Iterator,
|
class Iterator,
|
||||||
class ConnectCondition,
|
class ConnectCondition,
|
||||||
class IteratorConnectHandler>
|
class IteratorConnectHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||||
void (error_code, Iterator))
|
void (error_code, Iterator))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
Iterator begin, Iterator end,
|
Iterator begin, Iterator end,
|
||||||
ConnectCondition connect_condition,
|
ConnectCondition connect_condition,
|
||||||
IteratorConnectHandler&& handler);
|
IteratorConnectHandler&& handler);
|
||||||
|
@ -21,7 +21,7 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class, class, class>
|
template<class, class, class, class>
|
||||||
class basic_stream_connect_op;
|
class basic_stream_connect_op;
|
||||||
|
|
||||||
struct any_endpoint
|
struct any_endpoint
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/async_op_base.hpp>
|
#include <boost/beast/core/async_op_base.hpp>
|
||||||
#include <boost/beast/core/buffer_size.hpp>
|
#include <boost/beast/core/buffer_size.hpp>
|
||||||
|
#include <boost/beast/core/buffers_prefix.hpp>
|
||||||
#include <boost/beast/core/detail/type_traits.hpp>
|
#include <boost/beast/core/detail/type_traits.hpp>
|
||||||
#include <boost/beast/websocket/teardown.hpp>
|
#include <boost/beast/websocket/teardown.hpp>
|
||||||
#include <boost/asio/bind_executor.hpp>
|
#include <boost/asio/bind_executor.hpp>
|
||||||
@ -28,21 +29,82 @@ namespace beast {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
impl_type::
|
impl_type::
|
||||||
impl_type(Args&&... args)
|
impl_type(Args&&... args)
|
||||||
: socket(std::forward<Args>(args)...)
|
: socket(std::forward<Args>(args)...)
|
||||||
, read(ex())
|
, read(ex())
|
||||||
, write(ex())
|
, write(ex())
|
||||||
|
, timer(ex())
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
|
template<class Executor2>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
|
impl_type::
|
||||||
|
on_timer(Executor2 const& ex2)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(waiting > 0);
|
||||||
|
|
||||||
|
// the last waiter starts the new slice
|
||||||
|
if(--waiting > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update the expiration time
|
||||||
|
BOOST_VERIFY(timer.expires_after(
|
||||||
|
std::chrono::seconds(1)) == 0);
|
||||||
|
|
||||||
|
rate_policy_access::on_timer(policy());
|
||||||
|
|
||||||
|
struct handler : boost::empty_value<Executor2>
|
||||||
|
{
|
||||||
|
boost::weak_ptr<impl_type> wp;
|
||||||
|
|
||||||
|
using executor_type = Executor2;
|
||||||
|
|
||||||
|
executor_type
|
||||||
|
get_executor() const noexcept
|
||||||
|
{
|
||||||
|
return this->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
handler(
|
||||||
|
Executor2 const& ex2,
|
||||||
|
boost::shared_ptr<impl_type> const& sp)
|
||||||
|
: boost::empty_value<Executor2>(
|
||||||
|
boost::empty_init_t{}, ex2)
|
||||||
|
, wp(sp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
operator()(error_code ec)
|
||||||
|
{
|
||||||
|
auto sp = wp.lock();
|
||||||
|
if(! sp)
|
||||||
|
return;
|
||||||
|
if(ec == net::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
BOOST_ASSERT(! ec);
|
||||||
|
if(ec)
|
||||||
|
return;
|
||||||
|
sp->on_timer(this->get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// wait on the timer again
|
||||||
|
++waiting;
|
||||||
|
timer.async_wait(handler(ex2, this->shared_from_this()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
|
void
|
||||||
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
impl_type::
|
impl_type::
|
||||||
reset()
|
reset()
|
||||||
{
|
{
|
||||||
@ -62,13 +124,14 @@ reset()
|
|||||||
write.timer.expires_at(never()) == 0);
|
write.timer.expires_at(never()) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
impl_type::
|
impl_type::
|
||||||
close()
|
close()
|
||||||
{
|
{
|
||||||
socket.close();
|
socket.close();
|
||||||
|
timer.cancel();
|
||||||
|
|
||||||
// have to let the read/write ops cancel the timer,
|
// have to let the read/write ops cancel the timer,
|
||||||
// otherwise we will get error::timeout on close when
|
// otherwise we will get error::timeout on close when
|
||||||
@ -80,9 +143,9 @@ close()
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
struct basic_stream<
|
struct basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
Protocol, Executor>::timeout_handler
|
timeout_handler
|
||||||
{
|
{
|
||||||
op_state& state;
|
op_state& state;
|
||||||
boost::weak_ptr<impl_type> wp;
|
boost::weak_ptr<impl_type> wp;
|
||||||
@ -124,9 +187,9 @@ struct basic_stream<
|
|||||||
also provides this.
|
also provides this.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<bool isRead, class Buffers, class Handler>
|
template<bool isRead, class Buffers, class Handler>
|
||||||
class basic_stream<Protocol, Executor>::async_op
|
class basic_stream<Protocol, Executor, RatePolicy>::async_op
|
||||||
: public async_op_base<Handler, Executor>
|
: public async_op_base<Handler, Executor>
|
||||||
, public boost::asio::coroutine
|
, public boost::asio::coroutine
|
||||||
{
|
{
|
||||||
@ -134,6 +197,8 @@ class basic_stream<Protocol, Executor>::async_op
|
|||||||
pending_guard pg_;
|
pending_guard pg_;
|
||||||
Buffers b_;
|
Buffers b_;
|
||||||
|
|
||||||
|
using is_read = std::integral_constant<bool, isRead>;
|
||||||
|
|
||||||
op_state&
|
op_state&
|
||||||
state(std::true_type)
|
state(std::true_type)
|
||||||
{
|
{
|
||||||
@ -153,18 +218,62 @@ class basic_stream<Protocol, Executor>::async_op
|
|||||||
std::integral_constant<bool, isRead>{});
|
std::integral_constant<bool, isRead>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
std::size_t
|
||||||
async_perform(std::true_type)
|
available_bytes(std::true_type)
|
||||||
{
|
{
|
||||||
impl_->socket.async_read_some(
|
return rate_policy_access::
|
||||||
b_, std::move(*this));
|
available_read_bytes(impl_->policy());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_bytes(std::false_type)
|
||||||
|
{
|
||||||
|
return rate_policy_access::
|
||||||
|
available_write_bytes(impl_->policy());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_bytes()
|
||||||
|
{
|
||||||
|
return available_bytes(is_read{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
async_perform(std::false_type)
|
transfer_bytes(std::size_t n, std::true_type)
|
||||||
|
{
|
||||||
|
rate_policy_access::
|
||||||
|
transfer_read_bytes(impl_->policy(), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_bytes(std::size_t n, std::false_type)
|
||||||
|
{
|
||||||
|
rate_policy_access::
|
||||||
|
transfer_write_bytes(impl_->policy(), n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_bytes(std::size_t n)
|
||||||
|
{
|
||||||
|
transfer_bytes(n, is_read{});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
async_perform(
|
||||||
|
std::size_t amount, std::true_type)
|
||||||
|
{
|
||||||
|
impl_->socket.async_read_some(
|
||||||
|
beast::buffers_prefix(amount, b_),
|
||||||
|
std::move(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
async_perform(
|
||||||
|
std::size_t amount, std::false_type)
|
||||||
{
|
{
|
||||||
impl_->socket.async_write_some(
|
impl_->socket.async_write_some(
|
||||||
b_, std::move(*this));
|
beast::buffers_prefix(amount, b_),
|
||||||
|
std::move(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -189,16 +298,23 @@ public:
|
|||||||
{
|
{
|
||||||
BOOST_ASIO_CORO_REENTER(*this)
|
BOOST_ASIO_CORO_REENTER(*this)
|
||||||
{
|
{
|
||||||
|
// handle empty buffers
|
||||||
if(detail::buffers_empty(b_))
|
if(detail::buffers_empty(b_))
|
||||||
{
|
{
|
||||||
|
// make sure we perform the no-op
|
||||||
BOOST_ASIO_CORO_YIELD
|
BOOST_ASIO_CORO_YIELD
|
||||||
async_perform(
|
async_perform(0, is_read{});
|
||||||
std::integral_constant<bool, isRead>{});
|
// apply the timeout manually, otherwise
|
||||||
|
// behavior varies across platforms.
|
||||||
if(state().timer.expiry() <= clock_type::now())
|
if(state().timer.expiry() <= clock_type::now())
|
||||||
|
{
|
||||||
|
impl_->close();
|
||||||
ec = beast::error::timeout;
|
ec = beast::error::timeout;
|
||||||
|
}
|
||||||
goto upcall;
|
goto upcall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if a timeout is active, wait on the timer
|
||||||
if(state().timer.expiry() != never())
|
if(state().timer.expiry() != never())
|
||||||
state().timer.async_wait(
|
state().timer.async_wait(
|
||||||
net::bind_executor(
|
net::bind_executor(
|
||||||
@ -209,9 +325,38 @@ public:
|
|||||||
state().tick
|
state().tick
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// check rate limit, maybe wait
|
||||||
|
std::size_t amount;
|
||||||
|
amount = available_bytes();
|
||||||
|
if(amount == 0)
|
||||||
|
{
|
||||||
|
++impl_->waiting;
|
||||||
|
BOOST_ASIO_CORO_YIELD
|
||||||
|
impl_->timer.async_wait(std::move(*this));
|
||||||
|
if(ec)
|
||||||
|
{
|
||||||
|
// socket was closed, or a timeout
|
||||||
|
BOOST_ASSERT(ec ==
|
||||||
|
net::error::operation_aborted);
|
||||||
|
// timeout handler invoked?
|
||||||
|
if(state().timeout)
|
||||||
|
{
|
||||||
|
// yes, socket already closed
|
||||||
|
ec = beast::error::timeout;
|
||||||
|
state().timeout = false;
|
||||||
|
}
|
||||||
|
goto upcall;
|
||||||
|
}
|
||||||
|
impl_->on_timer(this->get_executor());
|
||||||
|
|
||||||
|
// Allow at least one byte, otherwise
|
||||||
|
// bytes_transferred could be 0.
|
||||||
|
amount = std::max<std::size_t>(
|
||||||
|
available_bytes(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_ASIO_CORO_YIELD
|
BOOST_ASIO_CORO_YIELD
|
||||||
async_perform(
|
async_perform(amount, is_read{});
|
||||||
std::integral_constant<bool, isRead>{});
|
|
||||||
|
|
||||||
if(state().timer.expiry() != never())
|
if(state().timer.expiry() != never())
|
||||||
{
|
{
|
||||||
@ -239,6 +384,7 @@ public:
|
|||||||
|
|
||||||
upcall:
|
upcall:
|
||||||
pg_.reset();
|
pg_.reset();
|
||||||
|
transfer_bytes(bytes_transferred);
|
||||||
this->invoke_now(ec, bytes_transferred);
|
this->invoke_now(ec, bytes_transferred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,12 +395,13 @@ public:
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor, class Handler>
|
class Protocol, class Executor, class RatePolicy,
|
||||||
|
class Handler>
|
||||||
class basic_stream_connect_op
|
class basic_stream_connect_op
|
||||||
: public async_op_base<Handler, Executor>
|
: public async_op_base<Handler, Executor>
|
||||||
{
|
{
|
||||||
using stream_type =
|
using stream_type = beast::basic_stream<
|
||||||
beast::basic_stream<Protocol, Executor>;
|
Protocol, Executor, RatePolicy>;
|
||||||
|
|
||||||
using timeout_handler =
|
using timeout_handler =
|
||||||
typename stream_type::timeout_handler;
|
typename stream_type::timeout_handler;
|
||||||
@ -390,8 +537,8 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
~basic_stream()
|
~basic_stream()
|
||||||
{
|
{
|
||||||
// the shared object can outlive *this,
|
// the shared object can outlive *this,
|
||||||
@ -400,17 +547,17 @@ basic_stream<Protocol, Executor>::
|
|||||||
impl_->close();
|
impl_->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
basic_stream(Args&&... args)
|
basic_stream(Args&&... args)
|
||||||
: impl_(boost::make_shared<impl_type>(
|
: impl_(boost::make_shared<impl_type>(
|
||||||
std::forward<Args>(args)...))
|
std::forward<Args>(args)...))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
basic_stream(basic_stream&& other)
|
basic_stream(basic_stream&& other)
|
||||||
: impl_(boost::make_shared<impl_type>(
|
: impl_(boost::make_shared<impl_type>(
|
||||||
std::move(*other.impl_)))
|
std::move(*other.impl_)))
|
||||||
@ -420,9 +567,9 @@ basic_stream(basic_stream&& other)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
auto
|
auto
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
release_socket() ->
|
release_socket() ->
|
||||||
socket_type
|
socket_type
|
||||||
{
|
{
|
||||||
@ -430,9 +577,9 @@ release_socket() ->
|
|||||||
return std::move(impl_->socket);
|
return std::move(impl_->socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
expires_after(std::chrono::nanoseconds expiry_time)
|
expires_after(std::chrono::nanoseconds expiry_time)
|
||||||
{
|
{
|
||||||
// If assert goes off, it means that there are
|
// If assert goes off, it means that there are
|
||||||
@ -455,9 +602,9 @@ expires_after(std::chrono::nanoseconds expiry_time)
|
|||||||
expiry_time) == 0);
|
expiry_time) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
expires_at(
|
expires_at(
|
||||||
net::steady_timer::time_point expiry_time)
|
net::steady_timer::time_point expiry_time)
|
||||||
{
|
{
|
||||||
@ -481,36 +628,37 @@ expires_at(
|
|||||||
expiry_time) == 0);
|
expiry_time) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
expires_never()
|
expires_never()
|
||||||
{
|
{
|
||||||
impl_->reset();
|
impl_->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
cancel()
|
cancel()
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
impl_->socket.cancel(ec);
|
impl_->socket.cancel(ec);
|
||||||
|
impl_->timer.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
close()
|
close()
|
||||||
{
|
{
|
||||||
impl_->close();
|
impl_->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<class ConnectHandler>
|
template<class ConnectHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(ConnectHandler,
|
||||||
void(error_code))
|
void(error_code))
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
async_connect(
|
async_connect(
|
||||||
endpoint_type const& ep,
|
endpoint_type const& ep,
|
||||||
ConnectHandler&& handler)
|
ConnectHandler&& handler)
|
||||||
@ -518,17 +666,18 @@ async_connect(
|
|||||||
BOOST_BEAST_HANDLER_INIT(
|
BOOST_BEAST_HANDLER_INIT(
|
||||||
ConnectHandler, void(error_code));
|
ConnectHandler, void(error_code));
|
||||||
detail::basic_stream_connect_op<
|
detail::basic_stream_connect_op<
|
||||||
Protocol, Executor, BOOST_ASIO_HANDLER_TYPE(
|
Protocol, Executor, RatePolicy,
|
||||||
|
BOOST_ASIO_HANDLER_TYPE(
|
||||||
ConnectHandler, void(error_code))>(*this,
|
ConnectHandler, void(error_code))>(*this,
|
||||||
ep, std::forward<ConnectHandler>(handler));
|
ep, std::forward<ConnectHandler>(handler));
|
||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
template<class MutableBufferSequence, class ReadHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
||||||
void(error_code, std::size_t))
|
void(error_code, std::size_t))
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
async_read_some(
|
async_read_some(
|
||||||
MutableBufferSequence const& buffers,
|
MutableBufferSequence const& buffers,
|
||||||
ReadHandler&& handler)
|
ReadHandler&& handler)
|
||||||
@ -544,11 +693,11 @@ async_read_some(
|
|||||||
return init.result.get();
|
return init.result.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor, class RatePolicy>
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
template<class ConstBufferSequence, class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t))
|
void(error_code, std::size_t))
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor, RatePolicy>::
|
||||||
async_write_some(
|
async_write_some(
|
||||||
ConstBufferSequence const& buffers,
|
ConstBufferSequence const& buffers,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
@ -567,20 +716,21 @@ async_write_some(
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class EndpointSequence,
|
class EndpointSequence,
|
||||||
class RangeConnectHandler,
|
class RangeConnectHandler,
|
||||||
class>
|
class>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||||
void(error_code, typename Protocol::endpoint))
|
void(error_code, typename Protocol::endpoint))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
EndpointSequence const& endpoints,
|
EndpointSequence const& endpoints,
|
||||||
RangeConnectHandler&& handler)
|
RangeConnectHandler&& handler)
|
||||||
{
|
{
|
||||||
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
||||||
void(error_code, typename Protocol::endpoint));
|
void(error_code, typename Protocol::endpoint));
|
||||||
detail::basic_stream_connect_op<Protocol, Executor,
|
detail::basic_stream_connect_op<
|
||||||
|
Protocol, Executor, RatePolicy,
|
||||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||||
void(error_code, typename Protocol::endpoint))>(
|
void(error_code, typename Protocol::endpoint))>(
|
||||||
stream, endpoints, detail::any_endpoint{},
|
stream, endpoints, detail::any_endpoint{},
|
||||||
@ -589,7 +739,7 @@ async_connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class EndpointSequence,
|
class EndpointSequence,
|
||||||
class ConnectCondition,
|
class ConnectCondition,
|
||||||
class RangeConnectHandler,
|
class RangeConnectHandler,
|
||||||
@ -597,14 +747,15 @@ template<
|
|||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
||||||
void (error_code, typename Protocol::endpoint))
|
void (error_code, typename Protocol::endpoint))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
EndpointSequence const& endpoints,
|
EndpointSequence const& endpoints,
|
||||||
ConnectCondition connect_condition,
|
ConnectCondition connect_condition,
|
||||||
RangeConnectHandler&& handler)
|
RangeConnectHandler&& handler)
|
||||||
{
|
{
|
||||||
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
||||||
void(error_code, typename Protocol::endpoint));
|
void(error_code, typename Protocol::endpoint));
|
||||||
detail::basic_stream_connect_op<Protocol, Executor,
|
detail::basic_stream_connect_op<
|
||||||
|
Protocol, Executor, RatePolicy,
|
||||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
||||||
void(error_code, typename Protocol::endpoint))>(
|
void(error_code, typename Protocol::endpoint))>(
|
||||||
stream, endpoints, connect_condition,
|
stream, endpoints, connect_condition,
|
||||||
@ -613,19 +764,20 @@ async_connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class Iterator,
|
class Iterator,
|
||||||
class IteratorConnectHandler>
|
class IteratorConnectHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||||
void (error_code, Iterator))
|
void (error_code, Iterator))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
Iterator begin, Iterator end,
|
Iterator begin, Iterator end,
|
||||||
IteratorConnectHandler&& handler)
|
IteratorConnectHandler&& handler)
|
||||||
{
|
{
|
||||||
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
||||||
void(error_code, Iterator));
|
void(error_code, Iterator));
|
||||||
detail::basic_stream_connect_op<Protocol, Executor,
|
detail::basic_stream_connect_op<
|
||||||
|
Protocol, Executor, RatePolicy,
|
||||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
||||||
void(error_code, Iterator))>(
|
void(error_code, Iterator))>(
|
||||||
stream, begin, end, detail::any_endpoint{},
|
stream, begin, end, detail::any_endpoint{},
|
||||||
@ -634,21 +786,22 @@ async_connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class Iterator,
|
class Iterator,
|
||||||
class ConnectCondition,
|
class ConnectCondition,
|
||||||
class IteratorConnectHandler>
|
class IteratorConnectHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
||||||
void (error_code, Iterator))
|
void (error_code, Iterator))
|
||||||
async_connect(
|
async_connect(
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
Iterator begin, Iterator end,
|
Iterator begin, Iterator end,
|
||||||
ConnectCondition connect_condition,
|
ConnectCondition connect_condition,
|
||||||
IteratorConnectHandler&& handler)
|
IteratorConnectHandler&& handler)
|
||||||
{
|
{
|
||||||
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
||||||
void(error_code, Iterator));
|
void(error_code, Iterator));
|
||||||
detail::basic_stream_connect_op<Protocol, Executor,
|
detail::basic_stream_connect_op<
|
||||||
|
Protocol, Executor, RatePolicy,
|
||||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
||||||
void(error_code, Iterator))>(
|
void(error_code, Iterator))>(
|
||||||
stream, begin, end, connect_condition,
|
stream, begin, end, connect_condition,
|
||||||
@ -663,20 +816,22 @@ async_connect(
|
|||||||
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<
|
||||||
|
class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
beast_close_socket(
|
beast_close_socket(
|
||||||
basic_stream<Protocol, Executor>& stream)
|
basic_stream<Protocol, Executor, RatePolicy>& stream)
|
||||||
{
|
{
|
||||||
error_code ec;
|
error_code ec;
|
||||||
stream.socket().close(ec);
|
stream.socket().close(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<
|
||||||
|
class Protocol, class Executor, class RatePolicy>
|
||||||
void
|
void
|
||||||
teardown(
|
teardown(
|
||||||
websocket::role_type role,
|
websocket::role_type role,
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
using beast::websocket::teardown;
|
using beast::websocket::teardown;
|
||||||
@ -684,12 +839,12 @@ teardown(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Executor,
|
class Protocol, class Executor, class RatePolicy,
|
||||||
class TeardownHandler>
|
class TeardownHandler>
|
||||||
void
|
void
|
||||||
async_teardown(
|
async_teardown(
|
||||||
websocket::role_type role,
|
websocket::role_type role,
|
||||||
basic_stream<Protocol, Executor>& stream,
|
basic_stream<Protocol, Executor, RatePolicy>& stream,
|
||||||
TeardownHandler&& handler)
|
TeardownHandler&& handler)
|
||||||
{
|
{
|
||||||
using beast::websocket::async_teardown;
|
using beast::websocket::async_teardown;
|
||||||
|
222
include/boost/beast/core/rate_policy.hpp
Normal file
222
include/boost/beast/core/rate_policy.hpp
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_CORE_RATE_POLICY_HPP
|
||||||
|
#define BOOST_BEAST_CORE_RATE_POLICY_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/** Helper class to assist implementing a RatePolicy.
|
||||||
|
|
||||||
|
This class is used by the implementation to gain access to the
|
||||||
|
private members of a user-defined object meeting the requirements
|
||||||
|
of <em>RatePolicy</em>. To use it, simply declare it as a friend
|
||||||
|
in your class:
|
||||||
|
|
||||||
|
@par Example
|
||||||
|
@code
|
||||||
|
class custom_rate_policy
|
||||||
|
{
|
||||||
|
friend class beast::rate_policy_access;
|
||||||
|
...
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@par Concepts
|
||||||
|
|
||||||
|
@li <em>RatePolicy</em>
|
||||||
|
|
||||||
|
@see @ref beast::basic_stream
|
||||||
|
*/
|
||||||
|
class rate_policy_access
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
template<class, class, class>
|
||||||
|
friend class basic_stream;
|
||||||
|
|
||||||
|
template<class Policy>
|
||||||
|
static
|
||||||
|
std::size_t
|
||||||
|
available_read_bytes(Policy& policy)
|
||||||
|
{
|
||||||
|
return policy.available_read_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Policy>
|
||||||
|
static
|
||||||
|
std::size_t
|
||||||
|
available_write_bytes(Policy& policy)
|
||||||
|
{
|
||||||
|
return policy.available_write_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Policy>
|
||||||
|
static
|
||||||
|
void
|
||||||
|
transfer_read_bytes(
|
||||||
|
Policy& policy, std::size_t n)
|
||||||
|
{
|
||||||
|
return policy.transfer_read_bytes(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Policy>
|
||||||
|
static
|
||||||
|
void
|
||||||
|
transfer_write_bytes(
|
||||||
|
Policy& policy, std::size_t n)
|
||||||
|
{
|
||||||
|
return policy.transfer_write_bytes(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Policy>
|
||||||
|
static
|
||||||
|
void
|
||||||
|
on_timer(Policy& policy)
|
||||||
|
{
|
||||||
|
return policy.on_timer();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** A rate policy with unlimited throughput.
|
||||||
|
|
||||||
|
This rate policy places no restrictions on read and write
|
||||||
|
bandwidth utilization.
|
||||||
|
|
||||||
|
@par Concepts
|
||||||
|
|
||||||
|
@li <em>RatePolicy</em>
|
||||||
|
|
||||||
|
@see @ref beast::basic_stream
|
||||||
|
*/
|
||||||
|
class unlimited_rate_policy
|
||||||
|
{
|
||||||
|
static std::size_t constexpr all =
|
||||||
|
(std::numeric_limits<std::size_t>::max)();
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class rate_policy_access;
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_read_bytes()
|
||||||
|
{
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_write_bytes()
|
||||||
|
{
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_read_bytes(std::size_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_write_bytes(std::size_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_timer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** A rate policy with simple, configurable limits on read and write throughput.
|
||||||
|
|
||||||
|
This rate policy allows for simple individual limits on the amount
|
||||||
|
of bytes per second allowed for reads and writes.
|
||||||
|
|
||||||
|
@par Concepts
|
||||||
|
|
||||||
|
@li <em>RatePolicy</em>
|
||||||
|
|
||||||
|
@see @ref beast::basic_stream
|
||||||
|
*/
|
||||||
|
class simple_rate_policy
|
||||||
|
{
|
||||||
|
friend class rate_policy_access;
|
||||||
|
|
||||||
|
static std::size_t constexpr all =
|
||||||
|
std::numeric_limits<std::size_t>::max();
|
||||||
|
|
||||||
|
std::size_t rd_remain_ = all;
|
||||||
|
std::size_t wr_remain_ = all;
|
||||||
|
std::size_t rd_limit_ = all;
|
||||||
|
std::size_t wr_limit_ = all;
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_read_bytes()
|
||||||
|
{
|
||||||
|
return rd_remain_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t
|
||||||
|
available_write_bytes()
|
||||||
|
{
|
||||||
|
return wr_remain_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_read_bytes(std::size_t n)
|
||||||
|
{
|
||||||
|
if( rd_remain_ != all)
|
||||||
|
rd_remain_ =
|
||||||
|
(n < rd_remain_) ? rd_remain_ - n : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
transfer_write_bytes(std::size_t n)
|
||||||
|
{
|
||||||
|
if( wr_remain_ != all)
|
||||||
|
wr_remain_ =
|
||||||
|
(n < wr_remain_) ? wr_remain_ - n : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
on_timer()
|
||||||
|
{
|
||||||
|
rd_remain_ = rd_limit_;
|
||||||
|
wr_remain_ = wr_limit_;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// Set the limit of bytes per second to read
|
||||||
|
void
|
||||||
|
read_limit(std::size_t bytes_per_second)
|
||||||
|
{
|
||||||
|
rd_limit_ = bytes_per_second;
|
||||||
|
if( rd_remain_ > bytes_per_second)
|
||||||
|
rd_remain_ = bytes_per_second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the limit of bytes per second to write
|
||||||
|
void
|
||||||
|
write_limit(std::size_t bytes_per_second)
|
||||||
|
{
|
||||||
|
wr_limit_ = bytes_per_second;
|
||||||
|
if( wr_remain_ > bytes_per_second)
|
||||||
|
wr_remain_ = bytes_per_second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
@ -59,6 +59,7 @@ add_executable (tests-beast-core
|
|||||||
make_strand.cpp
|
make_strand.cpp
|
||||||
multi_buffer.cpp
|
multi_buffer.cpp
|
||||||
ostream.cpp
|
ostream.cpp
|
||||||
|
rate_policy.cpp
|
||||||
read_size.cpp
|
read_size.cpp
|
||||||
saved_handler.cpp
|
saved_handler.cpp
|
||||||
span.cpp
|
span.cpp
|
||||||
|
@ -47,6 +47,7 @@ local SOURCES =
|
|||||||
make_strand.cpp
|
make_strand.cpp
|
||||||
multi_buffer.cpp
|
multi_buffer.cpp
|
||||||
ostream.cpp
|
ostream.cpp
|
||||||
|
rate_policy.cpp
|
||||||
read_size.cpp
|
read_size.cpp
|
||||||
saved_handler.cpp
|
saved_handler.cpp
|
||||||
span.cpp
|
span.cpp
|
||||||
|
@ -31,6 +31,18 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template class basic_stream<
|
||||||
|
net::ip::tcp,
|
||||||
|
net::executor,
|
||||||
|
unlimited_rate_policy>;
|
||||||
|
|
||||||
|
template class basic_stream<
|
||||||
|
net::ip::tcp,
|
||||||
|
net::executor,
|
||||||
|
simple_rate_policy>;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<class Executor = net::io_context::executor_type>
|
template<class Executor = net::io_context::executor_type>
|
||||||
|
34
test/beast/core/rate_policy.cpp
Normal file
34
test/beast/core/rate_policy.cpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||||||
|
//
|
||||||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/core/rate_policy.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
class rate_policy_test : public unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
unlimited_rate_policy{};
|
||||||
|
simple_rate_policy{};
|
||||||
|
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,rate_policy);
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
Reference in New Issue
Block a user