diff options
Diffstat (limited to 'openjdk/java/net')
-rw-r--r-- | openjdk/java/net/DefaultDatagramSocketImplFactory.java | 151 | ||||
-rw-r--r-- | openjdk/java/net/DualStackPlainDatagramSocketImpl.java | 334 | ||||
-rw-r--r-- | openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java | 488 | ||||
-rw-r--r-- | openjdk/java/net/DualStackPlainSocketImpl.java | 360 | ||||
-rw-r--r-- | openjdk/java/net/DualStackPlainSocketImpl_c.java | 490 | ||||
-rw-r--r-- | openjdk/java/net/PlainSocketImpl.java | 356 | ||||
-rw-r--r-- | openjdk/java/net/SocketInputStream.java | 332 | ||||
-rw-r--r-- | openjdk/java/net/SocketOutputStream.java | 254 | ||||
-rw-r--r-- | openjdk/java/net/SocketUtil.java | 190 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java | 269 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java | 2463 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl.java | 285 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl_c.java | 1080 | ||||
-rw-r--r-- | openjdk/java/net/net_util_md.java | 884 |
14 files changed, 0 insertions, 7936 deletions
diff --git a/openjdk/java/net/DefaultDatagramSocketImplFactory.java b/openjdk/java/net/DefaultDatagramSocketImplFactory.java deleted file mode 100644 index 7d4f8edb..00000000 --- a/openjdk/java/net/DefaultDatagramSocketImplFactory.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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); - } - } -} diff --git a/openjdk/java/net/DualStackPlainDatagramSocketImpl.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl.java deleted file mode 100644 index 1d74e28c..00000000 --- a/openjdk/java/net/DualStackPlainDatagramSocketImpl.java +++ /dev/null @@ -1,334 +0,0 @@ -/* - * 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; - } -} diff --git a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java deleted file mode 100644 index 1f4ed69b..00000000 --- a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java +++ /dev/null @@ -1,488 +0,0 @@ -/* - * 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]; -} -} diff --git a/openjdk/java/net/DualStackPlainSocketImpl.java b/openjdk/java/net/DualStackPlainSocketImpl.java deleted file mode 100644 index a3584d86..00000000 --- a/openjdk/java/net/DualStackPlainSocketImpl.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * 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(); - } -} diff --git a/openjdk/java/net/DualStackPlainSocketImpl_c.java b/openjdk/java/net/DualStackPlainSocketImpl_c.java deleted file mode 100644 index 15c2a184..00000000 --- a/openjdk/java/net/DualStackPlainSocketImpl_c.java +++ /dev/null @@ -1,490 +0,0 @@ -/* - * 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"); - } -} -} diff --git a/openjdk/java/net/PlainSocketImpl.java b/openjdk/java/net/PlainSocketImpl.java deleted file mode 100644 index 5b7f850d..00000000 --- a/openjdk/java/net/PlainSocketImpl.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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); - } -} diff --git a/openjdk/java/net/SocketInputStream.java b/openjdk/java/net/SocketInputStream.java deleted file mode 100644 index 161947cc..00000000 --- a/openjdk/java/net/SocketInputStream.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * 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() {} -} diff --git a/openjdk/java/net/SocketOutputStream.java b/openjdk/java/net/SocketOutputStream.java deleted file mode 100644 index fd6e2c4f..00000000 --- a/openjdk/java/net/SocketOutputStream.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * 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() {} -} diff --git a/openjdk/java/net/SocketUtil.java b/openjdk/java/net/SocketUtil.java deleted file mode 100644 index d9a30869..00000000 --- a/openjdk/java/net/SocketUtil.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - 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"); - } - } -} diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java deleted file mode 100644 index 2b2bde1b..00000000 --- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * 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); - } -} diff --git a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java deleted file mode 100644 index d84a427b..00000000 --- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java +++ /dev/null @@ -1,2463 +0,0 @@ -/* - * Copyright (c) 1997, 2013, 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.*; -import static java.net.InetAddress.IPv4; -import static java.net.InetAddress.IPv6; - -final class TwoStacksPlainDatagramSocketImpl_c -{ -static final int ni_class = 0; -static final int JVM_IO_ERR = -1; -static final int JVM_IO_INTR = -2; - -static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; -static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; -static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; -static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; -static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; -static final int java_net_SocketOptions_SO_BROADCAST = SocketOptions.SO_BROADCAST; -static final int java_net_SocketOptions_IP_MULTICAST_LOOP = SocketOptions.IP_MULTICAST_LOOP; -static final int java_net_SocketOptions_IP_MULTICAST_IF = SocketOptions.IP_MULTICAST_IF; -static final int java_net_SocketOptions_IP_MULTICAST_IF2 = SocketOptions.IP_MULTICAST_IF2; - -/* - -#include <windows.h> -#include <winsock2.h> -#include <ws2tcpip.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <malloc.h> -#include <sys/types.h> - -#ifndef IPTOS_TOS_MASK -#define IPTOS_TOS_MASK 0x1e -#endif -#ifndef IPTOS_PREC_MASK -#define IPTOS_PREC_MASK 0xe0 -#endif - -#include "java_net_TwoStacksPlainDatagramSocketImpl.h" -#include "java_net_SocketOptions.h" -#include "java_net_NetworkInterface.h" - -#include "NetworkInterface.h" -#include "jvm.h" -#include "jni_util.h" -#include "net_util.h" - -#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000) -#define IN_MULTICAST(i) IN_CLASSD(i) - -*/ - -static boolean IN_MULTICAST(int ipv4address) { - return ((ipv4address >> 24) & 0xf0) == 0xe0; -} - -/************************************************************************ - * TwoStacksPlainDatagramSocketImpl - */ - -/* -static jfieldID IO_fd_fdID; -static jfieldID pdsi_trafficClassID; -jfieldID pdsi_fdID; -jfieldID pdsi_fd1ID; -jfieldID pdsi_fduseID; -jfieldID pdsi_lastfdID; -jfieldID pdsi_timeoutID; - -jfieldID pdsi_localPortID; -jfieldID pdsi_connected; - -static jclass ia4_clazz; -static jmethodID ia4_ctor; - -static CRITICAL_SECTION sizeCheckLock; -*/ - -/* Windows OS version is XP or better */ -static final boolean xp_or_later = true; -/* Windows OS version is Windows 2000 or better */ -//static int w2k_or_later = 0; - -/* - * Notes about UDP/IPV6 on Windows (XP and 2003 server): - * - * fd always points to the IPv4 fd, and fd1 points to the IPv6 fd. - * Both fds are used when we bind to a wild-card address. When a specific - * address is used, only one of them is used. - */ - -/* - * Returns a java.lang.Integer based on 'i' - */ -/* -jobject createInteger(JNIEnv *env, int i) { - static jclass i_class; - static jmethodID i_ctrID; - static jfieldID i_valueID; - - if (i_class == NULL) { - jclass c = (*env)->FindClass(env, "java/lang/Integer"); - CHECK_NULL_RETURN(c, NULL); - i_ctrID = (*env)->GetMethodID(env, c, "<init>", "(I)V"); - CHECK_NULL_RETURN(i_ctrID, NULL); - i_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(i_class, NULL); - } - - return ( (*env)->NewObject(env, i_class, i_ctrID, i) ); -} -*/ - -/* - * Returns a java.lang.Boolean based on 'b' - */ -/* -jobject createBoolean(JNIEnv *env, int b) { - static jclass b_class; - static jmethodID b_ctrID; - static jfieldID b_valueID; - - if (b_class == NULL) { - jclass c = (*env)->FindClass(env, "java/lang/Boolean"); - CHECK_NULL_RETURN(c, NULL); - b_ctrID = (*env)->GetMethodID(env, c, "<init>", "(Z)V"); - CHECK_NULL_RETURN(b_ctrID, NULL); - b_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(b_class, NULL); - } - - return( (*env)->NewObject(env, b_class, b_ctrID, (jboolean)(b!=0)) ); -} -*/ - - -static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { - FileDescriptor fdObj = _this.fd; - - if (fdObj == NULL) { - return null; - } - return fdObj.getSocket(); -} - -static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { - FileDescriptor fdObj = _this.fd1; - - if (fdObj == NULL) { - return null; - } - return fdObj.getSocket(); -} - -/* - * This function returns JNI_TRUE if the datagram size exceeds the underlying - * provider's ability to send to the target address. The following OS - * oddities have been observed :- - * - * 1. On Windows 95/98 if we try to send a datagram > 12k to an application - * on the same machine then the send will fail silently. - * - * 2. On Windows ME if we try to send a datagram > supported by underlying - * provider then send will not return an error. - * - * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail - * with WSAEADDRNOTAVAIL. - * - * 4. On Windows 95/98 if we exceed the maximum size when sending to - * another machine then WSAEINVAL is returned. - * - */ -/* -jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) -{ -#define DEFAULT_MSG_SIZE 65527 - static jboolean initDone; - static jboolean is95or98; - static int maxmsg; - - typedef struct _netaddr { /* Windows 95/98 only *-/ - unsigned long addr; - struct _netaddr *next; - } netaddr; - static netaddr *addrList; - netaddr *curr; - - /* - * First time we are called we must determine which OS this is and also - * get the maximum size supported by the underlying provider. - * - * In addition on 95/98 we must enumerate our IP addresses. - *-/ - if (!initDone) { - EnterCriticalSection(&sizeCheckLock); - - if (initDone) { - /* another thread got there first *-/ - LeaveCriticalSection(&sizeCheckLock); - - } else { - OSVERSIONINFO ver; - int len; - - /* - * Step 1: Determine which OS this is. - *-/ - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - - is95or98 = JNI_FALSE; - if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && - ver.dwMajorVersion == 4 && - (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) { - - is95or98 = JNI_TRUE; - } - - /* - * Step 2: Determine the maximum datagram supported by the - * underlying provider. On Windows 95 if winsock hasn't been - * upgraded (ie: unsupported configuration) then we assume - * the default 64k limit. - *-/ - len = sizeof(maxmsg); - if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) { - maxmsg = DEFAULT_MSG_SIZE; - } - - /* - * Step 3: On Windows 95/98 then enumerate the IP addresses on - * this machine. This is neccesary because we need to check if the - * datagram is being sent to an application on the same machine. - *-/ - if (is95or98) { - char hostname[255]; - struct hostent *hp; - - if (gethostname(hostname, sizeof(hostname)) == -1) { - LeaveCriticalSection(&sizeCheckLock); - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname"); - return JNI_TRUE; - } - hp = (struct hostent *)gethostbyname(hostname); - if (hp != NULL) { - struct in_addr **addrp = (struct in_addr **) hp->h_addr_list; - - while (*addrp != (struct in_addr *) 0) { - curr = (netaddr *)malloc(sizeof(netaddr)); - if (curr == NULL) { - while (addrList != NULL) { - curr = addrList->next; - free(addrList); - addrList = curr; - } - LeaveCriticalSection(&sizeCheckLock); - JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); - return JNI_TRUE; - } - curr->addr = htonl((*addrp)->S_un.S_addr); - curr->next = addrList; - addrList = curr; - addrp++; - } - } - } - - /* - * Step 4: initialization is done so set flag and unlock cs - *-/ - initDone = JNI_TRUE; - LeaveCriticalSection(&sizeCheckLock); - } - } - - /* - * Now examine the size of the datagram :- - * - * (a) If exceeds size of service provider return 'false' to indicate that - * we exceed the limit. - * (b) If not 95/98 then return 'true' to indicate that the size is okay. - * (c) On 95/98 if the size is <12k we are okay. - * (d) On 95/98 if size > 12k then check if the destination is the current - * machine. - *-/ - if (size > maxmsg) { /* step (a) *-/ - return JNI_TRUE; - } - if (!is95or98) { /* step (b) *-/ - return JNI_FALSE; - } - if (size <= 12280) { /* step (c) *-/ - return JNI_FALSE; - } - - /* step (d) *-/ - - if ((addr & 0x7f000000) == 0x7f000000) { - return JNI_TRUE; - } - curr = addrList; - while (curr != NULL) { - if (curr->addr == addr) { - return JNI_TRUE; - } - curr = curr->next; - } - return JNI_FALSE; -} -*/ - -/* - * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable - */ -static boolean supportPortUnreachable() { - // we don't support anything pre-Win2K anyway - return true; -} - -/* - * 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(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; - - /* - * A no-op if this OS doesn't support it. - */ - if (!supportPortUnreachable()) { - return JNI_FALSE; - } - - /* - * 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_TwoStacksPlainDatagramSocketImpl - * Method: init - * Signature: ()V - */ -/* -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { - - OSVERSIONINFO ver; - int version; - ver.dwOSVersionInfoSize = sizeof(ver); - GetVersionEx(&ver); - - version = ver.dwMajorVersion * 10 + ver.dwMinorVersion; - xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51); - w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50); - - /* get fieldIDs *-/ - pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;"); - CHECK_NULL(pdsi_fdID); - pdsi_fd1ID = (*env)->GetFieldID(env, cls, "fd1", "Ljava/io/FileDescriptor;"); - CHECK_NULL(pdsi_fd1ID); - pdsi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); - CHECK_NULL(pdsi_timeoutID); - pdsi_fduseID = (*env)->GetFieldID(env, cls, "fduse", "I"); - CHECK_NULL(pdsi_fduseID); - pdsi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(pdsi_lastfdID); - pdsi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); - CHECK_NULL(pdsi_trafficClassID); - pdsi_localPortID = (*env)->GetFieldID(env, cls, "localPort", "I"); - CHECK_NULL(pdsi_localPortID); - pdsi_connected = (*env)->GetFieldID(env, cls, "connected", "Z"); - CHECK_NULL(pdsi_connected); - - cls = (*env)->FindClass(env, "java/io/FileDescriptor"); - CHECK_NULL(cls); - IO_fd_fdID = NET_GetFileDescriptorID(env); - CHECK_NULL(IO_fd_fdID); - - ia4_clazz = (*env)->FindClass(env, "java/net/Inet4Address"); - CHECK_NULL(ia4_clazz); - ia4_clazz = (*env)->NewGlobalRef(env, ia4_clazz); - CHECK_NULL(ia4_clazz); - ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V"); - CHECK_NULL(ia4_ctor); - - - InitializeCriticalSection(&sizeCheckLock); -} -*/ - -static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, - int port, InetAddress addressObj, - boolean exclBind) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - int family; - boolean ipv6_supported = ipv6_available(); - - SOCKETADDRESS lcladdr; - lcladdr = new SOCKETADDRESS(); - - family = getInetAddress_family(env, addressObj); - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Protocol family not supported"); - return; - } - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); - return; - } else { - fd = fdObj.getSocket(); - if (ipv6_supported) { - fd1 = fd1Obj.getSocket(); - } - } - if (IS_NULL(addressObj)) { - JNU_ThrowNullPointerException(env, "argument address"); - return; - } - - if (NET_InetAddressToSockaddr(env, addressObj, port, lcladdr, JNI_FALSE) != 0) { - return; - } - - if (ipv6_supported) { - ipv6bind v6bind = new ipv6bind(); - v6bind.addr = lcladdr; - v6bind.ipv4_fd = fd; - v6bind.ipv6_fd = fd1; - if (NET_BindV6(v6bind, exclBind) != -1) { - /* check if the fds have changed */ - if (v6bind.ipv4_fd != fd) { - fd = v6bind.ipv4_fd; - if (fd == null) { - /* socket is closed. */ - _this.fd = null; - } else { - /* socket was re-created */ - fdObj.setSocket(fd); - } - } - if (v6bind.ipv6_fd != fd1) { - fd1 = v6bind.ipv6_fd; - if (fd1 == null) { - /* socket is closed. */ - _this.fd1 = null; - } else { - /* socket was re-created */ - fd1Obj.setSocket(fd1); - } - } - } else { - NET_ThrowCurrent (env, "Cannot bind"); - return; - } - } else { - if (NET_WinBind(fd, lcladdr, exclBind) == -1) { - if (WSAGetLastError() == WSAEACCES) { - WSASetLastError(WSAEADDRINUSE); - } - NET_ThrowCurrent(env, "Cannot bind"); - return; - } - } - - if (port == 0) { - if (fd == null) { - /* must be an IPV6 only socket. */ - fd = fd1; - } - if (getsockname(fd, lcladdr) == -1) { - NET_ThrowCurrent(env, "JVM_GetSockName"); - return; - } - port = ntohs(GET_PORT (lcladdr)); - } - _this.localPort = port; -} - - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: connect0 - * Signature: (Ljava/net/InetAddress;I)V - */ - -static void connect0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress address, int port) { - /* The object's field */ - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - /* The fdObj'fd */ - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - cli.System.Net.Sockets.Socket fdc; - /* The packetAddress address, family and port */ - int addr, family; - SOCKETADDRESS rmtaddr; - rmtaddr = new SOCKETADDRESS(); - boolean ipv6_supported = ipv6_available(); - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - - if (IS_NULL(address)) { - JNU_ThrowNullPointerException(env, "address"); - return; - } - - addr = getInetAddress_addr(env, address); - - family = getInetAddress_family(env, address); - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Protocol family not supported"); - return; - } - - fdc = family == IPv4? fd: fd1; - - if (xp_or_later) { - /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which - * returns connection reset errors on connected UDP sockets (as well - * as connected sockets). The solution is to only enable this feature - * when the socket is connected - */ - WSAIoctl(fdc, SIO_UDP_CONNRESET, true); - } - - if (NET_InetAddressToSockaddr(env, address, port, rmtaddr, JNI_FALSE) != 0) { - return; - } - - if (connect(fdc, rmtaddr) == -1) { - NET_ThrowCurrent(env, "connect"); - return; - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: disconnect0 - * Signature: ()V - */ - -static void disconnect0(TwoStacksPlainDatagramSocketImpl _this, int family) { - /* The object's field */ - FileDescriptor fdObj; - /* The fdObj'fd */ - cli.System.Net.Sockets.Socket fd; - SOCKETADDRESS addr; - addr = new SOCKETADDRESS(); - - if (family == IPv4) { - fdObj = _this.fd; - } else { - fdObj = _this.fd1; - } - - if (IS_NULL(fdObj)) { - /* disconnect doesn't throw any exceptions */ - return; - } - fd = fdObj.getSocket(); - - connect(fd, addr); - - /* - * use SIO_UDP_CONNRESET - * to disable ICMP port unreachable handling here. - */ - if (xp_or_later) { - WSAIoctl(fd,SIO_UDP_CONNRESET,false); - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: send - * Signature: (Ljava/net/DatagramPacket;)V - */ -static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { - FileDescriptor fdObj; - cli.System.Net.Sockets.Socket fd; - - InetAddress iaObj; - int address; - int family; - - int packetBufferOffset, packetBufferLen, packetPort; - byte[] packetBuffer; - boolean connected; - - SOCKETADDRESS rmtaddr; - rmtaddr = new SOCKETADDRESS(); - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "null packet"); - return; - } - - iaObj = packet.address; - - packetPort = packet.port; - packetBufferOffset = packet.offset; - packetBuffer = packet.buf; - connected = _this.connected; - - if (IS_NULL(iaObj) || IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "null address || null buffer"); - return; - } - - family = getInetAddress_family(env, iaObj); - if (family == IPv4) { - fdObj = _this.fd; - } else { - if (!ipv6_available()) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Protocol not allowed"); - return; - } - fdObj = _this.fd1; - } - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } - fd = fdObj.getSocket(); - - packetBufferLen = packet.length; - /* Note: the buffer needn't be greater than 65,536 (0xFFFF)... - * the maximum size of an IP packet. Anything bigger is truncated anyway. - */ - if (packetBufferLen > MAX_PACKET_LEN) { - packetBufferLen = MAX_PACKET_LEN; - } - - if (connected) { - rmtaddr = null; - } else { - if (NET_InetAddressToSockaddr(env, iaObj, packetPort, rmtaddr, JNI_FALSE) != 0) { - return; - } - } - - /* - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* - * On 95/98 if we try to send a datagram >12k to an application - * on the same machine then this will fail silently. Thus we - * catch this situation here so that we can throw an exception - * when this arises. - * On ME if we try to send a datagram with a size greater than - * that supported by the service provider then no error is - * returned. - *-/ - if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6. - * Check is not necessary on these OSes *-/ - if (connected) { - address = getInetAddress_addr(env, iaObj); - } else { - address = ntohl(rmtaddr.him4.sin_addr.s_addr); - } - - if (exceedSizeLimit(env, fd, address, packetBufferLen)) { - if (!((*env)->ExceptionOccurred(env))) { - NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed"); - } - return; - } - } - - /* When JNI-ifying the JDK's IO routines, we turned - * reads and writes of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - *-/ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "Send buf native heap allocation failed"); - return; - } - } else { - fullPacket = &(BUF[0]); - } - */ - - switch (sendto(fd, packetBuffer, packetBufferOffset, packetBufferLen, 0, rmtaddr)) { - case JVM_IO_ERR: - NET_ThrowCurrent(env, "Datagram send failed"); - break; - - case JVM_IO_INTR: - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } -} - -/* - * check which socket was last serviced when there was data on both sockets. - * Only call this if sure that there is data on both sockets. - */ -private static cli.System.Net.Sockets.Socket checkLastFD (TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1) { - cli.System.Net.Sockets.Socket nextfd, lastfd = _this.lastfd; - if (lastfd == null) { - /* arbitrary. Choose fd */ - _this.lastfd = fd; - return fd; - } else { - if (lastfd == fd) { - nextfd = fd1; - } else { - nextfd = fd; - } - _this.lastfd = nextfd; - return nextfd; - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: peek - * Signature: (Ljava/net/InetAddress;)I - */ -static int peek(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress addressObj) { - FileDescriptor fdObj = _this.fd; - int timeout = _this.timeout; - cli.System.Net.Sockets.Socket fd; - - /* The address and family fields of addressObj */ - int address, family; - - int n; - SOCKETADDRESS remote_addr = new SOCKETADDRESS(); - byte[] buf = new byte[1]; - boolean retry; - long prevTime = 0; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); - return -1; - } else { - fd = fdObj.getSocket(); - if (fd == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - return -1; - } - } - if (IS_NULL(addressObj)) { - JNU_ThrowNullPointerException(env, "Null address in peek()"); - return -1; - } else { - address = getInetAddress_addr(env, addressObj); - /* We only handle IPv4 for now. Will support IPv6 once its in the os */ - family = AF_INET; - } - - do { - retry = FALSE; - - /* - * If a timeout has been specified then we select on the socket - * waiting for a read event or a timeout. - */ - if (timeout != 0) { - int ret; - prevTime = JVM_CurrentTimeMillis(env, 0); - ret = NET_Timeout (fd, timeout); - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Peek timed out"); - return ret; - } else if (ret == JVM_IO_ERR) { - NET_ThrowCurrent(env, "timeout in datagram socket peek"); - return ret; - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - return ret; - } - } - - /* now try the peek */ - n = recvfrom(fd, buf, 1, MSG_PEEK, - remote_addr); - - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - boolean connected; - - /* - * An icmp port unreachable - we must receive this as Windows - * does not reset the state of the socket until this has been - * received. - */ - purgeOutstandingICMP(fd); - - connected = _this.connected; - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", - "ICMP Port Unreachable"); - return 0; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout befor the icmp port - * unreachable arrived. - */ - if (timeout != 0) { - long newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - return 0; - } - prevTime = newTime; - } - - /* Need to retry the recv */ - retry = TRUE; - } - } - } while (retry); - - if (n == JVM_IO_ERR && WSAGetLastError() != WSAEMSGSIZE) { - NET_ThrowCurrent(env, "Datagram peek failed"); - return 0; - } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", null); - return 0; - } - addressObj.holder().address = ntohl(remote_addr.sin_addr.s_addr); - addressObj.holder().family = IPv4; - - /* return port */ - return ntohs(remote_addr.sin_port); -} - -static int peekData(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { - - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - int timeout = _this.timeout; - - byte[] packetBuffer; - int packetBufferOffset, packetBufferLen; - - cli.System.Net.Sockets.Socket fd = null, fd1 = null, fduse = null; - int nsockets=0, errorCode; - int port; - byte[] data; - - boolean checkBoth = false; - int datalen; - int n; - SOCKETADDRESS remote_addr; - remote_addr = new SOCKETADDRESS(); - boolean retry; - long prevTime = 0; - - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - if (fd == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - return -1; - } - nsockets = 1; - } - - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - if (fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - return -1; - } - nsockets ++; - } - - switch (nsockets) { - case 0: - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - return -1; - case 1: - if (!IS_NULL(fdObj)) { - fduse = fd; - } else { - fduse = fd1; - } - break; - case 2: - checkBoth = TRUE; - break; - } - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "packet"); - return -1; - } - - packetBuffer = packet.buf; - - if (IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "packet buffer"); - return -1; - } - - packetBufferOffset = packet.offset; - packetBufferLen = packet.bufLength; - - /* - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* When JNI-ifying the JDK's IO routines, we turned - * read's and write's of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - *-/ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); - return -1; - } - } else { - fullPacket = &(BUF[0]); - } - */ - - do { - int ret; - retry = FALSE; - - /* - * If a timeout has been specified then we select on the socket - * waiting for a read event or a timeout. - */ - if (checkBoth) { - int t = timeout == 0 ? -1: timeout; - prevTime = JVM_CurrentTimeMillis(env, 0); - cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; - ret = NET_Timeout2 (fd, fd1, t, tmp); - fduse = tmp[0]; - /* all subsequent calls to recv() or select() will use the same fd - * for this call to peek() */ - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", - "Peek timed out"); - } else if (ret == JVM_IO_ERR) { - NET_ThrowCurrent(env, "timeout in datagram socket peek"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } - return -1; - } - if (ret == 2) { - fduse = checkLastFD (_this, fd, fd1); - } - checkBoth = FALSE; - } else if (timeout != 0) { - if (prevTime == 0) { - prevTime = JVM_CurrentTimeMillis(env, 0); - } - ret = NET_Timeout (fduse, timeout); - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env,JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } - return -1; - } - } - - /* receive the packet */ - n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, MSG_PEEK, remote_addr); - port = ntohs (GET_PORT(remote_addr)); - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - boolean connected; - - /* - * An icmp port unreachable - we must receive this as Windows - * does not reset the state of the socket until this has been - * received. - */ - purgeOutstandingICMP(fduse); - - connected = _this.connected; - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", - "ICMP Port Unreachable"); - - return -1; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout befor the icmp port - * unreachable arrived. - */ - if (timeout != 0) { - long newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - if (timeout <= 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - return -1; - } - prevTime = newTime; - } - retry = TRUE; - } - } - } while (retry); - - if (n < 0) { - errorCode = WSAGetLastError(); - /* check to see if it's because the buffer was too small */ - if (errorCode == 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.. - */ - n = packetBufferLen; - } else { - /* failure */ - packet.length = 0; - } - } - if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); - } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } else if (n < 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 = packet.address; - if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { - /* force a new InetAddress to be created */ - packetAddress = null; - } - } - if (packetAddress == NULL) { - int[] tmp = { port }; - packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); - port = tmp[0]; - /* stuff the new Inetaddress in the packet */ - packet.address = packetAddress; - } - - /* populate the packet */ - packet.port = port; - packet.length = n; - } - - /* make sure receive() picks up the right fd */ - _this.fduse = fduse; - - return port; -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: receive - * Signature: (Ljava/net/DatagramPacket;)V - */ -static void receive0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPacket packet) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - int timeout = _this.timeout; - byte[] packetBuffer; - int packetBufferOffset, packetBufferLen; - boolean ipv6_supported = ipv6_available(); - - /* as a result of the changes for ipv6, peek() or peekData() - * must be called prior to receive() so that fduse can be set. - */ - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - cli.System.Net.Sockets.Socket fduse = null; - int errorCode; - - int n, nsockets=0; - SOCKETADDRESS remote_addr; - remote_addr = new SOCKETADDRESS(); - boolean retry; - long prevTime = 0, selectTime=0; - boolean connected; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } - - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - nsockets ++; - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - nsockets ++; - } - - if (nsockets == 2) { /* need to choose one of them */ - /* was fduse set in peek? */ - fduse = _this.fduse; - if (fduse == null) { - /* not set in peek(), must select on both sockets */ - int ret, t = (timeout == 0) ? -1: timeout; - cli.System.Net.Sockets.Socket[] tmp = new cli.System.Net.Sockets.Socket[] { fduse }; - ret = NET_Timeout2 (fd, fd1, t, tmp); - fduse = tmp[0]; - if (ret == 2) { - fduse = checkLastFD (_this, fd, fd1); - } else if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } - return; - } - } - } else if (!ipv6_supported) { - fduse = fd; - } else if (IS_NULL(fdObj)) { - /* ipv6 supported: and this socket bound to an IPV6 only address */ - fduse = fd1; - } else { - /* ipv6 supported: and this socket bound to an IPV4 only address */ - fduse = fd; - } - - if (IS_NULL(packet)) { - JNU_ThrowNullPointerException(env, "packet"); - return; - } - - packetBuffer = packet.buf; - - if (IS_NULL(packetBuffer)) { - JNU_ThrowNullPointerException(env, "packet buffer"); - return; - } - - packetBufferOffset = packet.offset; - packetBufferLen = packet.bufLength; - - /* - if (packetBufferLen > MAX_BUFFER_LEN) { - - /* When JNI-ifying the JDK's IO routines, we turned - * read's and write's of byte arrays of size greater - * than 2048 bytes into several operations of size 2048. - * This saves a malloc()/memcpy()/free() for big - * buffers. This is OK for file IO and TCP, but that - * strategy violates the semantics of a datagram protocol. - * (one big send) != (several smaller sends). So here - * we *must* alloc the buffer. Note it needn't be bigger - * than 65,536 (0xFFFF) the max size of an IP packet. - * anything bigger is truncated anyway. - *-/ - fullPacket = (char *)malloc(packetBufferLen); - if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "Receive buf native heap allocation failed"); - return; - } - } else { - fullPacket = &(BUF[0]); - } - */ - - - - /* - * If this Windows edition supports ICMP port unreachable and if we - * are not connected then we need to know if a timeout has been specified - * and if so we need to pick up the current time. These are required in - * order to implement the semantics of timeout, viz :- - * timeout set to t1 but ICMP port unreachable arrives in t2 where - * t2 < t1. In this case we must discard the ICMP packets and then - * wait for the next packet up to a maximum of t1 minus t2. - */ - connected = _this.connected; - if (supportPortUnreachable() && !connected && timeout != 0 &&!ipv6_supported) { - prevTime = JVM_CurrentTimeMillis(env, 0); - } - - if (timeout != 0 && nsockets == 1) { - int ret; - ret = NET_Timeout(fduse, timeout); - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } - return; - } - } - - /* - * Loop only if we discarding ICMP port unreachable packets - */ - do { - retry = FALSE; - - /* receive the packet */ - n = recvfrom(fduse, packetBuffer, packetBufferOffset, packetBufferLen, 0, remote_addr); - - if (n == JVM_IO_ERR) { - if (WSAGetLastError() == WSAECONNRESET) { - /* - * An icmp port unreachable has been received - consume any other - * outstanding packets. - */ - purgeOutstandingICMP(fduse); - - /* - * If connected throw a PortUnreachableException - */ - - if (connected) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"PortUnreachableException", - "ICMP Port Unreachable"); - return; - } - - /* - * If a timeout was specified then we need to adjust it because - * we may have used up some of the timeout before the icmp port - * unreachable arrived. - */ - if (timeout != 0) { - int ret; - long newTime = JVM_CurrentTimeMillis(env, 0); - timeout -= (newTime - prevTime); - prevTime = newTime; - - if (timeout <= 0) { - ret = 0; - } else { - ret = NET_Timeout(fduse, timeout); - } - - if (ret <= 0) { - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Receive timed out"); - } else if (ret == JVM_IO_ERR) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - } else if (ret == JVM_IO_INTR) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } - return; - } - } - - /* - * An ICMP port unreachable was received but we are - * not connected so ignore it. - */ - retry = TRUE; - } - } - } while (retry); - - if (n < 0) { - errorCode = WSAGetLastError(); - /* check to see if it's because the buffer was too small */ - if (errorCode == 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.. - */ - n = packetBufferLen; - } else { - /* failure */ - packet.length = 0; - } - } - if (n == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); - } else if (n == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } else if (n < 0) { - NET_ThrowCurrent(env, "Datagram receive failed"); - } else { - int port; - 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 = packet.address; - - if (packetAddress != NULL) { - if (!NET_SockaddrEqualsInetAddress(remote_addr, packetAddress)) { - /* force a new InetAddress to be created */ - packetAddress = null; - } - } - if (packetAddress == NULL) { - int[] tmp = { 0 }; - packetAddress = NET_SockaddrToInetAddress(remote_addr, tmp); - port = tmp[0]; - /* stuff the new Inetaddress in the packet */ - packet.address = packetAddress; - } else { - /* only get the new port number */ - port = NET_GetPortFromSockaddr(remote_addr); - } - /* populate the packet */ - packet.port = port; - packet.length = n; - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: datagramSocketCreate - * Signature: ()V - */ -static void datagramSocketCreate(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - boolean ipv6_supported = ipv6_available(); - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); - return; - } else { - fd = socket (AF_INET, SOCK_DGRAM, 0); - } - if (fd == INVALID_SOCKET) { - NET_ThrowCurrent(env, "Socket creation failed"); - return; - } - fdObj.setSocket(fd); - NET_SetSockOpt(fd, SOL_SOCKET, SO_BROADCAST, true); - - if (ipv6_supported) { - /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which - * returns connection reset errors un connected UDP sockets (as well - * as connected sockets. The solution is to only enable this feature - * when the socket is connected - */ - WSAIoctl(fd,SIO_UDP_CONNRESET,false); - fd1 = socket (AF_INET6, SOCK_DGRAM, 0); - if (fd1 == INVALID_SOCKET) { - NET_ThrowCurrent(env, "Socket creation failed"); - return; - } - NET_SetSockOpt(fd1, SOL_SOCKET, SO_BROADCAST, true); - WSAIoctl(fd1,SIO_UDP_CONNRESET,false); - fd1Obj.setSocket(fd1); - } else { - /* drop the second fd */ - _this.fd1 = null; - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: datagramSocketClose - * Signature: ()V - */ -static void datagramSocketClose(TwoStacksPlainDatagramSocketImpl _this) { - /* - * REMIND: PUT A LOCK AROUND THIS CODE - */ - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - boolean ipv6_supported = ipv6_available(); - cli.System.Net.Sockets.Socket fd = null, fd1 = null; - - if (IS_NULL(fdObj) && (!ipv6_supported || IS_NULL(fd1Obj))) { - return; - } - - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - if (fd != null) { - fdObj.setSocket(null); - NET_SocketClose(fd); - } - } - - if (ipv6_supported && fd1Obj != NULL) { - fd1 = fd1Obj.getSocket(); - if (fd1 == null) { - return; - } - fd1Obj.setSocket(null); - NET_SocketClose(fd1); - } -} - -/* - * check the addresses attached to the NetworkInterface object - * and return the first one (of the requested family Ipv4 or Ipv6) - * in *iaddr - */ - -private static int getInetAddrFromIf (JNIEnv env, int family, NetworkInterface nif, InetAddress[] iaddr) -{ - InetAddress[] addrArray; - int len; - InetAddress addr; - int i; - - addrArray = getNetworkInterfaceAddresses(nif); - len = addrArray.length; - - /* - * Check that there is at least one address bound to this - * interface. - */ - if (len < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "bad argument for IP_MULTICAST_IF2: No IP addresses bound to interface"); - return -1; - } - for (i=0; i<len; i++) { - int fam; - addr = addrArray[i]; - fam = getInetAddress_family(env, addr); - if (fam == family) { - iaddr[0] = addr; - return 0; - } - } - return -1; -} - -private static int getInet4AddrFromIf (JNIEnv env, NetworkInterface nif, in_addr iaddr) -{ - InetAddress[] addr = new InetAddress[1]; - - int ret = getInetAddrFromIf (env, IPv4, nif, addr); - if (ret == -1) { - return -1; - } - - iaddr.s_addr = htonl(getInetAddress_addr(env, addr[0])); - return 0; -} - -/* Get the multicasting index from the interface */ - -private static int getIndexFromIf (JNIEnv env, NetworkInterface nif) { - return nif.getIndex(); -} - -private static InetAddress[] getNetworkInterfaceAddresses(final NetworkInterface nif) { - // [IKVM] this is IKVM specific, because I don't want to use reflection (or map.xml hacks) to access the "addrs" member of NetworkInterface - return java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<InetAddress[]>() { - public InetAddress[] run() { - java.util.ArrayList<InetAddress> list = new java.util.ArrayList<InetAddress>(); - for (java.util.Enumeration<InetAddress> e = nif.getInetAddresses(); e.hasMoreElements(); ) { - list.add(e.nextElement()); - } - return list.toArray(new InetAddress[list.size()]); - } - }); -} - -static int isAdapterIpv6Enabled(JNIEnv env, int index) { - return java.security.AccessController.doPrivileged(new java.security.PrivilegedAction<Integer>() { - public Integer run() { - try { - for (java.util.Enumeration<InetAddress> e = NetworkInterface.getByIndex(index).getInetAddresses(); e.hasMoreElements(); ) { - if (e.nextElement() instanceof Inet6Address) { - return 1; - } - } - } catch (SocketException x) { - } - return 0; - } - }).intValue(); -} - -private static NetworkInterface Java_java_net_NetworkInterface_getByIndex(JNIEnv env, int ni_class, int index) -{ - try { - return NetworkInterface.getByIndex(index); - } catch (Exception x) { - env.Throw(x); - return null; - } -} - -private static NetworkInterface Java_java_net_NetworkInterface_getByInetAddress0(JNIEnv env, int ni_class, Object address) -{ - try { - return NetworkInterface.getByInetAddress((InetAddress)address); - } catch (Exception x) { - env.Throw(x); - return null; - } -} - -/* - * Sets the multicast interface. - * - * SocketOptions.IP_MULTICAST_IF (argument is an InetAddress) :- - * IPv4: set outgoing multicast interface using - * IPPROTO_IP/IP_MULTICAST_IF - * - * IPv6: Get the interface to which the - * InetAddress is bound - * and do same as SockOptions.IF_MULTICAST_IF2 - * - * SockOptions.IF_MULTICAST_IF2 (argument is a NetworkInterface ) :- - * For each stack: - * IPv4: Obtain IP address bound to network interface - * (NetworkInterface.addres[0]) - * set outgoing multicast interface using - * IPPROTO_IP/IP_MULTICAST_IF - * - * IPv6: Obtain NetworkInterface.index - * Set outgoing multicast interface using - * IPPROTO_IPV6/IPV6_MULTICAST_IF - * - */ -private static void setMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, - int opt, Object value) -{ - boolean ipv6_supported = ipv6_available(); - - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - /* - * value is an InetAddress. - * On IPv4 system use IP_MULTICAST_IF socket option - * On IPv6 system get the NetworkInterface that this IP - * address is bound to and use the IPV6_MULTICAST_IF - * option instead of IP_MULTICAST_IF - */ - if (ipv6_supported) { - value = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, value); - if (value == NULL) { - if (env.ExceptionOccurred() == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "bad argument for IP_MULTICAST_IF" - +": address not bound to any interface"); - } - return; - } - opt = java_net_SocketOptions_IP_MULTICAST_IF2; - } else { - in_addr in = new in_addr(); - - in.s_addr = htonl(getInetAddress_addr(env, (InetAddress)value)); - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - in) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error setting socket option"); - } - return; - } - } - - if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - /* - * value is a NetworkInterface. - * On IPv6 system get the index of the interface and use the - * IPV6_MULTICAST_IF socket option - * On IPv4 system extract addr[0] and use the IP_MULTICAST_IF - * option. For IPv6 both must be done. - */ - if (ipv6_supported) { - in_addr in = new in_addr(); - int index; - - index = ((NetworkInterface)value).getIndex(); - - if ( isAdapterIpv6Enabled(env, index) != 0 ) { - if (setsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - index) < 0) { - if (WSAGetLastError() == WSAEINVAL && index > 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "IPV6_MULTICAST_IF failed (interface has IPv4 " - +"address only?)"); - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error setting socket option"); - } - return; - } - } - - /* If there are any IPv4 addresses on this interface then - * repeat the operation on the IPv4 fd */ - - if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { - return; - } - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - in) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error setting socket option"); - } - return; - } else { - in_addr in = new in_addr(); - - if (getInet4AddrFromIf (env, (NetworkInterface)value, in) < 0) { - if (env.ExceptionOccurred() != null) { - return; - } - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "no InetAddress instances of requested type"); - return; - } - - if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - in) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error setting socket option"); - } - return; - } - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: socketNativeSetOption - * Signature: (ILjava/lang/Object;)V - */ -static void socketNativeSetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt, Object value) { - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - int[] levelv4 = new int[1]; - int[] levelv6 = new int[1]; - int[] optnamev4 = new int[1]; - int[] optnamev6 = new int[1]; - Object optval; - boolean ipv6_supported = ipv6_available(); - - fd = getFD(env, _this); - - if (ipv6_supported) { - fd1 = getFD1(env, _this); - } - if (fd == null && fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); - return; - } - - if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || - (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - - setMulticastInterface(env, _this, fd, fd1, opt, value); - return; - } - - /* - * Map the Java level socket option to the platform specific - * level(s) and option name(s). - */ - if (fd1 != null) { - if (NET_MapSocketOptionV6(opt, levelv6, optnamev6) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); - return; - } - } - if (fd != null) { - if (NET_MapSocketOption(opt, levelv4, optnamev4) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); - return; - } - } - - switch (opt) { - case java_net_SocketOptions_SO_SNDBUF : - case java_net_SocketOptions_SO_RCVBUF : - case java_net_SocketOptions_IP_TOS : - optval = ((Integer)value).intValue(); - break; - - case java_net_SocketOptions_SO_REUSEADDR: - case java_net_SocketOptions_SO_BROADCAST: - case java_net_SocketOptions_IP_MULTICAST_LOOP: - { - boolean on = ((Boolean)value).booleanValue(); - optval = on; - /* - * setLoopbackMode (true) disables IP_MULTICAST_LOOP rather - * than enabling it. - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_LOOP) { - optval = !on; - } - } - break; - - default : - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket option not supported by PlainDatagramSocketImp"); - return; - } - - if (fd1 != null) { - if (NET_SetSockOpt(fd1, levelv6[0], optnamev6[0], optval) < 0) { - NET_ThrowCurrent(env, "setsockopt IPv6"); - return; - } - } - if (fd != null) { - if (NET_SetSockOpt(fd, levelv4[0], optnamev4[0], optval) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - return; - } - } -} - -/* - * - * called by getMulticastInterface to retrieve a NetworkInterface - * configured for IPv4. - * The ipv4Mode parameter, is a closet boolean, which allows for a NULL return, - * or forces the creation of a NetworkInterface object with null data. - * It relates to its calling context in getMulticastInterface. - * ipv4Mode == 1, the context is IPV4 processing only. - * ipv4Mode == 0, the context is IPV6 processing - * - *-/ -static jobject getIPv4NetworkInterface (JNIEnv *env, jobject this, int fd, jint opt, int ipv4Mode) { - static jclass inet4_class; - static jmethodID inet4_ctrID; - - static jclass ni_class; static jmethodID ni_ctrID; - static jfieldID ni_indexID; - static jfieldID ni_addrsID; - - jobjectArray addrArray; - jobject addr; - jobject ni; - - struct in_addr in; - struct in_addr *inP = ∈ - int len = sizeof(struct in_addr); - if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - (char *)inP, &len) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Error getting socket option"); - return NULL; - } - - /* - * Construct and populate an Inet4Address - *-/ - if (inet4_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/Inet4Address"); - CHECK_NULL_RETURN(c, NULL); - inet4_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); - CHECK_NULL_RETURN(inet4_ctrID, NULL); - inet4_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(inet4_class, NULL); - } - addr = (*env)->NewObject(env, inet4_class, inet4_ctrID, 0); - CHECK_NULL_RETURN(addr, NULL); - - setInetAddress_addr(env, addr, ntohl(in.s_addr)); - - /* - * For IP_MULTICAST_IF return InetAddress - *-/ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - return addr; - } - - /* - * For IP_MULTICAST_IF2 we get the NetworkInterface for - * this address and return it - *-/ - if (ni_class == NULL) { - jclass c = (*env)->FindClass(env, "java/net/NetworkInterface"); - CHECK_NULL_RETURN(c, NULL); - ni_ctrID = (*env)->GetMethodID(env, c, "<init>", "()V"); - CHECK_NULL_RETURN(ni_ctrID, NULL); - ni_indexID = (*env)->GetFieldID(env, c, "index", "I"); - CHECK_NULL_RETURN(ni_indexID, NULL); - ni_addrsID = (*env)->GetFieldID(env, c, "addrs", - "[Ljava/net/InetAddress;"); - CHECK_NULL_RETURN(ni_addrsID, NULL); - ni_class = (*env)->NewGlobalRef(env, c); - CHECK_NULL_RETURN(ni_class, NULL); - } - ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); - if (ni) { - return ni; - } - if (ipv4Mode) { - ni = (*env)->NewObject(env, ni_class, ni_ctrID, 0); - CHECK_NULL_RETURN(ni, NULL); - - (*env)->SetIntField(env, ni, ni_indexID, -1); - addrArray = (*env)->NewObjectArray(env, 1, inet4_class, NULL); - CHECK_NULL_RETURN(addrArray, NULL); - (*env)->SetObjectArrayElement(env, addrArray, 0, addr); - (*env)->SetObjectField(env, ni, ni_addrsID, addrArray); - } else { - ni = NULL; - } - return ni; -} - -/* - * Return the multicast interface: - * - * SocketOptions.IP_MULTICAST_IF - * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF - * Create InetAddress - * IP_MULTICAST_IF returns struct ip_mreqn on 2.2 - * kernel but struct in_addr on 2.4 kernel - * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF or - * obtain from impl is Linux 2.2 kernel - * If index == 0 return InetAddress representing - * anyLocalAddress. - * If index > 0 query NetworkInterface by index - * and returns addrs[0] - * - * SocketOptions.IP_MULTICAST_IF2 - * IPv4: Query IPPROTO_IP/IP_MULTICAST_IF - * Query NetworkInterface by IP address and - * return the NetworkInterface that the address - * is bound too. - * IPv6: Query IPPROTO_IPV6 / IPV6_MULTICAST_IF - * (except Linux .2 kernel) - * Query NetworkInterface by index and - * return NetworkInterface. - */ -private static Object getMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, int opt) { - boolean isIPV4 = !ipv6_available() || fd1 == null; - - /* - * IPv4 implementation - */ - if (isIPV4) { - Inet4Address addr; - - in_addr in = new in_addr(); - - if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, - in) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error getting socket option"); - return NULL; - } - - /* - * Construct and populate an Inet4Address - */ - addr = new Inet4Address(); - addr.holder().address = ntohl(in.s_addr); - - /* - * For IP_MULTICAST_IF return InetAddress - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - return addr; - } - - NetworkInterface ni; - ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr); - if (ni != null) { - return ni; - } - - /* - * The address doesn't appear to be bound at any known - * NetworkInterface. Therefore we construct a NetworkInterface - * with this address. - */ - return new NetworkInterface(null, -1, new InetAddress[] { addr }); - } - - - /* - * IPv6 implementation - */ - if ((opt == java_net_SocketOptions_IP_MULTICAST_IF) || - (opt == java_net_SocketOptions_IP_MULTICAST_IF2)) { - - int index; - - InetAddress[] addrArray; - InetAddress addr; - NetworkInterface ni; - - { - int[] tmp = { 0 }; - if (getsockopt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, - tmp) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error getting socket option"); - return NULL; - } - index = tmp[0]; - } - - /* - * If multicast to a specific interface then return the - * interface (for IF2) or the any address on that interface - * (for IF). - */ - if (index > 0) { - ni = Java_java_net_NetworkInterface_getByIndex(env, ni_class, - index); - if (ni == NULL) { - String errmsg = "IPV6_MULTICAST_IF returned index to unrecognized interface: " + index; - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); - return NULL; - } - - /* - * For IP_MULTICAST_IF2 return the NetworkInterface - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - return ni; - } - - /* - * For IP_MULTICAST_IF return addrs[0] - */ - addrArray = getNetworkInterfaceAddresses(ni); - if (addrArray.length < 1) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "IPV6_MULTICAST_IF returned interface without IP bindings"); - return NULL; - } - - addr = addrArray[0]; - return addr; - } - - /* - * Multicast to any address - return anyLocalAddress - * or a NetworkInterface with addrs[0] set to anyLocalAddress - */ - - addr = InetAddress.anyLocalAddress(); - if (opt == java_net_SocketOptions_IP_MULTICAST_IF) { - return addr; - } - - return new NetworkInterface(null, -1, new InetAddress[] { addr }); - } - return NULL; -} -/* - * Returns relevant info as a jint. - * - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: socketGetOption - * Signature: (I)Ljava/lang/Object; - */ -static Object socketGetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt) { - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - int[] level = new int[1]; - int[] optname = new int[1]; - int[] optval = new int[1]; - boolean ipv6_supported = ipv6_available(); - - fd = getFD(env, _this); - if (ipv6_supported) { - fd1 = getFD1(env, _this); - } - - if (fd == null && fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return NULL; - } - - /* - * Handle IP_MULTICAST_IF separately - */ - if (opt == java_net_SocketOptions_IP_MULTICAST_IF || - opt == java_net_SocketOptions_IP_MULTICAST_IF2) { - return getMulticastInterface(env, _this, fd, fd1, opt); - } - - /* - * Map the Java level socket option to the platform specific - * level and option name. - */ - if (NET_MapSocketOption(opt, level, optname) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); - return NULL; - } - - if (fd == null) { - if (NET_MapSocketOptionV6(opt, level, optname) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); - return NULL; - } - fd = fd1; /* must be IPv6 only */ - } - - if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { - String errmsg = "error getting socket option: " + WSAGetLastError(); - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", errmsg); - return NULL; - } - - switch (opt) { - case java_net_SocketOptions_SO_BROADCAST: - case java_net_SocketOptions_SO_REUSEADDR: - return optval[0] != 0; - - case java_net_SocketOptions_IP_MULTICAST_LOOP: - /* getLoopbackMode() returns true if IP_MULTICAST_LOOP is disabled */ - return optval[0] == 0; - - case java_net_SocketOptions_SO_SNDBUF: - case java_net_SocketOptions_SO_RCVBUF: - case java_net_SocketOptions_IP_TOS: - return optval[0]; - - default : - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket option not supported by TwoStacksPlainDatagramSocketImpl"); - return NULL; - - } -} - -/* - * Returns local address of the socket. - * - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: socketLocalAddress - * Signature: (I)Ljava/lang/Object; - */ -static Object socketLocalAddress(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, - int family) { - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - SOCKETADDRESS him; - him = new SOCKETADDRESS(); - Object iaObj; - boolean ipv6_supported = ipv6_available(); - - fd = getFD(env, _this); - if (ipv6_supported) { - fd1 = getFD1(env, _this); - } - - if (fd == null && fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return NULL; - } - - /* find out local IP address */ - - /* family==-1 when socket is not connected */ - if ((family == IPv6) || (family == -1 && fd == null)) { - fd = fd1; /* must be IPv6 only */ - } - - if (fd == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return NULL; - } - - if (getsockname(fd, him) == -1) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error getting socket name"); - return NULL; - } - iaObj = NET_SockaddrToInetAddress(him, new int[1]); - - return iaObj; -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: setTimeToLive - * Signature: (I)V - */ -static void setTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int ttl) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } else { - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - } - - /* setsockopt to be correct ttl */ - if (fd != null) { - if (NET_SetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { - NET_ThrowCurrent(env, "set IP_MULTICAST_TTL failed"); - } - } - - if (fd1 != null) { - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) <0) { - NET_ThrowCurrent(env, "set IPV6_MULTICAST_HOPS failed"); - } - } -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: setTTL - * Signature: (B)V - */ -static void setTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, byte ttl) { - setTimeToLive(env, _this, ttl & 0xFF); -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: getTimeToLive - * Signature: ()I - */ -static int getTimeToLive(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - int[] ttl = new int[1]; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return -1; - } else { - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - } - - /* getsockopt of ttl */ - if (fd != null) { - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_TTL, ttl) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); - return -1; - } - return ttl[0]; - } - if (fd1 != null) { - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ttl) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_TTL failed"); - return -1; - } - return ttl[0]; - } - return -1; -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: getTTL - * Signature: ()B - */ -static byte getTTL(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this) { - int result = getTimeToLive(env, _this); - - return (byte)result; -} - -/* join/leave the named group on the named interface, or if no interface specified - * then the interface set with setInterfac(), or the default interface otherwise */ - -private static void mcast_join_leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress iaObj, NetworkInterface niObj, boolean join) -{ - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - - SOCKETADDRESS name; - name = new SOCKETADDRESS(); - ip_mreq mname = new ip_mreq(); - ipv6_mreq mname6 = new ipv6_mreq(); - - in_addr in = new in_addr(); - int ifindex; - - int family; - boolean ipv6_supported = ipv6_available(); - int cmd ; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "address"); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, 0, name, JNI_FALSE) != 0) { - return; - } - - /* Set the multicast group address in the ip_mreq field - * eventually this check should be done by the security manager - */ - family = name.him.sa_family; - - if (family == AF_INET) { - int address = name.him4.sin_addr.s_addr; - if (!IN_MULTICAST(ntohl(address))) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in multicast"); - return; - } - mname.imr_multiaddr.s_addr = address; - if (fd == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv4 group on an IPv6 only socket"); - return; - } - if (IS_NULL(niObj)) { - if (NET_GetSockOpt(fd, IPPROTO_IP, IP_MULTICAST_IF, in) < 0) { - NET_ThrowCurrent(env, "get IP_MULTICAST_IF failed"); - return; - } - mname.imr_interface.s_addr = in.s_addr; - } else { - if (getInet4AddrFromIf (env, niObj, mname.imr_interface) != 0) { - NET_ThrowCurrent(env, "no Inet4Address associated with interface"); - return; - } - } - - cmd = join ? IP_ADD_MEMBERSHIP: IP_DROP_MEMBERSHIP; - - /* Join the multicast group */ - if (NET_SetSockOpt(fd, IPPROTO_IP, cmd, mname) < 0) { - if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); - } - } - } else /* AF_INET6 */ { - if (ipv6_supported) { - in6_addr address; - address = in6_addr.FromSockAddr(name); - if (!IN6_IS_ADDR_MULTICAST(address)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "not in6 multicast"); - return; - } - mname6.ipv6mr_multiaddr = address; - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "IPv6 not supported"); - return; - } - if (fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Can't join an IPv6 group on a IPv4 socket"); - return; - } - if (IS_NULL(niObj)) { - int[] tmp = { 0 }; - if (NET_GetSockOpt(fd1, IPPROTO_IPV6, IPV6_MULTICAST_IF, tmp) < 0) { - NET_ThrowCurrent(env, "get IPV6_MULTICAST_IF failed"); - return; - } - ifindex = tmp[0]; - } else { - ifindex = getIndexFromIf (env, niObj); - if (ifindex == -1) { - NET_ThrowCurrent(env, "get ifindex failed"); - return; - } - } - mname6.ipv6mr_interface = ifindex; - cmd = join ? IPV6_ADD_MEMBERSHIP: IPV6_DROP_MEMBERSHIP; - - /* Join the multicast group */ - if (NET_SetSockOpt(fd1, IPPROTO_IPV6, cmd, mname6) < 0) { - if (WSAGetLastError() == WSAENOBUFS) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "IP_ADD_MEMBERSHIP failed (out of hardware filters?)"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException","error setting options"); - } - } - } - - return; -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: join - * Signature: (Ljava/net/InetAddress;)V - */ -static void join(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { - mcast_join_leave(env, _this, inetaddr, netIf, true); -} - -/* - * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: leave - * Signature: (Ljava/net/InetAddress;)V - */ -static void leave(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress inetaddr, NetworkInterface netIf) { - mcast_join_leave(env, _this, inetaddr, netIf, false); -} - -} diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl.java b/openjdk/java/net/TwoStacksPlainSocketImpl.java deleted file mode 100644 index 12c1794f..00000000 --- a/openjdk/java/net/TwoStacksPlainSocketImpl.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * 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(); - } -} diff --git a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java deleted file mode 100644 index d86e84d0..00000000 --- a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java +++ /dev/null @@ -1,1080 +0,0 @@ -/* - * Copyright (c) 1997, 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.FileDescriptor; -import static ikvm.internal.JNI.*; -import static ikvm.internal.Winsock.*; -import static java.net.net_util_md.*; -import static java.net.InetAddress.IPv4; -import static java.net.InetAddress.IPv6; - -final class TwoStacksPlainSocketImpl_c -{ -static final int JVM_IO_ERR = -1; -static final int JVM_IO_INTR = -2; - -static final int java_net_SocketOptions_SO_TIMEOUT = SocketOptions.SO_TIMEOUT; -static final int java_net_SocketOptions_SO_BINDADDR = SocketOptions.SO_BINDADDR; -static final int java_net_SocketOptions_SO_SNDBUF = SocketOptions.SO_SNDBUF; -static final int java_net_SocketOptions_SO_RCVBUF = SocketOptions.SO_RCVBUF; -static final int java_net_SocketOptions_IP_TOS = SocketOptions.IP_TOS; -static final int java_net_SocketOptions_SO_REUSEADDR = SocketOptions.SO_REUSEADDR; -static final int java_net_SocketOptions_TCP_NODELAY = SocketOptions.TCP_NODELAY; -static final int java_net_SocketOptions_SO_OOBINLINE = SocketOptions.SO_OOBINLINE; -static final int java_net_SocketOptions_SO_KEEPALIVE = SocketOptions.SO_KEEPALIVE; -static final int java_net_SocketOptions_SO_LINGER = SocketOptions.SO_LINGER; - -/* -#include <windows.h> -#include <winsock2.h> -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <malloc.h> -#include <sys/types.h> - -#include "java_net_SocketOptions.h" -#include "java_net_TwoStacksPlainSocketImpl.h" -#include "java_net_SocketImpl.h" -#include "java_net_InetAddress.h" -#include "java_io_FileDescriptor.h" -#include "java_lang_Integer.h" - -#include "jvm.h" -#include "net_util.h" -#include "jni_util.h" -*/ - -/************************************************************************ - * TwoStacksPlainSocketImpl - */ - -/* -static jfieldID IO_fd_fdID; - -jfieldID psi_fdID; -jfieldID psi_fd1ID; -jfieldID psi_addressID; -jfieldID psi_portID; -jfieldID psi_localportID; -jfieldID psi_timeoutID; -jfieldID psi_trafficClassID; -jfieldID psi_serverSocketID; -jfieldID psi_lastfdID; -*/ - -/* - * the level of the TCP protocol for setsockopt and getsockopt - * we only want to look this up once, from the static initializer - * of TwoStacksPlainSocketImpl - */ -static int tcp_level = -1; - -static cli.System.Net.Sockets.Socket getFD(JNIEnv env, TwoStacksPlainSocketImpl _this) { - FileDescriptor fdObj = _this.fd; - - if (fdObj == NULL) { - return null; - } - return fdObj.getSocket(); -} - -static cli.System.Net.Sockets.Socket getFD1(JNIEnv env, TwoStacksPlainSocketImpl _this) { - FileDescriptor fdObj = _this.fd1; - - if (fdObj == NULL) { - return null; - } - return fdObj.getSocket(); -} - - -/* - * The initProto function is called whenever TwoStacksPlainSocketImpl is - * loaded, to cache fieldIds for efficiency. This is called everytime - * the Java class is loaded. - * - * Class: java_net_TwoStacksPlainSocketImpl - * Method: initProto - - * Signature: ()V - */ -/* -JNIEXPORT void JNICALL -Java_java_net_TwoStacksPlainSocketImpl_initProto(JNIEnv *env, jclass cls) { - - struct protoent *proto = getprotobyname("TCP"); - tcp_level = (proto == 0 ? IPPROTO_TCP: proto->p_proto); - - psi_fdID = (*env)->GetFieldID(env, cls , "fd", "Ljava/io/FileDescriptor;"); - CHECK_NULL(psi_fdID); - psi_fd1ID =(*env)->GetFieldID(env, cls , "fd1", "Ljava/io/FileDescriptor;"); - CHECK_NULL(psi_fd1ID); - psi_addressID = (*env)->GetFieldID(env, cls, "address", - "Ljava/net/InetAddress;"); - CHECK_NULL(psi_addressID); - psi_portID = (*env)->GetFieldID(env, cls, "port", "I"); - CHECK_NULL(psi_portID); - psi_lastfdID = (*env)->GetFieldID(env, cls, "lastfd", "I"); - CHECK_NULL(psi_portID); - psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I"); - CHECK_NULL(psi_localportID); - psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I"); - CHECK_NULL(psi_timeoutID); - psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I"); - CHECK_NULL(psi_trafficClassID); - psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket", - "Ljava/net/ServerSocket;"); - CHECK_NULL(psi_serverSocketID); - IO_fd_fdID = NET_GetFileDescriptorID(env); - CHECK_NULL(IO_fd_fdID); -} -*/ - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketCreate - * Signature: (Z)V - */ -static void socketCreate(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean stream) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "null fd object"); - return; - } - fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd == INVALID_SOCKET) { - NET_ThrowCurrent(env, "create"); - return; - } else { - /* Set socket attribute so it is not passed to any child process */ - //SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE); - fdObj.setSocket(fd); - } - if (ipv6_available()) { - - if (IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "null fd1 object"); - fdObj.setSocket(null); - NET_SocketClose(fd); - return; - } - fd1 = socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0); - if (fd1 == INVALID_SOCKET) { - NET_ThrowCurrent(env, "create"); - fdObj.setSocket(null); - NET_SocketClose(fd); - return; - } else { - fd1Obj.setSocket(fd1); - } - } else { - _this.fd1 = null; - } -} - -/* - * inetAddress is the address object passed to the socket connect - * call. - * - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketConnect - * Signature: (Ljava/net/InetAddress;I)V - */ -static void socketConnect(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress iaObj, int port, int timeout) -{ - int localport = _this.localport; - - /* family and localport are int fields of iaObj */ - int family; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - boolean ipv6_supported = ipv6_available(); - - /* fd initially points to the IPv4 socket and fd1 to the IPv6 socket - * If we want to connect to IPv6 then we swap the two sockets/objects - * This way, fd is always the connected socket, and fd1 always gets closed. - */ - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - - SOCKETADDRESS him; - him = new SOCKETADDRESS(); - - /* The result of the connection */ - int connect_res; - - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - - if (ipv6_supported && !IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "inet address argument is null."); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, port, him, JNI_FALSE) != 0) { - return; - } - - family = him.him.sa_family; - if (family == AF_INET6) { - if (!ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Protocol family not supported"); - return; - } else { - if (fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Destination unreachable"); - return; - } - /* close the v4 socket, and set fd to be the v6 socket */ - _this.fd = fd1Obj; - _this.fd1 = null; - NET_SocketClose(fd); - fd = fd1; fdObj = fd1Obj; - } - } else { - if (fd1 != null) { - fd1Obj.setSocket(null); - NET_SocketClose(fd1); - } - if (fd == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Destination unreachable"); - return; - } - } - _this.fd1 = null; - - if (timeout <= 0) { - connect_res = connect(fd, him); - if (connect_res == SOCKET_ERROR) { - connect_res = WSAGetLastError(); - } - } else { - int optval; - - /* make socket non-blocking */ - optval = 1; - ioctlsocket( fd, FIONBIO, optval ); - - /* initiate the connect */ - connect_res = connect(fd, him); - if (connect_res == SOCKET_ERROR) { - if (WSAGetLastError() != WSAEWOULDBLOCK) { - connect_res = WSAGetLastError(); - } else { - 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 timout, connection established or - * connection failed. - */ - connect_res = 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 (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "connect timed out"); - shutdown( fd, SD_BOTH ); - - /* make socket blocking again - just in case */ - optval = 0; - ioctlsocket( fd, FIONBIO, optval ); - return; - } - - /* - * We must now determine if the connection has been established - * or if it has 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. - */ - if (!FD_ISSET(fd, ex)) { - connect_res = 0; - } else { - int retry; - for (retry=0; retry<3; retry++) { - int[] tmp = { 0 }; - NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR, - tmp); - connect_res = tmp[0]; - if (connect_res != 0) { - break; - } - Sleep(0); - } - - if (connect_res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Unable to establish connection"); - return; - } - } - } - } - - /* make socket blocking again */ - optval = 0; - ioctlsocket(fd, FIONBIO, optval); - } - - if (connect_res != 0) { - if (connect_res == 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, connect_res, "connect"); - } - return; - } - - fdObj.setSocket(fd); - - /* set the remote peer address and port */ - _this.address = iaObj; - _this.port = port; - - /* - * we need to initialize the local port field if bind was called - * previously to the connect (by the client) then localport field - * will already be initialized - */ - if (localport == 0) { - /* Now that we're a connected socket, let's extract the port number - * that the system chose for us and store it in the Socket object. - */ - if (getsockname(fd, him) == -1) { - - if (WSAGetLastError() == WSAENOTSOCK) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - } else { - NET_ThrowCurrent(env, "getsockname failed"); - } - return; - } - port = ntohs (GET_PORT(him)); - _this.localport = port; - } -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketBind - * Signature: (Ljava/net/InetAddress;I)V - */ -static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, - InetAddress iaObj, int localport, - boolean exclBind) { - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - boolean ipv6_supported = ipv6_available(); - - /* family is an int field of iaObj */ - int family; - int rv; - - SOCKETADDRESS him; - him = new SOCKETADDRESS(); - - family = getInetAddress_family(env, iaObj); - - if (family == IPv6 && !ipv6_supported) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Protocol family not supported"); - return; - } - - if (IS_NULL(fdObj) || (ipv6_supported && IS_NULL(fd1Obj))) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } else { - fd = fdObj.getSocket(); - if (ipv6_supported) { - fd1 = fd1Obj.getSocket(); - } - } - if (IS_NULL(iaObj)) { - JNU_ThrowNullPointerException(env, "inet address argument"); - return; - } - - if (NET_InetAddressToSockaddr(env, iaObj, localport, - him, JNI_FALSE) != 0) { - return; - } - if (ipv6_supported) { - ipv6bind v6bind = new ipv6bind(); - v6bind.addr = him; - v6bind.ipv4_fd = fd; - v6bind.ipv6_fd = fd1; - rv = NET_BindV6(v6bind, exclBind); - if (rv != -1) { - /* check if the fds have changed */ - if (v6bind.ipv4_fd != fd) { - fd = v6bind.ipv4_fd; - if (fd == null) { - /* socket is closed. */ - _this.fd = null; - } else { - /* socket was re-created */ - fdObj.setSocket(fd); - } - } - if (v6bind.ipv6_fd != fd1) { - fd1 = v6bind.ipv6_fd; - if (fd1 == null) { - /* socket is closed. */ - _this.fd1 = null; - } else { - /* socket was re-created */ - fd1Obj.setSocket(fd1); - } - } - } - } else { - rv = NET_WinBind(fd, him, exclBind); - } - - if (rv == -1) { - NET_ThrowCurrent(env, "JVM_Bind"); - return; - } - - /* set the address */ - _this.address = iaObj; - - /* intialize the local port */ - if (localport == 0) { - /* Now that we're a bound socket, let's extract the port number - * that the system chose for us and store it in the Socket object. - */ - int port; - fd = him.him.sa_family == AF_INET? fd: fd1; - - if (getsockname(fd, him) == -1) { - NET_ThrowCurrent(env, "getsockname in plain socketBind"); - return; - } - port = ntohs (GET_PORT (him)); - - _this.localport = port; - } else { - _this.localport = localport; - } -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketListen - * Signature: (I)V - */ -static void socketListen (JNIEnv env, TwoStacksPlainSocketImpl _this, int count) -{ - /* this FileDescriptor fd field */ - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - InetAddress address; - /* fdObj's int fd field */ - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - SOCKETADDRESS addr = new SOCKETADDRESS(); - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - return; - } - - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - /* Listen on V4 if address type is v4 or if v6 and address is ::0. - * Listen on V6 if address type is v6 or if v4 and address is 0.0.0.0. - * In cases, where we listen on one space only, we close the other socket. - */ - address = _this.address; - if (IS_NULL(address)) { - JNU_ThrowNullPointerException(env, "socket address"); - return; - } - if (NET_InetAddressToSockaddr(env, address, 0, addr, - JNI_FALSE) != 0) { - return; - } - - if (addr.him.sa_family == AF_INET || IN6ADDR_ISANY(addr.him6)) { - /* listen on v4 */ - if (listen(fd, count) == -1) { - NET_ThrowCurrent(env, "listen failed"); - } - } else { - NET_SocketClose (fd); - _this.fd = null; - } - if (ipv6_available() && !IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - if (addr.him.sa_family == AF_INET6 || addr.him4.sin_addr.s_addr == INADDR_ANY) { - /* listen on v6 */ - if (listen(fd1, count) == -1) { - NET_ThrowCurrent(env, "listen failed"); - } - } else { - NET_SocketClose (fd1); - _this.fd1 = null; - } - } -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketAccept - * Signature: (Ljava/net/SocketImpl;)V - */ -static void socketAccept(JNIEnv env, TwoStacksPlainSocketImpl _this, SocketImpl socket) -{ - /* fields on this */ - int port; - int timeout = _this.timeout; - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - - /* the FileDescriptor field on socket */ - FileDescriptor socketFdObj; - - /* the InetAddress field on socket */ - InetAddress socketAddressObj; - - /* the fd int field on fdObj */ - cli.System.Net.Sockets.Socket fd=null, fd1=null; - - SOCKETADDRESS him; - him = new SOCKETADDRESS(); - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Socket closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - if (IS_NULL(socket)) { - JNU_ThrowNullPointerException(env, "socket is null"); - return; - } else { - socketFdObj = socket.fd; - socketAddressObj = socket.address; - } - if ((IS_NULL(socketAddressObj)) || (IS_NULL(socketFdObj))) { - JNU_ThrowNullPointerException(env, "socket address or fd obj"); - return; - } - if (fd != null && fd1 != null) { - fd_set rfds = new fd_set(); - timeval t = new timeval(); - cli.System.Net.Sockets.Socket lastfd, fd2; - FD_ZERO(rfds); - FD_SET(fd,rfds); - FD_SET(fd1,rfds); - if (timeout != 0) { - t.tv_sec = timeout/1000; - t.tv_usec = (timeout%1000)*1000; - } else { - t = null; - } - int res = select (rfds, null, null, t); - if (res == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Accept timed out"); - return; - } else if (res == 1) { - fd2 = FD_ISSET(fd, rfds)? fd: fd1; - } else if (res == 2) { - /* avoid starvation */ - lastfd = _this.lastfd; - if (lastfd != null) { - fd2 = lastfd==fd? fd1: fd; - } else { - fd2 = fd; - } - _this.lastfd = fd2; - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "select failed"); - return; - } - fd = fd2; - } else { - int ret; - if (fd1 != null) { - fd = fd1; - } - if (timeout != 0) { - ret = NET_Timeout(fd, timeout); - if (ret == 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketTimeoutException", - "Accept timed out"); - return; - } else if (ret == -1) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "socket closed"); - /* REMIND: SOCKET CLOSED PROBLEM */ - /* NET_ThrowCurrent(env, "Accept failed"); */ - return; - } else if (ret == -2) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - return; - } - } - } - fd = accept(fd, him); - if (fd == null) { - /* REMIND: SOCKET CLOSED PROBLEM */ - if (false) { - JNU_ThrowByName(env, JNU_JAVAIOPKG+"InterruptedIOException", - "operation interrupted"); - } else { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket closed"); - } - return; - } - socketFdObj.setSocket(fd); - - if (him.him.sa_family == AF_INET) { - - /* - * fill up the remote peer port and address in the new socket structure - */ - socketAddressObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); - socket.address = socketAddressObj; - } else { - /* AF_INET6 -> Inet6Address */ - - // [IKVM] We need to convert scope_id 0 to -1 here, because for sin6_scope_id 0 means unspecified, whereas Java uses -1 - int scopeId = him.him6.sin6_scope_id; - socketAddressObj = new Inet6Address(null, him.him6.sin6_addr, scopeId == 0 ? -1 : scopeId); - } - /* fields common to AF_INET and AF_INET6 */ - - port = ntohs (GET_PORT (him)); - socket.port = port; - port = _this.localport; - socket.localport = port; - socket.address = socketAddressObj; -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketAvailable - * Signature: ()I - */ -static int socketAvailable(JNIEnv env, TwoStacksPlainSocketImpl _this) { - - int[] available = { -1 }; - int res; - FileDescriptor fdObj = _this.fd; - cli.System.Net.Sockets.Socket fd; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); - return -1; - } else { - fd = fdObj.getSocket(); - } - res = ioctlsocket(fd, FIONREAD, available); - /* if result isn't 0, it means an error */ - if (res != 0) { - NET_ThrowNew(env, res, "socket available"); - } - return available[0]; -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketClose - * Signature: ()V - */ -static void socketClose0(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean useDeferredClose) { - - FileDescriptor fdObj = _this.fd; - FileDescriptor fd1Obj = _this.fd1; - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket fd1 = null; - - if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket already closed"); - return; - } - if (!IS_NULL(fdObj)) { - fd = fdObj.getSocket(); - } - if (!IS_NULL(fd1Obj)) { - fd1 = fd1Obj.getSocket(); - } - if (fd != null) { - fdObj.setSocket(null); - NET_SocketClose(fd); - } - if (fd1 != null) { - fd1Obj.setSocket(null); - NET_SocketClose(fd1); - } -} - -/* - * Socket options for plainsocketImpl - * - * - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketNativeSetOption - * Signature: (IZLjava/lang/Object;)V - */ -static void socketNativeSetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int cmd, boolean on, Object value) { - cli.System.Net.Sockets.Socket fd, fd1; - int[] level = new int[1]; - int[] optname = new int[1]; - Object optval; - - /* - * Get SOCKET and check that it hasn't been closed - */ - fd = getFD(env, _this); - fd1 = getFD1(env, _this); - if (fd == null && fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); - return; - } - - /* - * SO_TIMEOUT is the socket option used to specify the timeout - * for ServerSocket.accept and Socket.getInputStream().read. - * It does not typically map to a native level socket option. - * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO - * socket option to specify a receive timeout on the socket. This - * receive timeout is applicable to Socket only and the socket - * option should not be set on ServerSocket. - */ - if (cmd == java_net_SocketOptions_SO_TIMEOUT) { - - /* - * Don't enable the socket option on ServerSocket as it's - * meaningless (we don't receive on a ServerSocket). - */ - Object ssObj = _this.serverSocket; - if (ssObj != NULL) { - return; - } - - /* - * SO_RCVTIMEO is only supported on Microsoft's implementation - * of Windows Sockets so if WSAENOPROTOOPT returned then - * reset flag and timeout will be implemented using - * select() -- see SocketInputStream.socketRead. - */ - if (isRcvTimeoutSupported) { - int timeout = ((Integer)value).intValue(); - - /* - * Disable SO_RCVTIMEO if timeout is <= 5 second. - */ - if (timeout <= 5000) { - timeout = 0; - } - - if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { - if (WSAGetLastError() == WSAENOPROTOOPT) { - isRcvTimeoutSupported = JNI_FALSE; - } else { - NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); - } - } - if (fd1 != null) { - if (setsockopt(fd1, SOL_SOCKET, SO_RCVTIMEO, timeout) < 0) { - NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); - } - } - } - return; - } - - /* - * Map the Java level socket option to the platform specific - * level - */ - if (NET_MapSocketOption(cmd, level, optname) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Invalid option"); - return; - } - - switch (cmd) { - - case java_net_SocketOptions_TCP_NODELAY : - case java_net_SocketOptions_SO_OOBINLINE : - case java_net_SocketOptions_SO_KEEPALIVE : - case java_net_SocketOptions_SO_REUSEADDR : - optval = on; - break; - - case java_net_SocketOptions_SO_SNDBUF : - case java_net_SocketOptions_SO_RCVBUF : - case java_net_SocketOptions_IP_TOS : - optval = ((Integer)value).intValue(); - break; - - case java_net_SocketOptions_SO_LINGER : - { - linger ling = new linger(); - if (on) { - ling.l_onoff = 1; - ling.l_linger = ((Integer)value).intValue(); - } else { - ling.l_onoff = 0; - ling.l_linger = 0; - } - optval = ling; - } - break; - - default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Option not supported by TwoStacksPlainSocketImpl"); - return; - } - - if (fd != null) { - if (NET_SetSockOpt(fd, level[0], optname[0], optval) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - } - } - - if (fd1 != null) { - if (NET_SetSockOpt(fd1, level[0], optname[0], optval) < 0) { - NET_ThrowCurrent(env, "setsockopt"); - } - } -} - - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketGetOption - * Signature: (I)I - */ -static int socketGetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int opt, Object iaContainerObj) { - - cli.System.Net.Sockets.Socket fd, fd1; - int[] level = new int[1]; - int[] optname = new int[1]; - Object optval; - - /* - * Get SOCKET and check it hasn't been closed - */ - fd = getFD(env, _this); - fd1 = getFD1(env, _this); - - if (fd == null && fd1 == null) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Socket closed"); - return -1; - } - if (fd == null) { - fd = fd1; - } - - /* For IPv6, we assume both sockets have the same setting always */ - - /* - * SO_BINDADDR isn't a socket option - */ - if (opt == java_net_SocketOptions_SO_BINDADDR) { - SOCKETADDRESS him; - him = new SOCKETADDRESS(); - int[] port = { 0 }; - InetAddress iaObj; - - if (fd == null) { - /* must be an IPV6 only socket. Case where both sockets are != -1 - * is handled in java - */ - fd = getFD1 (env, _this); - } - - if (getsockname(fd, him) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG+"SocketException", - "Error getting socket name"); - return -1; - } - iaObj = NET_SockaddrToInetAddress(him, port); - ((InetAddressContainer)iaContainerObj).addr = iaObj; - return 0; /* notice change from before */ - } - - /* - * Map the Java level socket option to the platform specific - * level and option name. - */ - if (NET_MapSocketOption(opt, level, optname) != 0) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Invalid option"); - return -1; - } - - /* - * Args are int except for SO_LINGER - */ - if (opt == java_net_SocketOptions_SO_LINGER) { - optval = new linger(); - } else { - optval = new int[1]; - } - - if (NET_GetSockOpt(fd, level[0], optname[0], optval) < 0) { - NET_ThrowCurrent(env, "getsockopt"); - return -1; - } - - switch (opt) { - case java_net_SocketOptions_SO_LINGER: - return (((linger)optval).l_onoff != 0 ? ((linger)optval).l_linger: -1); - - case java_net_SocketOptions_SO_SNDBUF: - case java_net_SocketOptions_SO_RCVBUF: - case java_net_SocketOptions_IP_TOS: - return ((int[])optval)[0]; - - case java_net_SocketOptions_TCP_NODELAY : - case java_net_SocketOptions_SO_OOBINLINE : - case java_net_SocketOptions_SO_KEEPALIVE : - case java_net_SocketOptions_SO_REUSEADDR : - return (((int[])optval)[0] == 0) ? -1 : 1; - - default: /* shouldn't get here */ - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "Option not supported by TwoStacksPlainSocketImpl"); - return -1; - } -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketShutdown - * Signature: (I)V - */ -static void socketShutdown(JNIEnv env, TwoStacksPlainSocketImpl _this, int howto) -{ - - FileDescriptor fdObj = _this.fd; - cli.System.Net.Sockets.Socket fd; - - /* - * WARNING: THIS NEEDS LOCKING. ALSO: SHOULD WE CHECK for fd being - * -1 already? - */ - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", - "socket already closed"); - return; - } else { - fd = fdObj.getSocket(); - } - shutdown(fd, howto); -} - -/* - * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketSendUrgentData - * Signature: (B)V - */ -static void socketSendUrgentData(JNIEnv env, TwoStacksPlainSocketImpl _this, int data) { - /* The fd field */ - FileDescriptor fdObj = _this.fd; - int n; - cli.System.Net.Sockets.Socket fd; - - if (IS_NULL(fdObj)) { - JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); - return; - } else { - fd = fdObj.getSocket(); - /* Bug 4086704 - If the Socket associated with this file descriptor - * was closed (sysCloseFD), the the file descriptor is set to -1. - */ - if (fd == null) { - JNU_ThrowByName(env, "java/net/SocketException", "Socket closed"); - return; - } - - } - n = send(fd, new byte[] { (byte)data }, 1, MSG_OOB); - if (n == JVM_IO_ERR) { - NET_ThrowCurrent(env, "send"); - return; - } - if (n == JVM_IO_INTR) { - JNU_ThrowByName(env, "java/io/InterruptedIOException", null); - return; - } -} -} diff --git a/openjdk/java/net/net_util_md.java b/openjdk/java/net/net_util_md.java deleted file mode 100644 index 724ba4cc..00000000 --- a/openjdk/java/net/net_util_md.java +++ /dev/null @@ -1,884 +0,0 @@ -/* - * Copyright (c) 1997, 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.FileDescriptor; -import cli.System.Net.IPAddress; -import cli.System.Net.IPEndPoint; -import static ikvm.internal.JNI.*; -import static ikvm.internal.Winsock.*; - -final class net_util_md -{ - private net_util_md() { } - - static final int INADDR_ANY = 0; - - static final int IPTOS_TOS_MASK = 0x1e; - static final int IPTOS_PREC_MASK = 0xe0; - - static boolean isRcvTimeoutSupported = true; - - /* - * Table of Windows Sockets errors, the specific exception we - * throw for the error, and the error text. - * - * Note that this table excludes OS dependent errors. - * - * Latest list of Windows Sockets errors can be found at :- - * http://msdn.microsoft.com/library/psdk/winsock/errors_3wc2.htm - */ - private static class WinsockError - { - final int errCode; - final int exc; - final String errString; - - WinsockError(int errCode, int exc, String errString) - { - this.errCode = errCode; - this.exc = exc; - this.errString = errString; - } - } - - private static final int Exception_BindException = 1; - private static final int Exception_ConnectException = 2; - private static final int Exception_NoRouteToHostException = 3; - - private static final WinsockError[] winsock_errors = { - new WinsockError(WSAEACCES, 0, "Permission denied"), - new WinsockError(WSAEADDRINUSE, Exception_BindException, "Address already in use"), - new WinsockError(WSAEADDRNOTAVAIL, Exception_BindException, "Cannot assign requested address"), - new WinsockError(WSAEAFNOSUPPORT, 0, "Address family not supported by protocol family"), - new WinsockError(WSAEALREADY, 0, "Operation already in progress"), - new WinsockError(WSAECONNABORTED, 0, "Software caused connection abort"), - new WinsockError(WSAECONNREFUSED, Exception_ConnectException, "Connection refused"), - new WinsockError(WSAECONNRESET, 0, "Connection reset by peer"), - new WinsockError(WSAEDESTADDRREQ, 0, "Destination address required"), - new WinsockError(WSAEFAULT, 0, "Bad address"), - new WinsockError(WSAEHOSTDOWN, 0, "Host is down"), - new WinsockError(WSAEHOSTUNREACH, Exception_NoRouteToHostException, "No route to host"), - new WinsockError(WSAEINPROGRESS, 0, "Operation now in progress"), - new WinsockError(WSAEINTR, 0, "Interrupted function call"), - new WinsockError(WSAEINVAL, 0, "Invalid argument"), - new WinsockError(WSAEISCONN, 0, "Socket is already connected"), - new WinsockError(WSAEMFILE, 0, "Too many open files"), - new WinsockError(WSAEMSGSIZE, 0, "The message is larger than the maximum supported by the underlying transport"), - new WinsockError(WSAENETDOWN, 0, "Network is down"), - new WinsockError(WSAENETRESET, 0, "Network dropped connection on reset"), - new WinsockError(WSAENETUNREACH, 0, "Network is unreachable"), - new WinsockError(WSAENOBUFS, 0, "No buffer space available (maximum connections reached?)"), - new WinsockError(WSAENOPROTOOPT, 0, "Bad protocol option"), - new WinsockError(WSAENOTCONN, 0, "Socket is not connected"), - new WinsockError(WSAENOTSOCK, 0, "Socket operation on nonsocket"), - new WinsockError(WSAEOPNOTSUPP, 0, "Operation not supported"), - new WinsockError(WSAEPFNOSUPPORT, 0, "Protocol family not supported"), - new WinsockError(WSAEPROCLIM, 0, "Too many processes"), - new WinsockError(WSAEPROTONOSUPPORT, 0, "Protocol not supported"), - new WinsockError(WSAEPROTOTYPE, 0, "Protocol wrong type for socket"), - new WinsockError(WSAESHUTDOWN, 0, "Cannot send after socket shutdown"), - new WinsockError(WSAESOCKTNOSUPPORT, 0, "Socket type not supported"), - new WinsockError(WSAETIMEDOUT, Exception_ConnectException, "Connection timed out"), - new WinsockError(WSATYPE_NOT_FOUND, 0, "Class type not found"), - new WinsockError(WSAEWOULDBLOCK, 0, "Resource temporarily unavailable"), - new WinsockError(WSAHOST_NOT_FOUND, 0, "Host not found"), - new WinsockError(WSA_NOT_ENOUGH_MEMORY, 0, "Insufficient memory available"), - new WinsockError(WSANOTINITIALISED, 0, "Successful WSAStartup not yet performed"), - new WinsockError(WSANO_DATA, 0, "Valid name, no data record of requested type"), - new WinsockError(WSANO_RECOVERY, 0, "This is a nonrecoverable error"), - new WinsockError(WSASYSNOTREADY, 0, "Network subsystem is unavailable"), - new WinsockError(WSATRY_AGAIN, 0, "Nonauthoritative host not found"), - new WinsockError(WSAVERNOTSUPPORTED, 0, "Winsock.dll version out of range"), - new WinsockError(WSAEDISCON, 0, "Graceful shutdown in progress"), - new WinsockError(WSA_OPERATION_ABORTED, 0, "Overlapped operation aborted") - }; - - /* - * Since winsock doesn't have the equivalent of strerror(errno) - * use table to lookup error text for the error. - */ - static SocketException NET_ThrowNew(int errorNum, String msg) - { - int i; - int table_size = winsock_errors.length; - int excP = 0; - String fullMsg; - - if (msg == null) { - msg = "no further information"; - } - - /* - * Check table for known winsock errors - */ - i=0; - while (i < table_size) { - if (errorNum == winsock_errors[i].errCode) { - break; - } - i++; - } - - /* - * If found get pick the specific exception and error - * message corresponding to this error. - */ - if (i < table_size) { - excP = winsock_errors[i].exc; - fullMsg = winsock_errors[i].errString + ": " + msg; - } else { - fullMsg = "Unrecognized Windows Sockets error: " + errorNum + ": " + msg; - } - - /* - * Throw SocketException if no specific exception for this - * error. - */ - switch (excP) { - case Exception_BindException: - return new BindException(fullMsg); - case Exception_ConnectException: - return new ConnectException(fullMsg); - case Exception_NoRouteToHostException: - return new NoRouteToHostException(fullMsg); - default: - return new SocketException(fullMsg); - } - } - - static void NET_ThrowNew(JNIEnv env, int errorNum, String msg) - { - env.Throw(NET_ThrowNew(errorNum, msg)); - } - - static SocketException NET_ThrowCurrent(String msg) - { - return NET_ThrowNew(WSAGetLastError(), msg); - } - - static void NET_ThrowCurrent(JNIEnv env, String msg) - { - env.Throw(NET_ThrowCurrent(msg)); - } - - /* - * Return the default TOS value - */ - static int NET_GetDefaultTOS() { - // we always use the "default" default... - return 0; - } - - /* - * Map the Java level socket option to the platform specific - * level and option name. - */ - - private static final class sockopts { - int cmd; - int level; - int optname; - - sockopts(int cmd, int level, int optname) { - this.cmd = cmd; - this.level = level; - this.optname = optname; - } - } - - private static final sockopts opts[] = { - new sockopts(SocketOptions.TCP_NODELAY, IPPROTO_TCP, TCP_NODELAY ), - new sockopts(SocketOptions.SO_OOBINLINE, SOL_SOCKET, SO_OOBINLINE ), - new sockopts(SocketOptions.SO_LINGER, SOL_SOCKET, SO_LINGER ), - new sockopts(SocketOptions.SO_SNDBUF, SOL_SOCKET, SO_SNDBUF ), - new sockopts(SocketOptions.SO_RCVBUF, SOL_SOCKET, SO_RCVBUF ), - new sockopts(SocketOptions.SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE ), - new sockopts(SocketOptions.SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR ), - new sockopts(SocketOptions.SO_BROADCAST, SOL_SOCKET, SO_BROADCAST ), - new sockopts(SocketOptions.IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF ), - new sockopts(SocketOptions.IP_MULTICAST_LOOP, IPPROTO_IP, IP_MULTICAST_LOOP ), - new sockopts(SocketOptions.IP_TOS, IPPROTO_IP, IP_TOS ), - - }; - - /* call NET_MapSocketOptionV6 for the IPv6 fd only - * and NET_MapSocketOption for the IPv4 fd - */ - static int NET_MapSocketOptionV6(int cmd, int[] level, int[] optname) { - - switch (cmd) { - case SocketOptions.IP_MULTICAST_IF: - case SocketOptions.IP_MULTICAST_IF2: - level[0] = IPPROTO_IPV6; - optname[0] = IPV6_MULTICAST_IF; - return 0; - - case SocketOptions.IP_MULTICAST_LOOP: - level[0] = IPPROTO_IPV6; - optname[0] = IPV6_MULTICAST_LOOP; - return 0; - } - return NET_MapSocketOption (cmd, level, optname); - } - - static int NET_MapSocketOption(int cmd, int[] level, int[] optname) { - /* - * Map the Java level option to the native level - */ - for (int i=0; i<opts.length; i++) { - if (cmd == opts[i].cmd) { - level[0] = opts[i].level; - optname[0] = opts[i].optname; - return 0; - } - } - - /* not found */ - return -1; - } - - static int NET_SetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval) - { - int rv; - - if (level == IPPROTO_IP && optname == IP_TOS) { - int tos = (Integer)optval; - tos &= (IPTOS_TOS_MASK | IPTOS_PREC_MASK); - optval = tos; - } - - if (optname == SO_REUSEADDR) { - /* - * Do not set SO_REUSEADDE if SO_EXCLUSIVEADDUSE is already set - */ - int[] parg = new int[1]; - rv = NET_GetSockOpt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, parg); - if (rv == 0 && parg[0] == 1) { - return rv; - } - } - - rv = setsockopt(s, level, optname, optval); - - if (rv == SOCKET_ERROR) { - /* - * IP_TOS & IP_MULTICAST_LOOP can't be set on some versions - * of Windows. - */ - if ((WSAGetLastError() == WSAENOPROTOOPT) && - (level == IPPROTO_IP) && - (optname == IP_TOS || optname == IP_MULTICAST_LOOP)) { - rv = 0; - } - - /* - * IP_TOS can't be set on unbound UDP sockets. - */ - if ((WSAGetLastError() == WSAEINVAL) && - (level == IPPROTO_IP) && - (optname == IP_TOS)) { - rv = 0; - } - } - - return rv; - } - - /* - * Wrapper for setsockopt dealing with Windows specific issues :- - * - * IP_TOS is not supported on some versions of Windows so - * instead return the default value for the OS. - */ - static int NET_GetSockOpt(cli.System.Net.Sockets.Socket s, int level, int optname, Object optval) - { - int rv; - - rv = getsockopt(s, level, optname, optval); - - - /* - * IPPROTO_IP/IP_TOS is not supported on some Windows - * editions so return the default type-of-service - * value. - */ - if (rv == SOCKET_ERROR) { - - if (WSAGetLastError() == WSAENOPROTOOPT && - level == IPPROTO_IP && optname == IP_TOS) { - - ((int[])optval)[0] = NET_GetDefaultTOS(); - - rv = 0; - } - } - - return rv; - } - - /* - * Sets SO_ECLUSIVEADDRUSE if SO_REUSEADDR is not already set. - */ - static void setExclusiveBind(cli.System.Net.Sockets.Socket fd) { - int[] parg = new int[1]; - int rv = 0; - rv = NET_GetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, parg); - if (rv == 0 && parg[0] == 0) { - rv = NET_SetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, 1); - } - } - - /* - * Wrapper for bind winsock call - transparent converts an - * error related to binding to a port that has exclusive access - * into an error indicating the port is in use (facilitates - * better error reporting). - */ - static int NET_Bind(cli.System.Net.Sockets.Socket s, SOCKETADDRESS him) - { - int rv; - rv = bind(s, him); - - if (rv == SOCKET_ERROR) { - /* - * If bind fails with WSAEACCES it means that a privileged - * process has done an exclusive bind (NT SP4/2000/XP only). - */ - if (WSAGetLastError() == WSAEACCES) { - WSASetLastError(WSAEADDRINUSE); - } - } - - return rv; - } - - /* - * Wrapper for NET_Bind call. Sets SO_EXCLUSIVEADDRUSE - * if required, and then calls NET_BIND - */ - static int NET_WinBind(cli.System.Net.Sockets.Socket s, SOCKETADDRESS him, boolean exclBind) - { - if (exclBind == JNI_TRUE) - setExclusiveBind(s); - return NET_Bind(s, him); - } - - static int NET_SocketClose(cli.System.Net.Sockets.Socket fd) { - linger l = new linger(); - int ret; - if (getsockopt(fd, SOL_SOCKET, SO_LINGER, l) == 0) { - if (l.l_onoff == 0) { - WSASendDisconnect(fd); - } - } - ret = closesocket (fd); - return ret; - } - - static int NET_Timeout(cli.System.Net.Sockets.Socket fd, long timeout) { - int ret; - fd_set tbl = new fd_set(); - timeval t = new timeval(); - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - FD_ZERO(tbl); - FD_SET(fd, tbl); - ret = select (tbl, null, null, t); - return ret; - } - - /* - * differs from NET_Timeout() as follows: - * - * If timeout = -1, it blocks forever. - * - * returns 1 or 2 depending if only one or both sockets - * fire at same time. - * - * *fdret is (one of) the active fds. If both sockets - * fire at same time, *fdret = fd always. - */ - static int NET_Timeout2(cli.System.Net.Sockets.Socket fd, cli.System.Net.Sockets.Socket fd1, long timeout, cli.System.Net.Sockets.Socket[] fdret) { - int ret; - fd_set tbl = new fd_set(); - timeval t = new timeval(); - if (timeout == -1) { - t = null; - } else { - t.tv_sec = timeout / 1000; - t.tv_usec = (timeout % 1000) * 1000; - } - FD_ZERO(tbl); - FD_SET(fd, tbl); - FD_SET(fd1, tbl); - ret = select (tbl, null, null, t); - switch (ret) { - case 0: - return 0; /* timeout */ - case 1: - if (FD_ISSET (fd, tbl)) { - fdret[0]= fd; - } else { - fdret[0]= fd1; - } - return 1; - case 2: - fdret[0]= fd; - return 2; - } - return -1; - } - - /* - * if ipv6 is available, call NET_BindV6 to bind to the required address/port. - * Because the same port number may need to be reserved in both v4 and v6 space, - * this may require socket(s) to be re-opened. Therefore, all of this information - * is passed in and returned through the ipv6bind structure. - * - * If the request is to bind to a specific address, then this (by definition) means - * only bind in either v4 or v6, and this is just the same as normal. ie. a single - * call to bind() will suffice. The other socket is closed in this case. - * - * The more complicated case is when the requested address is ::0 or 0.0.0.0. - * - * Two further cases: - * 2. If the reqeusted port is 0 (ie. any port) then we try to bind in v4 space - * first with a wild-card port argument. We then try to bind in v6 space - * using the returned port number. If this fails, we repeat the process - * until a free port common to both spaces becomes available. - * - * 3. If the requested port is a specific port, then we just try to get that - * port in both spaces, and if it is not free in both, then the bind fails. - * - * On failure, sockets are closed and an error returned with CLOSE_SOCKETS_AND_RETURN - */ - - static class ipv6bind { - SOCKETADDRESS addr; - cli.System.Net.Sockets.Socket ipv4_fd; - cli.System.Net.Sockets.Socket ipv6_fd; - } - - private static int CLOSE_SOCKETS_AND_RETURN( - cli.System.Net.Sockets.Socket fd, - cli.System.Net.Sockets.Socket ofd, - cli.System.Net.Sockets.Socket close_fd, - cli.System.Net.Sockets.Socket close_ofd, - ipv6bind b) { - if (fd != null) { - closesocket (fd); - } - if (ofd != null) { - closesocket (ofd); - } - if (close_fd != null) { - closesocket (close_fd); - } - if (close_ofd != null) { - closesocket (close_ofd); - } - b.ipv4_fd = b.ipv6_fd = null; - return SOCKET_ERROR; - } - - static int NET_BindV6(ipv6bind b, boolean exclBind) { - cli.System.Net.Sockets.Socket fd = null; - cli.System.Net.Sockets.Socket ofd = null; - int rv; - /* need to defer close until new sockets created */ - cli.System.Net.Sockets.Socket close_fd = null; - cli.System.Net.Sockets.Socket close_ofd = null; - - SOCKETADDRESS oaddr = new SOCKETADDRESS(); - int family = b.addr.him.sa_family; - int ofamily; - int port; - int bound_port; - - if (family == AF_INET && (b.addr.him4.sin_addr.s_addr != INADDR_ANY)) { - /* bind to v4 only */ - int ret; - ret = NET_WinBind (b.ipv4_fd, b.addr, exclBind); - if (ret == SOCKET_ERROR) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - closesocket (b.ipv6_fd); - b.ipv6_fd = null; - return 0; - } - if (family == AF_INET6 && (!IN6ADDR_ISANY(b.addr))) { - /* bind to v6 only */ - int ret; - ret = NET_WinBind (b.ipv6_fd, b.addr, exclBind); - if (ret == SOCKET_ERROR) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - closesocket (b.ipv4_fd); - b.ipv4_fd = null; - return 0; - } - - /* We need to bind on both stacks, with the same port number */ - - if (family == AF_INET) { - ofamily = AF_INET6; - fd = b.ipv4_fd; - ofd = b.ipv6_fd; - port = GET_PORT (b.addr); - oaddr.set(new IPEndPoint(IPAddress.IPv6Any, htons(port))); - } else { - ofamily = AF_INET; - ofd = b.ipv4_fd; - fd = b.ipv6_fd; - port = GET_PORT (b.addr); - oaddr.set(new IPEndPoint(IPAddress.Any, htons(port))); - } - - rv = NET_WinBind (fd, b.addr, exclBind); - if (rv == SOCKET_ERROR) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - - /* get the port and set it in the other address */ - if (getsockname(fd, b.addr) == -1) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - bound_port = b.addr.sin_port; - oaddr.sin_port = bound_port; - if ((rv=NET_Bind (ofd, oaddr)) == SOCKET_ERROR) { - - /* no retries unless, the request was for any free port */ - - if (port != 0) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - - int sotype = fd.get_SocketType().Value; - - /* 50 is an arbitrary limit, just to ensure that this - * cannot be an endless loop. Would expect socket creation to - * succeed sooner. - */ - for (int retries = 0; retries < 50 /*SOCK_RETRIES*/; retries ++) { - close_fd = fd; - fd = null; - close_ofd = ofd; - ofd = null; - b.ipv4_fd = null; - b.ipv6_fd = null; - - /* create two new sockets */ - fd = socket (family, sotype, 0); - if (fd == INVALID_SOCKET) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - ofd = socket (ofamily, sotype, 0); - if (ofd == INVALID_SOCKET) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - - /* bind random port on first socket */ - oaddr.sin_port = 0; - rv = NET_WinBind (ofd, oaddr, - exclBind); - if (rv == SOCKET_ERROR) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - /* close the original pair of sockets before continuing */ - closesocket (close_fd); - closesocket (close_ofd); - close_fd = close_ofd = null; - - /* bind new port on second socket */ - if (getsockname(ofd, oaddr) == -1) { - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - bound_port = oaddr.sin_port; - b.addr.sin_port = bound_port; - rv = NET_WinBind (fd, b.addr, - exclBind); - - if (rv != SOCKET_ERROR) { - if (family == AF_INET) { - b.ipv4_fd = fd; - b.ipv6_fd = ofd; - } else { - b.ipv4_fd = ofd; - b.ipv6_fd = fd; - } - return 0; - } - } - return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); - } - return 0; - } - - /* If address types is IPv6, then IPv6 must be available. Otherwise - * no address can be generated. In the case of an IPv4 Inetaddress this - * method will return an IPv4 mapped address where IPv6 is available and - * v4MappedAddress is TRUE. Otherwise it will return a sockaddr_in - * structure for an IPv4 InetAddress. - */ - static int NET_InetAddressToSockaddr(JNIEnv env, InetAddress iaObj, int port, SOCKETADDRESS him, boolean v4MappedAddress) { - if (iaObj.family == InetAddress.IPv4) { - him.set(new IPEndPoint(new IPAddress(htonl(iaObj.address) & 0xFFFFFFFFL), port)); - return 0; - } else { - Inet6Address v6addr = (Inet6Address)iaObj; - int scope = v6addr.getScopeId(); - if (scope == 0) { - him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress), port)); - return 0; - } else { - him.set(new IPEndPoint(new IPAddress(v6addr.ipaddress, scope & 0xFFFFFFFFL), port)); - return 0; - } - } - } - - static int NET_GetPortFromSockaddr(SOCKETADDRESS him) { - return ntohs(GET_PORT(him)); - } - - static boolean NET_IsIPv4Mapped(byte[] caddr) { - int i; - for (i = 0; i < 10; i++) { - if (caddr[i] != 0x00) { - return false; - } - } - - if (((caddr[10] & 0xff) == 0xff) && ((caddr[11] & 0xff) == 0xff)) { - return true; - } - return false; - } - - static int NET_IPv4MappedToIPv4(byte[] caddr) { - return ((caddr[12] & 0xff) << 24) | ((caddr[13] & 0xff) << 16) | ((caddr[14] & 0xff) << 8) - | (caddr[15] & 0xff); - } - - static boolean NET_IsEqual(byte[] caddr1, byte[] caddr2) { - int i; - for (i = 0; i < 16; i++) { - if (caddr1[i] != caddr2[i]) { - return false; - } - } - return true; - } - - static int getScopeID (SOCKETADDRESS him) { - return him.him6.sin6_scope_id; - } - - static boolean cmpScopeID (int scope, SOCKETADDRESS him) { - return him.him6.sin6_scope_id == scope; - } - - /* these methods are not from net_util_md.c */ - - static boolean ipv6_available() { - return InetAddressImplFactory.isIPv6Supported(); - } - - static boolean IS_NULL(Object obj) { - return obj == null; - } - - static boolean IN6ADDR_ISANY(SOCKETADDRESS him) { - if (him.sa_family != AF_INET6) { - return false; - } - byte[] addr = him.him6.sin6_addr; - byte b = 0; - for (int i = 0; i < addr.length; i++) { - b |= addr[i]; - } - return b == 0; - } - - static boolean NET_SockaddrEqualsInetAddress(SOCKETADDRESS him, InetAddress iaObj) { - int family = iaObj.family == InetAddress.IPv4 ? AF_INET : AF_INET6; - - if (him.sa_family == AF_INET6) { - byte[] caddrNew = him.him6.sin6_addr; - if (NET_IsIPv4Mapped(caddrNew)) { - int addrNew; - int addrCur; - if (family == AF_INET6) { - return false; - } - addrNew = NET_IPv4MappedToIPv4(caddrNew); - addrCur = iaObj.address; - if (addrNew == addrCur) { - return true; - } else { - return false; - } - } else { - byte[] caddrCur; - int scope; - - if (family == AF_INET) { - return false; - } - scope = ((Inet6Address)iaObj).getScopeId(); - caddrCur = ((Inet6Address)iaObj).ipaddress; - if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) { - return true; - } else { - return false; - } - } - } else { - int addrNew, addrCur; - if (family != AF_INET) { - return false; - } - addrNew = ntohl(him.him4.sin_addr.s_addr); - addrCur = iaObj.address; - if (addrNew == addrCur) { - return true; - } else { - return false; - } - } - } - - static InetAddress NET_SockaddrToInetAddress(JNIEnv env, SOCKETADDRESS him, int[] port) { - return NET_SockaddrToInetAddress(him, port); - } - - static InetAddress NET_SockaddrToInetAddress(SOCKETADDRESS him, int[] port) { - InetAddress iaObj; - if (him.sa_family == AF_INET6) { - byte[] caddr = him.him6.sin6_addr; - if (NET_IsIPv4Mapped(caddr)) { - iaObj = new Inet4Address(null, NET_IPv4MappedToIPv4(caddr)); - } else { - int scope = getScopeID(him); - iaObj = new Inet6Address(null, caddr, scope > 0 ? scope : -1); - } - port[0] = ntohs(him.him6.sin_port); - } else { - iaObj = new Inet4Address(null, ntohl(him.him4.sin_addr.s_addr)); - port[0] = ntohs(him.him4.sin_port); - } - return iaObj; - } - - static void NET_ThrowByNameWithLastError(JNIEnv env, String exceptionClass, String message) { - JNU_ThrowByName(env, exceptionClass, "errno: " + WSAGetLastError() + ", error: " + message + "\n"); - } - - static boolean IN_MULTICAST(int ipv4address) { - return ((ipv4address >> 24) & 0xf0) == 0xe0; - } - - static boolean IN6_IS_ADDR_MULTICAST(in6_addr address) { - return (address.s6_bytes()[0] & 0xff) == 0xff; - } - - static final class SOCKETADDRESS implements IIPEndPointWrapper { - final SOCKETADDRESS him = this; - final SOCKETADDRESS him4 = this; - final SOCKETADDRESS him6 = this; - final SOCKETADDRESS sin_addr = this; - int sa_family; - int sin_port; - int s_addr; - byte[] sin6_addr; - int sin6_scope_id; - - public void set(IPEndPoint ep) { - if (ep == null) { - sa_family = 0; - sin_port = 0; - s_addr = 0; - sin6_addr = null; - sin6_scope_id = 0; - } else { - sa_family = ep.get_AddressFamily().Value; - sin_port = htons(ep.get_Port()); - if (sa_family == AF_INET) { - s_addr = (int)ep.get_Address().get_Address(); - sin6_addr = null; - sin6_scope_id = 0; - } else { - s_addr = 0; - IPAddress addr = ep.get_Address(); - sin6_addr = addr.GetAddressBytes(); - sin6_scope_id = (int)addr.get_ScopeId(); - } - } - } - - public IPEndPoint get() { - if (sa_family == AF_INET) { - return new IPEndPoint(new IPAddress(s_addr & 0xFFFFFFFFL), ntohs(sin_port)); - } else if (sa_family == AF_INET6) { - IPAddress addr; - if (sin6_addr == null) { - addr = IPAddress.IPv6Any; - } else { - addr = new IPAddress(sin6_addr, sin6_scope_id & 0xFFFFFFFFL); - } - return new IPEndPoint(addr, ntohs(sin_port)); - } else { - return null; - } - } - } - - static int GET_PORT(SOCKETADDRESS sockaddr) { - return sockaddr.sin_port; - } - - static void Sleep(int ms) { - cli.System.Threading.Thread.Sleep(ms); - } - - static cli.System.Net.Sockets.Socket NET_Socket (int domain, int type, int protocol) { - cli.System.Net.Sockets.Socket sock; - sock = socket (domain, type, protocol); - if (sock != INVALID_SOCKET) { - //SetHandleInformation((HANDLE)(uintptr_t)sock, HANDLE_FLAG_INHERIT, FALSE); - } - return sock; - } - - static int getInetAddress_addr(JNIEnv env, InetAddress iaObj) { - return iaObj.address; - } - - static int getInetAddress_family(JNIEnv env, InetAddress iaObj) { - return iaObj.family; - } -} |