mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-11 21:11:07 +00:00
Update networking code to libp2p 0.14 (#4383)
* Entirely update substrate-telemetry to futures 0.3 * Add a Closed error * Update to libp2p 0.14 * More work * More work * More work * More work * Fix warnings * Remove unwrap() * Work on tests fixing * Fix network tests * Fix external network tests * Update libp2p and restore Yamux in discovery test * Ignore DNS if initializatio nfails * Restore variables ordering * Forgot browser-utils * Fix downfall after merge * Fix tests
This commit is contained in:
committed by
Gavin Wood
parent
6e572a9477
commit
ca997cf1e4
Generated
+304
-316
File diff suppressed because it is too large
Load Diff
@@ -183,19 +183,16 @@ macro_rules! new_full {
|
||||
service.spawn_essential_task(babe);
|
||||
|
||||
let network = service.network();
|
||||
let dht_event_stream = network.event_stream().filter_map(|e| match e {
|
||||
let dht_event_stream = network.event_stream().filter_map(|e| async move { match e {
|
||||
Event::Dht(e) => Some(e),
|
||||
_ => None,
|
||||
});
|
||||
let future03_dht_event_stream = dht_event_stream.compat()
|
||||
.map(|x| x.expect("<mpsc::channel::Receiver as Stream> never returns an error; qed"))
|
||||
.boxed();
|
||||
}}).boxed();
|
||||
let authority_discovery = sc_authority_discovery::AuthorityDiscovery::new(
|
||||
service.client(),
|
||||
network,
|
||||
sentry_nodes,
|
||||
service.keystore(),
|
||||
future03_dht_event_stream,
|
||||
dht_event_stream,
|
||||
);
|
||||
let future01_authority_discovery = authority_discovery.map(|x| Ok(x)).compat();
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ codec = { package = "parity-scale-codec", default-features = false, version = "1
|
||||
derive_more = "0.99.2"
|
||||
futures = "0.3.1"
|
||||
futures-timer = "2.0"
|
||||
libp2p = { version = "0.13.2", default-features = false, features = ["secp256k1", "libp2p-websocket"] }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["secp256k1", "libp2p-websocket"] }
|
||||
log = "0.4.8"
|
||||
prost = "0.5.0"
|
||||
rand = "0.7.2"
|
||||
|
||||
@@ -12,7 +12,7 @@ futures01 = { package = "futures", version = "0.1.29" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
futures-timer = "0.4.0"
|
||||
lru = "0.1.2"
|
||||
libp2p = { version = "0.13.2", default-features = false, features = ["libp2p-websocket"] }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] }
|
||||
sc-network = { version = "0.8", path = "../network" }
|
||||
parking_lot = "0.9.0"
|
||||
sp-runtime = { version = "2.0.0", path = "../../primitives/runtime" }
|
||||
|
||||
@@ -59,6 +59,7 @@ pub use self::state_machine::{TopicNotification, MessageIntent};
|
||||
pub use self::state_machine::{Validator, ValidatorContext, ValidationResult};
|
||||
pub use self::state_machine::DiscardAll;
|
||||
|
||||
use futures::prelude::*;
|
||||
use sc_network::{specialization::NetworkSpecialization, Event, ExHashT, NetworkService, PeerId, ReputationChange};
|
||||
use sp_runtime::{traits::Block as BlockT, ConsensusEngineId};
|
||||
use std::sync::Arc;
|
||||
@@ -97,7 +98,7 @@ pub trait Network<B: BlockT> {
|
||||
|
||||
impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Network<B> for Arc<NetworkService<B, S, H>> {
|
||||
fn event_stream(&self) -> Box<dyn futures01::Stream<Item = Event, Error = ()> + Send> {
|
||||
Box::new(NetworkService::event_stream(self))
|
||||
Box::new(NetworkService::event_stream(self).map(|v| Ok::<_, ()>(v)).compat())
|
||||
}
|
||||
|
||||
fn report_peer(&self, peer_id: PeerId, reputation: ReputationChange) {
|
||||
|
||||
@@ -7,22 +7,22 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bytes = "0.4.12"
|
||||
bytes = "0.5.0"
|
||||
derive_more = "0.99.2"
|
||||
either = "1.5.3"
|
||||
log = "0.4.8"
|
||||
parking_lot = "0.9.0"
|
||||
bitflags = "1.2.0"
|
||||
fnv = "1.0.6"
|
||||
futures = "0.1.29"
|
||||
futures03 = { package = "futures", version = "0.3.1", features = ["compat"] }
|
||||
futures = "0.3.1"
|
||||
futures_codec = "0.3.3"
|
||||
futures-timer = "0.4.0"
|
||||
linked-hash-map = "0.5.2"
|
||||
linked_hash_set = "0.1.3"
|
||||
lru = "0.4.0"
|
||||
rustc-hex = "2.0.1"
|
||||
rand = "0.7.2"
|
||||
libp2p = { version = "0.13.2", default-features = false, features = ["libp2p-websocket"] }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] }
|
||||
fork-tree = { version = "2.0.0", path = "../../utils/fork-tree" }
|
||||
sp-consensus = { version = "0.8", path = "../../primitives/consensus/common" }
|
||||
sc-client = { version = "2.0.0", path = "../" }
|
||||
@@ -39,9 +39,7 @@ serde_json = "1.0.41"
|
||||
slog = { version = "2.5.2", features = ["nested-values"] }
|
||||
slog_derive = "0.2.0"
|
||||
smallvec = "0.6.10"
|
||||
tokio-io = "0.1.12"
|
||||
tokio = { version = "0.1.22", optional = true }
|
||||
unsigned-varint = { version = "0.2.2", features = ["codec"] }
|
||||
unsigned-varint = { version = "0.3.0", features = ["codec"] }
|
||||
sp-keyring = { version = "2.0.0", optional = true, path = "../../primitives/keyring" }
|
||||
substrate-test-client = { version = "2.0.0", optional = true, path = "../../test-utils/client" }
|
||||
substrate-test-runtime-client = { version = "2.0.0", optional = true, path = "../../test-utils/runtime/client" }
|
||||
@@ -57,8 +55,7 @@ sp-keyring = { version = "2.0.0", path = "../../primitives/keyring" }
|
||||
quickcheck = "0.9.0"
|
||||
rand = "0.7.2"
|
||||
tempfile = "3.1.0"
|
||||
tokio = "0.1.22"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
test-helpers = ["sp-keyring", "substrate-test-runtime-client", "tokio"]
|
||||
test-helpers = ["sp-keyring", "substrate-test-runtime-client"]
|
||||
|
||||
@@ -20,7 +20,6 @@ use crate::{
|
||||
};
|
||||
use crate::{ExHashT, specialization::NetworkSpecialization};
|
||||
use crate::protocol::{CustomMessageOutcome, Protocol};
|
||||
use futures::prelude::*;
|
||||
use libp2p::NetworkBehaviour;
|
||||
use libp2p::core::{Multiaddr, PeerId, PublicKey};
|
||||
use libp2p::kad::record;
|
||||
@@ -29,7 +28,7 @@ use libp2p::core::{nodes::Substream, muxing::StreamMuxerBox};
|
||||
use log::{debug, warn};
|
||||
use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}};
|
||||
use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification};
|
||||
use std::iter;
|
||||
use std::{iter, task::Context, task::Poll};
|
||||
use void;
|
||||
|
||||
/// General behaviour of the network. Combines all protocols together.
|
||||
@@ -59,7 +58,7 @@ pub enum BehaviourOut<B: BlockT> {
|
||||
|
||||
impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Behaviour<B, S, H> {
|
||||
/// Builds a new `Behaviour`.
|
||||
pub fn new(
|
||||
pub async fn new(
|
||||
substrate: Protocol<B, S, H>,
|
||||
user_agent: String,
|
||||
local_public_key: PublicKey,
|
||||
@@ -75,7 +74,7 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Behaviour<B, S, H> {
|
||||
known_addresses,
|
||||
enable_mdns,
|
||||
allow_private_ipv4
|
||||
),
|
||||
).await,
|
||||
events: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -212,11 +211,11 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> NetworkBehaviourEventPr
|
||||
}
|
||||
|
||||
impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Behaviour<B, S, H> {
|
||||
fn poll<TEv>(&mut self) -> Async<NetworkBehaviourAction<TEv, BehaviourOut<B>>> {
|
||||
fn poll<TEv>(&mut self, _: &mut Context) -> Poll<NetworkBehaviourAction<TEv, BehaviourOut<B>>> {
|
||||
if !self.events.is_empty() {
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0)))
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(self.events.remove(0)))
|
||||
}
|
||||
|
||||
Async::NotReady
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
use fnv::FnvHashMap;
|
||||
use futures::prelude::*;
|
||||
use futures03::{StreamExt as _, TryStreamExt as _};
|
||||
use libp2p::Multiaddr;
|
||||
use libp2p::core::{ConnectedPoint, either::EitherOutput, PeerId, PublicKey};
|
||||
use libp2p::swarm::{IntoProtocolsHandler, IntoProtocolsHandlerSelect, ProtocolsHandler};
|
||||
@@ -25,8 +24,9 @@ use libp2p::identify::{Identify, IdentifyEvent, IdentifyInfo};
|
||||
use libp2p::ping::{Ping, PingConfig, PingEvent, PingSuccess};
|
||||
use log::{debug, trace, error};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use crate::utils::interval;
|
||||
|
||||
/// Time after we disconnect from a node before we purge its information from the cache.
|
||||
@@ -44,7 +44,7 @@ pub struct DebugInfoBehaviour<TSubstream> {
|
||||
/// Information that we know about all nodes.
|
||||
nodes_info: FnvHashMap<PeerId, NodeInfo>,
|
||||
/// Interval at which we perform garbage collection in `nodes_info`.
|
||||
garbage_collect: Box<dyn Stream<Item = (), Error = ()> + Send>,
|
||||
garbage_collect: Pin<Box<dyn Stream<Item = ()> + Send>>,
|
||||
}
|
||||
|
||||
/// Information about a node we're connected to.
|
||||
@@ -76,7 +76,7 @@ impl<TSubstream> DebugInfoBehaviour<TSubstream> {
|
||||
ping: Ping::new(PingConfig::new()),
|
||||
identify,
|
||||
nodes_info: FnvHashMap::default(),
|
||||
garbage_collect: Box::new(interval(GARBAGE_COLLECT_INTERVAL).map(|()| Ok(())).compat()),
|
||||
garbage_collect: Box::pin(interval(GARBAGE_COLLECT_INTERVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ pub enum DebugInfoEvent {
|
||||
}
|
||||
|
||||
impl<TSubstream> NetworkBehaviour for DebugInfoBehaviour<TSubstream>
|
||||
where TSubstream: AsyncRead + AsyncWrite {
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin + Send + 'static {
|
||||
type ProtocolsHandler = IntoProtocolsHandlerSelect<
|
||||
<Ping<TSubstream> as NetworkBehaviour>::ProtocolsHandler,
|
||||
<Identify<TSubstream> as NetworkBehaviour>::ProtocolsHandler
|
||||
@@ -253,70 +253,71 @@ where TSubstream: AsyncRead + AsyncWrite {
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
params: &mut impl PollParameters
|
||||
) -> Async<
|
||||
) -> Poll<
|
||||
NetworkBehaviourAction<
|
||||
<<Self::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
|
||||
Self::OutEvent
|
||||
>
|
||||
> {
|
||||
loop {
|
||||
match self.ping.poll(params) {
|
||||
Async::NotReady => break,
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => {
|
||||
match self.ping.poll(cx, params) {
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => {
|
||||
if let PingEvent { peer, result: Ok(PingSuccess::Ping { rtt }) } = ev {
|
||||
self.handle_ping_report(&peer, rtt)
|
||||
}
|
||||
},
|
||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::SendEvent {
|
||||
Poll::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::SendEvent {
|
||||
peer_id,
|
||||
event: EitherOutput::First(event)
|
||||
}),
|
||||
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
match self.identify.poll(params) {
|
||||
Async::NotReady => break,
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
|
||||
match self.identify.poll(cx, params) {
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
|
||||
match event {
|
||||
IdentifyEvent::Received { peer_id, info, .. } => {
|
||||
self.handle_identify_report(&peer_id, &info);
|
||||
let event = DebugInfoEvent::Identified { peer_id, info };
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(event));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(event));
|
||||
}
|
||||
IdentifyEvent::Error { peer_id, error } =>
|
||||
debug!(target: "sub-libp2p", "Identification with peer {:?} failed => {}", peer_id, error),
|
||||
IdentifyEvent::Sent { .. } => {}
|
||||
}
|
||||
},
|
||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::SendEvent {
|
||||
Poll::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::SendEvent {
|
||||
peer_id,
|
||||
event: EitherOutput::Second(event)
|
||||
}),
|
||||
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
}
|
||||
}
|
||||
|
||||
while let Ok(Async::Ready(Some(_))) = self.garbage_collect.poll() {
|
||||
while let Poll::Ready(Some(())) = self.garbage_collect.poll_next_unpin(cx) {
|
||||
self.nodes_info.retain(|_, node| {
|
||||
node.info_expire.as_ref().map(|exp| *exp >= Instant::now()).unwrap_or(true)
|
||||
});
|
||||
}
|
||||
|
||||
Async::NotReady
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
|
||||
use futures::prelude::*;
|
||||
use futures_timer::Delay;
|
||||
use futures03::{compat::Compat, TryFutureExt as _};
|
||||
use libp2p::core::{ConnectedPoint, Multiaddr, PeerId, PublicKey};
|
||||
use libp2p::swarm::{ProtocolsHandler, NetworkBehaviour, NetworkBehaviourAction, PollParameters};
|
||||
use libp2p::kad::{Kademlia, KademliaEvent, Quorum, Record};
|
||||
@@ -62,7 +61,7 @@ use libp2p::mdns::{Mdns, MdnsEvent};
|
||||
use libp2p::multiaddr::Protocol;
|
||||
use log::{debug, info, trace, warn};
|
||||
use std::{cmp, collections::VecDeque, time::Duration};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use std::task::{Context, Poll};
|
||||
use sp_core::hexdisplay::HexDisplay;
|
||||
|
||||
/// Implementation of `NetworkBehaviour` that discovers the nodes on the network.
|
||||
@@ -76,7 +75,7 @@ pub struct DiscoveryBehaviour<TSubstream> {
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
mdns: Toggle<Mdns<Substream<StreamMuxerBox>>>,
|
||||
/// Stream that fires when we need to perform the next random Kademlia query.
|
||||
next_kad_random_query: Compat<Delay>,
|
||||
next_kad_random_query: Delay,
|
||||
/// After `next_kad_random_query` triggers, the next one triggers after this duration.
|
||||
duration_to_next_kad: Duration,
|
||||
/// Discovered nodes to return.
|
||||
@@ -94,7 +93,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
|
||||
/// Builds a new `DiscoveryBehaviour`.
|
||||
///
|
||||
/// `user_defined` is a list of known address for nodes that never expire.
|
||||
pub fn new(
|
||||
pub async fn new(
|
||||
local_public_key: PublicKey,
|
||||
user_defined: Vec<(PeerId, Multiaddr)>,
|
||||
enable_mdns: bool,
|
||||
@@ -115,7 +114,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
|
||||
DiscoveryBehaviour {
|
||||
user_defined,
|
||||
kademlia,
|
||||
next_kad_random_query: Delay::new(Duration::new(0, 0)).compat(),
|
||||
next_kad_random_query: Delay::new(Duration::new(0, 0)),
|
||||
duration_to_next_kad: Duration::from_secs(1),
|
||||
discoveries: VecDeque::new(),
|
||||
local_peer_id: local_public_key.into_peer_id(),
|
||||
@@ -123,7 +122,7 @@ impl<TSubstream> DiscoveryBehaviour<TSubstream> {
|
||||
allow_private_ipv4,
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
mdns: if enable_mdns {
|
||||
match Mdns::new() {
|
||||
match Mdns::new().await {
|
||||
Ok(mdns) => Some(mdns).into(),
|
||||
Err(err) => {
|
||||
warn!(target: "sub-libp2p", "Failed to initialize mDNS: {:?}", err);
|
||||
@@ -206,7 +205,7 @@ pub enum DiscoveryOut {
|
||||
|
||||
impl<TSubstream> NetworkBehaviour for DiscoveryBehaviour<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
type ProtocolsHandler = <Kademlia<TSubstream, MemoryStore> as NetworkBehaviour>::ProtocolsHandler;
|
||||
type OutEvent = DiscoveryOut;
|
||||
@@ -287,8 +286,9 @@ where
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
params: &mut impl PollParameters,
|
||||
) -> Async<
|
||||
) -> Poll<
|
||||
NetworkBehaviourAction<
|
||||
<Self::ProtocolsHandler as ProtocolsHandler>::InEvent,
|
||||
Self::OutEvent,
|
||||
@@ -297,45 +297,35 @@ where
|
||||
// Immediately process the content of `discovered`.
|
||||
if let Some(peer_id) = self.discoveries.pop_front() {
|
||||
let ev = DiscoveryOut::Discovered(peer_id);
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
|
||||
// Poll the stream that fires when we need to start a random Kademlia query.
|
||||
loop {
|
||||
match self.next_kad_random_query.poll() {
|
||||
Ok(Async::NotReady) => break,
|
||||
Ok(Async::Ready(_)) => {
|
||||
let random_peer_id = PeerId::random();
|
||||
debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \
|
||||
{:?}", random_peer_id);
|
||||
while let Poll::Ready(_) = self.next_kad_random_query.poll_unpin(cx) {
|
||||
let random_peer_id = PeerId::random();
|
||||
debug!(target: "sub-libp2p", "Libp2p <= Starting random Kademlia request for \
|
||||
{:?}", random_peer_id);
|
||||
|
||||
self.kademlia.get_closest_peers(random_peer_id);
|
||||
self.kademlia.get_closest_peers(random_peer_id);
|
||||
|
||||
// Schedule the next random query with exponentially increasing delay,
|
||||
// capped at 60 seconds.
|
||||
self.next_kad_random_query = Delay::new(self.duration_to_next_kad).compat();
|
||||
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
|
||||
Duration::from_secs(60));
|
||||
},
|
||||
Err(err) => {
|
||||
warn!(target: "sub-libp2p", "Kademlia query timer errored: {:?}", err);
|
||||
break
|
||||
}
|
||||
}
|
||||
// Schedule the next random query with exponentially increasing delay,
|
||||
// capped at 60 seconds.
|
||||
self.next_kad_random_query = Delay::new(self.duration_to_next_kad);
|
||||
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
|
||||
Duration::from_secs(60));
|
||||
}
|
||||
|
||||
// Poll Kademlia.
|
||||
loop {
|
||||
match self.kademlia.poll(params) {
|
||||
Async::NotReady => break,
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => match ev {
|
||||
while let Poll::Ready(ev) = self.kademlia.poll(cx, params) {
|
||||
match ev {
|
||||
NetworkBehaviourAction::GenerateEvent(ev) => match ev {
|
||||
KademliaEvent::UnroutablePeer { peer, .. } => {
|
||||
let ev = DiscoveryOut::UnroutablePeer(peer);
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
KademliaEvent::RoutingUpdated { peer, .. } => {
|
||||
let ev = DiscoveryOut::Discovered(peer);
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
KademliaEvent::GetClosestPeersResult(res) => {
|
||||
match res {
|
||||
@@ -369,7 +359,7 @@ where
|
||||
DiscoveryOut::ValueNotFound(e.into_key())
|
||||
}
|
||||
};
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
KademliaEvent::PutRecordResult(res) => {
|
||||
let ev = match res {
|
||||
@@ -378,7 +368,7 @@ where
|
||||
DiscoveryOut::ValuePutFailed(e.into_key())
|
||||
}
|
||||
};
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
KademliaEvent::RepublishRecordResult(res) => {
|
||||
match res {
|
||||
@@ -398,46 +388,45 @@ where
|
||||
warn!(target: "sub-libp2p", "Libp2p => Unhandled Kademlia event: {:?}", e)
|
||||
}
|
||||
},
|
||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
|
||||
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
NetworkBehaviourAction::DialAddress { address } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
NetworkBehaviourAction::DialPeer { peer_id } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
NetworkBehaviourAction::SendEvent { peer_id, event } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
|
||||
NetworkBehaviourAction::ReportObservedAddr { address } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
}
|
||||
}
|
||||
|
||||
// Poll mDNS.
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
loop {
|
||||
match self.mdns.poll(params) {
|
||||
Async::NotReady => break,
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(event)) => {
|
||||
while let Poll::Ready(ev) = self.mdns.poll(cx, params) {
|
||||
match ev {
|
||||
NetworkBehaviourAction::GenerateEvent(event) => {
|
||||
match event {
|
||||
MdnsEvent::Discovered(list) => {
|
||||
self.discoveries.extend(list.into_iter().map(|(peer_id, _)| peer_id));
|
||||
if let Some(peer_id) = self.discoveries.pop_front() {
|
||||
let ev = DiscoveryOut::Discovered(peer_id);
|
||||
return Async::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
|
||||
}
|
||||
},
|
||||
MdnsEvent::Expired(_) => {}
|
||||
}
|
||||
},
|
||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Async::Ready(NetworkBehaviourAction::SendEvent { event, .. }) =>
|
||||
NetworkBehaviourAction::DialAddress { address } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
NetworkBehaviourAction::DialPeer { peer_id } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
NetworkBehaviourAction::SendEvent { event, .. } =>
|
||||
match event {}, // `event` is an enum with no variant
|
||||
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
NetworkBehaviourAction::ReportObservedAddr { address } =>
|
||||
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
}
|
||||
}
|
||||
|
||||
Async::NotReady
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,7 +439,7 @@ mod tests {
|
||||
use libp2p::core::transport::{Transport, MemoryTransport};
|
||||
use libp2p::core::upgrade::{InboundUpgradeExt, OutboundUpgradeExt};
|
||||
use libp2p::swarm::Swarm;
|
||||
use std::collections::HashSet;
|
||||
use std::{collections::HashSet, task::Poll};
|
||||
use super::{DiscoveryBehaviour, DiscoveryOut};
|
||||
|
||||
#[test]
|
||||
@@ -469,7 +458,7 @@ mod tests {
|
||||
out,
|
||||
secio,
|
||||
endpoint,
|
||||
libp2p::core::upgrade::Version::V1
|
||||
upgrade::Version::V1
|
||||
)
|
||||
})
|
||||
.and_then(move |(peer_id, stream), endpoint| {
|
||||
@@ -477,10 +466,16 @@ mod tests {
|
||||
let upgrade = libp2p::yamux::Config::default()
|
||||
.map_inbound(move |muxer| (peer_id, muxer))
|
||||
.map_outbound(move |muxer| (peer_id2, muxer));
|
||||
upgrade::apply(stream, upgrade, endpoint, libp2p::core::upgrade::Version::V1)
|
||||
upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1)
|
||||
});
|
||||
|
||||
let behaviour = DiscoveryBehaviour::new(keypair.public(), user_defined.clone(), false, true);
|
||||
let behaviour = futures::executor::block_on({
|
||||
let user_defined = user_defined.clone();
|
||||
let keypair_public = keypair.public();
|
||||
async move {
|
||||
DiscoveryBehaviour::new(keypair_public, user_defined, false, true).await
|
||||
}
|
||||
});
|
||||
let mut swarm = Swarm::new(transport, behaviour, keypair.public().into_peer_id());
|
||||
let listen_addr: Multiaddr = format!("/memory/{}", rand::random::<u64>()).parse().unwrap();
|
||||
|
||||
@@ -499,11 +494,11 @@ mod tests {
|
||||
.collect::<HashSet<_>>()
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let fut = futures::future::poll_fn::<_, (), _>(move || {
|
||||
let fut = futures::future::poll_fn(move |cx| {
|
||||
'polling: loop {
|
||||
for swarm_n in 0..swarms.len() {
|
||||
match swarms[swarm_n].0.poll().unwrap() {
|
||||
Async::Ready(Some(e)) => {
|
||||
match swarms[swarm_n].0.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(e)) => {
|
||||
match e {
|
||||
DiscoveryOut::UnroutablePeer(other) => {
|
||||
// Call `add_self_reported_address` to simulate identify happening.
|
||||
@@ -530,12 +525,12 @@ mod tests {
|
||||
}
|
||||
|
||||
if to_discover.iter().all(|l| l.is_empty()) {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
});
|
||||
|
||||
tokio::runtime::Runtime::new().unwrap().block_on(fut).unwrap();
|
||||
futures::executor::block_on(fut);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
//! On-demand requests service.
|
||||
|
||||
use crate::protocol::light_dispatch::RequestData;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use futures::{prelude::*, sync::mpsc, sync::oneshot};
|
||||
use futures03::compat::{Compat01As03, Future01CompatExt as _};
|
||||
use std::{collections::HashMap, pin::Pin, sync::Arc, task::Context, task::Poll};
|
||||
use futures::{prelude::*, channel::mpsc, channel::oneshot};
|
||||
use parking_lot::Mutex;
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use sc_client_api::{Fetcher, FetchChecker, RemoteHeaderRequest,
|
||||
@@ -84,22 +82,22 @@ impl<B> Fetcher<B> for OnDemand<B> where
|
||||
B: BlockT,
|
||||
B::Header: HeaderT,
|
||||
{
|
||||
type RemoteHeaderResult = Compat01As03<RemoteResponse<B::Header>>;
|
||||
type RemoteReadResult = Compat01As03<RemoteResponse<HashMap<Vec<u8>, Option<Vec<u8>>>>>;
|
||||
type RemoteCallResult = Compat01As03<RemoteResponse<Vec<u8>>>;
|
||||
type RemoteChangesResult = Compat01As03<RemoteResponse<Vec<(NumberFor<B>, u32)>>>;
|
||||
type RemoteBodyResult = Compat01As03<RemoteResponse<Vec<B::Extrinsic>>>;
|
||||
type RemoteHeaderResult = RemoteResponse<B::Header>;
|
||||
type RemoteReadResult = RemoteResponse<HashMap<Vec<u8>, Option<Vec<u8>>>>;
|
||||
type RemoteCallResult = RemoteResponse<Vec<u8>>;
|
||||
type RemoteChangesResult = RemoteResponse<Vec<(NumberFor<B>, u32)>>;
|
||||
type RemoteBodyResult = RemoteResponse<Vec<B::Extrinsic>>;
|
||||
|
||||
fn remote_header(&self, request: RemoteHeaderRequest<B::Header>) -> Self::RemoteHeaderResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteHeader(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
|
||||
fn remote_read(&self, request: RemoteReadRequest<B::Header>) -> Self::RemoteReadResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteRead(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
|
||||
fn remote_read_child(
|
||||
@@ -108,25 +106,25 @@ impl<B> Fetcher<B> for OnDemand<B> where
|
||||
) -> Self::RemoteReadResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteReadChild(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
|
||||
fn remote_call(&self, request: RemoteCallRequest<B::Header>) -> Self::RemoteCallResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteCall(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
|
||||
fn remote_changes(&self, request: RemoteChangesRequest<B::Header>) -> Self::RemoteChangesResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteChanges(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
|
||||
fn remote_body(&self, request: RemoteBodyRequest<B::Header>) -> Self::RemoteBodyResult {
|
||||
let (sender, receiver) = oneshot::channel();
|
||||
let _ = self.requests_send.unbounded_send(RequestData::RemoteBody(request, sender));
|
||||
RemoteResponse { receiver }.compat()
|
||||
RemoteResponse { receiver }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,16 +134,13 @@ pub struct RemoteResponse<T> {
|
||||
}
|
||||
|
||||
impl<T> Future for RemoteResponse<T> {
|
||||
type Item = T;
|
||||
type Error = ClientError;
|
||||
type Output = Result<T, ClientError>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
self.receiver.poll()
|
||||
.map_err(|_| ClientError::RemoteFetchCancelled.into())
|
||||
.and_then(|r| match r {
|
||||
Async::Ready(Ok(ready)) => Ok(Async::Ready(ready)),
|
||||
Async::Ready(Err(error)) => Err(error),
|
||||
Async::NotReady => Ok(Async::NotReady),
|
||||
})
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
match self.receiver.poll_unpin(cx) {
|
||||
Poll::Ready(Ok(res)) => Poll::Ready(res),
|
||||
Poll::Ready(Err(_)) => Poll::Ready(Err(From::from(ClientError::RemoteFetchCancelled))),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ use legacy_proto::{LegacyProto, LegacyProtoOut};
|
||||
use crate::utils::interval;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use futures::prelude::*;
|
||||
use futures03::{StreamExt as _, TryStreamExt as _};
|
||||
use libp2p::{Multiaddr, PeerId};
|
||||
use libp2p::core::{ConnectedPoint, nodes::Substream, muxing::StreamMuxerBox};
|
||||
use libp2p::swarm::{ProtocolsHandler, IntoProtocolsHandler};
|
||||
@@ -47,7 +46,7 @@ use rustc_hex::ToHex;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use std::fmt::Write;
|
||||
use std::{cmp, num::NonZeroUsize, time};
|
||||
use std::{cmp, num::NonZeroUsize, pin::Pin, task::Poll, time};
|
||||
use log::{log, Level, trace, debug, warn, error};
|
||||
use crate::chain::{Client, FinalityProofProvider};
|
||||
use sc_client_api::{FetchChecker, ChangesProof, StorageProof};
|
||||
@@ -124,9 +123,9 @@ mod rep {
|
||||
// Lock must always be taken in order declared here.
|
||||
pub struct Protocol<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> {
|
||||
/// Interval at which we call `tick`.
|
||||
tick_timeout: Box<dyn Stream<Item = (), Error = ()> + Send>,
|
||||
tick_timeout: Pin<Box<dyn Stream<Item = ()> + Send>>,
|
||||
/// Interval at which we call `propagate_extrinsics`.
|
||||
propagate_timeout: Box<dyn Stream<Item = (), Error = ()> + Send>,
|
||||
propagate_timeout: Pin<Box<dyn Stream<Item = ()> + Send>>,
|
||||
config: ProtocolConfig,
|
||||
/// Handler for light client requests.
|
||||
light_dispatch: LightDispatch<B>,
|
||||
@@ -464,8 +463,8 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
|
||||
let behaviour = LegacyProto::new(protocol_id, versions, peerset);
|
||||
|
||||
let protocol = Protocol {
|
||||
tick_timeout: Box::new(interval(TICK_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()),
|
||||
propagate_timeout: Box::new(interval(PROPAGATE_TIMEOUT).map(|v| Ok::<_, ()>(v)).compat()),
|
||||
tick_timeout: Box::pin(interval(TICK_TIMEOUT)),
|
||||
propagate_timeout: Box::pin(interval(PROPAGATE_TIMEOUT)),
|
||||
config,
|
||||
context_data: ContextData {
|
||||
peers: HashMap::new(),
|
||||
@@ -1884,18 +1883,19 @@ Protocol<B, S, H> {
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut std::task::Context,
|
||||
params: &mut impl PollParameters,
|
||||
) -> Async<
|
||||
) -> Poll<
|
||||
NetworkBehaviourAction<
|
||||
<<Self::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
|
||||
Self::OutEvent
|
||||
>
|
||||
> {
|
||||
while let Ok(Async::Ready(_)) = self.tick_timeout.poll() {
|
||||
while let Poll::Ready(Some(())) = self.tick_timeout.poll_next_unpin(cx) {
|
||||
self.tick();
|
||||
}
|
||||
|
||||
while let Ok(Async::Ready(_)) = self.propagate_timeout.poll() {
|
||||
while let Poll::Ready(Some(())) = self.propagate_timeout.poll_next_unpin(cx) {
|
||||
self.propagate_extrinsics();
|
||||
}
|
||||
|
||||
@@ -1926,17 +1926,17 @@ Protocol<B, S, H> {
|
||||
GenericMessage::FinalityProofRequest(r))
|
||||
}
|
||||
|
||||
let event = match self.behaviour.poll(params) {
|
||||
Async::NotReady => return Async::NotReady,
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev,
|
||||
Async::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
|
||||
Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Async::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
let event = match self.behaviour.poll(cx, params) {
|
||||
Poll::Pending => return Poll::Pending,
|
||||
Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev)) => ev,
|
||||
Poll::Ready(NetworkBehaviourAction::DialAddress { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialAddress { address }),
|
||||
Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::DialPeer { peer_id }),
|
||||
Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::SendEvent { peer_id, event }),
|
||||
Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }) =>
|
||||
return Poll::Ready(NetworkBehaviourAction::ReportObservedAddr { address }),
|
||||
};
|
||||
|
||||
let outcome = match event {
|
||||
@@ -1970,9 +1970,9 @@ Protocol<B, S, H> {
|
||||
};
|
||||
|
||||
if let CustomMessageOutcome::None = outcome {
|
||||
Async::NotReady
|
||||
Poll::Pending
|
||||
} else {
|
||||
Async::Ready(NetworkBehaviourAction::GenerateEvent(outcome))
|
||||
Poll::Ready(NetworkBehaviourAction::GenerateEvent(outcome))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ use crate::protocol::legacy_proto::upgrade::RegisteredProtocol;
|
||||
use bytes::BytesMut;
|
||||
use fnv::FnvHashMap;
|
||||
use futures::prelude::*;
|
||||
use futures03::{compat::Compat, TryFutureExt as _, StreamExt as _, TryStreamExt as _};
|
||||
use libp2p::core::{ConnectedPoint, Multiaddr, PeerId};
|
||||
use libp2p::swarm::{NetworkBehaviour, NetworkBehaviourAction, PollParameters};
|
||||
use log::{debug, error, trace, warn};
|
||||
@@ -28,7 +27,7 @@ use rand::distributions::{Distribution as _, Uniform};
|
||||
use smallvec::SmallVec;
|
||||
use std::{borrow::Cow, collections::hash_map::Entry, cmp, error, marker::PhantomData, mem, pin::Pin};
|
||||
use std::time::{Duration, Instant};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
/// Network behaviour that handles opening substreams for custom protocols with other nodes.
|
||||
///
|
||||
@@ -103,7 +102,7 @@ enum PeerState {
|
||||
/// The peerset requested that we connect to this peer. We are not connected to this node.
|
||||
PendingRequest {
|
||||
/// When to actually start dialing.
|
||||
timer: Compat<futures_timer::Delay>,
|
||||
timer: futures_timer::Delay,
|
||||
/// When the `timer` will trigger.
|
||||
timer_deadline: Instant,
|
||||
},
|
||||
@@ -135,7 +134,7 @@ enum PeerState {
|
||||
/// state mismatch.
|
||||
open: bool,
|
||||
/// When to enable this remote.
|
||||
timer: Compat<futures_timer::Delay>,
|
||||
timer: futures_timer::Delay,
|
||||
/// When the `timer` will trigger.
|
||||
timer_deadline: Instant,
|
||||
},
|
||||
@@ -388,7 +387,7 @@ impl<TSubstream> LegacyProto<TSubstream> {
|
||||
debug!(target: "sub-libp2p", "PSM => Connect({:?}): Will start to connect at \
|
||||
until {:?}", occ_entry.key(), until);
|
||||
*occ_entry.into_mut() = PeerState::PendingRequest {
|
||||
timer: futures_timer::Delay::new_at(until.clone()).compat(),
|
||||
timer: futures_timer::Delay::new_at(until.clone()),
|
||||
timer_deadline: until.clone(),
|
||||
};
|
||||
},
|
||||
@@ -407,7 +406,7 @@ impl<TSubstream> LegacyProto<TSubstream> {
|
||||
*occ_entry.into_mut() = PeerState::DisabledPendingEnable {
|
||||
connected_point: connected_point.clone(),
|
||||
open,
|
||||
timer: futures_timer::Delay::new_at(banned.clone()).compat(),
|
||||
timer: futures_timer::Delay::new_at(banned.clone()),
|
||||
timer_deadline: banned.clone(),
|
||||
};
|
||||
},
|
||||
@@ -616,7 +615,7 @@ impl<TSubstream> DiscoveryNetBehaviour for LegacyProto<TSubstream> {
|
||||
|
||||
impl<TSubstream> NetworkBehaviour for LegacyProto<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
type ProtocolsHandler = CustomProtoHandlerProto<TSubstream>;
|
||||
type OutEvent = LegacyProtoOut;
|
||||
@@ -951,8 +950,9 @@ where
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
_params: &mut impl PollParameters,
|
||||
) -> Async<
|
||||
) -> Poll<
|
||||
NetworkBehaviourAction<
|
||||
CustomProtoHandlerIn,
|
||||
Self::OutEvent,
|
||||
@@ -961,38 +961,31 @@ where
|
||||
// Poll for instructions from the peerset.
|
||||
// Note that the peerset is a *best effort* crate, and we have to use defensive programming.
|
||||
loop {
|
||||
let mut peerset01 = futures03::stream::poll_fn(|cx|
|
||||
futures03::Stream::poll_next(Pin::new(&mut self.peerset), cx)
|
||||
).map(|v| Ok::<_, ()>(v)).compat();
|
||||
match peerset01.poll() {
|
||||
Ok(Async::Ready(Some(sc_peerset::Message::Accept(index)))) => {
|
||||
match futures::Stream::poll_next(Pin::new(&mut self.peerset), cx) {
|
||||
Poll::Ready(Some(sc_peerset::Message::Accept(index))) => {
|
||||
self.peerset_report_accept(index);
|
||||
}
|
||||
Ok(Async::Ready(Some(sc_peerset::Message::Reject(index)))) => {
|
||||
Poll::Ready(Some(sc_peerset::Message::Reject(index))) => {
|
||||
self.peerset_report_reject(index);
|
||||
}
|
||||
Ok(Async::Ready(Some(sc_peerset::Message::Connect(id)))) => {
|
||||
Poll::Ready(Some(sc_peerset::Message::Connect(id))) => {
|
||||
self.peerset_report_connect(id);
|
||||
}
|
||||
Ok(Async::Ready(Some(sc_peerset::Message::Drop(id)))) => {
|
||||
Poll::Ready(Some(sc_peerset::Message::Drop(id))) => {
|
||||
self.peerset_report_disconnect(id);
|
||||
}
|
||||
Ok(Async::Ready(None)) => {
|
||||
Poll::Ready(None) => {
|
||||
error!(target: "sub-libp2p", "Peerset receiver stream has returned None");
|
||||
break;
|
||||
}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(err) => {
|
||||
error!(target: "sub-libp2p", "Peerset receiver stream has errored: {:?}", err);
|
||||
break
|
||||
}
|
||||
Poll::Pending => break,
|
||||
}
|
||||
}
|
||||
|
||||
for (peer_id, peer_state) in self.peers.iter_mut() {
|
||||
match mem::replace(peer_state, PeerState::Poisoned) {
|
||||
PeerState::PendingRequest { mut timer, timer_deadline } => {
|
||||
if let Ok(Async::NotReady) = timer.poll() {
|
||||
if let Poll::Pending = Pin::new(&mut timer).poll(cx) {
|
||||
*peer_state = PeerState::PendingRequest { timer, timer_deadline };
|
||||
continue;
|
||||
}
|
||||
@@ -1003,7 +996,7 @@ where
|
||||
}
|
||||
|
||||
PeerState::DisabledPendingEnable { mut timer, connected_point, open, timer_deadline } => {
|
||||
if let Ok(Async::NotReady) = timer.poll() {
|
||||
if let Poll::Pending = Pin::new(&mut timer).poll(cx) {
|
||||
*peer_state = PeerState::DisabledPendingEnable {
|
||||
timer,
|
||||
connected_point,
|
||||
@@ -1026,9 +1019,9 @@ where
|
||||
}
|
||||
|
||||
if !self.events.is_empty() {
|
||||
return Async::Ready(self.events.remove(0))
|
||||
return Poll::Ready(self.events.remove(0))
|
||||
}
|
||||
|
||||
Async::NotReady
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
use super::upgrade::{RegisteredProtocol, RegisteredProtocolEvent, RegisteredProtocolSubstream};
|
||||
use bytes::BytesMut;
|
||||
use futures::prelude::*;
|
||||
use futures03::{compat::Compat, TryFutureExt as _};
|
||||
use futures_timer::Delay;
|
||||
use libp2p::core::{ConnectedPoint, PeerId, Endpoint};
|
||||
use libp2p::core::upgrade::{InboundUpgrade, OutboundUpgrade};
|
||||
@@ -31,7 +30,7 @@ use libp2p::swarm::{
|
||||
use log::{debug, error};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::{borrow::Cow, error, fmt, io, marker::PhantomData, mem, time::Duration};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use std::{pin::Pin, task::{Context, Poll}};
|
||||
|
||||
/// Implements the `IntoProtocolsHandler` trait of libp2p.
|
||||
///
|
||||
@@ -97,7 +96,7 @@ pub struct CustomProtoHandlerProto<TSubstream> {
|
||||
|
||||
impl<TSubstream> CustomProtoHandlerProto<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
/// Builds a new `CustomProtoHandlerProto`.
|
||||
pub fn new(protocol: RegisteredProtocol) -> Self {
|
||||
@@ -110,7 +109,7 @@ where
|
||||
|
||||
impl<TSubstream> IntoProtocolsHandler for CustomProtoHandlerProto<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
type Handler = CustomProtoHandler<TSubstream>;
|
||||
|
||||
@@ -125,7 +124,7 @@ where
|
||||
remote_peer_id: remote_peer_id.clone(),
|
||||
state: ProtocolState::Init {
|
||||
substreams: SmallVec::new(),
|
||||
init_deadline: Delay::new(Duration::from_secs(5)).compat()
|
||||
init_deadline: Delay::new(Duration::from_secs(5))
|
||||
},
|
||||
events_queue: SmallVec::new(),
|
||||
}
|
||||
@@ -152,7 +151,7 @@ pub struct CustomProtoHandler<TSubstream> {
|
||||
///
|
||||
/// This queue must only ever be modified to insert elements at the back, or remove the first
|
||||
/// element.
|
||||
events_queue: SmallVec<[ProtocolsHandlerEvent<RegisteredProtocol, (), CustomProtoHandlerOut>; 16]>,
|
||||
events_queue: SmallVec<[ProtocolsHandlerEvent<RegisteredProtocol, (), CustomProtoHandlerOut, ConnectionKillError>; 16]>,
|
||||
}
|
||||
|
||||
/// State of the handler.
|
||||
@@ -162,14 +161,14 @@ enum ProtocolState<TSubstream> {
|
||||
/// List of substreams opened by the remote but that haven't been processed yet.
|
||||
substreams: SmallVec<[RegisteredProtocolSubstream<TSubstream>; 6]>,
|
||||
/// Deadline after which the initialization is abnormally long.
|
||||
init_deadline: Compat<Delay>,
|
||||
init_deadline: Delay,
|
||||
},
|
||||
|
||||
/// Handler is opening a substream in order to activate itself.
|
||||
/// If we are in this state, we haven't sent any `CustomProtocolOpen` yet.
|
||||
Opening {
|
||||
/// Deadline after which the opening is abnormally long.
|
||||
deadline: Compat<Delay>,
|
||||
deadline: Delay,
|
||||
},
|
||||
|
||||
/// Normal operating mode. Contains the substreams that are open.
|
||||
@@ -260,7 +259,7 @@ pub enum CustomProtoHandlerOut {
|
||||
|
||||
impl<TSubstream> CustomProtoHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
/// Enables the handler.
|
||||
fn enable(&mut self) {
|
||||
@@ -280,7 +279,7 @@ where
|
||||
});
|
||||
}
|
||||
ProtocolState::Opening {
|
||||
deadline: Delay::new(Duration::from_secs(60)).compat()
|
||||
deadline: Delay::new(Duration::from_secs(60))
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -337,8 +336,8 @@ where
|
||||
|
||||
/// Polls the state for events. Optionally returns an event to produce.
|
||||
#[must_use]
|
||||
fn poll_state(&mut self)
|
||||
-> Option<ProtocolsHandlerEvent<RegisteredProtocol, (), CustomProtoHandlerOut>> {
|
||||
fn poll_state(&mut self, cx: &mut Context)
|
||||
-> Option<ProtocolsHandlerEvent<RegisteredProtocol, (), CustomProtoHandlerOut, ConnectionKillError>> {
|
||||
match mem::replace(&mut self.state, ProtocolState::Poisoned) {
|
||||
ProtocolState::Poisoned => {
|
||||
error!(target: "sub-libp2p", "Handler with {:?} is in poisoned state",
|
||||
@@ -348,14 +347,14 @@ where
|
||||
}
|
||||
|
||||
ProtocolState::Init { substreams, mut init_deadline } => {
|
||||
match init_deadline.poll() {
|
||||
Ok(Async::Ready(())) => {
|
||||
init_deadline = Delay::new(Duration::from_secs(60)).compat();
|
||||
match Pin::new(&mut init_deadline).poll(cx) {
|
||||
Poll::Ready(Ok(())) => {
|
||||
init_deadline = Delay::new(Duration::from_secs(60));
|
||||
error!(target: "sub-libp2p", "Handler initialization process is too long \
|
||||
with {:?}", self.remote_peer_id)
|
||||
},
|
||||
Ok(Async::NotReady) => {}
|
||||
Err(_) => error!(target: "sub-libp2p", "Tokio timer has errored")
|
||||
Poll::Pending => {}
|
||||
Poll::Ready(Err(_)) => error!(target: "sub-libp2p", "Tokio timer has errored")
|
||||
}
|
||||
|
||||
self.state = ProtocolState::Init { substreams, init_deadline };
|
||||
@@ -363,9 +362,9 @@ where
|
||||
}
|
||||
|
||||
ProtocolState::Opening { mut deadline } => {
|
||||
match deadline.poll() {
|
||||
Ok(Async::Ready(())) => {
|
||||
deadline = Delay::new(Duration::from_secs(60)).compat();
|
||||
match Pin::new(&mut deadline).poll(cx) {
|
||||
Poll::Ready(Ok(())) => {
|
||||
deadline = Delay::new(Duration::from_secs(60));
|
||||
let event = CustomProtoHandlerOut::ProtocolError {
|
||||
is_severe: true,
|
||||
error: "Timeout when opening protocol".to_string().into(),
|
||||
@@ -373,13 +372,13 @@ where
|
||||
self.state = ProtocolState::Opening { deadline };
|
||||
Some(ProtocolsHandlerEvent::Custom(event))
|
||||
},
|
||||
Ok(Async::NotReady) => {
|
||||
Poll::Pending => {
|
||||
self.state = ProtocolState::Opening { deadline };
|
||||
None
|
||||
},
|
||||
Err(_) => {
|
||||
Poll::Ready(Err(_)) => {
|
||||
error!(target: "sub-libp2p", "Tokio timer has errored");
|
||||
deadline = Delay::new(Duration::from_secs(60)).compat();
|
||||
deadline = Delay::new(Duration::from_secs(60));
|
||||
self.state = ProtocolState::Opening { deadline };
|
||||
None
|
||||
},
|
||||
@@ -389,9 +388,9 @@ where
|
||||
ProtocolState::Normal { mut substreams, mut shutdown } => {
|
||||
for n in (0..substreams.len()).rev() {
|
||||
let mut substream = substreams.swap_remove(n);
|
||||
match substream.poll() {
|
||||
Ok(Async::NotReady) => substreams.push(substream),
|
||||
Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(message)))) => {
|
||||
match Pin::new(&mut substream).poll_next(cx) {
|
||||
Poll::Pending => substreams.push(substream),
|
||||
Poll::Ready(Some(Ok(RegisteredProtocolEvent::Message(message)))) => {
|
||||
let event = CustomProtoHandlerOut::CustomMessage {
|
||||
message
|
||||
};
|
||||
@@ -399,7 +398,7 @@ where
|
||||
self.state = ProtocolState::Normal { substreams, shutdown };
|
||||
return Some(ProtocolsHandlerEvent::Custom(event));
|
||||
},
|
||||
Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged { messages }))) => {
|
||||
Poll::Ready(Some(Ok(RegisteredProtocolEvent::Clogged { messages }))) => {
|
||||
let event = CustomProtoHandlerOut::Clogged {
|
||||
messages,
|
||||
};
|
||||
@@ -407,7 +406,7 @@ where
|
||||
self.state = ProtocolState::Normal { substreams, shutdown };
|
||||
return Some(ProtocolsHandlerEvent::Custom(event));
|
||||
}
|
||||
Ok(Async::Ready(None)) => {
|
||||
Poll::Ready(None) => {
|
||||
shutdown.push(substream);
|
||||
if substreams.is_empty() {
|
||||
let event = CustomProtoHandlerOut::CustomProtocolClosed {
|
||||
@@ -420,7 +419,7 @@ where
|
||||
return Some(ProtocolsHandlerEvent::Custom(event));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
Poll::Ready(Some(Err(err))) => {
|
||||
if substreams.is_empty() {
|
||||
let event = CustomProtoHandlerOut::CustomProtocolClosed {
|
||||
reason: format!("Error on the last substream: {:?}", err).into(),
|
||||
@@ -443,12 +442,12 @@ where
|
||||
}
|
||||
|
||||
ProtocolState::Disabled { mut shutdown, reenable } => {
|
||||
shutdown_list(&mut shutdown);
|
||||
shutdown_list(&mut shutdown, cx);
|
||||
// If `reenable` is `true`, that means we should open the substreams system again
|
||||
// after all the substreams are closed.
|
||||
if reenable && shutdown.is_empty() {
|
||||
self.state = ProtocolState::Opening {
|
||||
deadline: Delay::new(Duration::from_secs(60)).compat()
|
||||
deadline: Delay::new(Duration::from_secs(60))
|
||||
};
|
||||
Some(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol: SubstreamProtocol::new(self.protocol.clone()),
|
||||
@@ -524,7 +523,7 @@ where
|
||||
}
|
||||
|
||||
impl<TSubstream> ProtocolsHandler for CustomProtoHandler<TSubstream>
|
||||
where TSubstream: AsyncRead + AsyncWrite {
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin {
|
||||
type InEvent = CustomProtoHandlerIn;
|
||||
type OutEvent = CustomProtoHandlerOut;
|
||||
type Substream = TSubstream;
|
||||
@@ -585,33 +584,33 @@ where TSubstream: AsyncRead + AsyncWrite {
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
) -> Poll<
|
||||
ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent>,
|
||||
Self::Error,
|
||||
ProtocolsHandlerEvent<Self::OutboundProtocol, Self::OutboundOpenInfo, Self::OutEvent, Self::Error>
|
||||
> {
|
||||
// Flush the events queue if necessary.
|
||||
if !self.events_queue.is_empty() {
|
||||
let event = self.events_queue.remove(0);
|
||||
return Ok(Async::Ready(event))
|
||||
return Poll::Ready(event)
|
||||
}
|
||||
|
||||
// Kill the connection if needed.
|
||||
if let ProtocolState::KillAsap = self.state {
|
||||
return Err(ConnectionKillError);
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Close(ConnectionKillError));
|
||||
}
|
||||
|
||||
// Process all the substreams.
|
||||
if let Some(event) = self.poll_state() {
|
||||
return Ok(Async::Ready(event))
|
||||
if let Some(event) = self.poll_state(cx) {
|
||||
return Poll::Ready(event)
|
||||
}
|
||||
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<TSubstream> fmt::Debug for CustomProtoHandler<TSubstream>
|
||||
where
|
||||
TSubstream: AsyncRead + AsyncWrite,
|
||||
TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
f.debug_struct("CustomProtoHandler")
|
||||
@@ -622,15 +621,16 @@ where
|
||||
/// Given a list of substreams, tries to shut them down. The substreams that have been successfully
|
||||
/// shut down are removed from the list.
|
||||
fn shutdown_list<TSubstream>
|
||||
(list: &mut SmallVec<impl smallvec::Array<Item = RegisteredProtocolSubstream<TSubstream>>>)
|
||||
where TSubstream: AsyncRead + AsyncWrite {
|
||||
(list: &mut SmallVec<impl smallvec::Array<Item = RegisteredProtocolSubstream<TSubstream>>>,
|
||||
cx: &mut Context)
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin {
|
||||
'outer: for n in (0..list.len()).rev() {
|
||||
let mut substream = list.swap_remove(n);
|
||||
loop {
|
||||
match substream.poll() {
|
||||
Ok(Async::Ready(Some(_))) => {}
|
||||
Ok(Async::NotReady) => break,
|
||||
Err(_) | Ok(Async::Ready(None)) => continue 'outer,
|
||||
match substream.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(Ok(_))) => {}
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(Some(Err(_))) | Poll::Ready(None) => continue 'outer,
|
||||
}
|
||||
}
|
||||
list.push(substream);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#![cfg(test)]
|
||||
|
||||
use futures::{future, prelude::*, try_ready};
|
||||
use futures::{prelude::*, ready};
|
||||
use codec::{Encode, Decode};
|
||||
use libp2p::core::nodes::Substream;
|
||||
use libp2p::core::{ConnectedPoint, transport::boxed::Boxed, muxing::StreamMuxerBox};
|
||||
@@ -24,7 +24,7 @@ use libp2p::swarm::{Swarm, ProtocolsHandler, IntoProtocolsHandler};
|
||||
use libp2p::swarm::{PollParameters, NetworkBehaviour, NetworkBehaviourAction};
|
||||
use libp2p::{PeerId, Multiaddr, Transport};
|
||||
use rand::seq::SliceRandom;
|
||||
use std::{io, time::Duration, time::Instant};
|
||||
use std::{io, task::Context, task::Poll, time::Duration};
|
||||
use crate::message::Message;
|
||||
use crate::protocol::legacy_proto::{LegacyProto, LegacyProtoOut};
|
||||
use sp_test_primitives::Block;
|
||||
@@ -62,7 +62,7 @@ fn build_nodes()
|
||||
endpoint,
|
||||
libp2p::core::upgrade::Version::V1
|
||||
)
|
||||
.map(|muxer| (peer_id, libp2p::core::muxing::StreamMuxerBox::new(muxer)))
|
||||
.map_ok(|muxer| (peer_id, libp2p::core::muxing::StreamMuxerBox::new(muxer)))
|
||||
})
|
||||
.timeout(Duration::from_secs(20))
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||
@@ -170,14 +170,15 @@ impl NetworkBehaviour for CustomProtoWithAddr {
|
||||
|
||||
fn poll(
|
||||
&mut self,
|
||||
cx: &mut Context,
|
||||
params: &mut impl PollParameters
|
||||
) -> Async<
|
||||
) -> Poll<
|
||||
NetworkBehaviourAction<
|
||||
<<Self::ProtocolsHandler as IntoProtocolsHandler>::Handler as ProtocolsHandler>::InEvent,
|
||||
Self::OutEvent
|
||||
>
|
||||
> {
|
||||
self.inner.poll(params)
|
||||
self.inner.poll(cx, params)
|
||||
}
|
||||
|
||||
fn inject_replaced(&mut self, peer_id: PeerId, closed_endpoint: ConnectedPoint, new_endpoint: ConnectedPoint) {
|
||||
@@ -216,9 +217,9 @@ fn two_nodes_transfer_lots_of_packets() {
|
||||
|
||||
let (mut service1, mut service2) = build_nodes();
|
||||
|
||||
let fut1 = future::poll_fn(move || -> io::Result<_> {
|
||||
let fut1 = future::poll_fn(move |cx| -> Poll<()> {
|
||||
loop {
|
||||
match try_ready!(service1.poll()) {
|
||||
match ready!(service1.poll_next_unpin(cx)) {
|
||||
Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => {
|
||||
for n in 0 .. NUM_PACKETS {
|
||||
service1.send_packet(
|
||||
@@ -233,9 +234,9 @@ fn two_nodes_transfer_lots_of_packets() {
|
||||
});
|
||||
|
||||
let mut packet_counter = 0u32;
|
||||
let fut2 = future::poll_fn(move || -> io::Result<_> {
|
||||
let fut2 = future::poll_fn(move |cx| {
|
||||
loop {
|
||||
match try_ready!(service2.poll()) {
|
||||
match ready!(service2.poll_next_unpin(cx)) {
|
||||
Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {},
|
||||
Some(LegacyProtoOut::CustomMessage { message, .. }) => {
|
||||
match Message::<Block>::decode(&mut &message[..]).unwrap() {
|
||||
@@ -243,7 +244,7 @@ fn two_nodes_transfer_lots_of_packets() {
|
||||
assert_eq!(message.len(), 1);
|
||||
packet_counter += 1;
|
||||
if packet_counter == NUM_PACKETS {
|
||||
return Ok(Async::Ready(()))
|
||||
return Poll::Ready(())
|
||||
}
|
||||
},
|
||||
_ => panic!(),
|
||||
@@ -254,8 +255,9 @@ fn two_nodes_transfer_lots_of_packets() {
|
||||
}
|
||||
});
|
||||
|
||||
let combined = fut1.select(fut2).map_err(|(err, _)| err);
|
||||
let _ = tokio::runtime::Runtime::new().unwrap().block_on(combined).unwrap();
|
||||
futures::executor::block_on(async move {
|
||||
future::select(fut1, fut2).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -277,9 +279,9 @@ fn basic_two_nodes_requests_in_parallel() {
|
||||
let mut to_receive = to_send.clone();
|
||||
to_send.shuffle(&mut rand::thread_rng());
|
||||
|
||||
let fut1 = future::poll_fn(move || -> io::Result<_> {
|
||||
let fut1 = future::poll_fn(move |cx| -> Poll<()> {
|
||||
loop {
|
||||
match try_ready!(service1.poll()) {
|
||||
match ready!(service1.poll_next_unpin(cx)) {
|
||||
Some(LegacyProtoOut::CustomProtocolOpen { peer_id, .. }) => {
|
||||
for msg in to_send.drain(..) {
|
||||
service1.send_packet(&peer_id, msg.encode());
|
||||
@@ -290,15 +292,15 @@ fn basic_two_nodes_requests_in_parallel() {
|
||||
}
|
||||
});
|
||||
|
||||
let fut2 = future::poll_fn(move || -> io::Result<_> {
|
||||
let fut2 = future::poll_fn(move |cx| {
|
||||
loop {
|
||||
match try_ready!(service2.poll()) {
|
||||
match ready!(service2.poll_next_unpin(cx)) {
|
||||
Some(LegacyProtoOut::CustomProtocolOpen { .. }) => {},
|
||||
Some(LegacyProtoOut::CustomMessage { message, .. }) => {
|
||||
let pos = to_receive.iter().position(|m| m.encode() == message).unwrap();
|
||||
to_receive.remove(pos);
|
||||
if to_receive.is_empty() {
|
||||
return Ok(Async::Ready(()))
|
||||
return Poll::Ready(())
|
||||
}
|
||||
}
|
||||
_ => panic!(),
|
||||
@@ -306,8 +308,9 @@ fn basic_two_nodes_requests_in_parallel() {
|
||||
}
|
||||
});
|
||||
|
||||
let combined = fut1.select(fut2).map_err(|(err, _)| err);
|
||||
let _ = tokio::runtime::Runtime::new().unwrap().block_on_all(combined).unwrap();
|
||||
futures::executor::block_on(async move {
|
||||
future::select(fut1, fut2).await;
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -317,9 +320,6 @@ fn reconnect_after_disconnect() {
|
||||
|
||||
let (mut service1, mut service2) = build_nodes();
|
||||
|
||||
// We use the `current_thread` runtime because it doesn't require us to have `'static` futures.
|
||||
let mut runtime = tokio::runtime::current_thread::Runtime::new().unwrap();
|
||||
|
||||
// For this test, the services can be in the following states.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
enum ServiceState { NotConnected, FirstConnec, Disconnected, ConnectedAgain }
|
||||
@@ -327,12 +327,12 @@ fn reconnect_after_disconnect() {
|
||||
let mut service2_state = ServiceState::NotConnected;
|
||||
|
||||
// Run the events loops.
|
||||
runtime.block_on(future::poll_fn(|| -> Result<_, io::Error> {
|
||||
futures::executor::block_on(future::poll_fn(|cx| -> Poll<Result<_, io::Error>> {
|
||||
loop {
|
||||
let mut service1_not_ready = false;
|
||||
|
||||
match service1.poll().unwrap() {
|
||||
Async::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => {
|
||||
match service1.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => {
|
||||
match service1_state {
|
||||
ServiceState::NotConnected => {
|
||||
service1_state = ServiceState::FirstConnec;
|
||||
@@ -344,19 +344,19 @@ fn reconnect_after_disconnect() {
|
||||
ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(),
|
||||
}
|
||||
},
|
||||
Async::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => {
|
||||
Poll::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => {
|
||||
match service1_state {
|
||||
ServiceState::FirstConnec => service1_state = ServiceState::Disconnected,
|
||||
ServiceState::ConnectedAgain| ServiceState::NotConnected |
|
||||
ServiceState::Disconnected => panic!(),
|
||||
}
|
||||
},
|
||||
Async::NotReady => service1_not_ready = true,
|
||||
Poll::Pending => service1_not_ready = true,
|
||||
_ => panic!()
|
||||
}
|
||||
|
||||
match service2.poll().unwrap() {
|
||||
Async::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => {
|
||||
match service2.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(LegacyProtoOut::CustomProtocolOpen { .. })) => {
|
||||
match service2_state {
|
||||
ServiceState::NotConnected => {
|
||||
service2_state = ServiceState::FirstConnec;
|
||||
@@ -368,43 +368,43 @@ fn reconnect_after_disconnect() {
|
||||
ServiceState::FirstConnec | ServiceState::ConnectedAgain => panic!(),
|
||||
}
|
||||
},
|
||||
Async::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => {
|
||||
Poll::Ready(Some(LegacyProtoOut::CustomProtocolClosed { .. })) => {
|
||||
match service2_state {
|
||||
ServiceState::FirstConnec => service2_state = ServiceState::Disconnected,
|
||||
ServiceState::ConnectedAgain| ServiceState::NotConnected |
|
||||
ServiceState::Disconnected => panic!(),
|
||||
}
|
||||
},
|
||||
Async::NotReady if service1_not_ready => break,
|
||||
Async::NotReady => {}
|
||||
Poll::Pending if service1_not_ready => break,
|
||||
Poll::Pending => {}
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
if service1_state == ServiceState::ConnectedAgain && service2_state == ServiceState::ConnectedAgain {
|
||||
Ok(Async::Ready(()))
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
})).unwrap();
|
||||
|
||||
// Do a second 3-seconds run to make sure we don't get disconnected immediately again.
|
||||
let mut delay = tokio::timer::Delay::new(Instant::now() + Duration::from_secs(3));
|
||||
runtime.block_on(future::poll_fn(|| -> Result<_, io::Error> {
|
||||
match service1.poll().unwrap() {
|
||||
Async::NotReady => {},
|
||||
let mut delay = futures_timer::Delay::new(Duration::from_secs(3));
|
||||
futures::executor::block_on(future::poll_fn(|cx| -> Poll<Result<_, io::Error>> {
|
||||
match service1.poll_next_unpin(cx) {
|
||||
Poll::Pending => {},
|
||||
_ => panic!()
|
||||
}
|
||||
|
||||
match service2.poll().unwrap() {
|
||||
Async::NotReady => {},
|
||||
match service2.poll_next_unpin(cx) {
|
||||
Poll::Pending => {},
|
||||
_ => panic!()
|
||||
}
|
||||
|
||||
if let Async::Ready(()) = delay.poll().unwrap() {
|
||||
Ok(Async::Ready(()))
|
||||
if let Poll::Ready(Ok(_)) = delay.poll_unpin(cx) {
|
||||
Poll::Ready(Ok(()))
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
})).unwrap();
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::config::ProtocolId;
|
||||
use bytes::{Bytes, BytesMut};
|
||||
use bytes::BytesMut;
|
||||
use futures::prelude::*;
|
||||
use futures_codec::Framed;
|
||||
use libp2p::core::{Negotiated, Endpoint, UpgradeInfo, InboundUpgrade, OutboundUpgrade, upgrade::ProtocolName};
|
||||
use libp2p::tokio_codec::Framed;
|
||||
use std::{collections::VecDeque, io, vec::IntoIter as VecIntoIter};
|
||||
use futures::{prelude::*, future, stream};
|
||||
use tokio_io::{AsyncRead, AsyncWrite};
|
||||
use std::{collections::VecDeque, io, pin::Pin, vec::IntoIter as VecIntoIter};
|
||||
use std::task::{Context, Poll};
|
||||
use unsigned_varint::codec::UviBytes;
|
||||
|
||||
/// Connection upgrade for a single protocol.
|
||||
@@ -32,7 +32,7 @@ pub struct RegisteredProtocol {
|
||||
id: ProtocolId,
|
||||
/// Base name of the protocol as advertised on the network.
|
||||
/// Ends with `/` so that we can append a version number behind.
|
||||
base_name: Bytes,
|
||||
base_name: Vec<u8>,
|
||||
/// List of protocol versions that we support.
|
||||
/// Ordered in descending order so that the best comes first.
|
||||
supported_versions: Vec<u8>,
|
||||
@@ -44,7 +44,7 @@ impl RegisteredProtocol {
|
||||
pub fn new(protocol: impl Into<ProtocolId>, versions: &[u8])
|
||||
-> Self {
|
||||
let protocol = protocol.into();
|
||||
let mut base_name = Bytes::from_static(b"/substrate/");
|
||||
let mut base_name = b"/substrate/".to_vec();
|
||||
base_name.extend_from_slice(protocol.as_bytes());
|
||||
base_name.extend_from_slice(b"/");
|
||||
|
||||
@@ -78,11 +78,11 @@ pub struct RegisteredProtocolSubstream<TSubstream> {
|
||||
/// the remote (listener).
|
||||
endpoint: Endpoint,
|
||||
/// Buffer of packets to send.
|
||||
send_queue: VecDeque<Vec<u8>>,
|
||||
send_queue: VecDeque<BytesMut>,
|
||||
/// If true, we should call `poll_complete` on the inner sink.
|
||||
requires_poll_complete: bool,
|
||||
requires_poll_flush: bool,
|
||||
/// The underlying substream.
|
||||
inner: stream::Fuse<Framed<Negotiated<TSubstream>, UviBytes<Vec<u8>>>>,
|
||||
inner: stream::Fuse<Framed<Negotiated<TSubstream>, UviBytes<BytesMut>>>,
|
||||
/// Version of the protocol that was negotiated.
|
||||
protocol_version: u8,
|
||||
/// If true, we have sent a "remote is clogged" event recently and shouldn't send another one
|
||||
@@ -119,7 +119,7 @@ impl<TSubstream> RegisteredProtocolSubstream<TSubstream> {
|
||||
return
|
||||
}
|
||||
|
||||
self.send_queue.push_back(data);
|
||||
self.send_queue.push_back(From::from(&data[..]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,25 +138,31 @@ pub enum RegisteredProtocolEvent {
|
||||
}
|
||||
|
||||
impl<TSubstream> Stream for RegisteredProtocolSubstream<TSubstream>
|
||||
where TSubstream: AsyncRead + AsyncWrite {
|
||||
type Item = RegisteredProtocolEvent;
|
||||
type Error = io::Error;
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin {
|
||||
type Item = Result<RegisteredProtocolEvent, io::Error>;
|
||||
|
||||
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
// Flushing the local queue.
|
||||
while let Some(packet) = self.send_queue.pop_front() {
|
||||
match self.inner.start_send(packet)? {
|
||||
AsyncSink::NotReady(packet) => {
|
||||
self.send_queue.push_front(packet);
|
||||
break
|
||||
},
|
||||
AsyncSink::Ready => self.requires_poll_complete = true,
|
||||
while !self.send_queue.is_empty() {
|
||||
match Pin::new(&mut self.inner).poll_ready(cx) {
|
||||
Poll::Ready(Ok(())) => {},
|
||||
Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err))),
|
||||
Poll::Pending => break,
|
||||
}
|
||||
|
||||
if let Some(packet) = self.send_queue.pop_front() {
|
||||
Pin::new(&mut self.inner).start_send(packet)?;
|
||||
self.requires_poll_flush = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are closing, close as soon as the Sink is closed.
|
||||
if self.is_closing {
|
||||
return Ok(self.inner.close()?.map(|()| None))
|
||||
return match Pin::new(&mut self.inner).poll_close(cx) {
|
||||
Poll::Pending => Poll::Pending,
|
||||
Poll::Ready(Ok(_)) => Poll::Ready(None),
|
||||
Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))),
|
||||
}
|
||||
}
|
||||
|
||||
// Indicating that the remote is clogged if that's the case.
|
||||
@@ -166,9 +172,9 @@ where TSubstream: AsyncRead + AsyncWrite {
|
||||
// if you remove the fuse, then we will always return early from this function and
|
||||
// thus never read any message from the network.
|
||||
self.clogged_fuse = true;
|
||||
return Ok(Async::Ready(Some(RegisteredProtocolEvent::Clogged {
|
||||
return Poll::Ready(Some(Ok(RegisteredProtocolEvent::Clogged {
|
||||
messages: self.send_queue.iter()
|
||||
.map(|m| m.clone())
|
||||
.map(|m| m.clone().to_vec())
|
||||
.collect(),
|
||||
})))
|
||||
}
|
||||
@@ -177,25 +183,25 @@ where TSubstream: AsyncRead + AsyncWrite {
|
||||
}
|
||||
|
||||
// Flushing if necessary.
|
||||
if self.requires_poll_complete {
|
||||
if let Async::Ready(()) = self.inner.poll_complete()? {
|
||||
self.requires_poll_complete = false;
|
||||
if self.requires_poll_flush {
|
||||
if let Poll::Ready(()) = Pin::new(&mut self.inner).poll_flush(cx)? {
|
||||
self.requires_poll_flush = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Receiving incoming packets.
|
||||
// Note that `inner` is wrapped in a `Fuse`, therefore we can poll it forever.
|
||||
match self.inner.poll()? {
|
||||
Async::Ready(Some(data)) => {
|
||||
Ok(Async::Ready(Some(RegisteredProtocolEvent::Message(data))))
|
||||
match Pin::new(&mut self.inner).poll_next(cx)? {
|
||||
Poll::Ready(Some(data)) => {
|
||||
Poll::Ready(Some(Ok(RegisteredProtocolEvent::Message(data))))
|
||||
}
|
||||
Async::Ready(None) =>
|
||||
if !self.requires_poll_complete && self.send_queue.is_empty() {
|
||||
Ok(Async::Ready(None))
|
||||
Poll::Ready(None) =>
|
||||
if !self.requires_poll_flush && self.send_queue.is_empty() {
|
||||
Poll::Ready(None)
|
||||
} else {
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
Async::NotReady => Ok(Async::NotReady),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -224,7 +230,7 @@ impl UpgradeInfo for RegisteredProtocol {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct RegisteredProtocolName {
|
||||
/// Protocol name, as advertised on the wire.
|
||||
name: Bytes,
|
||||
name: Vec<u8>,
|
||||
/// Version number. Stored in string form in `name`, but duplicated here for easier retrieval.
|
||||
version: u8,
|
||||
}
|
||||
@@ -236,10 +242,10 @@ impl ProtocolName for RegisteredProtocolName {
|
||||
}
|
||||
|
||||
impl<TSubstream> InboundUpgrade<TSubstream> for RegisteredProtocol
|
||||
where TSubstream: AsyncRead + AsyncWrite,
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
type Output = RegisteredProtocolSubstream<TSubstream>;
|
||||
type Future = future::FutureResult<Self::Output, io::Error>;
|
||||
type Future = future::Ready<Result<Self::Output, io::Error>>;
|
||||
type Error = io::Error;
|
||||
|
||||
fn upgrade_inbound(
|
||||
@@ -257,7 +263,7 @@ where TSubstream: AsyncRead + AsyncWrite,
|
||||
is_closing: false,
|
||||
endpoint: Endpoint::Listener,
|
||||
send_queue: VecDeque::new(),
|
||||
requires_poll_complete: false,
|
||||
requires_poll_flush: false,
|
||||
inner: framed.fuse(),
|
||||
protocol_version: info.version,
|
||||
clogged_fuse: false,
|
||||
@@ -266,7 +272,7 @@ where TSubstream: AsyncRead + AsyncWrite,
|
||||
}
|
||||
|
||||
impl<TSubstream> OutboundUpgrade<TSubstream> for RegisteredProtocol
|
||||
where TSubstream: AsyncRead + AsyncWrite,
|
||||
where TSubstream: AsyncRead + AsyncWrite + Unpin,
|
||||
{
|
||||
type Output = <Self as InboundUpgrade<TSubstream>>::Output;
|
||||
type Future = <Self as InboundUpgrade<TSubstream>>::Future;
|
||||
@@ -283,7 +289,7 @@ where TSubstream: AsyncRead + AsyncWrite,
|
||||
is_closing: false,
|
||||
endpoint: Endpoint::Dialer,
|
||||
send_queue: VecDeque::new(),
|
||||
requires_poll_complete: false,
|
||||
requires_poll_flush: false,
|
||||
inner: framed.fuse(),
|
||||
protocol_version: info.version,
|
||||
clogged_fuse: false,
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::collections::{HashMap, VecDeque};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Instant, Duration};
|
||||
use log::{trace, info};
|
||||
use futures::sync::oneshot::{Sender as OneShotSender};
|
||||
use futures::channel::oneshot::{Sender as OneShotSender};
|
||||
use linked_hash_map::{Entry, LinkedHashMap};
|
||||
use sp_blockchain::Error as ClientError;
|
||||
use sc_client_api::{FetchChecker, RemoteHeaderRequest,
|
||||
@@ -680,7 +680,7 @@ pub mod tests {
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use futures::{Future, sync::oneshot};
|
||||
use futures::channel::oneshot;
|
||||
use sp_core::storage::ChildInfo;
|
||||
use sp_runtime::traits::{Block as BlockT, NumberFor, Header as HeaderT};
|
||||
use sp_blockchain::{Error as ClientError, Result as ClientResult};
|
||||
@@ -999,7 +999,7 @@ pub mod tests {
|
||||
}, tx));
|
||||
|
||||
receive_call_response(&mut network_interface, &mut light_dispatch, peer0.clone(), 0);
|
||||
assert_eq!(response.wait().unwrap().unwrap(), vec![42]);
|
||||
assert_eq!(futures::executor::block_on(response).unwrap().unwrap(), vec![42]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1021,7 +1021,10 @@ pub mod tests {
|
||||
id: 0,
|
||||
proof: StorageProof::empty(),
|
||||
});
|
||||
assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42]));
|
||||
assert_eq!(
|
||||
futures::executor::block_on(response).unwrap().unwrap().remove(b":key".as_ref()).unwrap(),
|
||||
Some(vec![42])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1049,7 +1052,7 @@ pub mod tests {
|
||||
id: 0,
|
||||
proof: StorageProof::empty(),
|
||||
});
|
||||
assert_eq!(response.wait().unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42]));
|
||||
assert_eq!(futures::executor::block_on(response).unwrap().unwrap().remove(b":key".as_ref()).unwrap(), Some(vec![42]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1078,7 +1081,7 @@ pub mod tests {
|
||||
proof: StorageProof::empty(),
|
||||
});
|
||||
assert_eq!(
|
||||
response.wait().unwrap().unwrap().hash(),
|
||||
futures::executor::block_on(response).unwrap().unwrap().hash(),
|
||||
"6443a0b46e0412e626363028115a9f2cf963eeed526b8b33e5316f08b50d0dc3".parse().unwrap(),
|
||||
);
|
||||
}
|
||||
@@ -1109,7 +1112,7 @@ pub mod tests {
|
||||
roots: vec![],
|
||||
roots_proof: StorageProof::empty(),
|
||||
});
|
||||
assert_eq!(response.wait().unwrap().unwrap(), vec![(100, 2)]);
|
||||
assert_eq!(futures::executor::block_on(response).unwrap().unwrap(), vec![(100, 2)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -27,11 +27,12 @@
|
||||
|
||||
use std::{collections::{HashMap, HashSet}, fs, marker::PhantomData, io, path::Path};
|
||||
use std::sync::{Arc, atomic::{AtomicBool, AtomicUsize, Ordering}};
|
||||
use std::pin::Pin;
|
||||
use std::task::Poll;
|
||||
|
||||
use sp_consensus::import_queue::{ImportQueue, Link};
|
||||
use sp_consensus::import_queue::{BlockImportResult, BlockImportError};
|
||||
use futures::{prelude::*, sync::mpsc};
|
||||
use futures03::TryFutureExt as _;
|
||||
use futures::{prelude::*, channel::mpsc};
|
||||
use log::{warn, error, info};
|
||||
use libp2p::{PeerId, Multiaddr, kad::record};
|
||||
use libp2p::core::{transport::boxed::Boxed, muxing::StreamMuxerBox};
|
||||
@@ -216,7 +217,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> NetworkWorker
|
||||
params.network_config.client_version,
|
||||
params.network_config.node_name
|
||||
);
|
||||
let behaviour = Behaviour::new(
|
||||
let behaviour = futures::executor::block_on(Behaviour::new(
|
||||
protocol,
|
||||
user_agent,
|
||||
local_public,
|
||||
@@ -229,7 +230,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> NetworkWorker
|
||||
TransportConfig::MemoryOnly => false,
|
||||
TransportConfig::Normal { allow_private_ipv4, .. } => allow_private_ipv4,
|
||||
},
|
||||
);
|
||||
));
|
||||
let (transport, bandwidth) = {
|
||||
let (config_mem, config_wasm) = match params.network_config.transport {
|
||||
TransportConfig::MemoryOnly => (true, None),
|
||||
@@ -451,7 +452,7 @@ impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> NetworkServic
|
||||
/// If this method is called multiple times, the events are duplicated.
|
||||
///
|
||||
/// The stream never ends (unless the `NetworkWorker` gets shut down).
|
||||
pub fn event_stream(&self) -> impl Stream<Item = Event, Error = ()> {
|
||||
pub fn event_stream(&self) -> impl Stream<Item = Event> {
|
||||
// Note: when transitioning to stable futures, remove the `Error` entirely
|
||||
let (tx, rx) = mpsc::unbounded();
|
||||
let _ = self.to_worker.unbounded_send(ServiceToWorkerMsg::EventStream(tx));
|
||||
@@ -711,106 +712,106 @@ pub struct NetworkWorker<B: BlockT + 'static, S: NetworkSpecialization<B>, H: Ex
|
||||
}
|
||||
|
||||
impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> Future for NetworkWorker<B, S, H> {
|
||||
type Item = ();
|
||||
type Error = io::Error;
|
||||
type Output = Result<(), io::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context) -> Poll<Self::Output> {
|
||||
let this = &mut *self;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
// Poll the import queue for actions to perform.
|
||||
let _ = futures03::future::poll_fn(|cx| {
|
||||
self.import_queue.poll_actions(cx, &mut NetworkLink {
|
||||
protocol: &mut self.network_service,
|
||||
});
|
||||
std::task::Poll::Pending::<Result<(), ()>>
|
||||
}).compat().poll();
|
||||
this.import_queue.poll_actions(cx, &mut NetworkLink {
|
||||
protocol: &mut this.network_service,
|
||||
});
|
||||
|
||||
// Check for new incoming light client requests.
|
||||
if let Some(light_client_rqs) = self.light_client_rqs.as_mut() {
|
||||
while let Ok(Async::Ready(Some(rq))) = light_client_rqs.poll() {
|
||||
self.network_service.user_protocol_mut().add_light_client_request(rq);
|
||||
if let Some(light_client_rqs) = this.light_client_rqs.as_mut() {
|
||||
while let Poll::Ready(Some(rq)) = light_client_rqs.poll_next_unpin(cx) {
|
||||
this.network_service.user_protocol_mut().add_light_client_request(rq);
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
// Process the next message coming from the `NetworkService`.
|
||||
let msg = match self.from_worker.poll() {
|
||||
Ok(Async::Ready(Some(msg))) => msg,
|
||||
Ok(Async::Ready(None)) | Err(_) => return Ok(Async::Ready(())),
|
||||
Ok(Async::NotReady) => break,
|
||||
let msg = match this.from_worker.poll_next_unpin(cx) {
|
||||
Poll::Ready(Some(msg)) => msg,
|
||||
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||
Poll::Pending => break,
|
||||
};
|
||||
|
||||
match msg {
|
||||
ServiceToWorkerMsg::ExecuteWithSpec(task) => {
|
||||
let protocol = self.network_service.user_protocol_mut();
|
||||
let protocol = this.network_service.user_protocol_mut();
|
||||
let (mut context, spec) = protocol.specialization_lock();
|
||||
task(spec, &mut context);
|
||||
},
|
||||
ServiceToWorkerMsg::AnnounceBlock(hash, data) =>
|
||||
self.network_service.user_protocol_mut().announce_block(hash, data),
|
||||
this.network_service.user_protocol_mut().announce_block(hash, data),
|
||||
ServiceToWorkerMsg::RequestJustification(hash, number) =>
|
||||
self.network_service.user_protocol_mut().request_justification(&hash, number),
|
||||
this.network_service.user_protocol_mut().request_justification(&hash, number),
|
||||
ServiceToWorkerMsg::PropagateExtrinsics =>
|
||||
self.network_service.user_protocol_mut().propagate_extrinsics(),
|
||||
this.network_service.user_protocol_mut().propagate_extrinsics(),
|
||||
ServiceToWorkerMsg::GetValue(key) =>
|
||||
self.network_service.get_value(&key),
|
||||
this.network_service.get_value(&key),
|
||||
ServiceToWorkerMsg::PutValue(key, value) =>
|
||||
self.network_service.put_value(key, value),
|
||||
this.network_service.put_value(key, value),
|
||||
ServiceToWorkerMsg::AddKnownAddress(peer_id, addr) =>
|
||||
self.network_service.add_known_address(peer_id, addr),
|
||||
this.network_service.add_known_address(peer_id, addr),
|
||||
ServiceToWorkerMsg::SyncFork(peer_ids, hash, number) =>
|
||||
self.network_service.user_protocol_mut().set_sync_fork_request(peer_ids, &hash, number),
|
||||
this.network_service.user_protocol_mut().set_sync_fork_request(peer_ids, &hash, number),
|
||||
ServiceToWorkerMsg::EventStream(sender) =>
|
||||
self.event_streams.push(sender),
|
||||
this.event_streams.push(sender),
|
||||
ServiceToWorkerMsg::WriteNotification { message, engine_id, target } =>
|
||||
self.network_service.user_protocol_mut().write_notification(target, engine_id, message),
|
||||
this.network_service.user_protocol_mut().write_notification(target, engine_id, message),
|
||||
ServiceToWorkerMsg::RegisterNotifProtocol { engine_id } => {
|
||||
let events = self.network_service.user_protocol_mut().register_notifications_protocol(engine_id);
|
||||
let events = this.network_service.user_protocol_mut().register_notifications_protocol(engine_id);
|
||||
for event in events {
|
||||
self.event_streams.retain(|sender| sender.unbounded_send(event.clone()).is_ok());
|
||||
this.event_streams.retain(|sender| sender.unbounded_send(event.clone()).is_ok());
|
||||
}
|
||||
},
|
||||
ServiceToWorkerMsg::DisconnectPeer(who) =>
|
||||
self.network_service.user_protocol_mut().disconnect_peer(&who),
|
||||
this.network_service.user_protocol_mut().disconnect_peer(&who),
|
||||
}
|
||||
}
|
||||
|
||||
loop {
|
||||
// Process the next action coming from the network.
|
||||
let poll_value = self.network_service.poll();
|
||||
let poll_value = this.network_service.poll_next_unpin(cx);
|
||||
|
||||
match poll_value {
|
||||
Ok(Async::NotReady) => break,
|
||||
Ok(Async::Ready(Some(BehaviourOut::BlockImport(origin, blocks)))) =>
|
||||
self.import_queue.import_blocks(origin, blocks),
|
||||
Ok(Async::Ready(Some(BehaviourOut::JustificationImport(origin, hash, nb, justification)))) =>
|
||||
self.import_queue.import_justification(origin, hash, nb, justification),
|
||||
Ok(Async::Ready(Some(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)))) =>
|
||||
self.import_queue.import_finality_proof(origin, hash, nb, proof),
|
||||
Ok(Async::Ready(Some(BehaviourOut::Event(ev)))) => {
|
||||
self.event_streams.retain(|sender| sender.unbounded_send(ev.clone()).is_ok());
|
||||
Poll::Pending => break,
|
||||
Poll::Ready(Some(BehaviourOut::BlockImport(origin, blocks))) =>
|
||||
this.import_queue.import_blocks(origin, blocks),
|
||||
Poll::Ready(Some(BehaviourOut::JustificationImport(origin, hash, nb, justification))) =>
|
||||
this.import_queue.import_justification(origin, hash, nb, justification),
|
||||
Poll::Ready(Some(BehaviourOut::FinalityProofImport(origin, hash, nb, proof))) =>
|
||||
this.import_queue.import_finality_proof(origin, hash, nb, proof),
|
||||
Poll::Ready(Some(BehaviourOut::Event(ev))) => {
|
||||
this.event_streams.retain(|sender| sender.unbounded_send(ev.clone()).is_ok());
|
||||
},
|
||||
Poll::Ready(None) => {
|
||||
error!(target: "sync", "Network events stream has returned None");
|
||||
break;
|
||||
},
|
||||
Ok(Async::Ready(None)) => {},
|
||||
Err(err) => {
|
||||
error!(target: "sync", "Error in the network: {:?}", err);
|
||||
return Err(err)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Update the variables shared with the `NetworkService`.
|
||||
self.num_connected.store(self.network_service.user_protocol_mut().num_connected_peers(), Ordering::Relaxed);
|
||||
this.num_connected.store(this.network_service.user_protocol_mut().num_connected_peers(), Ordering::Relaxed);
|
||||
{
|
||||
let external_addresses = Swarm::<B, S, H>::external_addresses(&self.network_service).cloned().collect();
|
||||
*self.external_addresses.lock() = external_addresses;
|
||||
let external_addresses = Swarm::<B, S, H>::external_addresses(&this.network_service).cloned().collect();
|
||||
*this.external_addresses.lock() = external_addresses;
|
||||
}
|
||||
self.is_major_syncing.store(match self.network_service.user_protocol_mut().sync_state() {
|
||||
this.is_major_syncing.store(match this.network_service.user_protocol_mut().sync_state() {
|
||||
SyncState::Idle => false,
|
||||
SyncState::Downloading => true,
|
||||
}, Ordering::Relaxed);
|
||||
|
||||
Ok(Async::NotReady)
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BlockT + 'static, S: NetworkSpecialization<B>, H: ExHashT> Unpin for NetworkWorker<B, S, H> {
|
||||
}
|
||||
|
||||
/// The libp2p swarm, customized for our needs.
|
||||
type Swarm<B, S, H> = libp2p::swarm::Swarm<
|
||||
Boxed<(PeerId, StreamMuxerBox), io::Error>,
|
||||
|
||||
@@ -71,7 +71,11 @@ pub fn build_transport(
|
||||
let desktop_trans = tcp::TcpConfig::new();
|
||||
let desktop_trans = websocket::WsConfig::new(desktop_trans.clone())
|
||||
.or_transport(desktop_trans);
|
||||
OptionalTransport::some(dns::DnsConfig::new(desktop_trans))
|
||||
OptionalTransport::some(if let Ok(dns) = dns::DnsConfig::new(desktop_trans.clone()) {
|
||||
dns.boxed()
|
||||
} else {
|
||||
desktop_trans.map_err(dns::DnsErr::Underlying).boxed()
|
||||
})
|
||||
} else {
|
||||
OptionalTransport::none()
|
||||
});
|
||||
@@ -91,7 +95,7 @@ pub fn build_transport(
|
||||
let transport = transport.and_then(move |stream, endpoint| {
|
||||
let upgrade = core::upgrade::SelectUpgrade::new(noise_config, secio_config);
|
||||
core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1)
|
||||
.and_then(|out| match out {
|
||||
.map(|out| match out? {
|
||||
// We negotiated noise
|
||||
EitherOutput::First((remote_id, out)) => {
|
||||
let remote_key = match remote_id {
|
||||
@@ -110,7 +114,7 @@ pub fn build_transport(
|
||||
#[cfg(target_os = "unknown")]
|
||||
let transport = transport.and_then(move |stream, endpoint| {
|
||||
core::upgrade::apply(stream, secio_config, endpoint, upgrade::Version::V1)
|
||||
.and_then(|(id, stream)| Ok((stream, id)))
|
||||
.map_ok(|(id, stream)| ((stream, id)))
|
||||
});
|
||||
|
||||
// Multiplexing
|
||||
@@ -121,7 +125,7 @@ pub fn build_transport(
|
||||
.map_outbound(move |muxer| (peer_id2, muxer));
|
||||
|
||||
core::upgrade::apply(stream, upgrade, endpoint, upgrade::Version::V1)
|
||||
.map(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer)))
|
||||
.map_ok(|(id, muxer)| (id, core::muxing::StreamMuxerBox::new(muxer)))
|
||||
})
|
||||
|
||||
.timeout(Duration::from_secs(20))
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::time::Duration;
|
||||
use futures03::{FutureExt, Stream, StreamExt, stream::unfold};
|
||||
use futures::{FutureExt, Stream, StreamExt, stream::unfold};
|
||||
use futures_timer::Delay;
|
||||
|
||||
pub fn interval(duration: Duration) -> impl Stream<Item=()> + Unpin {
|
||||
|
||||
@@ -14,7 +14,7 @@ futures = "0.1.29"
|
||||
futures03 = { package = "futures", version = "0.3.1", features = ["compat"] }
|
||||
futures-timer = "0.4.0"
|
||||
rand = "0.7.2"
|
||||
libp2p = { version = "0.13.2", default-features = false, features = ["libp2p-websocket"] }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] }
|
||||
sp-consensus = { version = "0.8", path = "../../../primitives/consensus/common" }
|
||||
sc-client = { version = "2.0.0", path = "../../" }
|
||||
sc-client-api = { version = "2.0.0", path = "../../api" }
|
||||
|
||||
@@ -22,6 +22,7 @@ mod block_import;
|
||||
mod sync;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use libp2p::build_multiaddr;
|
||||
@@ -48,7 +49,7 @@ use sp_consensus::block_import::{BlockImport, ImportResult};
|
||||
use sp_consensus::Error as ConsensusError;
|
||||
use sp_consensus::{BlockOrigin, ForkChoiceStrategy, BlockImportParams, BlockCheckParams, JustificationImport};
|
||||
use futures::prelude::*;
|
||||
use futures03::{StreamExt as _, TryStreamExt as _};
|
||||
use futures03::{Future as _, FutureExt as _, TryFutureExt as _, StreamExt as _, TryStreamExt as _};
|
||||
use sc_network::{NetworkWorker, NetworkStateInfo, NetworkService, ReportHandle, config::ProtocolId};
|
||||
use sc_network::config::{NetworkConfiguration, TransportConfig, BoxFinalityProofRequestBuilder};
|
||||
use libp2p::PeerId;
|
||||
@@ -713,7 +714,9 @@ pub trait TestNetFactory: Sized {
|
||||
self.mut_peers(|peers| {
|
||||
for peer in peers {
|
||||
trace!(target: "sync", "-- Polling {}", peer.id());
|
||||
peer.network.poll().unwrap();
|
||||
futures03::future::poll_fn(|cx| Pin::new(&mut peer.network).poll(cx))
|
||||
.map(|item| Ok::<_, ()>(item))
|
||||
.compat().poll().unwrap();
|
||||
trace!(target: "sync", "-- Polling complete {}", peer.id());
|
||||
|
||||
// We poll `imported_blocks_stream`.
|
||||
|
||||
@@ -9,7 +9,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.1"
|
||||
libp2p = { version = "0.13.2", default-features = false }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false }
|
||||
log = "0.4.8"
|
||||
serde_json = "1.0.41"
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ pub mod error;
|
||||
mod builder;
|
||||
mod status_sinks;
|
||||
|
||||
use std::io;
|
||||
use std::{io, pin::Pin};
|
||||
use std::marker::PhantomData;
|
||||
use std::net::SocketAddr;
|
||||
use std::collections::HashMap;
|
||||
@@ -479,7 +479,9 @@ fn build_network_future<
|
||||
});
|
||||
|
||||
// Main network polling.
|
||||
if let Ok(Async::Ready(())) = network.poll().map_err(|err| {
|
||||
let mut net_poll = futures03::future::poll_fn(|cx| futures03::future::Future::poll(Pin::new(&mut network), cx))
|
||||
.compat();
|
||||
if let Ok(Async::Ready(())) = net_poll.poll().map_err(|err| {
|
||||
warn!(target: "service", "Error in network: {:?}", err);
|
||||
}) {
|
||||
return Ok(Async::Ready(()));
|
||||
|
||||
@@ -6,18 +6,17 @@ description = "Telemetry utils"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bytes = "0.4.12"
|
||||
bytes = "0.5"
|
||||
parking_lot = "0.9.0"
|
||||
futures01 = { package = "futures", version = "0.1" }
|
||||
futures = { version = "0.3.1", features = ["compat"] }
|
||||
futures = "0.3.1"
|
||||
futures-timer = "2.0.0"
|
||||
libp2p = { version = "0.13.2", default-features = false, features = ["libp2p-websocket"] }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false, features = ["libp2p-websocket"] }
|
||||
log = "0.4.8"
|
||||
pin-project = "0.4.6"
|
||||
rand = "0.7.2"
|
||||
serde = { version = "1.0.101", features = ["derive"] }
|
||||
slog = { version = "2.5.2", features = ["nested-values"] }
|
||||
slog-json = { version = "2.3.0", features = ["nested-values"] }
|
||||
slog-scope = "4.1.2"
|
||||
tokio-io = "0.1.12"
|
||||
take_mut = "0.2.2"
|
||||
void = "1.0.2"
|
||||
|
||||
@@ -60,11 +60,12 @@
|
||||
|
||||
use futures::{prelude::*, channel::mpsc};
|
||||
use libp2p::{Multiaddr, wasm_ext};
|
||||
use log::warn;
|
||||
use log::{error, warn};
|
||||
use parking_lot::Mutex;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::{pin::Pin, sync::Arc, task::{Context, Poll}, time::{Duration, Instant}};
|
||||
|
||||
pub use libp2p::wasm_ext::ExtTransport;
|
||||
pub use slog_scope::with_logger;
|
||||
pub use slog;
|
||||
|
||||
@@ -129,8 +130,8 @@ pub struct Telemetry {
|
||||
/// where we extract the telemetry registration so that it continues running during the shutdown
|
||||
/// process.
|
||||
struct TelemetryInner {
|
||||
/// Worker for the telemetry.
|
||||
worker: worker::TelemetryWorker,
|
||||
/// Worker for the telemetry. `None` if it failed to initialize.
|
||||
worker: Option<worker::TelemetryWorker>,
|
||||
/// Receives log entries for them to be dispatched to the worker.
|
||||
receiver: mpsc::Receiver<async_record::AsyncRecord>,
|
||||
}
|
||||
@@ -162,9 +163,17 @@ pub fn init_telemetry(config: TelemetryConfig) -> Telemetry {
|
||||
slog_scope::set_global_logger(root)
|
||||
};
|
||||
|
||||
let worker = match worker::TelemetryWorker::new(endpoints, config.wasm_external_transport) {
|
||||
Ok(w) => Some(w),
|
||||
Err(err) => {
|
||||
error!(target: "telemetry", "Failed to initialize telemetry worker: {:?}", err);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
Telemetry {
|
||||
inner: Arc::new(Mutex::new(TelemetryInner {
|
||||
worker: worker::TelemetryWorker::new(endpoints, config.wasm_external_transport),
|
||||
worker,
|
||||
receiver,
|
||||
})),
|
||||
_guard: Arc::new(guard),
|
||||
@@ -209,15 +218,19 @@ impl Stream for Telemetry {
|
||||
// The polling pattern is: poll the worker so that it processes its queue, then add one
|
||||
// message from the receiver (if possible), then poll the worker again, and so on.
|
||||
loop {
|
||||
while let Poll::Ready(event) = inner.worker.poll(cx) {
|
||||
// Right now we only have one possible event. This line is here in order to not
|
||||
// forget to handle any possible new event type.
|
||||
let worker::TelemetryWorkerEvent::Connected = event;
|
||||
has_connected = true;
|
||||
if let Some(worker) = inner.worker.as_mut() {
|
||||
while let Poll::Ready(event) = worker.poll(cx) {
|
||||
// Right now we only have one possible event. This line is here in order to not
|
||||
// forget to handle any possible new event type.
|
||||
let worker::TelemetryWorkerEvent::Connected = event;
|
||||
has_connected = true;
|
||||
}
|
||||
}
|
||||
|
||||
if let Poll::Ready(Some(log_entry)) = Stream::poll_next(Pin::new(&mut inner.receiver), cx) {
|
||||
log_entry.as_record_values(|rec, val| { let _ = inner.worker.log(rec, val); });
|
||||
if let Some(worker) = inner.worker.as_mut() {
|
||||
log_entry.as_record_values(|rec, val| { let _ = worker.log(rec, val); });
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
//!
|
||||
|
||||
use bytes::BytesMut;
|
||||
use futures::compat::Compat01As03Sink;
|
||||
use libp2p::{core::transport::OptionalTransport, core::ConnectedPoint, Multiaddr, Transport, wasm_ext};
|
||||
use futures::{prelude::*, ready};
|
||||
use libp2p::{core::transport::OptionalTransport, Multiaddr, Transport, wasm_ext};
|
||||
use log::{trace, warn, error};
|
||||
use slog::Drain;
|
||||
use std::{io, pin::Pin, task::Context, task::Poll, time};
|
||||
@@ -54,33 +54,16 @@ pub struct TelemetryWorker {
|
||||
nodes: Vec<(node::Node<WsTrans>, u8)>,
|
||||
}
|
||||
|
||||
/// The pile of libp2p transports.
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
type WsTrans = libp2p::core::transport::timeout::TransportTimeout<
|
||||
libp2p::core::transport::map::Map<
|
||||
libp2p::core::transport::OrTransport<
|
||||
libp2p::core::transport::map::Map<
|
||||
OptionalTransport<wasm_ext::ExtTransport>,
|
||||
fn(wasm_ext::Connection, ConnectedPoint) -> StreamSink<wasm_ext::Connection>
|
||||
>,
|
||||
libp2p::websocket::framed::WsConfig<libp2p::dns::DnsConfig<libp2p::tcp::TcpConfig>>
|
||||
>,
|
||||
fn(libp2p::core::either::EitherOutput<StreamSink<wasm_ext::Connection>,
|
||||
libp2p::websocket::framed::BytesConnection<libp2p::tcp::TcpTransStream>>, ConnectedPoint)
|
||||
-> Compat01As03Sink<libp2p::core::either::EitherOutput<StreamSink<wasm_ext::Connection>,
|
||||
libp2p::websocket::framed::BytesConnection<libp2p::tcp::TcpTransStream>>, BytesMut>
|
||||
>
|
||||
>;
|
||||
#[cfg(target_os = "unknown")]
|
||||
type WsTrans = libp2p::core::transport::timeout::TransportTimeout<
|
||||
libp2p::core::transport::map::Map<
|
||||
libp2p::core::transport::map::Map<
|
||||
OptionalTransport<wasm_ext::ExtTransport>,
|
||||
fn(wasm_ext::Connection, ConnectedPoint) -> StreamSink<wasm_ext::Connection>
|
||||
>,
|
||||
fn(StreamSink<wasm_ext::Connection>, ConnectedPoint)
|
||||
-> Compat01As03Sink<StreamSink<wasm_ext::Connection>, BytesMut>
|
||||
>
|
||||
trait StreamAndSink<I>: Stream + Sink<I> {}
|
||||
impl<T: ?Sized + Stream + Sink<I>, I> StreamAndSink<I> for T {}
|
||||
|
||||
type WsTrans = libp2p::core::transport::boxed::Boxed<
|
||||
Pin<Box<dyn StreamAndSink<
|
||||
BytesMut,
|
||||
Item = Result<BytesMut, io::Error>,
|
||||
Error = io::Error
|
||||
> + Send>>,
|
||||
io::Error
|
||||
>;
|
||||
|
||||
impl TelemetryWorker {
|
||||
@@ -92,31 +75,48 @@ impl TelemetryWorker {
|
||||
pub fn new(
|
||||
endpoints: impl IntoIterator<Item = (Multiaddr, u8)>,
|
||||
wasm_external_transport: impl Into<Option<wasm_ext::ExtTransport>>
|
||||
) -> Self {
|
||||
) -> Result<Self, io::Error> {
|
||||
let transport = match wasm_external_transport.into() {
|
||||
Some(t) => OptionalTransport::some(t),
|
||||
None => OptionalTransport::none()
|
||||
}.map((|inner, _| StreamSink(inner)) as fn(_, _) -> _);
|
||||
}.map((|inner, _| StreamSink::from(inner)) as fn(_, _) -> _);
|
||||
|
||||
// The main transport is the `wasm_external_transport`, but if we're on desktop we add
|
||||
// support for TCP+WebSocket+DNS as a fallback. In practice, you're not expected to pass
|
||||
// an external transport on desktop and the fallback is used all the time.
|
||||
#[cfg(not(target_os = "unknown"))]
|
||||
let transport = transport.or_transport({
|
||||
let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new());
|
||||
let inner = libp2p::dns::DnsConfig::new(libp2p::tcp::TcpConfig::new())?;
|
||||
libp2p::websocket::framed::WsConfig::new(inner)
|
||||
.and_then(|connec, _| {
|
||||
let connec = connec
|
||||
.with(|item: BytesMut| {
|
||||
let item = libp2p::websocket::framed::OutgoingData::Binary(item);
|
||||
future::ready(Ok::<_, io::Error>(item))
|
||||
})
|
||||
.try_filter(|item| future::ready(item.is_data()))
|
||||
.map_ok(|data| BytesMut::from(data.as_ref()));
|
||||
future::ready(Ok::<_, io::Error>(connec))
|
||||
})
|
||||
});
|
||||
|
||||
let transport = transport
|
||||
.map((|inner, _| Compat01As03Sink::new(inner)) as fn(_, _) -> _)
|
||||
.timeout(CONNECT_TIMEOUT);
|
||||
.timeout(CONNECT_TIMEOUT)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||
.map(|out, _| {
|
||||
let out = out
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))
|
||||
.sink_map_err(|err| io::Error::new(io::ErrorKind::Other, err));
|
||||
Box::pin(out) as Pin<Box<_>>
|
||||
})
|
||||
.boxed();
|
||||
|
||||
TelemetryWorker {
|
||||
Ok(TelemetryWorker {
|
||||
nodes: endpoints.into_iter().map(|(addr, verbosity)| {
|
||||
let node = node::Node::new(transport.clone(), addr);
|
||||
(node, verbosity)
|
||||
}).collect()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Polls the worker for events that happened.
|
||||
@@ -174,7 +174,7 @@ impl TelemetryWorker {
|
||||
}
|
||||
|
||||
// `send_message` returns an error if we're not connected, which we silently ignore.
|
||||
let _ = node.send_message(serialized.clone());
|
||||
let _ = node.send_message(&serialized.clone()[..]);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -186,50 +186,74 @@ impl TelemetryWorker {
|
||||
///
|
||||
/// For some context, we put this object around the `wasm_ext::ExtTransport` in order to make sure
|
||||
/// that each telemetry message maps to one single call to `write` in the WASM FFI.
|
||||
struct StreamSink<T>(T);
|
||||
#[pin_project::pin_project]
|
||||
struct StreamSink<T>(#[pin] T, Option<BytesMut>);
|
||||
|
||||
impl<T: tokio_io::AsyncRead> futures01::Stream for StreamSink<T> {
|
||||
type Item = BytesMut;
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll(&mut self) -> futures01::Poll<Option<Self::Item>, Self::Error> {
|
||||
let mut buf = [0; 128];
|
||||
Ok(self.0.poll_read(&mut buf)?
|
||||
.map(|n|
|
||||
if n == 0 {
|
||||
None
|
||||
} else {
|
||||
let buf: BytesMut = buf[..n].into();
|
||||
Some(buf)
|
||||
}
|
||||
))
|
||||
impl<T> From<T> for StreamSink<T> {
|
||||
fn from(inner: T) -> StreamSink<T> {
|
||||
StreamSink(inner, None)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: tokio_io::AsyncWrite> futures01::Sink for StreamSink<T> {
|
||||
type SinkItem = BytesMut;
|
||||
type SinkError = io::Error;
|
||||
impl<T: AsyncRead> Stream for StreamSink<T> {
|
||||
type Item = Result<BytesMut, io::Error>;
|
||||
|
||||
fn start_send(&mut self, item: Self::SinkItem)
|
||||
-> Result<futures01::AsyncSink<Self::SinkItem>, io::Error> {
|
||||
match self.0.write(&item[..]) {
|
||||
Ok(n) if n == item.len() => Ok(futures01::AsyncSink::Ready),
|
||||
Ok(_) => {
|
||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
||||
let this = self.project();
|
||||
let mut buf = [0; 128];
|
||||
match ready!(AsyncRead::poll_read(this.0, cx, &mut buf)) {
|
||||
Ok(0) => Poll::Ready(None),
|
||||
Ok(n) => {
|
||||
let buf: BytesMut = buf[..n].into();
|
||||
Poll::Ready(Some(Ok(buf)))
|
||||
},
|
||||
Err(err) => Poll::Ready(Some(Err(err))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsyncWrite> StreamSink<T> {
|
||||
fn poll_flush_buffer(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), io::Error>> {
|
||||
let this = self.project();
|
||||
|
||||
if let Some(buffer) = this.1 {
|
||||
if ready!(this.0.poll_write(cx, &buffer[..]))? != buffer.len() {
|
||||
error!(target: "telemetry",
|
||||
"Detected some internal buffering happening in the telemetry");
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Internal buffering detected"))
|
||||
},
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock =>
|
||||
Ok(futures01::AsyncSink::NotReady(item)),
|
||||
Err(err) => Err(err),
|
||||
let err = io::Error::new(io::ErrorKind::Other, "Internal buffering detected");
|
||||
return Poll::Ready(Err(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_complete(&mut self) -> futures01::Poll<(), io::Error> {
|
||||
match self.0.flush() {
|
||||
Ok(()) => Ok(futures01::Async::Ready(())),
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(futures01::Async::NotReady),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
*this.1 = None;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsyncWrite> Sink<BytesMut> for StreamSink<T> {
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(StreamSink::poll_flush_buffer(self, cx))?;
|
||||
Poll::Ready(Ok(()))
|
||||
}
|
||||
|
||||
fn start_send(self: Pin<&mut Self>, item: BytesMut) -> Result<(), Self::Error> {
|
||||
let this = self.project();
|
||||
debug_assert!(this.1.is_none());
|
||||
*this.1 = Some(item);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll_flush_buffer(cx))?;
|
||||
let this = self.project();
|
||||
AsyncWrite::poll_flush(this.0, cx)
|
||||
}
|
||||
|
||||
fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
ready!(self.as_mut().poll_flush_buffer(cx))?;
|
||||
let this = self.project();
|
||||
AsyncWrite::poll_close(this.0, cx)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
//! Contains the `Node` struct, which handles communications with a single telemetry endpoint.
|
||||
|
||||
use bytes::BytesMut;
|
||||
use futures::{prelude::*, compat::{Future01CompatExt as _, Compat01As03}};
|
||||
use futures::prelude::*;
|
||||
use futures_timer::Delay;
|
||||
use libp2p::Multiaddr;
|
||||
use libp2p::core::transport::Transport;
|
||||
@@ -42,7 +42,7 @@ enum NodeSocket<TTrans: Transport> {
|
||||
/// We're connected to the node. This is the normal state.
|
||||
Connected(NodeSocketConnected<TTrans>),
|
||||
/// We are currently dialing the node.
|
||||
Dialing(Compat01As03<TTrans::Dial>),
|
||||
Dialing(TTrans::Dial),
|
||||
/// A new connection should be started as soon as possible.
|
||||
ReconnectNow,
|
||||
/// Waiting before attempting to dial again.
|
||||
@@ -76,6 +76,9 @@ pub enum NodeEvent<TSinkErr> {
|
||||
pub enum ConnectionError<TSinkErr> {
|
||||
/// The connection timed-out.
|
||||
Timeout,
|
||||
/// Reading from the socket returned and end-of-file, indicating that the socket has been
|
||||
/// closed.
|
||||
Closed,
|
||||
/// The sink errored.
|
||||
Sink(TSinkErr),
|
||||
}
|
||||
@@ -106,7 +109,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin,
|
||||
/// Sends a WebSocket frame to the node. Returns an error if we are not connected to the node.
|
||||
///
|
||||
/// After calling this method, you should call `poll` in order for it to be properly processed.
|
||||
pub fn send_message(&mut self, payload: Vec<u8>) -> Result<(), ()> {
|
||||
pub fn send_message(&mut self, payload: impl Into<BytesMut>) -> Result<(), ()> {
|
||||
if let NodeSocket::Connected(NodeSocketConnected { pending, .. }) = &mut self.socket {
|
||||
if pending.len() <= MAX_PENDING {
|
||||
trace!(target: "telemetry", "Adding log entry to queue for {:?}", self.addr);
|
||||
@@ -163,7 +166,7 @@ where TTrans: Clone + Unpin, TTrans::Dial: Unpin,
|
||||
NodeSocket::ReconnectNow => match self.transport.clone().dial(self.addr.clone()) {
|
||||
Ok(d) => {
|
||||
debug!(target: "telemetry", "Started dialing {}", self.addr);
|
||||
socket = NodeSocket::Dialing(d.compat());
|
||||
socket = NodeSocket::Dialing(d);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!(target: "telemetry", "Error while dialing {}: {:?}", self.addr, err);
|
||||
@@ -212,10 +215,13 @@ where TTrans::Output: Sink<BytesMut, Error = TSinkErr>
|
||||
) -> Poll<Result<futures::never::Never, ConnectionError<TSinkErr>>> {
|
||||
|
||||
while let Some(item) = self.pending.pop_front() {
|
||||
if let Poll::Ready(_) = Sink::poll_ready(Pin::new(&mut self.sink), cx) {
|
||||
if let Poll::Ready(result) = Sink::poll_ready(Pin::new(&mut self.sink), cx) {
|
||||
if let Err(err) = result {
|
||||
return Poll::Ready(Err(ConnectionError::Sink(err)))
|
||||
}
|
||||
|
||||
let item_len = item.len();
|
||||
if let Err(err) = Sink::start_send(Pin::new(&mut self.sink), item) {
|
||||
self.timeout = None;
|
||||
return Poll::Ready(Err(ConnectionError::Sink(err)))
|
||||
}
|
||||
trace!(
|
||||
@@ -270,7 +276,10 @@ where TTrans::Output: Sink<BytesMut, Error = TSinkErr>
|
||||
Poll::Ready(Some(Err(err))) => {
|
||||
return Poll::Ready(Err(ConnectionError::Sink(err)))
|
||||
},
|
||||
Poll::Pending | Poll::Ready(None) => {},
|
||||
Poll::Ready(None) => {
|
||||
return Poll::Ready(Err(ConnectionError::Closed))
|
||||
},
|
||||
Poll::Pending => {},
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
|
||||
@@ -7,7 +7,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
derive_more = "0.99.2"
|
||||
libp2p = { version = "0.13.2", default-features = false }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false }
|
||||
log = "0.4.8"
|
||||
sp-core = { path= "../../core" }
|
||||
sp-inherents = { version = "2.0.0", path = "../../inherents" }
|
||||
|
||||
@@ -9,7 +9,7 @@ edition = "2018"
|
||||
futures = "0.3"
|
||||
futures01 = { package = "futures", version = "0.1.29" }
|
||||
log = "0.4.8"
|
||||
libp2p = { version = "0.13.2", default-features = false }
|
||||
libp2p = { version = "0.14.0-alpha.1", default-features = false }
|
||||
console_error_panic_hook = "0.1.6"
|
||||
console_log = "0.1.2"
|
||||
js-sys = "0.3.34"
|
||||
|
||||
Reference in New Issue
Block a user