src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
branchunixdomainchannels
changeset 58801 119ac9128c1b
parent 55081 dd321e3596c0
child 58847 692de65ab293
equal deleted inserted replaced
58799:eb491334113f 58801:119ac9128c1b
    62 
    62 
    63 /**
    63 /**
    64  * An implementation of SocketChannels
    64  * An implementation of SocketChannels
    65  */
    65  */
    66 
    66 
    67 class SocketChannelImpl
    67 public abstract class SocketChannelImpl
    68     extends SocketChannel
    68     extends SocketChannel
    69     implements SelChImpl
    69     implements SelChImpl
    70 {
    70 {
    71     // Used to make native read and write calls
    71     // Used to make native read and write calls
    72     private static final NativeDispatcher nd = new SocketDispatcher();
    72     private static final NativeDispatcher nd = new SocketDispatcher();
    73 
    73 
    74     // Our file descriptor object
    74     // Our file descriptor object
    75     private final FileDescriptor fd;
    75     final FileDescriptor fd;
    76     private final int fdVal;
    76     private final int fdVal;
    77 
    77 
    78     // Lock held by current reading or connecting thread
    78     // Lock held by current reading or connecting thread
    79     private final ReentrantLock readLock = new ReentrantLock();
    79     final ReentrantLock readLock = new ReentrantLock();
    80 
    80 
    81     // Lock held by current writing or connecting thread
    81     // Lock held by current writing or connecting thread
    82     private final ReentrantLock writeLock = new ReentrantLock();
    82     final ReentrantLock writeLock = new ReentrantLock();
    83 
    83 
    84     // Lock held by any thread that modifies the state fields declared below
    84     // Lock held by any thread that modifies the state fields declared below
    85     // DO NOT invoke a blocking I/O operation while holding this lock!
    85     // DO NOT invoke a blocking I/O operation while holding this lock!
    86     private final Object stateLock = new Object();
    86     final Object stateLock = new Object();
    87 
    87 
    88     // Input/Output closed
    88     // Input/Output closed
    89     private volatile boolean isInputClosed;
    89     volatile boolean isInputClosed;
    90     private volatile boolean isOutputClosed;
    90     volatile boolean isOutputClosed;
    91 
    91 
    92     // Connection reset protected by readLock
    92     // Connection reset protected by readLock
    93     private boolean connectionReset;
    93     private boolean connectionReset;
    94 
    94 
    95     // -- The following fields are protected by stateLock
    95     // -- The following fields are protected by stateLock
    96 
    96 
    97     // set true when exclusive binding is on and SO_REUSEADDR is emulated
       
    98     private boolean isReuseAddress;
       
    99 
       
   100     // State, increases monotonically
    97     // State, increases monotonically
   101     private static final int ST_UNCONNECTED = 0;
    98     static final int ST_UNCONNECTED = 0;
   102     private static final int ST_CONNECTIONPENDING = 1;
    99     static final int ST_CONNECTIONPENDING = 1;
   103     private static final int ST_CONNECTED = 2;
   100     static final int ST_CONNECTED = 2;
   104     private static final int ST_CLOSING = 3;
   101     static final int ST_CLOSING = 3;
   105     private static final int ST_CLOSED = 4;
   102     static final int ST_CLOSED = 4;
   106     private volatile int state;  // need stateLock to change
   103     volatile int state;  // need stateLock to change
   107 
   104 
   108     // IDs of native threads doing reads and writes, for signalling
   105     // IDs of native threads doing reads and writes, for signalling
   109     private long readerThread;
   106     private long readerThread;
   110     private long writerThread;
   107     private long writerThread;
   111 
   108 
   112     // Binding
   109     // Binding
   113     private InetSocketAddress localAddress;
   110     SocketAddress localAddress;
   114     private InetSocketAddress remoteAddress;
   111     SocketAddress remoteAddress;
   115 
   112 
   116     // Socket adaptor, created on demand
   113     // Socket adaptor, created on demand
   117     private Socket socket;
   114     Socket socket;
   118 
   115 
   119     // -- End of fields protected by stateLock
   116     // -- End of fields protected by stateLock
   120 
   117 
   121 
   118 
   122     // Constructor for normal connecting sockets
   119     // Constructor for normal connecting sockets
   123     //
   120     //
   124     SocketChannelImpl(SelectorProvider sp) throws IOException {
   121     public SocketChannelImpl(SelectorProvider sp) throws IOException {
   125         super(sp);
   122         super(sp);
   126         this.fd = Net.socket(true);
   123         this.fd = Net.socket(true);
   127         this.fdVal = IOUtil.fdVal(fd);
   124         this.fdVal = IOUtil.fdVal(fd);
   128     }
   125     }
   129 
   126 
   130     SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
   127     public SocketChannelImpl(SelectorProvider sp, FileDescriptor fd)
   131         throws IOException
   128         throws IOException
   132     {
   129     {
   133         super(sp);
   130         super(sp);
   134         this.fd = fd;
   131         this.fd = fd;
   135         this.fdVal = IOUtil.fdVal(fd);
   132         this.fdVal = IOUtil.fdVal(fd);
   136         if (bound) {
       
   137             synchronized (stateLock) {
       
   138                 this.localAddress = Net.localAddress(fd);
       
   139             }
       
   140         }
       
   141     }
       
   142 
       
   143     // Constructor for sockets obtained from server sockets
       
   144     //
       
   145     SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, InetSocketAddress isa)
       
   146         throws IOException
       
   147     {
       
   148         super(sp);
       
   149         this.fd = fd;
       
   150         this.fdVal = IOUtil.fdVal(fd);
       
   151         synchronized (stateLock) {
       
   152             this.localAddress = Net.localAddress(fd);
       
   153             this.remoteAddress = isa;
       
   154             this.state = ST_CONNECTED;
       
   155         }
       
   156     }
   133     }
   157 
   134 
   158     /**
   135     /**
   159      * Checks that the channel is open.
   136      * Checks that the channel is open.
   160      *
   137      *
   161      * @throws ClosedChannelException if channel is closed (or closing)
   138      * @throws ClosedChannelException if channel is closed (or closing)
   162      */
   139      */
   163     private void ensureOpen() throws ClosedChannelException {
   140     void ensureOpen() throws ClosedChannelException {
   164         if (!isOpen())
   141         if (!isOpen())
   165             throw new ClosedChannelException();
   142             throw new ClosedChannelException();
   166     }
   143     }
   167 
   144 
   168     /**
   145     /**
   182         if (state < ST_CONNECTED) {
   159         if (state < ST_CONNECTED) {
   183             throw new NotYetConnectedException();
   160             throw new NotYetConnectedException();
   184         } else if (state > ST_CONNECTED) {
   161         } else if (state > ST_CONNECTED) {
   185             throw new ClosedChannelException();
   162             throw new ClosedChannelException();
   186         }
   163         }
   187     }
       
   188 
       
   189     @Override
       
   190     public Socket socket() {
       
   191         synchronized (stateLock) {
       
   192             if (socket == null)
       
   193                 socket = SocketAdaptor.create(this);
       
   194             return socket;
       
   195         }
       
   196     }
       
   197 
       
   198     @Override
       
   199     public SocketAddress getLocalAddress() throws IOException {
       
   200         synchronized (stateLock) {
       
   201             ensureOpen();
       
   202             return Net.getRevealedLocalAddress(localAddress);
       
   203         }
       
   204     }
       
   205 
       
   206     @Override
       
   207     public SocketAddress getRemoteAddress() throws IOException {
       
   208         synchronized (stateLock) {
       
   209             ensureOpen();
       
   210             return remoteAddress;
       
   211         }
       
   212     }
       
   213 
       
   214     @Override
       
   215     public <T> SocketChannel setOption(SocketOption<T> name, T value)
       
   216         throws IOException
       
   217     {
       
   218         Objects.requireNonNull(name);
       
   219         if (!supportedOptions().contains(name))
       
   220             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   221         if (!name.type().isInstance(value))
       
   222             throw new IllegalArgumentException("Invalid value '" + value + "'");
       
   223 
       
   224         synchronized (stateLock) {
       
   225             ensureOpen();
       
   226 
       
   227             if (name == StandardSocketOptions.IP_TOS) {
       
   228                 ProtocolFamily family = Net.isIPv6Available() ?
       
   229                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
       
   230                 Net.setSocketOption(fd, family, name, value);
       
   231                 return this;
       
   232             }
       
   233 
       
   234             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
       
   235                 // SO_REUSEADDR emulated when using exclusive bind
       
   236                 isReuseAddress = (Boolean)value;
       
   237                 return this;
       
   238             }
       
   239 
       
   240             // no options that require special handling
       
   241             Net.setSocketOption(fd, name, value);
       
   242             return this;
       
   243         }
       
   244     }
       
   245 
       
   246     @Override
       
   247     @SuppressWarnings("unchecked")
       
   248     public <T> T getOption(SocketOption<T> name)
       
   249         throws IOException
       
   250     {
       
   251         Objects.requireNonNull(name);
       
   252         if (!supportedOptions().contains(name))
       
   253             throw new UnsupportedOperationException("'" + name + "' not supported");
       
   254 
       
   255         synchronized (stateLock) {
       
   256             ensureOpen();
       
   257 
       
   258             if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
       
   259                 // SO_REUSEADDR emulated when using exclusive bind
       
   260                 return (T)Boolean.valueOf(isReuseAddress);
       
   261             }
       
   262 
       
   263             // special handling for IP_TOS: always return 0 when IPv6
       
   264             if (name == StandardSocketOptions.IP_TOS) {
       
   265                 ProtocolFamily family = Net.isIPv6Available() ?
       
   266                     StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
       
   267                 return (T) Net.getSocketOption(fd, family, name);
       
   268             }
       
   269 
       
   270             // no options that require special handling
       
   271             return (T) Net.getSocketOption(fd, name);
       
   272         }
       
   273     }
       
   274 
       
   275     private static class DefaultOptionsHolder {
       
   276         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
       
   277 
       
   278         private static Set<SocketOption<?>> defaultOptions() {
       
   279             HashSet<SocketOption<?>> set = new HashSet<>();
       
   280             set.add(StandardSocketOptions.SO_SNDBUF);
       
   281             set.add(StandardSocketOptions.SO_RCVBUF);
       
   282             set.add(StandardSocketOptions.SO_KEEPALIVE);
       
   283             set.add(StandardSocketOptions.SO_REUSEADDR);
       
   284             if (Net.isReusePortAvailable()) {
       
   285                 set.add(StandardSocketOptions.SO_REUSEPORT);
       
   286             }
       
   287             set.add(StandardSocketOptions.SO_LINGER);
       
   288             set.add(StandardSocketOptions.TCP_NODELAY);
       
   289             // additional options required by socket adaptor
       
   290             set.add(StandardSocketOptions.IP_TOS);
       
   291             set.add(ExtendedSocketOption.SO_OOBINLINE);
       
   292             set.addAll(ExtendedSocketOptions.clientSocketOptions());
       
   293             return Collections.unmodifiableSet(set);
       
   294         }
       
   295     }
       
   296 
       
   297     @Override
       
   298     public final Set<SocketOption<?>> supportedOptions() {
       
   299         return DefaultOptionsHolder.defaultOptions;
       
   300     }
   164     }
   301 
   165 
   302     /**
   166     /**
   303      * Marks the beginning of a read operation that might block.
   167      * Marks the beginning of a read operation that might block.
   304      *
   168      *
   431      * Marks the beginning of a write operation that might block.
   295      * Marks the beginning of a write operation that might block.
   432      *
   296      *
   433      * @throws ClosedChannelException if the channel is closed or output shutdown
   297      * @throws ClosedChannelException if the channel is closed or output shutdown
   434      * @throws NotYetConnectedException if the channel is not yet connected
   298      * @throws NotYetConnectedException if the channel is not yet connected
   435      */
   299      */
   436     private void beginWrite(boolean blocking) throws ClosedChannelException {
   300     void beginWrite(boolean blocking) throws ClosedChannelException {
   437         if (blocking) {
   301         if (blocking) {
   438             // set hook for Thread.interrupt
   302             // set hook for Thread.interrupt
   439             begin();
   303             begin();
   440 
   304 
   441             synchronized (stateLock) {
   305             synchronized (stateLock) {
   454      * Marks the end of a write operation that may have blocked.
   318      * Marks the end of a write operation that may have blocked.
   455      *
   319      *
   456      * @throws AsynchronousCloseException if the channel was closed due to this
   320      * @throws AsynchronousCloseException if the channel was closed due to this
   457      * thread being interrupted on a blocking write operation.
   321      * thread being interrupted on a blocking write operation.
   458      */
   322      */
   459     private void endWrite(boolean blocking, boolean completed)
   323     void endWrite(boolean blocking, boolean completed)
   460         throws AsynchronousCloseException
   324         throws AsynchronousCloseException
   461     {
   325     {
   462         if (blocking) {
   326         if (blocking) {
   463             synchronized (stateLock) {
   327             synchronized (stateLock) {
   464                 writerThread = 0;
   328                 writerThread = 0;
   527         } finally {
   391         } finally {
   528             writeLock.unlock();
   392             writeLock.unlock();
   529         }
   393         }
   530     }
   394     }
   531 
   395 
   532     /**
       
   533      * Writes a byte of out of band data.
       
   534      */
       
   535     int sendOutOfBandData(byte b) throws IOException {
       
   536         writeLock.lock();
       
   537         try {
       
   538             boolean blocking = isBlocking();
       
   539             int n = 0;
       
   540             try {
       
   541                 beginWrite(blocking);
       
   542                 if (blocking) {
       
   543                     do {
       
   544                         n = Net.sendOOB(fd, b);
       
   545                     } while (n == IOStatus.INTERRUPTED && isOpen());
       
   546                 } else {
       
   547                     n = Net.sendOOB(fd, b);
       
   548                 }
       
   549             } finally {
       
   550                 endWrite(blocking, n > 0);
       
   551                 if (n <= 0 && isOutputClosed)
       
   552                     throw new AsynchronousCloseException();
       
   553             }
       
   554             return IOStatus.normalize(n);
       
   555         } finally {
       
   556             writeLock.unlock();
       
   557         }
       
   558     }
       
   559 
       
   560     @Override
   396     @Override
   561     protected void implConfigureBlocking(boolean block) throws IOException {
   397     protected void implConfigureBlocking(boolean block) throws IOException {
   562         readLock.lock();
   398         readLock.lock();
   563         try {
   399         try {
   564             writeLock.lock();
   400             writeLock.lock();
   584     }
   420     }
   585 
   421 
   586     /**
   422     /**
   587      * Returns the local address, or null if not bound
   423      * Returns the local address, or null if not bound
   588      */
   424      */
   589     InetSocketAddress localAddress() {
   425     SocketAddress localAddress() {
   590         synchronized (stateLock) {
   426         synchronized (stateLock) {
   591             return localAddress;
   427             return localAddress;
   592         }
   428         }
   593     }
   429     }
   594 
   430 
   595     /**
   431     /**
   596      * Returns the remote address, or null if not connected
   432      * Returns the remote address, or null if not connected
   597      */
   433      */
   598     InetSocketAddress remoteAddress() {
   434     SocketAddress remoteAddress() {
   599         synchronized (stateLock) {
   435         synchronized (stateLock) {
   600             return remoteAddress;
   436             return remoteAddress;
   601         }
   437         }
   602     }
       
   603 
       
   604     @Override
       
   605     public SocketChannel bind(SocketAddress local) throws IOException {
       
   606         readLock.lock();
       
   607         try {
       
   608             writeLock.lock();
       
   609             try {
       
   610                 synchronized (stateLock) {
       
   611                     ensureOpen();
       
   612                     if (state == ST_CONNECTIONPENDING)
       
   613                         throw new ConnectionPendingException();
       
   614                     if (localAddress != null)
       
   615                         throw new AlreadyBoundException();
       
   616                     InetSocketAddress isa = (local == null) ?
       
   617                         new InetSocketAddress(0) : Net.checkAddress(local);
       
   618                     SecurityManager sm = System.getSecurityManager();
       
   619                     if (sm != null) {
       
   620                         sm.checkListen(isa.getPort());
       
   621                     }
       
   622                     NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
       
   623                     Net.bind(fd, isa.getAddress(), isa.getPort());
       
   624                     localAddress = Net.localAddress(fd);
       
   625                 }
       
   626             } finally {
       
   627                 writeLock.unlock();
       
   628             }
       
   629         } finally {
       
   630             readLock.unlock();
       
   631         }
       
   632         return this;
       
   633     }
   438     }
   634 
   439 
   635     @Override
   440     @Override
   636     public boolean isConnected() {
   441     public boolean isConnected() {
   637         return (state == ST_CONNECTED);
   442         return (state == ST_CONNECTED);
   649      * @throws ClosedChannelException if the channel is closed
   454      * @throws ClosedChannelException if the channel is closed
   650      * @throws AlreadyConnectedException if already connected
   455      * @throws AlreadyConnectedException if already connected
   651      * @throws ConnectionPendingException is a connection is pending
   456      * @throws ConnectionPendingException is a connection is pending
   652      * @throws IOException if the pre-connect hook fails
   457      * @throws IOException if the pre-connect hook fails
   653      */
   458      */
   654     private void beginConnect(boolean blocking, InetSocketAddress isa)
   459     private void beginConnect(boolean blocking, SocketAddress sa)
   655         throws IOException
   460         throws IOException
   656     {
   461     {
   657         if (blocking) {
   462         if (blocking) {
   658             // set hook for Thread.interrupt
   463             // set hook for Thread.interrupt
   659             begin();
   464             begin();
   666             if (state == ST_CONNECTIONPENDING)
   471             if (state == ST_CONNECTIONPENDING)
   667                 throw new ConnectionPendingException();
   472                 throw new ConnectionPendingException();
   668             assert state == ST_UNCONNECTED;
   473             assert state == ST_UNCONNECTED;
   669             this.state = ST_CONNECTIONPENDING;
   474             this.state = ST_CONNECTIONPENDING;
   670 
   475 
   671             if (localAddress == null)
   476             if (localAddress == null && sa instanceof InetSocketAddress) {
       
   477                 InetSocketAddress isa = (InetSocketAddress)sa;
   672                 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
   478                 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
   673             remoteAddress = isa;
   479             }
       
   480             remoteAddress = sa;
   674 
   481 
   675             if (blocking) {
   482             if (blocking) {
   676                 // record thread so it can be signalled if needed
   483                 // record thread so it can be signalled if needed
   677                 readerThread = NativeThread.current();
   484                 readerThread = NativeThread.current();
   678             }
   485             }
   684      *
   491      *
   685      * @throws AsynchronousCloseException if the channel was closed due to this
   492      * @throws AsynchronousCloseException if the channel was closed due to this
   686      * thread being interrupted on a blocking connect operation.
   493      * thread being interrupted on a blocking connect operation.
   687      * @throws IOException if completed and unable to obtain the local address
   494      * @throws IOException if completed and unable to obtain the local address
   688      */
   495      */
   689     private void endConnect(boolean blocking, boolean completed)
   496     void endConnect(boolean blocking, boolean completed)
   690         throws IOException
   497         throws IOException
   691     {
   498     {
   692         endRead(blocking, completed);
   499         endRead(blocking, completed);
   693 
   500 
   694         if (completed) {
   501         if (completed) {
   695             synchronized (stateLock) {
   502             synchronized (stateLock) {
   696                 if (state == ST_CONNECTIONPENDING) {
   503                 if (state == ST_CONNECTIONPENDING) {
   697                     localAddress = Net.localAddress(fd);
   504                     localAddress = localAddressImpl(fd);
   698                     state = ST_CONNECTED;
   505                     state = ST_CONNECTED;
   699                 }
   506                 }
   700             }
   507             }
   701         }
   508         }
   702     }
   509     }
   703 
   510 
   704     /**
   511     /**
   705      * Checks the remote address to which this channel is to be connected.
   512      * Checks the remote address to which this channel is to be connected.
   706      */
   513      */
   707     private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {
   514     abstract SocketAddress checkRemote(SocketAddress sa) throws IOException;
   708         InetSocketAddress isa = Net.checkAddress(sa);
   515 
   709         SecurityManager sm = System.getSecurityManager();
   516     abstract int connectImpl(FileDescriptor fd,SocketAddress sa) throws IOException;
   710         if (sm != null) {
       
   711             sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
       
   712         }
       
   713         if (isa.getAddress().isAnyLocalAddress()) {
       
   714             return new InetSocketAddress(InetAddress.getLocalHost(), isa.getPort());
       
   715         } else {
       
   716             return isa;
       
   717         }
       
   718     }
       
   719 
   517 
   720     @Override
   518     @Override
   721     public boolean connect(SocketAddress remote) throws IOException {
   519     public boolean connect(SocketAddress remote) throws IOException {
   722         InetSocketAddress isa = checkRemote(remote);
   520         SocketAddress sa = checkRemote(remote);
   723         try {
   521         try {
   724             readLock.lock();
   522             readLock.lock();
   725             try {
   523             try {
   726                 writeLock.lock();
   524                 writeLock.lock();
   727                 try {
   525                 try {
   728                     boolean blocking = isBlocking();
   526                     boolean blocking = isBlocking();
   729                     boolean connected = false;
   527                     boolean connected = false;
   730                     try {
   528                     try {
   731                         beginConnect(blocking, isa);
   529                         beginConnect(blocking, sa);
   732                         int n = Net.connect(fd, isa.getAddress(), isa.getPort());
   530                         int n = connectImpl(fd, sa);
   733                         if (n > 0) {
   531                         if (n > 0) {
   734                             connected = true;
   532                             connected = true;
   735                         } else if (blocking) {
   533                         } else if (blocking) {
   736                             assert IOStatus.okayToRetry(n);
   534                             assert IOStatus.okayToRetry(n);
   737                             boolean polled = false;
   535                             boolean polled = false;
   752                 readLock.unlock();
   550                 readLock.unlock();
   753             }
   551             }
   754         } catch (IOException ioe) {
   552         } catch (IOException ioe) {
   755             // connect failed, close the channel
   553             // connect failed, close the channel
   756             close();
   554             close();
   757             throw SocketExceptions.of(ioe, isa);
   555             throw SocketExceptions.of(ioe, sa);
   758         }
   556         }
   759     }
   557     }
   760 
   558 
   761     /**
   559     /**
   762      * Marks the beginning of a finishConnect operation that might block.
   560      * Marks the beginning of a finishConnect operation that might block.
   778                 readerThread = NativeThread.current();
   576                 readerThread = NativeThread.current();
   779             }
   577             }
   780         }
   578         }
   781     }
   579     }
   782 
   580 
       
   581     abstract SocketAddress localAddressImpl(FileDescriptor fd)
       
   582         throws IOException;
       
   583 
   783     /**
   584     /**
   784      * Marks the end of a finishConnect operation that may have blocked.
   585      * Marks the end of a finishConnect operation that may have blocked.
   785      *
   586      *
   786      * @throws AsynchronousCloseException if the channel was closed due to this
   587      * @throws AsynchronousCloseException if the channel was closed due to this
   787      * thread being interrupted on a blocking connect operation.
   588      * thread being interrupted on a blocking connect operation.
   793         endRead(blocking, completed);
   594         endRead(blocking, completed);
   794 
   595 
   795         if (completed) {
   596         if (completed) {
   796             synchronized (stateLock) {
   597             synchronized (stateLock) {
   797                 if (state == ST_CONNECTIONPENDING) {
   598                 if (state == ST_CONNECTIONPENDING) {
   798                     localAddress = Net.localAddress(fd);
   599                     localAddress = localAddressImpl(fd);
   799                     state = ST_CONNECTED;
   600                     state = ST_CONNECTED;
   800                 }
   601                 }
   801             }
   602             }
   802         }
   603         }
   803     }
   604     }
   962                 tryFinishClose();
   763                 tryFinishClose();
   963             }
   764             }
   964         }
   765         }
   965     }
   766     }
   966 
   767 
       
   768     /**
       
   769      * Package private version called from InheritedChannel
       
   770      */
       
   771     void localImplCloseSelectableChannel() throws IOException {
       
   772         implCloseSelectableChannel();
       
   773     }
       
   774 
   967     @Override
   775     @Override
   968     public SocketChannel shutdownInput() throws IOException {
   776     public SocketChannel shutdownInput() throws IOException {
   969         synchronized (stateLock) {
   777         synchronized (stateLock) {
   970             ensureOpen();
   778             ensureOpen();
   971             if (!isConnected())
   779             if (!isConnected())
  1032      *
   840      *
  1033      * @throws IllegalBlockingModeException if the channel is non-blocking
   841      * @throws IllegalBlockingModeException if the channel is non-blocking
  1034      * @throws SocketTimeoutException if the read timeout elapses
   842      * @throws SocketTimeoutException if the read timeout elapses
  1035      */
   843      */
  1036     void blockingConnect(SocketAddress remote, long nanos) throws IOException {
   844     void blockingConnect(SocketAddress remote, long nanos) throws IOException {
  1037         InetSocketAddress isa = checkRemote(remote);
   845         SocketAddress sa = checkRemote(remote);
  1038         try {
   846         try {
  1039             readLock.lock();
   847             readLock.lock();
  1040             try {
   848             try {
  1041                 writeLock.lock();
   849                 writeLock.lock();
  1042                 try {
   850                 try {
  1043                     if (!isBlocking())
   851                     if (!isBlocking())
  1044                         throw new IllegalBlockingModeException();
   852                         throw new IllegalBlockingModeException();
  1045                     boolean connected = false;
   853                     boolean connected = false;
  1046                     try {
   854                     try {
  1047                         beginConnect(true, isa);
   855                         beginConnect(true, sa);
  1048                         // change socket to non-blocking
   856                         // change socket to non-blocking
  1049                         lockedConfigureBlocking(false);
   857                         lockedConfigureBlocking(false);
  1050                         try {
   858                         try {
  1051                             int n = Net.connect(fd, isa.getAddress(), isa.getPort());
   859                             int n = connectImpl(fd, sa);
  1052                             connected = (n > 0) ? true : finishTimedConnect(nanos);
   860                             connected = (n > 0) ? true : finishTimedConnect(nanos);
  1053                         } finally {
   861                         } finally {
  1054                             // restore socket to blocking mode
   862                             // restore socket to blocking mode
  1055                             lockedConfigureBlocking(true);
   863                             lockedConfigureBlocking(true);
  1056                         }
   864                         }
  1064                 readLock.unlock();
   872                 readLock.unlock();
  1065             }
   873             }
  1066         } catch (IOException ioe) {
   874         } catch (IOException ioe) {
  1067             // connect failed, close the channel
   875             // connect failed, close the channel
  1068             close();
   876             close();
  1069             throw SocketExceptions.of(ioe, isa);
   877             throw SocketExceptions.of(ioe, sa);
  1070         }
   878         }
  1071     }
   879     }
  1072 
   880 
  1073     /**
   881     /**
  1074      * Attempts to read bytes from the socket into the given byte array.
   882      * Attempts to read bytes from the socket into the given byte array.
  1306     }
  1114     }
  1307 
  1115 
  1308     public int getFDVal() {
  1116     public int getFDVal() {
  1309         return fdVal;
  1117         return fdVal;
  1310     }
  1118     }
       
  1119 
       
  1120     abstract String getRevealedLocalAddressAsString(SocketAddress sa);
  1311 
  1121 
  1312     @Override
  1122     @Override
  1313     public String toString() {
  1123     public String toString() {
  1314         StringBuilder sb = new StringBuilder();
  1124         StringBuilder sb = new StringBuilder();
  1315         sb.append(this.getClass().getSuperclass().getName());
  1125         sb.append(this.getClass().getSuperclass().getName());
  1331                         sb.append(" ishut");
  1141                         sb.append(" ishut");
  1332                     if (isOutputClosed)
  1142                     if (isOutputClosed)
  1333                         sb.append(" oshut");
  1143                         sb.append(" oshut");
  1334                     break;
  1144                     break;
  1335                 }
  1145                 }
  1336                 InetSocketAddress addr = localAddress();
  1146                 SocketAddress addr = localAddress();
  1337                 if (addr != null) {
  1147                 if (addr != null) {
  1338                     sb.append(" local=");
  1148                     sb.append(" local=");
  1339                     sb.append(Net.getRevealedLocalAddressAsString(addr));
  1149                     sb.append(getRevealedLocalAddressAsString(addr));
  1340                 }
  1150                 }
  1341                 if (remoteAddress() != null) {
  1151                 if (remoteAddress() != null) {
  1342                     sb.append(" remote=");
  1152                     sb.append(" remote=");
  1343                     sb.append(remoteAddress().toString());
  1153                     sb.append(remoteAddress().toString());
  1344                 }
  1154                 }