feat(swarm): Make executor for connection tasks explicit (#3097)

Previously, the executor for connection tasks silently defaulted to a `futures::executor::ThreadPool`. This causes issues such as https://github.com/libp2p/rust-libp2p/issues/2230.

With this patch, we force the user to choose, which executor they want to run the connection tasks on which results in overall simpler API with less footguns.

Closes #3068.
This commit is contained in:
Hannes
2022-11-15 15:26:03 +01:00
committed by GitHub
parent d8fe7bf49f
commit d5ea93dd71
41 changed files with 384 additions and 181 deletions

View File

@ -39,7 +39,7 @@ use libp2p::{
TokioMdns,
},
mplex, noise,
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
swarm::{NetworkBehaviour, SwarmEvent},
tcp, Multiaddr, PeerId, Transport,
};
use std::error::Error;
@ -97,23 +97,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
// Create a Swarm to manage peers and events.
let mut swarm = {
let mdns = TokioMdns::new(Default::default())?;
let mut behaviour = MyBehaviour {
floodsub: Floodsub::new(peer_id),
mdns,
};
behaviour.floodsub.subscribe(floodsub_topic.clone());
SwarmBuilder::new(transport, behaviour, peer_id)
// We want the connection background tasks to be spawned
// onto the tokio runtime.
.executor(Box::new(|fut| {
tokio::spawn(fut);
}))
.build()
let mdns = TokioMdns::new(Default::default())?;
let behaviour = MyBehaviour {
floodsub: Floodsub::new(peer_id),
mdns,
};
let mut swarm = libp2p_swarm::Swarm::with_tokio_executor(transport, behaviour, peer_id);
// Reach out to another node if specified
if let Some(to_dial) = std::env::args().nth(1) {

View File

@ -115,7 +115,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
};
behaviour.floodsub.subscribe(floodsub_topic.clone());
Swarm::new(transport, behaviour, local_peer_id)
Swarm::with_threadpool_executor(transport, behaviour, local_peer_id)
};
// Reach out to another node if specified

View File

@ -99,7 +99,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let kademlia = Kademlia::new(local_peer_id, store);
let mdns = Mdns::new(MdnsConfig::default())?;
let behaviour = MyBehaviour { kademlia, mdns };
Swarm::new(transport, behaviour, local_peer_id)
Swarm::with_async_std_executor(transport, behaviour, local_peer_id)
};
// Read full lines from stdin

View File

@ -219,9 +219,7 @@ mod network {
ProtocolSupport, RequestId, RequestResponse, RequestResponseCodec, RequestResponseEvent,
RequestResponseMessage, ResponseChannel,
};
use libp2p::swarm::{
ConnectionHandlerUpgrErr, NetworkBehaviour, Swarm, SwarmBuilder, SwarmEvent,
};
use libp2p::swarm::{ConnectionHandlerUpgrErr, NetworkBehaviour, Swarm, SwarmEvent};
use std::collections::{hash_map, HashMap, HashSet};
use std::iter;
@ -252,7 +250,7 @@ mod network {
// Build the Swarm, connecting the lower layer transport logic with the
// higher layer network behaviour logic.
let swarm = SwarmBuilder::new(
let swarm = Swarm::with_threadpool_executor(
libp2p::development_transport(id_keys).await?,
ComposedBehaviour {
kademlia: Kademlia::new(peer_id, MemoryStore::new(peer_id)),
@ -263,8 +261,7 @@ mod network {
),
},
peer_id,
)
.build();
);
let (command_sender, command_receiver) = mpsc::channel(0);
let (event_sender, event_receiver) = mpsc::channel(0);

View File

@ -110,7 +110,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let mut swarm = {
let mdns = Mdns::new(MdnsConfig::default())?;
let behaviour = MyBehaviour { gossipsub, mdns };
Swarm::new(transport, behaviour, local_peer_id)
Swarm::with_async_std_executor(transport, behaviour, local_peer_id)
};
// Read full lines from stdin

View File

@ -68,7 +68,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
behaviour.add_address(&PeerId::from_str(peer)?, bootaddr.clone());
}
Swarm::new(transport, behaviour, local_peer_id)
Swarm::with_async_std_executor(transport, behaviour, local_peer_id)
};
// Order Kademlia to search for a peer.

View File

@ -204,7 +204,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("Subscribing to {gossipsub_topic:?}");
behaviour.gossipsub.subscribe(&gossipsub_topic).unwrap();
Swarm::new(transport, behaviour, local_peer_id)
Swarm::with_async_std_executor(transport, behaviour, local_peer_id)
};
// Reach out to other nodes if specified

View File

@ -45,7 +45,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Create a Swarm that establishes connections through the given transport.
// Note that the MDNS behaviour itself will not actually inititiate any connections,
// as it only uses UDP.
let mut swarm = Swarm::new(transport, behaviour, peer_id);
let mut swarm = Swarm::with_async_std_executor(transport, behaviour, peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
loop {

View File

@ -54,7 +54,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let transport = libp2p::development_transport(local_key).await?;
let mut swarm = Swarm::new(transport, Behaviour::default(), local_peer_id);
let mut swarm = Swarm::with_async_std_executor(transport, Behaviour::default(), local_peer_id);
// Tell the swarm to listen on all interfaces and a random, OS-assigned
// port.