Skip to content

Commit

Permalink
Add hole punching examples
Browse files Browse the repository at this point in the history
  • Loading branch information
arpankapoor authored and kpp committed May 24, 2023
1 parent c48b8e6 commit add3fdd
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 78 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions examples/dcutr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ env_logger = "0.10.0"
futures = "0.3.28"
futures-timer = "3.0"
libp2p = { path = "../../libp2p", features = ["async-std", "dns", "dcutr", "identify", "macros", "noise", "ping", "relay", "rendezvous", "tcp", "tokio", "yamux"] }
libp2p-quic = { path = "../../transports/quic", features = ["async-std"] }
log = "0.4"
69 changes: 46 additions & 23 deletions examples/dcutr/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
use clap::Parser;
use futures::{
executor::{block_on, ThreadPool},
future::FutureExt,
future::{Either, FutureExt},
stream::StreamExt,
};
use libp2p::{
core::{
multiaddr::{Multiaddr, Protocol},
muxing::StreamMuxerBox,
transport::{OrTransport, Transport},
upgrade,
},
Expand All @@ -36,6 +37,7 @@ use libp2p::{
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp, yamux, PeerId,
};
use libp2p_quic as quic;
use log::info;
use std::error::Error;
use std::net::Ipv4Addr;
Expand Down Expand Up @@ -85,23 +87,44 @@ fn main() -> Result<(), Box<dyn Error>> {

let local_key = generate_ed25519(opts.secret_key_seed);
let local_peer_id = PeerId::from(local_key.public());
info!("Local peer id: {:?}", local_peer_id);
println!("Local peer id: {:?}", local_peer_id);

let (relay_transport, client) = relay::client::new(local_peer_id);

let transport = OrTransport::new(
relay_transport,
block_on(DnsConfig::system(tcp::async_io::Transport::new(
tcp::Config::default().port_reuse(true),
)))
.unwrap(),
)
.upgrade(upgrade::Version::V1Lazy)
.authenticate(
noise::Config::new(&local_key).expect("Signing libp2p-noise static DH keypair failed."),
)
.multiplex(yamux::Config::default())
.boxed();
let is_quic_relay = opts.relay_address.iter().any(|p| p == Protocol::QuicV1);
let transport = if is_quic_relay {
let relay_transport = relay_transport
.upgrade(upgrade::Version::V1)
.authenticate(noise::Config::new(&local_key).unwrap())
.multiplex(yamux::Config::default());

OrTransport::new(
relay_transport,
block_on(DnsConfig::system(quic::async_std::Transport::new(
quic::Config::new(&local_key),
)))
.unwrap(),
)
.map(|either_output, _| match either_output {
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
})
.boxed()
} else {
OrTransport::new(
relay_transport,
block_on(DnsConfig::system(tcp::async_io::Transport::new(
tcp::Config::default().port_reuse(true),
)))
.unwrap(),
)
.upgrade(upgrade::Version::V1Lazy)
.authenticate(
noise::Config::new(&local_key).expect("Signing libp2p-noise static DH keypair failed."),
)
.multiplex(yamux::Config::default())
.boxed()
};

#[derive(NetworkBehaviour)]
#[behaviour(to_swarm = "Event", event_process = false)]
Expand Down Expand Up @@ -161,13 +184,13 @@ fn main() -> Result<(), Box<dyn Error>> {
}
.build();

swarm
.listen_on(
Multiaddr::empty()
.with("0.0.0.0".parse::<Ipv4Addr>().unwrap().into())
.with(Protocol::Tcp(0)),
)
.unwrap();
let listen_addr = Multiaddr::empty().with("0.0.0.0".parse::<Ipv4Addr>().unwrap().into());
let listen_addr = if is_quic_relay {
listen_addr.with(Protocol::Udp(0)).with(Protocol::QuicV1)
} else {
listen_addr.with(Protocol::Tcp(0))
};
swarm.listen_on(listen_addr).unwrap();

// Wait to listen on all interfaces.
block_on(async {
Expand All @@ -177,7 +200,7 @@ fn main() -> Result<(), Box<dyn Error>> {
event = swarm.next() => {
match event.unwrap() {
SwarmEvent::NewListenAddr { address, .. } => {
info!("Listening on {:?}", address);
println!("Listening on {:?}", address);
}
event => panic!("{event:?}"),
}
Expand Down
1 change: 1 addition & 0 deletions examples/relay-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ async-trait = "0.1"
env_logger = "0.10.0"
futures = "0.3.28"
libp2p = { path = "../../libp2p", features = ["async-std", "noise", "macros", "ping", "tcp", "identify", "yamux", "relay"] }
libp2p-quic = { path = "../../transports/quic", features = ["async-std"] }
30 changes: 25 additions & 5 deletions examples/relay-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
// DEALINGS IN THE SOFTWARE.

use clap::Parser;
use futures::executor::block_on;
use futures::stream::StreamExt;
use futures::{executor::block_on, future::Either};
use libp2p::{
core::multiaddr::Protocol,
core::muxing::StreamMuxerBox,
core::upgrade,
core::{Multiaddr, Transport},
identify, identity,
Expand All @@ -32,6 +33,7 @@ use libp2p::{
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
tcp,
};
use libp2p_quic as quic;
use std::error::Error;
use std::net::{Ipv4Addr, Ipv6Addr};

Expand All @@ -48,12 +50,21 @@ fn main() -> Result<(), Box<dyn Error>> {

let tcp_transport = tcp::async_io::Transport::default();

let transport = tcp_transport
let tcp_transport = tcp_transport
.upgrade(upgrade::Version::V1Lazy)
.authenticate(
noise::Config::new(&local_key).expect("Signing libp2p-noise static DH keypair failed."),
)
.multiplex(libp2p::yamux::Config::default())
.multiplex(libp2p::yamux::Config::default());

let quic_transport = quic::async_std::Transport::new(quic::Config::new(&local_key));

let transport = quic_transport
.or_transport(tcp_transport)
.map(|either_output, _| match either_output {
Either::Left((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
Either::Right((peer_id, muxer)) => (peer_id, StreamMuxerBox::new(muxer)),
})
.boxed();

let behaviour = Behaviour {
Expand All @@ -68,13 +79,22 @@ fn main() -> Result<(), Box<dyn Error>> {
let mut swarm = SwarmBuilder::without_executor(transport, behaviour, local_peer_id).build();

// Listen on all interfaces
let listen_addr = Multiaddr::empty()
let listen_addr_tcp = Multiaddr::empty()
.with(match opt.use_ipv6 {
Some(true) => Protocol::from(Ipv6Addr::UNSPECIFIED),
_ => Protocol::from(Ipv4Addr::UNSPECIFIED),
})
.with(Protocol::Tcp(opt.port));
swarm.listen_on(listen_addr)?;
swarm.listen_on(listen_addr_tcp)?;

let listen_addr_quic = Multiaddr::empty()
.with(match opt.use_ipv6 {
Some(true) => Protocol::from(Ipv6Addr::UNSPECIFIED),
_ => Protocol::from(Ipv4Addr::UNSPECIFIED),
})
.with(Protocol::Udp(opt.port))
.with(Protocol::QuicV1);
swarm.listen_on(listen_addr_quic)?;

block_on(async {
loop {
Expand Down
82 changes: 32 additions & 50 deletions protocols/dcutr/src/behaviour_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,32 +246,23 @@ impl NetworkBehaviour for Behaviour {
local_addr: &Multiaddr,
remote_addr: &Multiaddr,
) -> Result<THandler<Self>, ConnectionDenied> {
match self
.outgoing_direct_connection_attempts
.remove(&(connection_id, peer))
if is_relayed(local_addr) {
Ok(Either::Left(handler::relayed::Handler::new(
ConnectedPoint::Listener {
local_addr: local_addr.clone(),
send_back_addr: remote_addr.clone(),
},
))) // TODO: We could make two `handler::relayed::Handler` here, one inbound one outbound.
} else if let Some(&relayed_connection_id) =
self.direct_to_relayed_connections.get(&connection_id)
{
None => {
let handler = if is_relayed(local_addr) {
Either::Left(handler::relayed::Handler::new(ConnectedPoint::Listener {
local_addr: local_addr.clone(),
send_back_addr: remote_addr.clone(),
})) // TODO: We could make two `handler::relayed::Handler` here, one inbound one outbound.
} else {
Either::Right(Either::Right(dummy::ConnectionHandler))
};

Ok(handler)
}
Some(_) => {
assert!(
!is_relayed(local_addr),
"`Prototype::DirectConnection` is never created for relayed connection."
);

Ok(Either::Right(Either::Left(
handler::direct::Handler::default(),
)))
}
self.outgoing_direct_connection_attempts
.remove(&(relayed_connection_id, peer));
Ok(Either::Right(Either::Left(
handler::direct::Handler::default(),
)))
} else {
Ok(Either::Right(Either::Right(dummy::ConnectionHandler)))
}
}

Expand All @@ -282,32 +273,23 @@ impl NetworkBehaviour for Behaviour {
addr: &Multiaddr,
role_override: Endpoint,
) -> Result<THandler<Self>, ConnectionDenied> {
match self
.outgoing_direct_connection_attempts
.remove(&(connection_id, peer))
if is_relayed(addr) {
Ok(Either::Left(handler::relayed::Handler::new(
ConnectedPoint::Dialer {
address: addr.clone(),
role_override,
},
))) // TODO: We could make two `handler::relayed::Handler` here, one inbound one outbound.
} else if let Some(&relayed_connection_id) =
self.direct_to_relayed_connections.get(&connection_id)
{
None => {
let handler = if is_relayed(addr) {
Either::Left(handler::relayed::Handler::new(ConnectedPoint::Dialer {
address: addr.clone(),
role_override,
})) // TODO: We could make two `handler::relayed::Handler` here, one inbound one outbound.
} else {
Either::Right(Either::Right(dummy::ConnectionHandler))
};

Ok(handler)
}
Some(_) => {
assert!(
!is_relayed(addr),
"`Prototype::DirectConnection` is never created for relayed connection."
);

Ok(Either::Right(Either::Left(
handler::direct::Handler::default(),
)))
}
self.outgoing_direct_connection_attempts
.remove(&(relayed_connection_id, peer));
Ok(Either::Right(Either::Left(
handler::direct::Handler::default(),
)))
} else {
Ok(Either::Right(Either::Right(dummy::ConnectionHandler)))
}
}

Expand Down

0 comments on commit add3fdd

Please sign in to comment.