diff options
author | jfrijters <jfrijters> | 2013-08-14 18:04:06 +0400 |
---|---|---|
committer | jfrijters <jfrijters> | 2013-08-14 18:04:06 +0400 |
commit | c0417b59efbbaba4651a60fb425d9a0ecbd40acc (patch) | |
tree | 29b9d17ebcaf28631a42c0fce808cdd798869e3f /openjdk/java | |
parent | d96db2d6ff1514e3a0b3196d54fa4f5a7392471f (diff) |
Merged OpenJDK 7u40 changes to use SO_EXCLUSIVEADDRUSE for stream sockets that don't use SO_REUSEADDR.
Diffstat (limited to 'openjdk/java')
-rw-r--r-- | openjdk/java/net/DualStackPlainSocketImpl.java | 37 | ||||
-rw-r--r-- | openjdk/java/net/DualStackPlainSocketImpl_c.java | 6 | ||||
-rw-r--r-- | openjdk/java/net/PlainSocketImpl.java | 25 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl.java | 44 | ||||
-rw-r--r-- | openjdk/java/net/TwoStacksPlainSocketImpl_c.java | 16 |
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]; |