1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
//! Declare a "command checker" trait that checks whether a given relay message
//! is acceptable on a given stream.
use tor_cell::relaycell::UnparsedRelayCell;
use crate::Result;
/// A value returned by CmdChecker on success.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum StreamStatus {
/// The stream is still open.
Open,
/// The stream has been closed successfully; any further messages received
/// on this stream would be a protocol violation, which should cause
/// us to close the circuit.
Closed,
}
/// An object that checks incoming commands before they are sent to a stream.
///
/// These checks are called from the circuit reactor code, which runs in its own
/// task. The reactor code continues calling these checks we have sent our own
/// END cell on the stream. See `crate::circuit::halfstream` for more
/// information.
///
/// NOTE: The checking DOES NOT take SENDME messages into account; those are
/// handled separately. Neither of the methods on this trait will ever be
/// passed a SENDME message.
///
/// See [`circuit::reactor`](crate::circuit::reactor) for more information on
/// how these checks relate to other checks performed on incoming messages.
pub(crate) trait CmdChecker: std::fmt::Debug {
/// Look at a message `msg` and decide whether it can be handled on this
/// stream.
///
/// If `msg` is invalid, return an error, indicating that the protocol has
/// been violated and the corresponding circuit should be closed.
///
/// If `msg` is invalid, update the state of this checker, and return a
/// `StreamStatus` indicating whether the last message closed.
fn check_msg(&mut self, msg: &UnparsedRelayCell) -> Result<StreamStatus>;
/// Consume `msg` and make sure it can be parsed correctly.
///
/// This is an additional check, beyond check_msg(), performed for half-open
/// streams. It should only be called if check_msg() succeeds. It shouldn't
/// be called on open streams: for those, the stream itself parses the message
/// and consumes it.
fn consume_checked_msg(&mut self, msg: UnparsedRelayCell) -> Result<()>;
}
/// Type alias for a CmdChecker of unspecified type.
//
// TODO: Someday we might turn this into an enum if we decide it's beneficial.
pub(crate) type AnyCmdChecker = Box<dyn CmdChecker + Send + 'static>;