Bounded WEB HTTP conveyor with replay-safe streaming downlink added

Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
Alexey
2026-10-03 16:02:18 +03:00
parent c4555e25f3
commit 823c6cbc7f
39 changed files with 2186 additions and 237 deletions
+5
View File
@@ -337,6 +337,11 @@ impl Drop for WebSocketBudgetLease {
}
impl WebProcessRuntime {
/// Reserves a parked future uplink without consuming the head request's capacity.
pub(crate) fn try_conveyor_waiter(&self) -> Option<OwnedSemaphorePermit> {
Arc::clone(&self.conveyor_waiters).try_acquire_owned().ok()
}
/// Reserves one body reader and its declared bounded body allocation.
pub(crate) fn try_body_budget(
&self,
+1
View File
@@ -136,6 +136,7 @@ impl WebProcessRuntime {
self.lane_aux_polls.close();
self.body_readers.close();
self.body_bytes.close();
self.conveyor_waiters.close();
self.stream_handshakes.close();
self.websocket_connections.close();
let sessions = {
+16
View File
@@ -130,6 +130,7 @@ pub(crate) struct CarrierRequest {
attempt: Option<u8>,
failure: Option<CarrierFailure>,
user_agent_hash: [u8; 32],
up_window: Option<u8>,
}
impl CarrierRequest {
@@ -141,6 +142,7 @@ impl CarrierRequest {
attempt: None,
failure: None,
user_agent_hash,
up_window: None,
}
}
@@ -152,6 +154,7 @@ impl CarrierRequest {
attempt: None,
failure: None,
user_agent_hash,
up_window: None,
}
}
@@ -169,9 +172,21 @@ impl CarrierRequest {
attempt: Some(attempt),
failure,
user_agent_hash,
up_window: None,
}
}
/// Attaches the separately validated HTTP conveyor capability.
pub(crate) const fn with_up_window(mut self, window: Option<u8>) -> Self {
self.up_window = window;
self
}
/// Returns the separately advertised HTTP conveyor capability.
pub(crate) const fn up_window(self) -> Option<u8> {
self.up_window
}
/// Returns whether this request participates in server-side negotiation.
pub(crate) const fn is_automatic(self) -> bool {
self.capabilities.is_some()
@@ -215,6 +230,7 @@ impl CarrierRequest {
self.class == other.class
&& self.capabilities_bits() == other.capabilities_bits()
&& self.user_agent_hash == other.user_agent_hash
&& self.up_window == other.up_window
}
/// Checks the complete idempotent identity of one exact attempt request.
+7
View File
@@ -125,6 +125,7 @@ impl WebProcessRuntime {
entry.carrier_phase.as_str()
};
let result = CreateResult {
up_window: carrier_request.up_window().map(|_| session.up_window()),
token: entry.session_token.as_str().to_owned(),
carrier: session.carrier(),
attempt: carrier_request.attempt(),
@@ -357,6 +358,11 @@ impl WebProcessRuntime {
issued_timeouts.clone(),
Some(user_registration),
);
session.configure_conveyor(if config.web.conveyor {
carrier_request.up_window().unwrap_or(1)
} else {
1
});
state.sessions.insert(session_hash, Arc::clone(&session));
*state.sessions_per_ip.entry(client_ip).or_insert(0) += 1;
*state.sessions_per_profile.entry(profile_key).or_insert(0) += 1;
@@ -399,6 +405,7 @@ impl WebProcessRuntime {
}
let identity = session.trace_identity();
let result = CreateResult {
up_window: carrier_request.up_window().map(|_| session.up_window()),
token: session_token,
carrier,
attempt: carrier_request.attempt(),
@@ -104,6 +104,7 @@ impl WebProcessRuntime {
replacement.old_session.timeouts().clone(),
Some(user_registration),
);
session.configure_conveyor(replacement.old_session.conveyor_offer());
let Some(supersede) = replacement.old_session.prepare_carrier_supersede() else {
drop(user_publication);
drop(state);
@@ -149,6 +150,7 @@ impl WebProcessRuntime {
crate::web::session::SessionCloseReason::CarrierSuperseded,
);
let result = CreateResult {
up_window: replacement.request.up_window().map(|_| session.up_window()),
token: session_token,
carrier: replacement.carrier,
attempt: Some(replacement.attempt),