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 }
|