payload_bytes_for_frame: closed form instead of a search; serve checks the plain limits before the frame

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-10-28 06:16:11 +01:00
commit 41c75bb9e7
2 changed files with 22 additions and 22 deletions

View file

@ -65,20 +65,20 @@ pub fn frame_bytes_for_payload(ciphertext_len: usize) -> usize {
/// the inverse of [`frame_bytes_for_payload`]. `None` when the frame cannot
/// carry even an empty envelope.
pub fn payload_bytes_for_frame(max_frame_bytes: usize) -> Option<usize> {
if frame_bytes_for_payload(0) > max_frame_bytes {
return None;
}
// frame_bytes_for_payload is increasing; the answer is at most half the frame.
let (mut low, mut high) = (0, max_frame_bytes / 2);
while low < high {
let mid = low + (high - low).div_ceil(2);
if frame_bytes_for_payload(mid) <= max_frame_bytes {
low = mid;
} else {
high = mid - 1;
}
}
Some(low)
// frame_bytes_for_payload(0) is the shell plus a one-byte array header.
let fixed = frame_bytes_for_payload(0) - 1;
let room = max_frame_bytes.checked_sub(fixed)?;
// Each array header width bounds the payloads it can describe; the
// widest payload any width admits is the answer.
let by_header = |header: usize, cap: usize| room.checked_sub(header).map(|r| (r / 2).min(cap));
[
by_header(5, usize::MAX),
by_header(3, 65_535),
by_header(1, 15),
]
.into_iter()
.flatten()
.max()
}
pub fn encrypt_invocation(

View file

@ -52,14 +52,6 @@ impl ServeLimits {
/// An admitted payload therefore always fits, and `complete` is given the
/// same frame bound to fit every result in.
fn validate(&self, admissions: &[CallerAdmission]) -> Result<(), ServeError> {
let smallest = frame_bytes_for_payload(MIN_PAYLOAD_BYTES);
if self.max_frame_bytes > 0 && self.max_frame_bytes < smallest {
return Err(ServeError::FrameBound {
max_frame_bytes: self.max_frame_bytes,
payload_bytes: MIN_PAYLOAD_BYTES,
needed_frame_bytes: smallest,
});
}
if self.max_frame_bytes == 0
|| self.max_frame_bytes > u32::MAX as usize
|| self.max_connections == 0
@ -68,6 +60,14 @@ impl ServeLimits {
{
return Err(ServeError::InvalidConfig("serve limits"));
}
let smallest = frame_bytes_for_payload(MIN_PAYLOAD_BYTES);
if self.max_frame_bytes < smallest {
return Err(ServeError::FrameBound {
max_frame_bytes: self.max_frame_bytes,
payload_bytes: MIN_PAYLOAD_BYTES,
needed_frame_bytes: smallest,
});
}
if admissions.is_empty() {
return Err(ServeError::InvalidConfig("callers"));
}