fd7123b268
Reviewed-by: dfuchs, alanb
308 lines
13 KiB
Java
308 lines
13 KiB
Java
/*
|
|
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
import jdk.test.lib.NetworkConfiguration;
|
|
import jdk.test.lib.net.IPSupport;
|
|
import org.testng.annotations.BeforeTest;
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
|
|
import java.io.IOException;
|
|
import java.net.*;
|
|
import java.nio.channels.*;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.LinkedList;
|
|
|
|
import static java.lang.System.getProperty;
|
|
import static java.lang.System.out;
|
|
import static java.net.StandardProtocolFamily.INET;
|
|
import static java.net.StandardProtocolFamily.INET6;
|
|
import static jdk.test.lib.net.IPSupport.*;
|
|
|
|
/*
|
|
* @test
|
|
* @summary Test SocketChannel, ServerSocketChannel and DatagramChannel
|
|
* open() and connect(), taking into consideration combinations of
|
|
* protocol families (INET, INET6, default),
|
|
* addresses (Inet4Address, Inet6Address).
|
|
* @library /test/lib
|
|
* @build jdk.test.lib.NetworkConfiguration
|
|
* @run testng/othervm OpenAndConnect
|
|
*/
|
|
|
|
|
|
public class OpenAndConnect {
|
|
static final Inet4Address IA4ANYLOCAL;
|
|
static final Inet6Address IA6ANYLOCAL;
|
|
static final Inet4Address IA4LOOPBACK;
|
|
static final Inet6Address IA6LOOPBACK;
|
|
static Inet4Address IA4LOCAL = null;
|
|
static Inet6Address IA6LOCAL = null;
|
|
static InetAddress DONT_BIND;
|
|
|
|
static {
|
|
try {
|
|
IA4ANYLOCAL = (Inet4Address) InetAddress.getByName("0.0.0.0");
|
|
IA6ANYLOCAL = (Inet6Address) InetAddress.getByName("::0");
|
|
IA4LOOPBACK = (Inet4Address) InetAddress.getByName("127.0.0.1");
|
|
IA6LOOPBACK = (Inet6Address) InetAddress.getByName("::1");
|
|
|
|
// Special value to tell test not to call bind (address is not used)
|
|
DONT_BIND = (Inet4Address) InetAddress.getByName("127.0.0.3");
|
|
|
|
initAddrs();
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("Could not initialize addresses", e);
|
|
}
|
|
}
|
|
|
|
@BeforeTest()
|
|
public void setup() {
|
|
NetworkConfiguration.printSystemConfiguration(out);
|
|
IPSupport.printPlatformSupport(out);
|
|
throwSkippedExceptionIfNonOperational();
|
|
|
|
out.println("IA4LOCAL: " + IA4LOCAL);
|
|
out.println("IA6LOCAL: " + IA6LOCAL);
|
|
out.println("IA4ANYLOCAL: " + IA4ANYLOCAL);
|
|
out.println("IA6ANYLOCAL: " + IA6ANYLOCAL);
|
|
out.println("IA4LOOPBACK: " + IA4LOOPBACK);
|
|
out.println("IA6LOOPBACK: " + IA6LOOPBACK);
|
|
}
|
|
|
|
@DataProvider(name = "openConnect")
|
|
public Object[][] openConnect() {
|
|
LinkedList<Object[]> l = new LinkedList<>();
|
|
if (IPSupport.hasIPv4()) {
|
|
l.addAll(openConnectV4Tests);
|
|
if (IA4LOCAL != null) {
|
|
l.addAll(openConnectV4LocalTests);
|
|
}
|
|
}
|
|
if (IPSupport.hasIPv6()) {
|
|
l.addAll(openConnectV6Tests);
|
|
if (IA6LOCAL != null) {
|
|
l.addAll(openConnectV6LocalTests);
|
|
}
|
|
}
|
|
if (IPSupport.hasIPv4() && IPSupport.hasIPv6()) {
|
|
l.addAll(openConnectV4AndV6Tests);
|
|
if (IA4LOCAL != null) {
|
|
l.addAll(openConnectV4LocalAndV6Tests);
|
|
}
|
|
}
|
|
return l.toArray(new Object[][]{});
|
|
}
|
|
|
|
// +----- sfam is server/first socket family
|
|
// |
|
|
// | +------ saddr is bind address for server/first socket
|
|
// | |
|
|
// | | +---- cfam is family for client/second socket
|
|
// | | |
|
|
// | | | +---- caddr is address client/second
|
|
// | | | | socket binds to. When the server
|
|
// | | | | has bound to a wildcard address
|
|
// | | | | this is address used for connect
|
|
// | | | | also.
|
|
// | | | |
|
|
// | | | |
|
|
// | | | |
|
|
// | | | |
|
|
// + + + +
|
|
// { sfam, saddr, cfam, caddr, }
|
|
|
|
// Basic tests for when an IPv4 is available
|
|
public static List<Object[]> openConnectV4Tests =
|
|
Arrays.asList(new Object[][] {
|
|
{ INET, IA4LOOPBACK, INET, IA4LOOPBACK },
|
|
{ INET, IA4LOOPBACK, null, IA4LOOPBACK },
|
|
{ INET, IA4ANYLOCAL, null, IA4LOOPBACK },
|
|
{ INET, IA4ANYLOCAL, INET, IA4LOOPBACK },
|
|
{ null, IA4LOOPBACK, INET, IA4ANYLOCAL },
|
|
{ null, IA4LOOPBACK, INET, IA4LOOPBACK },
|
|
{ null, IA4LOOPBACK, INET, null },
|
|
{ null, IA4LOOPBACK, null, null }
|
|
});
|
|
|
|
// Additional tests for when an IPv4 local address is available
|
|
public List<Object[]> openConnectV4LocalTests =
|
|
Arrays.asList(new Object[][] {
|
|
{ INET, IA4LOCAL, INET, IA4LOCAL },
|
|
{ INET, IA4LOCAL, null, IA4LOCAL },
|
|
{ INET, IA4LOCAL, null, DONT_BIND },
|
|
{ INET, IA4ANYLOCAL, INET, IA4LOCAL },
|
|
{ INET, IA4ANYLOCAL, null, IA4LOCAL },
|
|
{ null, IA4LOCAL, INET, IA4ANYLOCAL },
|
|
{ null, IA4LOCAL, INET, IA4LOCAL },
|
|
{ null, IA4LOCAL, INET, null },
|
|
{ null, IA4LOCAL, null, null }
|
|
});
|
|
|
|
// Basic tests for when an IPv6 is available
|
|
public List<Object[]> openConnectV6Tests =
|
|
Arrays.asList(new Object[][] {
|
|
{ INET6, IA6ANYLOCAL, null, IA6LOOPBACK },
|
|
{ INET6, IA6ANYLOCAL, INET6, IA6LOOPBACK },
|
|
{ INET6, IA6LOOPBACK, INET6, IA6LOOPBACK },
|
|
{ INET6, IA6LOOPBACK, INET6, IA6LOOPBACK },
|
|
{ null, IA6ANYLOCAL, null, IA6LOOPBACK },
|
|
{ null, IA6ANYLOCAL, INET6, IA6LOOPBACK },
|
|
{ null, IA6LOOPBACK, INET6, IA6LOOPBACK },
|
|
{ null, IA6LOOPBACK, INET6, DONT_BIND },
|
|
{ null, IA6LOOPBACK, INET6, null },
|
|
{ null, IA6LOOPBACK, null, IA6LOOPBACK },
|
|
{ null, IA6LOOPBACK, null, null },
|
|
{ null, IA6LOOPBACK, INET6, IA6ANYLOCAL },
|
|
{ null, IA6LOOPBACK, null, IA6ANYLOCAL }
|
|
});
|
|
|
|
// Additional tests for when an IPv6 local address is available
|
|
public List<Object[]> openConnectV6LocalTests =
|
|
Arrays.asList(new Object[][] {
|
|
{ INET6, IA6ANYLOCAL, null, IA6LOCAL },
|
|
{ INET6, IA6ANYLOCAL, INET6, IA6LOCAL },
|
|
{ INET6, IA6LOCAL, INET6, IA6LOCAL },
|
|
{ INET6, IA6LOCAL, null, IA6LOCAL },
|
|
{ INET6, IA6LOCAL, null, DONT_BIND },
|
|
{ INET6, IA6LOCAL, INET6, IA6LOCAL },
|
|
{ null, IA6ANYLOCAL, null, IA6LOCAL },
|
|
{ null, IA6ANYLOCAL, INET6, IA6LOCAL },
|
|
{ null, IA6LOCAL, INET6, IA6LOCAL },
|
|
{ null, IA6LOCAL, INET6, IA6ANYLOCAL },
|
|
{ null, IA6LOCAL, null, IA6ANYLOCAL },
|
|
{ null, IA6LOCAL, null, IA6LOCAL },
|
|
{ null, IA6LOCAL, INET6, null },
|
|
{ null, IA6LOCAL, null, null }
|
|
});
|
|
|
|
// Additional tests for when IPv4 and IPv6 are available
|
|
public List<Object[]> openConnectV4AndV6Tests =
|
|
Arrays.asList(new Object[][] {
|
|
{ null, IA4LOOPBACK, INET6, IA6ANYLOCAL },
|
|
{ null, IA4LOOPBACK, null, IA6ANYLOCAL },
|
|
{ null, IA4LOOPBACK, INET6, DONT_BIND },
|
|
{ null, IA4LOOPBACK, INET6, null }
|
|
});
|
|
|
|
// Additional tests for when IPv4 local address and IPv6 are available
|
|
public List<Object[]> openConnectV4LocalAndV6Tests =
|
|
Arrays.asList(new Object[][] {
|
|
{ null, IA4LOCAL, INET6, IA6ANYLOCAL },
|
|
{ null, IA4LOCAL, INET6, null },
|
|
{ null, IA4LOCAL, null, IA6ANYLOCAL }
|
|
});
|
|
|
|
/**
|
|
* If the destination address is the wildcard, it is replaced by the alternate
|
|
* using the port number from destination. Otherwise destination is returned.
|
|
* Only used by dcOpenAndConnect
|
|
*/
|
|
static InetSocketAddress getDestinationAddress(SocketAddress destination, InetAddress alternate) {
|
|
InetSocketAddress isa = (InetSocketAddress)destination;
|
|
if (isa.getAddress().isAnyLocalAddress())
|
|
return new InetSocketAddress(alternate, isa.getPort());
|
|
else
|
|
return isa;
|
|
}
|
|
|
|
@Test(dataProvider = "openConnect")
|
|
public void scOpenAndConnect(ProtocolFamily sfam,
|
|
InetAddress saddr,
|
|
ProtocolFamily cfam,
|
|
InetAddress caddr) throws IOException
|
|
{
|
|
out.printf("scOpenAndConnect: server bind: %s client bind: %s\n", saddr, caddr);
|
|
try (ServerSocketChannel ssc = openSSC(sfam)) {
|
|
ssc.bind(getSocketAddress(saddr));
|
|
InetSocketAddress ssa = (InetSocketAddress)ssc.getLocalAddress();
|
|
ssa = getDestinationAddress(ssa, caddr);
|
|
out.println(ssa);
|
|
try (SocketChannel csc = openSC(cfam)) {
|
|
if (caddr != DONT_BIND) {
|
|
csc.bind(getSocketAddress(caddr));
|
|
}
|
|
csc.connect(ssa);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test(dataProvider = "openConnect")
|
|
public void dcOpenAndConnect(ProtocolFamily sfam,
|
|
InetAddress saddr,
|
|
ProtocolFamily cfam,
|
|
InetAddress caddr) throws IOException
|
|
{
|
|
try (DatagramChannel sdc = openDC(sfam)) {
|
|
sdc.bind(getSocketAddress(saddr));
|
|
SocketAddress ssa = sdc.socket().getLocalSocketAddress();
|
|
ssa = getDestinationAddress(ssa, caddr);
|
|
out.println(ssa);
|
|
try (DatagramChannel dc = openDC(cfam)) {
|
|
if (caddr != DONT_BIND) {
|
|
dc.bind(getSocketAddress(caddr));
|
|
}
|
|
dc.connect(ssa);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
private static SocketChannel openSC(ProtocolFamily fam) throws IOException {
|
|
return fam == null ? SocketChannel.open() : SocketChannel.open(fam);
|
|
}
|
|
|
|
private static ServerSocketChannel openSSC(ProtocolFamily fam)
|
|
throws IOException {
|
|
return fam == null ? ServerSocketChannel.open()
|
|
: ServerSocketChannel.open(fam);
|
|
}
|
|
|
|
private static DatagramChannel openDC(ProtocolFamily fam)
|
|
throws IOException {
|
|
return fam == null ? DatagramChannel.open()
|
|
: DatagramChannel.open(fam);
|
|
}
|
|
|
|
private static SocketAddress getSocketAddress(InetAddress ia) {
|
|
return ia == null ? null : new InetSocketAddress(ia, 0);
|
|
}
|
|
|
|
private static void initAddrs() throws IOException {
|
|
|
|
NetworkConfiguration cfg = NetworkConfiguration.probe();
|
|
|
|
IA4LOCAL = cfg.ip4Addresses()
|
|
.filter(a -> !a.isLoopbackAddress())
|
|
.findFirst()
|
|
.orElse(null);
|
|
|
|
IA6LOCAL = cfg.ip6Addresses()
|
|
.filter(a -> !a.isLoopbackAddress())
|
|
.findFirst()
|
|
.orElse(null);
|
|
}
|
|
}
|