Skip to content

Commit

Permalink
protocols/: Implement Direct Connection Upgrade through Relay (DCUtR) (
Browse files Browse the repository at this point in the history
…#2438)

Enables two peers to coordinate a hole punch (direct connection upgrade)
via a relayed connection.

See https://github.com/libp2p/specs/blob/master/relay/DCUtR.md for
specification.
  • Loading branch information
mxinden committed Feb 8, 2022
1 parent bd41e04 commit 0bb8ee9
Show file tree
Hide file tree
Showing 19 changed files with 2,111 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ default = [
"yamux",
]
autonat = ["libp2p-autonat"]
dcutr = ["libp2p-dcutr", "libp2p-metrics/dcutr"]
deflate = ["libp2p-deflate"]
dns-async-std = ["libp2p-dns", "libp2p-dns/async-std"]
dns-tokio = ["libp2p-dns", "libp2p-dns/tokio"]
Expand Down Expand Up @@ -78,6 +79,7 @@ lazy_static = "1.2"

libp2p-autonat = { version = "0.2.0", path = "protocols/autonat", optional = true }
libp2p-core = { version = "0.32.0", path = "core", default-features = false }
libp2p-dcutr = { version = "0.1.0", path = "protocols/dcutr", optional = true }
libp2p-floodsub = { version = "0.34.0", path = "protocols/floodsub", optional = true }
libp2p-gossipsub = { version = "0.36.0", path = "./protocols/gossipsub", optional = true }
libp2p-identify = { version = "0.34.0", path = "protocols/identify", optional = true }
Expand Down Expand Up @@ -124,6 +126,7 @@ members = [
"misc/peer-id-generator",
"muxers/mplex",
"muxers/yamux",
"protocols/dcutr",
"protocols/autonat",
"protocols/floodsub",
"protocols/gossipsub",
Expand Down
2 changes: 2 additions & 0 deletions misc/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ identify = ["libp2p-identify"]
kad = ["libp2p-kad"]
ping = ["libp2p-ping"]
relay = ["libp2p-relay"]
dcutr = ["libp2p-dcutr"]

[dependencies]
libp2p-core = { version = "0.32.0", path = "../../core", default-features = false }
libp2p-dcutr = { version = "0.1.0", path = "../../protocols/dcutr", optional = true }
libp2p-gossipsub = { version = "0.36.0", path = "../../protocols/gossipsub", optional = true }
libp2p-identify = { version = "0.34.0", path = "../../protocols/identify", optional = true }
libp2p-kad = { version = "0.35.0", path = "../../protocols/kad", optional = true }
Expand Down
89 changes: 89 additions & 0 deletions misc/metrics/src/dcutr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2021 Protocol Labs.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use prometheus_client::encoding::text::Encode;
use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
use prometheus_client::registry::Registry;

pub struct Metrics {
events: Family<EventLabels, Counter>,
}

impl Metrics {
pub fn new(registry: &mut Registry) -> Self {
let sub_registry = registry.sub_registry_with_prefix("relay");

let events = Family::default();
sub_registry.register(
"events",
"Events emitted by the relay NetworkBehaviour",
Box::new(events.clone()),
);

Self { events }
}
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, Encode)]
struct EventLabels {
event: EventType,
}

#[derive(Debug, Clone, Hash, PartialEq, Eq, Encode)]
enum EventType {
InitiateDirectConnectionUpgrade,
RemoteInitiatedDirectConnectionUpgrade,
DirectConnectionUpgradeSucceeded,
DirectConnectionUpgradeFailed,
}

impl From<&libp2p_dcutr::behaviour::Event> for EventType {
fn from(event: &libp2p_dcutr::behaviour::Event) -> Self {
match event {
libp2p_dcutr::behaviour::Event::InitiatedDirectConnectionUpgrade {
remote_peer_id: _,
local_relayed_addr: _,
} => EventType::InitiateDirectConnectionUpgrade,
libp2p_dcutr::behaviour::Event::RemoteInitiatedDirectConnectionUpgrade {
remote_peer_id: _,
remote_relayed_addr: _,
} => EventType::RemoteInitiatedDirectConnectionUpgrade,
libp2p_dcutr::behaviour::Event::DirectConnectionUpgradeSucceeded {
remote_peer_id: _,
} => EventType::DirectConnectionUpgradeSucceeded,
libp2p_dcutr::behaviour::Event::DirectConnectionUpgradeFailed {
remote_peer_id: _,
error: _,
} => EventType::DirectConnectionUpgradeFailed,
}
}
}

impl super::Recorder<libp2p_dcutr::behaviour::Event> for super::Metrics {
fn record(&self, event: &libp2p_dcutr::behaviour::Event) {
self.dcutr
.events
.get_or_create(&EventLabels {
event: event.into(),
})
.inc();
}
}
6 changes: 6 additions & 0 deletions misc/metrics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
//!
//! See `examples` directory for more.

#[cfg(feature = "dcutr")]
mod dcutr;
#[cfg(feature = "gossipsub")]
mod gossipsub;
#[cfg(feature = "identify")]
Expand All @@ -41,6 +43,8 @@ use prometheus_client::registry::Registry;

/// Set of Swarm and protocol metrics derived from emitted events.
pub struct Metrics {
#[cfg(feature = "dcutr")]
dcutr: dcutr::Metrics,
#[cfg(feature = "gossipsub")]
gossipsub: gossipsub::Metrics,
#[cfg(feature = "identify")]
Expand All @@ -66,6 +70,8 @@ impl Metrics {
pub fn new(registry: &mut Registry) -> Self {
let sub_registry = registry.sub_registry_with_prefix("libp2p");
Self {
#[cfg(feature = "dcutr")]
dcutr: dcutr::Metrics::new(sub_registry),
#[cfg(feature = "gossipsub")]
gossipsub: gossipsub::Metrics::new(sub_registry),
#[cfg(feature = "identify")]
Expand Down
39 changes: 39 additions & 0 deletions protocols/dcutr/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "libp2p-dcutr"
edition = "2021"
rust-version = "1.56.1"
description = "Direct connection upgrade through relay"
version = "0.1.0"
authors = ["Max Inden <[email protected]>"]
license = "MIT"
repository = "https://github.com/libp2p/rust-libp2p"
keywords = ["peer-to-peer", "libp2p", "networking"]
categories = ["network-programming", "asynchronous"]

[dependencies]
asynchronous-codec = "0.6"
bytes = "1"
either = "1.6.0"
futures = "0.3.1"
futures-timer = "3.0"
instant = "0.1.11"
libp2p-core = { version = "0.32", path = "../../core" }
libp2p-swarm = { version = "0.34", path = "../../swarm" }
log = "0.4"
prost = "0.7"
thiserror = "1.0"
unsigned-varint = { version = "0.7", features = ["asynchronous_codec"] }
void = "1"

[build-dependencies]
prost-build = "0.7"

[dev-dependencies]
env_logger = "0.8.3"
libp2p = { path = "../..", features = ["dcutr"] }
libp2p-identify = { path = "../identify" }
libp2p-plaintext = { path = "../../transports/plaintext" }
libp2p-relay = { path = "../relay" }
libp2p-yamux = { path = "../../muxers/yamux" }
rand = "0.7"
structopt = "0.3.21"
23 changes: 23 additions & 0 deletions protocols/dcutr/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2021 Protocol Labs.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

fn main() {
prost_build::compile_protos(&["src/message.proto"], &["src"]).unwrap();
}
Loading

0 comments on commit 0bb8ee9

Please sign in to comment.