tor-cell: Have restrict_msg add conversion functions.

Every FooMsg type now implements Into<AnyFooMsg>, and
TryFrom<FooMsg>.

Additionally, it now implements From<X> for every distinct type that
it supports.  This last part lets us discard a bunch of code.

Unfortunately, I needed some downright hackish trickery in order to
get these macros to avoid generating `From<AnyFooMsg> for AnyFooMsg`
and conflicting with the blanket implementation.

The trickery to deal with RelayEarly and Relay being the same type
was not necessarily worth it; I will be separating them and removing
said trickery in the next commit.
This commit is contained in:
Nick Mathewson 2023-02-07 17:35:14 -05:00
parent b6f6fa4d4b
commit e832cbd29c
6 changed files with 72 additions and 104 deletions

View File

@ -32,6 +32,7 @@ crate::restrict::restricted_msg! {
/// a TLS connection.
#[derive(Clone, Debug)]
#[non_exhaustive]
@omit_from "avoid_conflict_with_a_blanket_implementation"
pub enum AnyChanMsg : ChanMsg {
/// A Padding message
Padding,
@ -52,6 +53,7 @@ pub enum AnyChanMsg : ChanMsg {
/// A message sent along a circuit, likely to a more-distant relay.
Relay,
/// A message sent along a circuit (limited supply)
[omit_from = "relay_and_relay_early_are_the_same_type"]
RelayEarly,
/// Tear down a circuit
Destroy,
@ -1167,12 +1169,6 @@ impl Readable for Unrecognized {
}
}
impl<B: Body> From<B> for AnyChanMsg {
fn from(body: B) -> Self {
body.into_message()
}
}
/// Helper: declare a From<> implementation from message types for
/// cells that don't take a circid.
macro_rules! msg_into_cell {

View File

@ -31,6 +31,7 @@ crate::restrict::restricted_msg! {
/// A single parsed relay message, sent or received along a circuit
#[derive(Debug, Clone)]
#[non_exhaustive]
@omit_from "avoid_conflict_with_a_blanket_implementation"
pub enum AnyRelayMsg : RelayMsg {
/// Create a stream
Begin,
@ -107,20 +108,12 @@ pub enum AnyRelayMsg : RelayMsg {
/// Internal: traits in common different cell bodies.
pub trait Body: Sized {
/// Convert this type into a RelayMsg, wrapped appropriate.
fn into_message(self) -> AnyRelayMsg;
/// Decode a relay cell body from a provided reader.
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self>;
/// Encode the body of this cell into the end of a writer.
fn encode_onto<W: Writer + ?Sized>(self, w: &mut W) -> EncodeResult<()>;
}
impl<B: Body> From<B> for AnyRelayMsg {
fn from(b: B) -> AnyRelayMsg {
b.into_message()
}
}
bitflags! {
/// A set of recognized flags that can be attached to a begin cell.
///
@ -209,9 +202,6 @@ impl Begin {
}
impl Body for Begin {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Begin(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let addr = {
if r.peek(1)? == b"[" {
@ -324,9 +314,6 @@ impl AsRef<[u8]> for Data {
}
impl Body for Data {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Data(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Data {
body: r.take(r.remaining())?.into(),
@ -437,9 +424,6 @@ impl End {
}
}
impl Body for End {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::End(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
if r.remaining() == 0 {
return Ok(End {
@ -528,9 +512,6 @@ impl Connected {
}
}
impl Body for Connected {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Connected(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
if r.remaining() == 0 {
return Ok(Connected { addr: None });
@ -607,9 +588,6 @@ impl Sendme {
}
}
impl Body for Sendme {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Sendme(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let digest = if r.remaining() == 0 {
None
@ -672,9 +650,6 @@ impl Extend {
}
}
impl Body for Extend {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Extend(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let addr = r.extract()?;
let port = r.take_u16()?;
@ -713,9 +688,6 @@ impl Extended {
}
}
impl Body for Extended {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Extended(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let handshake = r.take(TAP_S_HANDSHAKE_LEN)?.into();
Ok(Extended { handshake })
@ -777,9 +749,6 @@ impl Extend2 {
}
impl Body for Extend2 {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Extend2(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let n = r.take_u8()?;
let linkspec = r.extract_n(n as usize)?;
@ -836,9 +805,6 @@ impl Extended2 {
}
}
impl Body for Extended2 {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Extended2(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let hlen = r.take_u16()?;
let handshake = r.take(hlen as usize)?;
@ -881,9 +847,6 @@ impl Truncated {
}
}
impl Body for Truncated {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Truncated(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Truncated {
reason: r.take_u8()?.into(),
@ -937,9 +900,6 @@ impl Resolve {
}
}
impl Body for Resolve {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Resolve(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let query = r.take_until(0)?;
Ok(Resolve {
@ -1106,9 +1066,6 @@ impl Resolved {
}
}
impl Body for Resolved {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Resolved(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let mut answers = Vec::new();
while r.remaining() > 0 {
@ -1161,9 +1118,6 @@ impl Unrecognized {
}
impl Body for Unrecognized {
fn into_message(self) -> AnyRelayMsg {
AnyRelayMsg::Unrecognized(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Unrecognized {
cmd: 0.into(),
@ -1187,9 +1141,6 @@ macro_rules! empty_body {
#[non_exhaustive]
pub struct $name {}
impl $crate::relaycell::msg::Body for $name {
fn into_message(self) -> $crate::relaycell::msg::AnyRelayMsg {
$crate::relaycell::msg::AnyRelayMsg::$name(self)
}
fn decode_from_reader(_r: &mut Reader<'_>) -> Result<Self> {
Ok(Self::default())
}

View File

@ -157,9 +157,6 @@ pub struct EstablishIntro {
}
impl msg::Body for EstablishIntro {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::EstablishIntro(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let auth_key_type = r.take_u8()?.into();
let auth_key_len = r.take_u16()?;
@ -259,9 +256,6 @@ impl EstablishRendezvous {
}
}
impl msg::Body for EstablishRendezvous {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::EstablishRendezvous(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let cookie = r.extract()?;
r.take_rest();
@ -277,9 +271,6 @@ impl msg::Body for EstablishRendezvous {
pub struct Introduce1(Introduce);
impl msg::Body for Introduce1 {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::Introduce1(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Self(Introduce::decode_from_reader(r)?))
}
@ -300,9 +291,6 @@ impl Introduce1 {
pub struct Introduce2(Introduce);
impl msg::Body for Introduce2 {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::Introduce2(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Self(Introduce::decode_from_reader(r)?))
}
@ -387,10 +375,6 @@ pub struct Rendezvous1 {
}
impl Body for Rendezvous1 {
fn into_message(self) -> msg::AnyRelayMsg {
todo!()
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
todo!()
}
@ -409,10 +393,6 @@ pub struct Rendezvous2 {
}
impl Body for Rendezvous2 {
fn into_message(self) -> msg::AnyRelayMsg {
todo!()
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
todo!()
}
@ -434,10 +414,6 @@ pub struct IntroEstablished {
}
impl Body for IntroEstablished {
fn into_message(self) -> msg::AnyRelayMsg {
todo!()
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
todo!()
}
@ -466,10 +442,6 @@ pub struct IntroduceAck {
}
impl Body for IntroduceAck {
fn into_message(self) -> msg::AnyRelayMsg {
todo!()
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
todo!()
}

View File

@ -188,10 +188,6 @@ impl ConnectUdp {
}
impl msg::Body for ConnectUdp {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::ConnectUdp(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let flags = r.take_u32()?;
let addr = r.extract()?;
@ -230,10 +226,6 @@ impl ConnectedUdp {
}
impl msg::Body for ConnectedUdp {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::ConnectedUdp(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
let our_address: AddressPort = r.extract()?;
if our_address.addr.is_hostname() {
@ -305,10 +297,6 @@ impl AsRef<[u8]> for Datagram {
}
impl msg::Body for Datagram {
fn into_message(self) -> msg::AnyRelayMsg {
msg::AnyRelayMsg::Datagram(self)
}
fn decode_from_reader(r: &mut Reader<'_>) -> Result<Self> {
Ok(Datagram {
body: r.take(r.remaining())?.into(),

View File

@ -40,18 +40,20 @@ pub use tor_bytes;
macro_rules! restricted_msg {
{
$(#[$meta:meta])*
$(@omit_from $omit_from:literal)?
$v:vis enum $name:ident : RelayMsg {
$($tt:tt)*
}
} => {
$crate::restrict::restricted_msg!{
[
base_type: $crate::relaycell::msg::AnyRelayMsg,
any_type: $crate::relaycell::msg::AnyRelayMsg,
msg_mod: $crate::relaycell::msg,
cmd_type: $crate::relaycell::RelayCmd,
unrecognized: $crate::relaycell::msg::Unrecognized,
body_trait: $crate::relaycell::msg::Body,
msg_trait: $crate::relaycell::RelayMsg
msg_trait: $crate::relaycell::RelayMsg,
omit_from: $($omit_from)?
]
$(#[$meta])*
$v enum $name { $($tt)*}
@ -59,18 +61,20 @@ macro_rules! restricted_msg {
};
{
$(#[$meta:meta])*
$(@omit_from $omit_from:literal)?
$v:vis enum $name:ident : ChanMsg {
$($tt:tt)*
}
} => {
$crate::restrict::restricted_msg!{
[
base_type: $crate::chancell::msg::AnyChanMsg,
any_type: $crate::chancell::msg::AnyChanMsg,
msg_mod: $crate::chancell::msg,
cmd_type: $crate::chancell::ChanCmd,
unrecognized: $crate::chancell::msg::Unrecognized,
body_trait: $crate::chancell::msg::Body,
msg_trait: $crate::chancell::ChanMsg
msg_trait: $crate::chancell::ChanMsg,
omit_from: $($omit_from)?
]
$(#[$meta])*
$v enum $name { $($tt)*}
@ -78,18 +82,20 @@ macro_rules! restricted_msg {
};
{
[
base_type: $base:ty,
any_type: $any_msg:ty,
msg_mod: $msg_mod:path,
cmd_type: $cmd_type:ty,
unrecognized: $unrec_type:ty,
body_trait: $body_type:ty,
msg_trait: $msg_trait:ty
msg_trait: $msg_trait:ty,
omit_from: $($omit_from:literal)?
]
$(#[$meta:meta])*
$v:vis enum $name:ident {
$(
$(#[$case_meta:meta])*
$([feature=$feat:literal])?
$([omit_from=$c_omit_from:literal])?
$case:ident
),*
$(, _ =>
@ -157,6 +163,61 @@ macro_rules! restricted_msg {
})
}
}
$(
#[cfg(feature = $omit_from)]
)?
impl From<$name> for $any_msg {
fn from(msg: $name) -> $any_msg {
match msg {
$(
$( #[cfg(feature=$feat)] )?
$name::$case(b) => Self::$case(b),
)*
$(
$name::$unrecognized(u) => $any_msg::Unrecognized(u),
)?
}
}
}
$(
#[cfg(feature = $omit_from)]
)?
impl TryFrom<$any_msg> for $name {
type Error = $any_msg;
fn try_from(msg: $any_msg) -> std::result::Result<$name, $any_msg> {
Ok(match msg {
$(
$( #[cfg(feature=$feat)] )?
$any_msg::$case(b) => $name::$case(b),
)*
$(
$any_msg::Unrecognized(u) => Self::$unrecognized(u),
)?
#[allow(unreachable_patterns)]
other => return Err(other),
})
}
}
$(
$(
#[cfg(feature = $c_omit_from)]
)?
$( #[cfg(feature=$feat)] )?
impl From<$msg_mod :: $case> for $name {
fn from(m: $msg_mod::$case) -> $name {
$name :: $case(m)
}
}
)*
$(
impl From<$unrec_type> for $name {
fn from (u: $unrec_type) -> $name {
$name::$unrecognized(u)
}
}
)?
}
}
}

View File

@ -324,7 +324,7 @@ where
let mut rng = rand::thread_rng();
let unique_id = reactor.unique_id;
use tor_cell::relaycell::msg::{Body, Extend2};
use tor_cell::relaycell::msg::Extend2;
// Perform the first part of the cryptographic handshake
let (state, msg) = H::client1(&mut rng, key)?;
@ -339,7 +339,7 @@ where
);
let extend_msg = Extend2::new(linkspecs, handshake_id, msg);
let cell = AnyRelayCell::new(0.into(), extend_msg.into_message());
let cell = AnyRelayCell::new(0.into(), extend_msg.into());
// Send the message to the last hop...
reactor.send_relay_cell(