Skip to content

Commit

Permalink
fix(quic): allow listening on ipv4 and ipv6 separately
Browse files Browse the repository at this point in the history
Resolves #4165.

Pull-Request: #4289.
  • Loading branch information
jxs authored Aug 8, 2023
1 parent b5d9932 commit 02dc432
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 5 deletions.
3 changes: 2 additions & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
7 changes: 7 additions & 0 deletions transports/quic/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down
3 changes: 2 additions & 1 deletion transports/quic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libp2p-quic"
version = "0.9.0-alpha"
version = "0.9.1-alpha"
authors = ["Parity Technologies <[email protected]>"]
edition = "2021"
rust-version = { workspace = true }
Expand All @@ -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"]
Expand Down
42 changes: 40 additions & 2 deletions transports/quic/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -172,6 +173,21 @@ impl<P: Provider> GenTransport<P> {
}
}
}

fn create_socket(&self, socket_addr: SocketAddr) -> io::Result<UdpSocket> {
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<P: Provider> Transport for GenTransport<P> {
Expand All @@ -188,7 +204,8 @@ impl<P: Provider> Transport for GenTransport<P> {
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(
Expand Down Expand Up @@ -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();
}
}

0 comments on commit 02dc432

Please sign in to comment.