@@ -5,18 +5,17 @@ use std::{
55} ;
66
77use instant:: Instant ;
8- use libp2p:: { request_response :: InboundRequestId , PeerId } ;
8+ use libp2p:: PeerId ;
99use nimiq_network_interface:: request:: { RequestCommon , RequestType } ;
10- use parking_lot:: Mutex ;
1110
1211/// The rate limiting request metadata that will be passed on between the network and the swarm.
1312/// This is not sent through the wire.
1413#[ derive( Debug , PartialEq ) ]
1514pub ( crate ) struct RequestRateLimitData {
1615 /// Maximum requests allowed by this request type.
17- max_requests : u32 ,
16+ pub ( crate ) max_requests : u32 ,
1817 /// The range/window of time of this request type.
19- time_window : Duration ,
18+ pub ( crate ) time_window : Duration ,
2019}
2120
2221impl RequestRateLimitData {
@@ -163,26 +162,27 @@ impl RateLimit {
163162 }
164163}
165164
166- // Network helpers for rate limiting
165+ // Rate limiting overarching structure. It holds the rate limits by peer and request type.
166+ // This handles the case of a peer reconnecting within the time window to attempt to bypass the rate limits established.
167167#[ derive( Default ) ]
168168pub ( crate ) struct RateLimits {
169- peer_request_limits : Mutex < HashMap < PeerId , HashMap < RequestType , RateLimit > > > ,
170- rate_limits_pending_deletion : Mutex < PendingDeletion > ,
169+ /// The rate limits per active peer.
170+ peer_request_limits : HashMap < PeerId , HashMap < RequestType , RateLimit > > ,
171+ /// All the pending deletion rate limits.
172+ rate_limits_pending_deletion : PendingDeletion ,
171173}
172174
173175impl RateLimits {
176+ /// Increases the counter of the rate limit and returns a bool in case the defined rate limit is surpassed.
174177 pub ( crate ) fn exceeds_rate_limit (
175178 & mut self ,
176179 peer_id : PeerId ,
177180 request_type : RequestType ,
178- request_id : InboundRequestId ,
179181 request_rate_limit_data : & RequestRateLimitData ,
180182 ) -> bool {
181- // Gets lock of peer requests limits read and write on it.
182- let mut peer_request_limits = self . peer_request_limits . lock ( ) ;
183-
184183 // If the peer has never sent a request of this type, creates a new entry.
185- let requests_limit = peer_request_limits
184+ let requests_limit = self
185+ . peer_request_limits
186186 . entry ( peer_id)
187187 . or_default ( )
188188 . entry ( request_type)
@@ -195,67 +195,44 @@ impl RateLimits {
195195 } ) ;
196196
197197 // Ensures that the request is allowed based on the set limits and updates the counter.
198- // Returns early if not allowed.
199- if !requests_limit. increment_and_is_allowed ( 1 ) {
200- info ! (
201- %request_id,
202- %peer_id,
203- %request_type,
204- "Rate limit was exceeded!" ,
205- ) ;
206- log:: debug!(
207- "[{:?}][{:?}] {:?} Exceeded max requests rate {:?} requests per {:?} seconds" ,
208- request_id,
209- peer_id,
210- request_type,
211- request_rate_limit_data. max_requests,
212- request_rate_limit_data. time_window,
213- ) ;
214- return true ;
215- }
216-
217- false
198+ !requests_limit. increment_and_is_allowed ( 1 )
218199 }
219200
201+ /// Mark all rate limits of a given peer as pending for deletion.
202+ /// Every time this is called the expired rate limits will get delete pruned.
220203 pub ( crate ) fn remove_rate_limits ( & mut self , peer_id : PeerId ) {
221204 // Every time a peer disconnects, we delete all expired pending limits.
222205 self . clean_up ( ) ;
223206
224- // Firstly we must acquire the lock of the pending deletes to avoid deadlocks.
225- let mut rate_limits_pending_deletion_l = self . rate_limits_pending_deletion . lock ( ) ;
226- let mut peer_request_limits_l = self . peer_request_limits . lock ( ) ;
227-
228207 // Go through all existing request types of the given peer and deletes the limit counters if possible or marks it for deletion.
229- if let Some ( request_limits) = peer_request_limits_l . get_mut ( & peer_id) {
208+ if let Some ( request_limits) = self . peer_request_limits . get_mut ( & peer_id) {
230209 request_limits. retain ( |req_type, rate_limit| {
231210 // Gets the requests limit and deletes it if no counter info would be lost, otherwise places it as pending deletion.
232211 if !rate_limit. can_delete ( Instant :: now ( ) ) {
233- rate_limits_pending_deletion_l. insert ( peer_id, * req_type, rate_limit) ;
212+ self . rate_limits_pending_deletion
213+ . insert ( peer_id, * req_type, rate_limit) ;
234214 true
235215 } else {
236216 false
237217 }
238218 } ) ;
239219 // If the peer no longer has any pending rate limits, then it gets removed.
240220 if request_limits. is_empty ( ) {
241- peer_request_limits_l . remove ( & peer_id) ;
221+ self . peer_request_limits . remove ( & peer_id) ;
242222 }
243223 }
244224 }
245225
246226 /// Deletes the rate limits that were previously marked as pending if its expiration time has passed.
247227 fn clean_up ( & mut self ) {
248- let mut rate_limits_pending_deletion_l = self . rate_limits_pending_deletion . lock ( ) ;
249-
250228 // Iterates from the oldest to the most recent expiration date and deletes the entries that have expired.
251229 // The pending to deletion is ordered from the oldest to the most recent expiration date, thus we break early
252230 // from the loop once we find a non expired rate limit.
253- while let Some ( peer_expiration) = rate_limits_pending_deletion_l . first ( ) {
231+ while let Some ( peer_expiration) = self . rate_limits_pending_deletion . first ( ) {
254232 let current_timestamp = Instant :: now ( ) ;
255233 if peer_expiration. expiration_time <= current_timestamp {
256- let mut peer_request_limits_l = self . peer_request_limits . lock ( ) ;
257-
258- if let Some ( peer_req_limits) = peer_request_limits_l
234+ if let Some ( peer_req_limits) = self
235+ . peer_request_limits
259236 . get_mut ( & peer_expiration. peer_id )
260237 . and_then ( |peer_req_limits| {
261238 if let Some ( rate_limit) = peer_req_limits. get ( & peer_expiration. req_type ) {
@@ -272,7 +249,7 @@ impl RateLimits {
272249 {
273250 // If the peer no longer has any pending rate limits, then it gets removed from both rate limits and pending deletion.
274251 if peer_req_limits. is_empty ( ) {
275- peer_request_limits_l . remove ( & peer_expiration. peer_id ) ;
252+ self . peer_request_limits . remove ( & peer_expiration. peer_id ) ;
276253 }
277254 } else {
278255 // If the information is in pending deletion, that should mean it was not deleted from peer_request_limits yet, so that
@@ -282,7 +259,7 @@ impl RateLimits {
282259 ) ;
283260 }
284261 // Removes the entry from the pending for deletion.
285- rate_limits_pending_deletion_l . remove_first ( ) ;
262+ self . rate_limits_pending_deletion . remove_first ( ) ;
286263 } else {
287264 break ;
288265 }
0 commit comments