Home | History | Annotate | Download | only in ch
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package sun.nio.ch;
     28 
     29 import java.io.FileDescriptor;
     30 import java.io.IOException;
     31 import java.net.InetAddress;
     32 import java.net.InetSocketAddress;
     33 import java.net.ProtocolFamily;
     34 import java.net.Socket;
     35 import java.net.SocketAddress;
     36 import java.net.SocketOption;
     37 import java.net.StandardProtocolFamily;
     38 import java.net.StandardSocketOptions;
     39 import java.nio.ByteBuffer;
     40 import java.nio.channels.AlreadyBoundException;
     41 import java.nio.channels.AlreadyConnectedException;
     42 import java.nio.channels.AsynchronousCloseException;
     43 import java.nio.channels.ClosedChannelException;
     44 import java.nio.channels.ConnectionPendingException;
     45 import java.nio.channels.NoConnectionPendingException;
     46 import java.nio.channels.NotYetConnectedException;
     47 import java.nio.channels.SelectionKey;
     48 import java.nio.channels.SocketChannel;
     49 import java.nio.channels.spi.SelectorProvider;
     50 import java.util.Collections;
     51 import java.util.HashSet;
     52 import java.util.Set;
     53 
     54 import dalvik.system.BlockGuard;
     55 import dalvik.system.CloseGuard;
     56 import sun.net.ExtendedOptionsImpl;
     57 import sun.net.NetHooks;
     58 
     59 
     60 /**
     61  * An implementation of SocketChannels
     62  */
     63 
     64 class SocketChannelImpl
     65     extends SocketChannel
     66     implements SelChImpl
     67 {
     68 
     69     // Used to make native read and write calls
     70     private static NativeDispatcher nd;
     71 
     72     // Our file descriptor object
     73     private final FileDescriptor fd;
     74 
     75     // fd value needed for dev/poll. This value will remain valid
     76     // even after the value in the file descriptor object has been set to -1
     77     private final int fdVal;
     78 
     79     // IDs of native threads doing reads and writes, for signalling
     80     private volatile long readerThread = 0;
     81     private volatile long writerThread = 0;
     82 
     83     // Lock held by current reading or connecting thread
     84     private final Object readLock = new Object();
     85 
     86     // Lock held by current writing or connecting thread
     87     private final Object writeLock = new Object();
     88 
     89     // Lock held by any thread that modifies the state fields declared below
     90     // DO NOT invoke a blocking I/O operation while holding this lock!
     91     private final Object stateLock = new Object();
     92 
     93     // -- The following fields are protected by stateLock
     94 
     95     // set true when exclusive binding is on and SO_REUSEADDR is emulated
     96     private boolean isReuseAddress;
     97 
     98     // State, increases monotonically
     99     private static final int ST_UNINITIALIZED = -1;
    100     private static final int ST_UNCONNECTED = 0;
    101     private static final int ST_PENDING = 1;
    102     private static final int ST_CONNECTED = 2;
    103     private static final int ST_KILLPENDING = 3;
    104     private static final int ST_KILLED = 4;
    105     private int state = ST_UNINITIALIZED;
    106 
    107     // Binding
    108     private InetSocketAddress localAddress;
    109     private InetSocketAddress remoteAddress;
    110 
    111     // Input/Output open
    112     private boolean isInputOpen = true;
    113     private boolean isOutputOpen = true;
    114     private boolean readyToConnect = false;
    115 
    116     // Socket adaptor, created on demand
    117     private Socket socket;
    118 
    119     // -- End of fields protected by stateLock
    120 
    121     // Android-changed: Add CloseGuard support.
    122     private final CloseGuard guard = CloseGuard.get();
    123 
    124     // Constructor for normal connecting sockets
    125     //
    126     SocketChannelImpl(SelectorProvider sp) throws IOException {
    127         super(sp);
    128         this.fd = Net.socket(true);
    129         this.fdVal = IOUtil.fdVal(fd);
    130         this.state = ST_UNCONNECTED;
    131 
    132         // Android-changed: Add CloseGuard support.
    133         // Net#socket will set |fd| if it succeeds.
    134         if (fd != null && fd.valid()) {
    135             guard.open("close");
    136         }
    137     }
    138 
    139     SocketChannelImpl(SelectorProvider sp,
    140                       FileDescriptor fd,
    141                       boolean bound)
    142         throws IOException
    143     {
    144         super(sp);
    145         this.fd = fd;
    146         this.fdVal = IOUtil.fdVal(fd);
    147         this.state = ST_UNCONNECTED;
    148 
    149         // Android-changed: Add CloseGuard support.
    150         if (fd != null && fd.valid()) {
    151             guard.open("close");
    152         }
    153 
    154         if (bound)
    155             this.localAddress = Net.localAddress(fd);
    156     }
    157 
    158     // Constructor for sockets obtained from server sockets
    159     //
    160     SocketChannelImpl(SelectorProvider sp,
    161                       FileDescriptor fd, InetSocketAddress remote)
    162         throws IOException
    163     {
    164         super(sp);
    165         this.fd = fd;
    166         this.fdVal = IOUtil.fdVal(fd);
    167         this.state = ST_CONNECTED;
    168         this.localAddress = Net.localAddress(fd);
    169         this.remoteAddress = remote;
    170         // Android-changed: Add CloseGuard support.
    171         if (fd != null && fd.valid()) {
    172             guard.open("close");
    173         }
    174     }
    175 
    176     public Socket socket() {
    177         synchronized (stateLock) {
    178             if (socket == null)
    179                 socket = SocketAdaptor.create(this);
    180             return socket;
    181         }
    182     }
    183 
    184     @Override
    185     public SocketAddress getLocalAddress() throws IOException {
    186         synchronized (stateLock) {
    187             if (!isOpen())
    188                 throw new ClosedChannelException();
    189             return  Net.getRevealedLocalAddress(localAddress);
    190         }
    191     }
    192 
    193     @Override
    194     public SocketAddress getRemoteAddress() throws IOException {
    195         synchronized (stateLock) {
    196             if (!isOpen())
    197                 throw new ClosedChannelException();
    198             return remoteAddress;
    199         }
    200     }
    201 
    202     @Override
    203     public <T> SocketChannel setOption(SocketOption<T> name, T value)
    204         throws IOException
    205     {
    206         if (name == null)
    207             throw new NullPointerException();
    208         if (!supportedOptions().contains(name))
    209             throw new UnsupportedOperationException("'" + name + "' not supported");
    210 
    211         synchronized (stateLock) {
    212             if (!isOpen())
    213                 throw new ClosedChannelException();
    214 
    215             if (name == StandardSocketOptions.IP_TOS) {
    216                 ProtocolFamily family = Net.isIPv6Available() ?
    217                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
    218                 Net.setSocketOption(fd, family, name, value);
    219                 return this;
    220             }
    221 
    222             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
    223                 // SO_REUSEADDR emulated when using exclusive bind
    224                 isReuseAddress = (Boolean)value;
    225                 return this;
    226             }
    227 
    228             // no options that require special handling
    229             Net.setSocketOption(fd, Net.UNSPEC, name, value);
    230             return this;
    231         }
    232     }
    233 
    234     @Override
    235     @SuppressWarnings("unchecked")
    236     public <T> T getOption(SocketOption<T> name)
    237         throws IOException
    238     {
    239         if (name == null)
    240             throw new NullPointerException();
    241         if (!supportedOptions().contains(name))
    242             throw new UnsupportedOperationException("'" + name + "' not supported");
    243 
    244         synchronized (stateLock) {
    245             if (!isOpen())
    246                 throw new ClosedChannelException();
    247 
    248             if (name == StandardSocketOptions.SO_REUSEADDR &&
    249                     Net.useExclusiveBind())
    250             {
    251                 // SO_REUSEADDR emulated when using exclusive bind
    252                 return (T)Boolean.valueOf(isReuseAddress);
    253             }
    254 
    255             // special handling for IP_TOS: always return 0 when IPv6
    256             if (name == StandardSocketOptions.IP_TOS) {
    257                 ProtocolFamily family = Net.isIPv6Available() ?
    258                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
    259                 return (T) Net.getSocketOption(fd, family, name);
    260             }
    261 
    262             // no options that require special handling
    263             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
    264         }
    265     }
    266 
    267     private static class DefaultOptionsHolder {
    268         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
    269 
    270         private static Set<SocketOption<?>> defaultOptions() {
    271             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
    272             set.add(StandardSocketOptions.SO_SNDBUF);
    273             set.add(StandardSocketOptions.SO_RCVBUF);
    274             set.add(StandardSocketOptions.SO_KEEPALIVE);
    275             set.add(StandardSocketOptions.SO_REUSEADDR);
    276             set.add(StandardSocketOptions.SO_LINGER);
    277             set.add(StandardSocketOptions.TCP_NODELAY);
    278             // additional options required by socket adaptor
    279             set.add(StandardSocketOptions.IP_TOS);
    280             set.add(ExtendedSocketOption.SO_OOBINLINE);
    281             if (ExtendedOptionsImpl.flowSupported()) {
    282                 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
    283             }
    284             return Collections.unmodifiableSet(set);
    285         }
    286     }
    287 
    288     @Override
    289     public final Set<SocketOption<?>> supportedOptions() {
    290         return DefaultOptionsHolder.defaultOptions;
    291     }
    292 
    293     private boolean ensureReadOpen() throws ClosedChannelException {
    294         synchronized (stateLock) {
    295             if (!isOpen())
    296                 throw new ClosedChannelException();
    297             if (!isConnected())
    298                 throw new NotYetConnectedException();
    299             if (!isInputOpen)
    300                 return false;
    301             else
    302                 return true;
    303         }
    304     }
    305 
    306     private void ensureWriteOpen() throws ClosedChannelException {
    307         synchronized (stateLock) {
    308             if (!isOpen())
    309                 throw new ClosedChannelException();
    310             if (!isOutputOpen)
    311                 throw new ClosedChannelException();
    312             if (!isConnected())
    313                 throw new NotYetConnectedException();
    314         }
    315     }
    316 
    317     private void readerCleanup() throws IOException {
    318         synchronized (stateLock) {
    319             readerThread = 0;
    320             if (state == ST_KILLPENDING)
    321                 kill();
    322         }
    323     }
    324 
    325     private void writerCleanup() throws IOException {
    326         synchronized (stateLock) {
    327             writerThread = 0;
    328             if (state == ST_KILLPENDING)
    329                 kill();
    330         }
    331     }
    332 
    333     public int read(ByteBuffer buf) throws IOException {
    334 
    335         if (buf == null)
    336             throw new NullPointerException();
    337 
    338         synchronized (readLock) {
    339             if (!ensureReadOpen())
    340                 return -1;
    341             int n = 0;
    342             try {
    343 
    344                 // Set up the interruption machinery; see
    345                 // AbstractInterruptibleChannel for details
    346                 //
    347                 begin();
    348 
    349                 synchronized (stateLock) {
    350                     if (!isOpen()) {
    351                     // Either the current thread is already interrupted, so
    352                     // begin() closed the channel, or another thread closed the
    353                     // channel since we checked it a few bytecodes ago.  In
    354                     // either case the value returned here is irrelevant since
    355                     // the invocation of end() in the finally block will throw
    356                     // an appropriate exception.
    357                     //
    358                         return 0;
    359 
    360                     }
    361 
    362                     // Save this thread so that it can be signalled on those
    363                     // platforms that require it
    364                     //
    365                     readerThread = NativeThread.current();
    366                 }
    367 
    368                 // Between the previous test of isOpen() and the return of the
    369                 // IOUtil.read invocation below, this channel might be closed
    370                 // or this thread might be interrupted.  We rely upon the
    371                 // implicit synchronization point in the kernel read() call to
    372                 // make sure that the right thing happens.  In either case the
    373                 // implCloseSelectableChannel method is ultimately invoked in
    374                 // some other thread, so there are three possibilities:
    375                 //
    376                 //   - implCloseSelectableChannel() invokes nd.preClose()
    377                 //     before this thread invokes read(), in which case the
    378                 //     read returns immediately with either EOF or an error,
    379                 //     the latter of which will cause an IOException to be
    380                 //     thrown.
    381                 //
    382                 //   - implCloseSelectableChannel() invokes nd.preClose() after
    383                 //     this thread is blocked in read().  On some operating
    384                 //     systems (e.g., Solaris and Windows) this causes the read
    385                 //     to return immediately with either EOF or an error
    386                 //     indication.
    387                 //
    388                 //   - implCloseSelectableChannel() invokes nd.preClose() after
    389                 //     this thread is blocked in read() but the operating
    390                 //     system (e.g., Linux) doesn't support preemptive close,
    391                 //     so implCloseSelectableChannel() proceeds to signal this
    392                 //     thread, thereby causing the read to return immediately
    393                 //     with IOStatus.INTERRUPTED.
    394                 //
    395                 // In all three cases the invocation of end() in the finally
    396                 // clause will notice that the channel has been closed and
    397                 // throw an appropriate exception (AsynchronousCloseException
    398                 // or ClosedByInterruptException) if necessary.
    399                 //
    400                 // *There is A fourth possibility. implCloseSelectableChannel()
    401                 // invokes nd.preClose(), signals reader/writer thred and quickly
    402                 // moves on to nd.close() in kill(), which does a real close.
    403                 // Then a third thread accepts a new connection, opens file or
    404                 // whatever that causes the released "fd" to be recycled. All
    405                 // above happens just between our last isOpen() check and the
    406                 // next kernel read reached, with the recycled "fd". The solution
    407                 // is to postpone the real kill() if there is a reader or/and
    408                 // writer thread(s) over there "waiting", leave the cleanup/kill
    409                 // to the reader or writer thread. (the preClose() still happens
    410                 // so the connection gets cut off as usual).
    411                 //
    412                 // For socket channels there is the additional wrinkle that
    413                 // asynchronous shutdown works much like asynchronous close,
    414                 // except that the channel is shutdown rather than completely
    415                 // closed.  This is analogous to the first two cases above,
    416                 // except that the shutdown operation plays the role of
    417                 // nd.preClose().
    418                 for (;;) {
    419                     n = IOUtil.read(fd, buf, -1, nd);
    420                     if ((n == IOStatus.INTERRUPTED) && isOpen()) {
    421                         // The system call was interrupted but the channel
    422                         // is still open, so retry
    423                         continue;
    424                     }
    425                     return IOStatus.normalize(n);
    426                 }
    427 
    428             } finally {
    429                 readerCleanup();        // Clear reader thread
    430                 // The end method, which is defined in our superclass
    431                 // AbstractInterruptibleChannel, resets the interruption
    432                 // machinery.  If its argument is true then it returns
    433                 // normally; otherwise it checks the interrupt and open state
    434                 // of this channel and throws an appropriate exception if
    435                 // necessary.
    436                 //
    437                 // So, if we actually managed to do any I/O in the above try
    438                 // block then we pass true to the end method.  We also pass
    439                 // true if the channel was in non-blocking mode when the I/O
    440                 // operation was initiated but no data could be transferred;
    441                 // this prevents spurious exceptions from being thrown in the
    442                 // rare event that a channel is closed or a thread is
    443                 // interrupted at the exact moment that a non-blocking I/O
    444                 // request is made.
    445                 //
    446                 end(n > 0 || (n == IOStatus.UNAVAILABLE));
    447 
    448                 // Extra case for socket channels: Asynchronous shutdown
    449                 //
    450                 synchronized (stateLock) {
    451                     if ((n <= 0) && (!isInputOpen))
    452                         return IOStatus.EOF;
    453                 }
    454 
    455                 assert IOStatus.check(n);
    456 
    457             }
    458         }
    459     }
    460 
    461     public long read(ByteBuffer[] dsts, int offset, int length)
    462         throws IOException
    463     {
    464         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
    465             throw new IndexOutOfBoundsException();
    466         synchronized (readLock) {
    467             if (!ensureReadOpen())
    468                 return -1;
    469             long n = 0;
    470             try {
    471                 begin();
    472                 synchronized (stateLock) {
    473                     if (!isOpen())
    474                         return 0;
    475                     readerThread = NativeThread.current();
    476                 }
    477 
    478                 for (;;) {
    479                     n = IOUtil.read(fd, dsts, offset, length, nd);
    480                     if ((n == IOStatus.INTERRUPTED) && isOpen())
    481                         continue;
    482                     return IOStatus.normalize(n);
    483                 }
    484             } finally {
    485                 readerCleanup();
    486                 end(n > 0 || (n == IOStatus.UNAVAILABLE));
    487                 synchronized (stateLock) {
    488                     if ((n <= 0) && (!isInputOpen))
    489                         return IOStatus.EOF;
    490                 }
    491                 assert IOStatus.check(n);
    492             }
    493         }
    494     }
    495 
    496     public int write(ByteBuffer buf) throws IOException {
    497         if (buf == null)
    498             throw new NullPointerException();
    499         synchronized (writeLock) {
    500             ensureWriteOpen();
    501             int n = 0;
    502             try {
    503                 begin();
    504                 synchronized (stateLock) {
    505                     if (!isOpen())
    506                         return 0;
    507                     writerThread = NativeThread.current();
    508                 }
    509                 for (;;) {
    510                     n = IOUtil.write(fd, buf, -1, nd);
    511                     if ((n == IOStatus.INTERRUPTED) && isOpen())
    512                         continue;
    513                     return IOStatus.normalize(n);
    514                 }
    515             } finally {
    516                 writerCleanup();
    517                 end(n > 0 || (n == IOStatus.UNAVAILABLE));
    518                 synchronized (stateLock) {
    519                     if ((n <= 0) && (!isOutputOpen))
    520                         throw new AsynchronousCloseException();
    521                 }
    522                 assert IOStatus.check(n);
    523             }
    524         }
    525     }
    526 
    527     public long write(ByteBuffer[] srcs, int offset, int length)
    528         throws IOException
    529     {
    530         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
    531             throw new IndexOutOfBoundsException();
    532         synchronized (writeLock) {
    533             ensureWriteOpen();
    534             long n = 0;
    535             try {
    536                 begin();
    537                 synchronized (stateLock) {
    538                     if (!isOpen())
    539                         return 0;
    540                     writerThread = NativeThread.current();
    541                 }
    542                 for (;;) {
    543                     n = IOUtil.write(fd, srcs, offset, length, nd);
    544                     if ((n == IOStatus.INTERRUPTED) && isOpen())
    545                         continue;
    546                     return IOStatus.normalize(n);
    547                 }
    548             } finally {
    549                 writerCleanup();
    550                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
    551                 synchronized (stateLock) {
    552                     if ((n <= 0) && (!isOutputOpen))
    553                         throw new AsynchronousCloseException();
    554                 }
    555                 assert IOStatus.check(n);
    556             }
    557         }
    558     }
    559 
    560     // package-private
    561     int sendOutOfBandData(byte b) throws IOException {
    562         synchronized (writeLock) {
    563             ensureWriteOpen();
    564             int n = 0;
    565             try {
    566                 begin();
    567                 synchronized (stateLock) {
    568                     if (!isOpen())
    569                         return 0;
    570                     writerThread = NativeThread.current();
    571                 }
    572                 for (;;) {
    573                     n = sendOutOfBandData(fd, b);
    574                     if ((n == IOStatus.INTERRUPTED) && isOpen())
    575                         continue;
    576                     return IOStatus.normalize(n);
    577                 }
    578             } finally {
    579                 writerCleanup();
    580                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
    581                 synchronized (stateLock) {
    582                     if ((n <= 0) && (!isOutputOpen))
    583                         throw new AsynchronousCloseException();
    584                 }
    585                 assert IOStatus.check(n);
    586             }
    587         }
    588     }
    589 
    590     protected void implConfigureBlocking(boolean block) throws IOException {
    591         IOUtil.configureBlocking(fd, block);
    592     }
    593 
    594     public InetSocketAddress localAddress() {
    595         synchronized (stateLock) {
    596             return localAddress;
    597         }
    598     }
    599 
    600     public SocketAddress remoteAddress() {
    601         synchronized (stateLock) {
    602             return remoteAddress;
    603         }
    604     }
    605 
    606     @Override
    607     public SocketChannel bind(SocketAddress local) throws IOException {
    608         synchronized (readLock) {
    609             synchronized (writeLock) {
    610                 synchronized (stateLock) {
    611                     if (!isOpen())
    612                         throw new ClosedChannelException();
    613                     if (state == ST_PENDING)
    614                         throw new ConnectionPendingException();
    615                     if (localAddress != null)
    616                         throw new AlreadyBoundException();
    617                     InetSocketAddress isa = (local == null) ?
    618                         new InetSocketAddress(0) : Net.checkAddress(local);
    619                     SecurityManager sm = System.getSecurityManager();
    620                     if (sm != null) {
    621                         sm.checkListen(isa.getPort());
    622                     }
    623                     NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
    624                     Net.bind(fd, isa.getAddress(), isa.getPort());
    625                     localAddress = Net.localAddress(fd);
    626                 }
    627             }
    628         }
    629         return this;
    630     }
    631 
    632     public boolean isConnected() {
    633         synchronized (stateLock) {
    634             return (state == ST_CONNECTED);
    635         }
    636     }
    637 
    638     public boolean isConnectionPending() {
    639         synchronized (stateLock) {
    640             return (state == ST_PENDING);
    641         }
    642     }
    643 
    644     void ensureOpenAndUnconnected() throws IOException { // package-private
    645         synchronized (stateLock) {
    646             if (!isOpen())
    647                 throw new ClosedChannelException();
    648             if (state == ST_CONNECTED)
    649                 throw new AlreadyConnectedException();
    650             if (state == ST_PENDING)
    651                 throw new ConnectionPendingException();
    652         }
    653     }
    654 
    655     public boolean connect(SocketAddress sa) throws IOException {
    656         int localPort = 0;
    657 
    658         synchronized (readLock) {
    659             synchronized (writeLock) {
    660                 ensureOpenAndUnconnected();
    661                 InetSocketAddress isa = Net.checkAddress(sa);
    662                 SecurityManager sm = System.getSecurityManager();
    663                 if (sm != null)
    664                     sm.checkConnect(isa.getAddress().getHostAddress(),
    665                                     isa.getPort());
    666                 synchronized (blockingLock()) {
    667                     int n = 0;
    668                     try {
    669                         try {
    670                             begin();
    671                             synchronized (stateLock) {
    672                                 if (!isOpen()) {
    673                                     return false;
    674                                 }
    675                                 // notify hook only if unbound
    676                                 if (localAddress == null) {
    677                                     NetHooks.beforeTcpConnect(fd,
    678                                                            isa.getAddress(),
    679                                                            isa.getPort());
    680                                 }
    681                                 readerThread = NativeThread.current();
    682                             }
    683                             for (;;) {
    684                                 InetAddress ia = isa.getAddress();
    685                                 if (ia.isAnyLocalAddress())
    686                                     ia = InetAddress.getLocalHost();
    687                                 n = Net.connect(fd,
    688                                                 ia,
    689                                                 isa.getPort());
    690                                 if (  (n == IOStatus.INTERRUPTED)
    691                                       && isOpen())
    692                                     continue;
    693                                 break;
    694                             }
    695 
    696                         } finally {
    697                             readerCleanup();
    698                             end((n > 0) || (n == IOStatus.UNAVAILABLE));
    699                             assert IOStatus.check(n);
    700                         }
    701                     } catch (IOException x) {
    702                         // If an exception was thrown, close the channel after
    703                         // invoking end() so as to avoid bogus
    704                         // AsynchronousCloseExceptions
    705                         close();
    706                         throw x;
    707                     }
    708                     synchronized (stateLock) {
    709                         remoteAddress = isa;
    710                         if (n > 0) {
    711 
    712                             // Connection succeeded; disallow further
    713                             // invocation
    714                             state = ST_CONNECTED;
    715                             if (isOpen())
    716                                 localAddress = Net.localAddress(fd);
    717                             return true;
    718                         }
    719                         // If nonblocking and no exception then connection
    720                         // pending; disallow another invocation
    721                         if (!isBlocking()) {
    722                             state = ST_PENDING;
    723                             if (isOpen()) {
    724                                 localAddress = Net.localAddress(fd);
    725                             }
    726                         }
    727                     }
    728                 }
    729                 return false;
    730             }
    731         }
    732     }
    733 
    734     public boolean finishConnect() throws IOException {
    735         synchronized (readLock) {
    736             synchronized (writeLock) {
    737                 synchronized (stateLock) {
    738                     if (!isOpen())
    739                         throw new ClosedChannelException();
    740                     if (state == ST_CONNECTED)
    741                         return true;
    742                     if (state != ST_PENDING)
    743                         throw new NoConnectionPendingException();
    744                 }
    745                 int n = 0;
    746                 try {
    747                     try {
    748                         begin();
    749                         synchronized (blockingLock()) {
    750                             synchronized (stateLock) {
    751                                 if (!isOpen()) {
    752                                     return false;
    753                                 }
    754                                 readerThread = NativeThread.current();
    755                             }
    756 
    757                             BlockGuard.getThreadPolicy().onNetwork();
    758                             if (!isBlocking()) {
    759                                 for (;;) {
    760                                     n = checkConnect(fd, false,
    761                                                      readyToConnect);
    762                                     if (  (n == IOStatus.INTERRUPTED)
    763                                           && isOpen())
    764                                         continue;
    765                                     break;
    766                                 }
    767                             } else {
    768                                 for (;;) {
    769                                     n = checkConnect(fd, true,
    770                                                      readyToConnect);
    771                                     if (n == 0) {
    772                                         // Loop in case of
    773                                         // spurious notifications
    774                                         continue;
    775                                     }
    776                                     if (  (n == IOStatus.INTERRUPTED)
    777                                           && isOpen())
    778                                         continue;
    779                                     break;
    780                                 }
    781                             }
    782                         }
    783                     } finally {
    784                         synchronized (stateLock) {
    785                             readerThread = 0;
    786                             if (state == ST_KILLPENDING) {
    787                                 kill();
    788                                 // poll()/getsockopt() does not report
    789                                 // error (throws exception, with n = 0)
    790                                 // on Linux platform after dup2 and
    791                                 // signal-wakeup. Force n to 0 so the
    792                                 // end() can throw appropriate exception
    793                                 n = 0;
    794                             }
    795                         }
    796                         end((n > 0) || (n == IOStatus.UNAVAILABLE));
    797                         assert IOStatus.check(n);
    798                     }
    799                 } catch (IOException x) {
    800                     // If an exception was thrown, close the channel after
    801                     // invoking end() so as to avoid bogus
    802                     // AsynchronousCloseExceptions
    803                     close();
    804                     throw x;
    805                 }
    806                 if (n > 0) {
    807                     synchronized (stateLock) {
    808                         state = ST_CONNECTED;
    809                         if (isOpen())
    810                             localAddress = Net.localAddress(fd);
    811                     }
    812                     return true;
    813                 }
    814                 return false;
    815             }
    816         }
    817     }
    818 
    819     @Override
    820     public SocketChannel shutdownInput() throws IOException {
    821         synchronized (stateLock) {
    822             if (!isOpen())
    823                 throw new ClosedChannelException();
    824             if (!isConnected())
    825                 throw new NotYetConnectedException();
    826             if (isInputOpen) {
    827                 Net.shutdown(fd, Net.SHUT_RD);
    828                 if (readerThread != 0)
    829                     NativeThread.signal(readerThread);
    830                 isInputOpen = false;
    831             }
    832             return this;
    833         }
    834     }
    835 
    836     @Override
    837     public SocketChannel shutdownOutput() throws IOException {
    838         synchronized (stateLock) {
    839             if (!isOpen())
    840                 throw new ClosedChannelException();
    841             if (!isConnected())
    842                 throw new NotYetConnectedException();
    843             if (isOutputOpen) {
    844                 Net.shutdown(fd, Net.SHUT_WR);
    845                 if (writerThread != 0)
    846                     NativeThread.signal(writerThread);
    847                 isOutputOpen = false;
    848             }
    849             return this;
    850         }
    851     }
    852 
    853     public boolean isInputOpen() {
    854         synchronized (stateLock) {
    855             return isInputOpen;
    856         }
    857     }
    858 
    859     public boolean isOutputOpen() {
    860         synchronized (stateLock) {
    861             return isOutputOpen;
    862         }
    863     }
    864 
    865     // AbstractInterruptibleChannel synchronizes invocations of this method
    866     // using AbstractInterruptibleChannel.closeLock, and also ensures that this
    867     // method is only ever invoked once.  Before we get to this method, isOpen
    868     // (which is volatile) will have been set to false.
    869     //
    870     protected void implCloseSelectableChannel() throws IOException {
    871         synchronized (stateLock) {
    872             isInputOpen = false;
    873             isOutputOpen = false;
    874 
    875             // Close the underlying file descriptor and dup it to a known fd
    876             // that's already closed.  This prevents other operations on this
    877             // channel from using the old fd, which might be recycled in the
    878             // meantime and allocated to an entirely different channel.
    879             //
    880             if (state != ST_KILLED) {
    881                 // Android-changed: Add CloseGuard support.
    882                 guard.close();
    883                 nd.preClose(fd);
    884             }
    885 
    886             // Signal native threads, if needed.  If a target thread is not
    887             // currently blocked in an I/O operation then no harm is done since
    888             // the signal handler doesn't actually do anything.
    889             //
    890             if (readerThread != 0)
    891                 NativeThread.signal(readerThread);
    892 
    893             if (writerThread != 0)
    894                 NativeThread.signal(writerThread);
    895 
    896             // If this channel is not registered then it's safe to close the fd
    897             // immediately since we know at this point that no thread is
    898             // blocked in an I/O operation upon the channel and, since the
    899             // channel is marked closed, no thread will start another such
    900             // operation.  If this channel is registered then we don't close
    901             // the fd since it might be in use by a selector.  In that case
    902             // closing this channel caused its keys to be cancelled, so the
    903             // last selector to deregister a key for this channel will invoke
    904             // kill() to close the fd.
    905             //
    906             if (!isRegistered())
    907                 kill();
    908         }
    909     }
    910 
    911     public void kill() throws IOException {
    912         synchronized (stateLock) {
    913             if (state == ST_KILLED)
    914                 return;
    915             if (state == ST_UNINITIALIZED) {
    916                 state = ST_KILLED;
    917                 return;
    918             }
    919             assert !isOpen() && !isRegistered();
    920 
    921             // Postpone the kill if there is a waiting reader
    922             // or writer thread. See the comments in read() for
    923             // more detailed explanation.
    924             if (readerThread == 0 && writerThread == 0) {
    925                 nd.close(fd);
    926                 state = ST_KILLED;
    927             } else {
    928                 state = ST_KILLPENDING;
    929             }
    930         }
    931     }
    932 
    933     protected void finalize() throws IOException {
    934         if (guard != null) {
    935             guard.warnIfOpen();
    936         }
    937         close();
    938     }
    939 
    940     /**
    941      * Translates native poll revent ops into a ready operation ops
    942      */
    943     public boolean translateReadyOps(int ops, int initialOps,
    944                                      SelectionKeyImpl sk) {
    945         int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
    946         int oldOps = sk.nioReadyOps();
    947         int newOps = initialOps;
    948 
    949         if ((ops & Net.POLLNVAL) != 0) {
    950             // This should only happen if this channel is pre-closed while a
    951             // selection operation is in progress
    952             // ## Throw an error if this channel has not been pre-closed
    953             return false;
    954         }
    955 
    956         if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
    957             newOps = intOps;
    958             sk.nioReadyOps(newOps);
    959             // No need to poll again in checkConnect,
    960             // the error will be detected there
    961             readyToConnect = true;
    962             return (newOps & ~oldOps) != 0;
    963         }
    964 
    965         if (((ops & Net.POLLIN) != 0) &&
    966             ((intOps & SelectionKey.OP_READ) != 0) &&
    967             (state == ST_CONNECTED))
    968             newOps |= SelectionKey.OP_READ;
    969 
    970         if (((ops & Net.POLLCONN) != 0) &&
    971             ((intOps & SelectionKey.OP_CONNECT) != 0) &&
    972             ((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
    973             newOps |= SelectionKey.OP_CONNECT;
    974             readyToConnect = true;
    975         }
    976 
    977         if (((ops & Net.POLLOUT) != 0) &&
    978             ((intOps & SelectionKey.OP_WRITE) != 0) &&
    979             (state == ST_CONNECTED))
    980             newOps |= SelectionKey.OP_WRITE;
    981 
    982         sk.nioReadyOps(newOps);
    983         return (newOps & ~oldOps) != 0;
    984     }
    985 
    986     public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
    987         return translateReadyOps(ops, sk.nioReadyOps(), sk);
    988     }
    989 
    990     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
    991         return translateReadyOps(ops, 0, sk);
    992     }
    993 
    994     // package-private
    995     int poll(int events, long timeout) throws IOException {
    996         assert Thread.holdsLock(blockingLock()) && !isBlocking();
    997 
    998         synchronized (readLock) {
    999             int n = 0;
   1000             try {
   1001                 begin();
   1002                 synchronized (stateLock) {
   1003                     if (!isOpen())
   1004                         return 0;
   1005                     readerThread = NativeThread.current();
   1006                 }
   1007                 n = Net.poll(fd, events, timeout);
   1008             } finally {
   1009                 readerCleanup();
   1010                 end(n > 0);
   1011             }
   1012             return n;
   1013         }
   1014     }
   1015 
   1016     /**
   1017      * Translates an interest operation set into a native poll event set
   1018      */
   1019     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
   1020         int newOps = 0;
   1021         if ((ops & SelectionKey.OP_READ) != 0)
   1022             newOps |= Net.POLLIN;
   1023         if ((ops & SelectionKey.OP_WRITE) != 0)
   1024             newOps |= Net.POLLOUT;
   1025         if ((ops & SelectionKey.OP_CONNECT) != 0)
   1026             newOps |= Net.POLLCONN;
   1027         sk.selector.putEventOps(sk, newOps);
   1028     }
   1029 
   1030     public FileDescriptor getFD() {
   1031         return fd;
   1032     }
   1033 
   1034     public int getFDVal() {
   1035         return fdVal;
   1036     }
   1037 
   1038     @Override
   1039     public String toString() {
   1040         StringBuffer sb = new StringBuffer();
   1041         sb.append(this.getClass().getSuperclass().getName());
   1042         sb.append('[');
   1043         if (!isOpen())
   1044             sb.append("closed");
   1045         else {
   1046             synchronized (stateLock) {
   1047                 switch (state) {
   1048                 case ST_UNCONNECTED:
   1049                     sb.append("unconnected");
   1050                     break;
   1051                 case ST_PENDING:
   1052                     sb.append("connection-pending");
   1053                     break;
   1054                 case ST_CONNECTED:
   1055                     sb.append("connected");
   1056                     if (!isInputOpen)
   1057                         sb.append(" ishut");
   1058                     if (!isOutputOpen)
   1059                         sb.append(" oshut");
   1060                     break;
   1061                 }
   1062                 InetSocketAddress addr = localAddress();
   1063                 if (addr != null) {
   1064                     sb.append(" local=");
   1065                     sb.append(Net.getRevealedLocalAddressAsString(addr));
   1066                 }
   1067                 if (remoteAddress() != null) {
   1068                     sb.append(" remote=");
   1069                     sb.append(remoteAddress().toString());
   1070                 }
   1071             }
   1072         }
   1073         sb.append(']');
   1074         return sb.toString();
   1075     }
   1076 
   1077 
   1078     // -- Native methods --
   1079 
   1080     private static native int checkConnect(FileDescriptor fd,
   1081                                            boolean block, boolean ready)
   1082         throws IOException;
   1083 
   1084     private static native int sendOutOfBandData(FileDescriptor fd, byte data)
   1085         throws IOException;
   1086 
   1087     static {
   1088         nd = new SocketDispatcher();
   1089     }
   1090 
   1091 }
   1092