feat: extended Multiaddr wrapper error handling

Signed-off-by: ljedrz <ljedrz@gmail.com>
This commit is contained in:
ljedrz 2020-08-18 15:59:27 +02:00
parent 10639a614a
commit dcae04f6e2
2 changed files with 35 additions and 25 deletions

View File

@ -1,16 +1,25 @@
use libp2p::{multiaddr::Protocol, Multiaddr, PeerId};
use std::{convert::TryFrom, fmt, str::FromStr};
use libp2p::{
multiaddr::{self, Protocol},
Multiaddr, PeerId,
};
use std::{
convert::{TryFrom, TryInto},
fmt,
str::FromStr,
};
/// An error that can be thrown when converting to `MultiaddrWithPeerId` and
/// `MultiaddrWithoutPeerId`.
#[derive(Debug, Clone)]
#[derive(Debug)]
pub enum MultiaddrWrapperError {
/// The source `Multiaddr` unexpectedly contains `Protocol::P2p`.
ContainsProtocolP2p,
/// The provided `Multiaddr` is invalid.
InvalidMultiaddr,
/// The `Protocol::P2p` is missing from the source `Multiaddr`.
MissingProtocolP2p,
InvalidMultiaddr(multiaddr::Error),
/// The `PeerId` created based on the `Protocol::P2p` is invalid.
InvalidPeerId,
/// The `Protocol::P2p` is unexpectedly missing from the source `Multiaddr`.
MissingProtocolP2p,
}
impl fmt::Display for MultiaddrWrapperError {
@ -25,13 +34,15 @@ impl std::error::Error for MultiaddrWrapperError {}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MultiaddrWithoutPeerId(Multiaddr);
impl From<Multiaddr> for MultiaddrWithoutPeerId {
fn from(addr: Multiaddr) -> Self {
Self(
addr.into_iter()
.filter(|p| !matches!(p, Protocol::P2p(_)))
.collect(),
)
impl TryFrom<Multiaddr> for MultiaddrWithoutPeerId {
type Error = MultiaddrWrapperError;
fn try_from(addr: Multiaddr) -> Result<Self, Self::Error> {
if addr.iter().any(|p| matches!(p, Protocol::P2p(_))) {
Err(MultiaddrWrapperError::ContainsProtocolP2p)
} else {
Ok(Self(addr))
}
}
}
@ -54,8 +65,8 @@ impl FromStr for MultiaddrWithoutPeerId {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let multiaddr = s
.parse::<Multiaddr>()
.map_err(|_| MultiaddrWrapperError::InvalidMultiaddr)?;
Ok(multiaddr.into())
.map_err(MultiaddrWrapperError::InvalidMultiaddr)?;
multiaddr.try_into()
}
}
@ -95,7 +106,7 @@ impl FromStr for MultiaddrWithPeerId {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let multiaddr = s
.parse::<Multiaddr>()
.map_err(|_| MultiaddrWrapperError::InvalidMultiaddr)?;
.map_err(MultiaddrWrapperError::InvalidMultiaddr)?;
Self::try_from(multiaddr)
}
}

View File

@ -7,6 +7,7 @@ use libp2p::swarm::protocols_handler::{
};
use libp2p::swarm::{self, NetworkBehaviour, PollParameters, Swarm};
use std::collections::{HashMap, HashSet, VecDeque};
use std::convert::TryInto;
use std::time::Duration;
/// A description of currently active connection.
@ -154,18 +155,17 @@ impl NetworkBehaviour for SwarmApi {
) {
// TODO: could be that the connection is not yet fully established at this point
trace!("inject_connected {} {:?}", peer_id, cp);
let addr = connection_point_addr(cp).to_owned();
let addr: MultiaddrWithoutPeerId = connection_point_addr(cp).to_owned().try_into().unwrap();
self.peers.insert(peer_id.clone());
let connections = self.connected_peers.entry(peer_id.clone()).or_default();
connections.push(addr.clone().into());
connections.push(addr.clone());
self.connections
.insert(addr.clone().into(), peer_id.clone());
self.connections.insert(addr.clone(), peer_id.clone());
if let ConnectedPoint::Dialer { .. } = cp {
let addr = MultiaddrWithPeerId {
multiaddr: addr.into(),
multiaddr: addr,
peer_id: peer_id.clone(),
};
@ -185,7 +185,7 @@ impl NetworkBehaviour for SwarmApi {
cp: &ConnectedPoint,
) {
trace!("inject_connection_closed {} {:?}", peer_id, cp);
let closed_addr = connection_point_addr(cp).to_owned().into();
let closed_addr = connection_point_addr(cp).to_owned().try_into().unwrap();
let became_empty = if let Some(connections) = self.connected_peers.get_mut(peer_id) {
if let Some(index) = connections.iter().position(|addr| *addr == closed_addr) {
@ -223,9 +223,8 @@ impl NetworkBehaviour for SwarmApi {
error: &dyn std::error::Error,
) {
trace!("inject_addr_reach_failure {} {}", addr, error);
if let Some(peer_id) = peer_id {
let ma: MultiaddrWithoutPeerId = addr.clone().into();
let addr = MultiaddrWithPeerId::from((ma, peer_id.to_owned()));
if peer_id.is_some() {
let addr: MultiaddrWithPeerId = addr.clone().try_into().unwrap();
self.connect_registry
.finish_subscription(addr.into(), Err(error.to_string()));
}