Skip to content

Commit

Permalink
client: add WebRTC transport
Browse files Browse the repository at this point in the history
warning: uses my fork of libp2p and webrtc-rs library
Impl: libp2p/rust-libp2p#2622
Spec: libp2p/specs#412

Refs paritytech/smoldot#1712
  • Loading branch information
melekes committed Jun 30, 2022
1 parent 0fbf917 commit 6cf708f
Show file tree
Hide file tree
Showing 15 changed files with 2,164 additions and 1,480 deletions.
3,539 changes: 2,076 additions & 1,463 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Expand Up @@ -305,3 +305,8 @@ inherits = "release"
lto = "fat"
# https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units
codegen-units = 1

# TODO: remove
[patch.crates-io]
libp2p = { version = "0.46.0", git = "https://github.com/melekes/rust-libp2p.git", branch = "anton/webrtc-transport" }
multiaddr = { version = "0.14.0", git = "https://github.com/melekes/rust-multiaddr.git", branch = "anton/x-webrtc" }
2 changes: 1 addition & 1 deletion client/authority-discovery/Cargo.toml
Expand Up @@ -22,7 +22,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", default-features =
futures = "0.3.21"
futures-timer = "3.0.1"
ip_network = "0.4.1"
libp2p = { version = "0.45.1", default-features = false, features = ["kad"] }
libp2p = { version = "0.46.0", default-features = false, features = ["kad"] }
log = "0.4.17"
prost = "0.10"
rand = "0.7.2"
Expand Down
2 changes: 1 addition & 1 deletion client/cli/Cargo.toml
Expand Up @@ -18,7 +18,7 @@ clap = { version = "3.1.18", features = ["derive"] }
fdlimit = "0.2.1"
futures = "0.3.21"
hex = "0.4.2"
libp2p = "0.45.1"
libp2p = "0.46.0"
log = "0.4.17"
names = { version = "0.13.0", default-features = false }
parity-scale-codec = "3.0.0"
Expand Down
2 changes: 1 addition & 1 deletion client/consensus/common/Cargo.toml
Expand Up @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
async-trait = "0.1.42"
futures = { version = "0.3.21", features = ["thread-pool"] }
futures-timer = "3.0.1"
libp2p = { version = "0.45.1", default-features = false }
libp2p = { version = "0.46.0", default-features = false }
log = "0.4.17"
parking_lot = "0.12.0"
serde = { version = "1.0", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion client/network-gossip/Cargo.toml
Expand Up @@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu"]
ahash = "0.7.6"
futures = "0.3.21"
futures-timer = "3.0.1"
libp2p = { version = "0.45.1", default-features = false }
libp2p = { version = "0.46.0", default-features = false }
log = "0.4.17"
lru = "0.7.5"
tracing = "0.1.29"
Expand Down
5 changes: 4 additions & 1 deletion client/network/Cargo.toml
Expand Up @@ -29,7 +29,7 @@ futures = "0.3.21"
futures-timer = "3.0.2"
hex = "0.4.0"
ip_network = "0.4.1"
libp2p = "0.45.1"
libp2p = { version = "0.46.0", features = ["webrtc"] }
linked_hash_set = "0.1.3"
linked-hash-map = "0.5.4"
log = "0.4.17"
Expand Down Expand Up @@ -62,6 +62,9 @@ sp-core = { version = "6.0.0", path = "../../primitives/core" }
sp-finality-grandpa = { version = "4.0.0-dev", path = "../../primitives/finality-grandpa" }
sp-runtime = { version = "6.0.0", path = "../../primitives/runtime" }

webrtc = { version = "0.4.0", git = "https://github.com/melekes/webrtc.git", branch = "anton/168-allow-persistent-certificates-plus-deps" }
rcgen = "0.9.2"

[dev-dependencies]
assert_matches = "1.3"
async-std = "1.11.0"
Expand Down
2 changes: 1 addition & 1 deletion client/network/common/Cargo.toml
Expand Up @@ -21,6 +21,6 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [
"derive",
] }
futures = "0.3.21"
libp2p = "0.45.1"
libp2p = "0.46.0"
smallvec = "1.8.0"
sc-peerset = { version = "4.0.0-dev", path = "../../peerset" }
2 changes: 1 addition & 1 deletion client/network/light/Cargo.toml
Expand Up @@ -21,7 +21,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [
"derive",
] }
futures = "0.3.21"
libp2p = "0.45.1"
libp2p = "0.46.0"
log = "0.4.16"
prost = "0.10"
sp-blockchain = { version = "4.0.0-dev", path = "../../../primitives/blockchain" }
Expand Down
19 changes: 19 additions & 0 deletions client/network/src/service.rs
Expand Up @@ -343,6 +343,10 @@ where
config_mem,
params.network_config.yamux_window_size,
yamux_maximum_buffer_size,
webrtc_listen_address(
params.network_config.listen_addresses.iter(),
&params.network_config.transport,
),
)
};

Expand Down Expand Up @@ -2255,3 +2259,18 @@ fn ensure_addresses_consistent_with_transport<'a>(

Ok(())
}

/// Returns the first WebRTC [`Multiaddr`] or `None`, if there are no such addresses or memory-only
/// transport is being used.
fn webrtc_listen_address<'a>(
addresses: impl Iterator<Item = &'a Multiaddr>,
transport: &TransportConfig,
) -> Option<Multiaddr> {
if matches!(transport, TransportConfig::MemoryOnly) {
None
} else {
return addresses
.filter(|x| x.iter().any(|y| matches!(y,
libp2p::core::multiaddr::Protocol::XWebRTC(_)))).cloned().next()
}
}
56 changes: 50 additions & 6 deletions client/network/src/transport.rs
Expand Up @@ -25,12 +25,41 @@ use libp2p::{
transport::{Boxed, OptionalTransport},
upgrade,
},
dns, identity, mplex, noise, tcp, websocket, PeerId, Transport,
dns, identity, mplex, noise, tcp, webrtc as webrtc_p2p, websocket, Multiaddr, PeerId,
Transport,
};
use std::{sync::Arc, time::Duration};

use libp2p::multiaddr::Protocol;
use std::net::SocketAddr;
use webrtc::peer_connection::certificate::RTCCertificate;

pub use self::bandwidth::BandwidthSinks;

// TODO: implement Into<SocketAddr> for Multiaddr and remove this.
fn multiaddr_to_socketaddr(addr: &Multiaddr) -> Option<SocketAddr> {
let mut iter = addr.iter();
let proto1 = iter.next()?;
let proto2 = iter.next()?;
let proto3 = iter.next()?;

for proto in iter {
match proto {
Protocol::P2p(_) => {}, /* Ignore a `/p2p/...` prefix of possibly outer protocols, */
// if present.
_ => return None,
}
}

match (proto1, proto2, proto3) {
(Protocol::Ip4(ip), Protocol::Udp(port), Protocol::XWebRTC(_)) =>
Some(SocketAddr::new(ip.into(), port)),
(Protocol::Ip6(ip), Protocol::Udp(port), Protocol::XWebRTC(_)) =>
Some(SocketAddr::new(ip.into(), port)),
_ => None,
}
}

/// Builds the transport that serves as a common ground for all connections.
///
/// If `memory_only` is true, then only communication within the same process are allowed. Only
Expand All @@ -46,11 +75,12 @@ pub use self::bandwidth::BandwidthSinks;
///
/// Returns a `BandwidthSinks` object that allows querying the average bandwidth produced by all
/// the connections spawned with this transport.
pub fn build_transport(
pub fn build_transport<'a>(
keypair: identity::Keypair,
memory_only: bool,
yamux_window_size: Option<u32>,
yamux_maximum_buffer_size: usize,
webrtc_listen_address: Option<Multiaddr>,
) -> (Boxed<(PeerId, StreamMuxerBox)>, Arc<BandwidthSinks>) {
// Build the base layer of the transport.
let transport = if !memory_only {
Expand Down Expand Up @@ -115,8 +145,22 @@ pub fn build_transport(
.upgrade(upgrade::Version::V1Lazy)
.authenticate(authentication_config)
.multiplex(multiplexing_config)
.timeout(Duration::from_secs(20))
.boxed();

(transport, bandwidth)
.timeout(Duration::from_secs(20));

if let Some(listen_addr) = webrtc_listen_address {
// TODO: make `cert` an argument
let kp = rcgen::KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256).expect("key pair");
let cert = RTCCertificate::from_key_pair(kp).expect("certificate");
let webrtc_transport =
futures::executor::block_on(webrtc_p2p::transport::WebRTCTransport::new(
cert,
keypair,
multiaddr_to_socketaddr(&listen_addr).unwrap(),
))
.unwrap();
// TODO: use or_transport
(webrtc_transport.boxed(), bandwidth)
} else {
(transport.boxed(), bandwidth)
}
}
2 changes: 1 addition & 1 deletion client/network/sync/Cargo.toml
Expand Up @@ -23,7 +23,7 @@ codec = { package = "parity-scale-codec", version = "3.0.0", features = [
] }
either = "1.5.3"
futures = "0.3.21"
libp2p = "0.45.1"
libp2p = "0.46.0"
log = "0.4.17"
lru = "0.7.5"
prost = "0.10"
Expand Down
2 changes: 1 addition & 1 deletion client/network/test/Cargo.toml
Expand Up @@ -17,7 +17,7 @@ async-std = "1.11.0"
async-trait = "0.1.50"
futures = "0.3.21"
futures-timer = "3.0.1"
libp2p = { version = "0.45.1", default-features = false }
libp2p = { version = "0.46.0", default-features = false }
log = "0.4.17"
parking_lot = "0.12.0"
rand = "0.7.2"
Expand Down
2 changes: 1 addition & 1 deletion client/peerset/Cargo.toml
Expand Up @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
futures = "0.3.21"
libp2p = { version = "0.45.1", default-features = false }
libp2p = { version = "0.46.0", default-features = false }
log = "0.4.17"
serde_json = "1.0.79"
wasm-timer = "0.2"
Expand Down
2 changes: 1 addition & 1 deletion client/telemetry/Cargo.toml
Expand Up @@ -16,7 +16,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
chrono = "0.4.19"
futures = "0.3.21"
libp2p = { version = "0.45.1", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] }
libp2p = { version = "0.46.0", default-features = false, features = ["dns-async-std", "tcp-async-io", "wasm-ext", "websocket"] }
log = "0.4.17"
parking_lot = "0.12.0"
pin-project = "1.0.10"
Expand Down

0 comments on commit 6cf708f

Please sign in to comment.