提交 3b4107a5 编写于 作者: M michaelm

8039509: Wrap sockets more thoroughly

Reviewed-by: chegar, alanb
上级 af22d925
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
SUNWprivate_1.1 { SUNWprivate_1.1 {
global: global:
JNI_OnLoad; JNI_OnLoad;
Java_java_net_AbstractPlainDatagramSocketImpl_init;
Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable;
Java_java_net_PlainSocketImpl_socketListen; Java_java_net_PlainSocketImpl_socketListen;
Java_java_net_PlainDatagramSocketImpl_getTTL; Java_java_net_PlainDatagramSocketImpl_getTTL;
Java_java_net_PlainDatagramSocketImpl_init; Java_java_net_PlainDatagramSocketImpl_init;
......
...@@ -68,6 +68,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl ...@@ -68,6 +68,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
return null; return null;
} }
}); });
init();
} }
/** /**
...@@ -362,4 +363,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl ...@@ -362,4 +363,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
protected boolean nativeConnectDisabled() { protected boolean nativeConnectDisabled() {
return connectDisabled; return connectDisabled;
} }
native int dataAvailable();
private static native void init();
} }
...@@ -83,6 +83,17 @@ class DatagramSocket implements java.io.Closeable { ...@@ -83,6 +83,17 @@ class DatagramSocket implements java.io.Closeable {
*/ */
boolean oldImpl = false; 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: * Connection state:
* ST_NOT_CONNECTED = socket not connected * ST_NOT_CONNECTED = socket not connected
...@@ -142,6 +153,15 @@ class DatagramSocket implements java.io.Closeable { ...@@ -142,6 +153,15 @@ class DatagramSocket implements java.io.Closeable {
// socket is now connected by the impl // socket is now connected by the impl
connectState = ST_CONNECTED; 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) { } catch (SocketException se) {
// connection will be emulated by DatagramSocket // connection will be emulated by DatagramSocket
...@@ -489,6 +509,7 @@ class DatagramSocket implements java.io.Closeable { ...@@ -489,6 +509,7 @@ class DatagramSocket implements java.io.Closeable {
connectedAddress = null; connectedAddress = null;
connectedPort = -1; connectedPort = -1;
connectState = ST_NOT_CONNECTED; connectState = ST_NOT_CONNECTED;
explicitFilter = false;
} }
} }
...@@ -747,10 +768,12 @@ class DatagramSocket implements java.io.Closeable { ...@@ -747,10 +768,12 @@ class DatagramSocket implements java.io.Closeable {
} // end of while } // 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 // We have to do the filtering the old fashioned way since
// the native impl doesn't support connect or the connect // 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; boolean stop = false;
while (!stop) { while (!stop) {
InetAddress peekAddress = null; InetAddress peekAddress = null;
...@@ -769,8 +792,12 @@ class DatagramSocket implements java.io.Closeable { ...@@ -769,8 +792,12 @@ class DatagramSocket implements java.io.Closeable {
if ((!connectedAddress.equals(peekAddress)) || if ((!connectedAddress.equals(peekAddress)) ||
(connectedPort != peekPort)) { (connectedPort != peekPort)) {
// throw the packet away and silently continue // 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); getImpl().receive(tmp);
if (explicitFilter) {
bytesLeftToFilter -= tmp.getLength();
}
} else { } else {
stop = true; stop = true;
} }
...@@ -779,6 +806,15 @@ class DatagramSocket implements java.io.Closeable { ...@@ -779,6 +806,15 @@ class DatagramSocket implements java.io.Closeable {
// If the security check succeeds, or the datagram is // If the security check succeeds, or the datagram is
// connected then receive the packet // connected then receive the packet
getImpl().receive(p); 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;
}
}
} }
} }
......
...@@ -47,6 +47,12 @@ public abstract class DatagramSocketImpl implements SocketOptions { ...@@ -47,6 +47,12 @@ public abstract class DatagramSocketImpl implements SocketOptions {
*/ */
protected FileDescriptor fd; protected FileDescriptor fd;
int dataAvailable() {
// default impl returns zero, which disables the calling
// functionality
return 0;
}
/** /**
* Creates a datagram socket. * Creates a datagram socket.
* @exception SocketException if there is an error in the * @exception SocketException if there is an error in the
......
...@@ -751,6 +751,26 @@ class DatagramChannelImpl ...@@ -751,6 +751,26 @@ class DatagramChannelImpl
// set or refresh local address // set or refresh local address
localAddress = Net.localAddress(fd); localAddress = Net.localAddress(fd);
// flush any packets already received.
boolean blocking = false;
synchronized (blockingLock()) {
try {
blocking = isBlocking();
// remainder of each packet thrown away
ByteBuffer tmpBuf = ByteBuffer.allocate(1);
if (blocking) {
configureBlocking(false);
}
do {
tmpBuf.clear();
} while (read(tmpBuf) > 0);
} finally {
if (blocking) {
configureBlocking(true);
}
}
}
} }
} }
} }
......
/*
* 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;
}
/*
* 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;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册