Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/ikvm-fork.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjfrijters <jfrijters>2013-08-14 18:04:06 +0400
committerjfrijters <jfrijters>2013-08-14 18:04:06 +0400
commitc0417b59efbbaba4651a60fb425d9a0ecbd40acc (patch)
tree29b9d17ebcaf28631a42c0fce808cdd798869e3f /openjdk/java/net
parentd96db2d6ff1514e3a0b3196d54fa4f5a7392471f (diff)
Merged OpenJDK 7u40 changes to use SO_EXCLUSIVEADDRUSE for stream sockets that don't use SO_REUSEADDR.
Diffstat (limited to 'openjdk/java/net')
-rw-r--r--openjdk/java/net/DualStackPlainSocketImpl.java37
-rw-r--r--openjdk/java/net/DualStackPlainSocketImpl_c.java6
-rw-r--r--openjdk/java/net/PlainSocketImpl.java25
-rw-r--r--openjdk/java/net/TwoStacksPlainSocketImpl.java44
-rw-r--r--openjdk/java/net/TwoStacksPlainSocketImpl_c.java16
5 files changed, 101 insertions, 27 deletions
diff --git a/openjdk/java/net/DualStackPlainSocketImpl.java b/openjdk/java/net/DualStackPlainSocketImpl.java
index 4f35a6c6..a3584d86 100644
--- a/openjdk/java/net/DualStackPlainSocketImpl.java
+++ b/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/openjdk/java/net/DualStackPlainSocketImpl_c.java b/openjdk/java/net/DualStackPlainSocketImpl_c.java
index b5b856dd..15c2a184 100644
--- a/openjdk/java/net/DualStackPlainSocketImpl_c.java
+++ b/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/openjdk/java/net/PlainSocketImpl.java b/openjdk/java/net/PlainSocketImpl.java
index d67825bc..5b7f850d 100644
--- a/openjdk/java/net/PlainSocketImpl.java
+++ b/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/openjdk/java/net/TwoStacksPlainSocketImpl.java b/openjdk/java/net/TwoStacksPlainSocketImpl.java
index 41790788..12c1794f 100644
--- a/openjdk/java/net/TwoStacksPlainSocketImpl.java
+++ b/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/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
index ad1614f7..d86e84d0 100644
--- a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
+++ b/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",
@@ -462,7 +464,7 @@ static void socketBind(JNIEnv env, TwoStacksPlainSocketImpl _this, InetAddress i
v6bind.addr = him;
v6bind.ipv4_fd = fd;
v6bind.ipv6_fd = fd1;
- rv = NET_BindV6(v6bind, false);
+ rv = NET_BindV6(v6bind, exclBind);
if (rv != -1) {
/* check if the fds have changed */
if (v6bind.ipv4_fd != fd) {
@@ -487,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) {
@@ -786,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];