--- old/src/java.base/unix/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java 2020-08-26 14:45:43.000000000 +0100 +++ /dev/null 2020-08-26 14:45:43.000000000 +0100 @@ -1,266 +0,0 @@ -/* - * Copyright (c) 2019, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.nio.ch; - -import java.io.FileDescriptor; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousCloseException; -import java.nio.channels.ByteChannel; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NotYetConnectedException; -import java.nio.channels.spi.AbstractInterruptibleChannel; -import java.util.Objects; -import java.util.concurrent.locks.ReentrantLock; - -import static java.util.concurrent.TimeUnit.NANOSECONDS; - -class UnixDomainSocketChannelImpl - extends AbstractInterruptibleChannel - implements ByteChannel -{ - // Used to make native read and write calls - private static final NativeDispatcher nd = new SocketDispatcher(); - - // Our file descriptor object - private final FileDescriptor fd; - // Lock held by current reading or connecting thread - private final ReentrantLock readLock = new ReentrantLock(); - - // Lock held by current writing or connecting thread - private final ReentrantLock writeLock = new ReentrantLock(); - - // Lock for managing close state - private final Object stateLock = new Object(); - - // Channel state - private static final int ST_INUSE = 0; - private static final int ST_CLOSING = 1; - private static final int ST_CLOSED = 2; - private int state; - - // IDs of native threads doing reads and writes, for signalling - private long readerThread; - private long writerThread; - - UnixDomainSocketChannelImpl(FileDescriptor fd) - throws IOException - { - this.fd = fd; - } - - /** - * Checks that the channel is open. - * - * @throws ClosedChannelException if channel is closed (or closing) - */ - private void ensureOpen() throws ClosedChannelException { - if (!isOpen()) - throw new ClosedChannelException(); - } - - /** - * Closes the socket if there are no I/O operations in progress - */ - private boolean tryClose() throws IOException { - assert Thread.holdsLock(stateLock) && state == ST_CLOSING; - if (readerThread == 0 && writerThread == 0) { - state = ST_CLOSED; - nd.close(fd); - return true; - } else { - return false; - } - } - - /** - * Complete closure of pre-closed socket (release the file descriptor) - */ - private void tryFinishClose() { - try { - tryClose(); - } catch (IOException ignore) { } - } - - /** - * Marks the beginning of a read operation - * - * @throws ClosedChannelException if the channel is closed - * @throws NotYetConnectedException if the channel is not yet connected - */ - private void beginRead() throws ClosedChannelException { - // set hook for Thread.interrupt - begin(); - synchronized (stateLock) { - ensureOpen(); - readerThread = NativeThread.current(); - } - } - - /** - * Marks the end of a read operation that may have blocked. - * - * @throws AsynchronousCloseException if the channel was closed due to this - * thread being interrupted on a blocking read operation. - */ - private void endRead(boolean completed) - throws AsynchronousCloseException - { - synchronized (stateLock) { - readerThread = 0; - if (state == ST_CLOSING) { - tryFinishClose(); - } - } - end(completed); - } - - @Override - public int read(ByteBuffer buf) throws IOException { - Objects.requireNonNull(buf); - - readLock.lock(); - try { - int n = 0; - try { - beginRead(); - n = IOUtil.read(fd, buf, -1, nd); - while (IOStatus.okayToRetry(n) && isOpen()) { - park(Net.POLLIN, 0L); - n = IOUtil.read(fd, buf, -1, nd); - } - } finally { - endRead(n > 0); - } - return n; - } finally { - readLock.unlock(); - } - } - - /** - * Marks the beginning of a write operation that might block. - * - * @throws ClosedChannelException if the channel is closed - * @throws NotYetConnectedException if the channel is not yet connected - */ - private void beginWrite() throws ClosedChannelException { - begin(); - synchronized (stateLock) { - // set hook for Thread.interrupt - ensureOpen(); - writerThread = NativeThread.current(); - } - } - - /** - * Marks the end of a write operation that may have blocked. - * - * @throws AsynchronousCloseException if the channel was closed due to this - * thread being interrupted on a blocking write operation. - */ - private void endWrite(boolean completed) - throws AsynchronousCloseException - { - synchronized (stateLock) { - writerThread = 0; - if (state == ST_CLOSING) { - tryFinishClose(); - } - } - end(completed); - } - - void park(int event, long nanos) throws IOException { - long millis; - if (nanos <= 0) { - millis = -1; - } else { - millis = NANOSECONDS.toMillis(nanos); - } - Net.poll(fd, event, millis); - } - - @Override - public int write(ByteBuffer buf) throws IOException { - Objects.requireNonNull(buf); - - writeLock.lock(); - try { - int n = 0; - try { - beginWrite(); - n = IOUtil.write(fd, buf, -1, nd); - while (IOStatus.okayToRetry(n) && isOpen()) { - park(Net.POLLOUT, 0L); - n = IOUtil.write(fd, buf, -1, nd); - } - } finally { - endWrite(n > 0); - } - return n; - } finally { - writeLock.unlock(); - } - } - - /** - * Closes this channel - * - * If there is an I/O operation in progress then the socket is pre-closed - * and the I/O threads signalled, in which case the final close is deferred - * until all I/O operations complete. - */ - @Override - protected void implCloseChannel() throws IOException { - synchronized (stateLock) { - assert state == ST_INUSE; - state = ST_CLOSING; - if (!tryClose()) { - long reader = readerThread; - long writer = writerThread; - if (reader != 0 || writer != 0) { - nd.preClose(fd); - if (reader != 0) - NativeThread.signal(reader); - if (writer != 0) - NativeThread.signal(writer); - } - } - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(this.getClass().getSuperclass().getName()); - sb.append('['); - if (!isOpen()) - sb.append("closed"); - sb.append(']'); - return sb.toString(); - } -} --- /dev/null 2020-08-26 14:45:43.000000000 +0100 +++ new/src/java.base/share/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java 2020-08-26 14:45:43.000000000 +0100 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2000, 2019, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.NetPermission; +import java.net.ProtocolFamily; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.SocketException; +import java.net.SocketOption; +import java.net.SocketTimeoutException; +import java.net.StandardProtocolFamily; +import java.net.StandardSocketOptions; +import java.net.UnixDomainSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.AlreadyBoundException; +import java.nio.channels.AlreadyConnectedException; +import java.nio.channels.AsynchronousCloseException; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.ConnectionPendingException; +import java.nio.channels.IllegalBlockingModeException; +import java.nio.channels.NoConnectionPendingException; +import java.nio.channels.NotYetConnectedException; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.nio.channels.spi.SelectorProvider; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.locks.ReentrantLock; + +import sun.net.ConnectionResetException; +import sun.net.NetHooks; +import sun.net.ext.ExtendedSocketOptions; +import sun.net.util.SocketExceptions; + +/** + * An implementation of SocketChannels + */ + +public class UnixDomainSocketChannelImpl extends SocketChannelImpl +{ + UnixDomainSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound) + throws IOException + { + super(sp, fd, bound); + } + + // Constructor for sockets obtained from server sockets + // + UnixDomainSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, SocketAddress isa) + throws IOException + { + super(sp, fd, isa); + } + + @Override + SocketAddress implLocalAddress(FileDescriptor fd) throws IOException { + return UnixDomainNet.localAddress(fd); + } + + @Override + SocketAddress getRevealedLocalAddress(SocketAddress address) { + UnixDomainSocketAddress uaddr = (UnixDomainSocketAddress)address; + return UnixDomainNet.getRevealedLocalAddress(uaddr); + } + + @SuppressWarnings("unchecked") + @Override + T implGetOption(SocketOption name) throws IOException { + return (T) Net.getSocketOption(getFD(), name); + } + + @Override + void implSetOption(SocketOption name, T value) throws IOException { + Net.setSocketOption(getFD(), name, value); + } + + private static class DefaultOptionsHolder { + static final Set> defaultOptions = defaultOptions(); + + private static Set> defaultOptions() { + HashSet> set = new HashSet<>(); + set.add(StandardSocketOptions.SO_SNDBUF); + set.add(StandardSocketOptions.SO_RCVBUF); + set.add(StandardSocketOptions.SO_LINGER); + set.addAll(ExtendedSocketOptions.unixSocketOptions()); + return Collections.unmodifiableSet(set); + } + } + + @Override + public final Set> supportedOptions() { + return DefaultOptionsHolder.defaultOptions; + } + + @Override + SocketAddress implBind(SocketAddress local) throws IOException { + UnixDomainNet.checkCapability(); + UnixDomainSocketAddress usa = UnixDomainNet.checkAddress(local); + Path path = usa == null ? null : usa.getPath(); + UnixDomainNet.bind(getFD(), path); + if (usa == null || path.toString().equals("")) { + return UnixDomainNet.UNNAMED; + } else { + return UnixDomainNet.localAddress(getFD()); + } + } + + @Override + public Socket socket() { + throw new UnsupportedOperationException("socket not supported"); + } + + /** + * Checks the permissions required for connect + */ + @Override + SocketAddress checkRemote(SocketAddress sa) throws IOException { + Objects.requireNonNull(sa); + UnixDomainNet.checkCapability(); + UnixDomainSocketAddress usa = UnixDomainNet.checkAddress(sa); + return usa; + } + + @Override + int implConnect(FileDescriptor fd, SocketAddress sa) throws IOException { + UnixDomainSocketAddress usa = (UnixDomainSocketAddress)sa; + return UnixDomainNet.connect(fd, usa.getPath()); + } + + String getRevealedLocalAddressAsString(SocketAddress sa) { + UnixDomainSocketAddress usa = (UnixDomainSocketAddress)sa; + return UnixDomainNet.getRevealedLocalAddressAsString(usa); + } + + /** + * Read/write need to be overridden for JFR + */ + @Override + public int read(ByteBuffer buf) throws IOException { + return super.read(buf); + } + + @Override + public int write(ByteBuffer buf) throws IOException { + return super.write(buf); + } + + @Override + public long write(ByteBuffer[] srcs, int offset, int length) + throws IOException + { + return super.write(srcs, offset, length); + } + + @Override + public long read(ByteBuffer[] dsts, int offset, int length) + throws IOException + { + return super.read(dsts, offset, length); + } +}