Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
/*
* Copyright (c) 2007, 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.security.AccessController;
import java.security.PrivilegedAction;
/**
* This class defines a factory for creating DatagramSocketImpls. It defaults
* to creating plain DatagramSocketImpls, but may create other DatagramSocketImpls
* by setting the impl.prefix system property.
*
* For Windows versions lower than Windows Vista a TwoStacksPlainDatagramSocketImpl
* is always created. This impl supports IPv6 on these platform where available.
*
* On Windows platforms greater than Vista that support a dual layer TCP/IP stack
* a DualStackPlainDatagramSocketImpl is created for DatagramSockets. For MulticastSockets
* a TwoStacksPlainDatagramSocketImpl is always created. This is to overcome the lack
* of behavior defined for multicasting over a dual layer socket by the RFC.
*
* @author Chris Hegarty
*/
class DefaultDatagramSocketImplFactory
{
static Class prefixImplClass = null;
/* the windows version. */
private static float version;
/* java.net.preferIPv4Stack */
private static boolean preferIPv4Stack = false;
/* If the version supports a dual stack TCP implementation */
private static boolean useDualStackImpl = false;
/* sun.net.useExclusiveBind */
private static String exclBindProp;
/* True if exclusive binding is on for Windows */
private static boolean exclusiveBind = true;
static {
// Determine Windows Version.
java.security.AccessController.doPrivileged(
new PrivilegedAction<Object>() {
public Object run() {
version = 0;
try {
version = Float.parseFloat(System.getProperties()
.getProperty("os.version"));
preferIPv4Stack = Boolean.parseBoolean(
System.getProperties()
.getProperty(
"java.net.preferIPv4Stack"));
exclBindProp = System.getProperty(
"sun.net.useExclusiveBind");
} catch (NumberFormatException e ) {
assert false : e;
}
return null; // nothing to return
}
});
String ipv6 = ikvm.internal.Util.SafeGetEnvironmentVariable("IKVM_IPV6");
if (ipv6 != null) {
try {
if ((Integer.parseInt(ipv6) & 4) == 0) {
preferIPv4Stack = true;
} else {
useDualStackImpl = true;
}
} catch (NumberFormatException _) {
}
} else if (!InetAddressImplFactory.isIPv6Supported()) {
preferIPv4Stack = true;
}
// (version >= 6.0) implies Vista or greater.
if (version >= 6.0 && !preferIPv4Stack) {
useDualStackImpl = true;
}
if (exclBindProp != null) {
// sun.net.useExclusiveBind is true
exclusiveBind = exclBindProp.length() == 0 ? true
: Boolean.parseBoolean(exclBindProp);
} else if (version < 6.0) {
exclusiveBind = false;
}
// impl.prefix
String prefix = null;
try {
prefix = AccessController.doPrivileged(
new sun.security.action.GetPropertyAction("impl.prefix", null));
if (prefix != null)
prefixImplClass = Class.forName("java.net."+prefix+"DatagramSocketImpl");
} catch (Exception e) {
System.err.println("Can't find class: java.net." +
prefix +
"DatagramSocketImpl: check impl.prefix property");
}
}
/**
* Creates a new <code>DatagramSocketImpl</code> instance.
*
* @param isMulticast true if this impl is to be used for a MutlicastSocket
* @return a new instance of <code>PlainDatagramSocketImpl</code>.
*/
static DatagramSocketImpl createDatagramSocketImpl(boolean isMulticast)
throws SocketException {
if (prefixImplClass != null) {
try {
return (DatagramSocketImpl) prefixImplClass.newInstance();
} catch (Exception e) {
throw new SocketException("can't instantiate DatagramSocketImpl");
}
} else {
if (isMulticast)
exclusiveBind = false;
if (useDualStackImpl && !isMulticast)
return new DualStackPlainDatagramSocketImpl(exclusiveBind);
else
return new TwoStacksPlainDatagramSocketImpl(exclusiveBind);
}
}
}

View File

@@ -0,0 +1,334 @@
/*
* Copyright (c) 2007, 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;
/**
* This class defines the plain DatagramSocketImpl that is used on
* Windows platforms greater than 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.
* <p>
* Note: Multicasting on a dual layer TCP/IP stack is always done with
* TwoStacksPlainDatagramSocketImpl. This is to overcome the lack
* of behavior defined for multicasting over a dual layer socket by the RFC.
*
* @author Chris Hegarty
*/
class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
{
// true if this socket is exclusively bound
private final boolean exclusiveBind;
/*
* Set to true if SO_REUSEADDR is set after the socket is bound to
* indicate SO_REUSEADDR is being emulated
*/
private boolean reuseAddressEmulated;
// emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
private boolean isReuseAddress;
DualStackPlainDatagramSocketImpl(boolean exclBind) {
exclusiveBind = exclBind;
}
protected void datagramSocketCreate() throws SocketException {
if (fd == null)
throw new SocketException("Socket closed");
cli.System.Net.Sockets.Socket newfd = socketCreate(false /* v6Only */);
fd.setSocket(newfd);
}
protected synchronized void bind0(int lport, InetAddress laddr)
throws SocketException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (laddr == null)
throw new NullPointerException("argument address");
socketBind(nativefd, laddr, lport, exclusiveBind);
if (lport == 0) {
localPort = socketLocalPort(nativefd);
} else {
localPort = lport;
}
}
protected synchronized int peek(InetAddress address) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("Null address in peek()");
// Use peekData()
DatagramPacket peekPacket = new DatagramPacket(new byte[1], 1);
int peekPort = peekData(peekPacket);
address = peekPacket.getAddress();
return peekPort;
}
protected synchronized int peekData(DatagramPacket p) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("packet");
if (p.getData() == null)
throw new NullPointerException("packet buffer");
return socketReceiveOrPeekData(nativefd, p, timeout, connected, true /*peek*/);
}
protected synchronized void receive0(DatagramPacket p) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("packet");
if (p.getData() == null)
throw new NullPointerException("packet buffer");
socketReceiveOrPeekData(nativefd, p, timeout, connected, false /*receive*/);
}
protected void send(DatagramPacket p) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (p == null)
throw new NullPointerException("null packet");
if (p.getAddress() == null ||p.getData() ==null)
throw new NullPointerException("null address || null buffer");
socketSend(nativefd, p.getData(), p.getOffset(), p.getLength(),
p.getAddress(), p.getPort(), connected);
}
protected void connect0(InetAddress address, int port) throws SocketException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (address == null)
throw new NullPointerException("address");
socketConnect(nativefd, address, port);
}
protected void disconnect0(int family /*unused*/) {
if (fd == null || !fd.valid())
return; // disconnect doesn't throw any exceptions
socketDisconnect(fd.getSocket());
}
protected void datagramSocketClose() {
if (fd == null || !fd.valid())
return; // close doesn't throw any exceptions
socketClose(fd.getSocket());
fd.setSocket(null);
}
@SuppressWarnings("fallthrough")
protected void socketSetOption(int opt, Object val) throws SocketException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
int optionValue = 0;
switch(opt) {
case IP_TOS :
case SO_RCVBUF :
case SO_SNDBUF :
optionValue = ((Integer)val).intValue();
break;
case SO_REUSEADDR :
if (exclusiveBind && localPort != 0) {
// socket already bound, emulate SO_REUSEADDR
reuseAddressEmulated = true;
isReuseAddress = (Boolean)val;
return;
}
//Intentional fallthrough
case SO_BROADCAST :
optionValue = ((Boolean)val).booleanValue() ? 1 : 0;
break;
default: /* shouldn't get here */
throw new SocketException("Option not supported");
}
socketSetIntOption(nativefd, opt, optionValue);
}
protected Object socketGetOption(int opt) throws SocketException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
// SO_BINDADDR is not a socket option.
if (opt == SO_BINDADDR) {
return socketLocalAddress(nativefd);
}
if (opt == SO_REUSEADDR && reuseAddressEmulated)
return isReuseAddress;
int value = socketGetIntOption(nativefd, opt);
Object returnValue = null;
switch (opt) {
case SO_REUSEADDR :
case SO_BROADCAST :
returnValue = (value == 0) ? Boolean.FALSE : Boolean.TRUE;
break;
case IP_TOS :
case SO_RCVBUF :
case SO_SNDBUF :
returnValue = new Integer(value);
break;
default: /* shouldn't get here */
throw new SocketException("Option not supported");
}
return returnValue;
}
/* Multicast specific methods.
* Multicasting on a dual layer TCP/IP stack is always done with
* TwoStacksPlainDatagramSocketImpl. This is to overcome the lack
* of behavior defined for multicasting over a dual layer socket by the RFC.
*/
protected void join(InetAddress inetaddr, NetworkInterface netIf)
throws IOException {
throw new IOException("Method not implemented!");
}
protected void leave(InetAddress inetaddr, NetworkInterface netIf)
throws IOException {
throw new IOException("Method not implemented!");
}
protected void setTimeToLive(int ttl) throws IOException {
throw new IOException("Method not implemented!");
}
protected int getTimeToLive() throws IOException {
throw new IOException("Method not implemented!");
}
protected void setTTL(byte ttl) throws IOException {
throw new IOException("Method not implemented!");
}
protected byte getTTL() throws IOException {
throw new IOException("Method not implemented!");
}
/* END Multicast specific methods */
private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException {
if (fd == null || !fd.valid())
throw new SocketException("Socket closed");
return fd.getSocket();
}
/* Native methods */
private static cli.System.Net.Sockets.Socket socketCreate(boolean v6Only) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainDatagramSocketImpl_c.socketCreate(env, v6Only);
env.ThrowPendingException();
return ret;
}
private static void socketBind(cli.System.Net.Sockets.Socket fd, InetAddress localAddress,
int localport, boolean exclBind) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketBind(env, fd, localAddress, localport, exclBind);
env.ThrowPendingException();
}
private static void socketConnect(cli.System.Net.Sockets.Socket fd, InetAddress address, int port)
throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketConnect(env, fd, address, port);
env.ThrowPendingException();
}
private static void socketDisconnect(cli.System.Net.Sockets.Socket fd) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketDisconnect(env, fd);
env.ThrowPendingException();
}
private static void socketClose(cli.System.Net.Sockets.Socket fd) {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketClose(env, fd);
env.ThrowPendingException();
}
private static int socketLocalPort(cli.System.Net.Sockets.Socket fd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketLocalPort(env, fd);
env.ThrowPendingException();
return ret;
}
private static Object socketLocalAddress(cli.System.Net.Sockets.Socket fd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
Object ret = DualStackPlainDatagramSocketImpl_c.socketLocalAddress(env, fd);
env.ThrowPendingException();
return ret;
}
private static int socketReceiveOrPeekData(cli.System.Net.Sockets.Socket fd, DatagramPacket packet,
int timeout, boolean connected, boolean peek) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketReceiveOrPeekData(env, fd, packet, timeout, connected, peek);
env.ThrowPendingException();
return ret;
}
private static void socketSend(cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length,
InetAddress address, int port, boolean connected) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketSend(env, fd, data, offset, length, address, port, connected);
env.ThrowPendingException();
}
private static void socketSetIntOption(cli.System.Net.Sockets.Socket fd, int cmd,
int optionValue) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainDatagramSocketImpl_c.socketSetIntOption(env, fd, cmd, optionValue);
env.ThrowPendingException();
}
private static int socketGetIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainDatagramSocketImpl_c.socketGetIntOption(env, fd, cmd);
env.ThrowPendingException();
return ret;
}
}

View File

@@ -0,0 +1,488 @@
/*
* Copyright (c) 2007, 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.FileDescriptor;
import static ikvm.internal.JNI.*;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
final class DualStackPlainDatagramSocketImpl_c
{
static final int TRUE = 1;
static final int FALSE = 0;
static final int JVM_IO_ERR = -1;
static final int JVM_IO_INTR = -2;
/*
#include <windows.h>
#include <winsock2.h>
#include "jni.h"
#include "net_util.h"
#include "java_net_DualStackPlainDatagramSocketImpl.h"
/*
* This function "purges" all outstanding ICMP port unreachable packets
* outstanding on a socket and returns JNI_TRUE if any ICMP messages
* have been purged. The rational for purging is to emulate normal BSD
* behaviour whereby receiving a "connection reset" status resets the
* socket.
*/
static boolean purgeOutstandingICMP(JNIEnv env, cli.System.Net.Sockets.Socket fd)
{
boolean got_icmp = false;
byte[] buf = new byte[1];
fd_set tbl = new fd_set();
timeval t = new timeval();
SOCKETADDRESS rmtaddr = null;
/*
* Peek at the queue to see if there is an ICMP port unreachable. If there
* is then receive it.
*/
FD_ZERO(tbl);
FD_SET(fd, tbl);
while(true) {
if (select(tbl, null, null, t) <= 0) {
break;
}
if (recvfrom(fd, buf, 1, MSG_PEEK,
rmtaddr) != JVM_IO_ERR) {
break;
}
if (WSAGetLastError() != WSAECONNRESET) {
/* some other error - we don't care here */
break;
}
recvfrom(fd, buf, 1, 0, rmtaddr);
got_icmp = JNI_TRUE;
}
return got_icmp;
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketCreate
* Signature: (Z)I
*/
static cli.System.Net.Sockets.Socket socketCreate
(JNIEnv env, boolean v6Only /*unused*/) {
cli.System.Net.Sockets.Socket fd;
int rv, opt=0, t=TRUE;
fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
return null;
}
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Socket creation failed");
return null;
}
//SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, t);
/* SIO_UDP_CONNRESET fixes a "bug" introduced in Windows 2000, which
* returns connection reset errors on unconnected UDP sockets (as well
* as connected sockets). The solution is to only enable this feature
* when the socket is connected.
*/
t = FALSE;
WSAIoctl(fd ,SIO_UDP_CONNRESET ,false);
return fd;
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketBind
* Signature: (ILjava/net/InetAddress;I)V
*/
static void socketBind
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port, boolean exclBind) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = NET_WinBind(fd, sa, exclBind);
if (rv == SOCKET_ERROR) {
if (WSAGetLastError() == WSAEACCES) {
WSASetLastError(WSAEADDRINUSE);
}
NET_ThrowNew(env, WSAGetLastError(), "Cannot bind");
}
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketConnect
* Signature: (ILjava/net/InetAddress;I)V
*/
static void socketConnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
int t = TRUE;
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = connect(fd, sa);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "connect");
return;
}
/* see comment in socketCreate */
WSAIoctl(fd, SIO_UDP_CONNRESET, true);
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketDisconnect
* Signature: (I)V
*/
static void socketDisconnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd ) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
connect(fd, sa);
/* see comment in socketCreate */
WSAIoctl(fd, SIO_UDP_CONNRESET, false);
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketClose
* Signature: (I)V
*/
static void socketClose
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
NET_SocketClose(fd);
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketLocalPort
* Signature: (I)I
*/
static int socketLocalPort
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "JVM_GetSockName");
return -1;
}
return ntohs(GET_PORT(sa));
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketLocalAddress
* Signature: (I)Ljava/lang/Object;
*/
static InetAddress socketLocalAddress
(JNIEnv env , cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
InetAddress iaObj;
int[] port = { 0 };
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return null;
}
iaObj = NET_SockaddrToInetAddress(env, sa, port);
return iaObj;
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketReceiveOrPeekData
* Signature: (ILjava/net/DatagramPacket;IZZ)I
*/
static int socketReceiveOrPeekData
(JNIEnv env, cli.System.Net.Sockets.Socket fd, DatagramPacket dpObj,
int timeout, boolean connected, boolean peek) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int port, rv, flags=0;
boolean retry;
long prevTime = 0;
int packetBufferOffset, packetBufferLen;
byte[] packetBuffer;
/* if we are only peeking. Called from peekData */
if (peek) {
flags = MSG_PEEK;
}
packetBuffer = dpObj.buf;
packetBufferOffset = dpObj.offset;
packetBufferLen = dpObj.bufLength;
/*
if (packetBufferLen > MAX_BUFFER_LEN) {
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
* the max size of an IP packet. Anything bigger is truncated anyway.
*-/
if (packetBufferLen > MAX_PACKET_LEN) {
packetBufferLen = MAX_PACKET_LEN;
}
fullPacket = (char *)malloc(packetBufferLen);
if (!fullPacket) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
return -1;
}
} else {
fullPacket = &(BUF[0]);
}
*/
do {
retry = false;
if (timeout != 0) {
if (prevTime == 0) {
prevTime = JVM_CurrentTimeMillis(env, 0);
}
rv = NET_Timeout(fd, timeout);
if (rv <= 0) {
if (rv == 0) {
JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException",
"Receive timed out");
} else if (rv == JVM_IO_ERR) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Socket closed");
} else if (rv == JVM_IO_INTR) {
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
return -1;
}
}
/* receive the packet */
rv = recvfrom(fd, packetBuffer, packetBufferOffset, packetBufferLen, flags,
sa);
if (rv == SOCKET_ERROR && (WSAGetLastError() == WSAECONNRESET)) {
/* An icmp port unreachable - we must receive this as Windows
* does not reset the state of the socket until this has been
* received.
*/
purgeOutstandingICMP(env, fd);
if (connected) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException",
"ICMP Port Unreachable");
return -1;
} else if (timeout != 0) {
/* Adjust timeout */
long newTime = JVM_CurrentTimeMillis(env, 0);
timeout -= (int)(newTime - prevTime);
if (timeout <= 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"Receive timed out");
return -1;
}
prevTime = newTime;
}
retry = true;
}
} while (retry);
port = ntohs (GET_PORT(sa));
/* truncate the data if the packet's length is too small */
if (rv > packetBufferLen) {
rv = packetBufferLen;
}
if (rv < 0) {
if (WSAGetLastError() == WSAEMSGSIZE) {
/* it is because the buffer is too small. It's UDP, it's
* unreliable, it's all good. discard the rest of the
* data..
*/
rv = packetBufferLen;
} else {
/* failure */
dpObj.length = 0;
}
}
if (rv == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed");
} else if (rv == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
} else if (rv < 0) {
NET_ThrowCurrent(env, "Datagram receive failed");
} else {
InetAddress packetAddress;
/*
* Check if there is an InetAddress already associated with this
* packet. If so, we check if it is the same source address. We
* can't update any existing InetAddress because it is immutable
*/
packetAddress = dpObj.address;
if (packetAddress != NULL) {
if (!NET_SockaddrEqualsInetAddress(sa,
packetAddress)) {
/* force a new InetAddress to be created */
packetAddress = null;
}
}
if (packetAddress == NULL) {
int[] tmp = { port };
packetAddress = NET_SockaddrToInetAddress(sa, tmp);
port = tmp[0];
/* stuff the new Inetaddress into the packet */
dpObj.address = packetAddress;
}
/* populate the packet */
dpObj.port = port;
dpObj.length = rv;
}
return port;
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketSend
* Signature: (I[BIILjava/net/InetAddress;IZ)V
*/
static void socketSend
(JNIEnv env, cli.System.Net.Sockets.Socket fd, byte[] data, int offset, int length,
InetAddress iaObj, int port, boolean connected) {
SOCKETADDRESS sa;
int rv;
if (connected) {
sa = null; /* arg to JVM_Sendto () null in this case */
} else {
sa = new SOCKETADDRESS();
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
}
/*
if (length > MAX_BUFFER_LEN) {
/* Note: the buffer needn't be greater than 65,536 (0xFFFF)
* the max size of an IP packet. Anything bigger is truncated anyway.
*-/
if (length > MAX_PACKET_LEN) {
length = MAX_PACKET_LEN;
}
fullPacket = (char *)malloc(length);
if (!fullPacket) {
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
return;
}
} else {
fullPacket = &(BUF[0]);
}
*/
rv = sendto(fd, data, offset, length, 0, sa);
if (rv == SOCKET_ERROR) {
if (rv == JVM_IO_ERR) {
NET_ThrowNew(env, WSAGetLastError(), "Datagram send failed");
} else if (rv == JVM_IO_INTR) {
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
}
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketSetIntOption
* Signature: (III)V
*/
static void socketSetIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd , int cmd, int value) {
int[] level = { 0 }, opt = { 0 };
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Invalid option");
return;
}
if (NET_SetSockOpt(fd, level[0], opt[0], value) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
}
}
/*
* Class: java_net_DualStackPlainDatagramSocketImpl
* Method: socketGetIntOption
* Signature: (II)I
*/
static int socketGetIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) {
int[] level = { 0 }, opt = { 0 }, result = { 0 };
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Invalid option");
return -1;
}
if (NET_GetSockOpt(fd, level[0], opt[0], result) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
return -1;
}
return result[0];
}
}

View File

@@ -0,0 +1,360 @@
/*
* Copyright (c) 2007, 2008, 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;
/**
* 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.
*
* @author Chris Hegarty
*/
class DualStackPlainSocketImpl extends AbstractPlainSocketImpl
{
// true if this socket is exclusively bound
private final boolean exclusiveBind;
// emulates SO_REUSEADDR when exclusiveBind is true
private boolean isReuseAddress;
public DualStackPlainSocketImpl(boolean exclBind) {
exclusiveBind = exclBind;
}
public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
this.fd = fd;
exclusiveBind = exclBind;
}
void socketCreate(boolean stream) throws IOException {
if (fd == null)
throw new SocketException("Socket closed");
cli.System.Net.Sockets.Socket newfd = socket0(stream, false /*v6 Only*/);
fd.setSocket(newfd);
}
void socketConnect(InetAddress address, int port, int timeout)
throws IOException {
cli.System.Net.Sockets.Socket 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);
}
void socketBind(InetAddress address, int port) throws IOException {
cli.System.Net.Sockets.Socket 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;
}
void socketListen(int backlog) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
listen0(nativefd, backlog);
}
void socketAccept(SocketImpl s) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (s == null)
throw new NullPointerException("socket is null");
cli.System.Net.Sockets.Socket newfd = null;
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 != null) {
configureBlocking(newfd, true);
}
} finally {
configureBlocking(nativefd, true);
}
}
/* Update (SocketImpl)s' fd */
s.fd.setSocket(newfd);
/* Update socketImpls remote port, address and localport */
InetSocketAddress isa = isaa[0];
s.port = isa.getPort();
s.address = isa.getAddress();
s.localport = localport;
}
int socketAvailable() throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
return available0(nativefd);
}
void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
if (fd == null)
throw new SocketException("Socket closed");
if (!fd.valid())
return;
close0(fd.getSocket());
fd.setSocket(null);
}
void socketShutdown(int howto) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
shutdown0(nativefd, howto);
}
// Intentional fallthrough after SO_REUSEADDR
@SuppressWarnings("fallthrough")
void socketSetOption(int opt, boolean on, Object value)
throws SocketException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
if (opt == SO_TIMEOUT) { // timeout implemented through select.
return;
}
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);
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
cli.System.Net.Sockets.Socket 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_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;
}
void socketSendUrgentData(int data) throws IOException {
cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD();
sendOOB(nativefd, data);
}
private cli.System.Net.Sockets.Socket checkAndReturnNativeFD() throws SocketException {
if (fd == null || !fd.valid())
throw new SocketException("Socket closed");
return fd.getSocket();
}
static final int WOULDBLOCK = -2; // Nothing available (non-blocking)
/* Native methods */
static cli.System.Net.Sockets.Socket socket0(boolean stream, boolean v6Only) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.socket0(env, stream, v6Only);
env.ThrowPendingException();
return ret;
}
static void bind0(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport,
boolean exclBind)
throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.bind0(env, fd, localAddress, localport, exclBind);
env.ThrowPendingException();
}
static int connect0(cli.System.Net.Sockets.Socket fd, InetAddress remote, int remotePort)
throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.connect0(env, fd, remote, remotePort);
env.ThrowPendingException();
return ret;
}
static void waitForConnect(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.waitForConnect(env, fd, timeout);
env.ThrowPendingException();
}
static int localPort0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.localPort0(env, fd);
env.ThrowPendingException();
return ret;
}
static void localAddress(cli.System.Net.Sockets.Socket fd, InetAddressContainer in) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.localAddress(env, fd, in);
env.ThrowPendingException();
}
static void listen0(cli.System.Net.Sockets.Socket fd, int backlog) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.listen0(env, fd, backlog);
env.ThrowPendingException();
}
static cli.System.Net.Sockets.Socket accept0(cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
cli.System.Net.Sockets.Socket ret = DualStackPlainSocketImpl_c.accept0(env, fd, isaa);
env.ThrowPendingException();
return ret;
}
static void waitForNewConnection(cli.System.Net.Sockets.Socket fd, int timeout) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.waitForNewConnection(env, fd, timeout);
env.ThrowPendingException();
}
static int available0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.available0(env, fd);
env.ThrowPendingException();
return ret;
}
static void close0(cli.System.Net.Sockets.Socket fd) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.close0(env, fd);
env.ThrowPendingException();
}
static void shutdown0(cli.System.Net.Sockets.Socket fd, int howto) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.shutdown0(env, fd, howto);
env.ThrowPendingException();
}
static void setIntOption(cli.System.Net.Sockets.Socket fd, int cmd, int optionValue) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.setIntOption(env, fd, cmd, optionValue);
env.ThrowPendingException();
}
static int getIntOption(cli.System.Net.Sockets.Socket fd, int cmd) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = DualStackPlainSocketImpl_c.getIntOption(env, fd, cmd);
env.ThrowPendingException();
return ret;
}
static void sendOOB(cli.System.Net.Sockets.Socket fd, int data) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.sendOOB(env, fd, data);
env.ThrowPendingException();
}
static void configureBlocking(cli.System.Net.Sockets.Socket fd, boolean blocking) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
DualStackPlainSocketImpl_c.configureBlocking(env, fd, blocking);
env.ThrowPendingException();
}
}

View File

@@ -0,0 +1,490 @@
/*
* Copyright (c) 2007, 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.FileDescriptor;
import static ikvm.internal.JNI.*;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
final class DualStackPlainSocketImpl_c
{
private static final int JVM_IO_ERR = -1;
private static final int JVM_IO_INTR = -2;
private static final int SET_BLOCKING = 0;
private static final int SET_NONBLOCKING = 1;
/*
#include <windows.h>
#include <winsock2.h>
#include "jni.h"
#include "net_util.h"
#include "java_net_DualStackPlainSocketImpl.h"
#define SET_BLOCKING 0
#define SET_NONBLOCKING 1
static jclass isa_class; /* java.net.InetSocketAddress *-/
static jmethodID isa_ctorID; /* InetSocketAddress(InetAddress, int) *-/
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: initIDs
* Signature: ()V
*-/
JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
(JNIEnv *env, jclass clazz) {
jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
isa_class = (*env)->NewGlobalRef(env, cls);
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
"(Ljava/net/InetAddress;I)V");
// implement read timeout with select.
isRcvTimeoutSupported = 0;
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: socket0
* Signature: (ZZ)I
*/
static cli.System.Net.Sockets.Socket socket0
(JNIEnv env, boolean stream, boolean v6Only /*unused*/) {
cli.System.Net.Sockets.Socket fd;
int rv, opt=0;
fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
if (fd == INVALID_SOCKET) {
NET_ThrowNew(env, WSAGetLastError(), "create");
return null;
}
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, opt);
if (rv == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "create");
}
return fd;
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: bind0
* Signature: (ILjava/net/InetAddress;I)V
*/
static void bind0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port,
boolean exclBind)
{
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return;
}
rv = NET_WinBind(fd, sa, exclBind);
if (rv == SOCKET_ERROR)
NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind");
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: connect0
* Signature: (ILjava/net/InetAddress;I)I
*/
static int connect0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
int rv;
if (NET_InetAddressToSockaddr(env, iaObj, port, sa,
JNI_TRUE) != 0) {
return -1;
}
rv = connect(fd, sa);
if (rv == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
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");
} else {
NET_ThrowNew(env, err, "connect");
}
return -1; // return value not important.
}
return rv;
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: waitForConnect
* Signature: (II)V
*/
static void waitForConnect
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
int rv, retry;
fd_set wr, ex;
wr = new fd_set(); ex = new fd_set();
timeval t = new timeval();
FD_ZERO(wr);
FD_ZERO(ex);
FD_SET(fd, wr);
FD_SET(fd, ex);
t.tv_sec = timeout / 1000;
t.tv_usec = (timeout % 1000) * 1000;
/*
* Wait for timeout, connection established or
* connection failed.
*/
rv = select(null, wr, ex, t);
/*
* Timeout before connection is established/failed so
* we throw exception and shutdown input/output to prevent
* socket from being used.
* The socket should be closed immediately by the caller.
*/
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"connect timed out");
shutdown( fd, SD_BOTH );
return;
}
/*
* Socket is writable or error occured. On some Windows editions
* the socket will appear writable when the connect fails so we
* check for error rather than writable.
*/
if (!FD_ISSET(fd, ex)) {
return; /* connection established */
}
/*
* Connection failed. The logic here is designed to work around
* bug on Windows NT whereby using getsockopt to obtain the
* last error (SO_ERROR) indicates there is no error. The workaround
* on NT is to allow winsock to be scheduled and this is done by
* yielding and retrying. As yielding is problematic in heavy
* load conditions we attempt up to 3 times to get the error reason.
*/
for (retry=0; retry<3; retry++) {
int[] tmp = { 0 };
NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
tmp);
rv = tmp[0];
if (rv != 0) {
break;
}
Sleep(0);
}
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Unable to establish connection");
} else {
NET_ThrowNew(env, rv, "connect");
}
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: localPort0
* Signature: (I)I
*/
static int localPort0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
if (getsockname(fd, sa) == SOCKET_ERROR) {
if (WSAGetLastError() == WSAENOTSOCK) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"Socket closed");
} else {
NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
}
return -1;
}
return ntohs(GET_PORT(sa));
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: localAddress
* Signature: (ILjava/net/InetAddressContainer;)V
*/
static void localAddress
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddressContainer iaContainerObj) {
int[] port = { 0 };
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
InetAddress iaObj;
if (getsockname(fd, sa) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
return;
}
iaObj = NET_SockaddrToInetAddress(env, sa, port);
iaContainerObj.addr = iaObj;
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: listen0
* Signature: (II)V
*/
static void listen0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int backlog) {
if (listen(fd, backlog) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "listen failed");
}
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: accept0
* Signature: (I[Ljava/net/InetSocketAddress;)I
*/
static cli.System.Net.Sockets.Socket accept0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, InetSocketAddress[] isaa) {
cli.System.Net.Sockets.Socket newfd;
int[] port = { 0 };
InetSocketAddress isa;
InetAddress ia;
SOCKETADDRESS sa;
sa = new SOCKETADDRESS();
newfd = accept(fd, sa);
if (newfd == INVALID_SOCKET) {
if (WSAGetLastError() == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
} else {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException",
"socket closed");
}
return null;
}
ia = NET_SockaddrToInetAddress(env, sa, port);
isa = new InetSocketAddress(ia, port[0]);
isaa[0] = isa;
return newfd;
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: waitForNewConnection
* Signature: (II)V
*/
static void waitForNewConnection
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int timeout) {
int rv;
rv = NET_Timeout(fd, timeout);
if (rv == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException",
"Accept timed out");
} else if (rv == -1) {
JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed");
} else if (rv == -2) {
JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException",
"operation interrupted");
}
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: available0
* Signature: (I)I
*/
static int available0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
int[] available = { -1 };
if ((ioctlsocket(fd, FIONREAD, available)) == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "socket available");
}
return available[0];
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: close0
* Signature: (I)V
*/
static void close0
(JNIEnv env, cli.System.Net.Sockets.Socket fd) {
NET_SocketClose(fd);
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: shutdown0
* Signature: (II)V
*/
static void shutdown0
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int howto) {
shutdown(fd, howto);
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: setIntOption
* Signature: (III)V
*/
static void setIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd, int value) {
int[] level = { 0 };
int[] opt = { 0 };
linger linger;
Object optval;
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env,
JNU_JAVANETPKG+"SocketException",
"Invalid option");
return;
}
if (opt[0] == java.net.SocketOptions.SO_LINGER) {
linger = new linger();
if (value >= 0) {
linger.l_onoff = 1;
linger.l_linger = value & 0xFFFF;
} else {
linger.l_onoff = 0;
linger.l_linger = 0;
}
optval = linger;
} else {
optval = value;
}
if (NET_SetSockOpt(fd, level[0], opt[0], optval) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
}
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: getIntOption
* Signature: (II)I
*/
static int getIntOption
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int cmd) {
int[] level = { 0 };
int[] opt = { 0 };
int[] result = { 0 };
linger linger;
Object optval;
if (NET_MapSocketOption(cmd, level, opt) < 0) {
JNU_ThrowByName(env,
JNU_JAVANETPKG+"SocketException",
"Unsupported socket option");
return -1;
}
if (opt[0] == java.net.SocketOptions.SO_LINGER) {
linger = new linger();
optval = linger;
} else {
linger = null;
optval = result;
}
if (NET_GetSockOpt(fd, level[0], opt[0], optval) < 0) {
NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
return -1;
}
if (opt[0] == java.net.SocketOptions.SO_LINGER)
return linger.l_onoff != 0 ? linger.l_linger : -1;
else
return result[0];
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: sendOOB
* Signature: (II)V
*/
static void sendOOB
(JNIEnv env, cli.System.Net.Sockets.Socket fd, int data) {
int n;
n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB);
if (n == JVM_IO_ERR) {
NET_ThrowNew(env, WSAGetLastError(), "send");
} else if (n == JVM_IO_INTR) {
JNU_ThrowByName(env, "java.io.InterruptedIOException", null);
}
}
/*
* Class: java_net_DualStackPlainSocketImpl
* Method: configureBlocking
* Signature: (IZ)V
*/
static void configureBlocking
(JNIEnv env, cli.System.Net.Sockets.Socket fd, boolean blocking) {
int arg;
int result;
if (blocking == JNI_TRUE) {
arg = SET_BLOCKING; // 0
} else {
arg = SET_NONBLOCKING; // 1
}
result = ioctlsocket(fd, FIONBIO, arg);
if (result == SOCKET_ERROR) {
NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
}
}
}

View File

@@ -0,0 +1,356 @@
/*
* Copyright (c) 2007, 2011, 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.*;
import java.security.PrivilegedAction;
/*
* This class PlainSocketImpl simply delegates to the appropriate real
* SocketImpl. We do this because PlainSocketImpl is already extended
* by SocksSocketImpl.
* <p>
* 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.
*
* @author Chris Hegarty
*/
class PlainSocketImpl extends AbstractPlainSocketImpl
{
private AbstractPlainSocketImpl impl;
/* the windows version. */
private static float version;
/* java.net.preferIPv4Stack */
private static boolean preferIPv4Stack = false;
/* If the version supports a dual stack TCP implementation */
private static boolean useDualStackImpl = false;
/* sun.net.useExclusiveBind */
private static String exclBindProp;
/* True if exclusive binding is on for Windows */
private static boolean exclusiveBind = true;
static {
java.security.AccessController.doPrivileged( new PrivilegedAction<Object>() {
public Object run() {
version = 0;
try {
version = Float.parseFloat(System.getProperties().getProperty("os.version"));
preferIPv4Stack = Boolean.parseBoolean(
System.getProperties().getProperty("java.net.preferIPv4Stack"));
exclBindProp = System.getProperty("sun.net.useExclusiveBind");
} catch (NumberFormatException e ) {
assert false : e;
}
return null; // nothing to return
} });
String ipv6 = ikvm.internal.Util.SafeGetEnvironmentVariable("IKVM_IPV6");
if (ipv6 != null) {
try {
if ((Integer.parseInt(ipv6) & 4) == 0) {
preferIPv4Stack = true;
} else {
useDualStackImpl = true;
}
} catch (NumberFormatException _) {
}
} else if (!InetAddressImplFactory.isIPv6Supported()) {
preferIPv4Stack = true;
}
// (version >= 6.0) implies Vista or greater.
if (version >= 6.0 && !preferIPv4Stack) {
useDualStackImpl = true;
}
if (exclBindProp != null) {
// sun.net.useExclusiveBind is true
exclusiveBind = exclBindProp.length() == 0 ? true
: Boolean.parseBoolean(exclBindProp);
} else if (version < 6.0) {
exclusiveBind = false;
}
}
/**
* Constructs an empty instance.
*/
PlainSocketImpl() {
if (useDualStackImpl) {
impl = new DualStackPlainSocketImpl(exclusiveBind);
} else {
impl = new TwoStacksPlainSocketImpl(exclusiveBind);
}
}
/**
* Constructs an instance with the given file descriptor.
*/
PlainSocketImpl(FileDescriptor fd) {
if (useDualStackImpl) {
impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
} else {
impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
}
}
// Override methods in SocketImpl that access impl's fields.
protected FileDescriptor getFileDescriptor() {
return impl.getFileDescriptor();
}
protected InetAddress getInetAddress() {
return impl.getInetAddress();
}
protected int getPort() {
return impl.getPort();
}
protected int getLocalPort() {
return impl.getLocalPort();
}
void setSocket(Socket soc) {
impl.setSocket(soc);
}
Socket getSocket() {
return impl.getSocket();
}
void setServerSocket(ServerSocket soc) {
impl.setServerSocket(soc);
}
ServerSocket getServerSocket() {
return impl.getServerSocket();
}
public String toString() {
return impl.toString();
}
// Override methods in AbstractPlainSocketImpl that access impl's fields.
protected synchronized void create(boolean stream) throws IOException {
impl.create(stream);
// set fd to delegate's fd to be compatible with older releases
this.fd = impl.fd;
}
protected void connect(String host, int port)
throws UnknownHostException, IOException
{
impl.connect(host, port);
}
protected void connect(InetAddress address, int port) throws IOException {
impl.connect(address, port);
}
protected void connect(SocketAddress address, int timeout) throws IOException {
impl.connect(address, timeout);
}
public void setOption(int opt, Object val) throws SocketException {
impl.setOption(opt, val);
}
public Object getOption(int opt) throws SocketException {
return impl.getOption(opt);
}
synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
impl.doConnect(address, port, timeout);
}
protected synchronized void bind(InetAddress address, int lport)
throws IOException
{
impl.bind(address, lport);
}
protected synchronized void accept(SocketImpl s) throws IOException {
// pass in the real impl not the wrapper.
SocketImpl delegate = ((PlainSocketImpl)s).impl;
delegate.address = new InetAddress();
delegate.fd = new FileDescriptor();
impl.accept(delegate);
// set fd to delegate's fd to be compatible with older releases
s.fd = delegate.fd;
}
void setFileDescriptor(FileDescriptor fd) {
impl.setFileDescriptor(fd);
}
void setAddress(InetAddress address) {
impl.setAddress(address);
}
void setPort(int port) {
impl.setPort(port);
}
void setLocalPort(int localPort) {
impl.setLocalPort(localPort);
}
protected synchronized InputStream getInputStream() throws IOException {
return impl.getInputStream();
}
void setInputStream(SocketInputStream in) {
impl.setInputStream(in);
}
protected synchronized OutputStream getOutputStream() throws IOException {
return impl.getOutputStream();
}
protected void close() throws IOException {
try {
impl.close();
} finally {
// set fd to delegate's fd to be compatible with older releases
this.fd = null;
}
}
void reset() throws IOException {
try {
impl.reset();
} finally {
// set fd to delegate's fd to be compatible with older releases
this.fd = null;
}
}
protected void shutdownInput() throws IOException {
impl.shutdownInput();
}
protected void shutdownOutput() throws IOException {
impl.shutdownOutput();
}
protected void sendUrgentData(int data) throws IOException {
impl.sendUrgentData(data);
}
FileDescriptor acquireFD() {
return impl.acquireFD();
}
void releaseFD() {
impl.releaseFD();
}
public boolean isConnectionReset() {
return impl.isConnectionReset();
}
public boolean isConnectionResetPending() {
return impl.isConnectionResetPending();
}
public void setConnectionReset() {
impl.setConnectionReset();
}
public void setConnectionResetPending() {
impl.setConnectionResetPending();
}
public boolean isClosedOrPending() {
return impl.isClosedOrPending();
}
public int getTimeout() {
return impl.getTimeout();
}
// Override methods in AbstractPlainSocketImpl that need to be implemented.
void socketCreate(boolean isServer) throws IOException {
impl.socketCreate(isServer);
}
void socketConnect(InetAddress address, int port, int timeout)
throws IOException {
impl.socketConnect(address, port, timeout);
}
void socketBind(InetAddress address, int port)
throws IOException {
impl.socketBind(address, port);
}
void socketListen(int count) throws IOException {
impl.socketListen(count);
}
void socketAccept(SocketImpl s) throws IOException {
impl.socketAccept(s);
}
int socketAvailable() throws IOException {
return impl.socketAvailable();
}
void socketClose0(boolean useDeferredClose) throws IOException {
impl.socketClose0(useDeferredClose);
}
void socketShutdown(int howto) throws IOException {
impl.socketShutdown(howto);
}
void socketSetOption(int cmd, boolean on, Object value)
throws SocketException {
socketSetOption(cmd, on, value);
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
return impl.socketGetOption(opt, iaContainerObj);
}
void socketSendUrgentData(int data) throws IOException {
impl.socketSendUrgentData(data);
}
}

View File

@@ -0,0 +1,332 @@
/*
* Copyright (c) 1995, 2010, 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.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
import sun.misc.IoTrace;
import sun.net.ConnectionResetException;
/**
* This stream extends FileInputStream to implement a
* SocketInputStream. Note that this class should <b>NOT</b> be
* public.
*
* @author Jonathan Payne
* @author Arthur van Hoff
*/
class SocketInputStream extends FileInputStream
{
private boolean eof;
private AbstractPlainSocketImpl impl = null;
private byte temp[];
private Socket socket = null;
/**
* Creates a new SocketInputStream. Can only be called
* by a Socket. This method needs to hang on to the owner Socket so
* that the fd will not be closed.
* @param impl the implemented socket input stream
*/
SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
super(impl.getFileDescriptor());
this.impl = impl;
socket = impl.getSocket();
}
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file input stream.</p>
*
* The <code>getChannel</code> method of <code>SocketInputStream</code>
* returns <code>null</code> since it is a socket based stream.</p>
*
* @return the file channel associated with this file input stream
*
* @since 1.4
* @spec JSR-51
*/
public final FileChannel getChannel() {
return null;
}
/**
* Reads into an array of bytes at the specified offset using
* the received socket primitive.
* @param fd the FileDescriptor
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes read
* @param timeout the read timeout in ms
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
private int socketRead0(FileDescriptor fdObj, byte bufP[], int off, int len, int timeout) throws IOException
{
// [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketInputStream.c
cli.System.Net.Sockets.Socket fd = null;
int nread;
if (IS_NULL(fdObj)) {
throw new SocketException("socket closed");
}
fd = fdObj.getSocket();
if (fd == null) {
throw new SocketException("Socket closed");
}
if (timeout != 0) {
if (timeout <= 5000 || !isRcvTimeoutSupported) {
int ret = NET_Timeout (fd, timeout);
if (ret <= 0) {
if (ret == 0) {
throw new SocketTimeoutException("Read timed out");
} else {
// [IKVM] the OpenJDK native code is broken and always throws this exception on any failure of NET_Timeout
throw new SocketException("socket closed");
}
}
/*check if the socket has been closed while we were in timeout*/
if (fdObj.getSocket() == null) {
throw new SocketException("Socket Closed");
}
}
}
nread = recv(fd, bufP, off, len, 0);
if (nread > 0) {
// ok
} else {
if (nread < 0) {
/*
* Recv failed.
*/
switch (WSAGetLastError()) {
case WSAEINTR:
throw new SocketException("socket closed");
case WSAECONNRESET:
case WSAESHUTDOWN:
/*
* Connection has been reset - Windows sometimes reports
* the reset as a shutdown error.
*/
throw new ConnectionResetException();
case WSAETIMEDOUT :
throw new SocketTimeoutException("Read timed out");
default:
throw NET_ThrowCurrent("recv failed");
}
}
}
return nread;
}
/**
* Reads into a byte array data from the socket.
* @param b the buffer into which the data is read
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* Reads into a byte array <i>b</i> at offset <i>off</i>,
* <i>length</i> bytes of data.
* @param b the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes read
* @return the actual number of bytes read, -1 is
* returned when the end of the stream is reached.
* @exception IOException If an I/O error has occurred.
*/
public int read(byte b[], int off, int length) throws IOException {
return read(b, off, length, impl.getTimeout());
}
int read(byte b[], int off, int length, int timeout) throws IOException {
int n = 0;
// EOF already encountered
if (eof) {
return -1;
}
// connection reset
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
// bounds check
if (length <= 0 || off < 0 || off + length > b.length) {
if (length == 0) {
return 0;
}
throw new ArrayIndexOutOfBoundsException();
}
boolean gotReset = false;
Object traceContext = IoTrace.socketReadBegin();
// acquire file descriptor and do the read
FileDescriptor fd = impl.acquireFD();
try {
n = socketRead0(fd, b, off, length, timeout);
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
gotReset = true;
} finally {
impl.releaseFD();
IoTrace.socketReadEnd(traceContext, impl.address, impl.port,
timeout, n > 0 ? n : 0);
}
/*
* We receive a "connection reset" but there may be bytes still
* buffered on the socket
*/
if (gotReset) {
traceContext = IoTrace.socketReadBegin();
impl.setConnectionResetPending();
impl.acquireFD();
try {
n = socketRead0(fd, b, off, length, timeout);
if (n > 0) {
return n;
}
} catch (ConnectionResetException rstExc) {
} finally {
impl.releaseFD();
IoTrace.socketReadEnd(traceContext, impl.address, impl.port,
timeout, n > 0 ? n : 0);
}
}
/*
* If we get here we are at EOF, the socket has been closed,
* or the connection has been reset.
*/
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
}
if (impl.isConnectionResetPending()) {
impl.setConnectionReset();
}
if (impl.isConnectionReset()) {
throw new SocketException("Connection reset");
}
eof = true;
return -1;
}
/**
* Reads a single byte from the socket.
*/
public int read() throws IOException {
if (eof) {
return -1;
}
temp = new byte[1];
int n = read(temp, 0, 1);
if (n <= 0) {
return -1;
}
return temp[0] & 0xff;
}
/**
* Skips n bytes of input.
* @param n the number of bytes to skip
* @return the actual number of bytes skipped.
* @exception IOException If an I/O error has occurred.
*/
public long skip(long numbytes) throws IOException {
if (numbytes <= 0) {
return 0;
}
long n = numbytes;
int buflen = (int) Math.min(1024, n);
byte data[] = new byte[buflen];
while (n > 0) {
int r = read(data, 0, (int) Math.min((long) buflen, n));
if (r < 0) {
break;
}
n -= r;
}
return numbytes - n;
}
/**
* Returns the number of bytes that can be read without blocking.
* @return the number of immediately available bytes
*/
public int available() throws IOException {
return impl.available();
}
/**
* Closes the stream.
*/
private boolean closing = false;
public void close() throws IOException {
// Prevent recursion. See BugId 4484411
if (closing)
return;
closing = true;
if (socket != null) {
if (!socket.isClosed())
socket.close();
} else
impl.close();
closing = false;
}
void setEOF(boolean eof) {
this.eof = eof;
}
/**
* Overrides finalize, the fd is closed by the Socket.
*/
protected void finalize() {}
}

View File

@@ -0,0 +1,254 @@
/*
* Copyright (c) 1995, 2007, 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.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import static ikvm.internal.Winsock.*;
import static java.net.net_util_md.*;
import sun.misc.IoTrace;
/**
* This stream extends FileOutputStream to implement a
* SocketOutputStream. Note that this class should <b>NOT</b> be
* public.
*
* @author Jonathan Payne
* @author Arthur van Hoff
*/
class SocketOutputStream extends FileOutputStream
{
private AbstractPlainSocketImpl impl = null;
private byte temp[] = new byte[1];
private Socket socket = null;
/**
* Creates a new SocketOutputStream. Can only be called
* by a Socket. This method needs to hang on to the owner Socket so
* that the fd will not be closed.
* @param impl the socket output stream inplemented
*/
SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
super(impl.getFileDescriptor());
this.impl = impl;
socket = impl.getSocket();
}
/**
* Returns the unique {@link java.nio.channels.FileChannel FileChannel}
* object associated with this file output stream. </p>
*
* The <code>getChannel</code> method of <code>SocketOutputStream</code>
* returns <code>null</code> since it is a socket based stream.</p>
*
* @return the file channel associated with this file output stream
*
* @since 1.4
* @spec JSR-51
*/
public final FileChannel getChannel() {
return null;
}
/**
* Writes to the socket.
* @param fd the FileDescriptor
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private void socketWrite0(FileDescriptor fdObj, byte[] data, int off, int len) throws IOException
{
// [IKVM] this method is a direct port of the native code in openjdk6-b18\jdk\src\windows\native\java\net\SocketOutputStream.c
final int MAX_BUFFER_LEN = 2048;
cli.System.Net.Sockets.Socket fd;
int buflen = 65536; // MAX_HEAP_BUFFER_LEN
int n;
if (IS_NULL(fdObj)) {
throw new SocketException("socket closed");
} else {
fd = fdObj.getSocket();
}
if (IS_NULL(data)) {
throw new NullPointerException("data argument");
}
while(len > 0) {
int loff = 0;
int chunkLen = Math.min(buflen, len);
int llen = chunkLen;
int retry = 0;
while(llen > 0) {
n = send(fd, data, off + loff, llen, 0);
if (n > 0) {
llen -= n;
loff += n;
continue;
}
/*
* Due to a bug in Windows Sockets (observed on NT and Windows
* 2000) it may be necessary to retry the send. The issue is that
* on blocking sockets send/WSASend is supposed to block if there
* is insufficient buffer space available. If there are a large
* number of threads blocked on write due to congestion then it's
* possile to hit the NT/2000 bug whereby send returns WSAENOBUFS.
* The workaround we use is to retry the send. If we have a
* large buffer to send (>2k) then we retry with a maximum of
* 2k buffer. If we hit the issue with <=2k buffer then we backoff
* for 1 second and retry again. We repeat this up to a reasonable
* limit before bailing out and throwing an exception. In load
* conditions we've observed that the send will succeed after 2-3
* attempts but this depends on network buffers associated with
* other sockets draining.
*/
if (WSAGetLastError() == WSAENOBUFS) {
if (llen > MAX_BUFFER_LEN) {
buflen = MAX_BUFFER_LEN;
chunkLen = MAX_BUFFER_LEN;
llen = MAX_BUFFER_LEN;
continue;
}
if (retry >= 30) {
throw new SocketException("No buffer space available - exhausted attempts to queue buffer");
}
cli.System.Threading.Thread.Sleep(1000);
retry++;
continue;
}
/*
* Send failed - can be caused by close or write error.
*/
if (WSAGetLastError() == WSAENOTSOCK) {
throw new SocketException("Socket closed");
} else {
throw NET_ThrowCurrent("socket write error");
}
}
len -= chunkLen;
off += chunkLen;
}
}
/**
* Writes to the socket with appropriate locking of the
* FileDescriptor.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private void socketWrite(byte b[], int off, int len) throws IOException {
if (len <= 0 || off < 0 || off + len > b.length) {
if (len == 0) {
return;
}
throw new ArrayIndexOutOfBoundsException();
}
Object traceContext = IoTrace.socketWriteBegin();
int bytesWritten = 0;
FileDescriptor fd = impl.acquireFD();
try {
socketWrite0(fd, b, off, len);
bytesWritten = len;
} catch (SocketException se) {
if (se instanceof sun.net.ConnectionResetException) {
impl.setConnectionResetPending();
se = new SocketException("Connection reset");
}
if (impl.isClosedOrPending()) {
throw new SocketException("Socket closed");
} else {
throw se;
}
} finally {
impl.releaseFD();
IoTrace.socketWriteEnd(traceContext, impl.address, impl.port, bytesWritten);
}
}
/**
* Writes a byte to the socket.
* @param b the data to be written
* @exception IOException If an I/O error has occurred.
*/
public void write(int b) throws IOException {
temp[0] = (byte)b;
socketWrite(temp, 0, 1);
}
/**
* Writes the contents of the buffer <i>b</i> to the socket.
* @param b the data to be written
* @exception SocketException If an I/O error has occurred.
*/
public void write(byte b[]) throws IOException {
socketWrite(b, 0, b.length);
}
/**
* Writes <i>length</i> bytes from buffer <i>b</i> starting at
* offset <i>len</i>.
* @param b the data to be written
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception SocketException If an I/O error has occurred.
*/
public void write(byte b[], int off, int len) throws IOException {
socketWrite(b, off, len);
}
/**
* Closes the stream.
*/
private boolean closing = false;
public void close() throws IOException {
// Prevent recursion. See BugId 4484411
if (closing)
return;
closing = true;
if (socket != null) {
if (!socket.isClosed())
socket.close();
} else
impl.close();
closing = false;
}
/**
* Overrides finalize, the fd is closed by the Socket.
*/
protected void finalize() {}
}

View File

@@ -0,0 +1,190 @@
/*
Copyright (C) 2002-2010 Jeroen Frijters
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
package java.net;
import cli.System.Net.IPAddress;
import cli.System.Net.IPEndPoint;
import cli.System.Net.Sockets.SocketOptionName;
import cli.System.Net.Sockets.SocketOptionLevel;
import ikvm.lang.CIL;
import java.io.IOException;
@ikvm.lang.Internal
public final class SocketUtil
{
private SocketUtil() { }
// Winsock Error Codes
public static final int WSAEINVAL = 10022;
public static final int WSAEWOULDBLOCK = 10035;
public static final int WSAEMSGSIZE = 10040;
public static final int WSAENOPROTOOPT = 10042;
public static final int WSAEADDRINUSE = 10048;
public static final int WSAENETUNREACH = 10051;
public static final int WSAECONNRESET = 10054;
public static final int WSAESHUTDOWN = 10058;
public static final int WSAETIMEDOUT = 10060;
public static final int WSAECONNREFUSED = 10061;
public static final int WSAEHOSTUNREACH = 10065;
public static final int WSAHOST_NOT_FOUND = 11001;
public static IOException convertSocketExceptionToIOException(cli.System.Net.Sockets.SocketException x) throws IOException
{
switch (x.get_ErrorCode())
{
case WSAEADDRINUSE:
return new BindException(x.getMessage());
case WSAENETUNREACH:
case WSAEHOSTUNREACH:
return new NoRouteToHostException(x.getMessage());
case WSAETIMEDOUT:
return new SocketTimeoutException(x.getMessage());
case WSAECONNREFUSED:
return new PortUnreachableException(x.getMessage());
case WSAHOST_NOT_FOUND:
return new UnknownHostException(x.getMessage());
default:
return new SocketException(x.getMessage() + "\nError Code: " + x.get_ErrorCode());
}
}
public static IPAddress getAddressFromInetAddress(InetAddress addr)
{
return getAddressFromInetAddress(addr, false);
}
public static IPAddress getAddressFromInetAddress(InetAddress addr, boolean v4mapped)
{
byte[] b = addr.getAddress();
if (b.length == 16)
{
// FXBUG in .NET 1.1 you can only construct IPv6 addresses (not IPv4) with this constructor
// (according to the documentation this was fixed in .NET 2.0)
return new IPAddress(b);
}
else if (v4mapped)
{
if (b[0] == 0 && b[1] == 0 && b[2] == 0 && b[3] == 0)
{
return IPAddress.IPv6Any;
}
byte[] b16 = new byte[16];
b16[10] = -1;
b16[11] = -1;
b16[12] = b[0];
b16[13] = b[1];
b16[14] = b[2];
b16[15] = b[3];
return new IPAddress(b16);
}
else
{
return new IPAddress((((b[3] & 0xff) << 24) + ((b[2] & 0xff) << 16) + ((b[1] & 0xff) << 8) + (b[0] & 0xff)) & 0xffffffffL);
}
}
public static InetAddress getInetAddressFromIPEndPoint(IPEndPoint endpoint)
{
try
{
return InetAddress.getByAddress(endpoint.get_Address().GetAddressBytes());
}
catch (UnknownHostException x)
{
// this exception only happens if the address byte array is of invalid length, which cannot happen unless
// the .NET socket returns a bogus address
throw (InternalError)new InternalError().initCause(x);
}
}
static void setCommonSocketOption(cli.System.Net.Sockets.Socket netSocket, int cmd, boolean on, Object value) throws SocketException
{
try
{
if (false) throw new cli.System.Net.Sockets.SocketException();
if (false) throw new cli.System.ObjectDisposedException("");
switch (cmd)
{
case SocketOptions.SO_REUSEADDR:
netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress), on ? 1 : 0);
break;
case SocketOptions.SO_SNDBUF:
netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer), ((Integer)value).intValue());
break;
case SocketOptions.SO_RCVBUF:
netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer), ((Integer)value).intValue());
break;
case SocketOptions.IP_TOS:
netSocket.SetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService), ((Integer)value).intValue());
break;
case SocketOptions.SO_BINDADDR: // read-only
default:
throw new SocketException("Invalid socket option: " + cmd);
}
}
catch (cli.System.Net.Sockets.SocketException x)
{
throw new SocketException(x.getMessage());
}
catch (cli.System.ObjectDisposedException x1)
{
throw new SocketException("Socket is closed");
}
}
static int getCommonSocketOption(cli.System.Net.Sockets.Socket netSocket, int opt, Object iaContainerObj) throws SocketException
{
try
{
if (false) throw new cli.System.Net.Sockets.SocketException();
if (false) throw new cli.System.ObjectDisposedException("");
switch (opt)
{
case SocketOptions.SO_REUSEADDR:
return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReuseAddress))) == 0 ? -1 : 1;
case SocketOptions.SO_SNDBUF:
return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.SendBuffer)));
case SocketOptions.SO_RCVBUF:
return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.Socket), SocketOptionName.wrap(SocketOptionName.ReceiveBuffer)));
case SocketOptions.IP_TOS:
// TODO handle IPv6 here
return CIL.unbox_int(netSocket.GetSocketOption(SocketOptionLevel.wrap(SocketOptionLevel.IP), SocketOptionName.wrap(SocketOptionName.TypeOfService)));
case SocketOptions.SO_BINDADDR:
((InetAddressContainer)iaContainerObj).addr = getInetAddressFromIPEndPoint((IPEndPoint)netSocket.get_LocalEndPoint());
return 0;
default:
throw new SocketException("Invalid socket option: " + opt);
}
}
catch (cli.System.Net.Sockets.SocketException x)
{
throw new SocketException(x.getMessage());
}
catch (cli.System.ObjectDisposedException x1)
{
throw new SocketException("Socket is closed");
}
}
}

View File

@@ -0,0 +1,269 @@
/*
* Copyright (c) 2007, 2011, 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;
/**
* This class defines the plain DatagramSocketImpl that is used for all
* Windows versions lower than Vista. It adds support for IPv6 on
* these platforms where available.
*
* For backward compatibility windows platforms that do not have IPv6
* support also use this implementation, and fd1 gets set to null
* during socket creation.
*
* @author Chris Hegarty
*/
class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl
{
/* Used for IPv6 on Windows only */
FileDescriptor fd1;
/*
* Needed for ipv6 on windows because we need to know
* if the socket was bound to ::0 or 0.0.0.0, when a caller
* asks for it. In this case, both sockets are used, but we
* don't know whether the caller requested ::0 or 0.0.0.0
* and need to remember it here.
*/
private InetAddress anyLocalBoundAddr=null;
cli.System.Net.Sockets.Socket fduse=null; /* saved between peek() and receive() calls */
/* saved between successive calls to receive, if data is detected
* on both sockets at same time. To ensure that one socket is not
* starved, they rotate using this field
*/
cli.System.Net.Sockets.Socket lastfd=null;
// true if this socket is exclusively bound
private final boolean exclusiveBind;
/*
* Set to true if SO_REUSEADDR is set after the socket is bound to
* indicate SO_REUSEADDR is being emulated
*/
private boolean reuseAddressEmulated;
// emulates SO_REUSEADDR when exclusiveBind is true and socket is bound
private boolean isReuseAddress;
TwoStacksPlainDatagramSocketImpl(boolean exclBind) {
exclusiveBind = exclBind;
}
protected synchronized void create() throws SocketException {
fd1 = new FileDescriptor();
try {
super.create();
} catch (SocketException e) {
fd1 = null;
throw e;
}
}
protected synchronized void bind(int lport, InetAddress laddr)
throws SocketException {
super.bind(lport, laddr);
if (laddr.isAnyLocalAddress()) {
anyLocalBoundAddr = laddr;
}
}
@Override
protected synchronized void bind0(int lport, InetAddress laddr)
throws SocketException
{
bind0(lport, laddr, exclusiveBind);
}
protected synchronized void receive(DatagramPacket p)
throws IOException {
try {
receive0(p);
} finally {
fduse = null;
}
}
public Object getOption(int optID) throws SocketException {
if (isClosed()) {
throw new SocketException("Socket Closed");
}
if (optID == SO_BINDADDR) {
if (fd != null && fd1 != null) {
return anyLocalBoundAddr;
}
return socketGetOption(optID);
} else if (optID == SO_REUSEADDR && reuseAddressEmulated) {
return isReuseAddress;
} else {
return super.getOption(optID);
}
}
protected void socketSetOption(int opt, Object val)
throws SocketException
{
if (opt == SO_REUSEADDR && exclusiveBind && localPort != 0) {
// socket already bound, emulate
reuseAddressEmulated = true;
isReuseAddress = (Boolean)val;
} else {
socketNativeSetOption(opt, val);
}
}
protected boolean isClosed() {
return (fd == null && fd1 == null) ? true : false;
}
protected void close() {
if (fd != null || fd1 != null) {
datagramSocketClose();
ResourceManager.afterUdpClose();
fd = null;
fd1 = null;
}
}
/* Native methods */
protected synchronized void bind0(int lport, InetAddress laddr,
boolean exclBind) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.bind0(env, this, lport, laddr, exclBind);
env.ThrowPendingException();
}
protected void send(DatagramPacket packet) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.send(env, this, packet);
env.ThrowPendingException();
}
protected synchronized int peek(InetAddress addressObj) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = TwoStacksPlainDatagramSocketImpl_c.peek(env, this, addressObj);
env.ThrowPendingException();
return ret;
}
protected synchronized int peekData(DatagramPacket p) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = TwoStacksPlainDatagramSocketImpl_c.peekData(env, this, p);
env.ThrowPendingException();
return ret;
}
protected synchronized void receive0(DatagramPacket packet) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.receive0(env, this, packet);
env.ThrowPendingException();
}
protected void setTimeToLive(int ttl) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.setTimeToLive(env, this, ttl);
env.ThrowPendingException();
}
protected int getTimeToLive() throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = TwoStacksPlainDatagramSocketImpl_c.getTimeToLive(env, this);
env.ThrowPendingException();
return ret;
}
protected void setTTL(byte ttl) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.setTTL(env, this, ttl);
env.ThrowPendingException();
}
protected byte getTTL() throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
byte ret = TwoStacksPlainDatagramSocketImpl_c.getTTL(env, this);
env.ThrowPendingException();
return ret;
}
protected void join(InetAddress inetaddr, NetworkInterface netIf) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.join(env, this, inetaddr, netIf);
env.ThrowPendingException();
}
protected void leave(InetAddress inetaddr, NetworkInterface netIf) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.leave(env, this, inetaddr, netIf);
env.ThrowPendingException();
}
protected void datagramSocketCreate() throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.datagramSocketCreate(env, this);
env.ThrowPendingException();
}
protected void datagramSocketClose() {
TwoStacksPlainDatagramSocketImpl_c.datagramSocketClose(this);
}
protected void socketNativeSetOption(int opt, Object val) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.socketNativeSetOption(env, this, opt, val);
env.ThrowPendingException();
}
protected Object socketGetOption(int opt) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
Object ret = TwoStacksPlainDatagramSocketImpl_c.socketGetOption(env, this, opt);
env.ThrowPendingException();
return ret;
}
protected void connect0(InetAddress address, int port) throws SocketException {
if (ikvm.internal.Util.MONO) {
// MONOBUG Mono doesn't allow Socket.Connect(IPAddress.Any, 0) to disconnect a datagram socket,
// so we throw a SocketException, this will cause DatagramSocket to emulate connectedness
throw new SocketException("connected datagram sockets not supported on Mono");
}
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainDatagramSocketImpl_c.connect0(env, this, address, port);
env.ThrowPendingException();
}
protected void disconnect0(int family) {
TwoStacksPlainDatagramSocketImpl_c.disconnect0(this, family);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,285 @@
/*
* Copyright (c) 2007, 2008, 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;
/*
* This class defines the plain SocketImpl that is used for all
* Windows version lower than Vista. It adds support for IPv6 on
* these platforms where available.
*
* For backward compatibility Windows platforms that do not have IPv6
* support also use this implementation, and fd1 gets set to null
* during socket creation.
*
* @author Chris Hegarty
*/
class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl
{
/* second fd, used for ipv6 on windows only.
* fd1 is used for listeners and for client sockets at initialization
* until the socket is connected. Up to this point fd always refers
* to the ipv4 socket and fd1 to the ipv6 socket. After the socket
* becomes connected, fd always refers to the connected socket
* (either v4 or v6) and fd1 is closed.
*
* For ServerSockets, fd always refers to the v4 listener and
* fd1 the v6 listener.
*/
FileDescriptor fd1;
/*
* Needed for ipv6 on windows because we need to know
* if the socket is bound to ::0 or 0.0.0.0, when a caller
* asks for it. Otherwise we don't know which socket to ask.
*/
private InetAddress anyLocalBoundAddr = null;
/* to prevent starvation when listening on two sockets, this is
* is used to hold the id of the last socket we accepted on.
*/
cli.System.Net.Sockets.Socket lastfd = null;
// 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;
}
/**
* Creates a socket with a boolean that specifies whether this
* is a stream socket (true) or an unconnected UDP socket (false).
*/
protected synchronized void create(boolean stream) throws IOException {
fd1 = new FileDescriptor();
try {
super.create(stream);
} catch (IOException e) {
fd1 = null;
throw e;
}
}
/**
* Binds the socket to the specified address of the specified local port.
* @param address the address
* @param port the port
*/
protected synchronized void bind(InetAddress address, int lport)
throws IOException
{
super.bind(address, lport);
if (address.isAnyLocalAddress()) {
anyLocalBoundAddr = address;
}
}
public Object getOption(int opt) throws SocketException {
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
if (opt == SO_BINDADDR) {
if (fd != null && fd1 != null ) {
/* must be unbound or else bound to anyLocal */
return anyLocalBoundAddr;
}
InetAddressContainer in = new InetAddressContainer();
socketGetOption(opt, in);
return in.addr;
} else if (opt == SO_REUSEADDR && exclusiveBind) {
// SO_REUSEADDR emulated when using exclusive bind
return isReuseAddress;
} else
return super.getOption(opt);
}
@Override
void socketBind(InetAddress address, int port) throws IOException {
socketBind(address, port, exclusiveBind);
}
@Override
void socketSetOption(int opt, boolean on, Object value)
throws SocketException
{
// SO_REUSEADDR emulated when using exclusive bind
if (opt == SO_REUSEADDR && exclusiveBind)
isReuseAddress = on;
else
socketNativeSetOption(opt, on, value);
}
/**
* Closes the socket.
*/
@Override
protected void close() throws IOException {
synchronized(fdLock) {
if (fd != null || fd1 != null) {
if (!stream) {
ResourceManager.afterUdpClose();
}
if (fdUseCount == 0) {
if (closePending) {
return;
}
closePending = true;
socketClose();
fd = null;
fd1 = null;
return;
} else {
/*
* If a thread has acquired the fd and a close
* isn't pending then use a deferred close.
* Also decrement fdUseCount to signal the last
* thread that releases the fd to close it.
*/
if (!closePending) {
closePending = true;
fdUseCount--;
socketClose();
}
}
}
}
}
@Override
void reset() throws IOException {
if (fd != null || fd1 != null) {
socketClose();
}
fd = null;
fd1 = null;
super.reset();
}
/*
* Return true if already closed or close is pending
*/
@Override
public boolean isClosedOrPending() {
/*
* Lock on fdLock to ensure that we wait if a
* close is in progress.
*/
synchronized (fdLock) {
if (closePending || (fd == null && fd1 == null)) {
return true;
} else {
return false;
}
}
}
/* Native methods */
void socketCreate(boolean stream) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketCreate(env, this, stream);
env.ThrowPendingException();
}
void socketConnect(InetAddress address, int port, int timeout) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketConnect(env, this, address, port, timeout);
env.ThrowPendingException();
}
void socketBind(InetAddress address, int localport, boolean exclBind) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketBind(env, this, address, localport, exclBind);
env.ThrowPendingException();
}
void socketListen(int count) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketListen(env, this, count);
env.ThrowPendingException();
}
void socketAccept(SocketImpl socket) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketAccept(env, this, socket);
env.ThrowPendingException();
}
int socketAvailable() throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = TwoStacksPlainSocketImpl_c.socketAvailable(env, this);
env.ThrowPendingException();
return ret;
}
void socketClose0(boolean useDeferredClose) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketClose0(env, this, useDeferredClose);
env.ThrowPendingException();
}
void socketShutdown(int howto) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketShutdown(env, this, howto);
env.ThrowPendingException();
}
void socketNativeSetOption(int cmd, boolean on, Object value) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketNativeSetOption(env, this, cmd, on, value);
env.ThrowPendingException();
}
int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
int ret = TwoStacksPlainSocketImpl_c.socketGetOption(env, this, opt, iaContainerObj);
env.ThrowPendingException();
return ret;
}
int socketGetOption1(int opt, Object iaContainerObj, FileDescriptor fd) throws SocketException {
throw new UnsatisfiedLinkError();
}
void socketSendUrgentData(int data) throws IOException {
ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv();
TwoStacksPlainSocketImpl_c.socketSendUrgentData(env, this, data);
env.ThrowPendingException();
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff