mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-08-01 01:11:58 +00:00
*: Format with rustfmt (#2188)
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
@@ -19,28 +19,23 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::protocol;
|
||||
use futures::prelude::*;
|
||||
use futures::future::BoxFuture;
|
||||
use libp2p_core::{UpgradeError, upgrade::NegotiationError};
|
||||
use futures::prelude::*;
|
||||
use libp2p_core::{upgrade::NegotiationError, UpgradeError};
|
||||
use libp2p_swarm::{
|
||||
KeepAlive,
|
||||
NegotiatedSubstream,
|
||||
SubstreamProtocol,
|
||||
ProtocolsHandler,
|
||||
ProtocolsHandlerUpgrErr,
|
||||
ProtocolsHandlerEvent
|
||||
};
|
||||
use std::{
|
||||
error::Error,
|
||||
io,
|
||||
fmt,
|
||||
num::NonZeroU32,
|
||||
task::{Context, Poll},
|
||||
time::Duration
|
||||
KeepAlive, NegotiatedSubstream, ProtocolsHandler, ProtocolsHandlerEvent,
|
||||
ProtocolsHandlerUpgrErr, SubstreamProtocol,
|
||||
};
|
||||
use std::collections::VecDeque;
|
||||
use wasm_timer::Delay;
|
||||
use std::{
|
||||
error::Error,
|
||||
fmt, io,
|
||||
num::NonZeroU32,
|
||||
task::{Context, Poll},
|
||||
time::Duration,
|
||||
};
|
||||
use void::Void;
|
||||
use wasm_timer::Delay;
|
||||
|
||||
/// The configuration for outbound pings.
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -82,7 +77,7 @@ impl PingConfig {
|
||||
timeout: Duration::from_secs(20),
|
||||
interval: Duration::from_secs(15),
|
||||
max_failures: NonZeroU32::new(1).expect("1 != 0"),
|
||||
keep_alive: false
|
||||
keep_alive: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +139,9 @@ pub enum PingFailure {
|
||||
/// The peer does not support the ping protocol.
|
||||
Unsupported,
|
||||
/// The ping failed for reasons other than a timeout.
|
||||
Other { error: Box<dyn std::error::Error + Send + 'static> }
|
||||
Other {
|
||||
error: Box<dyn std::error::Error + Send + 'static>,
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for PingFailure {
|
||||
@@ -190,7 +187,7 @@ pub struct PingHandler {
|
||||
/// next inbound ping to be answered.
|
||||
inbound: Option<PongFuture>,
|
||||
/// Tracks the state of our handler.
|
||||
state: State
|
||||
state: State,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -200,7 +197,7 @@ enum State {
|
||||
/// Whether or not we've reported the missing support yet.
|
||||
///
|
||||
/// This is used to avoid repeated events being emitted for a specific connection.
|
||||
reported: bool
|
||||
reported: bool,
|
||||
},
|
||||
/// We are actively pinging the other peer.
|
||||
Active,
|
||||
@@ -252,11 +249,9 @@ impl ProtocolsHandler for PingHandler {
|
||||
ProtocolsHandlerUpgrErr::Upgrade(UpgradeError::Select(NegotiationError::Failed)) => {
|
||||
debug_assert_eq!(self.state, State::Active);
|
||||
|
||||
self.state = State::Inactive {
|
||||
reported: false
|
||||
};
|
||||
self.state = State::Inactive { reported: false };
|
||||
return;
|
||||
},
|
||||
}
|
||||
// Note: This timeout only covers protocol negotiation.
|
||||
ProtocolsHandlerUpgrErr::Timeout => PingFailure::Timeout,
|
||||
e => PingFailure::Other { error: Box::new(e) },
|
||||
@@ -273,22 +268,25 @@ impl ProtocolsHandler for PingHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fn poll(&mut self, cx: &mut Context<'_>) -> Poll<ProtocolsHandlerEvent<protocol::Ping, (), PingResult, Self::Error>> {
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context<'_>,
|
||||
) -> Poll<ProtocolsHandlerEvent<protocol::Ping, (), PingResult, Self::Error>> {
|
||||
match self.state {
|
||||
State::Inactive { reported: true } => {
|
||||
return Poll::Pending // nothing to do on this connection
|
||||
},
|
||||
return Poll::Pending; // nothing to do on this connection
|
||||
}
|
||||
State::Inactive { reported: false } => {
|
||||
self.state = State::Inactive { reported: true };
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Err(PingFailure::Unsupported)));
|
||||
},
|
||||
}
|
||||
State::Active => {}
|
||||
}
|
||||
|
||||
// Respond to inbound pings.
|
||||
if let Some(fut) = self.inbound.as_mut() {
|
||||
match fut.poll_unpin(cx) {
|
||||
Poll::Pending => {},
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(Err(e)) => {
|
||||
log::debug!("Inbound ping error: {:?}", e);
|
||||
self.inbound = None;
|
||||
@@ -296,7 +294,7 @@ impl ProtocolsHandler for PingHandler {
|
||||
Poll::Ready(Ok(stream)) => {
|
||||
// A ping from a remote peer has been answered, wait for the next.
|
||||
self.inbound = Some(protocol::recv_ping(stream).boxed());
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Ok(PingSuccess::Pong)))
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Ok(PingSuccess::Pong)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,10 +316,10 @@ impl ProtocolsHandler for PingHandler {
|
||||
if self.failures > 1 || self.config.max_failures.get() > 1 {
|
||||
if self.failures >= self.config.max_failures.get() {
|
||||
log::debug!("Too many failures ({}). Closing connection.", self.failures);
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Close(error))
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Close(error));
|
||||
}
|
||||
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Err(error)))
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Err(error)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,50 +331,48 @@ impl ProtocolsHandler for PingHandler {
|
||||
self.pending_errors.push_front(PingFailure::Timeout);
|
||||
} else {
|
||||
self.outbound = Some(PingState::Ping(ping));
|
||||
break
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
Poll::Ready(Ok((stream, rtt))) => {
|
||||
self.failures = 0;
|
||||
self.timer.reset(self.config.interval);
|
||||
self.outbound = Some(PingState::Idle(stream));
|
||||
return Poll::Ready(
|
||||
ProtocolsHandlerEvent::Custom(
|
||||
Ok(PingSuccess::Ping { rtt })))
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(Ok(PingSuccess::Ping {
|
||||
rtt,
|
||||
})));
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
self.pending_errors.push_front(PingFailure::Other {
|
||||
error: Box::new(e)
|
||||
});
|
||||
self.pending_errors
|
||||
.push_front(PingFailure::Other { error: Box::new(e) });
|
||||
}
|
||||
},
|
||||
Some(PingState::Idle(stream)) => match self.timer.poll_unpin(cx) {
|
||||
Poll::Pending => {
|
||||
self.outbound = Some(PingState::Idle(stream));
|
||||
break
|
||||
},
|
||||
break;
|
||||
}
|
||||
Poll::Ready(Ok(())) => {
|
||||
self.timer.reset(self.config.timeout);
|
||||
self.outbound = Some(PingState::Ping(protocol::send_ping(stream).boxed()));
|
||||
},
|
||||
Poll::Ready(Err(e)) => {
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Close(
|
||||
PingFailure::Other {
|
||||
error: Box::new(e)
|
||||
}))
|
||||
}
|
||||
}
|
||||
Poll::Ready(Err(e)) => {
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Close(PingFailure::Other {
|
||||
error: Box::new(e),
|
||||
}))
|
||||
}
|
||||
},
|
||||
Some(PingState::OpenStream) => {
|
||||
self.outbound = Some(PingState::OpenStream);
|
||||
break
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
self.outbound = Some(PingState::OpenStream);
|
||||
let protocol = SubstreamProtocol::new(protocol::Ping, ())
|
||||
.with_timeout(self.config.timeout);
|
||||
return Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol
|
||||
})
|
||||
protocol,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -40,13 +40,13 @@
|
||||
//! [`Swarm`]: libp2p_swarm::Swarm
|
||||
//! [`Transport`]: libp2p_core::Transport
|
||||
|
||||
pub mod protocol;
|
||||
pub mod handler;
|
||||
pub mod protocol;
|
||||
|
||||
pub use handler::{PingConfig, PingResult, PingSuccess, PingFailure};
|
||||
use handler::PingHandler;
|
||||
pub use handler::{PingConfig, PingFailure, PingResult, PingSuccess};
|
||||
|
||||
use libp2p_core::{PeerId, connection::ConnectionId};
|
||||
use libp2p_core::{connection::ConnectionId, PeerId};
|
||||
use libp2p_swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters};
|
||||
use std::{collections::VecDeque, task::Context, task::Poll};
|
||||
use void::Void;
|
||||
@@ -99,9 +99,11 @@ impl NetworkBehaviour for Ping {
|
||||
self.events.push_front(PingEvent { peer, result })
|
||||
}
|
||||
|
||||
fn poll(&mut self, _: &mut Context<'_>, _: &mut impl PollParameters)
|
||||
-> Poll<NetworkBehaviourAction<Void, PingEvent>>
|
||||
{
|
||||
fn poll(
|
||||
&mut self,
|
||||
_: &mut Context<'_>,
|
||||
_: &mut impl PollParameters,
|
||||
) -> Poll<NetworkBehaviourAction<Void, PingEvent>> {
|
||||
if let Some(e) = self.events.pop_back() {
|
||||
Poll::Ready(NetworkBehaviourAction::GenerateEvent(e))
|
||||
} else {
|
||||
|
@@ -82,7 +82,7 @@ impl OutboundUpgrade<NegotiatedSubstream> for Ping {
|
||||
/// Sends a ping and waits for the pong.
|
||||
pub async fn send_ping<S>(mut stream: S) -> io::Result<(S, Duration)>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
let payload: [u8; PING_SIZE] = thread_rng().sample(distributions::Standard);
|
||||
log::debug!("Preparing ping payload {:?}", payload);
|
||||
@@ -95,14 +95,17 @@ where
|
||||
if recv_payload == payload {
|
||||
Ok((stream, started.elapsed()))
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::InvalidData, "Ping payload mismatch"))
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::InvalidData,
|
||||
"Ping payload mismatch",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits for a ping and sends a pong.
|
||||
pub async fn recv_ping<S>(mut stream: S) -> io::Result<S>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
let mut payload = [0u8; PING_SIZE];
|
||||
log::debug!("Waiting for ping ...");
|
||||
@@ -118,11 +121,7 @@ mod tests {
|
||||
use super::*;
|
||||
use libp2p_core::{
|
||||
multiaddr::multiaddr,
|
||||
transport::{
|
||||
Transport,
|
||||
ListenerEvent,
|
||||
memory::MemoryTransport
|
||||
}
|
||||
transport::{memory::MemoryTransport, ListenerEvent, Transport},
|
||||
};
|
||||
use rand::{thread_rng, Rng};
|
||||
use std::time::Duration;
|
||||
|
@@ -20,13 +20,12 @@
|
||||
|
||||
//! Integration tests for the `Ping` network behaviour.
|
||||
|
||||
use futures::{channel::mpsc, prelude::*};
|
||||
use libp2p_core::{
|
||||
Multiaddr,
|
||||
PeerId,
|
||||
identity,
|
||||
muxing::StreamMuxerBox,
|
||||
transport::{self, Transport},
|
||||
upgrade
|
||||
upgrade, Multiaddr, PeerId,
|
||||
};
|
||||
use libp2p_mplex as mplex;
|
||||
use libp2p_noise as noise;
|
||||
@@ -34,7 +33,6 @@ use libp2p_ping::*;
|
||||
use libp2p_swarm::{DummyBehaviour, KeepAlive, Swarm, SwarmEvent};
|
||||
use libp2p_tcp::TcpConfig;
|
||||
use libp2p_yamux as yamux;
|
||||
use futures::{prelude::*, channel::mpsc};
|
||||
use quickcheck::*;
|
||||
use rand::prelude::*;
|
||||
use std::{num::NonZeroU8, time::Duration};
|
||||
@@ -65,13 +63,18 @@ fn ping_pong() {
|
||||
loop {
|
||||
match swarm1.select_next_some().await {
|
||||
SwarmEvent::NewListenAddr { address, .. } => tx.send(address).await.unwrap(),
|
||||
SwarmEvent::Behaviour(PingEvent { peer, result: Ok(PingSuccess::Ping { rtt }) }) => {
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
peer,
|
||||
result: Ok(PingSuccess::Ping { rtt }),
|
||||
}) => {
|
||||
count1 -= 1;
|
||||
if count1 == 0 {
|
||||
return (pid1.clone(), peer, rtt)
|
||||
return (pid1.clone(), peer, rtt);
|
||||
}
|
||||
},
|
||||
SwarmEvent::Behaviour(PingEvent { result: Err(e), .. }) => panic!("Ping failure: {:?}", e),
|
||||
}
|
||||
SwarmEvent::Behaviour(PingEvent { result: Err(e), .. }) => {
|
||||
panic!("Ping failure: {:?}", e)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -85,17 +88,16 @@ fn ping_pong() {
|
||||
match swarm2.select_next_some().await {
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
peer,
|
||||
result: Ok(PingSuccess::Ping { rtt })
|
||||
result: Ok(PingSuccess::Ping { rtt }),
|
||||
}) => {
|
||||
count2 -= 1;
|
||||
if count2 == 0 {
|
||||
return (pid2.clone(), peer, rtt)
|
||||
return (pid2.clone(), peer, rtt);
|
||||
}
|
||||
},
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Err(e),
|
||||
..
|
||||
}) => panic!("Ping failure: {:?}", e),
|
||||
}
|
||||
SwarmEvent::Behaviour(PingEvent { result: Err(e), .. }) => {
|
||||
panic!("Ping failure: {:?}", e)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -107,7 +109,7 @@ fn ping_pong() {
|
||||
assert!(rtt < Duration::from_millis(50));
|
||||
}
|
||||
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_,_))
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_, _))
|
||||
}
|
||||
|
||||
/// Tests that the connection is closed upon a configurable
|
||||
@@ -139,18 +141,15 @@ fn max_failures() {
|
||||
match swarm1.select_next_some().await {
|
||||
SwarmEvent::NewListenAddr { address, .. } => tx.send(address).await.unwrap(),
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Ok(PingSuccess::Ping { .. }), ..
|
||||
result: Ok(PingSuccess::Ping { .. }),
|
||||
..
|
||||
}) => {
|
||||
count1 = 0; // there may be an occasional success
|
||||
}
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Err(_), ..
|
||||
}) => {
|
||||
SwarmEvent::Behaviour(PingEvent { result: Err(_), .. }) => {
|
||||
count1 += 1;
|
||||
}
|
||||
SwarmEvent::ConnectionClosed { .. } => {
|
||||
return count1
|
||||
}
|
||||
SwarmEvent::ConnectionClosed { .. } => return count1,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -164,18 +163,15 @@ fn max_failures() {
|
||||
loop {
|
||||
match swarm2.select_next_some().await {
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Ok(PingSuccess::Ping { .. }), ..
|
||||
result: Ok(PingSuccess::Ping { .. }),
|
||||
..
|
||||
}) => {
|
||||
count2 = 0; // there may be an occasional success
|
||||
}
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Err(_), ..
|
||||
}) => {
|
||||
SwarmEvent::Behaviour(PingEvent { result: Err(_), .. }) => {
|
||||
count2 += 1;
|
||||
}
|
||||
SwarmEvent::ConnectionClosed { .. } => {
|
||||
return count2
|
||||
}
|
||||
SwarmEvent::ConnectionClosed { .. } => return count2,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -186,16 +182,24 @@ fn max_failures() {
|
||||
assert_eq!(u8::max(count1, count2), max_failures.get() - 1);
|
||||
}
|
||||
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_,_))
|
||||
QuickCheck::new().tests(10).quickcheck(prop as fn(_, _))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsupported_doesnt_fail() {
|
||||
let (peer1_id, trans) = mk_transport(MuxerChoice::Mplex);
|
||||
let mut swarm1 = Swarm::new(trans, DummyBehaviour::with_keep_alive(KeepAlive::Yes), peer1_id.clone());
|
||||
let mut swarm1 = Swarm::new(
|
||||
trans,
|
||||
DummyBehaviour::with_keep_alive(KeepAlive::Yes),
|
||||
peer1_id.clone(),
|
||||
);
|
||||
|
||||
let (peer2_id, trans) = mk_transport(MuxerChoice::Mplex);
|
||||
let mut swarm2 = Swarm::new(trans, Ping::new(PingConfig::new().with_keep_alive(true)), peer2_id.clone());
|
||||
let mut swarm2 = Swarm::new(
|
||||
trans,
|
||||
Ping::new(PingConfig::new().with_keep_alive(true)),
|
||||
peer2_id.clone(),
|
||||
);
|
||||
|
||||
let (mut tx, mut rx) = mpsc::channel::<Multiaddr>(1);
|
||||
|
||||
@@ -217,7 +221,8 @@ fn unsupported_doesnt_fail() {
|
||||
loop {
|
||||
match swarm2.select_next_some().await {
|
||||
SwarmEvent::Behaviour(PingEvent {
|
||||
result: Err(PingFailure::Unsupported), ..
|
||||
result: Err(PingFailure::Unsupported),
|
||||
..
|
||||
}) => {
|
||||
swarm2.disconnect_peer_id(peer1_id).unwrap();
|
||||
}
|
||||
@@ -235,25 +240,24 @@ fn unsupported_doesnt_fail() {
|
||||
result.expect("node with ping should not fail connection due to unsupported protocol");
|
||||
}
|
||||
|
||||
|
||||
fn mk_transport(muxer: MuxerChoice) -> (
|
||||
PeerId,
|
||||
transport::Boxed<(PeerId, StreamMuxerBox)>
|
||||
) {
|
||||
fn mk_transport(muxer: MuxerChoice) -> (PeerId, transport::Boxed<(PeerId, StreamMuxerBox)>) {
|
||||
let id_keys = identity::Keypair::generate_ed25519();
|
||||
let peer_id = id_keys.public().to_peer_id();
|
||||
let noise_keys = noise::Keypair::<noise::X25519Spec>::new().into_authentic(&id_keys).unwrap();
|
||||
(peer_id, TcpConfig::new()
|
||||
.nodelay(true)
|
||||
.upgrade(upgrade::Version::V1)
|
||||
.authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
|
||||
.multiplex(match muxer {
|
||||
MuxerChoice::Yamux =>
|
||||
upgrade::EitherUpgrade::A(yamux::YamuxConfig::default()),
|
||||
MuxerChoice::Mplex =>
|
||||
upgrade::EitherUpgrade::B(mplex::MplexConfig::default()),
|
||||
})
|
||||
.boxed())
|
||||
let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
|
||||
.into_authentic(&id_keys)
|
||||
.unwrap();
|
||||
(
|
||||
peer_id,
|
||||
TcpConfig::new()
|
||||
.nodelay(true)
|
||||
.upgrade(upgrade::Version::V1)
|
||||
.authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
|
||||
.multiplex(match muxer {
|
||||
MuxerChoice::Yamux => upgrade::EitherUpgrade::A(yamux::YamuxConfig::default()),
|
||||
MuxerChoice::Mplex => upgrade::EitherUpgrade::B(mplex::MplexConfig::default()),
|
||||
})
|
||||
.boxed(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
Reference in New Issue
Block a user