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