< prev index next >

src/java.base/share/classes/sun/nio/ch/UnixDomainSocketChannelImpl.java

Print this page


   1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;











  30 import java.nio.ByteBuffer;


  31 import java.nio.channels.AsynchronousCloseException;
  32 import java.nio.channels.ByteChannel;
  33 import java.nio.channels.ClosedChannelException;



  34 import java.nio.channels.NotYetConnectedException;
  35 import java.nio.channels.spi.AbstractInterruptibleChannel;








  36 import java.util.Objects;

  37 import java.util.concurrent.locks.ReentrantLock;
  38 
  39 import static java.util.concurrent.TimeUnit.NANOSECONDS;



  40 
  41 class UnixDomainSocketChannelImpl
  42     extends AbstractInterruptibleChannel
  43     implements ByteChannel
  44 {
  45     // Used to make native read and write calls
  46     private static final NativeDispatcher nd = new SocketDispatcher();
  47 
  48     // Our file descriptor object
  49     private final FileDescriptor fd;
  50     // Lock held by current reading or connecting thread
  51     private final ReentrantLock readLock = new ReentrantLock();
  52 
  53     // Lock held by current writing or connecting thread
  54     private final ReentrantLock writeLock = new ReentrantLock();
  55 
  56     // Lock for managing close state
  57     private final Object stateLock = new Object();
  58 
  59     // Channel state
  60     private static final int ST_INUSE = 0;
  61     private static final int ST_CLOSING = 1;
  62     private static final int ST_CLOSED = 2;
  63     private int state;
  64 
  65     // IDs of native threads doing reads and writes, for signalling
  66     private long readerThread;
  67     private long writerThread;
  68 
  69     UnixDomainSocketChannelImpl(FileDescriptor fd)


  70         throws IOException
  71     {
  72         this.fd = fd;
  73     }
  74 
  75     /**
  76      * Checks that the channel is open.
  77      *
  78      * @throws ClosedChannelException if channel is closed (or closing)
  79      */
  80     private void ensureOpen() throws ClosedChannelException {
  81         if (!isOpen())
  82             throw new ClosedChannelException();
  83     }
  84 
  85     /**
  86      * Closes the socket if there are no I/O operations in progress
  87      */
  88     private boolean tryClose() throws IOException {
  89         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
  90         if (readerThread == 0 && writerThread == 0) {
  91             state = ST_CLOSED;
  92             nd.close(fd);
  93             return true;
  94         } else {
  95             return false;
  96         }
  97     }
  98 
  99     /**
 100      * Complete closure of pre-closed socket (release the file descriptor)
 101      */
 102     private void tryFinishClose() {
 103         try {
 104             tryClose();
 105         } catch (IOException ignore) { }
 106     }
 107 
 108     /**
 109      * Marks the beginning of a read operation
 110      *
 111      * @throws ClosedChannelException if the channel is closed
 112      * @throws NotYetConnectedException if the channel is not yet connected
 113      */
 114     private void beginRead() throws ClosedChannelException {
 115         // set hook for Thread.interrupt
 116         begin();
 117         synchronized (stateLock) {
 118             ensureOpen();
 119             readerThread = NativeThread.current();
 120         }
 121     }
 122 
 123     /**
 124      * Marks the end of a read operation that may have blocked.
 125      *
 126      * @throws AsynchronousCloseException if the channel was closed due to this
 127      * thread being interrupted on a blocking read operation.
 128      */
 129     private void endRead(boolean completed)
 130         throws AsynchronousCloseException
 131     {
 132         synchronized (stateLock) {
 133             readerThread = 0;
 134             if (state == ST_CLOSING) {
 135                 tryFinishClose();
 136             }











 137         }
 138         end(completed);
 139     }
 140 
 141     @Override
 142     public int read(ByteBuffer buf) throws IOException {
 143         Objects.requireNonNull(buf);

 144 
 145         readLock.lock();
 146         try {
 147             int n = 0;
 148             try {
 149                 beginRead();
 150                 n = IOUtil.read(fd, buf, -1, nd);
 151                 while (IOStatus.okayToRetry(n) && isOpen()) {
 152                     park(Net.POLLIN, 0L);
 153                     n = IOUtil.read(fd, buf, -1, nd);
 154                 }
 155             } finally {
 156                 endRead(n > 0);
 157             }
 158             return n;
 159         } finally {
 160             readLock.unlock();
 161         }
 162     }
 163 
 164     /**
 165      * Marks the beginning of a write operation that might block.
 166      *
 167      * @throws ClosedChannelException if the channel is closed
 168      * @throws NotYetConnectedException if the channel is not yet connected
 169      */
 170     private void beginWrite() throws ClosedChannelException {
 171         begin();
 172         synchronized (stateLock) {
 173             // set hook for Thread.interrupt
 174             ensureOpen();
 175             writerThread = NativeThread.current();
 176         }
 177     }
 178 
 179     /**
 180      * Marks the end of a write operation that may have blocked.
 181      *
 182      * @throws AsynchronousCloseException if the channel was closed due to this
 183      * thread being interrupted on a blocking write operation.
 184      */
 185     private void endWrite(boolean completed)
 186         throws AsynchronousCloseException
 187     {
 188         synchronized (stateLock) {
 189             writerThread = 0;
 190             if (state == ST_CLOSING) {
 191                 tryFinishClose();
 192             }
 193         }
 194         end(completed);
 195     }
 196 
 197     void park(int event, long nanos) throws IOException {
 198         long millis;
 199         if (nanos <= 0) {
 200             millis = -1;
 201         } else {
 202             millis = NANOSECONDS.toMillis(nanos);
 203         }
 204         Net.poll(fd, event, millis);
 205     }
 206 
 207     @Override
 208     public int write(ByteBuffer buf) throws IOException {
 209         Objects.requireNonNull(buf);
 210 
 211         writeLock.lock();
 212         try {
 213             int n = 0;
 214             try {
 215                 beginWrite();
 216                 n = IOUtil.write(fd, buf, -1, nd);
 217                 while (IOStatus.okayToRetry(n) && isOpen()) {
 218                     park(Net.POLLOUT, 0L);
 219                     n = IOUtil.write(fd, buf, -1, nd);
 220                 }
 221             } finally {
 222                 endWrite(n > 0);
 223             }
 224             return n;
 225         } finally {
 226             writeLock.unlock();
 227         }




 228     }
 229 
 230     /**
 231      * Closes this channel
 232      *
 233      * If there is an I/O operation in progress then the socket is pre-closed
 234      * and the I/O threads signalled, in which case the final close is deferred
 235      * until all I/O operations complete.
 236      */
 237     @Override
 238     protected void implCloseChannel() throws IOException {
 239         synchronized (stateLock) {
 240             assert state == ST_INUSE;
 241             state = ST_CLOSING;
 242             if (!tryClose()) {
 243                 long reader = readerThread;
 244                 long writer = writerThread;
 245                 if (reader != 0 || writer != 0) {
 246                     nd.preClose(fd);
 247                     if (reader != 0)
 248                         NativeThread.signal(reader);
 249                     if (writer != 0)
 250                         NativeThread.signal(writer);
 251                 }
 252             }




 253         }






 254     }
 255 
 256     @Override
 257     public String toString() {
 258         StringBuilder sb = new StringBuilder();
 259         sb.append(this.getClass().getSuperclass().getName());
 260         sb.append('[');
 261         if (!isOpen())
 262             sb.append("closed");
 263         sb.append(']');
 264         return sb.toString();
 265     }
 266 }
   1 /*
   2  * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.nio.ch;
  27 
  28 import java.io.FileDescriptor;
  29 import java.io.IOException;
  30 import java.io.UncheckedIOException;
  31 import java.net.NetPermission;
  32 import java.net.ProtocolFamily;
  33 import java.net.Socket;
  34 import java.net.SocketAddress;
  35 import java.net.SocketException;
  36 import java.net.SocketOption;
  37 import java.net.SocketTimeoutException;
  38 import java.net.StandardProtocolFamily;
  39 import java.net.StandardSocketOptions;
  40 import java.net.UnixDomainSocketAddress;
  41 import java.nio.ByteBuffer;
  42 import java.nio.channels.AlreadyBoundException;
  43 import java.nio.channels.AlreadyConnectedException;
  44 import java.nio.channels.AsynchronousCloseException;

  45 import java.nio.channels.ClosedChannelException;
  46 import java.nio.channels.ConnectionPendingException;
  47 import java.nio.channels.IllegalBlockingModeException;
  48 import java.nio.channels.NoConnectionPendingException;
  49 import java.nio.channels.NotYetConnectedException;
  50 import java.nio.channels.SelectionKey;
  51 import java.nio.channels.SocketChannel;
  52 import java.nio.channels.spi.SelectorProvider;
  53 import java.nio.file.InvalidPathException;
  54 import java.nio.file.Path;
  55 import java.security.AccessController;
  56 import java.security.PrivilegedAction;
  57 import java.util.Collections;
  58 import java.util.HashSet;
  59 import java.util.Objects;
  60 import java.util.Set;
  61 import java.util.concurrent.locks.ReentrantLock;
  62 
  63 import sun.net.ConnectionResetException;
  64 import sun.net.NetHooks;
  65 import sun.net.ext.ExtendedSocketOptions;
  66 import sun.net.util.SocketExceptions;
  67 
  68 /**
  69  * An implementation of SocketChannels
  70  */
























  71 
  72 public class UnixDomainSocketChannelImpl extends SocketChannelImpl
  73 {
  74     UnixDomainSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
  75         throws IOException
  76     {
  77         super(sp, fd, bound);
  78     }
  79 
  80     // Constructor for sockets obtained from server sockets
  81     //
  82     UnixDomainSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, SocketAddress isa)
  83         throws IOException
  84     {
  85         super(sp, fd, isa);


  86     }
  87 
  88     @Override
  89     SocketAddress implLocalAddress(FileDescriptor fd) throws IOException {
  90         return UnixDomainNet.localAddress(fd);









  91     }
  92 
  93     @Override
  94     SocketAddress getRevealedLocalAddress(SocketAddress address) {
  95         UnixDomainSocketAddress uaddr = (UnixDomainSocketAddress)address;
  96         return UnixDomainNet.getRevealedLocalAddress(uaddr);



  97     }
  98 
  99     @SuppressWarnings("unchecked")
 100     @Override
 101     <T> T implGetOption(SocketOption<T> name) throws IOException {
 102         return (T) Net.getSocketOption(getFD(), name);









 103     }
 104 
 105     @Override
 106     <T> void implSetOption(SocketOption<T> name, T value) throws IOException {
 107         Net.setSocketOption(getFD(), name, value);










 108     }
 109 
 110     private static class DefaultOptionsHolder {
 111         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 112 
 113         private static Set<SocketOption<?>> defaultOptions() {
 114             HashSet<SocketOption<?>> set = new HashSet<>();
 115             set.add(StandardSocketOptions.SO_SNDBUF);
 116             set.add(StandardSocketOptions.SO_RCVBUF);
 117             set.add(StandardSocketOptions.SO_LINGER);
 118             set.addAll(ExtendedSocketOptions.unixSocketOptions());
 119             return Collections.unmodifiableSet(set);
 120         }

 121     }
 122 
 123     @Override
 124     public final Set<SocketOption<?>> supportedOptions() {
 125         return DefaultOptionsHolder.defaultOptions;
 126     }
 127 
 128     @Override
 129     SocketAddress implBind(SocketAddress local) throws IOException {
 130         UnixDomainNet.checkCapability();
 131         UnixDomainSocketAddress usa = UnixDomainNet.checkAddress(local);
 132         Path path = usa == null ? null : usa.getPath();
 133         UnixDomainNet.bind(getFD(), path);
 134         if (usa == null || path.toString().equals("")) {
 135             return UnixDomainNet.UNNAMED;
 136         } else {
 137             return UnixDomainNet.localAddress(getFD());






 138         }
 139     }
 140 
 141     @Override
 142     public Socket socket() {
 143         throw new UnsupportedOperationException("socket not supported");










 144     }
 145 
 146     /**
 147      * Checks the permissions required for connect



 148      */
 149     @Override
 150     SocketAddress checkRemote(SocketAddress sa) throws IOException {
 151         Objects.requireNonNull(sa);
 152         UnixDomainNet.checkCapability();
 153         UnixDomainSocketAddress usa = UnixDomainNet.checkAddress(sa);
 154         return usa;














 155     }
 156 
 157     @Override
 158     int implConnect(FileDescriptor fd, SocketAddress sa) throws IOException {
 159         UnixDomainSocketAddress usa = (UnixDomainSocketAddress)sa;
 160         return UnixDomainNet.connect(fd, usa.getPath());
















 161     }
 162 
 163     String getRevealedLocalAddressAsString(SocketAddress sa) {
 164         UnixDomainSocketAddress usa = (UnixDomainSocketAddress)sa;
 165         return UnixDomainNet.getRevealedLocalAddressAsString(usa);
 166     }
 167 
 168     /**
 169      * Read/write need to be overridden for JFR




 170      */
 171     @Override
 172     public int read(ByteBuffer buf) throws IOException {
 173         return super.read(buf);












 174     }
 175 
 176     @Override
 177     public int write(ByteBuffer buf) throws IOException {
 178         return super.write(buf);
 179     }
 180 
 181     @Override
 182     public long write(ByteBuffer[] srcs, int offset, int length)
 183         throws IOException
 184     {
 185         return super.write(srcs, offset, length);
 186     }
 187 
 188     @Override
 189     public long read(ByteBuffer[] dsts, int offset, int length)
 190         throws IOException
 191     {
 192         return super.read(dsts, offset, length);




 193     }
 194 }
< prev index next >