History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/nio/ch/SocketChannelImpl.java (1 of 18352 files). Show all

Unified · Split

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