Skip to content

Commit 02dc432

Browse files
authored
fix(quic): allow listening on ipv4 and ipv6 separately
Resolves #4165. Pull-Request: #4289.
1 parent b5d9932 commit 02dc432

5 files changed

Lines changed: 52 additions & 5 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ libp2p-perf = { version = "0.2.0", path = "protocols/perf" }
8585
libp2p-ping = { version = "0.43.0", path = "protocols/ping" }
8686
libp2p-plaintext = { version = "0.40.0", path = "transports/plaintext" }
8787
libp2p-pnet = { version = "0.23.0", path = "transports/pnet" }
88-
libp2p-quic = { version = "0.9.0-alpha", path = "transports/quic" }
88+
libp2p-quic = { version = "0.9.1-alpha", path = "transports/quic" }
8989
libp2p-relay = { version = "0.16.1", path = "protocols/relay" }
9090
libp2p-rendezvous = { version = "0.13.0", path = "protocols/rendezvous" }
9191
libp2p-request-response = { version = "0.25.1", path = "protocols/request-response" }

transports/quic/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 0.9.1-alpha - unreleased
2+
3+
- Allow listening on ipv4 and ipv6 separately.
4+
See [PR 4289].
5+
6+
[PR 4289]: https://github.com/libp2p/rust-libp2p/pull/4289
7+
18
## 0.9.0-alpha
29

310
- Use `quinn` instead of `quinn-proto`.

transports/quic/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "libp2p-quic"
3-
version = "0.9.0-alpha"
3+
version = "0.9.1-alpha"
44
authors = ["Parity Technologies <admin@parity.io>"]
55
edition = "2021"
66
rust-version = { workspace = true }
@@ -24,6 +24,7 @@ rand = "0.8.5"
2424
rustls = { version = "0.21.2", default-features = false }
2525
thiserror = "1.0.44"
2626
tokio = { version = "1.29.1", default-features = false, features = ["net", "rt", "time"], optional = true }
27+
socket2 = "0.5.3"
2728

2829
[features]
2930
tokio = ["dep:tokio", "if-watch/tokio", "quinn/runtime-tokio"]

transports/quic/src/transport.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,13 @@ use libp2p_core::{
3737
Transport,
3838
};
3939
use libp2p_identity::PeerId;
40+
use socket2::{Domain, Socket, Type};
4041
use std::collections::hash_map::{DefaultHasher, Entry};
4142
use std::collections::HashMap;
42-
use std::fmt;
4343
use std::hash::{Hash, Hasher};
4444
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, UdpSocket};
4545
use std::time::Duration;
46+
use std::{fmt, io};
4647
use std::{
4748
net::SocketAddr,
4849
pin::Pin,
@@ -172,6 +173,21 @@ impl<P: Provider> GenTransport<P> {
172173
}
173174
}
174175
}
176+
177+
fn create_socket(&self, socket_addr: SocketAddr) -> io::Result<UdpSocket> {
178+
let socket = Socket::new(
179+
Domain::for_address(socket_addr),
180+
Type::DGRAM,
181+
Some(socket2::Protocol::UDP),
182+
)?;
183+
if socket_addr.is_ipv6() {
184+
socket.set_only_v6(true)?;
185+
}
186+
187+
socket.bind(&socket_addr.into())?;
188+
189+
Ok(socket.into())
190+
}
175191
}
176192

177193
impl<P: Provider> Transport for GenTransport<P> {
@@ -188,7 +204,8 @@ impl<P: Provider> Transport for GenTransport<P> {
188204
let (socket_addr, version, _peer_id) = self.remote_multiaddr_to_socketaddr(addr, false)?;
189205
let endpoint_config = self.quinn_config.endpoint_config.clone();
190206
let server_config = self.quinn_config.server_config.clone();
191-
let socket = UdpSocket::bind(socket_addr).map_err(Self::Error::from)?;
207+
let socket = self.create_socket(socket_addr).map_err(Self::Error::from)?;
208+
192209
let socket_c = socket.try_clone().map_err(Self::Error::from)?;
193210
let endpoint = Self::new_endpoint(endpoint_config, Some(server_config), socket)?;
194211
let listener = Listener::new(
@@ -888,4 +905,25 @@ mod test {
888905
.unwrap();
889906
assert!(!transport.dialer.contains_key(&SocketFamily::Ipv4));
890907
}
908+
909+
#[cfg(feature = "tokio")]
910+
#[tokio::test]
911+
async fn test_listens_ipv4_ipv6_separately() {
912+
let keypair = libp2p_identity::Keypair::generate_ed25519();
913+
let config = Config::new(&keypair);
914+
let mut transport = crate::tokio::Transport::new(config);
915+
916+
transport
917+
.listen_on(
918+
ListenerId::next(),
919+
"/ip4/0.0.0.0/udp/4001/quic-v1".parse().unwrap(),
920+
)
921+
.unwrap();
922+
transport
923+
.listen_on(
924+
ListenerId::next(),
925+
"/ip6/::/udp/4001/quic-v1".parse().unwrap(),
926+
)
927+
.unwrap();
928+
}
891929
}

0 commit comments

Comments
 (0)