Skip to content

Commit

Permalink
[libp2p-dns] Use trust-dns-resolver (with either async-std or tokio).…
Browse files Browse the repository at this point in the history
… Remove thread pool. (#1927)

* [libp2p-dns] Use trust-dns-resolver.

Use the `trust-dns-resolver` library for DNS resolution,
thereby removing current use of the thread pool.

Since `trust-dns-resolver` and related crates already
provide support for both `async-std` and `tokio`, we
make use of that here in our own feature flags.

Since `trust-dns-resolver` provides many useful
configuration options and error detail, central
types of `trust-dns-resolver` like `ResolverConfig`,
`ResolverOpts` and `ResolveError` are re-exposed
in the API of `libp2p-dns`. Full encapsulation
does not seem preferable in this case.

* Cleanup

* Fix two intra-doc links.

* Simplify slightly.

* Incorporate review feedback.

* Remove git dependency and fix example.

* Update version and changelogs.
  • Loading branch information
romanb authored Mar 16, 2021
1 parent 9dbc90e commit cd15bc9
Show file tree
Hide file tree
Showing 12 changed files with 334 additions and 211 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@

## Version 0.36.0 [unreleased]

- Consolidate top-level utility functions for constructing development
transports. There is now just `development_transport()` (available with default features)
and `tokio_development_transport()` (available when the corresponding tokio features are enabled).
Furthermore, these are now `async fn`s. The minor variations that also included `pnet`
support have been removed.
[PR 1927](https://github.com/libp2p/rust-libp2p/pull/1927)

- Update libp2p crates.

- Do not leak default features from libp2p crates.
Expand Down
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories = ["network-programming", "asynchronous"]
[features]
default = [
"deflate",
"dns",
"dns-async-std",
"floodsub",
"identify",
"kad",
Expand All @@ -33,7 +33,8 @@ default = [
"yamux",
]
deflate = ["libp2p-deflate"]
dns = ["libp2p-dns"]
dns-async-std = ["libp2p-dns", "libp2p-dns/async-std"]
dns-tokio = ["libp2p-dns", "libp2p-dns/tokio"]
floodsub = ["libp2p-floodsub"]
identify = ["libp2p-identify"]
kad = ["libp2p-kad"]
Expand Down Expand Up @@ -88,7 +89,7 @@ wasm-timer = "0.2.4"

[target.'cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))'.dependencies]
libp2p-deflate = { version = "0.27.1", path = "transports/deflate", optional = true }
libp2p-dns = { version = "0.27.0", path = "transports/dns", optional = true }
libp2p-dns = { version = "0.28.0", path = "transports/dns", optional = true, default-features = false }
libp2p-mdns = { version = "0.29.0", path = "protocols/mdns", optional = true }
libp2p-tcp = { version = "0.27.1", path = "transports/tcp", default-features = false, optional = true }
libp2p-websocket = { version = "0.28.0", path = "transports/websocket", optional = true }
Expand Down
5 changes: 3 additions & 2 deletions examples/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ use libp2p::{
};
use std::{error::Error, task::{Context, Poll}};

fn main() -> Result<(), Box<dyn Error>> {
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
env_logger::init();

// Create a random PeerId
Expand All @@ -72,7 +73,7 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("Local peer id: {:?}", local_peer_id);

// Set up a an encrypted DNS-enabled TCP Transport over the Mplex and Yamux protocols
let transport = libp2p::build_development_transport(local_key)?;
let transport = libp2p::development_transport(local_key).await?;

// Create a Floodsub topic
let floodsub_topic = floodsub::Topic::new("chat");
Expand Down
7 changes: 4 additions & 3 deletions examples/distributed-key-value-store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,22 +58,23 @@ use libp2p::{
NetworkBehaviour,
PeerId,
Swarm,
build_development_transport,
development_transport,
identity,
mdns::{Mdns, MdnsConfig, MdnsEvent},
swarm::NetworkBehaviourEventProcess
};
use std::{error::Error, task::{Context, Poll}};

fn main() -> Result<(), Box<dyn Error>> {
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
env_logger::init();

// Create a random key for ourselves.
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());

// Set up a an encrypted DNS-enabled TCP Transport over the Mplex protocol.
let transport = build_development_transport(local_key)?;
let transport = development_transport(local_key).await?;

// We create a custom network behaviour that combines Kademlia and mDNS.
#[derive(NetworkBehaviour)]
Expand Down
5 changes: 3 additions & 2 deletions examples/gossipsub-chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ use std::{
task::{Context, Poll},
};

fn main() -> Result<(), Box<dyn Error>> {
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
Builder::from_env(Env::default().default_filter_or("info")).init();

// Create a random PeerId
Expand All @@ -71,7 +72,7 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("Local peer id: {:?}", local_peer_id);

// Set up an encrypted TCP Transport over the Mplex and Yamux protocols
let transport = libp2p::build_development_transport(local_key.clone())?;
let transport = libp2p::development_transport(local_key.clone()).await?;

// Create a Gossipsub topic
let topic = Topic::new("test-net");
Expand Down
7 changes: 4 additions & 3 deletions examples/ipfs-kad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use libp2p::{
Swarm,
PeerId,
identity,
build_development_transport
development_transport
};
use libp2p::kad::{
Kademlia,
Expand All @@ -40,15 +40,16 @@ use libp2p::kad::{
use libp2p::kad::record::store::MemoryStore;
use std::{env, error::Error, time::Duration};

fn main() -> Result<(), Box<dyn Error>> {
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
env_logger::init();

// Create a random key for ourselves.
let local_key = identity::Keypair::generate_ed25519();
let local_peer_id = PeerId::from(local_key.public());

// Set up a an encrypted DNS-enabled TCP Transport over the Mplex protocol
let transport = build_development_transport(local_key)?;
let transport = development_transport(local_key).await?;

// Create a swarm to manage peers and events.
let mut swarm = {
Expand Down
2 changes: 1 addition & 1 deletion examples/mdns-passive-discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("Local peer id: {:?}", peer_id);

// Create a transport.
let transport = libp2p::build_development_transport(id_keys)?;
let transport = libp2p::development_transport(id_keys).await?;

// Create an MDNS network behaviour.
let behaviour = Mdns::new(MdnsConfig::default()).await?;
Expand Down
5 changes: 3 additions & 2 deletions examples/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ use futures::{future, prelude::*};
use libp2p::{identity, PeerId, ping::{Ping, PingConfig}, Swarm};
use std::{error::Error, task::{Context, Poll}};

fn main() -> Result<(), Box<dyn Error>> {
#[async_std::main]
async fn main() -> Result<(), Box<dyn Error>> {
env_logger::init();

// Create a random PeerId.
Expand All @@ -52,7 +53,7 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("Local peer id: {:?}", peer_id);

// Create a transport.
let transport = libp2p::build_development_transport(id_keys)?;
let transport = libp2p::development_transport(id_keys).await?;

// Create a ping network behaviour.
//
Expand Down
82 changes: 37 additions & 45 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
//! the dialing to take place and eventually resolve to a connection. Polling
//! futures is typically done through a [tokio] runtime.
//!
//! The easiest way to create a transport is to use [`build_development_transport`].
//! The easiest way to create a transport is to use [`development_transport`].
//! This function provides support for the most common protocols but it is also
//! subject to change over time and should thus not be used in production
//! configurations.
Expand All @@ -65,8 +65,8 @@
//!
//! ```rust
//! let keypair = libp2p::identity::Keypair::generate_ed25519();
//! let _transport = libp2p::build_development_transport(keypair);
//! // _transport.dial(...);
//! let _transport = libp2p::development_transport(keypair);
//! // _transport.await?.dial(...);
//! ```
//!
//! The keypair that is passed as an argument in the above example is used
Expand All @@ -85,7 +85,7 @@
//! Example ([`noise`] + [`yamux`] Protocol Upgrade):
//!
//! ```rust
//! # #[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "noise", feature = "yamux"))] {
//! # #[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "tcp-async-io", feature = "noise", feature = "yamux"))] {
//! use libp2p::{Transport, core::upgrade, tcp::TcpConfig, noise, identity::Keypair, yamux};
//! let tcp = TcpConfig::new();
//! let id_keys = Keypair::generate_ed25519();
Expand Down Expand Up @@ -130,7 +130,7 @@
//! identity of the remote peer of the established connection, which is
//! usually obtained through a transport encryption protocol such as
//! [`noise`] that authenticates the peer. See the implementation of
//! [`build_development_transport`] for an example.
//! [`development_transport`] for an example.
//! 3. Creating a struct that implements the [`NetworkBehaviour`] trait and combines all the
//! desired network behaviours, implementing the event handlers as per the
//! desired application's networking logic.
Expand All @@ -154,9 +154,6 @@
#![doc(html_logo_url = "https://libp2p.io/img/logo_small.png")]
#![doc(html_favicon_url = "https://libp2p.io/img/favicon.png")]

#[cfg(feature = "pnet")]
use libp2p_pnet::{PnetConfig, PreSharedKey};

pub use bytes;
pub use futures;
#[doc(inline)]
Expand All @@ -171,8 +168,8 @@ pub use libp2p_core as core;
#[cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))]
#[doc(inline)]
pub use libp2p_deflate as deflate;
#[cfg(feature = "dns")]
#[cfg_attr(docsrs, doc(cfg(feature = "dns")))]
#[cfg(any(feature = "dns-async-std", feature = "dns-tokio"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "dns-async-std", feature = "dns-tokio"))))]
#[cfg(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")))]
#[doc(inline)]
pub use libp2p_dns as dns;
Expand Down Expand Up @@ -268,35 +265,27 @@ pub use self::simple::SimpleProtocol;
pub use self::swarm::Swarm;
pub use self::transport_ext::TransportExt;

/// Builds a `Transport` that supports the most commonly-used protocols that libp2p supports.
/// Builds a `Transport` based on TCP/IP that supports the most commonly-used features of libp2p:
///
/// * DNS resolution.
/// * Noise protocol encryption.
/// * Websockets.
/// * Both Yamux and Mplex for substream multiplexing.
///
/// All async I/O of the transport is based on `async-std`.
///
/// > **Note**: This `Transport` is not suitable for production usage, as its implementation
/// > reserves the right to support additional protocols or remove deprecated protocols.
#[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))]
#[cfg_attr(docsrs, doc(cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))))]
pub fn build_development_transport(keypair: identity::Keypair)
-> std::io::Result<core::transport::Boxed<(PeerId, core::muxing::StreamMuxerBox)>>
{
build_tcp_ws_noise_mplex_yamux(keypair)
}

/// Builds an implementation of `Transport` that is suitable for usage with the `Swarm`.
///
/// The implementation supports TCP/IP, WebSockets over TCP/IP, noise as the encryption layer,
/// and mplex or yamux as the multiplexing layer.
#[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))]
#[cfg_attr(docsrs, doc(cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))))]
pub fn build_tcp_ws_noise_mplex_yamux(keypair: identity::Keypair)
#[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "tcp-async-io", feature = "dns-async-std", feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))]
#[cfg_attr(docsrs, doc(cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "tcp-async-io", feature = "dns-async-std", feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))))]
pub async fn development_transport(keypair: identity::Keypair)
-> std::io::Result<core::transport::Boxed<(PeerId, core::muxing::StreamMuxerBox)>>
{
let transport = {
#[cfg(feature = "tcp-async-io")]
let tcp = tcp::TcpConfig::new().nodelay(true);
#[cfg(feature = "tcp-tokio")]
let tcp = tcp::TokioTcpConfig::new().nodelay(true);
let transport = dns::DnsConfig::new(tcp)?;
let trans_clone = transport.clone();
transport.or_transport(websocket::WsConfig::new(trans_clone))
let transport = dns::DnsConfig::system(tcp).await?;
let websockets = websocket::WsConfig::new(transport.clone());
transport.or_transport(websockets)
};

let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
Expand All @@ -311,31 +300,34 @@ pub fn build_tcp_ws_noise_mplex_yamux(keypair: identity::Keypair)
.boxed())
}

/// Builds an implementation of `Transport` that is suitable for usage with the `Swarm`.
/// Builds a `Transport` based on TCP/IP that supports the most commonly-used features of libp2p:
///
/// * DNS resolution.
/// * Noise protocol encryption.
/// * Websockets.
/// * Both Yamux and Mplex for substream multiplexing.
///
/// All async I/O of the transport is based on `tokio`.
///
/// The implementation supports TCP/IP, WebSockets over TCP/IP, noise as the encryption layer,
/// and mplex or yamux as the multiplexing layer.
#[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux", feature = "pnet"))]
#[cfg_attr(docsrs, doc(cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), any(feature = "tcp-async-io", feature = "tcp-tokio"), feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux", feature = "pnet"))))]
pub fn build_tcp_ws_pnet_noise_mplex_yamux(keypair: identity::Keypair, psk: PreSharedKey)
/// > **Note**: This `Transport` is not suitable for production usage, as its implementation
/// > reserves the right to support additional protocols or remove deprecated protocols.
#[cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "tcp-tokio", feature = "dns-tokio", feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))]
#[cfg_attr(docsrs, doc(cfg(all(not(any(target_os = "emscripten", target_os = "wasi", target_os = "unknown")), feature = "tcp-tokio", feature = "dns-tokio", feature = "websocket", feature = "noise", feature = "mplex", feature = "yamux"))))]
pub fn tokio_development_transport(keypair: identity::Keypair)
-> std::io::Result<core::transport::Boxed<(PeerId, core::muxing::StreamMuxerBox)>>
{
let transport = {
#[cfg(feature = "tcp-async-io")]
let tcp = tcp::TcpConfig::new().nodelay(true);
#[cfg(feature = "tcp-tokio")]
let tcp = tcp::TokioTcpConfig::new().nodelay(true);
let transport = dns::DnsConfig::new(tcp)?;
let trans_clone = transport.clone();
transport.or_transport(websocket::WsConfig::new(trans_clone))
let transport = dns::TokioDnsConfig::system(tcp)?;
let websockets = websocket::WsConfig::new(transport.clone());
transport.or_transport(websockets)
};

let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
.into_authentic(&keypair)
.expect("Signing libp2p-noise static DH keypair failed.");

Ok(transport
.and_then(move |socket, _| PnetConfig::new(psk).handshake(socket))
.upgrade(core::upgrade::Version::V1)
.authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
.multiplex(core::upgrade::SelectUpgrade::new(yamux::YamuxConfig::default(), mplex::MplexConfig::default()))
Expand Down
7 changes: 7 additions & 0 deletions transports/dns/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 0.28.0 [unreleased]

- Use `trust-dns-resolver`, removing the internal thread pool and
expanding the configurability of `libp2p-dns` by largely exposing the
configuration of `trust-dns-resolver`.
[PR 1927](https://github.com/libp2p/rust-libp2p/pull/1927)

# 0.27.0 [2021-01-12]

- Update dependencies.
Expand Down
20 changes: 19 additions & 1 deletion transports/dns/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "libp2p-dns"
edition = "2018"
description = "DNS transport implementation for libp2p"
version = "0.27.0"
version = "0.28.0"
authors = ["Parity Technologies <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
Expand All @@ -13,3 +13,21 @@ categories = ["network-programming", "asynchronous"]
libp2p-core = { version = "0.27.0", path = "../../core" }
log = "0.4.1"
futures = "0.3.1"
trust-dns-resolver = { version = "0.20", default-features = false, features = ["system-config"] }
async-std-resolver = { version = "0.20", optional = true }

[dev-dependencies]
env_logger = "0.6"
tokio-crate = { package = "tokio", version = "1.0", default-features = false, features = ["rt", "time"] }
async-std-crate = { package = "async-std", version = "1.6" }

[features]
default = ["async-std"]
async-std = ["async-std-resolver"]
tokio = ["trust-dns-resolver/tokio-runtime"]
# The `tokio-` prefix and feature dependency is just to be explicit,
# since these features of `trust-dns-resolver` are currently only
# available for `tokio`.
tokio-dns-over-rustls = ["tokio", "trust-dns-resolver/dns-over-rustls"]
tokio-dns-over-https-rustls = ["tokio", "trust-dns-resolver/dns-over-https-rustls"]

Loading

0 comments on commit cd15bc9

Please sign in to comment.