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