///|
pub(all) struct AgeCalculation {
apparent_age : DeltaSeconds
response_delay : DeltaSeconds
age_value : DeltaSeconds
corrected_age_value : DeltaSeconds
corrected_initial_age : DeltaSeconds
resident_time : DeltaSeconds
current_age : DeltaSeconds
clock_clamped : Bool
overflow_clamped : Bool
} derive(Eq, Debug)
///|
fn add_delta_with_overflow(
left : DeltaSeconds,
right : DeltaSeconds,
) -> (DeltaSeconds, Bool) {
let overflow = left.seconds() > MAX_DELTA_SECONDS - right.seconds()
(left.saturating_add(right), overflow)
}
///|
fn response_age_value(response : ResponseMeta) -> DeltaSeconds {
match response.headers.get_first("age") {
Some(value) => parse_delta_seconds(value).unwrap_or(DeltaSeconds::zero())
None => DeltaSeconds::zero()
}
}
///|
/// Calculate corrected current age according to RFC 9111 section 4.2.3.
pub fn calculate_current_age(
response : ResponseMeta,
now : Timestamp,
) -> AgeCalculation {
let parsed_date = match response.headers.get_first("date") {
Some(value) => parse_http_date(value)
None => None
}
let date_value = parsed_date.unwrap_or(response.response_time)
let apparent_age = response.response_time.elapsed_since(date_value)
let response_delay = response.response_time.elapsed_since(
response.request_time,
)
let age_value = response_age_value(response)
let (corrected_age_value, first_overflow) = add_delta_with_overflow(
age_value, response_delay,
)
let corrected_initial_age = apparent_age.max(corrected_age_value)
let resident_time = now.elapsed_since(response.response_time)
let (current_age, second_overflow) = add_delta_with_overflow(
corrected_initial_age, resident_time,
)
AgeCalculation::{
apparent_age,
response_delay,
age_value,
corrected_age_value,
corrected_initial_age,
resident_time,
current_age,
clock_clamped: date_value.seconds() > response.response_time.seconds() ||
response.request_time.seconds() > response.response_time.seconds() ||
response.response_time.seconds() > now.seconds(),
overflow_clamped: first_overflow || second_overflow,
}
}