Skip to content

Commit b8e4d3b

Browse files
Romain Roffédjc
authored andcommitted
quinn: Make Endpoint::server dual-stack V6 by default
1 parent 0adcd20 commit b8e4d3b

1 file changed

Lines changed: 20 additions & 6 deletions

File tree

quinn/src/endpoint.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,23 +107,37 @@ impl Endpoint {
107107

108108
/// Helper to construct an endpoint for use with both incoming and outgoing connections
109109
///
110-
/// Platform defaults for dual-stack sockets vary. For example, any socket bound to a wildcard
111-
/// IPv6 address on Windows will not by default be able to communicate with IPv4
112-
/// addresses. Portable applications should bind an address that matches the family they wish to
113-
/// communicate within.
110+
/// Note that `addr` is the *local* address to bind to, which should usually be a wildcard
111+
/// address like `0.0.0.0:0` or `[::]:0`, which allow communication with any reachable IPv4 or
112+
/// IPv6 address respectively from an OS-assigned port.
113+
///
114+
/// If an IPv6 address is provided, attempts to make the socket dual-stack so as to allow
115+
/// communication with both IPv4 and IPv6 clients. As such, calling `Endpoint::server` with
116+
/// the address `[::]:0` is a reasonable default to maximize the ability to accept connections
117+
/// from any address.
118+
///
119+
/// Some environments may not allow creation of dual-stack sockets, in which case an IPv6
120+
/// server will only be able to accept connections from IPv6 clients. An IPv4 server is never
121+
/// dual-stack.
114122
#[cfg(all(
115123
not(wasm_browser),
116124
any(feature = "runtime-tokio", feature = "runtime-smol"),
117125
any(feature = "aws-lc-rs", feature = "ring"), // `EndpointConfig::default()` is only available with these
118126
))]
119127
pub fn server(config: ServerConfig, addr: SocketAddr) -> io::Result<Self> {
120-
let socket = std::net::UdpSocket::bind(addr)?;
128+
let socket = Socket::new(Domain::for_address(addr), Type::DGRAM, Some(Protocol::UDP))?;
129+
if addr.is_ipv6() {
130+
if let Err(e) = socket.set_only_v6(false) {
131+
tracing::debug!(%e, "unable to make socket dual-stack");
132+
}
133+
}
134+
socket.bind(&addr.into())?;
121135
let runtime =
122136
default_runtime().ok_or_else(|| io::Error::other("no async runtime found"))?;
123137
Self::new_with_abstract_socket(
124138
EndpointConfig::default(),
125139
Some(config),
126-
runtime.wrap_udp_socket(socket)?,
140+
runtime.wrap_udp_socket(socket.into())?,
127141
runtime,
128142
)
129143
}

0 commit comments

Comments
 (0)