tor-cell: Implement {Relay,Chan}Msg for every body type
This will make it ergonomic to decode a single body type without having to declare a variant that accepts only a single message.
This commit is contained in:
parent
65cc7d0974
commit
3f1457ea04
|
@ -1170,6 +1170,54 @@ msg_into_cell!(AuthChallenge);
|
||||||
msg_into_cell!(Authenticate);
|
msg_into_cell!(Authenticate);
|
||||||
msg_into_cell!(Authorize);
|
msg_into_cell!(Authorize);
|
||||||
|
|
||||||
|
/// Helper: declare a ChanMsg implementation for a message type that has a
|
||||||
|
/// fixed command.
|
||||||
|
//
|
||||||
|
// TODO: It might be better to merge Body with ChanMsg, but that is complex,
|
||||||
|
// since their needs are _slightly_ different.
|
||||||
|
macro_rules! msg_impl_chanmsg {
|
||||||
|
($($body:ident,)*) =>
|
||||||
|
{paste::paste!{
|
||||||
|
$(impl crate::chancell::ChanMsg for $body {
|
||||||
|
fn cmd(&self) -> crate::chancell::ChanCmd { crate::chancell::ChanCmd::[< $body:snake:upper >] }
|
||||||
|
fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
|
||||||
|
crate::chancell::msg::Body::encode_onto(self, w)
|
||||||
|
}
|
||||||
|
fn decode_from_reader(cmd: ChanCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
|
||||||
|
if cmd != crate::chancell::ChanCmd::[< $body:snake:upper >] {
|
||||||
|
return Err(tor_bytes::Error::InvalidMessage(
|
||||||
|
format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
crate::chancell::msg::Body::decode_from_reader(r)
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We implement ChanMsg for every body type, so that you can write code that does
|
||||||
|
// e.g. ChanCell<Relay>.
|
||||||
|
msg_impl_chanmsg!(
|
||||||
|
Padding,
|
||||||
|
Vpadding,
|
||||||
|
Create,
|
||||||
|
CreateFast,
|
||||||
|
Create2,
|
||||||
|
Created,
|
||||||
|
CreatedFast,
|
||||||
|
Created2,
|
||||||
|
Relay,
|
||||||
|
RelayEarly,
|
||||||
|
Destroy,
|
||||||
|
Netinfo,
|
||||||
|
Versions,
|
||||||
|
PaddingNegotiate,
|
||||||
|
Certs,
|
||||||
|
AuthChallenge,
|
||||||
|
Authenticate,
|
||||||
|
Authorize,
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
// @@ begin test lint list maintained by maint/add_warning @@
|
// @@ begin test lint list maintained by maint/add_warning @@
|
||||||
|
|
|
@ -1175,3 +1175,49 @@ empty_body! {
|
||||||
/// Opens a new stream on a directory cache.
|
/// Opens a new stream on a directory cache.
|
||||||
pub struct BeginDir {}
|
pub struct BeginDir {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper: declare a RelayMsg implementation for a message type that has a
|
||||||
|
/// fixed command.
|
||||||
|
//
|
||||||
|
// TODO: It might be better to merge Body with RelayMsg, but that is complex,
|
||||||
|
// since their needs are _slightly_ different.
|
||||||
|
macro_rules! msg_impl_relaymsg {
|
||||||
|
($($body:ident),* $(,)?) =>
|
||||||
|
{paste::paste!{
|
||||||
|
$(impl crate::relaycell::RelayMsg for $body {
|
||||||
|
fn cmd(&self) -> crate::relaycell::RelayCmd { crate::relaycell::RelayCmd::[< $body:snake:upper >] }
|
||||||
|
fn encode_onto<W: tor_bytes::Writer + ?Sized>(self, w: &mut W) -> tor_bytes::EncodeResult<()> {
|
||||||
|
crate::relaycell::msg::Body::encode_onto(self, w)
|
||||||
|
}
|
||||||
|
fn decode_from_reader(cmd: RelayCmd, r: &mut tor_bytes::Reader<'_>) -> tor_bytes::Result<Self> {
|
||||||
|
if cmd != crate::relaycell::RelayCmd::[< $body:snake:upper >] {
|
||||||
|
return Err(tor_bytes::Error::InvalidMessage(
|
||||||
|
format!("Expected {} command; got {cmd}", stringify!([< $body:snake:upper >])).into()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
crate::relaycell::msg::Body::decode_from_reader(r)
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_impl_relaymsg!(
|
||||||
|
Begin, Data, End, Connected, Sendme, Extend, Extended, Extend2, Extended2, Truncate, Truncated,
|
||||||
|
Drop, Resolve, Resolved, BeginDir,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "experimental-udp")]
|
||||||
|
msg_impl_relaymsg!(ConnectUdp, ConnectedUdp, Datagram);
|
||||||
|
|
||||||
|
#[cfg(feature = "onion-service")]
|
||||||
|
msg_impl_relaymsg!(
|
||||||
|
EstablishIntro,
|
||||||
|
EstablishRendezvous,
|
||||||
|
Introduce1,
|
||||||
|
Introduce2,
|
||||||
|
Rendezvous1,
|
||||||
|
Rendezvous2,
|
||||||
|
IntroEstablished,
|
||||||
|
RendezvousEstablished,
|
||||||
|
IntroduceAck,
|
||||||
|
);
|
||||||
|
|
|
@ -134,24 +134,22 @@ macro_rules! restricted_msg {
|
||||||
where
|
where
|
||||||
W: $crate::restrict::tor_bytes::Writer + ?Sized
|
W: $crate::restrict::tor_bytes::Writer + ?Sized
|
||||||
{
|
{
|
||||||
use $body_type;
|
|
||||||
match self {
|
match self {
|
||||||
$(
|
$(
|
||||||
$( #[cfg(feature=$feat)] )?
|
$( #[cfg(feature=$feat)] )?
|
||||||
Self::$case(m) => m.encode_onto(w),
|
Self::$case(m) => $body_type::encode_onto(m, w),
|
||||||
)*
|
)*
|
||||||
$(
|
$(
|
||||||
Self::$unrecognized(u) => u.encode_onto(w),
|
Self::$unrecognized(u) => $body_type::encode_onto(u, w),
|
||||||
)?
|
)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_from_reader(cmd: $cmd_type, r: &mut $crate::restrict::tor_bytes::Reader<'_>) -> $crate::restrict::tor_bytes::Result<Self> {
|
fn decode_from_reader(cmd: $cmd_type, r: &mut $crate::restrict::tor_bytes::Reader<'_>) -> $crate::restrict::tor_bytes::Result<Self> {
|
||||||
use $body_type;
|
|
||||||
Ok(match cmd {
|
Ok(match cmd {
|
||||||
$(
|
$(
|
||||||
$( #[cfg(feature=$feat)] )?
|
$( #[cfg(feature=$feat)] )?
|
||||||
$cmd_type:: [<$case:snake:upper>] => Self::$case( $msg_mod :: $case :: decode_from_reader(r)? ),
|
$cmd_type:: [<$case:snake:upper>] => Self::$case( <$msg_mod :: $case as $body_type> :: decode_from_reader(r)? ),
|
||||||
)*
|
)*
|
||||||
$(
|
$(
|
||||||
_ => Self::$unrecognized($unrec_type::decode_with_cmd(cmd, r)?),
|
_ => Self::$unrecognized($unrec_type::decode_with_cmd(cmd, r)?),
|
||||||
|
|
Loading…
Reference in New Issue