mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-05 11:15:13 +00:00
8241305: Add protocol specific factory creation methods to SocketChannel and ServerSocketChannel
Reviewed-by: alanb, chegar, dfuchs
This commit is contained in:
parent
42bad03de8
commit
0f7aeed416
@ -33,6 +33,7 @@ import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A selectable channel for datagram-oriented sockets.
|
||||
@ -184,7 +185,7 @@ public abstract class DatagramChannel
|
||||
* @since 1.7
|
||||
*/
|
||||
public static DatagramChannel open(ProtocolFamily family) throws IOException {
|
||||
return SelectorProvider.provider().openDatagramChannel(family);
|
||||
return SelectorProvider.provider().openDatagramChannel(requireNonNull(family));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -26,11 +26,13 @@
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A selectable channel for stream-oriented listening sockets.
|
||||
@ -113,6 +115,34 @@ public abstract class ServerSocketChannel
|
||||
return SelectorProvider.provider().openServerSocketChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a server-socket channel.The {@code family} parameter specifies the
|
||||
* {@link ProtocolFamily protocol family} of the channel's socket.
|
||||
*
|
||||
* <p> The new channel is created by invoking the {@link
|
||||
* java.nio.channels.spi.SelectorProvider#openServerSocketChannel(ProtocolFamily)
|
||||
* openServerSocketChannel(ProtocolFamily)} method of the system-wide default {@link
|
||||
* java.nio.channels.spi.SelectorProvider} object. </p>
|
||||
*
|
||||
* @param family
|
||||
* The protocol family
|
||||
*
|
||||
* @return A new socket channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the specified protocol family is not supported. For example,
|
||||
* suppose the parameter is specified as {@link
|
||||
* java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
|
||||
* but IPv6 is not enabled on the platform.
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @since 15
|
||||
*/
|
||||
public static ServerSocketChannel open(ProtocolFamily family) throws IOException {
|
||||
return SelectorProvider.provider().openServerSocketChannel(requireNonNull(family));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an operation set identifying this channel's supported
|
||||
* operations.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -26,12 +26,14 @@
|
||||
package java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* A selectable channel for stream-oriented connecting sockets.
|
||||
@ -150,6 +152,34 @@ public abstract class SocketChannel
|
||||
return SelectorProvider.provider().openSocketChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a socket channel. The {@code family} parameter specifies the
|
||||
* {@link ProtocolFamily protocol family} of the channel's socket.
|
||||
*
|
||||
* <p> The new channel is created by invoking the {@link
|
||||
* java.nio.channels.spi.SelectorProvider#openSocketChannel(ProtocolFamily)
|
||||
* openSocketChannel(ProtocolFamily)} method of the system-wide default.
|
||||
* {@link java.nio.channels.spi.SelectorProvider} object.</p>
|
||||
*
|
||||
* @param family
|
||||
* The protocol family
|
||||
*
|
||||
* @return A new socket channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the specified protocol family is not supported. For example,
|
||||
* suppose the parameter is specified as {@link
|
||||
* java.net.StandardProtocolFamily#INET6 StandardProtocolFamily.INET6}
|
||||
* but IPv6 is not enabled on the platform.
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @since 15
|
||||
*/
|
||||
public static SocketChannel open(ProtocolFamily family) throws IOException {
|
||||
return SelectorProvider.provider().openSocketChannel(requireNonNull(family));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a socket channel and connects it to a remote address.
|
||||
*
|
||||
|
||||
@ -36,6 +36,7 @@ import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.ServiceConfigurationError;
|
||||
|
||||
@ -315,4 +316,51 @@ public abstract class SelectorProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a socket channel.
|
||||
*
|
||||
* @implSpec The default implementation of this method first checks that
|
||||
* the given protocol {@code family} is not {@code null},
|
||||
* then throws {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @param family
|
||||
* The protocol family
|
||||
*
|
||||
* @return The new channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the specified protocol family is not supported
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @since 15
|
||||
*/
|
||||
public SocketChannel openSocketChannel(ProtocolFamily family) throws IOException {
|
||||
Objects.requireNonNull(family);
|
||||
throw new UnsupportedOperationException("Protocol family not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a server-socket channel.
|
||||
*
|
||||
* @implSpec The default implementation of this method first checks that
|
||||
* the given protocol {@code family} is not {@code null},
|
||||
* then throws {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @param family
|
||||
* The protocol family
|
||||
*
|
||||
* @return The new channel
|
||||
*
|
||||
* @throws UnsupportedOperationException
|
||||
* If the specified protocol family is not supported
|
||||
* @throws IOException
|
||||
* If an I/O error occurs
|
||||
*
|
||||
* @since 15
|
||||
*/
|
||||
public ServerSocketChannel openServerSocketChannel(ProtocolFamily family) throws IOException {
|
||||
Objects.requireNonNull(family);
|
||||
throw new UnsupportedOperationException("Protocol family not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,6 +249,57 @@ public class Net {
|
||||
port);
|
||||
}
|
||||
|
||||
private static final InetAddress anyLocalInet4Address;
|
||||
private static final InetAddress anyLocalInet6Address;
|
||||
private static final InetAddress inet4LoopbackAddress;
|
||||
private static final InetAddress inet6LoopbackAddress;
|
||||
static {
|
||||
try {
|
||||
anyLocalInet4Address = inet4FromInt(0);
|
||||
assert anyLocalInet4Address instanceof Inet4Address
|
||||
&& anyLocalInet4Address.isAnyLocalAddress();
|
||||
|
||||
anyLocalInet6Address = InetAddress.getByAddress(new byte[16]);
|
||||
assert anyLocalInet6Address instanceof Inet6Address
|
||||
&& anyLocalInet6Address.isAnyLocalAddress();
|
||||
|
||||
inet4LoopbackAddress = inet4FromInt(0x7f000001);
|
||||
assert inet4LoopbackAddress instanceof Inet4Address
|
||||
&& inet4LoopbackAddress.isLoopbackAddress();
|
||||
|
||||
byte[] bytes = new byte[16];
|
||||
bytes[15] = 0x01;
|
||||
inet6LoopbackAddress = InetAddress.getByAddress(bytes);
|
||||
assert inet6LoopbackAddress instanceof Inet6Address
|
||||
&& inet6LoopbackAddress.isLoopbackAddress();
|
||||
} catch (Exception e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static InetAddress inet4LoopbackAddress() {
|
||||
return inet4LoopbackAddress;
|
||||
}
|
||||
|
||||
static InetAddress inet6LoopbackAddress() {
|
||||
return inet6LoopbackAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wildcard address that corresponds to the given protocol family.
|
||||
*
|
||||
* @see InetAddress#isAnyLocalAddress()
|
||||
*/
|
||||
static InetAddress anyLocalAddress(ProtocolFamily family) {
|
||||
if (family == StandardProtocolFamily.INET) {
|
||||
return anyLocalInet4Address;
|
||||
} else if (family == StandardProtocolFamily.INET6) {
|
||||
return anyLocalInet6Address;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any IPv4 address of the given network interface, or
|
||||
* null if the interface does not have any IPv4 addresses.
|
||||
@ -467,7 +518,13 @@ public class Net {
|
||||
}
|
||||
|
||||
static FileDescriptor serverSocket(boolean stream) {
|
||||
return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
|
||||
return serverSocket(UNSPEC, stream);
|
||||
}
|
||||
|
||||
static FileDescriptor serverSocket(ProtocolFamily family, boolean stream) {
|
||||
boolean preferIPv6 = isIPv6Available() &&
|
||||
(family != StandardProtocolFamily.INET);
|
||||
return IOUtil.newFD(socket0(preferIPv6, stream, true, fastLoopback));
|
||||
}
|
||||
|
||||
// Due to oddities SO_REUSEADDR on windows reuse is ignored
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
@ -72,4 +72,14 @@ public abstract class SelectorProviderImpl
|
||||
public SocketChannel openSocketChannel() throws IOException {
|
||||
return new SocketChannelImpl(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketChannel openSocketChannel(ProtocolFamily family) throws IOException {
|
||||
return new SocketChannelImpl(this, family);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocketChannel openServerSocketChannel(ProtocolFamily family) {
|
||||
return new ServerSocketChannelImpl(this, family);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,12 @@ package sun.nio.ch;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
@ -62,6 +64,9 @@ class ServerSocketChannelImpl
|
||||
// Used to make native close and configure calls
|
||||
private static final NativeDispatcher nd = new SocketDispatcher();
|
||||
|
||||
// The protocol family of the socket
|
||||
private final ProtocolFamily family;
|
||||
|
||||
// Our file descriptor
|
||||
private final FileDescriptor fd;
|
||||
private final int fdVal;
|
||||
@ -95,10 +100,26 @@ class ServerSocketChannelImpl
|
||||
|
||||
// -- End of fields protected by stateLock
|
||||
|
||||
|
||||
ServerSocketChannelImpl(SelectorProvider sp) {
|
||||
this(sp, Net.isIPv6Available()
|
||||
? StandardProtocolFamily.INET6
|
||||
: StandardProtocolFamily.INET);
|
||||
}
|
||||
|
||||
ServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family) {
|
||||
super(sp);
|
||||
this.fd = Net.serverSocket(true);
|
||||
Objects.requireNonNull(family, "'family' is null");
|
||||
|
||||
if ((family != StandardProtocolFamily.INET) &&
|
||||
(family != StandardProtocolFamily.INET6)) {
|
||||
throw new UnsupportedOperationException("Protocol family not supported");
|
||||
}
|
||||
if (family == StandardProtocolFamily.INET6 && !Net.isIPv6Available()) {
|
||||
throw new UnsupportedOperationException("IPv6 not available");
|
||||
}
|
||||
|
||||
this.family = family;
|
||||
this.fd = Net.serverSocket(family, true);
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
}
|
||||
|
||||
@ -106,8 +127,13 @@ class ServerSocketChannelImpl
|
||||
throws IOException
|
||||
{
|
||||
super(sp);
|
||||
|
||||
this.family = Net.isIPv6Available()
|
||||
? StandardProtocolFamily.INET6
|
||||
: StandardProtocolFamily.INET;
|
||||
this.fd = fd;
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
|
||||
if (bound) {
|
||||
synchronized (stateLock) {
|
||||
localAddress = Net.localAddress(fd);
|
||||
@ -210,14 +236,17 @@ class ServerSocketChannelImpl
|
||||
ensureOpen();
|
||||
if (localAddress != null)
|
||||
throw new AlreadyBoundException();
|
||||
InetSocketAddress isa = (local == null)
|
||||
? new InetSocketAddress(0)
|
||||
: Net.checkAddress(local);
|
||||
InetSocketAddress isa;
|
||||
if (local == null) {
|
||||
isa = new InetSocketAddress(Net.anyLocalAddress(family), 0);
|
||||
} else {
|
||||
isa = Net.checkAddress(local, family);
|
||||
}
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkListen(isa.getPort());
|
||||
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
|
||||
Net.bind(fd, isa.getAddress(), isa.getPort());
|
||||
Net.bind(family, fd, isa.getAddress(), isa.getPort());
|
||||
Net.listen(fd, backlog < 1 ? 50 : backlog);
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
@ -358,7 +387,7 @@ class ServerSocketChannelImpl
|
||||
if (sm != null) {
|
||||
sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
|
||||
}
|
||||
return new SocketChannelImpl(provider(), newfd, isa);
|
||||
return new SocketChannelImpl(provider(), family, newfd, isa);
|
||||
} catch (Exception e) {
|
||||
nd.close(newfd);
|
||||
throw e;
|
||||
|
||||
@ -28,6 +28,7 @@ package sun.nio.ch;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
@ -71,6 +72,9 @@ class SocketChannelImpl
|
||||
// Used to make native read and write calls
|
||||
private static final NativeDispatcher nd = new SocketDispatcher();
|
||||
|
||||
// The protocol family of the socket
|
||||
private final ProtocolFamily family;
|
||||
|
||||
// Our file descriptor object
|
||||
private final FileDescriptor fd;
|
||||
private final int fdVal;
|
||||
@ -118,12 +122,26 @@ class SocketChannelImpl
|
||||
|
||||
// -- End of fields protected by stateLock
|
||||
|
||||
|
||||
// Constructor for normal connecting sockets
|
||||
//
|
||||
SocketChannelImpl(SelectorProvider sp) throws IOException {
|
||||
this(sp, Net.isIPv6Available()
|
||||
? StandardProtocolFamily.INET6
|
||||
: StandardProtocolFamily.INET);
|
||||
}
|
||||
|
||||
SocketChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException {
|
||||
super(sp);
|
||||
this.fd = Net.socket(true);
|
||||
Objects.requireNonNull(family, "'family' is null");
|
||||
if ((family != StandardProtocolFamily.INET) &&
|
||||
(family != StandardProtocolFamily.INET6)) {
|
||||
throw new UnsupportedOperationException("Protocol family not supported");
|
||||
}
|
||||
if (family == StandardProtocolFamily.INET6 && !Net.isIPv6Available()) {
|
||||
throw new UnsupportedOperationException("IPv6 not available");
|
||||
}
|
||||
this.family = family;
|
||||
this.fd = Net.socket(family, true);
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
}
|
||||
|
||||
@ -131,8 +149,12 @@ class SocketChannelImpl
|
||||
throws IOException
|
||||
{
|
||||
super(sp);
|
||||
this.family = Net.isIPv6Available()
|
||||
? StandardProtocolFamily.INET6
|
||||
: StandardProtocolFamily.INET;
|
||||
this.fd = fd;
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
|
||||
if (bound) {
|
||||
synchronized (stateLock) {
|
||||
this.localAddress = Net.localAddress(fd);
|
||||
@ -142,10 +164,14 @@ class SocketChannelImpl
|
||||
|
||||
// Constructor for sockets obtained from server sockets
|
||||
//
|
||||
SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, InetSocketAddress isa)
|
||||
SocketChannelImpl(SelectorProvider sp,
|
||||
ProtocolFamily family,
|
||||
FileDescriptor fd,
|
||||
InetSocketAddress isa)
|
||||
throws IOException
|
||||
{
|
||||
super(sp);
|
||||
this.family = family;
|
||||
this.fd = fd;
|
||||
this.fdVal = IOUtil.fdVal(fd);
|
||||
synchronized (stateLock) {
|
||||
@ -225,8 +251,6 @@ class SocketChannelImpl
|
||||
ensureOpen();
|
||||
|
||||
if (name == StandardSocketOptions.IP_TOS) {
|
||||
ProtocolFamily family = Net.isIPv6Available() ?
|
||||
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||
Net.setSocketOption(fd, family, name, value);
|
||||
return this;
|
||||
}
|
||||
@ -260,10 +284,8 @@ class SocketChannelImpl
|
||||
return (T)Boolean.valueOf(isReuseAddress);
|
||||
}
|
||||
|
||||
// special handling for IP_TOS: always return 0 when IPv6
|
||||
// special handling for IP_TOS
|
||||
if (name == StandardSocketOptions.IP_TOS) {
|
||||
ProtocolFamily family = Net.isIPv6Available() ?
|
||||
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||
return (T) Net.getSocketOption(fd, family, name);
|
||||
}
|
||||
|
||||
@ -632,14 +654,18 @@ class SocketChannelImpl
|
||||
throw new ConnectionPendingException();
|
||||
if (localAddress != null)
|
||||
throw new AlreadyBoundException();
|
||||
InetSocketAddress isa = (local == null) ?
|
||||
new InetSocketAddress(0) : Net.checkAddress(local);
|
||||
InetSocketAddress isa;
|
||||
if (local == null) {
|
||||
isa = new InetSocketAddress(Net.anyLocalAddress(family), 0);
|
||||
} else {
|
||||
isa = Net.checkAddress(local, family);
|
||||
}
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkListen(isa.getPort());
|
||||
}
|
||||
NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
|
||||
Net.bind(fd, isa.getAddress(), isa.getPort());
|
||||
Net.bind(family, fd, isa.getAddress(), isa.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
@ -723,14 +749,21 @@ class SocketChannelImpl
|
||||
/**
|
||||
* Checks the remote address to which this channel is to be connected.
|
||||
*/
|
||||
private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {
|
||||
InetSocketAddress isa = Net.checkAddress(sa);
|
||||
private InetSocketAddress checkRemote(SocketAddress sa) {
|
||||
InetSocketAddress isa = Net.checkAddress(sa, family);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
|
||||
}
|
||||
if (isa.getAddress().isAnyLocalAddress()) {
|
||||
return new InetSocketAddress(InetAddress.getLocalHost(), isa.getPort());
|
||||
InetAddress address = isa.getAddress();
|
||||
if (address.isAnyLocalAddress()) {
|
||||
int port = isa.getPort();
|
||||
if (address instanceof Inet4Address) {
|
||||
return new InetSocketAddress(Net.inet4LoopbackAddress(), port);
|
||||
} else {
|
||||
assert family == StandardProtocolFamily.INET6;
|
||||
return new InetSocketAddress(Net.inet6LoopbackAddress(), port);
|
||||
}
|
||||
} else {
|
||||
return isa;
|
||||
}
|
||||
@ -748,7 +781,10 @@ class SocketChannelImpl
|
||||
boolean connected = false;
|
||||
try {
|
||||
beginConnect(blocking, isa);
|
||||
int n = Net.connect(fd, isa.getAddress(), isa.getPort());
|
||||
int n = Net.connect(family,
|
||||
fd,
|
||||
isa.getAddress(),
|
||||
isa.getPort());
|
||||
if (n > 0) {
|
||||
connected = true;
|
||||
} else if (blocking) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 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
|
||||
@ -29,12 +29,13 @@ import java.lang.reflect.Constructor;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.nio.channels.Channel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import static java.net.StandardProtocolFamily.INET6;
|
||||
import static java.net.StandardProtocolFamily.INET;
|
||||
|
||||
class InheritedChannel {
|
||||
|
||||
@ -81,12 +82,16 @@ class InheritedChannel {
|
||||
*/
|
||||
public static class InheritedSocketChannelImpl extends SocketChannelImpl {
|
||||
|
||||
static ProtocolFamily family(InetSocketAddress isa) {
|
||||
return (isa.getAddress() instanceof Inet6Address) ? INET6 : INET;
|
||||
}
|
||||
|
||||
InheritedSocketChannelImpl(SelectorProvider sp,
|
||||
FileDescriptor fd,
|
||||
InetSocketAddress remote)
|
||||
throws IOException
|
||||
{
|
||||
super(sp, fd, remote);
|
||||
super(sp, family(remote), fd, remote);
|
||||
}
|
||||
|
||||
protected void implCloseSelectableChannel() throws IOException {
|
||||
|
||||
102
test/jdk/java/nio/channels/etc/LocalSocketAddressType.java
Normal file
102
test/jdk/java/nio/channels/etc/LocalSocketAddressType.java
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test local address type
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* @run testng/othervm LocalSocketAddressType
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true LocalSocketAddressType
|
||||
*/
|
||||
|
||||
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.net.*;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Iterator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.Boolean.parseBoolean;
|
||||
import static java.lang.System.getProperty;
|
||||
import static java.lang.System.out;
|
||||
import static jdk.test.lib.Asserts.assertEquals;
|
||||
import static jdk.test.lib.Asserts.assertTrue;
|
||||
import static jdk.test.lib.net.IPSupport.*;
|
||||
|
||||
public class LocalSocketAddressType {
|
||||
|
||||
@BeforeTest()
|
||||
public void setup() {
|
||||
IPSupport.printPlatformSupport(out);
|
||||
throwSkippedExceptionIfNonOperational();
|
||||
}
|
||||
|
||||
@DataProvider(name = "addresses")
|
||||
public static Iterator<Object[]> addresses() throws Exception {
|
||||
NetworkConfiguration nc = NetworkConfiguration.probe();
|
||||
return Stream.concat(nc.ip4Addresses(), nc.ip6Addresses())
|
||||
.map(ia -> new Object[] { new InetSocketAddress(ia, 0) })
|
||||
.iterator();
|
||||
}
|
||||
|
||||
@Test(dataProvider = "addresses")
|
||||
public static void testSocketChannel(InetSocketAddress addr) throws Exception {
|
||||
try (var c = SocketChannel.open()) {
|
||||
Class<? extends InetAddress> cls = addr.getAddress().getClass();
|
||||
InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
ia = c.socket().getLocalAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "addresses")
|
||||
public static void testServerSocketChannel(InetSocketAddress addr) throws Exception {
|
||||
try (var c = ServerSocketChannel.open()) {
|
||||
Class<? extends InetAddress> cls = addr.getAddress().getClass();
|
||||
InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
ia = c.socket().getInetAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "addresses")
|
||||
public static void testDatagramChannel(InetSocketAddress addr) throws Exception {
|
||||
try (var c = DatagramChannel.open()) {
|
||||
Class<? extends InetAddress> cls = addr.getAddress().getClass();
|
||||
InetAddress ia = ((InetSocketAddress)c.bind(addr).getLocalAddress()).getAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
ia = c.socket().getLocalAddress();
|
||||
assertEquals(ia.getClass(), cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
282
test/jdk/java/nio/channels/etc/OpenAndConnect.java
Normal file
282
test/jdk/java/nio/channels/etc/OpenAndConnect.java
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* 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<>();
|
||||
l.addAll(openConnectGenTests);
|
||||
if (IA4LOCAL != null) {
|
||||
l.addAll(openConnectV4LocalTests);
|
||||
}
|
||||
if (IA6LOCAL != null) {
|
||||
l.addAll(openConnectV6LocalTests);
|
||||
}
|
||||
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, }
|
||||
|
||||
public static List<Object[]> openConnectGenTests =
|
||||
Arrays.asList(new Object[][] {
|
||||
{ INET, IA4LOOPBACK, INET, IA4LOOPBACK },
|
||||
{ INET, IA4LOOPBACK, null, IA4LOOPBACK },
|
||||
{ INET, IA4ANYLOCAL, null, IA4LOOPBACK },
|
||||
{ INET, IA4ANYLOCAL, INET, IA4LOOPBACK },
|
||||
{ INET6, IA6ANYLOCAL, null, IA6LOOPBACK },
|
||||
{ INET6, IA6ANYLOCAL, INET6, IA6LOOPBACK },
|
||||
{ INET6, IA6LOOPBACK, INET6, IA6LOOPBACK },
|
||||
{ null, IA4LOOPBACK, INET, IA4ANYLOCAL },
|
||||
{ null, IA4LOOPBACK, INET, IA4LOOPBACK },
|
||||
{ null, IA4LOOPBACK, INET, null },
|
||||
{ null, IA4LOOPBACK, INET6, IA6ANYLOCAL },
|
||||
{ null, IA6LOOPBACK, INET6, IA6ANYLOCAL },
|
||||
{ null, IA6LOOPBACK, INET6, IA6LOOPBACK },
|
||||
{ null, IA6LOOPBACK, INET6, DONT_BIND },
|
||||
{ null, IA4LOOPBACK, INET6, DONT_BIND },
|
||||
{ null, IA4LOOPBACK, INET6, null },
|
||||
{ null, IA6LOOPBACK, INET6, null },
|
||||
{ null, IA4LOOPBACK, null, IA6ANYLOCAL },
|
||||
{ null, IA6LOOPBACK, null, IA6ANYLOCAL },
|
||||
{ null, IA6LOOPBACK, null, IA6LOOPBACK },
|
||||
{ null, IA4LOOPBACK, null, null },
|
||||
{ null, IA6LOOPBACK, null, null },
|
||||
{ null, IA6ANYLOCAL, null, IA6LOCAL },
|
||||
{ null, IA6ANYLOCAL, null, IA6LOOPBACK },
|
||||
{ null, IA6ANYLOCAL, INET6, IA6LOCAL },
|
||||
{ null, IA6ANYLOCAL, INET6, IA6LOOPBACK },
|
||||
{ INET6, IA6LOOPBACK, INET6, IA6LOOPBACK }
|
||||
});
|
||||
|
||||
// Additional tests for when an IPv4 local address or V6
|
||||
// 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, INET6, IA6ANYLOCAL },
|
||||
{ null, IA4LOCAL, INET6, null },
|
||||
{ null, IA4LOCAL, null, IA6ANYLOCAL }
|
||||
});
|
||||
|
||||
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 },
|
||||
{ null, IA6LOCAL, INET6, IA6LOCAL },
|
||||
{ null, IA6LOCAL, INET6, IA6ANYLOCAL },
|
||||
{ null, IA6LOCAL, null, IA6ANYLOCAL },
|
||||
{ null, IA6LOCAL, null, IA6LOCAL },
|
||||
{ null, IA6LOCAL, INET6, null },
|
||||
{ null, IA6LOCAL, null, null },
|
||||
{ null, IA4LOCAL, null, null },
|
||||
{ INET6, IA6LOCAL, INET6, IA6LOCAL }
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
381
test/jdk/java/nio/channels/etc/ProtocolFamilies.java
Normal file
381
test/jdk/java/nio/channels/etc/ProtocolFamilies.java
Normal file
@ -0,0 +1,381 @@
|
||||
/*
|
||||
* 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.Platform;
|
||||
import jdk.test.lib.net.IPSupport;
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import org.testng.Assert.ThrowingRunnable;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.AbstractSelector;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import static java.lang.System.out;
|
||||
import static java.lang.System.getProperty;
|
||||
import static java.lang.Boolean.parseBoolean;
|
||||
import static java.net.StandardProtocolFamily.INET;
|
||||
import static java.net.StandardProtocolFamily.INET6;
|
||||
import static jdk.test.lib.net.IPSupport.*;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test SocketChannel, ServerSocketChannel and DatagramChannel
|
||||
* with various ProtocolFamily combinations
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* @run testng ProtocolFamilies
|
||||
* @run testng/othervm -Djava.net.preferIPv4Stack=true ProtocolFamilies
|
||||
*/
|
||||
|
||||
|
||||
public class ProtocolFamilies {
|
||||
static final boolean hasIPv6 = hasIPv6();
|
||||
static final boolean preferIPv4 = preferIPv4Stack();
|
||||
static Inet4Address ia4;
|
||||
static Inet6Address ia6;
|
||||
|
||||
@BeforeTest()
|
||||
public void setup() throws Exception {
|
||||
NetworkConfiguration.printSystemConfiguration(out);
|
||||
IPSupport.printPlatformSupport(out);
|
||||
throwSkippedExceptionIfNonOperational();
|
||||
|
||||
ia4 = getLocalIPv4Address();
|
||||
ia6 = getLocalIPv6Address();
|
||||
out.println("ia4: " + ia4);
|
||||
out.println("ia6: " + ia6 + "\n");
|
||||
}
|
||||
|
||||
static final Class<UnsupportedAddressTypeException> UATE = UnsupportedAddressTypeException.class;
|
||||
static final Class<UnsupportedOperationException> UOE = UnsupportedOperationException.class;
|
||||
|
||||
@DataProvider(name = "open")
|
||||
public Object[][] open() {
|
||||
if (hasIPv6 && !preferIPv4) {
|
||||
return new Object[][]{
|
||||
{ INET, null },
|
||||
{ INET6, null }
|
||||
};
|
||||
} else {
|
||||
return new Object[][]{
|
||||
{ INET, null },
|
||||
{ INET6, UOE }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "open")
|
||||
public void scOpen(StandardProtocolFamily family,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
SocketChannel sc = null;
|
||||
try {
|
||||
if (expectedException == UOE) {
|
||||
try {
|
||||
sc = openSC(family);
|
||||
} catch (UnsupportedOperationException e) {}
|
||||
} else {
|
||||
sc = openSC(family);
|
||||
}
|
||||
} finally {
|
||||
if (sc != null)
|
||||
sc.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "open")
|
||||
public void sscOpen(StandardProtocolFamily family,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
ServerSocketChannel ssc = null;
|
||||
try {
|
||||
if (expectedException == UOE) {
|
||||
try {
|
||||
ssc = openSSC(family);
|
||||
} catch (UnsupportedOperationException e) {}
|
||||
} else {
|
||||
openSSC(family);
|
||||
}
|
||||
} finally {
|
||||
if (ssc != null)
|
||||
ssc.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "open")
|
||||
public void dcOpen(StandardProtocolFamily family,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
DatagramChannel dc = null;
|
||||
try {
|
||||
if (expectedException == UOE) {
|
||||
try {
|
||||
dc = openDC(family);
|
||||
} catch (UnsupportedOperationException e) {}
|
||||
} else {
|
||||
openDC(family);
|
||||
}
|
||||
} finally {
|
||||
if (dc != null)
|
||||
dc.close();
|
||||
}
|
||||
}
|
||||
|
||||
@DataProvider(name = "openBind")
|
||||
public Object[][] openBind() {
|
||||
if (hasIPv6 && !preferIPv4) {
|
||||
return new Object[][]{
|
||||
{ INET, INET, null },
|
||||
{ INET, INET6, UATE },
|
||||
{ INET, null, null },
|
||||
{ INET6, INET, null },
|
||||
{ INET6, INET6, null },
|
||||
{ INET6, null, null },
|
||||
{ null, INET, null },
|
||||
{ null, INET6, null },
|
||||
{ null, null, null }
|
||||
};
|
||||
} else {
|
||||
return new Object[][]{
|
||||
{ INET, INET, null },
|
||||
{ INET, INET6, UATE },
|
||||
{ INET, null, null },
|
||||
{ null, INET, null },
|
||||
{ null, INET6, UATE },
|
||||
{ null, null, null }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// SocketChannel open - INET, INET6, default
|
||||
// SocketChannel bind - INET, INET6, null
|
||||
|
||||
@Test(dataProvider = "openBind")
|
||||
public void scOpenBind(StandardProtocolFamily ofamily,
|
||||
StandardProtocolFamily bfamily,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
try (SocketChannel sc = openSC(ofamily)) {
|
||||
SocketAddress addr = getSocketAddress(bfamily);
|
||||
ThrowingRunnable bindOp = () -> sc.bind(addr);
|
||||
if (expectedException == null)
|
||||
bindOp.run();
|
||||
else
|
||||
assertThrows(expectedException, bindOp);
|
||||
}
|
||||
}
|
||||
|
||||
// ServerSocketChannel open - INET, INET6, default
|
||||
// ServerSocketChannel bind - INET, INET6, null
|
||||
|
||||
@Test(dataProvider = "openBind")
|
||||
public void sscOpenBind(StandardProtocolFamily ofamily,
|
||||
StandardProtocolFamily bfamily,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
try (ServerSocketChannel ssc = openSSC(ofamily)) {
|
||||
SocketAddress addr = getSocketAddress(bfamily);
|
||||
ThrowingRunnable bindOp = () -> ssc.bind(addr);
|
||||
if (expectedException == null)
|
||||
bindOp.run();
|
||||
else
|
||||
assertThrows(expectedException, bindOp);
|
||||
}
|
||||
}
|
||||
|
||||
// DatagramChannel open - INET, INET6, default
|
||||
// DatagramChannel bind - INET, INET6, null
|
||||
|
||||
@Test(dataProvider = "openBind")
|
||||
public void dcOpenBind(StandardProtocolFamily ofamily,
|
||||
StandardProtocolFamily bfamily,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
try (DatagramChannel dc = openDC(ofamily)) {
|
||||
SocketAddress addr = getSocketAddress(bfamily);
|
||||
ThrowingRunnable bindOp = () -> dc.bind(addr);
|
||||
if (expectedException == null)
|
||||
bindOp.run();
|
||||
else
|
||||
assertThrows(expectedException, bindOp);
|
||||
}
|
||||
}
|
||||
|
||||
// SocketChannel open - INET, INET6, default
|
||||
// SocketChannel connect - INET, INET6, default
|
||||
|
||||
@DataProvider(name = "openConnect")
|
||||
public Object[][] openConnect() {
|
||||
if (hasIPv6 && !preferIPv4) {
|
||||
return new Object[][]{
|
||||
{ INET, INET, null },
|
||||
{ INET, INET6, null },
|
||||
{ INET, null, null },
|
||||
{ INET6, INET, UATE },
|
||||
{ INET6, INET6, null },
|
||||
{ INET6, null, null },
|
||||
{ null, INET, UATE },
|
||||
{ null, INET6, null },
|
||||
{ null, null, null }
|
||||
};
|
||||
} else {
|
||||
// INET6 channels cannot be created - UOE - tested elsewhere
|
||||
return new Object[][]{
|
||||
{ INET, INET, null },
|
||||
{ INET, null, null },
|
||||
{ null, INET, null },
|
||||
{ null, null, null }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Test(dataProvider = "openConnect")
|
||||
public void scOpenConnect(StandardProtocolFamily sfamily,
|
||||
StandardProtocolFamily cfamily,
|
||||
Class<? extends Exception> expectedException)
|
||||
throws Throwable
|
||||
{
|
||||
try (ServerSocketChannel ssc = openSSC(sfamily)) {
|
||||
ssc.bind(null);
|
||||
SocketAddress saddr = ssc.getLocalAddress();
|
||||
try (SocketChannel sc = openSC(cfamily)) {
|
||||
if (expectedException == null)
|
||||
sc.connect(saddr);
|
||||
else
|
||||
assertThrows(expectedException, () -> sc.connect(saddr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final Class<NullPointerException> NPE = NullPointerException.class;
|
||||
|
||||
// Tests null handling
|
||||
@Test
|
||||
public void testNulls() {
|
||||
assertThrows(NPE, () -> SocketChannel.open((ProtocolFamily)null));
|
||||
assertThrows(NPE, () -> ServerSocketChannel.open(null));
|
||||
assertThrows(NPE, () -> DatagramChannel.open(null));
|
||||
|
||||
assertThrows(NPE, () -> SelectorProvider.provider().openSocketChannel(null));
|
||||
assertThrows(NPE, () -> SelectorProvider.provider().openServerSocketChannel(null));
|
||||
assertThrows(NPE, () -> SelectorProvider.provider().openDatagramChannel(null));
|
||||
}
|
||||
|
||||
static final ProtocolFamily BAD_PF = () -> "BAD_PROTOCOL_FAMILY";
|
||||
|
||||
// Tests UOE handling
|
||||
@Test
|
||||
public void testUoe() {
|
||||
assertThrows(UOE, () -> SocketChannel.open(BAD_PF));
|
||||
assertThrows(UOE, () -> ServerSocketChannel.open(BAD_PF));
|
||||
assertThrows(UOE, () -> DatagramChannel.open(BAD_PF));
|
||||
|
||||
assertThrows(UOE, () -> SelectorProvider.provider().openSocketChannel(BAD_PF));
|
||||
assertThrows(UOE, () -> SelectorProvider.provider().openServerSocketChannel(BAD_PF));
|
||||
assertThrows(UOE, () -> SelectorProvider.provider().openDatagramChannel(BAD_PF));
|
||||
}
|
||||
|
||||
// A concrete subclass of SelectorProvider, in order to test implSpec
|
||||
static final SelectorProvider customerSelectorProvider = new SelectorProvider() {
|
||||
@Override public DatagramChannel openDatagramChannel() { return null; }
|
||||
@Override public DatagramChannel openDatagramChannel(ProtocolFamily family) { return null; }
|
||||
@Override public Pipe openPipe() { return null; }
|
||||
@Override public AbstractSelector openSelector() { return null; }
|
||||
@Override public ServerSocketChannel openServerSocketChannel() { return null; }
|
||||
@Override public SocketChannel openSocketChannel() { return null; }
|
||||
};
|
||||
|
||||
// Tests the specified default implementation of SelectorProvider
|
||||
@Test
|
||||
public void testCustomProvider() {
|
||||
assertThrows(NPE, () -> customerSelectorProvider.openSocketChannel(null));
|
||||
assertThrows(NPE, () -> customerSelectorProvider.openServerSocketChannel(null));
|
||||
|
||||
assertThrows(UOE, () -> customerSelectorProvider.openSocketChannel(BAD_PF));
|
||||
assertThrows(UOE, () -> customerSelectorProvider.openServerSocketChannel(BAD_PF));
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
private static SocketChannel openSC(StandardProtocolFamily family)
|
||||
throws IOException {
|
||||
return family == null ? SocketChannel.open()
|
||||
: SocketChannel.open(family);
|
||||
}
|
||||
|
||||
private static ServerSocketChannel openSSC(StandardProtocolFamily family)
|
||||
throws IOException {
|
||||
return family == null ? ServerSocketChannel.open()
|
||||
: ServerSocketChannel.open(family);
|
||||
}
|
||||
|
||||
private static DatagramChannel openDC(StandardProtocolFamily family)
|
||||
throws IOException {
|
||||
return family == null ? DatagramChannel.open()
|
||||
: DatagramChannel.open(family);
|
||||
}
|
||||
|
||||
private static SocketAddress getSocketAddress(StandardProtocolFamily family) {
|
||||
return family == null ? null : switch (family) {
|
||||
case INET -> new InetSocketAddress(ia4, 0);
|
||||
case INET6 -> new InetSocketAddress(ia6, 0);
|
||||
};
|
||||
}
|
||||
|
||||
private static SocketAddress getLoopback(StandardProtocolFamily family, int port)
|
||||
throws UnknownHostException {
|
||||
if ((family == null || family == INET6) && hasIPv6) {
|
||||
return new InetSocketAddress(InetAddress.getByName("::1"), port);
|
||||
} else {
|
||||
return new InetSocketAddress(InetAddress.getByName("127.0.0.1"), port);
|
||||
}
|
||||
}
|
||||
|
||||
private static Inet4Address getLocalIPv4Address()
|
||||
throws Exception {
|
||||
return NetworkConfiguration.probe()
|
||||
.ip4Addresses()
|
||||
.filter(a -> !a.isLoopbackAddress())
|
||||
.findFirst()
|
||||
.orElse((Inet4Address)InetAddress.getByName("0.0.0.0"));
|
||||
}
|
||||
|
||||
private static Inet6Address getLocalIPv6Address()
|
||||
throws Exception {
|
||||
return NetworkConfiguration.probe()
|
||||
.ip6Addresses()
|
||||
.filter(a -> !a.isLoopbackAddress())
|
||||
.findFirst()
|
||||
.orElse((Inet6Address) InetAddress.getByName("::0"));
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user