pub trait ProxyHook: Send + Sync {
// Provided methods
fn interest(&self) -> Interest { ... }
fn on_control_message(
&self,
_cx: &FrameCtx<'_>,
_msg: &AnyControlMessage,
_raw: &[u8],
) -> Action { ... }
fn on_stream_open(&self, _cx: &StreamCtx<'_>) -> StreamAction { ... }
fn on_stream_header(
&self,
_cx: &StreamCtx<'_>,
_header: &DataStreamHeaderKind,
) -> StreamAction { ... }
fn on_object(&self, _cx: &ObjectCtx<'_>, _raw: &[u8]) -> Action { ... }
fn on_datagram(
&self,
_cx: &FrameCtx<'_>,
_header: Option<&AnyDatagramHeader>,
_raw: &[u8],
) -> Action { ... }
fn on_stream_end(&self, _cx: &StreamCtx<'_>, _end: StreamEnd) -> Action { ... }
}Expand description
Decide what happens to frames, objects, datagrams and streams.
Every method is synchronous and defaulted, so Arc<dyn ProxyHook> stays
dyn-compatible and an observing-only implementation is
impl ProxyHook for MyHook {}. There is no async fn in the trait and
no async-trait dependency. Cases that genuinely need to await an
external signal use Action::Hold, so a hook never stalls a read
loop: timing is expressed as data and executed by the engine, where it
is precise, attributable and bounded.
Provided Methods§
Sourcefn interest(&self) -> Interest
fn interest(&self) -> Interest
What this hook wants the proxy to parse.
Sampled once, at session start, and cached. Interest::NONE
keeps the zero-parse byte-pump path bit-for-bit on all three
forwarding paths.
Sourcefn on_control_message(
&self,
_cx: &FrameCtx<'_>,
_msg: &AnyControlMessage,
_raw: &[u8],
) -> Action
fn on_control_message( &self, _cx: &FrameCtx<'_>, _msg: &AnyControlMessage, _raw: &[u8], ) -> Action
Called before forwarding a control message.
Fires only when Interest::CONTROL is set: without it the control
stream takes the forward-first path, where the bytes are already in
flight by the time they are parsed and a return value would be
unexecutable.
raw is the frame’s original wire bytes — type, scope, length
prefix and payload.
Sourcefn on_stream_open(&self, _cx: &StreamCtx<'_>) -> StreamAction
fn on_stream_open(&self, _cx: &StreamCtx<'_>) -> StreamAction
Called after a unidirectional stream is accepted and before the peer
stream is opened. Stream identity only — see StreamCtx.
Fires only when Interest::STREAMS is set. Under any other
interest the decision point between accept_uni() and
open_uni() is not armed and the stream is forwarded. The gate is
spelled out because otherwise it is undefined whether an
Interest::NONE session calls a hook method at all: it does not,
on this method or any other.
Sourcefn on_stream_header(
&self,
_cx: &StreamCtx<'_>,
_header: &DataStreamHeaderKind,
) -> StreamAction
fn on_stream_header( &self, _cx: &StreamCtx<'_>, _header: &DataStreamHeaderKind, ) -> StreamAction
Called once the data stream’s header has been framed and before its bytes are forwarded.
This is where track-targeted decisions belong: header carries the
track alias, group and publisher priority.
Fires only when Interest::STREAMS is set. STREAMS includes
Interest::OBJECTS structurally, so declaring STREAMS alone is
sufficient and puts the stream on the framed path — which it must
be, because there is no header without framing. Declaring
OBJECTS alone frames the stream but does not call this
method.
Sourcefn on_object(&self, _cx: &ObjectCtx<'_>, _raw: &[u8]) -> Action
fn on_object(&self, _cx: &ObjectCtx<'_>, _raw: &[u8]) -> Action
Called before forwarding one complete object.
Fires only when Interest::OBJECTS is set (and therefore also
under Interest::STREAMS, which includes it). Attaching an
event observer does not turn this on: an observer makes the
proxy frame objects, so that
ProxyEvent::Object can fire,
but a hook that declared no object interest is never asked and
never has a returned Action honoured. Framing and consulting the
hook are separate decisions.
raw is the object’s exact wire bytes as they will be forwarded,
framing and payload; cx.meta.payload_len bytes at the end of it
are the payload. Action::ReplacePayload replaces that trailing
region.
As they will be forwarded is load-bearing after an elide: when a
previous object on this stream was elided on a delta-encoding draft, the
framer has already rewritten this object’s leading Object ID varint, so
raw is what goes on the wire and raw.len() - cx.meta.payload_len is
still the payload offset. cx.meta.object_id is the absolute ID either
way.
Not called for objects the framer could not address: an object
larger than
FramerConfig::max_buffered_object_bytes,
or any object on a stream the framer has stopped parsing. Those are
reported as
ProxyEvent::Impairment
instead, so “nothing matched” and “never parsed” are
distinguishable.
Sourcefn on_datagram(
&self,
_cx: &FrameCtx<'_>,
_header: Option<&AnyDatagramHeader>,
_raw: &[u8],
) -> Action
fn on_datagram( &self, _cx: &FrameCtx<'_>, _header: Option<&AnyDatagramHeader>, _raw: &[u8], ) -> Action
Called before forwarding a datagram.
Fires only when Interest::DATAGRAMS is set.
header is None when the datagram’s header did not decode. The
hook is still called, so Action::Drop on malformed traffic is
expressible. raw is the whole datagram.
Action::ReplacePayload is available here only when the
payload’s start is derivable: not on draft-14, whose
AnyDatagramHeader decode consumes the payload; not on a status
datagram, which has no payload slot; and not when header is
None. In those three cases it is refused with
Refusal::PayloadNotDelimited
and the datagram is forwarded unchanged. cx.caps answers this
before you ask for it.
Sourcefn on_stream_end(&self, _cx: &StreamCtx<'_>, _end: StreamEnd) -> Action
fn on_stream_end(&self, _cx: &StreamCtx<'_>, _end: StreamEnd) -> Action
Called when a forwarded stream ends, for any reason.
Fires when Interest::STREAMS is set, on data streams and on
the control stream — cx.is_control_stream says which rules apply,
and it must, because Action::ResetStream is illegal on a control
stream on every draft and is refused there with
Refusal::ControlStreamResetIllegal.
On drafts 17-19 that flag is also true for a bidirectional request
stream, which runs under the same rules; see
StreamCtx::is_control_stream for why and for what it costs.
Three actions are honoured here: Action::Pass,
Action::ResetStream (data streams only) and
Action::CloseSession (both, because a close is session-scoped
and no site can be the wrong one for it — it is the documented
escalation for a control stream, where a reset is a protocol
violation). Everything else is refused with
Refusal::WrongSite. To
delay a stream’s end, delay its last object.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".