ChanMgr: Add more contextual info to error types.

Now each type has a peer.  In some cases this peer is just an
address, whereas in others (where key is relevant or address isn't
yet narrowed down) it's a full OwnedChanTarget.
This commit is contained in:
Nick Mathewson 2022-07-05 11:37:29 -04:00
parent 6878e3a2d4
commit bc9db9b84c
4 changed files with 41 additions and 25 deletions

View File

@ -0,0 +1 @@
BREAKING: Changes to members of error variants.

View File

@ -61,7 +61,10 @@ impl<R: Runtime> crate::mgr::ChannelFactory for ChanBuilder<R> {
self.runtime
.timeout(five_seconds, self.build_channel_notimeout(target))
.await?
.await
.map_err(|_| Error::ChanTimeout {
peer: target.clone(),
})?
}
}
@ -190,7 +193,7 @@ impl<R: Runtime> ChanBuilder<R> {
)
.connect(|| self.runtime.wallclock())
.await
.map_err(Error::from_proto_no_skew)?;
.map_err(|e| Error::from_proto_no_skew(e, target))?;
let clock_skew = Some(chan.clock_skew()); // Not yet authenticated; can't use it till `check` is done.
let now = self.runtime.wallclock();
let chan = chan
@ -201,14 +204,19 @@ impl<R: Runtime> ChanBuilder<R> {
.lock()
.expect("Lock poisoned")
.record_handshake_done_with_skewed_clock();
Error::Proto { source, clock_skew }
Error::Proto {
source,
peer: target.clone(),
clock_skew,
}
}
_ => Error::from_proto_no_skew(source),
_ => Error::from_proto_no_skew(source, target),
})?;
let (chan, reactor) = chan
.finish()
.await
.map_err(|source| Error::Proto { source, clock_skew })?;
let (chan, reactor) = chan.finish().await.map_err(|source| Error::Proto {
source,
peer: target.clone(),
clock_skew,
})?;
{
self.event_sender

View File

@ -7,6 +7,7 @@ use futures::task::SpawnError;
use thiserror::Error;
use tor_error::{internal, ErrorKind};
use tor_linkspec::{ChanTarget, OwnedChanTarget};
use tor_proto::ClockSkew;
/// An error returned by a channel manager.
@ -18,19 +19,27 @@ pub enum Error {
UnusableTarget(#[source] tor_error::Bug),
/// We were waiting on a pending channel, but it didn't succeed.
#[error("Pending channel failed to launch")]
PendingFailed,
#[error("Pending channel for {peer} failed to launch")]
PendingFailed {
/// Who we were talking to
peer: OwnedChanTarget,
},
/// It took too long for us to establish this connection.
#[error("Channel timed out")]
ChanTimeout,
#[error("Channel for {peer} timed out")]
ChanTimeout {
/// Who we were trying to talk to
peer: OwnedChanTarget,
},
/// A protocol error while making a channel
#[error("Protocol error while opening a channel.")]
#[error("Protocol error while opening a channel with {peer}")]
Proto {
/// The underlying error
#[source]
source: tor_proto::Error,
/// Who we were trying to talk to
peer: OwnedChanTarget,
/// An authenticated ClockSkew (if available) that we received from the
/// peer.
clock_skew: Option<ClockSkew>,
@ -72,12 +81,6 @@ pub enum Error {
Internal(#[from] tor_error::Bug),
}
impl From<tor_rtcompat::TimeoutError> for Error {
fn from(_: tor_rtcompat::TimeoutError) -> Error {
Error::ChanTimeout
}
}
impl<T> From<std::sync::PoisonError<T>> for Error {
fn from(_: std::sync::PoisonError<T>) -> Error {
Error::Internal(internal!("Thread failed while holding lock"))
@ -90,7 +93,7 @@ impl tor_error::HasKind for Error {
use Error as E;
use ErrorKind as EK;
match self {
E::ChanTimeout
E::ChanTimeout { .. }
| E::Io { .. }
| E::Proto {
source: ProtoErr::ChanIoErr(_),
@ -98,7 +101,7 @@ impl tor_error::HasKind for Error {
} => EK::TorAccessFailed,
E::Spawn { cause, .. } => cause.kind(),
E::Proto { source, .. } => source.kind(),
E::PendingFailed => EK::TorAccessFailed,
E::PendingFailed { .. } => EK::TorAccessFailed,
E::UnusableTarget(_) | E::Internal(_) => EK::Internal,
Error::ChannelBuild { .. } => EK::TorAccessFailed,
}
@ -111,13 +114,13 @@ impl tor_error::HasRetryTime for Error {
use Error as E;
match self {
// We can retry this action immediately; there was already a time delay.
E::ChanTimeout => RT::Immediate,
E::ChanTimeout { .. } => RT::Immediate,
// These are worth retrying in a little while.
//
// TODO: Someday we might want to distinguish among different kinds of IO
// errors.
E::PendingFailed | E::Proto { .. } | E::Io { .. } => RT::AfterWaiting,
E::PendingFailed { .. } | E::Proto { .. } | E::Io { .. } => RT::AfterWaiting,
// This error reflects multiple attempts, but every failure is an IO
// error, so we can also retry this after a delay.
@ -150,9 +153,13 @@ impl Error {
///
/// This is not an `Into` implementation because we don't want to call it
/// accidentally when we actually do have clock skew information.
pub(crate) fn from_proto_no_skew(source: tor_proto::Error) -> Self {
pub(crate) fn from_proto_no_skew<T: ChanTarget + ?Sized>(
source: tor_proto::Error,
peer: &T,
) -> Self {
Error::Proto {
source,
peer: OwnedChanTarget::from_chan_target(peer),
clock_skew: None,
}
}

View File

@ -162,7 +162,7 @@ impl<R: Runtime> ChanMgr<R> {
// Double-check the match to make sure that the RSA identity is
// what we wanted too.
chan.check_match(target)
.map_err(Error::from_proto_no_skew)?;
.map_err(|e| Error::from_proto_no_skew(e, target))?;
Ok((chan, provenance))
}