mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-25 15:51:34 +00:00
Deny connection with local PeerId (#859)
This commit is contained in:
@ -61,7 +61,7 @@ where
|
|||||||
listeners: ListenersStream<TTrans>,
|
listeners: ListenersStream<TTrans>,
|
||||||
|
|
||||||
/// The nodes currently active.
|
/// The nodes currently active.
|
||||||
active_nodes: CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError<TTrans::Error>, THandlerErr>,
|
active_nodes: CollectionStream<TInEvent, TOutEvent, THandler, InternalReachErr<TTrans::Error>, THandlerErr>,
|
||||||
|
|
||||||
/// The reach attempts of the swarm.
|
/// The reach attempts of the swarm.
|
||||||
/// This needs to be a separate struct in order to handle multiple mutable borrows issues.
|
/// This needs to be a separate struct in order to handle multiple mutable borrows issues.
|
||||||
@ -190,7 +190,7 @@ where
|
|||||||
multiaddr: Multiaddr,
|
multiaddr: Multiaddr,
|
||||||
|
|
||||||
/// The error that happened.
|
/// The error that happened.
|
||||||
error: TransportError<TTrans::Error>,
|
error: UnknownPeerDialErr<TTrans::Error>,
|
||||||
|
|
||||||
/// The handler that was passed to `dial()`.
|
/// The handler that was passed to `dial()`.
|
||||||
handler: THandler,
|
handler: THandler,
|
||||||
@ -283,12 +283,55 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Internal error type that contains all the possible errors that can happen in a reach attempt.
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum InternalReachErr<TTransErr> {
|
||||||
|
/// Error in the transport layer.
|
||||||
|
Transport(TransportError<TTransErr>),
|
||||||
|
/// We successfully reached the peer, but there was a mismatch between the expected id and the
|
||||||
|
/// actual id of the peer.
|
||||||
|
PeerIdMismatch {
|
||||||
|
/// The peer id that the node reports.
|
||||||
|
obtained: PeerId,
|
||||||
|
},
|
||||||
|
/// The negotiated `PeerId` is the same as the one of the local node.
|
||||||
|
FoundLocalPeerId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TTransErr> fmt::Display for InternalReachErr<TTransErr>
|
||||||
|
where TTransErr: fmt::Display
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
InternalReachErr::Transport(err) => write!(f, "{}", err),
|
||||||
|
InternalReachErr::PeerIdMismatch { obtained } => {
|
||||||
|
write!(f, "Peer ID mismatch, obtained: {}", obtained.to_base58())
|
||||||
|
},
|
||||||
|
InternalReachErr::FoundLocalPeerId => {
|
||||||
|
write!(f, "Remote has the same PeerId as us")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TTransErr> error::Error for InternalReachErr<TTransErr>
|
||||||
|
where TTransErr: error::Error + 'static
|
||||||
|
{
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
InternalReachErr::Transport(err) => Some(err),
|
||||||
|
InternalReachErr::PeerIdMismatch { .. } => None,
|
||||||
|
InternalReachErr::FoundLocalPeerId => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can happen when trying to reach a node.
|
/// Error that can happen when trying to reach a node.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RawSwarmReachError<TTransErr> {
|
pub enum RawSwarmReachError<TTransErr> {
|
||||||
/// Error in the transport layer.
|
/// Error in the transport layer.
|
||||||
// TODO: is a TransportError correct here?
|
|
||||||
Transport(TransportError<TTransErr>),
|
Transport(TransportError<TTransErr>),
|
||||||
|
|
||||||
/// We successfully reached the peer, but there was a mismatch between the expected id and the
|
/// We successfully reached the peer, but there was a mismatch between the expected id and the
|
||||||
/// actual id of the peer.
|
/// actual id of the peer.
|
||||||
PeerIdMismatch {
|
PeerIdMismatch {
|
||||||
@ -321,6 +364,39 @@ where TTransErr: error::Error + 'static
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error that can happen when dialing a node with an unknown peer ID.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum UnknownPeerDialErr<TTransErr> {
|
||||||
|
/// Error in the transport layer.
|
||||||
|
Transport(TransportError<TTransErr>),
|
||||||
|
/// The negotiated `PeerId` is the same as the local node.
|
||||||
|
FoundLocalPeerId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TTransErr> fmt::Display for UnknownPeerDialErr<TTransErr>
|
||||||
|
where TTransErr: fmt::Display
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
UnknownPeerDialErr::Transport(err) => write!(f, "{}", err),
|
||||||
|
UnknownPeerDialErr::FoundLocalPeerId => {
|
||||||
|
write!(f, "Unknown peer has same PeerId as us")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TTransErr> error::Error for UnknownPeerDialErr<TTransErr>
|
||||||
|
where TTransErr: error::Error + 'static
|
||||||
|
{
|
||||||
|
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
UnknownPeerDialErr::Transport(err) => Some(err),
|
||||||
|
UnknownPeerDialErr::FoundLocalPeerId => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Error that can happen on an incoming connection.
|
/// Error that can happen on an incoming connection.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum IncomingError<TTransErr> {
|
pub enum IncomingError<TTransErr> {
|
||||||
@ -330,6 +406,8 @@ pub enum IncomingError<TTransErr> {
|
|||||||
/// Denied the incoming connection because we're already connected to this peer as a dialer
|
/// Denied the incoming connection because we're already connected to this peer as a dialer
|
||||||
/// and we have a higher priority than the remote.
|
/// and we have a higher priority than the remote.
|
||||||
DeniedLowerPriority,
|
DeniedLowerPriority,
|
||||||
|
/// The negotiated `PeerId` is the same as the local node.
|
||||||
|
FoundLocalPeerId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TTransErr> fmt::Display for IncomingError<TTransErr>
|
impl<TTransErr> fmt::Display for IncomingError<TTransErr>
|
||||||
@ -341,6 +419,9 @@ where TTransErr: fmt::Display
|
|||||||
IncomingError::DeniedLowerPriority => {
|
IncomingError::DeniedLowerPriority => {
|
||||||
write!(f, "Denied because of lower priority")
|
write!(f, "Denied because of lower priority")
|
||||||
},
|
},
|
||||||
|
IncomingError::FoundLocalPeerId => {
|
||||||
|
write!(f, "Incoming connection has same PeerId as us")
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,6 +433,7 @@ where TTransErr: error::Error + 'static
|
|||||||
match self {
|
match self {
|
||||||
IncomingError::Transport(err) => Some(err),
|
IncomingError::Transport(err) => Some(err),
|
||||||
IncomingError::DeniedLowerPriority => None,
|
IncomingError::DeniedLowerPriority => None,
|
||||||
|
IncomingError::FoundLocalPeerId => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -362,12 +444,14 @@ where TTrans: Transport
|
|||||||
{
|
{
|
||||||
/// The produced upgrade.
|
/// The produced upgrade.
|
||||||
upgrade: TTrans::ListenerUpgrade,
|
upgrade: TTrans::ListenerUpgrade,
|
||||||
|
/// PeerId of the local node.
|
||||||
|
local_peer_id: PeerId,
|
||||||
/// Address of the listener which received the connection.
|
/// Address of the listener which received the connection.
|
||||||
listen_addr: Multiaddr,
|
listen_addr: Multiaddr,
|
||||||
/// Address used to send back data to the remote.
|
/// Address used to send back data to the remote.
|
||||||
send_back_addr: Multiaddr,
|
send_back_addr: Multiaddr,
|
||||||
/// Reference to the `active_nodes` field of the swarm.
|
/// Reference to the `active_nodes` field of the swarm.
|
||||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError<TTrans::Error>, THandlerErr>,
|
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, InternalReachErr<TTrans::Error>, THandlerErr>,
|
||||||
/// Reference to the `other_reach_attempts` field of the swarm.
|
/// Reference to the `other_reach_attempts` field of the swarm.
|
||||||
other_reach_attempts: &'a mut Vec<(ReachAttemptId, ConnectedPoint)>,
|
other_reach_attempts: &'a mut Vec<(ReachAttemptId, ConnectedPoint)>,
|
||||||
}
|
}
|
||||||
@ -400,7 +484,17 @@ where
|
|||||||
{
|
{
|
||||||
let connected_point = self.to_connected_point();
|
let connected_point = self.to_connected_point();
|
||||||
let handler = builder(self.info());
|
let handler = builder(self.info());
|
||||||
let id = self.active_nodes.add_reach_attempt(self.upgrade.map_err(|err| RawSwarmReachError::Transport(TransportError::Other(err))), handler);
|
let local_peer_id = self.local_peer_id;
|
||||||
|
let upgrade = self.upgrade
|
||||||
|
.map_err(|err| InternalReachErr::Transport(TransportError::Other(err)))
|
||||||
|
.and_then(move |(peer_id, muxer)| {
|
||||||
|
if peer_id == local_peer_id {
|
||||||
|
Err(InternalReachErr::FoundLocalPeerId)
|
||||||
|
} else {
|
||||||
|
Ok((peer_id, muxer))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let id = self.active_nodes.add_reach_attempt(upgrade, handler);
|
||||||
self.other_reach_attempts.push((
|
self.other_reach_attempts.push((
|
||||||
id,
|
id,
|
||||||
connected_point,
|
connected_point,
|
||||||
@ -605,10 +699,19 @@ where
|
|||||||
TInEvent: Send + 'static,
|
TInEvent: Send + 'static,
|
||||||
TOutEvent: Send + 'static,
|
TOutEvent: Send + 'static,
|
||||||
{
|
{
|
||||||
let future = self.transport().clone().dial(addr.clone())?;
|
let local_peer_id = self.reach_attempts.local_peer_id.clone();
|
||||||
|
let future = self.transport().clone().dial(addr.clone())?
|
||||||
|
.map_err(|err| InternalReachErr::Transport(TransportError::Other(err)))
|
||||||
|
.and_then(move |(peer_id, muxer)| {
|
||||||
|
if peer_id == local_peer_id {
|
||||||
|
Err(InternalReachErr::FoundLocalPeerId)
|
||||||
|
} else {
|
||||||
|
Ok((peer_id, muxer))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let connected_point = ConnectedPoint::Dialer { address: addr };
|
let connected_point = ConnectedPoint::Dialer { address: addr };
|
||||||
let reach_id = self.active_nodes.add_reach_attempt(future.map_err(|err| RawSwarmReachError::Transport(TransportError::Other(err))), handler);
|
let reach_id = self.active_nodes.add_reach_attempt(future, handler);
|
||||||
self.reach_attempts.other_reach_attempts.push((reach_id, connected_point));
|
self.reach_attempts.other_reach_attempts.push((reach_id, connected_point));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -715,18 +818,18 @@ where
|
|||||||
Ok(fut) => {
|
Ok(fut) => {
|
||||||
let expected_peer_id = peer_id.clone();
|
let expected_peer_id = peer_id.clone();
|
||||||
let fut = fut
|
let fut = fut
|
||||||
.map_err(|err| RawSwarmReachError::Transport(TransportError::Other(err)))
|
.map_err(|err| InternalReachErr::Transport(TransportError::Other(err)))
|
||||||
.and_then(move |(actual_peer_id, muxer)| {
|
.and_then(move |(actual_peer_id, muxer)| {
|
||||||
if actual_peer_id == expected_peer_id {
|
if actual_peer_id == expected_peer_id {
|
||||||
Ok((actual_peer_id, muxer))
|
Ok((actual_peer_id, muxer))
|
||||||
} else {
|
} else {
|
||||||
Err(RawSwarmReachError::PeerIdMismatch { obtained: actual_peer_id })
|
Err(InternalReachErr::PeerIdMismatch { obtained: actual_peer_id })
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.active_nodes.add_reach_attempt(fut, handler)
|
self.active_nodes.add_reach_attempt(fut, handler)
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let fut = future::err(RawSwarmReachError::Transport(err));
|
let fut = future::err(InternalReachErr::Transport(err));
|
||||||
self.active_nodes.add_reach_attempt(fut, handler)
|
self.active_nodes.add_reach_attempt(fut, handler)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -766,6 +869,7 @@ where
|
|||||||
Async::Ready(ListenersEvent::Incoming { upgrade, listen_addr, send_back_addr }) => {
|
Async::Ready(ListenersEvent::Incoming { upgrade, listen_addr, send_back_addr }) => {
|
||||||
let event = IncomingConnectionEvent {
|
let event = IncomingConnectionEvent {
|
||||||
upgrade,
|
upgrade,
|
||||||
|
local_peer_id: self.reach_attempts.local_peer_id.clone(),
|
||||||
listen_addr,
|
listen_addr,
|
||||||
send_back_addr,
|
send_back_addr,
|
||||||
active_nodes: &mut self.active_nodes,
|
active_nodes: &mut self.active_nodes,
|
||||||
@ -876,7 +980,7 @@ impl<THandler> Default for ActionItem<THandler> {
|
|||||||
/// > panics will likely happen.
|
/// > panics will likely happen.
|
||||||
fn handle_node_reached<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler, THandlerErr>(
|
fn handle_node_reached<'a, TTrans, TMuxer, TInEvent, TOutEvent, THandler, THandlerErr>(
|
||||||
reach_attempts: &mut ReachAttempts,
|
reach_attempts: &mut ReachAttempts,
|
||||||
event: CollectionReachEvent<TInEvent, TOutEvent, THandler, RawSwarmReachError<TTrans::Error>, THandlerErr>
|
event: CollectionReachEvent<TInEvent, TOutEvent, THandler, InternalReachErr<TTrans::Error>, THandlerErr>
|
||||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
||||||
where
|
where
|
||||||
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
TTrans: Transport<Output = (PeerId, TMuxer)> + Clone,
|
||||||
@ -1005,7 +1109,7 @@ fn has_dial_prio(local: &PeerId, other: &PeerId) -> bool {
|
|||||||
fn handle_reach_error<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>(
|
fn handle_reach_error<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>(
|
||||||
reach_attempts: &mut ReachAttempts,
|
reach_attempts: &mut ReachAttempts,
|
||||||
reach_id: ReachAttemptId,
|
reach_id: ReachAttemptId,
|
||||||
error: RawSwarmReachError<TTrans::Error>,
|
error: InternalReachErr<TTrans::Error>,
|
||||||
handler: THandler,
|
handler: THandler,
|
||||||
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
) -> (ActionItem<THandler>, RawSwarmEvent<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>)
|
||||||
where TTrans: Transport
|
where TTrans: Transport
|
||||||
@ -1035,6 +1139,17 @@ where TTrans: Transport
|
|||||||
Default::default()
|
Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let error = match error {
|
||||||
|
InternalReachErr::Transport(err) => RawSwarmReachError::Transport(err),
|
||||||
|
InternalReachErr::PeerIdMismatch { obtained } => {
|
||||||
|
RawSwarmReachError::PeerIdMismatch { obtained }
|
||||||
|
},
|
||||||
|
InternalReachErr::FoundLocalPeerId => {
|
||||||
|
unreachable!("We only generate FoundLocalPeerId within dial() or accept(); neither \
|
||||||
|
of these methods add an entry to out_reach_attempts; QED")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (action, RawSwarmEvent::DialError {
|
return (action, RawSwarmEvent::DialError {
|
||||||
remain_addrs_attempt: num_remain,
|
remain_addrs_attempt: num_remain,
|
||||||
peer_id,
|
peer_id,
|
||||||
@ -1050,12 +1165,16 @@ where TTrans: Transport
|
|||||||
.position(|i| i.0 == reach_id)
|
.position(|i| i.0 == reach_id)
|
||||||
{
|
{
|
||||||
let (_, endpoint) = reach_attempts.other_reach_attempts.swap_remove(in_pos);
|
let (_, endpoint) = reach_attempts.other_reach_attempts.swap_remove(in_pos);
|
||||||
let error = match error {
|
|
||||||
RawSwarmReachError::Transport(err) => err,
|
|
||||||
RawSwarmReachError::PeerIdMismatch { .. } => unreachable!(), // TODO: prove
|
|
||||||
};
|
|
||||||
match endpoint {
|
match endpoint {
|
||||||
ConnectedPoint::Dialer { address } => {
|
ConnectedPoint::Dialer { address } => {
|
||||||
|
let error = match error {
|
||||||
|
InternalReachErr::Transport(err) => UnknownPeerDialErr::Transport(err),
|
||||||
|
InternalReachErr::FoundLocalPeerId => UnknownPeerDialErr::FoundLocalPeerId,
|
||||||
|
InternalReachErr::PeerIdMismatch { .. } => {
|
||||||
|
unreachable!("We only generate PeerIdMismatch within start_dial_out(),
|
||||||
|
which doesn't add any entry in other_reach_attempts; QED")
|
||||||
|
},
|
||||||
|
};
|
||||||
return (Default::default(), RawSwarmEvent::UnknownPeerDialError {
|
return (Default::default(), RawSwarmEvent::UnknownPeerDialError {
|
||||||
multiaddr: address,
|
multiaddr: address,
|
||||||
error,
|
error,
|
||||||
@ -1063,8 +1182,19 @@ where TTrans: Transport
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
ConnectedPoint::Listener { listen_addr, send_back_addr } => {
|
ConnectedPoint::Listener { listen_addr, send_back_addr } => {
|
||||||
let error = IncomingError::Transport(error);
|
let error = match error {
|
||||||
return (Default::default(), RawSwarmEvent::IncomingConnectionError { listen_addr, send_back_addr, error });
|
InternalReachErr::Transport(err) => IncomingError::Transport(err),
|
||||||
|
InternalReachErr::FoundLocalPeerId => IncomingError::FoundLocalPeerId,
|
||||||
|
InternalReachErr::PeerIdMismatch { .. } => {
|
||||||
|
unreachable!("We only generate PeerIdMismatch within start_dial_out(),
|
||||||
|
which doesn't add any entry in other_reach_attempts; QED")
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return (Default::default(), RawSwarmEvent::IncomingConnectionError {
|
||||||
|
listen_addr,
|
||||||
|
send_back_addr,
|
||||||
|
error
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1301,7 +1431,7 @@ where
|
|||||||
TTrans: Transport
|
TTrans: Transport
|
||||||
{
|
{
|
||||||
attempt: OccupiedEntry<'a, PeerId, OutReachAttempt>,
|
attempt: OccupiedEntry<'a, PeerId, OutReachAttempt>,
|
||||||
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, RawSwarmReachError<TTrans::Error>, THandlerErr>,
|
active_nodes: &'a mut CollectionStream<TInEvent, TOutEvent, THandler, InternalReachErr<TTrans::Error>, THandlerErr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr> PeerPendingConnect<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
impl<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr> PeerPendingConnect<'a, TTrans, TInEvent, TOutEvent, THandler, THandlerErr>
|
||||||
|
Reference in New Issue
Block a user