mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-12 09:31:20 +00:00
feat(quic): implement hole punching
Implement `Transport::dial_as_listener` for QUIC as specified by the [DCUtR spec](https://github.com/libp2p/specs/blob/master/relay/DCUtR.md). To facilitate hole punching in QUIC, one side needs to send random UDP packets to establish a mapping in the routing table of the NAT device. If successful, our listener will emit a new inbound connection. This connection needs to then be sent to the dialing task. We achieve this by storing a `HashMap` of hole punch attempts indexed by the remote's `SocketAddr`. A matching incoming connection is then sent via a oneshot channel to the dialing task which continues with upgrading the connection. Related #2883. Pull-Request: #3964.
This commit is contained in:
@ -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"] }
|
||||
|
@ -22,10 +22,11 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
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,
|
||||
@ -34,6 +35,7 @@ use libp2p::{
|
||||
swarm::{NetworkBehaviour, SwarmBuilder, SwarmEvent},
|
||||
tcp,
|
||||
};
|
||||
use libp2p_quic as quic;
|
||||
use std::error::Error;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
@ -50,12 +52,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 {
|
||||
@ -70,13 +81,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 {
|
||||
|
Reference in New Issue
Block a user