From fd37f3de153416df36c2e90727b8c16fc1d0c730 Mon Sep 17 00:00:00 2001 From: jfrijters Date: Thu, 15 Aug 2013 16:25:09 +0000 Subject: Merged 7u40 changes in sun/nio/ch/Net.java and partially merged DatagramChannelImpl.java. --- openjdk/sun/nio/ch/DatagramChannelImpl.java | 52 +++++++++----- openjdk/sun/nio/ch/Net.java | 107 +++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 19 deletions(-) (limited to 'openjdk/sun') diff --git a/openjdk/sun/nio/ch/DatagramChannelImpl.java b/openjdk/sun/nio/ch/DatagramChannelImpl.java index b2631530..08cc5c95 100644 --- a/openjdk/sun/nio/ch/DatagramChannelImpl.java +++ b/openjdk/sun/nio/ch/DatagramChannelImpl.java @@ -86,8 +86,8 @@ class DatagramChannelImpl private int state = ST_UNINITIALIZED; // Binding - private SocketAddress localAddress; - private SocketAddress remoteAddress; + private InetSocketAddress localAddress; + private InetSocketAddress remoteAddress; // Our socket adaptor, if any private DatagramSocket socket; @@ -95,6 +95,12 @@ class DatagramChannelImpl // Multicast support private MembershipRegistry registry; + // set true when socket is bound and SO_REUSEADDRESS is emulated + private boolean reuseAddressEmulated; + + // set true/false when socket is already bound and SO_REUSEADDR is emulated + private boolean isReuseAddress; + // -- End of fields protected by stateLock @@ -163,7 +169,7 @@ class DatagramChannelImpl synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); - return localAddress; + return Net.getRevealedLocalAddress(localAddress); } } @@ -223,6 +229,12 @@ class DatagramChannelImpl } return this; } + if (name == StandardSocketOptions.SO_REUSEADDR && + Net.useExclusiveBind() && localAddress != null) + { + reuseAddressEmulated = true; + this.isReuseAddress = (Boolean)value; + } // remaining options don't need any special handling Net.setSocketOption(fd, Net.UNSPEC, name, value); @@ -281,6 +293,12 @@ class DatagramChannelImpl } } + if (name == StandardSocketOptions.SO_REUSEADDR && + reuseAddressEmulated) + { + return (T)Boolean.valueOf(isReuseAddress); + } + // no special handling return (T) Net.getSocketOption(fd, Net.UNSPEC, name); } @@ -416,7 +434,7 @@ class DatagramChannelImpl synchronized (writeLock) { ensureOpen(); - InetSocketAddress isa = (InetSocketAddress)target; + InetSocketAddress isa = Net.checkAddress(target); InetAddress ia = isa.getAddress(); if (ia == null) throw new IOException("Target address not resolved"); @@ -427,9 +445,9 @@ class DatagramChannelImpl SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (ia.isMulticastAddress()) { - sm.checkMulticast(isa.getAddress()); + sm.checkMulticast(ia); } else { - sm.checkConnect(isa.getAddress().getHostAddress(), + sm.checkConnect(ia.getHostAddress(), isa.getPort()); } } @@ -449,7 +467,7 @@ class DatagramChannelImpl return 0; writerThread = NativeThread.current(); do { - n = send(fd, src, target); + n = send(fd, src, isa); } while ((n == IOStatus.INTERRUPTED) && isOpen()); synchronized (stateLock) { @@ -466,7 +484,7 @@ class DatagramChannelImpl } } - private int send(FileDescriptor fd, ByteBuffer src, SocketAddress target) + private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) throws IOException { if (src.hasArray()) @@ -496,7 +514,7 @@ class DatagramChannelImpl } private int sendFromManagedBuffer(FileDescriptor fd, ByteBuffer bb, - SocketAddress target) + InetSocketAddress target) throws IOException { int pos = bb.position(); @@ -508,7 +526,7 @@ class DatagramChannelImpl int written; try { written = send0(preferIPv6, fd, bb.array(), bb.arrayOffset() + pos, - rem, target); + rem, target.getAddress(), target.getPort()); } catch (PortUnreachableException pue) { if (isConnected()) throw pue; @@ -700,6 +718,7 @@ class DatagramChannelImpl } } + @Override public DatagramChannel connect(SocketAddress sa) throws IOException { int localPort = 0; @@ -721,7 +740,7 @@ class DatagramChannelImpl // Connection succeeded; disallow further invocation state = ST_CONNECTED; - remoteAddress = sa; + remoteAddress = isa; sender = isa; cachedSenderInetAddress = isa.getAddress(); cachedSenderPort = isa.getPort(); @@ -740,12 +759,13 @@ class DatagramChannelImpl synchronized (stateLock) { if (!isConnected() || !isOpen()) return this; - InetSocketAddress isa = (InetSocketAddress)remoteAddress; + InetSocketAddress isa = remoteAddress; SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort()); - disconnect0(fd); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + disconnect0(fd, isIPv6); remoteAddress = null; state = ST_UNCONNECTED; @@ -1074,15 +1094,15 @@ class DatagramChannelImpl private static native void initIDs(); - private static native void disconnect0(FileDescriptor fd) + private static native void disconnect0(FileDescriptor fd, boolean isIPv6) throws IOException; private native int receive0(FileDescriptor fd, byte[] buf, int pos, int len, boolean connected) throws IOException; - private native int send0(boolean preferIPv6, FileDescriptor fd, byte[] buf, int pos, int len, - SocketAddress sa) + private native int send0(boolean preferIPv6, FileDescriptor fd, byte[] buf, int pos, + int len, InetAddress addr, int port) throws IOException; static { diff --git a/openjdk/sun/nio/ch/Net.java b/openjdk/sun/nio/ch/Net.java index 71ae5436..d9ab0f0f 100644 --- a/openjdk/sun/nio/ch/Net.java +++ b/openjdk/sun/nio/ch/Net.java @@ -31,6 +31,7 @@ import java.nio.channels.*; import java.util.*; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.PrivilegedExceptionAction; class Net { // package-private @@ -44,6 +45,40 @@ class Net { // package-private } }; + // Value of jdk.net.revealLocalAddress + private static boolean revealLocalAddress; + + // True if jdk.net.revealLocalAddress had been read + private static volatile boolean propRevealLocalAddress; + + // set to true if exclusive binding is on for Windows + private static final boolean exclusiveBind; + + static { + int availLevel = isExclusiveBindAvailable(); + if (availLevel >= 0) { + String exclBindProp = + java.security.AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public String run() { + return System.getProperty( + "sun.net.useExclusiveBind"); + } + }); + if (exclBindProp != null) { + exclusiveBind = exclBindProp.length() == 0 ? + true : Boolean.parseBoolean(exclBindProp); + } else if (availLevel == 1) { + exclusiveBind = true; + } else { + exclusiveBind = false; + } + } else { + exclusiveBind = false; + } + } + // -- Miscellaneous utilities -- private static volatile boolean checkedIPv6 = false; @@ -60,6 +95,13 @@ class Net { // package-private return isIPv6Available; } + /** + * Returns true if exclusive binding is on + */ + static boolean useExclusiveBind() { + return exclusiveBind; + } + /** * Tells whether IPv6 sockets can join IPv4 multicast groups */ @@ -147,6 +189,58 @@ class Net { // package-private translateException(x, false); } + /** + * Returns the local address after performing a SecurityManager#checkConnect. + */ + static InetSocketAddress getRevealedLocalAddress(InetSocketAddress addr) { + SecurityManager sm = System.getSecurityManager(); + if (addr == null || sm == null) + return addr; + + if (!getRevealLocalAddress()) { + // Return loopback address only if security check fails + try{ + sm.checkConnect(addr.getAddress().getHostAddress(), -1); + //Security check passed + } catch (SecurityException e) { + //Return loopback address + addr = getLoopbackAddress(addr.getPort()); + } + } + return addr; + } + + static String getRevealedLocalAddressAsString(InetSocketAddress addr) { + if (!getRevealLocalAddress() && System.getSecurityManager() != null) + addr = getLoopbackAddress(addr.getPort()); + return addr.toString(); + } + + private static boolean getRevealLocalAddress() { + if (!propRevealLocalAddress) { + try { + revealLocalAddress = Boolean.parseBoolean( + AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public String run() { + return System.getProperty( + "jdk.net.revealLocalAddress"); + } + })); + + } catch (Exception e) { + // revealLocalAddress is false + } + propRevealLocalAddress = true; + } + return revealLocalAddress; + } + + private static InetSocketAddress getLoopbackAddress(int port) { + return new InetSocketAddress(InetAddress.getLoopbackAddress(), + port); + } + /** * Returns any IPv4 address of the given network interface, or * null if the interface does not have any IPv4 addresses. @@ -308,6 +402,12 @@ class Net { // package-private private static native boolean isIPv6Available0(); + /* + * Returns 1 for Windows versions that support exclusive binding by default, 0 + * for those that do not, and -1 for Solaris/Linux/Mac OS + */ + private static native int isExclusiveBindAvailable(); + private static native boolean canIPv6SocketJoinIPv4Group0(); private static native boolean canJoin6WithIPv4Group0(); @@ -341,11 +441,12 @@ class Net { // package-private { boolean preferIPv6 = isIPv6Available() && (family != StandardProtocolFamily.INET); - bind0(preferIPv6, fd, addr, port); + bind0(fd, preferIPv6, exclusiveBind, addr, port); } - private static native void bind0(boolean preferIPv6, FileDescriptor fd, - InetAddress addr, int port) + private static native void bind0(FileDescriptor fd, boolean preferIPv6, + boolean useExclBind, InetAddress addr, + int port) throws IOException; static native void listen(FileDescriptor fd, int backlog) throws IOException; -- cgit v1.2.3