# HG changeset patch # User igerasim # Date 1523643675 25200 # Fri Apr 13 11:21:15 2018 -0700 # Node ID f6ca2602a503093f2a6749553623ef45034d666d # Parent 4902927396523f324766b4c461ed6c99fd9aa5d3 [mq]: 8201510-Merge-TwoStacksPlainSocketImpl-into-DualStackPlainSocketImpl diff --git a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java b/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java --- a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java +++ b/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java @@ -26,14 +26,18 @@ import java.io.IOException; import java.io.FileDescriptor; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.security.action.GetPropertyAction; import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.JavaIOFileDescriptorAccess; /** - * This class defines the plain SocketImpl that is used on Windows platforms - * greater or equal to Windows Vista. These platforms have a dual - * layer TCP/IP stack and can handle both IPv4 and IPV6 through a - * single file descriptor. + * This class defines the plain SocketImpl. + * When java.net.preferIPv4Stack system property is set to true, it uses + * IPv4-only socket. + * When java.net.preferIPv4Stack is set to false, it handles both IPv4 + * and IPv6 through a single file descriptor. * * @author Chris Hegarty */ @@ -43,30 +47,35 @@ private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); - // true if this socket is exclusively bound - private final boolean exclusiveBind; + private static final boolean preferIPv4Stack = + Boolean.parseBoolean(AccessController.doPrivileged( + new GetPropertyAction("java.net.preferIPv4Stack", "false"))); - // emulates SO_REUSEADDR when exclusiveBind is true + private static final boolean useExclusiveBind = + Boolean.parseBoolean(AccessController.doPrivileged( + new GetPropertyAction("sun.net.useExclusiveBind", "true"))); + + // emulates SO_REUSEADDR when useExclusiveBind is true private boolean isReuseAddress; - public DualStackPlainSocketImpl(boolean exclBind) { - exclusiveBind = exclBind; + public DualStackPlainSocketImpl() { } - public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) { + public DualStackPlainSocketImpl(FileDescriptor fd) { this.fd = fd; - exclusiveBind = exclBind; } + @Override void socketCreate(boolean stream) throws IOException { if (fd == null) throw new SocketException("Socket closed"); - int newfd = socket0(stream, false /*v6 Only*/); + int newfd = socket0(stream); fdAccess.set(fd, newfd); } + @Override void socketConnect(InetAddress address, int port, int timeout) throws IOException { int nativefd = checkAndReturnNativeFD(); @@ -74,6 +83,9 @@ if (address == null) throw new NullPointerException("inet address argument is null."); + if (preferIPv4Stack && !(address instanceof Inet4Address)) + throw new SocketException("Protocol family not supported"); + int connectResult; if (timeout <= 0) { connectResult = connect0(nativefd, address, port); @@ -97,13 +109,17 @@ localport = localPort0(nativefd); } + @Override void socketBind(InetAddress address, int port) throws IOException { int nativefd = checkAndReturnNativeFD(); if (address == null) throw new NullPointerException("inet address argument is null."); - bind0(nativefd, address, port, exclusiveBind); + if (preferIPv4Stack && !(address instanceof Inet4Address)) + throw new SocketException("Protocol family not supported"); + + bind0(nativefd, address, port, useExclusiveBind); if (port == 0) { localport = localPort0(nativefd); } else { @@ -113,12 +129,14 @@ this.address = address; } + @Override void socketListen(int backlog) throws IOException { int nativefd = checkAndReturnNativeFD(); listen0(nativefd, backlog); } + @Override void socketAccept(SocketImpl s) throws IOException { int nativefd = checkAndReturnNativeFD(); @@ -148,13 +166,17 @@ s.port = isa.getPort(); s.address = isa.getAddress(); s.localport = localport; + if (preferIPv4Stack && !(s.address instanceof Inet4Address)) + throw new SocketException("Protocol family not supported"); } + @Override int socketAvailable() throws IOException { int nativefd = checkAndReturnNativeFD(); return available0(nativefd); } + @Override void socketClose0(boolean useDeferredClose/*unused*/) throws IOException { if (fd == null) throw new SocketException("Socket closed"); @@ -167,6 +189,7 @@ close0(nativefd); } + @Override void socketShutdown(int howto) throws IOException { int nativefd = checkAndReturnNativeFD(); shutdown0(nativefd, howto); @@ -174,41 +197,51 @@ // Intentional fallthrough after SO_REUSEADDR @SuppressWarnings("fallthrough") + @Override void socketSetOption(int opt, boolean on, Object value) throws SocketException { - int nativefd = checkAndReturnNativeFD(); - if (opt == SO_TIMEOUT) { // timeout implemented through select. - return; - } // SO_REUSEPORT is not supported on Windows. if (opt == SO_REUSEPORT) { throw new UnsupportedOperationException("unsupported option"); } + int nativefd = checkAndReturnNativeFD(); + + if (opt == SO_TIMEOUT) { + if (preferIPv4Stack) { + // Don't enable the socket option on ServerSocket as it's + // meaningless (we don't receive on a ServerSocket). + if (serverSocket == null) { + setSoTimeout0(nativefd, ((Integer)value).intValue()); + } + } // else timeout is implemented through select. + return; + } + int optionValue = 0; switch(opt) { - case SO_REUSEADDR : - if (exclusiveBind) { + case SO_REUSEADDR: + if (useExclusiveBind) { // SO_REUSEADDR emulated when using exclusive bind isReuseAddress = on; return; } // intentional fallthrough - case TCP_NODELAY : - case SO_OOBINLINE : - case SO_KEEPALIVE : + case TCP_NODELAY: + case SO_OOBINLINE: + case SO_KEEPALIVE: optionValue = on ? 1 : 0; break; - case SO_SNDBUF : - case SO_RCVBUF : - case IP_TOS : + case SO_SNDBUF: + case SO_RCVBUF: + case IP_TOS: optionValue = ((Integer)value).intValue(); break; - case SO_LINGER : + case SO_LINGER: if (on) { - optionValue = ((Integer)value).intValue(); + optionValue = ((Integer)value).intValue(); } else { optionValue = -1; } @@ -220,7 +253,15 @@ setIntOption(nativefd, opt, optionValue); } - int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + @Override + int socketGetOption(int opt, Object iaContainerObj) + throws SocketException { + + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } + int nativefd = checkAndReturnNativeFD(); // SO_BINDADDR is not a socket option. @@ -228,27 +269,24 @@ localAddress(nativefd, (InetAddressContainer)iaContainerObj); return 0; // return value doesn't matter. } - // SO_REUSEPORT is not supported on Windows. - if (opt == SO_REUSEPORT) { - throw new UnsupportedOperationException("unsupported option"); - } // SO_REUSEADDR emulated when using exclusive bind - if (opt == SO_REUSEADDR && exclusiveBind) - return isReuseAddress? 1 : -1; + if (opt == SO_REUSEADDR && useExclusiveBind) + return isReuseAddress ? 1 : -1; int value = getIntOption(nativefd, opt); switch (opt) { - case TCP_NODELAY : - case SO_OOBINLINE : - case SO_KEEPALIVE : - case SO_REUSEADDR : + case TCP_NODELAY: + case SO_OOBINLINE: + case SO_KEEPALIVE: + case SO_REUSEADDR: return (value == 0) ? -1 : 1; } return value; } + @Override void socketSendUrgentData(int data) throws IOException { int nativefd = checkAndReturnNativeFD(); sendOOB(nativefd, data); @@ -271,7 +309,7 @@ static native void initIDs(); - static native int socket0(boolean stream, boolean v6Only) throws IOException; + static native int socket0(boolean stream) throws IOException; static native void bind0(int fd, InetAddress localAddress, int localport, boolean exclBind) @@ -300,6 +338,8 @@ static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException; + static native void setSoTimeout0(int fd, int timeout) throws SocketException; + static native int getIntOption(int fd, int cmd) throws SocketException; static native void sendOOB(int fd, int data) throws IOException; diff --git a/src/java.base/windows/classes/java/net/PlainSocketImpl.java b/src/java.base/windows/classes/java/net/PlainSocketImpl.java --- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java +++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java @@ -25,20 +25,13 @@ package java.net; import java.io.*; -import java.security.AccessController; -import java.security.PrivilegedAction; -import sun.security.action.GetPropertyAction; /* * This class PlainSocketImpl simply delegates to the appropriate real * SocketImpl. We do this because PlainSocketImpl is already extended * by SocksSocketImpl. *
- * There are two possibilities for the real SocketImpl,
- * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use
- * DualStackPlainSocketImpl on systems that have a dual stack
- * TCP implementation. Otherwise we create an instance of
- * TwoStacksPlainSocketImpl and delegate to it.
+ * There is one possibility for the real SocketImpl: DualStackPlainSocketImpl.
*
* @author Chris Hegarty
*/
@@ -46,44 +39,18 @@
class PlainSocketImpl extends AbstractPlainSocketImpl {
private AbstractPlainSocketImpl impl;
- /* java.net.preferIPv4Stack */
- private static final boolean preferIPv4Stack;
-
- /* True if exclusive binding is on for Windows */
- private static final boolean exclusiveBind;
-
- static {
- preferIPv4Stack = Boolean.parseBoolean(
- AccessController.doPrivileged(
- new GetPropertyAction("java.net.preferIPv4Stack")));
-
- String exclBindProp = AccessController.doPrivileged(
- new GetPropertyAction("sun.net.useExclusiveBind", ""));
- exclusiveBind = (exclBindProp.isEmpty())
- ? true
- : Boolean.parseBoolean(exclBindProp);
- }
-
/**
* Constructs an empty instance.
*/
PlainSocketImpl() {
- if (!preferIPv4Stack) {
- impl = new DualStackPlainSocketImpl(exclusiveBind);
- } else {
- impl = new TwoStacksPlainSocketImpl(exclusiveBind);
- }
+ impl = new DualStackPlainSocketImpl();
}
/**
* Constructs an instance with the given file descriptor.
*/
PlainSocketImpl(FileDescriptor fd) {
- if (!preferIPv4Stack) {
- impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
- } else {
- impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
- }
+ impl = new DualStackPlainSocketImpl(fd);
}
// Override methods in SocketImpl that access impl's fields.
@@ -148,18 +115,10 @@
}
public void setOption(int opt, Object val) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
impl.setOption(opt, val);
}
public Object getOption(int opt) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
return impl.getOption(opt);
}
@@ -271,8 +230,8 @@
// Override methods in AbstractPlainSocketImpl that need to be implemented.
- void socketCreate(boolean isServer) throws IOException {
- impl.socketCreate(isServer);
+ void socketCreate(boolean stream) throws IOException {
+ impl.socketCreate(stream);
}
void socketConnect(InetAddress address, int port, int timeout)
@@ -307,18 +266,10 @@
void socketSetOption(int cmd, boolean on, Object value)
throws SocketException {
- if (cmd == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
impl.socketSetOption(cmd, on, value);
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
- if (opt == SocketOptions.SO_REUSEPORT) {
- // SO_REUSEPORT is not supported on Windows.
- throw new UnsupportedOperationException("unsupported option");
- }
return impl.socketGetOption(opt, iaContainerObj);
}
diff --git a/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java b/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java
deleted file mode 100644
--- a/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package java.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-import sun.net.ResourceManager;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.misc.JavaIOFileDescriptorAccess;
-
-/*
- * This class defines the plain SocketImpl that is used when
- * the System property java.net.preferIPv4Stack is set to true.
- *
- * @author Chris Hegarty
- */
-
-class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
-
- private static final JavaIOFileDescriptorAccess fdAccess =
- SharedSecrets.getJavaIOFileDescriptorAccess();
-
- // true if this socket is exclusively bound
- private final boolean exclusiveBind;
-
- // emulates SO_REUSEADDR when exclusiveBind is true
- private boolean isReuseAddress;
-
- public TwoStacksPlainSocketImpl(boolean exclBind) {
- exclusiveBind = exclBind;
- }
-
- public TwoStacksPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
- this.fd = fd;
- exclusiveBind = exclBind;
- }
-
- void socketCreate(boolean stream) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- int newfd = socket0(stream, false /*v6 Only*/);
-
- fdAccess.set(fd, newfd);
- }
-
- @Override
- void socketConnect(InetAddress address, int port, int timeout)
- throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- int connectResult;
- if (timeout <= 0) {
- connectResult = connect0(nativefd, address, port);
- } else {
- configureBlocking(nativefd, false);
- try {
- connectResult = connect0(nativefd, address, port);
- if (connectResult == WOULDBLOCK) {
- waitForConnect(nativefd, timeout);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /*
- * We need to set the local port field. If bind was called
- * previous to the connect (by the client) then localport field
- * will already be set.
- */
- if (localport == 0)
- localport = localPort0(nativefd);
- }
-
- @Override
- void socketBind(InetAddress address, int port) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (address == null)
- throw new NullPointerException("inet address argument is null.");
-
- bind0(nativefd, address, port, exclusiveBind);
- if (port == 0) {
- localport = localPort0(nativefd);
- } else {
- localport = port;
- }
-
- this.address = address;
- }
-
- @Override
- void socketListen(int backlog) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- listen0(nativefd, backlog);
- }
-
- @Override
- void socketAccept(SocketImpl s) throws IOException {
- int nativefd = checkAndReturnNativeFD();
-
- if (s == null)
- throw new NullPointerException("socket is null");
-
- int newfd = -1;
- InetSocketAddress[] isaa = new InetSocketAddress[1];
- if (timeout <= 0) {
- newfd = accept0(nativefd, isaa);
- } else {
- configureBlocking(nativefd, false);
- try {
- waitForNewConnection(nativefd, timeout);
- newfd = accept0(nativefd, isaa);
- if (newfd != -1) {
- configureBlocking(newfd, true);
- }
- } finally {
- configureBlocking(nativefd, true);
- }
- }
- /* Update (SocketImpl)s' fd */
- fdAccess.set(s.fd, newfd);
- /* Update socketImpls remote port, address and localport */
- InetSocketAddress isa = isaa[0];
- s.port = isa.getPort();
- s.address = isa.getAddress();
- s.localport = localport;
- }
-
- @Override
- int socketAvailable() throws IOException {
- int nativefd = checkAndReturnNativeFD();
- return available0(nativefd);
- }
-
- @Override
- void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
- if (fd == null)
- throw new SocketException("Socket closed");
-
- if (!fd.valid())
- return;
-
- final int nativefd = fdAccess.get(fd);
- fdAccess.set(fd, -1);
- close0(nativefd);
- }
-
- @Override
- void socketShutdown(int howto) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- shutdown0(nativefd, howto);
- }
-
- // Intentional fallthrough after SO_REUSEADDR
- @SuppressWarnings("fallthrough")
- @Override
- void socketSetOption(int opt, boolean on, Object value)
- throws SocketException {
- int nativefd = checkAndReturnNativeFD();
-
- if (opt == SO_TIMEOUT) {
- // Don't enable the socket option on ServerSocket as it's
- // meaningless (we don't receive on a ServerSocket).
- if (serverSocket == null) {
- setSoTimeout0(nativefd, ((Integer)value).intValue());
- }
- return;
- }
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- int optionValue = 0;
-
- switch(opt) {
- case SO_REUSEADDR :
- if (exclusiveBind) {
- // SO_REUSEADDR emulated when using exclusive bind
- isReuseAddress = on;
- return;
- }
- // intentional fallthrough
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
- optionValue = on ? 1 : 0;
- break;
- case SO_SNDBUF :
- case SO_RCVBUF :
- case IP_TOS :
- optionValue = ((Integer)value).intValue();
- break;
- case SO_LINGER :
- if (on) {
- optionValue = ((Integer)value).intValue();
- } else {
- optionValue = -1;
- }
- break;
- default :/* shouldn't get here */
- throw new SocketException("Option not supported");
- }
-
- setIntOption(nativefd, opt, optionValue);
- }
-
- @Override
- int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
- int nativefd = checkAndReturnNativeFD();
-
- // SO_BINDADDR is not a socket option.
- if (opt == SO_BINDADDR) {
- localAddress(nativefd, (InetAddressContainer)iaContainerObj);
- return 0; // return value doesn't matter.
- }
- // SO_REUSEPORT is not supported on Windows.
- if (opt == SO_REUSEPORT) {
- throw new UnsupportedOperationException("unsupported option");
- }
-
- // SO_REUSEADDR emulated when using exclusive bind
- if (opt == SO_REUSEADDR && exclusiveBind)
- return isReuseAddress? 1 : -1;
-
- int value = getIntOption(nativefd, opt);
-
- switch (opt) {
- case TCP_NODELAY :
- case SO_OOBINLINE :
- case SO_KEEPALIVE :
- case SO_REUSEADDR :
- return (value == 0) ? -1 : 1;
- }
- return value;
- }
-
- @Override
- void socketSendUrgentData(int data) throws IOException {
- int nativefd = checkAndReturnNativeFD();
- sendOOB(nativefd, data);
- }
-
- private int checkAndReturnNativeFD() throws SocketException {
- if (fd == null || !fd.valid())
- throw new SocketException("Socket closed");
-
- return fdAccess.get(fd);
- }
-
- static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
-
- static {
- initIDs();
- }
-
- /* Native methods */
-
- static native void initIDs();
-
- static native int socket0(boolean stream, boolean v6Only) throws IOException;
-
- static native void bind0(int fd, InetAddress localAddress, int localport,
- boolean exclBind)
- throws IOException;
-
- static native int connect0(int fd, InetAddress remote, int remotePort)
- throws IOException;
-
- static native void waitForConnect(int fd, int timeout) throws IOException;
-
- static native int localPort0(int fd) throws IOException;
-
- static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
-
- static native void listen0(int fd, int backlog) throws IOException;
-
- static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
-
- static native void waitForNewConnection(int fd, int timeout) throws IOException;
-
- static native int available0(int fd) throws IOException;
-
- static native void close0(int fd) throws IOException;
-
- static native void shutdown0(int fd, int howto) throws IOException;
-
- static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
-
- static native void setSoTimeout0(int fd, int timeout) throws SocketException;
-
- static native int getIntOption(int fd, int cmd) throws SocketException;
-
- static native void sendOOB(int fd, int data) throws IOException;
-
- static native void configureBlocking(int fd, boolean blocking) throws IOException;
-}
diff --git a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c b/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
+++ b/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -27,8 +27,8 @@
#include "java_net_DualStackPlainSocketImpl.h"
#include "java_net_SocketOptions.h"
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
+#define SET_BLOCKING 0
+#define SET_NONBLOCKING 1
static jclass isa_class; /* java.net.InetSocketAddress */
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
@@ -60,22 +60,28 @@
* Signature: (ZZ)I
*/
JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
- (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
+ (JNIEnv *env, jclass clazz, jboolean stream) {
int fd, rv, opt=0;
+ int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
- fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+ fd = NET_Socket(domain, type, 0);
+
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "create");
return -1;
}
- rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
- if (rv == SOCKET_ERROR) {
- NET_ThrowNew(env, WSAGetLastError(), "create");
+ if (domain == AF_INET6) {
+ rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
+ sizeof(opt));
+ if (rv == SOCKET_ERROR) {
+ NET_ThrowNew(env, WSAGetLastError(), "create");
+ closesocket(fd);
+ return -1;
+ }
}
- SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
-
return fd;
}
@@ -90,10 +96,11 @@
{
SOCKETADDRESS sa;
int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_TRUE) != 0) {
- return;
+ &sa_len, v4MappedAddress) != 0) {
+ return;
}
rv = NET_WinBind(fd, &sa, sa_len, exclBind);
@@ -111,10 +118,11 @@
(JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
SOCKETADDRESS sa;
int rv, sa_len = 0;
+ jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
- &sa_len, JNI_TRUE) != 0) {
- return -1;
+ &sa_len, v4MappedAddress) != 0) {
+ return -1;
}
rv = connect(fd, &sa.sa, sa_len);
@@ -124,7 +132,8 @@
return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
} else if (err == WSAEADDRNOTAVAIL) {
JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
- "connect: Address is invalid on local machine, or port is not valid on remote machine");
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
} else {
NET_ThrowNew(env, err, "connect");
}
@@ -200,6 +209,10 @@
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
"Unable to establish connection");
+ } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+ "connect: Address is invalid on local machine,"
+ " or port is not valid on remote machine");
} else {
NET_ThrowNew(env, rv, "connect");
}
@@ -284,13 +297,7 @@
newfd = accept(fd, &sa.sa, &len);
if (newfd == INVALID_SOCKET) {
- if (WSAGetLastError() == -2) {
- JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
- "operation interrupted");
- } else {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "socket closed");
- }
+ NET_ThrowNew(env, WSAGetLastError(), "accept failed");
return -1;
}
@@ -298,6 +305,10 @@
ia = NET_SockaddrToInetAddress(env, &sa, &port);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
+ if (isa == NULL) {
+ closesocket(newfd);
+ return -1;
+ }
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
return newfd;
@@ -402,6 +413,51 @@
/*
* Class: java_net_DualStackPlainSocketImpl
+ * Method: setSoTimeout0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
+ (JNIEnv *env, jclass clazz, jint fd, jint timeout)
+{
+ /*
+ * SO_TIMEOUT is the socket option used to specify the timeout
+ * for ServerSocket.accept and Socket.getInputStream().read.
+ * It does not typically map to a native level socket option.
+ * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
+ * socket option to specify a receive timeout on the socket. This
+ * receive timeout is applicable to Socket only and the socket
+ * option should not be set on ServerSocket.
+ */
+
+ /*
+ * SO_RCVTIMEO is only supported on Microsoft's implementation
+ * of Windows Sockets so if WSAENOPROTOOPT returned then
+ * reset flag and timeout will be implemented using
+ * select() -- see SocketInputStream.socketRead.
+ */
+ if (isRcvTimeoutSupported) {
+ /*
+ * Disable SO_RCVTIMEO if timeout is <= 5 second.
+ */
+ if (timeout <= 5000) {
+ timeout = 0;
+ }
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+ sizeof(timeout)) < 0) {
+ int err = WSAGetLastError();
+ if (err == WSAENOPROTOOPT) {
+ isRcvTimeoutSupported = JNI_FALSE;
+ } else {
+ NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
+ }
+ }
+ }
+}
+
+/*
+ * Class: java_net_DualStackPlainSocketImpl
* Method: getIntOption
* Signature: (II)I
*/
@@ -466,7 +522,7 @@
int result;
if (blocking == JNI_TRUE) {
- arg = SET_BLOCKING; // 0
+ arg = SET_BLOCKING; // 0
} else {
arg = SET_NONBLOCKING; // 1
}
diff --git a/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
deleted file mode 100644
--- a/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
+++ /dev/null
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 1997, 2018, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-#include "net_util.h"
-
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_InetAddress.h"
-
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
-
-static jclass isa_class; /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) */
-
-/************************************************************************
- * TwoStacksPlainSocketImpl
- */
-
-/*
- * The initIDs function is called whenever TwoStacksPlainSocketImpl is
- * loaded, to cache fieldIds for efficiency. This is called everytime
- * the Java class is loaded.
- *
- * Class: java_net_TwoStacksPlainSocketImpl
- * Method: initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_initIDs
- (JNIEnv *env, jclass clazz) {
-
- jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
- CHECK_NULL(cls);
- isa_class = (*env)->NewGlobalRef(env, cls);
- CHECK_NULL(isa_class);
- isa_ctorID = (*env)->GetMethodID(env, cls, "