Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Commit

Permalink
feat(errors): maintain Error chain in our Error types while customisi…
Browse files Browse the repository at this point in the history
…ng them when additional context is available/useful
  • Loading branch information
bochaco committed May 14, 2021
1 parent cf462f2 commit c89c3a4
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 28 deletions.
23 changes: 16 additions & 7 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{
messages::{CreateError, ExtendProofChainError},
section::SectionChainError,
};
use qp2p::Error as Qp2pError;
use std::net::SocketAddr;
use thiserror::Error;
use xor_name::XorName;
Expand All @@ -21,20 +22,28 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
/// Internal error.
#[derive(Debug, Error)]
#[allow(missing_docs)]
#[allow(clippy::large_enum_variant)]
pub enum Error {
#[error("Failed signature check.")]
FailedSignature,
#[error("Cannot route.")]
CannotRoute,
#[error("Empty recipient list")]
EmptyRecipientList,
#[error("The config is invalid")]
InvalidConfig,
#[error("Cannot connect to the endpoint")]
CannotConnectEndpoint,
#[error("Address not reachable: {0}")]
AddressNotReachable(usize),
#[error("The config is invalid: {err}")]
InvalidConfig {
#[source]
err: Qp2pError,
},
#[error("Cannot connect to the endpoint: {err}")]
CannotConnectEndpoint {
#[source]
err: Qp2pError,
},
#[error("Address not reachable: {err}")]
AddressNotReachable {
#[source]
err: Qp2pError,
},
#[error("The node is not in a state to handle the action.")]
InvalidState,
#[error("Invalid source location.")]
Expand Down
44 changes: 23 additions & 21 deletions src/routing/comm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Comm {
event_tx: mpsc::Sender<ConnectionEvent>,
) -> Result<Self> {
let quic_p2p = QuicP2p::with_config(Some(transport_config), &[], true)
.map_err(|_| Error::InvalidConfig)?;
.map_err(|err| Error::InvalidConfig { err })?;

// Don't bootstrap, just create an endpoint to listen to
// the incoming messages from other nodes.
Expand All @@ -46,7 +46,7 @@ impl Comm {
let (endpoint, _incoming_connections, incoming_messages, disconnections) = quic_p2p
.new_endpoint()
.await
.map_err(|_| Error::CannotConnectEndpoint)?;
.map_err(|err| Error::CannotConnectEndpoint { err })?;

let _ = task::spawn(handle_incoming_messages(
incoming_messages,
Expand All @@ -70,15 +70,15 @@ impl Comm {
event_tx: mpsc::Sender<ConnectionEvent>,
) -> Result<(Self, SocketAddr)> {
let quic_p2p = QuicP2p::with_config(Some(transport_config), &[], true)
.map_err(|_| Error::InvalidConfig)?;
.map_err(|err| Error::InvalidConfig { err })?;

// Bootstrap to the network returning the connection to a node.
// We can use the returned channels to listen for incoming messages and disconnection events
let (endpoint, _incoming_connections, incoming_messages, disconnections, bootstrap_addr) =
quic_p2p
.bootstrap()
.await
.map_err(|_| Error::CannotConnectEndpoint)?;
.map_err(|err| Error::CannotConnectEndpoint { err })?;

let _ = task::spawn(handle_incoming_messages(
incoming_messages,
Expand Down Expand Up @@ -141,18 +141,18 @@ impl Comm {
};

let qp2p = QuicP2p::with_config(Some(qp2p_config), &[], false)
.map_err(|_| Error::InvalidConfig)?;
.map_err(|err| Error::InvalidConfig { err })?;
let (connectivity_endpoint, _, _, _) = qp2p
.new_endpoint()
.await
.map_err(|_| Error::CannotConnectEndpoint)?;
.map_err(|err| Error::CannotConnectEndpoint { err })?;

connectivity_endpoint
.is_reachable(peer)
.await
.map_err(|err| {
info!("Peer {} is NOT externally reachable: {}", peer, err);
Error::AddressNotReachable(1)
Error::AddressNotReachable { err }
})
.map(|()| {
info!("Peer {} is externally reachable.", peer);
Expand Down Expand Up @@ -203,21 +203,23 @@ impl Comm {
delivery_group_size,
recipient.1
);
(
self.send_to(&recipient.1, bytes)
.await
.map_err(|e| match e {
qp2p::Error::Connection(qp2p::ConnectionError::LocallyClosed) => {
Error::AddressNotReachable(0)
}
_ => Error::AddressNotReachable(1),
}),
recipient.1,
)

let result = self
.send_to(&recipient.1, bytes)
.await
.map_err(|err| match err {
qp2p::Error::Connection(qp2p::ConnectionError::LocallyClosed) => {
Error::AddressNotReachable { err }
}
_ => Error::ConnectionClosed,
});

(result, recipient.1)
}
Err(e) => (Err(Error::Messaging(e)), recipient.1),
}
};

let mut tasks: FuturesUnordered<_> = recipients[0..delivery_group_size]
.iter()
.map(|(name, recipient)| send((*name, *recipient), msg.clone()))
Expand All @@ -230,9 +232,9 @@ impl Comm {
while let Some((result, addr)) = tasks.next().await {
match result {
Ok(()) => successes += 1,
Err(Error::AddressNotReachable(reason)) if reason == 1 => {
// The connection was closed by us which means we are terminating so let's cut
// this short.
Err(Error::ConnectionClosed) => {
// The connection was closed by us which means
// we are terminating so let's cut this short.
return Err(Error::ConnectionClosed);
}
Err(_) => {
Expand Down

0 comments on commit c89c3a4

Please sign in to comment.