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