typhoon/flow/probe.rs
1//! Active probing protection: sender trait and handler trait.
2//!
3//! [`ProbeFlowSender`] gives probe handlers a raw-socket send path that bypasses all TYPHOON
4//! framing. [`ActiveProbeHandler`] is the callback interface the flow manager uses to forward
5//! every unidentified packet it receives. The default no-op implementation lives in
6//! [`crate::defaults`].
7
8use std::future::Future;
9use std::net::SocketAddr;
10use std::pin::Pin;
11use std::sync::{Arc, Weak};
12
13use async_trait::async_trait;
14
15use crate::bytes::DynamicByteBuffer;
16use crate::settings::Settings;
17use crate::utils::socket::SocketError;
18use crate::utils::sync::AsyncExecutor;
19
20/// Object-safe interface for sending raw response packets through the flow manager's socket.
21///
22/// Implemented individually by `ServerFlowManager` (forwards to `send_to`) and
23/// `ClientFlowManager` (forwards to `send` on the connected socket, ignoring `target`).
24pub trait ProbeFlowSender: Send + Sync {
25 /// Send `packet` as raw bytes to `target`, bypassing all TYPHOON framing.
26 fn send_raw<'a>(&'a self, packet: DynamicByteBuffer, target: SocketAddr) -> Pin<Box<dyn Future<Output = Result<(), SocketError>> + Send + 'a>>;
27}
28
29/// Handler for packets the flow manager could not identify (active probing protection).
30///
31/// The flow manager calls [`start`] once at startup, then calls [`process`] for every packet
32/// whose tailer decryption or verification failed, and — on the server — for every
33/// non-handshake, non-decoy packet from an unregistered user.
34#[async_trait]
35pub trait ActiveProbeHandler<AE: AsyncExecutor + 'static>: Send + Sync {
36 /// Called once when the flow manager starts.
37 /// `manager` provides a raw-socket send path; `settings` carries runtime configuration.
38 async fn start(&mut self, manager: Weak<dyn ProbeFlowSender>, settings: Arc<Settings<AE>>);
39
40 /// Called for each unidentified packet.
41 /// `source` is the UDP sender address — `Some` on the server, `None` on the client (the
42 /// peer address is fixed for a connected socket and need not be threaded through).
43 async fn process(&mut self, packet: DynamicByteBuffer, source: Option<SocketAddr>);
44}
45
46/// Factory type for creating active probe handlers.
47///
48/// A simple no-arg closure — `manager` and `settings` are supplied to each handler via
49/// [`ActiveProbeHandler::start`] after construction, so the factory needs no arguments.
50pub type ProbeFactory<AE> = Arc<dyn Fn() -> Box<dyn ActiveProbeHandler<AE>> + Send + Sync>;
51
52/// Create a [`ProbeFactory`] from a [`Default`]-constructible [`ActiveProbeHandler`] type.
53pub fn probe_factory<AE, PH>() -> ProbeFactory<AE>
54where
55 AE: AsyncExecutor + 'static,
56 PH: ActiveProbeHandler<AE> + Default + 'static,
57{
58 Arc::new(|| Box::new(PH::default()))
59}