diff options
author | Jo Shields <directhex@apebox.org> | 2014-02-19 22:12:43 +0000 |
---|---|---|
committer | Jo Shields <directhex@apebox.org> | 2014-02-19 22:12:43 +0000 |
commit | 9972bf87b4f27d9c8f358ef8414ac1ab957a2f0f (patch) | |
tree | 5bb230c1d698659115f918e243c1d4b0aa4c7f51 /external/ikvm/openjdk/java/net | |
parent | d0a215f5626219ff7927f576588a777e5331c7be (diff) | |
download | mono-upstream/3.2.8+dfsg.tar.gz |
Imported Upstream version 3.2.8+dfsgupstream/3.2.8+dfsg
Diffstat (limited to 'external/ikvm/openjdk/java/net')
13 files changed, 305 insertions, 91 deletions
diff --git a/external/ikvm/openjdk/java/net/DefaultDatagramSocketImplFactory.java b/external/ikvm/openjdk/java/net/DefaultDatagramSocketImplFactory.java index c08fba397a..7d4f8edba7 100644 --- a/external/ikvm/openjdk/java/net/DefaultDatagramSocketImplFactory.java +++ b/external/ikvm/openjdk/java/net/DefaultDatagramSocketImplFactory.java @@ -56,20 +56,34 @@ class DefaultDatagramSocketImplFactory /* 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")); - } catch (NumberFormatException e ) { - assert false : e; + 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 } - return null; // nothing to return - } }); + }); String ipv6 = ikvm.internal.Util.SafeGetEnvironmentVariable("IKVM_IPV6"); if (ipv6 != null) { @@ -87,7 +101,14 @@ class DefaultDatagramSocketImplFactory // (version >= 6.0) implies Vista or greater. if (version >= 6.0 && !preferIPv4Stack) { - useDualStackImpl = true; + 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 @@ -119,10 +140,12 @@ class DefaultDatagramSocketImplFactory throw new SocketException("can't instantiate DatagramSocketImpl"); } } else { + if (isMulticast) + exclusiveBind = false; if (useDualStackImpl && !isMulticast) - return new DualStackPlainDatagramSocketImpl(); + return new DualStackPlainDatagramSocketImpl(exclusiveBind); else - return new TwoStacksPlainDatagramSocketImpl(); + return new TwoStacksPlainDatagramSocketImpl(exclusiveBind); } } } diff --git a/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl.java b/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl.java index dddc50cca0..1d74e28c71 100644 --- a/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl.java +++ b/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl.java @@ -42,6 +42,22 @@ import java.io.IOException; 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"); @@ -58,7 +74,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl if (laddr == null) throw new NullPointerException("argument address"); - socketBind(nativefd, laddr, lport); + socketBind(nativefd, laddr, lport, exclusiveBind); if (lport == 0) { localPort = socketLocalPort(nativefd); } else { @@ -138,6 +154,7 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl fd.setSocket(null); } + @SuppressWarnings("fallthrough") protected void socketSetOption(int opt, Object val) throws SocketException { cli.System.Net.Sockets.Socket nativefd = checkAndReturnNativeFD(); @@ -150,6 +167,13 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl 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; @@ -167,6 +191,8 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl if (opt == SO_BINDADDR) { return socketLocalAddress(nativefd); } + if (opt == SO_REUSEADDR && reuseAddressEmulated) + return isReuseAddress; int value = socketGetIntOption(nativefd, opt); Object returnValue = null; @@ -237,10 +263,10 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl return ret; } - private static void socketBind(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport) - throws SocketException { + 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); + DualStackPlainDatagramSocketImpl_c.socketBind(env, fd, localAddress, localport, exclBind); env.ThrowPendingException(); } diff --git a/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java b/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java index 5abb1109ae..1f4ed69bef 100644 --- a/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java +++ b/external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java @@ -127,7 +127,7 @@ static cli.System.Net.Sockets.Socket socketCreate * Signature: (ILjava/net/InetAddress;I)V */ static void socketBind - (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) { + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port, boolean exclBind) { SOCKETADDRESS sa; sa = new SOCKETADDRESS(); int rv; @@ -136,8 +136,7 @@ static void socketBind JNI_TRUE) != 0) { return; } - - rv = bind(fd, sa); + rv = NET_WinBind(fd, sa, exclBind); if (rv == SOCKET_ERROR) { if (WSAGetLastError() == WSAEACCES) { @@ -275,7 +274,7 @@ static int socketReceiveOrPeekData } fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); return -1; } } else { @@ -424,7 +423,7 @@ static void socketSend } fullPacket = (char *)malloc(length); if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); return; } } else { diff --git a/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl.java b/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl.java index 4f35a6c6f6..a3584d8632 100644 --- a/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl.java +++ b/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl.java @@ -34,15 +34,25 @@ import java.io.FileDescriptor; * single file descriptor. * * @author Chris Hegarty - * @author Jeroen Frijters */ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl { - public DualStackPlainSocketImpl() {} - public DualStackPlainSocketImpl(FileDescriptor fd) { + + // 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 { @@ -90,7 +100,7 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl if (address == null) throw new NullPointerException("inet address argument is null."); - bind0(nativefd, address, port); + bind0(nativefd, address, port, exclusiveBind); if (port == 0) { localport = localPort0(nativefd); } else { @@ -158,6 +168,8 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl 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(); @@ -169,10 +181,16 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl 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 : - case SO_REUSEADDR : optionValue = on ? 1 : 0; break; case SO_SNDBUF : @@ -203,6 +221,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl 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) { @@ -238,10 +260,11 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl return ret; } - static void bind0(cli.System.Net.Sockets.Socket fd, InetAddress localAddress, int localport) + 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); + DualStackPlainSocketImpl_c.bind0(env, fd, localAddress, localport, exclBind); env.ThrowPendingException(); } diff --git a/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.java b/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.java index b5b856dd23..15c2a1848b 100644 --- a/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.java +++ b/external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.java @@ -97,7 +97,9 @@ static cli.System.Net.Sockets.Socket socket0 * Signature: (ILjava/net/InetAddress;I)V */ static void bind0 - (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port) { + (JNIEnv env, cli.System.Net.Sockets.Socket fd, InetAddress iaObj, int port, + boolean exclBind) +{ SOCKETADDRESS sa; sa = new SOCKETADDRESS(); int rv; @@ -107,7 +109,7 @@ static void bind0 return; } - rv = NET_Bind(fd, sa); + rv = NET_WinBind(fd, sa, exclBind); if (rv == SOCKET_ERROR) NET_ThrowNew(env, WSAGetLastError(), "JVM_Bind"); diff --git a/external/ikvm/openjdk/java/net/PlainSocketImpl.java b/external/ikvm/openjdk/java/net/PlainSocketImpl.java index d67825bc61..5b7f850d18 100644 --- a/external/ikvm/openjdk/java/net/PlainSocketImpl.java +++ b/external/ikvm/openjdk/java/net/PlainSocketImpl.java @@ -54,6 +54,12 @@ class PlainSocketImpl extends AbstractPlainSocketImpl /* 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() { @@ -62,6 +68,7 @@ class PlainSocketImpl extends AbstractPlainSocketImpl 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; } @@ -84,7 +91,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl // (version >= 6.0) implies Vista or greater. if (version >= 6.0 && !preferIPv4Stack) { - useDualStackImpl = true; + 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; } } @@ -93,9 +108,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl */ PlainSocketImpl() { if (useDualStackImpl) { - impl = new DualStackPlainSocketImpl(); + impl = new DualStackPlainSocketImpl(exclusiveBind); } else { - impl = new TwoStacksPlainSocketImpl(); + impl = new TwoStacksPlainSocketImpl(exclusiveBind); } } @@ -104,9 +119,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl */ PlainSocketImpl(FileDescriptor fd) { if (useDualStackImpl) { - impl = new DualStackPlainSocketImpl(fd); + impl = new DualStackPlainSocketImpl(fd, exclusiveBind); } else { - impl = new TwoStacksPlainSocketImpl(fd); + impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind); } } diff --git a/external/ikvm/openjdk/java/net/SocketInputStream.java b/external/ikvm/openjdk/java/net/SocketInputStream.java index 830fa51ce1..161947cc5e 100644 --- a/external/ikvm/openjdk/java/net/SocketInputStream.java +++ b/external/ikvm/openjdk/java/net/SocketInputStream.java @@ -32,6 +32,7 @@ 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; /** @@ -41,7 +42,6 @@ import sun.net.ConnectionResetException; * * @author Jonathan Payne * @author Arthur van Hoff - * @author Jeroen Frijters */ class SocketInputStream extends FileInputStream { @@ -182,7 +182,7 @@ class SocketInputStream extends FileInputStream } int read(byte b[], int off, int length, int timeout) throws IOException { - int n; + int n = 0; // EOF already encountered if (eof) { @@ -204,6 +204,7 @@ class SocketInputStream extends FileInputStream boolean gotReset = false; + Object traceContext = IoTrace.socketReadBegin(); // acquire file descriptor and do the read FileDescriptor fd = impl.acquireFD(); try { @@ -215,6 +216,8 @@ class SocketInputStream extends FileInputStream gotReset = true; } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, impl.address, impl.port, + timeout, n > 0 ? n : 0); } /* @@ -222,6 +225,7 @@ class SocketInputStream extends FileInputStream * buffered on the socket */ if (gotReset) { + traceContext = IoTrace.socketReadBegin(); impl.setConnectionResetPending(); impl.acquireFD(); try { @@ -232,6 +236,8 @@ class SocketInputStream extends FileInputStream } catch (ConnectionResetException rstExc) { } finally { impl.releaseFD(); + IoTrace.socketReadEnd(traceContext, impl.address, impl.port, + timeout, n > 0 ? n : 0); } } diff --git a/external/ikvm/openjdk/java/net/SocketOutputStream.java b/external/ikvm/openjdk/java/net/SocketOutputStream.java index 9e6be018d9..fd6e2c4fb9 100644 --- a/external/ikvm/openjdk/java/net/SocketOutputStream.java +++ b/external/ikvm/openjdk/java/net/SocketOutputStream.java @@ -32,6 +32,8 @@ 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 @@ -39,7 +41,6 @@ import static java.net.net_util_md.*; * * @author Jonathan Payne * @author Arthur van Hoff - * @author Jeroen Frijters */ class SocketOutputStream extends FileOutputStream { @@ -176,9 +177,12 @@ class SocketOutputStream extends FileOutputStream 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(); @@ -191,6 +195,7 @@ class SocketOutputStream extends FileOutputStream } } finally { impl.releaseFD(); + IoTrace.socketWriteEnd(traceContext, impl.address, impl.port, bytesWritten); } } diff --git a/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java b/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java index a119c4b7fe..2b2bde1b41 100644 --- a/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -38,7 +38,6 @@ import sun.net.ResourceManager; * during socket creation. * * @author Chris Hegarty - * @author Jeroen Frijters */ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl @@ -63,6 +62,22 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl */ 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 { @@ -81,6 +96,14 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } } + @Override + protected synchronized void bind0(int lport, InetAddress laddr) + throws SocketException + { + bind0(lport, laddr, exclusiveBind); + + } + protected synchronized void receive(DatagramPacket p) throws IOException { try { @@ -100,8 +123,24 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl return anyLocalBoundAddr; } return socketGetOption(optID); - } else + } 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() { @@ -119,9 +158,10 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl /* Native methods */ - protected synchronized void bind0(int lport, InetAddress laddr) throws SocketException { + 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); + TwoStacksPlainDatagramSocketImpl_c.bind0(env, this, lport, laddr, exclBind); env.ThrowPendingException(); } @@ -199,9 +239,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl TwoStacksPlainDatagramSocketImpl_c.datagramSocketClose(this); } - protected void socketSetOption(int opt, Object val) throws SocketException { + protected void socketNativeSetOption(int opt, Object val) throws SocketException { ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); - TwoStacksPlainDatagramSocketImpl_c.socketSetOption(env, this, opt, val); + TwoStacksPlainDatagramSocketImpl_c.socketNativeSetOption(env, this, opt, val); env.ThrowPendingException(); } diff --git a/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java index 8f7e1644d3..26f78adc32 100644 --- a/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java +++ b/external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -282,7 +282,7 @@ jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size) addrList = curr; } LeaveCriticalSection(&sizeCheckLock); - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); return JNI_TRUE; } curr->addr = htonl((*addrp)->S_un.S_addr); @@ -447,7 +447,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { } */ -static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int port, InetAddress addressObj) { +static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, + int port, InetAddress addressObj, + boolean exclBind) { FileDescriptor fdObj = _this.fd; FileDescriptor fd1Obj = _this.fd1; @@ -459,12 +461,7 @@ static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int port, SOCKETADDRESS lcladdr; lcladdr = new SOCKETADDRESS(); - if (IS_NULL(addressObj)) { - JNU_ThrowNullPointerException(env, "argument address"); - return; - } - - family = addressObj.family; + family = getInetAddress_family(env, addressObj); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); @@ -494,7 +491,7 @@ static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int port, v6bind.addr = lcladdr; v6bind.ipv4_fd = fd; v6bind.ipv6_fd = fd1; - if (NET_BindV6(v6bind) != -1) { + if (NET_BindV6(v6bind, exclBind) != -1) { /* check if the fds have changed */ if (v6bind.ipv4_fd != fd) { fd = v6bind.ipv4_fd; @@ -521,7 +518,7 @@ static void bind0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int port, return; } } else { - if (bind(fd, lcladdr) == -1) { + if (NET_WinBind(fd, lcladdr, exclBind) == -1) { if (WSAGetLastError() == WSAEACCES) { WSASetLastError(WSAEADDRINUSE); } @@ -582,9 +579,9 @@ static void connect0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAdd return; } - addr = address.address; + addr = getInetAddress_addr(env, address); - family = address.family; + family = getInetAddress_family(env, address); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", "Protocol family not supported"); @@ -686,7 +683,7 @@ static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPac return; } - family = iaObj.family; + family = getInetAddress_family(env, iaObj); if (family == IPv4) { fdObj = _this.fd; } else { @@ -730,7 +727,7 @@ static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPac 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 = (*env)->GetIntField(env, iaObj, ia_addressID); + address = getInetAddress_addr(env, iaObj); } else { address = ntohl(rmtaddr.him4.sin_addr.s_addr); } @@ -756,7 +753,7 @@ static void send(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, DatagramPac *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Send buf native heap allocation failed"); return; } } else { @@ -830,7 +827,7 @@ static int peek(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, InetAddress JNU_ThrowNullPointerException(env, "Null address in peek()"); return -1; } else { - address = addressObj.address; + address = getInetAddress_addr(env, addressObj); /* We only handle IPv4 for now. Will support IPv6 once its in the os */ family = AF_INET; } @@ -1009,7 +1006,7 @@ static int peekData(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, Datagram *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed"); return -1; } } else { @@ -1275,7 +1272,7 @@ static void receive0(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, Datagra *-/ fullPacket = (char *)malloc(packetBufferLen); if (!fullPacket) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); + JNU_ThrowOutOfMemoryError(env, "Receive buf native heap allocation failed"); return; } } else { @@ -1549,7 +1546,7 @@ private static int getInetAddrFromIf (JNIEnv env, int family, NetworkInterface n for (i=0; i<len; i++) { int fam; addr = addrArray[i]; - fam = addr.family; + fam = getInetAddress_family(env, addr); if (fam == family) { iaddr[0] = addr; return 0; @@ -1567,7 +1564,7 @@ private static int getInet4AddrFromIf (JNIEnv env, NetworkInterface nif, in_addr return -1; } - iaddr.s_addr = htonl(addr[0].address); + iaddr.s_addr = htonl(getInetAddress_addr(env, addr[0])); return 0; } @@ -1660,7 +1657,7 @@ private static void setMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSock } else { in_addr in = new in_addr(); - in.s_addr = htonl(((InetAddress)value).address); + in.s_addr = htonl(getInetAddress_addr(env, (InetAddress)value)); if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, in) < 0) { @@ -1734,10 +1731,10 @@ private static void setMulticastInterface(JNIEnv env, TwoStacksPlainDatagramSock /* * Class: java_net_TwoStacksPlainDatagramSocketImpl - * Method: socketSetOption + * Method: socketNativeSetOption * Signature: (ILjava/lang/Object;)V */ -static void socketSetOption(JNIEnv env, TwoStacksPlainDatagramSocketImpl _this, int opt, Object value) { +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]; diff --git a/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl.java b/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl.java index 4179078852..12c1794f7d 100644 --- a/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl.java +++ b/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl.java @@ -66,10 +66,20 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl */ cli.System.Net.Sockets.Socket lastfd = null; - public TwoStacksPlainSocketImpl() {} + // true if this socket is exclusively bound + private final boolean exclusiveBind; - public TwoStacksPlainSocketImpl(FileDescriptor fd) { + // 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; } /** @@ -112,13 +122,33 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl 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) { @@ -151,6 +181,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl } } + @Override void reset() throws IOException { if (fd != null || fd1 != null) { socketClose(); @@ -163,6 +194,7 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl /* * Return true if already closed or close is pending */ + @Override public boolean isClosedOrPending() { /* * Lock on fdLock to ensure that we wait if a @@ -191,9 +223,9 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl env.ThrowPendingException(); } - void socketBind(InetAddress address, int localport) throws IOException { + 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); + TwoStacksPlainSocketImpl_c.socketBind(env, this, address, localport, exclBind); env.ThrowPendingException(); } @@ -228,9 +260,9 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl env.ThrowPendingException(); } - void socketSetOption(int cmd, boolean on, Object value) throws SocketException { + void socketNativeSetOption(int cmd, boolean on, Object value) throws SocketException { ikvm.internal.JNI.JNIEnv env = new ikvm.internal.JNI.JNIEnv(); - TwoStacksPlainSocketImpl_c.socketSetOption(env, this, cmd, on, value); + TwoStacksPlainSocketImpl_c.socketNativeSetOption(env, this, cmd, on, value); env.ThrowPendingException(); } diff --git a/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl_c.java index f6296bd4dd..d86e84d07e 100644 --- a/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl_c.java +++ b/external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl_c.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -416,7 +416,9 @@ static void socketConnect(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddres * Method: socketBind * Signature: (Ljava/net/InetAddress;I)V */ -static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress iaObj, int localport) { +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; @@ -430,7 +432,7 @@ static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress i SOCKETADDRESS him; him = new SOCKETADDRESS(); - family = iaObj.family; + family = getInetAddress_family(env, iaObj); if (family == IPv6 && !ipv6_supported) { JNU_ThrowByName(env, JNU_JAVANETPKG+"SocketException", @@ -457,13 +459,12 @@ static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress i 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); + rv = NET_BindV6(v6bind, exclBind); if (rv != -1) { /* check if the fds have changed */ if (v6bind.ipv4_fd != fd) { @@ -488,7 +489,7 @@ static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress i } } } else { - rv = NET_Bind(fd, him); + rv = NET_WinBind(fd, him, exclBind); } if (rv == -1) { @@ -787,10 +788,10 @@ static void socketClose0(JNIEnv env, TwoStacksPlainSocketImpl _this, boolean use * * * Class: java_net_TwoStacksPlainSocketImpl - * Method: socketSetOption + * Method: socketNativeSetOption * Signature: (IZLjava/lang/Object;)V */ -static void socketSetOption(JNIEnv env, TwoStacksPlainSocketImpl _this, int cmd, boolean on, Object value) { +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]; diff --git a/external/ikvm/openjdk/java/net/net_util_md.java b/external/ikvm/openjdk/java/net/net_util_md.java index d91323596b..724ba4ccf7 100644 --- a/external/ikvm/openjdk/java/net/net_util_md.java +++ b/external/ikvm/openjdk/java/net/net_util_md.java @@ -271,6 +271,17 @@ final class net_util_md 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) { @@ -330,6 +341,18 @@ final class net_util_md } /* + * 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 @@ -337,7 +360,8 @@ final class net_util_md */ static int NET_Bind(cli.System.Net.Sockets.Socket s, SOCKETADDRESS him) { - int rv = bind(s, him); + int rv; + rv = bind(s, him); if (rv == SOCKET_ERROR) { /* @@ -352,6 +376,17 @@ final class net_util_md 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; @@ -470,7 +505,7 @@ final class net_util_md return SOCKET_ERROR; } - static int NET_BindV6(ipv6bind b) { + static int NET_BindV6(ipv6bind b, boolean exclBind) { cli.System.Net.Sockets.Socket fd = null; cli.System.Net.Sockets.Socket ofd = null; int rv; @@ -487,7 +522,7 @@ final class net_util_md if (family == AF_INET && (b.addr.him4.sin_addr.s_addr != INADDR_ANY)) { /* bind to v4 only */ int ret; - ret = NET_Bind (b.ipv4_fd, b.addr); + 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); } @@ -498,7 +533,7 @@ final class net_util_md if (family == AF_INET6 && (!IN6ADDR_ISANY(b.addr))) { /* bind to v6 only */ int ret; - ret = NET_Bind (b.ipv6_fd, b.addr); + 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); } @@ -523,7 +558,7 @@ final class net_util_md oaddr.set(new IPEndPoint(IPAddress.Any, htons(port))); } - rv = NET_Bind (fd, b.addr); + rv = NET_WinBind (fd, b.addr, exclBind); if (rv == SOCKET_ERROR) { return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); } @@ -568,7 +603,8 @@ final class net_util_md /* bind random port on first socket */ oaddr.sin_port = 0; - rv = NET_Bind (ofd, oaddr); + rv = NET_WinBind (ofd, oaddr, + exclBind); if (rv == SOCKET_ERROR) { return CLOSE_SOCKETS_AND_RETURN(fd, ofd, close_fd, close_ofd, b); } @@ -583,7 +619,8 @@ final class net_util_md } bound_port = oaddr.sin_port; b.addr.sin_port = bound_port; - rv = NET_Bind (fd, b.addr); + rv = NET_WinBind (fd, b.addr, + exclBind); if (rv != SOCKET_ERROR) { if (family == AF_INET) { @@ -836,4 +873,12 @@ final class net_util_md } return sock; } + + static int getInetAddress_addr(JNIEnv env, InetAddress iaObj) { + return iaObj.address; + } + + static int getInetAddress_family(JNIEnv env, InetAddress iaObj) { + return iaObj.family; + } } |