tor-cell: Generic "Restricted{Relay,Chan}Cell" types.
These are generalizations of RelayCell and ChanCell respectively, that allow using an arbitrary message type in place of the fully general RelayMsg and ChanMsg types. Doing this is a prerequisite for usefully implementing arti#525.
This commit is contained in:
parent
3cc7ac45e3
commit
e099cc7ef8
|
@ -154,30 +154,53 @@ impl ChanCmd {
|
|||
}
|
||||
}
|
||||
|
||||
/// A decoded and parsed channel cell of unrestricted type.
|
||||
pub type ChanCell = RestrictedChanCell<msg::ChanMsg>;
|
||||
|
||||
/// Trait implemented by anything that can serve as a channel message.
|
||||
///
|
||||
/// Typically, this will be [`RelayMsg`] (to represent an unrestricted relay
|
||||
/// message), or a restricted subset of `RelayMsg`.
|
||||
pub trait ChanMsgClass {
|
||||
/// Return the [`ChanCmd`] for this message.
|
||||
fn cmd(&self) -> ChanCmd;
|
||||
/// Write the body of this message (not including length or command).
|
||||
fn write_body_onto<W: tor_bytes::Writer + ?Sized>(
|
||||
self,
|
||||
w: &mut W,
|
||||
) -> tor_bytes::EncodeResult<()>;
|
||||
/// Decode this message from a given reader, according to a specified
|
||||
/// command value. The reader must be truncated to the exact length
|
||||
/// of the body.
|
||||
fn take(r: &mut tor_bytes::Reader<'_>, cmd: ChanCmd) -> tor_bytes::Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// A decoded channel cell, to be sent or received on a channel.
|
||||
#[derive(Debug)]
|
||||
pub struct ChanCell {
|
||||
pub struct RestrictedChanCell<M> {
|
||||
/// Circuit ID associated with this cell
|
||||
circid: CircId,
|
||||
/// Underlying message in this cell
|
||||
msg: msg::ChanMsg,
|
||||
msg: M,
|
||||
}
|
||||
|
||||
impl ChanCell {
|
||||
impl<M: ChanMsgClass> RestrictedChanCell<M> {
|
||||
/// Construct a new channel cell.
|
||||
pub fn new(circid: CircId, msg: msg::ChanMsg) -> Self {
|
||||
ChanCell { circid, msg }
|
||||
pub fn new(circid: CircId, msg: M) -> Self {
|
||||
RestrictedChanCell { circid, msg }
|
||||
}
|
||||
/// Return the circuit ID for this cell.
|
||||
pub fn circid(&self) -> CircId {
|
||||
self.circid
|
||||
}
|
||||
/// Return a reference to the underlying message of this cell.
|
||||
pub fn msg(&self) -> &msg::ChanMsg {
|
||||
pub fn msg(&self) -> &M {
|
||||
&self.msg
|
||||
}
|
||||
/// Consume this cell and return its components.
|
||||
pub fn into_circid_and_msg(self) -> (CircId, msg::ChanMsg) {
|
||||
pub fn into_circid_and_msg(self) -> (CircId, M) {
|
||||
(self.circid, self.msg)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,9 +72,8 @@ pub enum ChanMsg {
|
|||
Unrecognized(Unrecognized),
|
||||
}
|
||||
|
||||
impl ChanMsg {
|
||||
/// Return the ChanCmd for this message.
|
||||
pub fn cmd(&self) -> ChanCmd {
|
||||
impl super::ChanMsgClass for ChanMsg {
|
||||
fn cmd(&self) -> ChanCmd {
|
||||
use ChanMsg::*;
|
||||
match self {
|
||||
Padding(_) => ChanCmd::PADDING,
|
||||
|
@ -99,8 +98,7 @@ impl ChanMsg {
|
|||
}
|
||||
}
|
||||
|
||||
/// Write the body of this message (not including length or command).
|
||||
pub fn write_body_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||
fn write_body_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||
use ChanMsg::*;
|
||||
match self {
|
||||
Padding(b) => b.write_body_onto(w),
|
||||
|
@ -125,10 +123,7 @@ impl ChanMsg {
|
|||
}
|
||||
}
|
||||
|
||||
/// Decode this message from a given reader, according to a specified
|
||||
/// command value. The reader must be truncated to the exact length
|
||||
/// of the body.
|
||||
pub fn take(r: &mut Reader<'_>, cmd: ChanCmd) -> Result<Self> {
|
||||
fn take(r: &mut Reader<'_>, cmd: ChanCmd) -> Result<Self> {
|
||||
use ChanMsg::*;
|
||||
Ok(match cmd {
|
||||
ChanCmd::PADDING => Padding(r.extract()?),
|
||||
|
@ -154,6 +149,25 @@ impl ChanMsg {
|
|||
}
|
||||
}
|
||||
|
||||
impl ChanMsg {
|
||||
/// Return the ChanCmd for this message.
|
||||
pub fn cmd(&self) -> ChanCmd {
|
||||
super::ChanMsgClass::cmd(self)
|
||||
}
|
||||
|
||||
/// Write the body of this message (not including length or command).
|
||||
pub fn write_body_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()> {
|
||||
super::ChanMsgClass::write_body_onto(self, w)
|
||||
}
|
||||
|
||||
/// Decode this message from a given reader, according to a specified
|
||||
/// command value. The reader must be truncated to the exact length
|
||||
/// of the body.
|
||||
pub fn take(r: &mut Reader<'_>, cmd: ChanCmd) -> Result<Self> {
|
||||
super::ChanMsgClass::take(r, cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/// A Padding message is a fixed-length message on a channel that is
|
||||
/// ignored.
|
||||
///
|
||||
|
|
|
@ -177,26 +177,44 @@ impl StreamId {
|
|||
}
|
||||
}
|
||||
|
||||
/// A decoded and parsed relay cell of unrestricted type.
|
||||
pub type RelayCell = RestrictedRelayCell<msg::RelayMsg>;
|
||||
|
||||
/// Trait implemented by anything that can serve as a relay message.
|
||||
///
|
||||
/// Typically, this will be [`RelayMsg`] (to represent an unrestricted relay
|
||||
/// message), or a restricted subset of `RelayMsg`.
|
||||
pub trait RelayMsgClass {
|
||||
/// Return the stream command associated with this message.
|
||||
fn cmd(&self) -> RelayCmd;
|
||||
/// Encode the body of this message, not including command or length
|
||||
fn encode_onto(self, w: &mut Vec<u8>) -> tor_bytes::EncodeResult<()>;
|
||||
/// Extract the body of a message with command `cmd` from reader `r`.
|
||||
fn decode_from_reader(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// A decoded and parsed relay cell.
|
||||
///
|
||||
/// Each relay cell represents a message that can be sent along a
|
||||
/// circuit, along with the ID for an associated stream that the
|
||||
/// message is meant for.
|
||||
#[derive(Debug)]
|
||||
pub struct RelayCell {
|
||||
pub struct RestrictedRelayCell<M> {
|
||||
/// The stream ID for the stream that this cell corresponds to.
|
||||
streamid: StreamId,
|
||||
/// The relay message for this cell.
|
||||
msg: msg::RelayMsg,
|
||||
msg: M,
|
||||
}
|
||||
|
||||
impl RelayCell {
|
||||
impl<M: RelayMsgClass> RestrictedRelayCell<M> {
|
||||
/// Construct a new relay cell.
|
||||
pub fn new(streamid: StreamId, msg: msg::RelayMsg) -> Self {
|
||||
RelayCell { streamid, msg }
|
||||
pub fn new(streamid: StreamId, msg: M) -> Self {
|
||||
RestrictedRelayCell { streamid, msg }
|
||||
}
|
||||
/// Consume this cell and return its components.
|
||||
pub fn into_streamid_and_msg(self) -> (StreamId, msg::RelayMsg) {
|
||||
pub fn into_streamid_and_msg(self) -> (StreamId, M) {
|
||||
(self.streamid, self.msg)
|
||||
}
|
||||
/// Return the command for this cell.
|
||||
|
@ -208,7 +226,7 @@ impl RelayCell {
|
|||
self.streamid
|
||||
}
|
||||
/// Return the underlying message for this cell.
|
||||
pub fn msg(&self) -> &msg::RelayMsg {
|
||||
pub fn msg(&self) -> &M {
|
||||
&self.msg
|
||||
}
|
||||
/// Consume this relay message and encode it as a 509-byte padded cell
|
||||
|
@ -262,7 +280,7 @@ impl RelayCell {
|
|||
/// performed
|
||||
pub fn decode(body: RawCellBody) -> Result<Self> {
|
||||
let mut reader = Reader::from_slice(body.as_ref());
|
||||
RelayCell::decode_from_reader(&mut reader)
|
||||
Self::decode_from_reader(&mut reader)
|
||||
}
|
||||
/// Parse a RELAY or RELAY_EARLY cell body into a RelayCell from a reader.
|
||||
///
|
||||
|
@ -278,7 +296,7 @@ impl RelayCell {
|
|||
return Err(Error::BadMessage("Insufficient data in relay cell"));
|
||||
}
|
||||
r.truncate(len);
|
||||
let msg = msg::RelayMsg::decode_from_reader(cmd, r)?;
|
||||
Ok(RelayCell { streamid, msg })
|
||||
let msg = M::decode_from_reader(cmd, r)?;
|
||||
Ok(Self { streamid, msg })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,9 +114,8 @@ impl<B: Body> From<B> for RelayMsg {
|
|||
}
|
||||
}
|
||||
|
||||
impl RelayMsg {
|
||||
/// Return the stream command associated with this message.
|
||||
pub fn cmd(&self) -> RelayCmd {
|
||||
impl super::RelayMsgClass for RelayMsg {
|
||||
fn cmd(&self) -> RelayCmd {
|
||||
use RelayMsg::*;
|
||||
match self {
|
||||
Begin(_) => RelayCmd::BEGIN,
|
||||
|
@ -162,8 +161,8 @@ impl RelayMsg {
|
|||
Unrecognized(u) => u.cmd(),
|
||||
}
|
||||
}
|
||||
/// Extract the body of this message from `r`
|
||||
pub fn decode_from_reader(c: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
|
||||
|
||||
fn decode_from_reader(c: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
|
||||
Ok(match c {
|
||||
RelayCmd::BEGIN => RelayMsg::Begin(Begin::decode_from_reader(r)?),
|
||||
RelayCmd::DATA => RelayMsg::Data(Data::decode_from_reader(r)?),
|
||||
|
@ -216,9 +215,8 @@ impl RelayMsg {
|
|||
})
|
||||
}
|
||||
|
||||
/// Encode the body of this message, not including command or length
|
||||
#[allow(clippy::missing_panics_doc)] // TODO hs
|
||||
pub fn encode_onto(self, w: &mut Vec<u8>) -> EncodeResult<()> {
|
||||
fn encode_onto(self, w: &mut Vec<u8>) -> EncodeResult<()> {
|
||||
use RelayMsg::*;
|
||||
match self {
|
||||
Begin(b) => b.encode_onto(w),
|
||||
|
@ -266,6 +264,21 @@ impl RelayMsg {
|
|||
}
|
||||
}
|
||||
|
||||
impl RelayMsg {
|
||||
/// Return the stream command associated with this message.
|
||||
pub fn cmd(&self) -> RelayCmd {
|
||||
super::RelayMsgClass::cmd(self)
|
||||
}
|
||||
/// Encode the body of this message, not including command or length
|
||||
pub fn encode_onto(self, w: &mut Vec<u8>) -> tor_bytes::EncodeResult<()> {
|
||||
super::RelayMsgClass::encode_onto(self, w)
|
||||
}
|
||||
/// Extract the body of a message with command `cmd` from reader `r`.
|
||||
pub fn decode_from_reader(cmd: RelayCmd, r: &mut Reader<'_>) -> Result<Self> {
|
||||
super::RelayMsgClass::decode_from_reader(cmd, r)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// A set of recognized flags that can be attached to a begin cell.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue