feat(server): enforce rate and session lifetime #80

Merged
Lochnair merged 3 commits from feat/server-lifecycle-policy into main 2026-08-12 18:06:55 +00:00
2 changed files with 18 additions and 1 deletions
Showing only changes of commit c7537b9c42 - Show all commits

No files matched your search

+7 -1
View File
2
@@ -80,7 +80,13 @@ pub(crate) fn negotiate_params(mut requested: Params, config: &ServerConfig) ->
if requested.interval_ns < minimum {
requested.interval_ns = minimum;
}
let idle_cap = saturating_ns(config.idle_timeout()) / 4;
// Divided as a `Duration`, before the conversion rather than after it. The
// two agree for every timeout `i64` nanoseconds can hold, but saturating
// first would cap an absurdly long timeout's quarter at `i64::MAX / 4` —
// reducing intervals the configured cap never meant to reach — where
// dividing first leaves every representable interval alone, which is what a
// timeout beyond the wire's range should do.
let idle_cap = saturating_ns(config.idle_timeout() / 4);
if idle_cap > 0 && requested.interval_ns > idle_cap {
requested.interval_ns = idle_cap;
}
@@ -118,6 +118,17 @@ fn a_negotiated_interval_is_capped_at_a_quarter_of_the_idle_timeout() {
negotiated(config, &requesting(3_000_000_000, 5_000_000_000)).interval_ns,
2_000_000_000
);
// A timeout whose quarter is past what the wire can express caps nothing,
// because no representable interval reaches it. The quarter is taken before
// the conversion to nanoseconds for exactly this reason: saturating first
// would put the cap at a quarter of `i64::MAX` and reduce a long interval
// the configured timeout never meant to touch.
let absurd = ServerConfig::default().with_idle_timeout(Duration::MAX);
assert_eq!(
negotiated(absurd, &requesting(3_000_000_000, i64::MAX)).interval_ns,
i64::MAX
);
}
#[test]