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 16:39:36 +0400
committerjfrijters <jfrijters>2013-08-14 16:39:36 +0400
commitd96db2d6ff1514e3a0b3196d54fa4f5a7392471f (patch)
tree8d00384f30cefe564721a9ae2c16e8556f332f8f /openjdk
parentc519faf5187301ea6e09ced0b449bcdd831e53f8 (diff)
Merged OpenJDK 7u40 changes to use SO_EXCLUSIVEADDRUSE for datagram sockets that don't use SO_REUSEADDR.
Diffstat (limited to 'openjdk')
-rw-r--r--openjdk/ikvm/internal/Winsock.java1
-rw-r--r--openjdk/java/net/DefaultDatagramSocketImplFactory.java51
-rw-r--r--openjdk/java/net/DualStackPlainDatagramSocketImpl.java34
-rw-r--r--openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java9
-rw-r--r--openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java52
-rw-r--r--openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java45
-rw-r--r--openjdk/java/net/TwoStacksPlainSocketImpl_c.java3
-rw-r--r--openjdk/java/net/net_util_md.java59
8 files changed, 192 insertions, 62 deletions
diff --git a/openjdk/ikvm/internal/Winsock.java b/openjdk/ikvm/internal/Winsock.java
index 86cbb852..ce05de03 100644
--- a/openjdk/ikvm/internal/Winsock.java
+++ b/openjdk/ikvm/internal/Winsock.java
@@ -122,6 +122,7 @@ public final class Winsock
public static final int SO_RCVBUF = SocketOptionName.ReceiveBuffer;
public static final int SO_KEEPALIVE = SocketOptionName.KeepAlive;
public static final int SO_REUSEADDR = SocketOptionName.ReuseAddress;
+ public static final int SO_EXCLUSIVEADDRUSE = SocketOptionName.ExclusiveAddressUse;
public static final int SO_BROADCAST = SocketOptionName.Broadcast;
public static final int SO_RCVTIMEO = SocketOptionName.ReceiveTimeout;
public static final int SO_ERROR = SocketOptionName.Error;
diff --git a/openjdk/java/net/DefaultDatagramSocketImplFactory.java b/openjdk/java/net/DefaultDatagramSocketImplFactory.java
index c08fba39..7d4f8edb 100644
--- a/openjdk/java/net/DefaultDatagramSocketImplFactory.java
+++ b/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/openjdk/java/net/DualStackPlainDatagramSocketImpl.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl.java
index dddc50cc..1d74e28c 100644
--- a/openjdk/java/net/DualStackPlainDatagramSocketImpl.java
+++ b/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/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java b/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java
index 5abb1109..1f4ed69b 100644
--- a/openjdk/java/net/DualStackPlainDatagramSocketImpl_c.java
+++ b/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/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java
index a119c4b7..2b2bde1b 100644
--- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl.java
+++ b/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/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java
index 8f7e1644..26f78adc 100644
--- a/openjdk/java/net/TwoStacksPlainDatagramSocketImpl_c.java
+++ b/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/openjdk/java/net/TwoStacksPlainSocketImpl_c.java b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
index f6296bd4..ad1614f7 100644
--- a/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
+++ b/openjdk/java/net/TwoStacksPlainSocketImpl_c.java
@@ -457,13 +457,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, false);
if (rv != -1) {
/* check if the fds have changed */
if (v6bind.ipv4_fd != fd) {
diff --git a/openjdk/java/net/net_util_md.java b/openjdk/java/net/net_util_md.java
index d9132359..724ba4cc 100644
--- a/openjdk/java/net/net_util_md.java
+++ b/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;
+ }
}