/src/samba/third_party/ngtcp2/lib/ngtcp2_ratelim.c
Line | Count | Source |
1 | | /* |
2 | | * ngtcp2 |
3 | | * |
4 | | * Copyright (c) 2025 ngtcp2 contributors |
5 | | * Copyright (c) 2023 nghttp2 contributors |
6 | | * |
7 | | * Permission is hereby granted, free of charge, to any person obtaining |
8 | | * a copy of this software and associated documentation files (the |
9 | | * "Software"), to deal in the Software without restriction, including |
10 | | * without limitation the rights to use, copy, modify, merge, publish, |
11 | | * distribute, sublicense, and/or sell copies of the Software, and to |
12 | | * permit persons to whom the Software is furnished to do so, subject to |
13 | | * the following conditions: |
14 | | * |
15 | | * The above copyright notice and this permission notice shall be |
16 | | * included in all copies or substantial portions of the Software. |
17 | | * |
18 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
19 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
20 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
21 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
22 | | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
23 | | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
24 | | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | | */ |
26 | | #include "ngtcp2_ratelim.h" |
27 | | |
28 | | #include <assert.h> |
29 | | |
30 | | #include "ngtcp2_macro.h" |
31 | | |
32 | | void ngtcp2_ratelim_init(ngtcp2_ratelim *rlim, uint64_t burst, uint64_t rate, |
33 | 0 | ngtcp2_tstamp ts) { |
34 | 0 | *rlim = (ngtcp2_ratelim){ |
35 | 0 | .burst = burst, |
36 | 0 | .rate = rate, |
37 | 0 | .tokens = burst, |
38 | 0 | .ts = ts, |
39 | 0 | }; |
40 | 0 | } |
41 | | |
42 | | /* ratelim_update updates rlim->tokens with the current |ts|. */ |
43 | 0 | static void ratelim_update(ngtcp2_ratelim *rlim, ngtcp2_tstamp ts) { |
44 | 0 | uint64_t d, gain, gps; |
45 | |
|
46 | 0 | assert(ts >= rlim->ts); |
47 | |
|
48 | 0 | if (ts == rlim->ts) { |
49 | 0 | return; |
50 | 0 | } |
51 | | |
52 | 0 | d = ts - rlim->ts; |
53 | 0 | rlim->ts = ts; |
54 | |
|
55 | 0 | if (rlim->rate > (UINT64_MAX - rlim->carry) / d) { |
56 | 0 | gain = UINT64_MAX; |
57 | 0 | } else { |
58 | 0 | gain = rlim->rate * d + rlim->carry; |
59 | 0 | } |
60 | |
|
61 | 0 | gps = gain / NGTCP2_SECONDS; |
62 | |
|
63 | 0 | if (gps < rlim->burst && rlim->tokens < rlim->burst - gps) { |
64 | 0 | rlim->tokens += gps; |
65 | 0 | rlim->carry = gain % NGTCP2_SECONDS; |
66 | |
|
67 | 0 | return; |
68 | 0 | } |
69 | | |
70 | 0 | rlim->tokens = rlim->burst; |
71 | 0 | rlim->carry = 0; |
72 | 0 | } |
73 | | |
74 | 0 | int ngtcp2_ratelim_drain(ngtcp2_ratelim *rlim, uint64_t n, ngtcp2_tstamp ts) { |
75 | 0 | ratelim_update(rlim, ts); |
76 | |
|
77 | 0 | if (rlim->tokens < n) { |
78 | 0 | return -1; |
79 | 0 | } |
80 | | |
81 | 0 | rlim->tokens -= n; |
82 | |
|
83 | 0 | return 0; |
84 | 0 | } |