--- a/jdk/make/mapfiles/libnet/mapfile-vers Tue May 27 08:56:59 2014 -0400
+++ b/jdk/make/mapfiles/libnet/mapfile-vers Wed May 28 14:51:24 2014 +0100
@@ -28,6 +28,8 @@
SUNWprivate_1.1 {
global:
JNI_OnLoad;
+ Java_java_net_AbstractPlainDatagramSocketImpl_init;
+ Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable;
Java_java_net_PlainSocketImpl_socketListen;
Java_java_net_PlainDatagramSocketImpl_getTTL;
Java_java_net_PlainDatagramSocketImpl_init;
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Tue May 27 08:56:59 2014 -0400
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed May 28 14:51:24 2014 +0100
@@ -68,6 +68,7 @@
return null;
}
});
+ init();
}
/**
@@ -362,4 +363,7 @@
protected boolean nativeConnectDisabled() {
return connectDisabled;
}
+
+ native int dataAvailable();
+ private static native void init();
}
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Tue May 27 08:56:59 2014 -0400
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java Wed May 28 14:51:24 2014 +0100
@@ -85,6 +85,17 @@
*/
boolean oldImpl = false;
+ /**
+ * Set when a socket is ST_CONNECTED until we are certain
+ * that any packets which might have been received prior
+ * to calling connect() but not read by the application
+ * have been read. During this time we check the source
+ * address of all packets received to be sure they are from
+ * the connected destination. Other packets are read but
+ * silently dropped.
+ */
+ private boolean explicitFilter = false;
+ private int bytesLeftToFilter;
/*
* Connection state:
* ST_NOT_CONNECTED = socket not connected
@@ -144,6 +155,15 @@
// socket is now connected by the impl
connectState = ST_CONNECTED;
+ // Do we need to filter some packets?
+ int avail = getImpl().dataAvailable();
+ if (avail == -1) {
+ throw new SocketException();
+ }
+ explicitFilter = avail > 0;
+ if (explicitFilter) {
+ bytesLeftToFilter = getReceiveBufferSize();
+ }
} catch (SocketException se) {
// connection will be emulated by DatagramSocket
@@ -492,6 +512,7 @@
connectedAddress = null;
connectedPort = -1;
connectState = ST_NOT_CONNECTED;
+ explicitFilter = false;
}
}
@@ -750,10 +771,12 @@
} // end of while
}
}
- if (connectState == ST_CONNECTED_NO_IMPL) {
+ 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
- // via the impl failed.
+ // via the impl failed, or .. "explicitFilter" may be set when
+ // a socket is connected via the impl, for a period of time
+ // when packets from other sources might be queued on socket.
boolean stop = false;
while (!stop) {
InetAddress peekAddress = null;
@@ -772,8 +795,12 @@
if ((!connectedAddress.equals(peekAddress)) ||
(connectedPort != peekPort)) {
// throw the packet away and silently continue
- DatagramPacket tmp = new DatagramPacket(new byte[1], 1);
+ DatagramPacket tmp = new DatagramPacket(
+ new byte[1024], 1024);
getImpl().receive(tmp);
+ if (explicitFilter) {
+ bytesLeftToFilter -= tmp.getLength();
+ }
} else {
stop = true;
}
@@ -782,6 +809,15 @@
// 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;
+ }
+ }
}
}
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Tue May 27 08:56:59 2014 -0400
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Wed May 28 14:51:24 2014 +0100
@@ -63,6 +63,12 @@
return socket;
}
+ int dataAvailable() {
+ // default impl returns zero, which disables the calling
+ // functionality
+ return 0;
+ }
+
/**
* Creates a datagram socket.
* @exception SocketException if there is an error in the
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Tue May 27 08:56:59 2014 -0400
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed May 28 14:51:24 2014 +0100
@@ -740,6 +740,25 @@
// set or refresh local address
localAddress = Net.localAddress(fd);
+
+ // flush any packets already received.
+ boolean blocking = false;
+ synchronized (blockingLock()) {
+ try {
+ blocking = isBlocking();
+ ByteBuffer tmpBuf = ByteBuffer.allocate(100);
+ if (blocking) {
+ configureBlocking(false);
+ }
+ do {
+ tmpBuf.clear();
+ } while (read(tmpBuf) > 0);
+ } finally {
+ if (blocking) {
+ configureBlocking(true);
+ }
+ }
+ }
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libnet/AbstractPlainDatagramSocketImpl.c Wed May 28 14:51:24 2014 +0100
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2014, 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 <sys/types.h>
+#include <sys/socket.h>
+
+#ifdef __solaris__
+#include <unistd.h>
+#include <stropts.h>
+
+#ifndef BSD_COMP
+#define BSD_COMP
+#endif
+
+#endif
+
+#include <sys/ioctl.h>
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_AbstractPlainDatagramSocketImpl.h"
+
+static jfieldID IO_fd_fdID;
+
+static jfieldID apdsi_fdID;
+
+
+/*
+ * Class: java_net_AbstractPlainDatagramSocketImpl
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
+
+ apdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
+ "Ljava/io/FileDescriptor;");
+ CHECK_NULL(apdsi_fdID);
+
+ IO_fd_fdID = NET_GetFileDescriptorID(env);
+}
+
+/*
+ * Class: java_net_AbstractPlainDatagramSocketImpl
+ * Method: dataAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
+(JNIEnv *env, jobject this) {
+ int fd, retval;
+
+ jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ }
+ fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (ioctl(fd, FIONREAD, &retval) < 0) {
+ return -1;
+ }
+ return retval;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c Wed May 28 14:51:24 2014 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014, 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 <windows.h>
+#include <winsock2.h>
+
+#include "jvm.h"
+#include "jni_util.h"
+#include "net_util.h"
+
+#include "java_net_AbstractPlainDatagramSocketImpl.h"
+
+static jfieldID IO_fd_fdID;
+
+static jfieldID apdsi_fdID;
+
+
+/*
+ * Class: java_net_AbstractPlainDatagramSocketImpl
+ * Method: init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
+
+ 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);
+
+ JNU_CHECK_EXCEPTION(env);
+}
+
+/*
+ * Class: java_net_AbstractPlainDatagramSocketImpl
+ * Method: dataAvailable
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable
+(JNIEnv *env, jobject this) {
+ SOCKET fd;
+ int retval;
+
+ jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID);
+
+ if (IS_NULL(fdObj)) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+ "Socket closed");
+ return -1;
+ }
+ fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID);
+
+ if (ioctlsocket(fd, FIONREAD, &retval) < 0) {
+ return -1;
+ }
+ return retval;
+}
+