pub struct UdpFlow {
pub client: SocketAddr,
pub backend_id: Option<String>,
pub backend_addr: Option<SocketAddr>,
pub phase: FlowPhase,
pub config: ClusterConfig,
pub requests_seen: u32,
pub responses_seen: u32,
pub idle_deadline: Instant,
pub timer_gen: u64,
pub first_upstream_pending: bool,
pub pending_payload: Option<Vec<u8>>,
}Expand description
Per-admitted-flow state. Slab slot payload owned by the manager.
Fields§
§client: SocketAddrReal (pre-NAT) client source address — the symmetric NAT return target and the PPv2 source address.
backend_id: Option<String>Resolved backend id, set on BackendResolved.
backend_addr: Option<SocketAddr>Resolved backend address, set on BackendResolved.
phase: FlowPhaseLifecycle phase.
config: ClusterConfigCaptured per-cluster knobs (responses/requests/timeouts/PPv2). Captured at admission so a mid-flow reconfig does not change a live flow’s teardown contract (stable affinity).
requests_seen: u32Client datagrams forwarded so far (counts toward requests).
responses_seen: u32Backend replies returned so far (counts toward responses).
idle_deadline: InstantAbsolute idle deadline; reset on every datagram in either direction.
timer_gen: u64Generation token. Incremented every time the idle deadline is pushed back. A wheel expiry only closes the flow when its captured generation still matches — defeating the stale-close busy-loop bug.
first_upstream_pending: boolTrue until the first upstream datagram is sent; gates PPv2 prefixing
when proxy_protocol_every_datagram is false (first-datagram-only).
pending_payload: Option<Vec<u8>>One-slot buffer for a client datagram that arrived while
AwaitingBackend. Flushed on
BackendResolved. A second datagram in the window replaces it (newest
wins) rather than allocating an unbounded queue.
Implementations§
Source§impl UdpFlow
impl UdpFlow
Sourcepub fn new(client: SocketAddr, config: ClusterConfig, now: Instant) -> Self
pub fn new(client: SocketAddr, config: ClusterConfig, now: Instant) -> Self
Create a flow for client, awaiting a backend, with its idle deadline
armed front_timeout from now.
Sourcepub fn touch(&mut self, timeout: Duration, now: Instant) -> u64
pub fn touch(&mut self, timeout: Duration, now: Instant) -> u64
Push the idle deadline back to now + timeout and bump the generation
token so any in-flight wheel expiry for the old deadline is invalidated.
Returns the new generation so the manager can re-arm the wheel.
Sourcepub fn on_client_datagram(&mut self, now: Instant) -> u64
pub fn on_client_datagram(&mut self, now: Instant) -> u64
Record that one client datagram was actually forwarded upstream: bump
the requests counter and refresh the front idle deadline. Returns the
new generation token. Call this only at a real forward site — a datagram
merely buffered while AwaitingBackend and
later overwritten (newest-wins) must NOT count, or a burst during await
could trip the requests cap having delivered fewer than requests
datagrams. Use touch for the buffer-only idle refresh.
Sourcepub fn on_backend_datagram(&mut self, now: Instant) -> u64
pub fn on_backend_datagram(&mut self, now: Instant) -> u64
Record that one backend reply was returned; refresh the back idle deadline. Returns the new generation token.
Sourcepub fn set_phase(&mut self, next: FlowPhase)
pub fn set_phase(&mut self, next: FlowPhase)
Transition the flow to next, asserting the move is legal. The lifecycle
is strictly forward: AwaitingBackend → Established → Closing, with a
self-loop allowed only into Closing (idempotent close). A backward move
(Established → AwaitingBackend) or skipping straight from
AwaitingBackend → Closing is allowed only into Closing (a flow may
be aborted before it establishes); every other transition is a bug.
Debug-only guard — the assignment itself is unconditional so release behavior is identical.
Sourcepub fn requests_exhausted(&self) -> bool
pub fn requests_exhausted(&self) -> bool
Whether the requests knob has been exhausted (0 = unlimited).
Sourcepub fn responses_exhausted(&self) -> bool
pub fn responses_exhausted(&self) -> bool
Whether the responses knob has been exhausted (0 = unlimited). A DNS
flow with responses = 1 closes after its single reply.
Sourcepub fn teardown_reason(&self) -> Option<CloseReason>
pub fn teardown_reason(&self) -> Option<CloseReason>
The teardown reason if any knob is exhausted, else None. Idle is
handled separately by the manager via the timer wheel.
Sourcepub fn take_proxy_protocol(&mut self) -> bool
pub fn take_proxy_protocol(&mut self) -> bool
Whether this upstream datagram should carry a PPv2 DGRAM prefix, given the cluster’s first-datagram-only vs every-datagram policy. Marks the first-datagram bookkeeping as consumed.