< prev index next >

src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java

Print this page
rev 55750 : UDS support, temporary commit


  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.SocketException;
  36 import java.net.SocketOption;
  37 import java.net.SocketTimeoutException;
  38 import java.net.StandardProtocolFamily;
  39 import java.net.StandardSocketOptions;

  40 import java.nio.ByteBuffer;
  41 import java.nio.channels.AlreadyBoundException;
  42 import java.nio.channels.AlreadyConnectedException;
  43 import java.nio.channels.AsynchronousCloseException;
  44 import java.nio.channels.ClosedChannelException;
  45 import java.nio.channels.ConnectionPendingException;
  46 import java.nio.channels.IllegalBlockingModeException;
  47 import java.nio.channels.NoConnectionPendingException;
  48 import java.nio.channels.NotYetConnectedException;
  49 import java.nio.channels.SelectionKey;
  50 import java.nio.channels.SocketChannel;
  51 import java.nio.channels.spi.SelectorProvider;
  52 import java.util.Collections;
  53 import java.util.HashSet;
  54 import java.util.Objects;
  55 import java.util.Set;
  56 import java.util.concurrent.locks.ReentrantLock;
  57 
  58 import sun.net.ConnectionResetException;
  59 import sun.net.NetHooks;


  93     private boolean connectionReset;
  94 
  95     // -- The following fields are protected by stateLock
  96 
  97     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  98     private boolean isReuseAddress;
  99 
 100     // State, increases monotonically
 101     private static final int ST_UNCONNECTED = 0;
 102     private static final int ST_CONNECTIONPENDING = 1;
 103     private static final int ST_CONNECTED = 2;
 104     private static final int ST_CLOSING = 3;
 105     private static final int ST_CLOSED = 4;
 106     private volatile int state;  // need stateLock to change
 107 
 108     // IDs of native threads doing reads and writes, for signalling
 109     private long readerThread;
 110     private long writerThread;
 111 
 112     // Binding
 113     private InetSocketAddress localAddress;
 114     private InetSocketAddress remoteAddress;
 115 
 116     // Socket adaptor, created on demand
 117     private Socket socket;
 118 
 119     // -- End of fields protected by stateLock
 120 





 121 
 122     // Constructor for normal connecting sockets
 123     //
 124     SocketChannelImpl(SelectorProvider sp) throws IOException {
 125         super(sp);
 126         this.fd = Net.socket(true);
 127         this.fdVal = IOUtil.fdVal(fd);
 128     }
 129 
 130     SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 131         throws IOException
 132     {
 133         super(sp);
 134         this.fd = fd;
 135         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     }
 157 
 158     /**
 159      * Checks that the channel is open.
 160      *
 161      * @throws ClosedChannelException if channel is closed (or closing)
 162      */
 163     private void ensureOpen() throws ClosedChannelException {
 164         if (!isOpen())
 165             throw new ClosedChannelException();
 166     }
 167 
 168     /**
 169      * Checks that the channel is open and connected.
 170      *
 171      * @apiNote This method uses the "state" field to check if the channel is
 172      * open. It should never be used in conjuncion with isOpen or ensureOpen


 182         if (state < ST_CONNECTED) {
 183             throw new NotYetConnectedException();
 184         } else if (state > ST_CONNECTED) {
 185             throw new ClosedChannelException();
 186         }
 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 + "'");


 571             readLock.unlock();
 572         }
 573     }
 574 
 575     /**
 576      * Adjust the blocking mode while holding the readLock or writeLock.
 577      */
 578     private void lockedConfigureBlocking(boolean block) throws IOException {
 579         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 580         synchronized (stateLock) {
 581             ensureOpen();
 582             IOUtil.configureBlocking(fd, block);
 583         }
 584     }
 585 
 586     /**
 587      * Returns the local address, or null if not bound
 588      */
 589     InetSocketAddress localAddress() {
 590         synchronized (stateLock) {
 591             return localAddress;
 592         }
 593     }
 594 
 595     /**
 596      * Returns the remote address, or null if not connected
 597      */
 598     InetSocketAddress remoteAddress() {
 599         synchronized (stateLock) {
 600             return remoteAddress;
 601         }
 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());


 663             int state = this.state;
 664             if (state == ST_CONNECTED)
 665                 throw new AlreadyConnectedException();
 666             if (state == ST_CONNECTIONPENDING)
 667                 throw new ConnectionPendingException();
 668             assert state == ST_UNCONNECTED;
 669             this.state = ST_CONNECTIONPENDING;
 670 
 671             if (localAddress == null)
 672                 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
 673             remoteAddress = isa;
 674 
 675             if (blocking) {
 676                 // record thread so it can be signalled if needed
 677                 readerThread = NativeThread.current();
 678             }
 679         }
 680     }
 681 
 682     /**

































 683      * Marks the end of a connect operation that may have blocked.
 684      *
 685      * @throws AsynchronousCloseException if the channel was closed due to this
 686      * thread being interrupted on a blocking connect operation.
 687      * @throws IOException if completed and unable to obtain the local address
 688      */
 689     private void endConnect(boolean blocking, boolean completed)
 690         throws IOException
 691     {
 692         endRead(blocking, completed);
 693 
 694         if (completed) {
 695             synchronized (stateLock) {
 696                 if (state == ST_CONNECTIONPENDING) {
 697                     localAddress = Net.localAddress(fd);
 698                     state = ST_CONNECTED;
 699                 }
 700             }
 701         }
 702     }
 703 
 704     /**
 705      * Checks the remote address to which this channel is to be connected.
 706      */
 707     private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {





 708         InetSocketAddress isa = Net.checkAddress(sa);
 709         SecurityManager sm = System.getSecurityManager();
 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 
 720     @Override
 721     public boolean connect(SocketAddress remote) throws IOException {
 722         InetSocketAddress isa = checkRemote(remote);
 723         try {
 724             readLock.lock();
 725             try {
 726                 writeLock.lock();
 727                 try {
 728                     boolean blocking = isBlocking();
 729                     boolean connected = false;
 730                     try {






 731                         beginConnect(blocking, isa);
 732                         int n = Net.connect(fd, isa.getAddress(), isa.getPort());

 733                         if (n > 0) {
 734                             connected = true;
 735                         } else if (blocking) {
 736                             assert IOStatus.okayToRetry(n);
 737                             boolean polled = false;
 738                             while (!polled && isOpen()) {
 739                                 park(Net.POLLOUT);
 740                                 polled = Net.pollConnectNow(fd);
 741                             }
 742                             connected = polled && isOpen();
 743                         }
 744                     } finally {
 745                         endConnect(blocking, connected);
 746                     }
 747                     return connected;
 748                 } finally {
 749                     writeLock.unlock();
 750                 }
 751             } finally {
 752                 readLock.unlock();
 753             }
 754         } catch (IOException ioe) {
 755             // connect failed, close the channel
 756             close();
 757             throw SocketExceptions.of(ioe, isa);
 758         }
 759     }
 760 
 761     /**
 762      * Marks the beginning of a finishConnect operation that might block.
 763      *
 764      * @throws ClosedChannelException if the channel is closed
 765      * @throws NoConnectionPendingException if no connection is pending
 766      */
 767     private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
 768         if (blocking) {
 769             // set hook for Thread.interrupt
 770             begin();
 771         }
 772         synchronized (stateLock) {
 773             ensureOpen();
 774             if (state != ST_CONNECTIONPENDING)
 775                 throw new NoConnectionPendingException();
 776             if (blocking) {
 777                 // record thread so it can be signalled if needed


1027     /**
1028      * Attempts to establish a connection to the given socket address with a
1029      * timeout. Closes the socket if connection cannot be established.
1030      *
1031      * @apiNote This method is for use by the socket adaptor.
1032      *
1033      * @throws IllegalBlockingModeException if the channel is non-blocking
1034      * @throws SocketTimeoutException if the read timeout elapses
1035      */
1036     void blockingConnect(SocketAddress remote, long nanos) throws IOException {
1037         InetSocketAddress isa = checkRemote(remote);
1038         try {
1039             readLock.lock();
1040             try {
1041                 writeLock.lock();
1042                 try {
1043                     if (!isBlocking())
1044                         throw new IllegalBlockingModeException();
1045                     boolean connected = false;
1046                     try {




1047                         beginConnect(true, isa);

1048                         // change socket to non-blocking
1049                         lockedConfigureBlocking(false);
1050                         try {
1051                             int n = Net.connect(fd, isa.getAddress(), isa.getPort());





1052                             connected = (n > 0) ? true : finishTimedConnect(nanos);
1053                         } finally {
1054                             // restore socket to blocking mode
1055                             lockedConfigureBlocking(true);
1056                         }
1057                     } finally {
1058                         endConnect(true, connected);
1059                     }
1060                 } finally {
1061                     writeLock.unlock();
1062                 }
1063             } finally {
1064                 readLock.unlock();
1065             }
1066         } catch (IOException ioe) {
1067             // connect failed, close the channel
1068             close();
1069             throw SocketExceptions.of(ioe, isa);
1070         }
1071     }




  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.SocketException;
  36 import java.net.SocketOption;
  37 import java.net.SocketTimeoutException;
  38 import java.net.StandardProtocolFamily;
  39 import java.net.StandardSocketOptions;
  40 import java.net.UnixSocketAddress;
  41 import java.nio.ByteBuffer;
  42 import java.nio.channels.AlreadyBoundException;
  43 import java.nio.channels.AlreadyConnectedException;
  44 import java.nio.channels.AsynchronousCloseException;
  45 import java.nio.channels.ClosedChannelException;
  46 import java.nio.channels.ConnectionPendingException;
  47 import java.nio.channels.IllegalBlockingModeException;
  48 import java.nio.channels.NoConnectionPendingException;
  49 import java.nio.channels.NotYetConnectedException;
  50 import java.nio.channels.SelectionKey;
  51 import java.nio.channels.SocketChannel;
  52 import java.nio.channels.spi.SelectorProvider;
  53 import java.util.Collections;
  54 import java.util.HashSet;
  55 import java.util.Objects;
  56 import java.util.Set;
  57 import java.util.concurrent.locks.ReentrantLock;
  58 
  59 import sun.net.ConnectionResetException;
  60 import sun.net.NetHooks;


  94     private boolean connectionReset;
  95 
  96     // -- The following fields are protected by stateLock
  97 
  98     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  99     private boolean isReuseAddress;
 100 
 101     // State, increases monotonically
 102     private static final int ST_UNCONNECTED = 0;
 103     private static final int ST_CONNECTIONPENDING = 1;
 104     private static final int ST_CONNECTED = 2;
 105     private static final int ST_CLOSING = 3;
 106     private static final int ST_CLOSED = 4;
 107     private volatile int state;  // need stateLock to change
 108 
 109     // IDs of native threads doing reads and writes, for signalling
 110     private long readerThread;
 111     private long writerThread;
 112 
 113     // Binding
 114     private SocketAddress localAddress;
 115     private SocketAddress remoteAddress;
 116 
 117     // Socket adaptor, created on demand
 118     private Socket socket;
 119 
 120     // -- End of fields protected by stateLock
 121 
 122     SocketChannelImpl(SelectorProvider sp, ProtocolFamily family) throws IOException {
 123         super(sp);
 124         this.fd = Net.socket(family, true);
 125         this.fdVal = IOUtil.fdVal(fd);
 126     }
 127 
 128     // Constructor for normal connecting sockets
 129     //
 130     SocketChannelImpl(SelectorProvider sp) throws IOException {
 131         super(sp);
 132         this.fd = Net.socket(true);
 133         this.fdVal = IOUtil.fdVal(fd);
 134     }
 135     
 136     SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 137         throws IOException
 138     {
 139         super(sp);
 140         this.fd = fd;
 141         this.fdVal = IOUtil.fdVal(fd);
 142         if (bound) {
 143             synchronized (stateLock) {
 144                 this.localAddress = Net.localAddress(fd);
 145             }
 146         }
 147     }
 148 
 149     // Constructor for sockets obtained from server sockets
 150     //
 151     SocketChannelImpl(SelectorProvider sp, FileDescriptor fd, SocketAddress isa)
 152         throws IOException
 153     {
 154         super(sp);
 155         this.fd = fd;
 156         this.fdVal = IOUtil.fdVal(fd);
 157         synchronized (stateLock) {
 158             this.localAddress = Net.localSocketAddress(fd);
 159             this.remoteAddress = isa;
 160             this.state = ST_CONNECTED;
 161         }
 162     }
 163 
 164     /**
 165      * Checks that the channel is open.
 166      *
 167      * @throws ClosedChannelException if channel is closed (or closing)
 168      */
 169     private void ensureOpen() throws ClosedChannelException {
 170         if (!isOpen())
 171             throw new ClosedChannelException();
 172     }
 173 
 174     /**
 175      * Checks that the channel is open and connected.
 176      *
 177      * @apiNote This method uses the "state" field to check if the channel is
 178      * open. It should never be used in conjuncion with isOpen or ensureOpen


 188         if (state < ST_CONNECTED) {
 189             throw new NotYetConnectedException();
 190         } else if (state > ST_CONNECTED) {
 191             throw new ClosedChannelException();
 192         }
 193     }
 194 
 195     @Override
 196     public Socket socket() {
 197         synchronized (stateLock) {
 198             if (socket == null)
 199                 socket = SocketAdaptor.create(this);
 200             return socket;
 201         }
 202     }
 203 
 204     @Override
 205     public SocketAddress getLocalAddress() throws IOException {
 206         synchronized (stateLock) {
 207             ensureOpen();
 208             return localAddress instanceof InetSocketAddress ? Net.getRevealedLocalAddress((InetSocketAddress) localAddress) : localAddress;
 209         }
 210     }
 211 
 212     @Override
 213     public SocketAddress getRemoteAddress() throws IOException {
 214         synchronized (stateLock) {
 215             ensureOpen();
 216             return remoteAddress;
 217         }
 218     }
 219 
 220     @Override
 221     public <T> SocketChannel setOption(SocketOption<T> name, T value)
 222         throws IOException
 223     {
 224         Objects.requireNonNull(name);
 225         if (!supportedOptions().contains(name))
 226             throw new UnsupportedOperationException("'" + name + "' not supported");
 227         if (!name.type().isInstance(value))
 228             throw new IllegalArgumentException("Invalid value '" + value + "'");


 577             readLock.unlock();
 578         }
 579     }
 580 
 581     /**
 582      * Adjust the blocking mode while holding the readLock or writeLock.
 583      */
 584     private void lockedConfigureBlocking(boolean block) throws IOException {
 585         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 586         synchronized (stateLock) {
 587             ensureOpen();
 588             IOUtil.configureBlocking(fd, block);
 589         }
 590     }
 591 
 592     /**
 593      * Returns the local address, or null if not bound
 594      */
 595     InetSocketAddress localAddress() {
 596         synchronized (stateLock) {
 597             return localAddress instanceof InetSocketAddress ? (InetSocketAddress) localAddress : null;
 598         }
 599     }
 600 
 601     /**
 602      * Returns the remote address, or null if not connected
 603      */
 604     InetSocketAddress remoteAddress() {
 605         synchronized (stateLock) {
 606             return remoteAddress instanceof InetSocketAddress ? (InetSocketAddress) remoteAddress : null;
 607         }
 608     }
 609 
 610     @Override
 611     public SocketChannel bind(SocketAddress local) throws IOException {
 612         readLock.lock();
 613         try {
 614             writeLock.lock();
 615             try {
 616                 synchronized (stateLock) {
 617                     ensureOpen();
 618                     if (state == ST_CONNECTIONPENDING)
 619                         throw new ConnectionPendingException();
 620                     if (localAddress != null)
 621                         throw new AlreadyBoundException();
 622                     InetSocketAddress isa = (local == null) ?
 623                         new InetSocketAddress(0) : Net.checkAddress(local);
 624                     SecurityManager sm = System.getSecurityManager();
 625                     if (sm != null) {
 626                         sm.checkListen(isa.getPort());


 669             int state = this.state;
 670             if (state == ST_CONNECTED)
 671                 throw new AlreadyConnectedException();
 672             if (state == ST_CONNECTIONPENDING)
 673                 throw new ConnectionPendingException();
 674             assert state == ST_UNCONNECTED;
 675             this.state = ST_CONNECTIONPENDING;
 676 
 677             if (localAddress == null)
 678                 NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
 679             remoteAddress = isa;
 680 
 681             if (blocking) {
 682                 // record thread so it can be signalled if needed
 683                 readerThread = NativeThread.current();
 684             }
 685         }
 686     }
 687     
 688     /**
 689      * TODO: refactoring, combine with InetSocketAddress method?
 690      * 
 691      * @param blocking
 692      * @param usa
 693      * @throws IOException 
 694      */
 695     private void beginConnect(boolean blocking, UnixSocketAddress usa)
 696         throws IOException
 697     {
 698         if (blocking) {
 699             // set hook for Thread.interrupt
 700             begin();
 701         }
 702         synchronized (stateLock) {
 703             ensureOpen();
 704             int state = this.state;
 705             if (state == ST_CONNECTED)
 706                 throw new AlreadyConnectedException();
 707             if (state == ST_CONNECTIONPENDING)
 708                 throw new ConnectionPendingException();
 709             assert state == ST_UNCONNECTED;
 710             this.state = ST_CONNECTIONPENDING;
 711 
 712             remoteAddress = usa;
 713 
 714             if (blocking) {
 715                 // record thread so it can be signalled if needed
 716                 readerThread = NativeThread.current();
 717             }
 718         }
 719     }
 720 
 721     /**
 722      * Marks the end of a connect operation that may have blocked.
 723      *
 724      * @throws AsynchronousCloseException if the channel was closed due to this
 725      * thread being interrupted on a blocking connect operation.
 726      * @throws IOException if completed and unable to obtain the local address
 727      */
 728     private void endConnect(boolean blocking, boolean completed)
 729         throws IOException
 730     {
 731         endRead(blocking, completed);
 732 
 733         if (completed) {
 734             synchronized (stateLock) {
 735                 if (state == ST_CONNECTIONPENDING) {
 736                     localAddress = Net.localAddress(fd);
 737                     state = ST_CONNECTED;
 738                 }
 739             }
 740         }
 741     }
 742 
 743     /**
 744      * Checks the remote address to which this channel is to be connected.
 745      */
 746     private InetSocketAddress checkRemote(SocketAddress sa) throws IOException {
 747         if (sa instanceof UnixSocketAddress) {
 748             // TODO: SecurityManager, refactor null
 749             return null;
 750         }
 751         
 752         InetSocketAddress isa = Net.checkAddress(sa);
 753         SecurityManager sm = System.getSecurityManager();
 754         if (sm != null) {
 755             sm.checkConnect(isa.getAddress().getHostAddress(), isa.getPort());
 756         }
 757         if (isa.getAddress().isAnyLocalAddress()) {
 758             return new InetSocketAddress(InetAddress.getLocalHost(), isa.getPort());
 759         } else {
 760             return isa;
 761         }
 762     }
 763 
 764     @Override
 765     public boolean connect(SocketAddress remote) throws IOException {
 766         InetSocketAddress isa = checkRemote(remote);
 767         try {
 768             readLock.lock();
 769             try {
 770                 writeLock.lock();
 771                 try {
 772                     boolean blocking = isBlocking();
 773                     boolean connected = false;
 774                     try {
 775                         int n;
 776                         if (remote instanceof UnixSocketAddress) {
 777                             UnixSocketAddress usa = (UnixSocketAddress)remote;
 778                             beginConnect(blocking, usa);
 779                             n = Net.connect(fd, usa);
 780                         } else {
 781                             beginConnect(blocking, isa);
 782                             n = Net.connect(fd, isa.getAddress(), isa.getPort());
 783                         }
 784                         if (n > 0) {
 785                             connected = true;
 786                         } else if (blocking) {
 787                             assert IOStatus.okayToRetry(n);
 788                             boolean polled = false;
 789                             while (!polled && isOpen()) {
 790                                 park(Net.POLLOUT);
 791                                 polled = Net.pollConnectNow(fd);
 792                             }
 793                             connected = polled && isOpen();
 794                         }
 795                     } finally {
 796                         endConnect(blocking, connected);
 797                     }
 798                     return connected;
 799                 } finally {
 800                     writeLock.unlock();
 801                 }
 802             } finally {
 803                 readLock.unlock();
 804             }
 805         } catch (IOException ioe) {
 806             // connect failed, close the channel
 807             close();
 808             throw SocketExceptions.of(ioe, remote);
 809         }
 810     }
 811 
 812     /**
 813      * Marks the beginning of a finishConnect operation that might block.
 814      *
 815      * @throws ClosedChannelException if the channel is closed
 816      * @throws NoConnectionPendingException if no connection is pending
 817      */
 818     private void beginFinishConnect(boolean blocking) throws ClosedChannelException {
 819         if (blocking) {
 820             // set hook for Thread.interrupt
 821             begin();
 822         }
 823         synchronized (stateLock) {
 824             ensureOpen();
 825             if (state != ST_CONNECTIONPENDING)
 826                 throw new NoConnectionPendingException();
 827             if (blocking) {
 828                 // record thread so it can be signalled if needed


1078     /**
1079      * Attempts to establish a connection to the given socket address with a
1080      * timeout. Closes the socket if connection cannot be established.
1081      *
1082      * @apiNote This method is for use by the socket adaptor.
1083      *
1084      * @throws IllegalBlockingModeException if the channel is non-blocking
1085      * @throws SocketTimeoutException if the read timeout elapses
1086      */
1087     void blockingConnect(SocketAddress remote, long nanos) throws IOException {
1088         InetSocketAddress isa = checkRemote(remote);
1089         try {
1090             readLock.lock();
1091             try {
1092                 writeLock.lock();
1093                 try {
1094                     if (!isBlocking())
1095                         throw new IllegalBlockingModeException();
1096                     boolean connected = false;
1097                     try {
1098                         if (remote instanceof UnixSocketAddress) {
1099                             UnixSocketAddress usa = (UnixSocketAddress)remote;
1100                             beginConnect(true, usa);
1101                         } else {
1102                             beginConnect(true, isa);
1103                         }
1104                         // change socket to non-blocking
1105                         lockedConfigureBlocking(false);
1106                         try {
1107                             int n;
1108                             if (remote instanceof UnixSocketAddress) {
1109                                 n = Net.connect(fd, (UnixSocketAddress) remote); // TODO: refactor null/remote/isa
1110                             } else {
1111                                 n = Net.connect(fd, isa.getAddress(), isa.getPort());
1112                             }
1113                             connected = (n > 0) ? true : finishTimedConnect(nanos);
1114                         } finally {
1115                             // restore socket to blocking mode
1116                             lockedConfigureBlocking(true);
1117                         }
1118                     } finally {
1119                         endConnect(true, connected);
1120                     }
1121                 } finally {
1122                     writeLock.unlock();
1123                 }
1124             } finally {
1125                 readLock.unlock();
1126             }
1127         } catch (IOException ioe) {
1128             // connect failed, close the channel
1129             close();
1130             throw SocketExceptions.of(ioe, isa);
1131         }
1132     }


< prev index next >