mirror of
https://github.com/telemt/telemt.git
synced 2026-11-02 05:42:00 +03:00
WEB Data Budget: Session effects until after state unlock deferred
This commit is contained in:
+45
-24
@@ -9,8 +9,8 @@ use subtle::ConstantTimeEq;
|
||||
|
||||
use super::backend::StreamCompletion;
|
||||
use super::{
|
||||
InboundChunk, PendingClass, QUEUE_ITEM_COST, SessionCloseReason, SessionState, StreamIdentity,
|
||||
StreamState, WebSession, inbound_queue_cost,
|
||||
DeferredSessionEffects, InboundChunk, PendingClass, QUEUE_ITEM_COST, SessionCloseReason,
|
||||
SessionState, StreamIdentity, StreamState, WebSession, inbound_queue_cost,
|
||||
};
|
||||
use crate::web::frame::{self, Frame, FrameType};
|
||||
use crate::web::manager::{ManagerError, TokenHash};
|
||||
@@ -99,6 +99,7 @@ impl WebSession {
|
||||
let mut opened = Vec::new();
|
||||
let mut committed = false;
|
||||
let mut healthy = None;
|
||||
let mut effects = DeferredSessionEffects::new();
|
||||
let result = {
|
||||
let mut state = self.state.lock();
|
||||
if state.closed {
|
||||
@@ -141,13 +142,20 @@ impl WebSession {
|
||||
let applied = self.apply_batch_locked(
|
||||
&mut state,
|
||||
&frames,
|
||||
&mut effects,
|
||||
&mut opened,
|
||||
&mut None,
|
||||
&mut unused_bytes,
|
||||
&mut unused_items,
|
||||
&mut progress,
|
||||
);
|
||||
self.release_locked(&mut state, unused_bytes, unused_items, false);
|
||||
self.release_locked(
|
||||
&mut state,
|
||||
&mut effects,
|
||||
unused_bytes,
|
||||
unused_items,
|
||||
false,
|
||||
);
|
||||
if !applied {
|
||||
Err(ManagerError::Closed)
|
||||
} else {
|
||||
@@ -157,6 +165,7 @@ impl WebSession {
|
||||
Ok((sequence, progress.any()))
|
||||
}
|
||||
};
|
||||
effects.finish();
|
||||
if matches!(result, Err(ManagerError::Backpressure)) {
|
||||
return result;
|
||||
}
|
||||
@@ -190,6 +199,7 @@ impl WebSession {
|
||||
self: &Arc<Self>,
|
||||
state: &mut SessionState,
|
||||
frames: &[Frame<'_>],
|
||||
effects: &mut DeferredSessionEffects,
|
||||
opened: &mut Vec<StreamCompletion>,
|
||||
reserved_open: &mut Option<(u32, u16)>,
|
||||
unused_bytes: &mut usize,
|
||||
@@ -218,10 +228,11 @@ impl WebSession {
|
||||
return false;
|
||||
}
|
||||
None => {
|
||||
let Some(peer_port) = self.reserve_stream_locked(state) else {
|
||||
self.remember_closed_locked(state, value.stream_id);
|
||||
let Some(peer_port) = self.reserve_stream_locked(state, effects) else {
|
||||
self.remember_closed_locked(state, effects, value.stream_id);
|
||||
if !self.queue_control_locked(
|
||||
state,
|
||||
effects,
|
||||
FrameType::Close,
|
||||
value.stream_id,
|
||||
&[],
|
||||
@@ -233,7 +244,7 @@ impl WebSession {
|
||||
peer_port
|
||||
}
|
||||
};
|
||||
state.streams.insert(
|
||||
if let Some(previous) = state.streams.insert(
|
||||
value.stream_id,
|
||||
StreamState {
|
||||
instance: stream.instance,
|
||||
@@ -243,7 +254,9 @@ impl WebSession {
|
||||
read_waker: None,
|
||||
write_waker: None,
|
||||
},
|
||||
);
|
||||
) {
|
||||
effects.retain_stream(previous);
|
||||
}
|
||||
progress.accepted_open = true;
|
||||
opened.push(self.own_stream_task(stream, peer_port));
|
||||
}
|
||||
@@ -261,7 +274,7 @@ impl WebSession {
|
||||
unused_bytes.saturating_sub(value.payload.len() + QUEUE_ITEM_COST);
|
||||
*unused_items = unused_items.saturating_sub(1);
|
||||
if let Some(waker) = stream.read_waker.take() {
|
||||
waker.wake();
|
||||
effects.wake(waker);
|
||||
}
|
||||
}
|
||||
FrameType::Window if !was_closed => {
|
||||
@@ -274,7 +287,7 @@ impl WebSession {
|
||||
.saturating_add(u64::from(amount))
|
||||
.min(u64::from(u32::MAX));
|
||||
if let Some(waker) = stream.write_waker.take() {
|
||||
waker.wake();
|
||||
effects.wake(waker);
|
||||
}
|
||||
}
|
||||
FrameType::Close if !was_closed => {
|
||||
@@ -285,13 +298,13 @@ impl WebSession {
|
||||
.closing_streams
|
||||
.insert(value.stream_id, stream.instance);
|
||||
let (bytes, items) = inbound_queue_cost(&stream.inbound);
|
||||
self.release_locked(state, bytes, items, false);
|
||||
self.remember_closed_locked(state, value.stream_id);
|
||||
self.release_locked(state, effects, bytes, items, false);
|
||||
self.remember_closed_locked(state, effects, value.stream_id);
|
||||
if let Some(waker) = stream.read_waker {
|
||||
waker.wake();
|
||||
effects.wake(waker);
|
||||
}
|
||||
if let Some(waker) = stream.write_waker {
|
||||
waker.wake();
|
||||
effects.wake(waker);
|
||||
}
|
||||
}
|
||||
FrameType::Data | FrameType::Window | FrameType::Close => {}
|
||||
@@ -301,7 +314,11 @@ impl WebSession {
|
||||
true
|
||||
}
|
||||
|
||||
fn reserve_stream_locked(&self, state: &mut SessionState) -> Option<u16> {
|
||||
fn reserve_stream_locked(
|
||||
&self,
|
||||
state: &mut SessionState,
|
||||
effects: &mut DeferredSessionEffects,
|
||||
) -> Option<u16> {
|
||||
let manager = self.manager.upgrade()?;
|
||||
if state.active_peer_ports.len() >= self.profile.max_streams_per_session {
|
||||
manager.record_stream_rejected_reason(
|
||||
@@ -309,23 +326,27 @@ impl WebSession {
|
||||
);
|
||||
return None;
|
||||
}
|
||||
let peer_port = manager
|
||||
.try_acquire_stream(
|
||||
self.profile_key,
|
||||
self.profile.max_streams,
|
||||
self.client_ip,
|
||||
self.profile.public_addr,
|
||||
)
|
||||
.ok()?;
|
||||
let (peer_port, notify) = manager.try_acquire_stream_quiet(
|
||||
self.profile_key,
|
||||
self.profile.max_streams,
|
||||
self.client_ip,
|
||||
self.profile.public_addr,
|
||||
);
|
||||
if let Some(notify) = notify {
|
||||
effects.notify(notify);
|
||||
}
|
||||
let peer_port = peer_port.ok()?;
|
||||
if state.active_peer_ports.insert(peer_port) {
|
||||
return Some(peer_port);
|
||||
}
|
||||
manager.release_stream(
|
||||
if let Some(notify) = manager.release_stream_quiet(
|
||||
self.profile_key,
|
||||
self.client_ip,
|
||||
self.profile.public_addr,
|
||||
peer_port,
|
||||
);
|
||||
) {
|
||||
effects.notify(notify);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user