Merge branch 'display_chan_target' into 'main'

ChanTarget: Add a display function, with better output.

Closes #647

See merge request tpo/core/arti!868
This commit is contained in:
Ian Jackson 2022-11-18 13:19:10 +00:00
commit c0fa78fd4d
3 changed files with 81 additions and 21 deletions

View File

@ -6,4 +6,4 @@ MODIFIED: RelayId and RelayIdRef now implement Ord.
MODIFIED: Added cmp_by_relay_ids() to HasRelayIds.
BREAKING: Replaced functions to access addresses from ChanMethod.
BREAKING: Replaced functions to strip addresses from ChanMethod.
BREAKING: Remove impl Display for OwnedCircTarget.

View File

@ -159,17 +159,7 @@ impl OwnedChanTarget {
/// Primarily for error reporting and logging
impl Display for OwnedChanTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[")?;
match &*self.addrs {
[] => write!(f, "?")?,
[a] => write!(f, "{}", a)?,
[a, ..] => write!(f, "{}+", a)?,
};
for ident in self.identities() {
write!(f, " {}", ident)?;
}
write!(f, "]")?;
Ok(())
write!(f, "{}", self.display_chan_target())
}
}
@ -209,13 +199,6 @@ impl OwnedCircTarget {
}
}
/// Primarily for error reporting and logging
impl Display for OwnedCircTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.chan_target, f)
}
}
impl HasAddrs for OwnedCircTarget {
fn addrs(&self) -> &[SocketAddr] {
self.chan_target.addrs()

View File

@ -1,7 +1,7 @@
//! Declare traits to be implemented by types that describe a place
//! that Tor can connect to, directly or indirectly.
use std::{iter::FusedIterator, net::SocketAddr};
use std::{fmt, iter::FusedIterator, net::SocketAddr};
use strum::IntoEnumIterator;
use tor_llcrypto::pk;
@ -195,7 +195,19 @@ impl<D: DirectChanMethodsHelper> HasChanMethod for D {
/// Anything that implements 'ChanTarget' can be used as the
/// identity of a relay for the purposes of launching a new
/// channel.
pub trait ChanTarget: HasRelayIds + HasAddrs + HasChanMethod {}
pub trait ChanTarget: HasRelayIds + HasAddrs + HasChanMethod {
/// Return a reference to this object suitable for formatting its
/// [`ChanTarget`]-specific members.
///
/// The display format is not exhaustive, but tries to give enough
/// information to identify which channel target we're talking about.
fn display_chan_target(&self) -> DisplayChanTarget<'_, Self>
where
Self: Sized,
{
DisplayChanTarget { inner: self }
}
}
impl<T: ChanTarget> From<&T> for OwnedChanTarget {
fn from(target: &T) -> Self {
@ -226,6 +238,44 @@ pub trait CircTarget: ChanTarget {
fn protovers(&self) -> &tor_protover::Protocols;
}
/// A reference to a ChanTarget that implements Display using a hopefully useful
/// format.
#[derive(Debug, Clone)]
pub struct DisplayChanTarget<'a, T> {
/// The ChanTarget that we're formatting.
inner: &'a T,
}
impl<'a, T: ChanTarget> fmt::Display for DisplayChanTarget<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
// We look at the chan_method() (where we would connect to) rather than
// the addrs() (where the relay is, nebulously, "located"). This lets us
// give a less surprising description.
match self.inner.chan_method() {
ChannelMethod::Direct(v) if v.is_empty() => write!(f, "?")?,
ChannelMethod::Direct(v) if v.len() == 1 => write!(f, "{}", v[0])?,
ChannelMethod::Direct(v) => write!(f, "{}+", v[0])?,
#[cfg(feature = "pt-client")]
ChannelMethod::Pluggable(target) => {
match target.addr() {
crate::PtTargetAddr::None => {}
other => write!(f, "{} ", other)?,
}
write!(f, "via {}", target.transport())?;
// This deliberately doesn't include the PtTargetSettings, since
// they can be large, and they're typically unnecessary.
}
}
for ident in self.inner.identities() {
write!(f, " {}", ident)?;
}
write!(f, "]")
}
}
#[cfg(test)]
mod test {
#![allow(clippy::unwrap_used)]
@ -383,4 +433,31 @@ mod test {
b(Some(ed1), Some(rsa1)),
]);
}
#[test]
fn display() {
use crate::PtTarget;
let e1 = example();
assert_eq!(
e1.display_chan_target().to_string(),
"[127.0.0.1:99+ ed25519:/FHNjmIYoaONpH7QAjDwWAgW7RO6MwOsXeuRFUiQgCU \
$1234567890abcdef12341234567890abcdef1234]"
);
let rsa = hex!("234461644a6f6b6523436f726e794f6e4d61696e").into();
let mut b = OwnedChanTarget::builder();
b.ids().rsa_identity(rsa);
let e2 = b
.method(ChannelMethod::Pluggable(PtTarget::new(
"obfs4".parse().unwrap(),
"127.0.0.1:99".parse().unwrap(),
)))
.build()
.unwrap();
assert_eq!(
e2.to_string(),
"[127.0.0.1:99 via obfs4 $234461644a6f6b6523436f726e794f6e4d61696e]"
);
}
}