--- old/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java 2018-03-06 12:26:27.714157956 -0800 +++ new/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java 2018-03-06 12:26:27.114157956 -0800 @@ -26,22 +26,15 @@ import java.io.IOException; import java.io.FileDescriptor; -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 that is used when + * the System property java.net.preferIPv4Stack is set to false. * * @author Chris Hegarty */ -class DualStackPlainSocketImpl extends AbstractPlainSocketImpl -{ - static JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess(); - +class DualStackPlainSocketImpl extends AbstractPlainSocketImpl { // true if this socket is exclusively bound private final boolean exclusiveBind; @@ -83,33 +76,18 @@ } @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) { + int socketGetOption(int opt, Object iaContainerObj) + throws SocketException + { + if (opt == SO_REUSEADDR && exclusiveBind) { + // SO_REUSEADDR emulated when using exclusive bind + return isReuseAddress ? 1 : -1; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. throw new UnsupportedOperationException("unsupported option"); + } else { + return socketNativeGetOption(opt, iaContainerObj); } - - // 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; } /* Native methods */ @@ -134,9 +112,6 @@ native void socketShutdown(int howto) throws IOException; - static native int getIntOption(int fd, int cmd) throws SocketException; - static native void localAddress(int fd, InetAddressContainer in) throws SocketException; - native void socketNativeSetOption(int cmd, boolean on, Object value) throws SocketException; @@ -144,11 +119,4 @@ throws SocketException; native void socketSendUrgentData(int data) throws IOException; - - private int checkAndReturnNativeFD() throws SocketException { - if (fd == null || !fd.valid()) - throw new SocketException("Socket closed"); - - return fdAccess.get(fd); - } } --- old/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c 2018-03-06 12:26:28.798157956 -0800 +++ new/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c 2018-03-06 12:26:28.482157956 -0800 @@ -371,33 +371,6 @@ /* * Class: java_net_DualStackPlainSocketImpl - * Method: localAddress - * Signature: (ILjava/net/InetAddressContainer;)V - */ -JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress - (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) { - int port; - SOCKETADDRESS sa; - int len = sizeof(sa); - jobject iaObj; - jclass iaContainerClass; - jfieldID iaFieldID; - - if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { - NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); - return; - } - iaObj = NET_SockaddrToInetAddress(env, &sa, &port); - CHECK_NULL(iaObj); - - iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj); - iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;"); - CHECK_NULL(iaFieldID); - (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); -} - -/* - * Class: java_net_DualStackPlainSocketImpl * Method: socketListen * Signature: (I)V */ @@ -619,44 +592,6 @@ /* * Class: java_net_DualStackPlainSocketImpl - * Method: getIntOption - * Signature: (II)I - */ -JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption - (JNIEnv *env, jclass clazz, jint fd, jint cmd) -{ - int level = 0, opt = 0; - int result=0; - struct linger linger = {0, 0}; - char *arg; - int arglen; - - if (NET_MapSocketOption(cmd, &level, &opt) < 0) { - JNU_ThrowByName(env, "java/net/SocketException", "Invalid option"); - return -1; - } - - if (opt == java_net_SocketOptions_SO_LINGER) { - arg = (char *)&linger; - arglen = sizeof(linger); - } else { - arg = (char *)&result; - arglen = sizeof(result); - } - - if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) { - NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); - return -1; - } - - if (opt == java_net_SocketOptions_SO_LINGER) - return linger.l_onoff ? linger.l_linger : -1; - else - return result; -} - -/* - * Class: java_net_DualStackPlainSocketImpl * Method: socketNativeSetOption * Signature: (IZLjava/lang/Object;)V */ @@ -706,17 +641,17 @@ switch (cmd) { - case java_net_SocketOptions_TCP_NODELAY : - case java_net_SocketOptions_SO_OOBINLINE : - case java_net_SocketOptions_SO_KEEPALIVE : - case java_net_SocketOptions_SO_REUSEADDR : + case java_net_SocketOptions_TCP_NODELAY: + case java_net_SocketOptions_SO_OOBINLINE: + case java_net_SocketOptions_SO_KEEPALIVE: + case java_net_SocketOptions_SO_REUSEADDR: optval.i = (on ? 1 : 0); optlen = sizeof(optval.i); break; - case java_net_SocketOptions_SO_SNDBUF : - case java_net_SocketOptions_SO_RCVBUF : - case java_net_SocketOptions_IP_TOS : + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: { jclass cls; jfieldID fid; @@ -773,7 +708,100 @@ Java_java_net_DualStackPlainSocketImpl_socketNativeGetOption (JNIEnv *env, jobject this, jint opt, jobject iaContainerObj) { - return -1; + /* The fd field */ + jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); + + int fd; + int level = 0, optname = 0, optlen = 0; + union { + int i; + struct linger ling; + } optval; + + /* + * Get SOCKET and check it hasn't been closed + */ + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return -1; + } else { + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + } + if (fd < 0) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed"); + return -1; + } + memset((char *)&optval, 0, sizeof(optval)); + + /* + * SO_BINDADDR isn't a socket option + */ + if (opt == java_net_SocketOptions_SO_BINDADDR) { + SOCKETADDRESS sa; + int len = sizeof(sa); + int port; + jobject iaObj; + jclass iaContainerClass; + jfieldID iaFieldID; + + if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) { + NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name"); + return -1; + } + iaObj = NET_SockaddrToInetAddress(env, &sa, &port); + CHECK_NULL_RETURN(iaObj, -1); + + iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj); + iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;"); + CHECK_NULL_RETURN(iaFieldID, -1); + (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj); + return 0; /* notice change from before */ + } + + /* + * Map the Java level socket option to the platform specific + * level and option name. + */ + if (NET_MapSocketOption(opt, &level, &optname)) { + JNU_ThrowByName(env, "java/net/SocketException", "Invalid option"); + return -1; + } + + /* + * Args are int except for SO_LINGER + */ + if (opt == java_net_SocketOptions_SO_LINGER) { + optlen = sizeof(optval.ling); + } else { + optlen = sizeof(optval.i); + optval.i = 0; + } + + if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) { + NET_ThrowNew(env, WSAGetLastError(), "getsockopt"); + return -1; + } + + switch (opt) { + case java_net_SocketOptions_SO_LINGER: + return (optval.ling.l_onoff ? optval.ling.l_linger: -1); + + case java_net_SocketOptions_SO_SNDBUF: + case java_net_SocketOptions_SO_RCVBUF: + case java_net_SocketOptions_IP_TOS: + return optval.i; + + case java_net_SocketOptions_TCP_NODELAY: + case java_net_SocketOptions_SO_OOBINLINE: + case java_net_SocketOptions_SO_KEEPALIVE: + case java_net_SocketOptions_SO_REUSEADDR: + return (optval.i == 0) ? -1 : 1; + + default: /* shouldn't get here */ + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Option not supported by TwoStacksPlainSocketImpl"); + return -1; + } } /*