summaryrefslogtreecommitdiff
path: root/external/ikvm/openjdk/java/net
diff options
context:
space:
mode:
authorJo Shields <directhex@apebox.org>2014-02-19 22:12:43 +0000
committerJo Shields <directhex@apebox.org>2014-02-19 22:12:43 +0000
commit9972bf87b4f27d9c8f358ef8414ac1ab957a2f0f (patch)
tree5bb230c1d698659115f918e243c1d4b0aa4c7f51 /external/ikvm/openjdk/java/net
parentd0a215f5626219ff7927f576588a777e5331c7be (diff)
downloadmono-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')
-rw-r--r--external/ikvm/openjdk/java/net/DefaultDatagramSocketImplFactory.java51
-rw-r--r--external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl.java34
-rw-r--r--external/ikvm/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java9
-rw-r--r--external/ikvm/openjdk/java/net/DualStackPlainSocketImpl.java37
-rw-r--r--external/ikvm/openjdk/java/net/DualStackPlainSocketImpl_c.java6
-rw-r--r--external/ikvm/openjdk/java/net/PlainSocketImpl.java25
-rw-r--r--external/ikvm/openjdk/java/net/SocketInputStream.java10
-rw-r--r--external/ikvm/openjdk/java/net/SocketOutputStream.java7
-rw-r--r--external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java52
-rw-r--r--external/ikvm/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java45
-rw-r--r--external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl.java44
-rw-r--r--external/ikvm/openjdk/java/net/TwoStacksPlainSocketImpl_c.java17
-rw-r--r--external/ikvm/openjdk/java/net/net_util_md.java59
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;
+ }
}