use std::time::Duration;
pub const MAX_NEGOTIATION_ROUNDS: usize = 32;
pub const MAX_HAVES_PER_ROUND: usize = 16384;
pub const MAX_PACK_SIZE_BYTES: u64 = 64 * 1024 * 1024;
pub const MAX_REQUEST_BODY_BYTES: u64 = MAX_PACK_SIZE_BYTES;
pub const MAX_OBJECT_SIZE_BYTES: u64 = 512 * 1024 * 1024;
pub const SESSION_WALL_CLOCK: Duration = Duration::from_secs(30 * 60);
pub const MAX_CONCURRENT_BLOCKING_TASKS: usize = 8;
pub const MAX_ADVERTISEMENT_REFS: usize = 10_000;
pub const PACKLESS_PEEK: Duration = Duration::from_millis(750);
pub const SIDEBAND_CHUNK_SIZE: usize = 65000;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Limits {
pub max_negotiation_rounds: usize,
pub max_haves_per_round: usize,
pub max_pack_size: u64,
pub max_request_body: u64,
pub max_object_size: u64,
pub session_wall_clock: Duration,
pub max_concurrent_blocking_tasks: usize,
pub max_advertisement_refs: usize,
pub packless_peek: Duration,
}
impl Default for Limits {
fn default() -> Self {
Self {
max_negotiation_rounds: MAX_NEGOTIATION_ROUNDS,
max_haves_per_round: MAX_HAVES_PER_ROUND,
max_pack_size: MAX_PACK_SIZE_BYTES,
max_request_body: MAX_REQUEST_BODY_BYTES,
max_object_size: MAX_OBJECT_SIZE_BYTES,
session_wall_clock: SESSION_WALL_CLOCK,
max_concurrent_blocking_tasks: MAX_CONCURRENT_BLOCKING_TASKS,
max_advertisement_refs: MAX_ADVERTISEMENT_REFS,
packless_peek: PACKLESS_PEEK,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_match_the_adr009_direction_column() {
let limits = Limits::default();
assert!(
(10..=90).contains(&limits.max_negotiation_rounds),
"max negotiation rounds is the tens direction: {:?}",
limits.max_negotiation_rounds
);
assert!(
(5 * 60..=60 * 60).contains(&limits.session_wall_clock.as_secs()),
"session wall clock is the tens-of-minutes direction: {:?}",
limits.session_wall_clock
);
assert!(
(1..=32).contains(&limits.max_concurrent_blocking_tasks),
"max concurrent blocking tasks is the small-count direction: {:?}",
limits.max_concurrent_blocking_tasks
);
assert_eq!(
limits.max_request_body, limits.max_pack_size,
"max request body matches max pack size"
);
assert!(
limits.max_pack_size >= 10 * 1024 * 1024 && limits.max_pack_size <= 100 * 1024 * 1024,
"max pack size is the tens-of-MB direction: {:?}",
limits.max_pack_size
);
}
#[test]
fn haves_default_reaches_the_stateless_doubling_ceiling() {
assert!(
Limits::default().max_haves_per_round >= 16384,
"the client's stateless doubling legitimately reaches 16384"
);
}
#[test]
fn peek_default_is_the_adr020_datum() {
assert_eq!(Limits::default().packless_peek, Duration::from_millis(750));
assert_eq!(PACKLESS_PEEK, Duration::from_millis(750));
}
#[test]
fn sideband_chunk_size_is_a_fixed_crate_constant() {
assert_eq!(SIDEBAND_CHUNK_SIZE, 65000);
}
#[test]
fn object_size_default_is_the_large_blob_datum() {
assert!(
(64 * 1024 * 1024..=1024 * 1024 * 1024).contains(&Limits::default().max_object_size),
"the decompressed-size cap is the large-blob direction: above the \
pack default, well below the bomb-shaped declarations"
);
}
#[test]
fn constants_match_their_fields_in_default() {
let limits = Limits::default();
assert_eq!(limits.max_negotiation_rounds, MAX_NEGOTIATION_ROUNDS);
assert_eq!(limits.max_haves_per_round, MAX_HAVES_PER_ROUND);
assert_eq!(limits.max_pack_size, MAX_PACK_SIZE_BYTES);
assert_eq!(limits.max_request_body, MAX_REQUEST_BODY_BYTES);
assert_eq!(limits.max_object_size, MAX_OBJECT_SIZE_BYTES);
assert_eq!(limits.max_advertisement_refs, MAX_ADVERTISEMENT_REFS);
assert_eq!(limits.session_wall_clock, SESSION_WALL_CLOCK);
assert_eq!(
limits.max_concurrent_blocking_tasks,
MAX_CONCURRENT_BLOCKING_TASKS
);
}
}