src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
changeset 54620 13b67c1420b8
parent 54246 f04e3492fd88
child 54754 193a8f1a4f3b
child 57339 40fdbdd92617
equal deleted inserted replaced
54619:b43cc3b9ef40 54620:13b67c1420b8
    32 import java.net.ProtocolFamily;
    32 import java.net.ProtocolFamily;
    33 import java.net.Socket;
    33 import java.net.Socket;
    34 import java.net.SocketAddress;
    34 import java.net.SocketAddress;
    35 import java.net.SocketException;
    35 import java.net.SocketException;
    36 import java.net.SocketOption;
    36 import java.net.SocketOption;
       
    37 import java.net.SocketTimeoutException;
    37 import java.net.StandardProtocolFamily;
    38 import java.net.StandardProtocolFamily;
    38 import java.net.StandardSocketOptions;
    39 import java.net.StandardSocketOptions;
    39 import java.nio.ByteBuffer;
    40 import java.nio.ByteBuffer;
    40 import java.nio.channels.AlreadyBoundException;
    41 import java.nio.channels.AlreadyBoundException;
    41 import java.nio.channels.AlreadyConnectedException;
    42 import java.nio.channels.AlreadyConnectedException;
    42 import java.nio.channels.AsynchronousCloseException;
    43 import java.nio.channels.AsynchronousCloseException;
    43 import java.nio.channels.ClosedChannelException;
    44 import java.nio.channels.ClosedChannelException;
    44 import java.nio.channels.ConnectionPendingException;
    45 import java.nio.channels.ConnectionPendingException;
       
    46 import java.nio.channels.IllegalBlockingModeException;
    45 import java.nio.channels.NoConnectionPendingException;
    47 import java.nio.channels.NoConnectionPendingException;
    46 import java.nio.channels.NotYetConnectedException;
    48 import java.nio.channels.NotYetConnectedException;
    47 import java.nio.channels.SelectionKey;
    49 import java.nio.channels.SelectionKey;
    48 import java.nio.channels.SocketChannel;
    50 import java.nio.channels.SocketChannel;
    49 import java.nio.channels.spi.SelectorProvider;
    51 import java.nio.channels.spi.SelectorProvider;
    50 import java.util.Collections;
    52 import java.util.Collections;
    51 import java.util.HashSet;
    53 import java.util.HashSet;
    52 import java.util.Objects;
    54 import java.util.Objects;
    53 import java.util.Set;
    55 import java.util.Set;
       
    56 import java.util.concurrent.locks.Condition;
    54 import java.util.concurrent.locks.ReentrantLock;
    57 import java.util.concurrent.locks.ReentrantLock;
    55 
    58 
    56 import sun.net.ConnectionResetException;
    59 import sun.net.ConnectionResetException;
    57 import sun.net.NetHooks;
    60 import sun.net.NetHooks;
    58 import sun.net.ext.ExtendedSocketOptions;
    61 import sun.net.ext.ExtendedSocketOptions;
    79     // Lock held by current writing or connecting thread
    82     // Lock held by current writing or connecting thread
    80     private final ReentrantLock writeLock = new ReentrantLock();
    83     private final ReentrantLock writeLock = new ReentrantLock();
    81 
    84 
    82     // Lock held by any thread that modifies the state fields declared below
    85     // Lock held by any thread that modifies the state fields declared below
    83     // DO NOT invoke a blocking I/O operation while holding this lock!
    86     // DO NOT invoke a blocking I/O operation while holding this lock!
    84     private final Object stateLock = new Object();
    87     private final ReentrantLock stateLock = new ReentrantLock();
       
    88     private final Condition stateCondition = stateLock.newCondition();
    85 
    89 
    86     // Input/Output closed
    90     // Input/Output closed
    87     private volatile boolean isInputClosed;
    91     private volatile boolean isInputClosed;
    88     private volatile boolean isOutputClosed;
    92     private volatile boolean isOutputClosed;
    89 
    93 
   131     {
   135     {
   132         super(sp);
   136         super(sp);
   133         this.fd = fd;
   137         this.fd = fd;
   134         this.fdVal = IOUtil.fdVal(fd);
   138         this.fdVal = IOUtil.fdVal(fd);
   135         if (bound) {
   139         if (bound) {
   136             synchronized (stateLock) {
   140             stateLock.lock();
       
   141             try {
   137                 this.localAddress = Net.localAddress(fd);
   142                 this.localAddress = Net.localAddress(fd);
       
   143             } finally {
       
   144                 stateLock.unlock();
   138             }
   145             }
   139         }
   146         }
   140     }
   147     }
   141 
   148 
   142     // Constructor for sockets obtained from server sockets
   149     // Constructor for sockets obtained from server sockets
   145         throws IOException
   152         throws IOException
   146     {
   153     {
   147         super(sp);
   154         super(sp);
   148         this.fd = fd;
   155         this.fd = fd;
   149         this.fdVal = IOUtil.fdVal(fd);
   156         this.fdVal = IOUtil.fdVal(fd);
   150         synchronized (stateLock) {
   157         stateLock.lock();
       
   158         try {
   151             this.localAddress = Net.localAddress(fd);
   159             this.localAddress = Net.localAddress(fd);
   152             this.remoteAddress = isa;
   160             this.remoteAddress = isa;
   153             this.state = ST_CONNECTED;
   161             this.state = ST_CONNECTED;
       
   162         } finally {
       
   163             stateLock.unlock();
   154         }
   164         }
   155     }
   165     }
   156 
   166 
   157     /**
   167     /**
   158      * Checks that the channel is open.
   168      * Checks that the channel is open.
   185         }
   195         }
   186     }
   196     }
   187 
   197 
   188     @Override
   198     @Override
   189     public Socket socket() {
   199     public Socket socket() {
   190         synchronized (stateLock) {
   200         stateLock.lock();
       
   201         try {
   191             if (socket == null)
   202             if (socket == null)
   192                 socket = SocketAdaptor.create(this);
   203                 socket = SocketAdaptor.create(this);
   193             return socket;
   204             return socket;
       
   205         } finally {
       
   206             stateLock.unlock();
   194         }
   207         }
   195     }
   208     }
   196 
   209 
   197     @Override
   210     @Override
   198     public SocketAddress getLocalAddress() throws IOException {
   211     public SocketAddress getLocalAddress() throws IOException {
   199         synchronized (stateLock) {
   212         stateLock.lock();
       
   213         try {
   200             ensureOpen();
   214             ensureOpen();
   201             return Net.getRevealedLocalAddress(localAddress);
   215             return Net.getRevealedLocalAddress(localAddress);
       
   216         } finally {
       
   217             stateLock.unlock();
   202         }
   218         }
   203     }
   219     }
   204 
   220 
   205     @Override
   221     @Override
   206     public SocketAddress getRemoteAddress() throws IOException {
   222     public SocketAddress getRemoteAddress() throws IOException {
   207         synchronized (stateLock) {
   223         stateLock.lock();
       
   224         try {
   208             ensureOpen();
   225             ensureOpen();
   209             return remoteAddress;
   226             return remoteAddress;
       
   227         } finally {
       
   228             stateLock.unlock();
   210         }
   229         }
   211     }
   230     }
   212 
   231 
   213     @Override
   232     @Override
   214     public <T> SocketChannel setOption(SocketOption<T> name, T value)
   233     public <T> SocketChannel setOption(SocketOption<T> name, T value)
   216     {
   235     {
   217         Objects.requireNonNull(name);
   236         Objects.requireNonNull(name);
   218         if (!supportedOptions().contains(name))
   237         if (!supportedOptions().contains(name))
   219             throw new UnsupportedOperationException("'" + name + "' not supported");
   238             throw new UnsupportedOperationException("'" + name + "' not supported");
   220 
   239 
   221         synchronized (stateLock) {
   240         stateLock.lock();
       
   241         try {
   222             ensureOpen();
   242             ensureOpen();
   223 
   243 
   224             if (name == StandardSocketOptions.IP_TOS) {
   244             if (name == StandardSocketOptions.IP_TOS) {
   225                 ProtocolFamily family = Net.isIPv6Available() ?
   245                 ProtocolFamily family = Net.isIPv6Available() ?
   226                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
   246                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
   235             }
   255             }
   236 
   256 
   237             // no options that require special handling
   257             // no options that require special handling
   238             Net.setSocketOption(fd, name, value);
   258             Net.setSocketOption(fd, name, value);
   239             return this;
   259             return this;
       
   260         } finally {
       
   261             stateLock.unlock();
   240         }
   262         }
   241     }
   263     }
   242 
   264 
   243     @Override
   265     @Override
   244     @SuppressWarnings("unchecked")
   266     @SuppressWarnings("unchecked")
   247     {
   269     {
   248         Objects.requireNonNull(name);
   270         Objects.requireNonNull(name);
   249         if (!supportedOptions().contains(name))
   271         if (!supportedOptions().contains(name))
   250             throw new UnsupportedOperationException("'" + name + "' not supported");
   272             throw new UnsupportedOperationException("'" + name + "' not supported");
   251 
   273 
   252         synchronized (stateLock) {
   274         stateLock.lock();
       
   275         try {
   253             ensureOpen();
   276             ensureOpen();
   254 
   277 
   255             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
   278             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
   256                 // SO_REUSEADDR emulated when using exclusive bind
   279                 // SO_REUSEADDR emulated when using exclusive bind
   257                 return (T)Boolean.valueOf(isReuseAddress);
   280                 return (T)Boolean.valueOf(isReuseAddress);
   264                 return (T) Net.getSocketOption(fd, family, name);
   287                 return (T) Net.getSocketOption(fd, family, name);
   265             }
   288             }
   266 
   289 
   267             // no options that require special handling
   290             // no options that require special handling
   268             return (T) Net.getSocketOption(fd, name);
   291             return (T) Net.getSocketOption(fd, name);
       
   292         } finally {
       
   293             stateLock.unlock();
   269         }
   294         }
   270     }
   295     }
   271 
   296 
   272     private static class DefaultOptionsHolder {
   297     private static class DefaultOptionsHolder {
   273         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
   298         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
   305     private void beginRead(boolean blocking) throws ClosedChannelException {
   330     private void beginRead(boolean blocking) throws ClosedChannelException {
   306         if (blocking) {
   331         if (blocking) {
   307             // set hook for Thread.interrupt
   332             // set hook for Thread.interrupt
   308             begin();
   333             begin();
   309 
   334 
   310             synchronized (stateLock) {
   335             stateLock.lock();
       
   336             try {
   311                 ensureOpenAndConnected();
   337                 ensureOpenAndConnected();
   312                 // record thread so it can be signalled if needed
   338                 // record thread so it can be signalled if needed
   313                 readerThread = NativeThread.current();
   339                 readerThread = NativeThread.current();
       
   340             } finally {
       
   341                 stateLock.unlock();
   314             }
   342             }
   315         } else {
   343         } else {
   316             ensureOpenAndConnected();
   344             ensureOpenAndConnected();
   317         }
   345         }
   318     }
   346     }
   325      */
   353      */
   326     private void endRead(boolean blocking, boolean completed)
   354     private void endRead(boolean blocking, boolean completed)
   327         throws AsynchronousCloseException
   355         throws AsynchronousCloseException
   328     {
   356     {
   329         if (blocking) {
   357         if (blocking) {
   330             synchronized (stateLock) {
   358             stateLock.lock();
       
   359             try {
   331                 readerThread = 0;
   360                 readerThread = 0;
   332                 // notify any thread waiting in implCloseSelectableChannel
   361                 // notify any thread waiting in implCloseSelectableChannel
   333                 if (state == ST_CLOSING) {
   362                 if (state == ST_CLOSING) {
   334                     stateLock.notifyAll();
   363                     stateCondition.signalAll();
   335                 }
   364                 }
       
   365             } finally {
       
   366                 stateLock.unlock();
   336             }
   367             }
   337             // remove hook for Thread.interrupt
   368             // remove hook for Thread.interrupt
   338             end(completed);
   369             end(completed);
   339         }
   370         }
   340     }
   371     }
   360 
   391 
   361                 // check if input is shutdown
   392                 // check if input is shutdown
   362                 if (isInputClosed)
   393                 if (isInputClosed)
   363                     return IOStatus.EOF;
   394                     return IOStatus.EOF;
   364 
   395 
       
   396                 n = IOUtil.read(fd, buf, -1, nd);
   365                 if (blocking) {
   397                 if (blocking) {
   366                     do {
   398                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
   399                         park(Net.POLLIN);
   367                         n = IOUtil.read(fd, buf, -1, nd);
   400                         n = IOUtil.read(fd, buf, -1, nd);
   368                     } while (n == IOStatus.INTERRUPTED && isOpen());
   401                     }
   369                 } else {
       
   370                     n = IOUtil.read(fd, buf, -1, nd);
       
   371                 }
   402                 }
   372             } catch (ConnectionResetException e) {
   403             } catch (ConnectionResetException e) {
   373                 connectionReset = true;
   404                 connectionReset = true;
   374                 throwConnectionReset();
   405                 throwConnectionReset();
   375             } finally {
   406             } finally {
   402 
   433 
   403                 // check if input is shutdown
   434                 // check if input is shutdown
   404                 if (isInputClosed)
   435                 if (isInputClosed)
   405                     return IOStatus.EOF;
   436                     return IOStatus.EOF;
   406 
   437 
       
   438                 n = IOUtil.read(fd, dsts, offset, length, nd);
   407                 if (blocking) {
   439                 if (blocking) {
   408                     do {
   440                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
   441                         park(Net.POLLIN);
   409                         n = IOUtil.read(fd, dsts, offset, length, nd);
   442                         n = IOUtil.read(fd, dsts, offset, length, nd);
   410                     } while (n == IOStatus.INTERRUPTED && isOpen());
   443                     }
   411                 } else {
       
   412                     n = IOUtil.read(fd, dsts, offset, length, nd);
       
   413                 }
   444                 }
   414             } catch (ConnectionResetException e) {
   445             } catch (ConnectionResetException e) {
   415                 connectionReset = true;
   446                 connectionReset = true;
   416                 throwConnectionReset();
   447                 throwConnectionReset();
   417             } finally {
   448             } finally {
   434     private void beginWrite(boolean blocking) throws ClosedChannelException {
   465     private void beginWrite(boolean blocking) throws ClosedChannelException {
   435         if (blocking) {
   466         if (blocking) {
   436             // set hook for Thread.interrupt
   467             // set hook for Thread.interrupt
   437             begin();
   468             begin();
   438 
   469 
   439             synchronized (stateLock) {
   470             stateLock.lock();
       
   471             try {
   440                 ensureOpenAndConnected();
   472                 ensureOpenAndConnected();
   441                 if (isOutputClosed)
   473                 if (isOutputClosed)
   442                     throw new ClosedChannelException();
   474                     throw new ClosedChannelException();
   443                 // record thread so it can be signalled if needed
   475                 // record thread so it can be signalled if needed
   444                 writerThread = NativeThread.current();
   476                 writerThread = NativeThread.current();
       
   477             } finally {
       
   478                 stateLock.unlock();
   445             }
   479             }
   446         } else {
   480         } else {
   447             ensureOpenAndConnected();
   481             ensureOpenAndConnected();
   448         }
   482         }
   449     }
   483     }
   456      */
   490      */
   457     private void endWrite(boolean blocking, boolean completed)
   491     private void endWrite(boolean blocking, boolean completed)
   458         throws AsynchronousCloseException
   492         throws AsynchronousCloseException
   459     {
   493     {
   460         if (blocking) {
   494         if (blocking) {
   461             synchronized (stateLock) {
   495             stateLock.lock();
       
   496             try {
   462                 writerThread = 0;
   497                 writerThread = 0;
   463                 // notify any thread waiting in implCloseSelectableChannel
   498                 // notify any thread waiting in implCloseSelectableChannel
   464                 if (state == ST_CLOSING) {
   499                 if (state == ST_CLOSING) {
   465                     stateLock.notifyAll();
   500                     stateCondition.signalAll();
   466                 }
   501                 }
       
   502             } finally {
       
   503                 stateLock.unlock();
   467             }
   504             }
   468             // remove hook for Thread.interrupt
   505             // remove hook for Thread.interrupt
   469             end(completed);
   506             end(completed);
   470         }
   507         }
   471     }
   508     }
   478         try {
   515         try {
   479             boolean blocking = isBlocking();
   516             boolean blocking = isBlocking();
   480             int n = 0;
   517             int n = 0;
   481             try {
   518             try {
   482                 beginWrite(blocking);
   519                 beginWrite(blocking);
       
   520                 n = IOUtil.write(fd, buf, -1, nd);
   483                 if (blocking) {
   521                 if (blocking) {
   484                     do {
   522                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
   523                         park(Net.POLLOUT);
   485                         n = IOUtil.write(fd, buf, -1, nd);
   524                         n = IOUtil.write(fd, buf, -1, nd);
   486                     } while (n == IOStatus.INTERRUPTED && isOpen());
   525                     }
   487                 } else {
       
   488                     n = IOUtil.write(fd, buf, -1, nd);
       
   489                 }
   526                 }
   490             } finally {
   527             } finally {
   491                 endWrite(blocking, n > 0);
   528                 endWrite(blocking, n > 0);
   492                 if (n <= 0 && isOutputClosed)
   529                 if (n <= 0 && isOutputClosed)
   493                     throw new AsynchronousCloseException();
   530                     throw new AsynchronousCloseException();
   508         try {
   545         try {
   509             boolean blocking = isBlocking();
   546             boolean blocking = isBlocking();
   510             long n = 0;
   547             long n = 0;
   511             try {
   548             try {
   512                 beginWrite(blocking);
   549                 beginWrite(blocking);
       
   550                 n = IOUtil.write(fd, srcs, offset, length, nd);
   513                 if (blocking) {
   551                 if (blocking) {
   514                     do {
   552                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
   553                         park(Net.POLLOUT);
   515                         n = IOUtil.write(fd, srcs, offset, length, nd);
   554                         n = IOUtil.write(fd, srcs, offset, length, nd);
   516                     } while (n == IOStatus.INTERRUPTED && isOpen());
   555                     }
   517                 } else {
       
   518                     n = IOUtil.write(fd, srcs, offset, length, nd);
       
   519                 }
   556                 }
   520             } finally {
   557             } finally {
   521                 endWrite(blocking, n > 0);
   558                 endWrite(blocking, n > 0);
   522                 if (n <= 0 && isOutputClosed)
   559                 if (n <= 0 && isOutputClosed)
   523                     throw new AsynchronousCloseException();
   560                     throw new AsynchronousCloseException();
   560     protected void implConfigureBlocking(boolean block) throws IOException {
   597     protected void implConfigureBlocking(boolean block) throws IOException {
   561         readLock.lock();
   598         readLock.lock();
   562         try {
   599         try {
   563             writeLock.lock();
   600             writeLock.lock();
   564             try {
   601             try {
   565                 synchronized (stateLock) {
   602                 lockedConfigureBlocking(block);
   566                     ensureOpen();
       
   567                     IOUtil.configureBlocking(fd, block);
       
   568                 }
       
   569             } finally {
   603             } finally {
   570                 writeLock.unlock();
   604                 writeLock.unlock();
   571             }
   605             }
   572         } finally {
   606         } finally {
   573             readLock.unlock();
   607             readLock.unlock();
   574         }
   608         }
   575     }
   609     }
   576 
   610 
   577     /**
   611     /**
       
   612      * Adjust the blocking mode while holding the readLock or writeLock.
       
   613      */
       
   614     private void lockedConfigureBlocking(boolean block) throws IOException {
       
   615         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
       
   616         stateLock.lock();
       
   617         try {
       
   618             ensureOpen();
       
   619             IOUtil.configureBlocking(fd, block);
       
   620         } finally {
       
   621             stateLock.unlock();
       
   622         }
       
   623     }
       
   624 
       
   625     /**
   578      * Returns the local address, or null if not bound
   626      * Returns the local address, or null if not bound
   579      */
   627      */
   580     InetSocketAddress localAddress() {
   628     InetSocketAddress localAddress() {
   581         synchronized (stateLock) {
   629         stateLock.lock();
       
   630         try {
   582             return localAddress;
   631             return localAddress;
       
   632         } finally {
       
   633             stateLock.unlock();
   583         }
   634         }
   584     }
   635     }
   585 
   636 
   586     /**
   637     /**
   587      * Returns the remote address, or null if not connected
   638      * Returns the remote address, or null if not connected
   588      */
   639      */
   589     InetSocketAddress remoteAddress() {
   640     InetSocketAddress remoteAddress() {
   590         synchronized (stateLock) {
   641         stateLock.lock();
       
   642         try {
   591             return remoteAddress;
   643             return remoteAddress;
       
   644         } finally {
       
   645             stateLock.unlock();
   592         }
   646         }
   593     }
   647     }
   594 
   648 
   595     @Override
   649     @Override
   596     public SocketChannel bind(SocketAddress local) throws IOException {
   650     public SocketChannel bind(SocketAddress local) throws IOException {
   597         readLock.lock();
   651         readLock.lock();
   598         try {
   652         try {
   599             writeLock.lock();
   653             writeLock.lock();
   600             try {
   654             try {
   601                 synchronized (stateLock) {
   655                 stateLock.lock();
       
   656                 try {
   602                     ensureOpen();
   657                     ensureOpen();
   603                     if (state == ST_CONNECTIONPENDING)
   658                     if (state == ST_CONNECTIONPENDING)
   604                         throw new ConnectionPendingException();
   659                         throw new ConnectionPendingException();
   605                     if (localAddress != null)
   660                     if (localAddress != null)
   606                         throw new AlreadyBoundException();
   661                         throw new AlreadyBoundException();
   611                         sm.checkListen(isa.getPort());
   666                         sm.checkListen(isa.getPort());
   612                     }
   667                     }
   613                     NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
   668                     NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
   614                     Net.bind(fd, isa.getAddress(), isa.getPort());
   669                     Net.bind(fd, isa.getAddress(), isa.getPort());
   615                     localAddress = Net.localAddress(fd);
   670                     localAddress = Net.localAddress(fd);
       
   671                 } finally {
       
   672                     stateLock.unlock();
   616                 }
   673                 }
   617             } finally {
   674             } finally {
   618                 writeLock.unlock();
   675                 writeLock.unlock();
   619             }
   676             }
   620         } finally {
   677         } finally {
   647     {
   704     {
   648         if (blocking) {
   705         if (blocking) {
   649             // set hook for Thread.interrupt
   706             // set hook for Thread.interrupt
   650             begin();
   707             begin();
   651         }
   708         }
   652         synchronized (stateLock) {
   709         stateLock.lock();
       
   710         try {
   653             ensureOpen();
   711             ensureOpen();
   654             int state = this.state;
   712             int state = this.state;
   655             if (state == ST_CONNECTED)
   713             if (state == ST_CONNECTED)
   656                 throw new AlreadyConnectedException();
   714                 throw new AlreadyConnectedException();
   657             if (state == ST_CONNECTIONPENDING)
   715             if (state == ST_CONNECTIONPENDING)
   665 
   723 
   666             if (blocking) {
   724             if (blocking) {
   667                 // record thread so it can be signalled if needed
   725                 // record thread so it can be signalled if needed
   668                 readerThread = NativeThread.current();
   726                 readerThread = NativeThread.current();
   669             }
   727             }
       
   728         } finally {
       
   729             stateLock.unlock();
   670         }
   730         }
   671     }
   731     }
   672 
   732 
   673     /**
   733     /**
   674      * Marks the end of a connect operation that may have blocked.
   734      * Marks the end of a connect operation that may have blocked.
   681         throws IOException
   741         throws IOException
   682     {
   742     {
   683         endRead(blocking, completed);
   743         endRead(blocking, completed);
   684 
   744 
   685         if (completed) {
   745         if (completed) {
   686             synchronized (stateLock) {
   746             stateLock.lock();
       
   747             try {
   687                 if (state == ST_CONNECTIONPENDING) {
   748                 if (state == ST_CONNECTIONPENDING) {
   688                     localAddress = Net.localAddress(fd);
   749                     localAddress = Net.localAddress(fd);
   689                     state = ST_CONNECTED;
   750                     state = ST_CONNECTED;
   690                 }
   751                 }
   691             }
   752             } finally {
   692         }
   753                 stateLock.unlock();
   693     }
   754             }
   694 
   755         }
   695     @Override
   756     }
   696     public boolean connect(SocketAddress sa) throws IOException {
   757 
       
   758     /**
       
   759      * Checks the remote address to which this channel is to be connected.
       
   760      */
       
   761     private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {
   697         InetSocketAddress isa = Net.checkAddress(sa);
   762         InetSocketAddress isa = Net.checkAddress(sa);
   698         SecurityManager sm = System.getSecurityManager();
   763         SecurityManager sm = System.getSecurityManager();
   699         if (sm != null)
   764         if (sm != null) {
   700             sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
   765             sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
   701 
   766         }
   702         InetAddress ia = isa.getAddress();
   767         if (isa.getAddress().isAnyLocalAddress()) {
   703         if (ia.isAnyLocalAddress())
   768             return new InetSocketAddress(InetAddress.getLocalHost(), isa.getPort());
   704             ia = InetAddress.getLocalHost();
   769         } else {
   705 
   770             return isa;
       
   771         }
       
   772     }
       
   773 
       
   774     @Override
       
   775     public boolean connect(SocketAddress remote) throws IOException {
       
   776         InetSocketAddress isa = checkRemote(remote);
   706         try {
   777         try {
   707             readLock.lock();
   778             readLock.lock();
   708             try {
   779             try {
   709                 writeLock.lock();
   780                 writeLock.lock();
   710                 try {
   781                 try {
   711                     int n = 0;
       
   712                     boolean blocking = isBlocking();
   782                     boolean blocking = isBlocking();
       
   783                     boolean connected = false;
   713                     try {
   784                     try {
   714                         beginConnect(blocking, isa);
   785                         beginConnect(blocking, isa);
   715                         do {
   786                         int n = Net.connect(fd, isa.getAddress(), isa.getPort());
   716                             n = Net.connect(fd, ia, isa.getPort());
   787                         if (n > 0) {
   717                         } while (n == IOStatus.INTERRUPTED && isOpen());
   788                             connected = true;
       
   789                         } else if (blocking) {
       
   790                             assert IOStatus.okayToRetry(n);
       
   791                             boolean polled = false;
       
   792                             while (!polled && isOpen()) {
       
   793                                 park(Net.POLLOUT);
       
   794                                 polled = Net.pollConnectNow(fd);
       
   795                             }
       
   796                             connected = polled && isOpen();
       
   797                         }
   718                     } finally {
   798                     } finally {
   719                         endConnect(blocking, (n > 0));
   799                         endConnect(blocking, connected);
   720                     }
   800                     }
   721                     assert IOStatus.check(n);
   801                     return connected;
   722                     return n > 0;
       
   723                 } finally {
   802                 } finally {
   724                     writeLock.unlock();
   803                     writeLock.unlock();
   725                 }
   804                 }
   726             } finally {
   805             } finally {
   727                 readLock.unlock();
   806                 readLock.unlock();
   742     private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
   821     private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
   743         if (blocking) {
   822         if (blocking) {
   744             // set hook for Thread.interrupt
   823             // set hook for Thread.interrupt
   745             begin();
   824             begin();
   746         }
   825         }
   747         synchronized (stateLock) {
   826         stateLock.lock();
       
   827         try {
   748             ensureOpen();
   828             ensureOpen();
   749             if (state != ST_CONNECTIONPENDING)
   829             if (state != ST_CONNECTIONPENDING)
   750                 throw new NoConnectionPendingException();
   830                 throw new NoConnectionPendingException();
   751             if (blocking) {
   831             if (blocking) {
   752                 // record thread so it can be signalled if needed
   832                 // record thread so it can be signalled if needed
   753                 readerThread = NativeThread.current();
   833                 readerThread = NativeThread.current();
   754             }
   834             }
       
   835         } finally {
       
   836             stateLock.unlock();
   755         }
   837         }
   756     }
   838     }
   757 
   839 
   758     /**
   840     /**
   759      * Marks the end of a finishConnect operation that may have blocked.
   841      * Marks the end of a finishConnect operation that may have blocked.
   766         throws IOException
   848         throws IOException
   767     {
   849     {
   768         endRead(blocking, completed);
   850         endRead(blocking, completed);
   769 
   851 
   770         if (completed) {
   852         if (completed) {
   771             synchronized (stateLock) {
   853             stateLock.lock();
       
   854             try {
   772                 if (state == ST_CONNECTIONPENDING) {
   855                 if (state == ST_CONNECTIONPENDING) {
   773                     localAddress = Net.localAddress(fd);
   856                     localAddress = Net.localAddress(fd);
   774                     state = ST_CONNECTED;
   857                     state = ST_CONNECTED;
   775                 }
   858                 }
       
   859             } finally {
       
   860                 stateLock.unlock();
   776             }
   861             }
   777         }
   862         }
   778     }
   863     }
   779 
   864 
   780     @Override
   865     @Override
   790 
   875 
   791                     boolean blocking = isBlocking();
   876                     boolean blocking = isBlocking();
   792                     boolean connected = false;
   877                     boolean connected = false;
   793                     try {
   878                     try {
   794                         beginFinishConnect(blocking);
   879                         beginFinishConnect(blocking);
       
   880                         boolean polled = Net.pollConnectNow(fd);
   795                         if (blocking) {
   881                         if (blocking) {
   796                             do {
   882                             while (!polled && isOpen()) {
   797                                 connected = Net.pollConnect(fd, -1);
   883                                 park(Net.POLLOUT);
   798                             } while (!connected && isOpen());
   884                                 polled = Net.pollConnectNow(fd);
   799                         } else {
   885                             }
   800                             connected = Net.pollConnect(fd, 0);
       
   801                         }
   886                         }
       
   887                         connected = polled && isOpen();
   802                     } finally {
   888                     } finally {
   803                         endFinishConnect(blocking, connected);
   889                         endFinishConnect(blocking, connected);
   804                     }
   890                     }
   805                     assert (blocking && connected) ^ !blocking;
   891                     assert (blocking && connected) ^ !blocking;
   806                     return connected;
   892                     return connected;
   841         boolean blocking;
   927         boolean blocking;
   842         boolean connected;
   928         boolean connected;
   843         boolean interrupted = false;
   929         boolean interrupted = false;
   844 
   930 
   845         // set state to ST_CLOSING
   931         // set state to ST_CLOSING
   846         synchronized (stateLock) {
   932         stateLock.lock();
       
   933         try {
   847             assert state < ST_CLOSING;
   934             assert state < ST_CLOSING;
   848             blocking = isBlocking();
   935             blocking = isBlocking();
   849             connected = (state == ST_CONNECTED);
   936             connected = (state == ST_CONNECTED);
   850             state = ST_CLOSING;
   937             state = ST_CLOSING;
       
   938         } finally {
       
   939             stateLock.unlock();
   851         }
   940         }
   852 
   941 
   853         // wait for any outstanding I/O operations to complete
   942         // wait for any outstanding I/O operations to complete
   854         if (blocking) {
   943         if (blocking) {
   855             synchronized (stateLock) {
   944             stateLock.lock();
       
   945             try {
   856                 assert state == ST_CLOSING;
   946                 assert state == ST_CLOSING;
   857                 long reader = readerThread;
   947                 long reader = readerThread;
   858                 long writer = writerThread;
   948                 long writer = writerThread;
   859                 if (reader != 0 || writer != 0) {
   949                 if (reader != 0 || writer != 0) {
   860                     nd.preClose(fd);
   950                     nd.preClose(fd);
   866                         NativeThread.signal(writer);
   956                         NativeThread.signal(writer);
   867 
   957 
   868                     // wait for blocking I/O operations to end
   958                     // wait for blocking I/O operations to end
   869                     while (readerThread != 0 || writerThread != 0) {
   959                     while (readerThread != 0 || writerThread != 0) {
   870                         try {
   960                         try {
   871                             stateLock.wait();
   961                             stateCondition.await();
   872                         } catch (InterruptedException e) {
   962                         } catch (InterruptedException e) {
   873                             interrupted = true;
   963                             interrupted = true;
   874                         }
   964                         }
   875                     }
   965                     }
   876                 }
   966                 }
       
   967             } finally {
       
   968                 stateLock.unlock();
   877             }
   969             }
   878         } else {
   970         } else {
   879             // non-blocking mode: wait for read/write to complete
   971             // non-blocking mode: wait for read/write to complete
   880             readLock.lock();
   972             readLock.lock();
   881             try {
   973             try {
   885                 readLock.unlock();
   977                 readLock.unlock();
   886             }
   978             }
   887         }
   979         }
   888 
   980 
   889         // set state to ST_KILLPENDING
   981         // set state to ST_KILLPENDING
   890         synchronized (stateLock) {
   982         stateLock.lock();
       
   983         try {
   891             assert state == ST_CLOSING;
   984             assert state == ST_CLOSING;
   892             // if connected and the channel is registered with a Selector then
   985             // if connected and the channel is registered with a Selector then
   893             // shutdown the output if possible so that the peer reads EOF. If
   986             // shutdown the output if possible so that the peer reads EOF. If
   894             // SO_LINGER is enabled and set to a non-zero value then it needs to
   987             // SO_LINGER is enabled and set to a non-zero value then it needs to
   895             // be disabled so that the Selector does not wait when it closes
   988             // be disabled so that the Selector does not wait when it closes
   906                         Net.shutdown(fd, Net.SHUT_WR);
   999                         Net.shutdown(fd, Net.SHUT_WR);
   907                     }
  1000                     }
   908                 } catch (IOException ignore) { }
  1001                 } catch (IOException ignore) { }
   909             }
  1002             }
   910             state = ST_KILLPENDING;
  1003             state = ST_KILLPENDING;
       
  1004         } finally {
       
  1005             stateLock.unlock();
   911         }
  1006         }
   912 
  1007 
   913         // close socket if not registered with Selector
  1008         // close socket if not registered with Selector
   914         if (!isRegistered())
  1009         if (!isRegistered())
   915             kill();
  1010             kill();
   919             Thread.currentThread().interrupt();
  1014             Thread.currentThread().interrupt();
   920     }
  1015     }
   921 
  1016 
   922     @Override
  1017     @Override
   923     public void kill() throws IOException {
  1018     public void kill() throws IOException {
   924         synchronized (stateLock) {
  1019         stateLock.lock();
       
  1020         try {
   925             if (state == ST_KILLPENDING) {
  1021             if (state == ST_KILLPENDING) {
   926                 state = ST_KILLED;
  1022                 state = ST_KILLED;
   927                 nd.close(fd);
  1023                 nd.close(fd);
   928             }
  1024             }
       
  1025         } finally {
       
  1026             stateLock.unlock();
   929         }
  1027         }
   930     }
  1028     }
   931 
  1029 
   932     @Override
  1030     @Override
   933     public SocketChannel shutdownInput() throws IOException {
  1031     public SocketChannel shutdownInput() throws IOException {
   934         synchronized (stateLock) {
  1032         stateLock.lock();
       
  1033         try {
   935             ensureOpen();
  1034             ensureOpen();
   936             if (!isConnected())
  1035             if (!isConnected())
   937                 throw new NotYetConnectedException();
  1036                 throw new NotYetConnectedException();
   938             if (!isInputClosed) {
  1037             if (!isInputClosed) {
   939                 Net.shutdown(fd, Net.SHUT_RD);
  1038                 Net.shutdown(fd, Net.SHUT_RD);
   941                 if (thread != 0)
  1040                 if (thread != 0)
   942                     NativeThread.signal(thread);
  1041                     NativeThread.signal(thread);
   943                 isInputClosed = true;
  1042                 isInputClosed = true;
   944             }
  1043             }
   945             return this;
  1044             return this;
       
  1045         } finally {
       
  1046             stateLock.unlock();
   946         }
  1047         }
   947     }
  1048     }
   948 
  1049 
   949     @Override
  1050     @Override
   950     public SocketChannel shutdownOutput() throws IOException {
  1051     public SocketChannel shutdownOutput() throws IOException {
   951         synchronized (stateLock) {
  1052         stateLock.lock();
       
  1053         try {
   952             ensureOpen();
  1054             ensureOpen();
   953             if (!isConnected())
  1055             if (!isConnected())
   954                 throw new NotYetConnectedException();
  1056                 throw new NotYetConnectedException();
   955             if (!isOutputClosed) {
  1057             if (!isOutputClosed) {
   956                 Net.shutdown(fd, Net.SHUT_WR);
  1058                 Net.shutdown(fd, Net.SHUT_WR);
   958                 if (thread != 0)
  1060                 if (thread != 0)
   959                     NativeThread.signal(thread);
  1061                     NativeThread.signal(thread);
   960                 isOutputClosed = true;
  1062                 isOutputClosed = true;
   961             }
  1063             }
   962             return this;
  1064             return this;
       
  1065         } finally {
       
  1066             stateLock.unlock();
   963         }
  1067         }
   964     }
  1068     }
   965 
  1069 
   966     boolean isInputOpen() {
  1070     boolean isInputOpen() {
   967         return !isInputClosed;
  1071         return !isInputClosed;
   970     boolean isOutputOpen() {
  1074     boolean isOutputOpen() {
   971         return !isOutputClosed;
  1075         return !isOutputClosed;
   972     }
  1076     }
   973 
  1077 
   974     /**
  1078     /**
   975      * Poll this channel's socket for reading up to the given timeout.
  1079      * Waits for a connection attempt to finish with a timeout
   976      * @return {@code true} if the socket is polled
  1080      * @throws SocketTimeoutException if the connect timeout elapses
   977      */
  1081      */
   978     boolean pollRead(long timeout) throws IOException {
  1082     private boolean finishTimedConnect(long nanos) throws IOException {
   979         boolean blocking = isBlocking();
  1083         long startNanos = System.nanoTime();
   980         assert Thread.holdsLock(blockingLock()) && blocking;
  1084         boolean polled = Net.pollConnectNow(fd);
       
  1085         while (!polled && isOpen()) {
       
  1086             long remainingNanos = nanos - (System.nanoTime() - startNanos);
       
  1087             if (remainingNanos <= 0) {
       
  1088                 throw new SocketTimeoutException("Connect timed out");
       
  1089             }
       
  1090             park(Net.POLLOUT, remainingNanos);
       
  1091             polled = Net.pollConnectNow(fd);
       
  1092         }
       
  1093         return polled && isOpen();
       
  1094     }
       
  1095 
       
  1096     /**
       
  1097      * Attempts to establish a connection to the given socket address with a
       
  1098      * timeout. Closes the socket if connection cannot be established.
       
  1099      *
       
  1100      * @apiNote This method is for use by the socket adaptor.
       
  1101      *
       
  1102      * @throws IllegalBlockingModeException if the channel is non-blocking
       
  1103      * @throws SocketTimeoutException if the read timeout elapses
       
  1104      */
       
  1105     void blockingConnect(SocketAddress remote, long nanos) throws IOException {
       
  1106         InetSocketAddress isa = checkRemote(remote);
       
  1107         try {
       
  1108             readLock.lock();
       
  1109             try {
       
  1110                 writeLock.lock();
       
  1111                 try {
       
  1112                     if (!isBlocking())
       
  1113                         throw new IllegalBlockingModeException();
       
  1114                     boolean connected = false;
       
  1115                     try {
       
  1116                         beginConnect(true, isa);
       
  1117                         // change socket to non-blocking
       
  1118                         lockedConfigureBlocking(false);
       
  1119                         try {
       
  1120                             int n = Net.connect(fd, isa.getAddress(), isa.getPort());
       
  1121                             connected = (n > 0) ? true : finishTimedConnect(nanos);
       
  1122                         } finally {
       
  1123                             // restore socket to blocking mode
       
  1124                             lockedConfigureBlocking(true);
       
  1125                         }
       
  1126                     } finally {
       
  1127                         endConnect(true, connected);
       
  1128                     }
       
  1129                 } finally {
       
  1130                     writeLock.unlock();
       
  1131                 }
       
  1132             } finally {
       
  1133                 readLock.unlock();
       
  1134             }
       
  1135         } catch (IOException ioe) {
       
  1136             // connect failed, close the channel
       
  1137             close();
       
  1138             throw SocketExceptions.of(ioe, isa);
       
  1139         }
       
  1140     }
       
  1141 
       
  1142     /**
       
  1143      * Attempts to read bytes from the socket into the given byte array.
       
  1144      */
       
  1145     private int tryRead(byte[] b, int off, int len) throws IOException {
       
  1146         ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
       
  1147         assert dst.position() == 0;
       
  1148         try {
       
  1149             int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
       
  1150             if (n > 0) {
       
  1151                 dst.get(b, off, n);
       
  1152             }
       
  1153             return n;
       
  1154         } finally{
       
  1155             Util.offerFirstTemporaryDirectBuffer(dst);
       
  1156         }
       
  1157     }
       
  1158 
       
  1159     /**
       
  1160      * Reads bytes from the socket into the given byte array with a timeout.
       
  1161      * @throws SocketTimeoutException if the read timeout elapses
       
  1162      */
       
  1163     private int timedRead(byte[] b, int off, int len, long nanos) throws IOException {
       
  1164         long startNanos = System.nanoTime();
       
  1165         int n = tryRead(b, off, len);
       
  1166         while (n == IOStatus.UNAVAILABLE && isOpen()) {
       
  1167             long remainingNanos = nanos - (System.nanoTime() - startNanos);
       
  1168             if (remainingNanos <= 0) {
       
  1169                 throw new SocketTimeoutException("Read timed out");
       
  1170             }
       
  1171             park(Net.POLLIN, remainingNanos);
       
  1172             n = tryRead(b, off, len);
       
  1173         }
       
  1174         return n;
       
  1175     }
       
  1176 
       
  1177     /**
       
  1178      * Reads bytes from the socket into the given byte array.
       
  1179      *
       
  1180      * @apiNote This method is for use by the socket adaptor.
       
  1181      *
       
  1182      * @throws IllegalBlockingModeException if the channel is non-blocking
       
  1183      * @throws SocketTimeoutException if the read timeout elapses
       
  1184      */
       
  1185     int blockingRead(byte[] b, int off, int len, long nanos) throws IOException {
       
  1186         Objects.checkFromIndexSize(off, len, b.length);
       
  1187         if (len == 0) {
       
  1188             // nothing to do
       
  1189             return 0;
       
  1190         }
   981 
  1191 
   982         readLock.lock();
  1192         readLock.lock();
   983         try {
  1193         try {
   984             boolean polled = false;
  1194             // check that channel is configured blocking
   985             try {
  1195             if (!isBlocking())
   986                 beginRead(blocking);
  1196                 throw new IllegalBlockingModeException();
   987                 int events = Net.poll(fd, Net.POLLIN, timeout);
  1197 
   988                 polled = (events != 0);
  1198             int n = 0;
   989             } finally {
  1199             try {
   990                 endRead(blocking, polled);
  1200                 beginRead(true);
   991             }
  1201 
   992             return polled;
  1202                 // check if connection has been reset
       
  1203                 if (connectionReset)
       
  1204                     throwConnectionReset();
       
  1205 
       
  1206                 // check if input is shutdown
       
  1207                 if (isInputClosed)
       
  1208                     return IOStatus.EOF;
       
  1209 
       
  1210                 if (nanos > 0) {
       
  1211                     // change socket to non-blocking
       
  1212                     lockedConfigureBlocking(false);
       
  1213                     try {
       
  1214                         n = timedRead(b, off, len, nanos);
       
  1215                     } finally {
       
  1216                         // restore socket to blocking mode
       
  1217                         lockedConfigureBlocking(true);
       
  1218                     }
       
  1219                 } else {
       
  1220                     // read, no timeout
       
  1221                     n = tryRead(b, off, len);
       
  1222                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
  1223                         park(Net.POLLIN);
       
  1224                         n = tryRead(b, off, len);
       
  1225                     }
       
  1226                 }
       
  1227             } catch (ConnectionResetException e) {
       
  1228                 connectionReset = true;
       
  1229                 throwConnectionReset();
       
  1230             } finally {
       
  1231                 endRead(true, n > 0);
       
  1232                 if (n <= 0 && isInputClosed)
       
  1233                     return IOStatus.EOF;
       
  1234             }
       
  1235             assert n > 0 || n == -1;
       
  1236             return n;
   993         } finally {
  1237         } finally {
   994             readLock.unlock();
  1238             readLock.unlock();
   995         }
  1239         }
   996     }
  1240     }
   997 
  1241 
   998     /**
  1242     /**
   999      * Poll this channel's socket for a connection, up to the given timeout.
  1243      * Attempts to write a sequence of bytes to the socket from the given
  1000      * @return {@code true} if the socket is polled
  1244      * byte array.
  1001      */
  1245      */
  1002     boolean pollConnected(long timeout) throws IOException {
  1246     private int tryWrite(byte[] b, int off, int len) throws IOException {
  1003         boolean blocking = isBlocking();
  1247         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
  1004         assert Thread.holdsLock(blockingLock()) && blocking;
  1248         assert src.position() == 0;
  1005 
  1249         try {
  1006         readLock.lock();
  1250             src.put(b, off, len);
  1007         try {
  1251             return nd.write(fd, ((DirectBuffer)src).address(), len);
  1008             writeLock.lock();
  1252         } finally {
  1009             try {
  1253             Util.offerFirstTemporaryDirectBuffer(src);
  1010                 boolean polled = false;
  1254         }
  1011                 try {
  1255     }
  1012                     beginFinishConnect(blocking);
  1256 
  1013                     int events = Net.poll(fd, Net.POLLCONN, timeout);
  1257     /**
  1014                     polled = (events != 0);
  1258      * Writes a sequence of bytes to the socket from the given byte array.
  1015                 } finally {
  1259      *
  1016                     // invoke endFinishConnect with completed = false so that
  1260      * @apiNote This method is for use by the socket adaptor.
  1017                     // the state is not changed to ST_CONNECTED. The socket
  1261      */
  1018                     // adaptor will use finishConnect to finish.
  1262     void blockingWriteFully(byte[] b, int off, int len) throws IOException {
  1019                     endFinishConnect(blocking, /*completed*/false);
  1263         Objects.checkFromIndexSize(off, len, b.length);
  1020                 }
  1264         if (len == 0) {
  1021                 return polled;
  1265             // nothing to do
  1022             } finally {
  1266             return;
  1023                 writeLock.unlock();
  1267         }
  1024             }
  1268 
  1025         } finally {
  1269         writeLock.lock();
  1026             readLock.unlock();
  1270         try {
       
  1271             // check that channel is configured blocking
       
  1272             if (!isBlocking())
       
  1273                 throw new IllegalBlockingModeException();
       
  1274 
       
  1275             // loop until all bytes have been written
       
  1276             int pos = off;
       
  1277             int end = off + len;
       
  1278             beginWrite(true);
       
  1279             try {
       
  1280                 while (pos < end && isOpen()) {
       
  1281                     int size = end - pos;
       
  1282                     int n = tryWrite(b, pos, size);
       
  1283                     while (IOStatus.okayToRetry(n) && isOpen()) {
       
  1284                         park(Net.POLLOUT);
       
  1285                         n = tryWrite(b, pos, size);
       
  1286                     }
       
  1287                     if (n > 0) {
       
  1288                         pos += n;
       
  1289                     }
       
  1290                 }
       
  1291             } finally {
       
  1292                 endWrite(true, pos >= end);
       
  1293             }
       
  1294         } finally {
       
  1295             writeLock.unlock();
  1027         }
  1296         }
  1028     }
  1297     }
  1029 
  1298 
  1030     /**
  1299     /**
  1031      * Return the number of bytes in the socket input buffer.
  1300      * Return the number of bytes in the socket input buffer.
  1032      */
  1301      */
  1033     int available() throws IOException {
  1302     int available() throws IOException {
  1034         synchronized (stateLock) {
  1303         stateLock.lock();
       
  1304         try {
  1035             ensureOpenAndConnected();
  1305             ensureOpenAndConnected();
  1036             if (isInputClosed) {
  1306             if (isInputClosed) {
  1037                 return 0;
  1307                 return 0;
  1038             } else {
  1308             } else {
  1039                 return Net.available(fd);
  1309                 return Net.available(fd);
  1040             }
  1310             }
       
  1311         } finally {
       
  1312             stateLock.unlock();
  1041         }
  1313         }
  1042     }
  1314     }
  1043 
  1315 
  1044     /**
  1316     /**
  1045      * Translates native poll revent ops into a ready operation ops
  1317      * Translates native poll revent ops into a ready operation ops
  1115         sb.append(this.getClass().getSuperclass().getName());
  1387         sb.append(this.getClass().getSuperclass().getName());
  1116         sb.append('[');
  1388         sb.append('[');
  1117         if (!isOpen())
  1389         if (!isOpen())
  1118             sb.append("closed");
  1390             sb.append("closed");
  1119         else {
  1391         else {
  1120             synchronized (stateLock) {
  1392             stateLock.lock();
       
  1393             try {
  1121                 switch (state) {
  1394                 switch (state) {
  1122                 case ST_UNCONNECTED:
  1395                 case ST_UNCONNECTED:
  1123                     sb.append("unconnected");
  1396                     sb.append("unconnected");
  1124                     break;
  1397                     break;
  1125                 case ST_CONNECTIONPENDING:
  1398                 case ST_CONNECTIONPENDING:
  1140                 }
  1413                 }
  1141                 if (remoteAddress() != null) {
  1414                 if (remoteAddress() != null) {
  1142                     sb.append(" remote=");
  1415                     sb.append(" remote=");
  1143                     sb.append(remoteAddress().toString());
  1416                     sb.append(remoteAddress().toString());
  1144                 }
  1417                 }
       
  1418             } finally {
       
  1419                 stateLock.unlock();
  1145             }
  1420             }
  1146         }
  1421         }
  1147         sb.append(']');
  1422         sb.append(']');
  1148         return sb.toString();
  1423         return sb.toString();
  1149     }
  1424     }