8053963: (dc) Use DatagramChannel.receive() instead of read() in connect
authormichaelm
Thu, 21 Aug 2014 17:51:29 +0100
changeset 27724 9a42fe09eb61
parent 27723 157e172623c0
child 27725 433b57a5a5c1
8053963: (dc) Use DatagramChannel.receive() instead of read() in connect Reviewed-by: alanb, chegar
jdk/src/java.base/share/classes/java/net/DatagramSocket.java
jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java	Wed Jul 30 11:08:41 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java	Thu Aug 21 17:51:29 2014 +0100
@@ -771,6 +771,7 @@
                     } // end of while
                 }
             }
+            DatagramPacket tmp = null;
             if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) {
                 // We have to do the filtering the old fashioned way since
                 // the native impl doesn't support connect or the connect
@@ -795,11 +796,13 @@
                     if ((!connectedAddress.equals(peekAddress)) ||
                         (connectedPort != peekPort)) {
                         // throw the packet away and silently continue
-                        DatagramPacket tmp = new DatagramPacket(
+                        tmp = new DatagramPacket(
                                                 new byte[1024], 1024);
                         getImpl().receive(tmp);
                         if (explicitFilter) {
-                            bytesLeftToFilter -= tmp.getLength();
+                            if (checkFiltering(tmp)) {
+                                stop = true;
+                            }
                         }
                     } else {
                         stop = true;
@@ -809,18 +812,22 @@
             // If the security check succeeds, or the datagram is
             // connected then receive the packet
             getImpl().receive(p);
-            if (explicitFilter) {
-                bytesLeftToFilter -= p.getLength();
-                if (bytesLeftToFilter <= 0) {
-                    explicitFilter = false;
-                } else {
-                    // break out of filter, if there is no more data queued
-                    explicitFilter = getImpl().dataAvailable() > 0;
-                }
+            if (explicitFilter && tmp == null) {
+                // packet was not filtered, account for it here
+                checkFiltering(p);
             }
         }
     }
 
+    private boolean checkFiltering(DatagramPacket p) throws SocketException {
+        bytesLeftToFilter -= p.getLength();
+        if (bytesLeftToFilter <= 0 || getImpl().dataAvailable() <= 0) {
+            explicitFilter = false;
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Gets the local address to which the socket is bound.
      *
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 30 11:08:41 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Aug 21 17:51:29 2014 +0100
@@ -752,7 +752,7 @@
                             }
                             do {
                                 tmpBuf.clear();
-                            } while (read(tmpBuf) > 0);
+                            } while (receive(tmpBuf) != null);
                         } finally {
                             if (blocking) {
                                 configureBlocking(true);
--- a/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c	Wed Jul 30 11:08:41 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c	Thu Aug 21 17:51:29 2014 +0100
@@ -32,9 +32,11 @@
 
 #include "java_net_AbstractPlainDatagramSocketImpl.h"
 
-static jfieldID IO_fd_fdID;
+static jfieldID IO_fd_fdID = NULL;
+static jfieldID apdsi_fdID = NULL;
 
-static jfieldID apdsi_fdID;
+static jfieldID apdsi_fd1ID = NULL;
+static jclass two_stacks_clazz = NULL;
 
 
 /*
@@ -48,10 +50,21 @@
     apdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
                                    "Ljava/io/FileDescriptor;");
     CHECK_NULL(apdsi_fdID);
-
     IO_fd_fdID = NET_GetFileDescriptorID(env);
     CHECK_NULL(IO_fd_fdID);
 
+    two_stacks_clazz = (*env)->FindClass(env, "java/net/TwoStacksPlainDatagramSocketImpl");
+    CHECK_NULL(two_stacks_clazz);
+
+    /* Handle both TwoStacks and DualStack here */
+
+    if (JNU_Equals(env, cls, two_stacks_clazz)) {
+        /* fd1 present only in TwoStack.. */
+        apdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1",
+                                   "Ljava/io/FileDescriptor;");
+        CHECK_NULL(apdsi_fd1ID);
+    }
+
     JNU_CHECK_EXCEPTION(env);
 }
 
@@ -63,20 +76,38 @@
 JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
 (JNIEnv *env, jobject this) {
     SOCKET fd;
-    int  retval;
-
+    SOCKET fd1;
+    int  rv = -1, rv1 = -1;
     jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
 
-    if (IS_NULL(fdObj)) {
+    if (!IS_NULL(fdObj)) {
+        int retval = 0;
+        fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
+        rv = ioctlsocket(fd, FIONREAD, &retval);
+        if (retval > 0) {
+            return retval;
+        }
+    }
+
+    if (!IS_NULL(apdsi_fd1ID)) {
+        /* TwoStacks */
+        jobject fd1Obj = (*env)->GetObjectField(env, this, apdsi_fd1ID);
+        if (!IS_NULL(fd1Obj)) {
+            int retval = 0;
+            fd1 = (SOCKET)(*env)->GetIntField(env, fd1Obj, IO_fd_fdID);
+            rv1 = ioctlsocket(fd1, FIONREAD, &retval);
+            if (retval > 0) {
+                return retval;
+            }
+        }
+    }
+
+    if (rv < 0 && rv1 < 0) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Socket closed");
+                            "Socket closed");
         return -1;
     }
-    fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
 
-    if (ioctlsocket(fd, FIONREAD, &retval) < 0) {
-        return -1;
-    }
-    return retval;
+    return 0;
 }