|
1 | 1 | use std::{
|
2 | 2 | io::{self, ErrorKind},
|
3 | 3 | net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
4 |
| - time::Duration, |
5 | 4 | };
|
6 | 5 |
|
7 | 6 | use cfg_if::cfg_if;
|
@@ -177,39 +176,34 @@ static IP_STACK_CAPABILITIES: Lazy<IpStackCapabilities> = Lazy::new(|| {
|
177 | 176 | });
|
178 | 177 |
|
179 | 178 | fn check_ipv4_mapped_ipv6_capability() -> io::Result<()> {
|
| 179 | + // https://stackoverflow.com/questions/30184377/how-to-detect-if-dual-stack-socket-is-supported |
| 180 | + |
180 | 181 | let local_host = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 0));
|
| 182 | + let local_host_53 = SockAddr::from(SocketAddr::new(Ipv4Addr::LOCALHOST.to_ipv6_mapped().into(), 53)); |
181 | 183 |
|
182 |
| - let socket1 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?; |
183 |
| - socket1.set_only_v6(false)?; |
184 |
| - socket1.bind(&local_host)?; |
185 |
| - socket1.listen(128)?; |
| 184 | + let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?; |
| 185 | + socket.set_only_v6(false)?; |
| 186 | + socket.bind(&local_host)?; |
| 187 | + socket.connect(&local_host_53)?; |
186 | 188 |
|
187 |
| - let socket1_address = socket1.local_addr()?; |
188 |
| - match socket1_address.as_socket() { |
| 189 | + // getsockname() |
| 190 | + let local_addr = socket.local_addr()?; |
| 191 | + match local_addr.as_socket() { |
189 | 192 | None => return Err(io::Error::new(ErrorKind::Other, "invalid local_addr")),
|
190 |
| - Some(socket_addr) => match socket_addr { |
191 |
| - SocketAddr::V4(..) => { |
192 |
| - return Err(io::Error::new( |
193 |
| - ErrorKind::Other, |
194 |
| - "local_addr shouldn't be an IPv4 address", |
195 |
| - )); |
196 |
| - } |
197 |
| - SocketAddr::V6(ref v6) => { |
198 |
| - if let None = v6.ip().to_ipv4_mapped() { |
| 193 | + Some(addr) => match addr { |
| 194 | + SocketAddr::V4(..) => return Err(io::Error::new(ErrorKind::Other, "local_addr returned an IPv4 address")), |
| 195 | + SocketAddr::V6(v6) => match v6.ip().to_ipv4_mapped() { |
| 196 | + Some(_) => {} |
| 197 | + None => { |
199 | 198 | return Err(io::Error::new(
|
200 | 199 | ErrorKind::Other,
|
201 |
| - "local_addr is not an IPv4-mapped-IPv6 address", |
| 200 | + "local_addr returned an non IPv4-mapped-IPv6 address", |
202 | 201 | ));
|
203 | 202 | }
|
204 |
| - } |
| 203 | + }, |
205 | 204 | },
|
206 | 205 | }
|
207 | 206 |
|
208 |
| - let socket2 = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))?; |
209 |
| - socket2.set_only_v6(false)?; |
210 |
| - socket2.bind(&local_host)?; |
211 |
| - socket2.connect_timeout(&socket1_address, Duration::from_secs(1))?; |
212 |
| - |
213 | 207 | Ok(())
|
214 | 208 | }
|
215 | 209 |
|
|
0 commit comments