diff --git a/Cargo.lock b/Cargo.lock index 2cf8332a7cd..5f5026f1afc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3058,7 +3058,7 @@ dependencies = [ [[package]] name = "libp2p-quic" -version = "0.9.0-alpha" +version = "0.9.1-alpha" dependencies = [ "async-std", "bytes", @@ -3079,6 +3079,7 @@ dependencies = [ "quinn", "rand 0.8.5", "rustls 0.21.5", + "socket2 0.5.3", "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index b2d30c9257d..6b4bd5ebe09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,7 +85,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" } libp2p-ping = { version = "0.43.0", path = "protocols/ping" } libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" } libp2p-pnet = { version = "0.23.0", path = "transports/pnet" } -libp2p-quic = { version = "0.9.0-alpha", path = "transports/quic" } +libp2p-quic = { version = "0.9.1-alpha", path = "transports/quic" } libp2p-relay = { version = "0.16.1", path = "protocols/relay" } libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" } libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" } diff --git a/transports/quic/CHANGELOG.md b/transports/quic/CHANGELOG.md index 11ee1e63394..7e0c09a1511 100644 --- a/transports/quic/CHANGELOG.md +++ b/transports/quic/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.9.1-alpha - unreleased + +- Allow listening on ipv4 and ipv6 separately. + See [PR 4289]. + +[PR 4289]: https://github.com/libp2p/rust-libp2p/pull/4289 + ## 0.9.0-alpha - Use `quinn` instead of `quinn-proto`. diff --git a/transports/quic/Cargo.toml b/transports/quic/Cargo.toml index 5d810860912..67f131aeb31 100644 --- a/transports/quic/Cargo.toml +++ b/transports/quic/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libp2p-quic" -version = "0.9.0-alpha" +version = "0.9.1-alpha" authors = ["Parity Technologies "] edition = "2021" rust-version = { workspace = true } @@ -24,6 +24,7 @@ rand = "0.8.5" rustls = { version = "0.21.2", default-features = false } thiserror = "1.0.44" tokio = { version = "1.29.1", default-features = false, features = ["net", "rt", "time"], optional = true } +socket2 = "0.5.3" [features] tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"] diff --git a/transports/quic/src/transport.rs b/transports/quic/src/transport.rs index d4a1db35604..7e0a4a812f7 100644 --- a/transports/quic/src/transport.rs +++ b/transports/quic/src/transport.rs @@ -37,12 +37,13 @@ use libp2p_core::{ Transport, }; use libp2p_identity::PeerId; +use socket2::{Domain, Socket, Type}; use std::collections::hash_map::{DefaultHasher, Entry}; use std::collections::HashMap; -use std::fmt; use std::hash::{Hash, Hasher}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket}; use std::time::Duration; +use std::{fmt, io}; use std::{ net::SocketAddr, pin::Pin, @@ -172,6 +173,21 @@ impl GenTransport

{ } } } + + fn create_socket(&self, socket_addr: SocketAddr) -> io::Result { + let socket = Socket::new( + Domain::for_address(socket_addr), + Type::DGRAM, + Some(socket2::Protocol::UDP), + )?; + if socket_addr.is_ipv6() { + socket.set_only_v6(true)?; + } + + socket.bind(&socket_addr.into())?; + + Ok(socket.into()) + } } impl Transport for GenTransport

{ @@ -188,7 +204,8 @@ impl Transport for GenTransport

{ let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?; let endpoint_config = self.quinn_config.endpoint_config.clone(); let server_config = self.quinn_config.server_config.clone(); - let socket = UdpSocket::bind(socket_addr).map_err(Self::Error::from)?; + let socket = self.create_socket(socket_addr).map_err(Self::Error::from)?; + let socket_c = socket.try_clone().map_err(Self::Error::from)?; let endpoint = Self::new_endpoint(endpoint_config, Some(server_config), socket)?; let listener = Listener::new( @@ -888,4 +905,25 @@ mod test { .unwrap(); assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4)); } + + #[cfg(feature = "tokio")] + #[tokio::test] + async fn test_listens_ipv4_ipv6_separately() { + let keypair = libp2p_identity::Keypair::generate_ed25519(); + let config = Config::new(&keypair); + let mut transport = crate::tokio::Transport::new(config); + + transport + .listen_on( + ListenerId::next(), + "/ip4/0.0.0.0/udp/4001/quic-v1".parse().unwrap(), + ) + .unwrap(); + transport + .listen_on( + ListenerId::next(), + "/ip6/::/udp/4001/quic-v1".parse().unwrap(), + ) + .unwrap(); + } }