Skip to content

Commit

Permalink
quic: match socket family of endpoint for dialing
Browse files Browse the repository at this point in the history
  • Loading branch information
elenaf9 committed Jul 23, 2022
1 parent 2c41f70 commit 1a4b8ac
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 22 deletions.
12 changes: 8 additions & 4 deletions transports/quic/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use quinn_proto::{ClientConfig as QuinnClientConfig, ServerConfig as QuinnServer
use std::{
collections::{HashMap, VecDeque},
fmt,
net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, UdpSocket},
sync::{Arc, Weak},
task::{Poll, Waker},
time::{Duration, Instant},
Expand Down Expand Up @@ -109,9 +109,13 @@ impl Endpoint {
}

/// Builds a new [`Endpoint`] that only supports outbound connections.
pub fn new_dialer(config: Config) -> Result<Arc<Endpoint>, transport::Error> {
let socket_addr = SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0);
Self::new(config, socket_addr.into(), None)
pub fn new_dialer(config: Config, is_ipv6: bool) -> Result<Arc<Endpoint>, transport::Error> {
let socket_addr = if is_ipv6 {
SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), 0)
} else {
SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0)
};
Self::new(config, socket_addr, None)
}

fn new(
Expand Down
48 changes: 31 additions & 17 deletions transports/quic/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,19 @@ pub use quinn_proto::{
pub struct QuicTransport {
config: Config,
listeners: SelectAll<Listener>,
/// Endpoint to use if no listener exists.
dialer: Option<Arc<Endpoint>>,
/// Endpoints to use for dialing Ipv4 addresses if no matching listener exists.
ipv4_dialer: Option<Arc<Endpoint>>,
/// Endpoints to use for dialing Ipv6 addresses if no matching listener exists.
ipv6_dialer: Option<Arc<Endpoint>>,
}

impl QuicTransport {
pub fn new(config: Config) -> Self {
Self {
listeners: SelectAll::new(),
config,
dialer: None,
ipv4_dialer: None,
ipv6_dialer: None,
}
}
}
Expand Down Expand Up @@ -102,7 +105,10 @@ impl Transport for QuicTransport {
// Drop reference to dialer endpoint so that the endpoint is dropped once the last
// connection that uses it is closed.
// New outbound connections will use a bidirectional (listener) endpoint.
let _ = self.dialer.take();
match socket_addr {
SocketAddr::V4(_) => self.ipv4_dialer.take(),
SocketAddr::V6(_) => self.ipv6_dialer.take(),
};
Ok(listener_id)
}

Expand All @@ -126,25 +132,33 @@ impl Transport for QuicTransport {
tracing::error!("multiaddr not supported");
return Err(TransportError::MultiaddrNotSupported(addr));
}
let endpoint = if self.listeners.is_empty() {
match self.dialer.clone() {
Some(endpoint) => endpoint,
let listeners = self
.listeners
.iter()
.filter(|l| {
let listen_addr = l.endpoint.socket_addr();
listen_addr.is_ipv4() == socket_addr.is_ipv4()
&& listen_addr.ip().is_loopback() == socket_addr.ip().is_loopback()
})
.collect::<Vec<_>>();
let endpoint = if listeners.is_empty() {
let dialer = match socket_addr {
SocketAddr::V4(_) => &mut self.ipv4_dialer,
SocketAddr::V6(_) => &mut self.ipv6_dialer,
};
match dialer {
Some(endpoint) => endpoint.clone(),
None => {
let endpoint =
Endpoint::new_dialer(self.config.clone()).map_err(TransportError::Other)?;
let _ = self.dialer.insert(endpoint.clone());
let endpoint = Endpoint::new_dialer(self.config.clone(), socket_addr.is_ipv6())
.map_err(TransportError::Other)?;
let _ = dialer.insert(endpoint.clone());
endpoint
}
}
} else {
// Pick a random listener to use for dialing.
// TODO: Prefer listeners with same IP version.
let n = rand::random::<usize>() % self.listeners.len();
let listener = self
.listeners
.iter_mut()
.nth(n)
.expect("Can not be out of bound.");
let n = rand::random::<usize>() % listeners.len();
let listener = listeners.get(n).expect("Can not be out of bound.");
listener.endpoint.clone()
};

Expand Down
1 change: 0 additions & 1 deletion transports/quic/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,6 @@ async fn endpoint_reuse() -> Result<()> {
}

#[async_std::test]
#[ignore]
async fn ipv4_dial_ipv6() -> Result<()> {
setup_global_subscriber();

Expand Down

0 comments on commit 1a4b8ac

Please sign in to comment.