diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketTest.java index 5c2f41acab..2f32444a8c 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/AbstractSocketTest.java @@ -34,11 +34,11 @@ public abstract class AbstractSocketTest extends AbstractComboTestsuiteTest { LinuxSocket s2 = LinuxSocket.newSocketDomain(); try { - DomainSocketAddress dsa = UnixTestUtils.newSocketAddress(); + DomainSocketAddress dsa = UnixTestUtils.newDomainSocketAddress(); s1.bind(dsa); s1.listen(1); diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketTestPermutation.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketTestPermutation.java index ca4960f0c0..aea11e24ae 100644 --- a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketTestPermutation.java +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollSocketTestPermutation.java @@ -259,7 +259,7 @@ class EpollSocketTestPermutation extends SocketTestPermutation { ); } - public static DomainSocketAddress newSocketAddress() { - return UnixTestUtils.newSocketAddress(); + public static DomainSocketAddress newDomainSocketAddress() { + return UnixTestUtils.newDomainSocketAddress(); } } diff --git a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/BsdSocket.java b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/BsdSocket.java index 75a2e92ea1..ab717aeef7 100644 --- a/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/BsdSocket.java +++ b/transport-native-kqueue/src/main/java/io/netty/channel/kqueue/BsdSocket.java @@ -125,8 +125,8 @@ final class BsdSocket extends Socket { sourcePort = 0; } else { InetAddress sourceInetAddress = source.getAddress(); - sourceIPv6 = sourceInetAddress instanceof Inet6Address; - if (sourceIPv6) { + sourceIPv6 = useIpv6(this, sourceInetAddress); + if (sourceInetAddress instanceof Inet6Address) { sourceAddress = sourceInetAddress.getAddress(); sourceScopeId = ((Inet6Address) sourceInetAddress).getScopeId(); } else { @@ -138,10 +138,10 @@ final class BsdSocket extends Socket { } InetAddress destinationInetAddress = destination.getAddress(); - boolean destinationIPv6 = destinationInetAddress instanceof Inet6Address; + boolean destinationIPv6 = useIpv6(this, destinationInetAddress); byte[] destinationAddress; int destinationScopeId; - if (destinationIPv6) { + if (destinationInetAddress instanceof Inet6Address) { destinationAddress = destinationInetAddress.getAddress(); destinationScopeId = ((Inet6Address) destinationInetAddress).getScopeId(); } else { diff --git a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueJdkLoopbackSocketSslEchoTest.java b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueJdkLoopbackSocketSslEchoTest.java new file mode 100644 index 0000000000..2f966a9f5b --- /dev/null +++ b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueJdkLoopbackSocketSslEchoTest.java @@ -0,0 +1,27 @@ +/* + * Copyright 2021 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.channel.kqueue; + +import io.netty.channel.unix.tests.UnixTestUtils; + +import java.net.SocketAddress; + +public class KQueueJdkLoopbackSocketSslEchoTest extends KQueueSocketSslEchoTest { + @Override + protected SocketAddress newSocketAddress() { + return UnixTestUtils.newInetLoopbackSocketAddress(); + } +} diff --git a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java index 7cac7ed532..3f44e9f5cb 100644 --- a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java +++ b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTest.java @@ -40,7 +40,7 @@ public class KQueueSocketTest extends SocketTest { BsdSocket s2 = BsdSocket.newSocketDomain(); try { - DomainSocketAddress dsa = UnixTestUtils.newSocketAddress(); + DomainSocketAddress dsa = UnixTestUtils.newDomainSocketAddress(); s1.bind(dsa); s1.listen(1); @@ -61,7 +61,7 @@ public class KQueueSocketTest extends SocketTest { BsdSocket s2 = BsdSocket.newSocketDomain(); try { - DomainSocketAddress dsa = UnixTestUtils.newSocketAddress(); + DomainSocketAddress dsa = UnixTestUtils.newDomainSocketAddress(); s1.bind(dsa); s1.listen(1); diff --git a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTestPermutation.java b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTestPermutation.java index eff955dbca..6ef900a7f5 100644 --- a/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTestPermutation.java +++ b/transport-native-kqueue/src/test/java/io/netty/channel/kqueue/KQueueSocketTestPermutation.java @@ -50,7 +50,7 @@ class KQueueSocketTestPermutation extends SocketTestPermutation { public List> socket() { List> list = - combo(serverSocket(), clientSocket()); + combo(serverSocket(), clientSocketWithFastOpen()); list.remove(list.size() - 1); // Exclude NIO x NIO test @@ -202,6 +202,6 @@ class KQueueSocketTestPermutation extends SocketTestPermutation { } public static DomainSocketAddress newSocketAddress() { - return UnixTestUtils.newSocketAddress(); + return UnixTestUtils.newDomainSocketAddress(); } } diff --git a/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/UnixTestUtils.java b/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/UnixTestUtils.java index 2108dfcc92..3453c236bc 100644 --- a/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/UnixTestUtils.java +++ b/transport-native-unix-common-tests/src/main/java/io/netty/channel/unix/tests/UnixTestUtils.java @@ -20,9 +20,26 @@ import io.netty.util.internal.PlatformDependent; import java.io.File; import java.io.IOException; +import java.lang.reflect.Method; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +import static org.junit.jupiter.api.Assumptions.assumeTrue; public final class UnixTestUtils { + private static final Object INET_LOOPBACK_UNAVAILABLE = new Object(); + private static volatile Object inetLoopbackCache; + + /** + * @deprecated Use {@link #newDomainSocketAddress()} instead. + */ + @Deprecated public static DomainSocketAddress newSocketAddress() { + return newDomainSocketAddress(); + } + + public static DomainSocketAddress newDomainSocketAddress() { try { File file; do { @@ -37,5 +54,30 @@ public final class UnixTestUtils { } } + /** + * The JDK method may produce IPv4 loopback addresses where {@link io.netty.util.NetUtil#LOCALHOST} might be an + * IPv6 addresses. + * This difference can stress the system in different ways that are important to test. + */ + public static SocketAddress newInetLoopbackSocketAddress() { + Object loopback = inetLoopbackCache; + + if (loopback == null) { + inetLoopbackCache = loopback = getLoopbackAddress(); + } + + assumeTrue(loopback != INET_LOOPBACK_UNAVAILABLE, "InetAddress.getLoopbackAddress() is not available"); + return new InetSocketAddress((InetAddress) loopback, 0); + } + + private static Object getLoopbackAddress() { + try { + Method method = InetAddress.class.getMethod("getLoopbackAddress"); + return method.invoke(null); + } catch (Exception ignore) { + return INET_LOOPBACK_UNAVAILABLE; + } + } + private UnixTestUtils() { } } diff --git a/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java index a2cf22e163..ecb3075abb 100644 --- a/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java +++ b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java @@ -59,7 +59,15 @@ public class Socket extends FileDescriptor { * Returns {@code true} if we should use IPv6 internally, {@code false} otherwise. */ private boolean useIpv6(InetAddress address) { - return ipv6 || address instanceof Inet6Address; + return useIpv6(this, address); + } + + /** + * Returns {@code true} if the given socket and address combination should use IPv6 internally, + * {@code false} otherwise. + */ + protected static boolean useIpv6(Socket socket, InetAddress address) { + return socket.ipv6 || address instanceof Inet6Address; } public final void shutdown() throws IOException {