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 
10 #ifndef BOOST_BEAST_CORE_RATE_POLICY_HPP
11 #define BOOST_BEAST_CORE_RATE_POLICY_HPP
12 
13 #include <boost/beast/core/detail/config.hpp>
14 #include <cstdint>
15 #include <limits>
16 
17 namespace boost {
18 namespace beast {
19 
20 /** Helper class to assist implementing a <em>RatePolicy</em>.
21 
22     This class is used by the implementation to gain access to the
23     private members of a user-defined object meeting the requirements
24     of <em>RatePolicy</em>. To use it, simply declare it as a friend
25     in your class:
26 
27     @par Example
28     @code
29     class custom_rate_policy
30     {
31         friend class beast::rate_policy_access;
32         ...
33     @endcode
34 
35     @par Concepts
36 
37     @li <em>RatePolicy</em>
38 
39     @see beast::basic_stream
40 */
41 class rate_policy_access
42 {
43 private:
44     template<class, class, class>
45     friend class basic_stream;
46 
47     template<class Policy>
48     static
49     std::size_t
available_read_bytes(Policy & policy)50     available_read_bytes(Policy& policy)
51     {
52         return policy.available_read_bytes();
53     }
54 
55     template<class Policy>
56     static
57     std::size_t
available_write_bytes(Policy & policy)58     available_write_bytes(Policy& policy)
59     {
60         return policy.available_write_bytes();
61     }
62 
63     template<class Policy>
64     static
65     void
transfer_read_bytes(Policy & policy,std::size_t n)66     transfer_read_bytes(
67         Policy& policy, std::size_t n)
68     {
69         return policy.transfer_read_bytes(n);
70     }
71 
72     template<class Policy>
73     static
74     void
transfer_write_bytes(Policy & policy,std::size_t n)75     transfer_write_bytes(
76         Policy& policy, std::size_t n)
77     {
78         return policy.transfer_write_bytes(n);
79     }
80 
81     template<class Policy>
82     static
83     void
on_timer(Policy & policy)84     on_timer(Policy& policy)
85     {
86         return policy.on_timer();
87     }
88 };
89 
90 //------------------------------------------------------------------------------
91 
92 /** A rate policy with unlimited throughput.
93 
94     This rate policy object does not apply any rate limit.
95 
96     @par Concepts
97 
98     @li <em>RatePolicy</em>
99 
100     @see beast::basic_stream, beast::tcp_stream
101 */
102 class unlimited_rate_policy
103 {
104     friend class rate_policy_access;
105 
106     static std::size_t constexpr all =
107         (std::numeric_limits<std::size_t>::max)();
108 
109     std::size_t
available_read_bytes() const110     available_read_bytes() const noexcept
111     {
112         return all;
113     }
114 
115     std::size_t
available_write_bytes() const116     available_write_bytes() const noexcept
117     {
118         return all;
119     }
120 
121     void
transfer_read_bytes(std::size_t) const122     transfer_read_bytes(std::size_t) const noexcept
123     {
124     }
125 
126     void
transfer_write_bytes(std::size_t) const127     transfer_write_bytes(std::size_t) const noexcept
128     {
129     }
130 
131     void
on_timer() const132     on_timer() const noexcept
133     {
134     }
135 };
136 
137 //------------------------------------------------------------------------------
138 
139 /** A rate policy with simple, configurable limits on reads and writes.
140 
141     This rate policy allows for simple individual limits on the amount
142     of bytes per second allowed for reads and writes.
143 
144     @par Concepts
145 
146     @li <em>RatePolicy</em>
147 
148     @see beast::basic_stream
149 */
150 class simple_rate_policy
151 {
152     friend class rate_policy_access;
153 
154     static std::size_t constexpr all =
155         (std::numeric_limits<std::size_t>::max)();
156 
157     std::size_t rd_remain_ = all;
158     std::size_t wr_remain_ = all;
159     std::size_t rd_limit_ = all;
160     std::size_t wr_limit_ = all;
161 
162     std::size_t
available_read_bytes() const163     available_read_bytes() const noexcept
164     {
165         return rd_remain_;
166     }
167 
168     std::size_t
available_write_bytes() const169     available_write_bytes() const noexcept
170     {
171         return wr_remain_;
172     }
173 
174     void
transfer_read_bytes(std::size_t n)175     transfer_read_bytes(std::size_t n) noexcept
176     {
177         if( rd_remain_ != all)
178             rd_remain_ =
179                 (n < rd_remain_) ? rd_remain_ - n : 0;
180     }
181 
182     void
transfer_write_bytes(std::size_t n)183     transfer_write_bytes(std::size_t n) noexcept
184     {
185         if( wr_remain_ != all)
186             wr_remain_ =
187                 (n < wr_remain_) ? wr_remain_ - n : 0;
188     }
189 
190     void
on_timer()191     on_timer() noexcept
192     {
193         rd_remain_ = rd_limit_;
194         wr_remain_ = wr_limit_;
195     }
196 
197 public:
198     /// Set the limit of bytes per second to read
199     void
read_limit(std::size_t bytes_per_second)200     read_limit(std::size_t bytes_per_second) noexcept
201     {
202         rd_limit_ = bytes_per_second;
203         if( rd_remain_ > bytes_per_second)
204             rd_remain_ = bytes_per_second;
205     }
206 
207     /// Set the limit of bytes per second to write
208     void
write_limit(std::size_t bytes_per_second)209     write_limit(std::size_t bytes_per_second) noexcept
210     {
211         wr_limit_ = bytes_per_second;
212         if( wr_remain_ > bytes_per_second)
213             wr_remain_ = bytes_per_second;
214     }
215 };
216 
217 } // beast
218 } // boost
219 
220 #endif
221