Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 45 additions & 4 deletions moq-native-ietf/src/quic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,53 @@ impl Client {
let host = url.host().context("invalid DNS name")?.to_string();
let port = url.port().unwrap_or(443);

// Look up the DNS entry.
let addr = tokio::net::lookup_host((host.clone(), port))
// Determine whether our local socket is IPv6 or IPv4
let is_ipv6 = self
.quic
.local_addr()
.context("failed to get local address")?
.is_ipv6();

// Perform DNS lookup to get all addresses
let addrs: Vec<std::net::SocketAddr> = tokio::net::lookup_host((host.clone(), port))
.await
.context("failed DNS lookup")?
.next()
.context("no DNS entries")?;
.collect();

// Fail early if DNS lookup returned no addresses
if addrs.is_empty() {
anyhow::bail!("DNS lookup for host '{}' returned no addresses", host);
}

// Log all DNS responses
for (i, addr) in addrs.iter().enumerate() {
log::debug!(
"DNS[{}] = {} ({})",
i,
addr,
if addr.is_ipv4() { "ipv4" } else { "ipv6" }
);
}

// Select DNS address to use based on local socket type and OS
let chosen = if !is_ipv6 {
// If we are bound to an IPv4 socket, prefer IPv4 addresses
addrs.iter().find(|a| a.is_ipv4()).cloned()
} else if cfg!(target_os = "linux") {
// If IPv6 and running on Linux, then assume dual-stack, and use top DNS result
addrs.first().cloned()
Comment on lines +338 to +340
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for Linux dual-stack sockets (line 325) uses the "top DNS result" without any preference for IPv4 or IPv6. While this may work, it's unclear why Linux is treated differently. The comment mentions "dual-stack" which suggests IPv6 sockets on Linux can handle both IPv4 and IPv6, but the code doesn't verify this assumption. If the intent is to handle IPv4-mapped IPv6 addresses on Linux, this should be documented more clearly, or the logic should explicitly check for dual-stack capability rather than assuming it based on OS.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a reasonable point, I'd like to leave this as a future todo, as the previous logic is still improved here, and not made worse.

} else {
// If IPv6 and not running on Linux: prefer IPv6 addresses
addrs.iter().find(|a| a.is_ipv6()).cloned()
};

// Fail if no compatible address is found
let addr = chosen.context(format!(
"No compatible address found for local socket type (IPv{})",
if is_ipv6 { "6" } else { "4" }
))?;

log::debug!("Connecting to address={}", addr);

let connection = self.quic.connect_with(config, addr, &host)?.await?;

Expand Down