1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  * Copyright (c) 2001, 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.DatagramSocket;
32 import java.net.Inet4Address;
33 import java.net.Inet6Address;
34 import java.net.InetAddress;
35 import java.net.InetSocketAddress;
36 import java.net.NetworkInterface;
37 import java.net.PortUnreachableException;
38 import java.net.ProtocolFamily;
39 import java.net.SocketAddress;
40 import java.net.SocketOption;
41 import java.net.StandardProtocolFamily;
42 import java.net.StandardSocketOptions;
43 import java.nio.ByteBuffer;
44 import java.nio.channels.AlreadyBoundException;
45 import java.nio.channels.ClosedChannelException;
46 import java.nio.channels.DatagramChannel;
47 import java.nio.channels.MembershipKey;
48 import java.nio.channels.NotYetConnectedException;
49 import java.nio.channels.SelectionKey;
50 import java.nio.channels.UnsupportedAddressTypeException;
51 import java.nio.channels.spi.SelectorProvider;
52 import java.util.Collections;
53 import java.util.HashSet;
54 import java.util.Set;
55 
56 import dalvik.system.BlockGuard;
57 import dalvik.system.CloseGuard;
58 import sun.net.ExtendedOptionsImpl;
59 import sun.net.ResourceManager;
60 
61 /**
62  * An implementation of DatagramChannels.
63  */
64 
65 class DatagramChannelImpl
66     extends DatagramChannel
67     implements SelChImpl
68 {
69 
70     // Used to make native read and write calls
71     private static NativeDispatcher nd = new DatagramDispatcher();
72 
73     // Our file descriptor
74     // Android-changed: Make the fd package visible so that we can expose it through DatagramSocketAdaptor.
75     final FileDescriptor fd;
76 
77     // fd value needed for dev/poll. This value will remain valid
78     // even after the value in the file descriptor object has been set to -1
79     private final int fdVal;
80 
81     // The protocol family of the socket
82     private final ProtocolFamily family;
83 
84     // IDs of native threads doing reads and writes, for signalling
85     private volatile long readerThread = 0;
86     private volatile long writerThread = 0;
87 
88     // Cached InetAddress and port for unconnected DatagramChannels
89     // used by receive0
90     private InetAddress cachedSenderInetAddress;
91     private int cachedSenderPort;
92 
93     // Lock held by current reading or connecting thread
94     private final Object readLock = new Object();
95 
96     // Lock held by current writing or connecting thread
97     private final Object writeLock = new Object();
98 
99     // Lock held by any thread that modifies the state fields declared below
100     // DO NOT invoke a blocking I/O operation while holding this lock!
101     private final Object stateLock = new Object();
102 
103     // -- The following fields are protected by stateLock
104 
105     // State (does not necessarily increase monotonically)
106     private static final int ST_UNINITIALIZED = -1;
107     private static final int ST_UNCONNECTED = 0;
108     private static final int ST_CONNECTED = 1;
109     private static final int ST_KILLED = 2;
110     private int state = ST_UNINITIALIZED;
111 
112     // Binding
113     private InetSocketAddress localAddress;
114     private InetSocketAddress remoteAddress;
115 
116     // Our socket adaptor, if any
117     private DatagramSocket socket;
118 
119     // Multicast support
120     private MembershipRegistry registry;
121 
122     // set true when socket is bound and SO_REUSEADDRESS is emulated
123     private boolean reuseAddressEmulated;
124 
125     // set true/false when socket is already bound and SO_REUSEADDR is emulated
126     private boolean isReuseAddress;
127 
128     // -- End of fields protected by stateLock
129 
130     // Android-changed: Add CloseGuard support.
131     private final CloseGuard guard = CloseGuard.get();
132 
DatagramChannelImpl(SelectorProvider sp)133     public DatagramChannelImpl(SelectorProvider sp)
134         throws IOException
135     {
136         super(sp);
137         ResourceManager.beforeUdpCreate();
138         try {
139             this.family = Net.isIPv6Available() ?
140                 StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
141             this.fd = Net.socket(family, false);
142             this.fdVal = IOUtil.fdVal(fd);
143             this.state = ST_UNCONNECTED;
144             // Android-changed: Add CloseGuard support.
145             // Net#socket will set |fd| if it succeeds.
146             if (fd != null && fd.valid()) {
147                 guard.open("close");
148             }
149         } catch (IOException ioe) {
150             ResourceManager.afterUdpClose();
151             throw ioe;
152         }
153     }
154 
DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)155     public DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family)
156         throws IOException
157     {
158         super(sp);
159         if ((family != StandardProtocolFamily.INET) &&
160             (family != StandardProtocolFamily.INET6))
161         {
162             if (family == null)
163                 throw new NullPointerException("'family' is null");
164             else
165                 throw new UnsupportedOperationException("Protocol family not supported");
166         }
167         if (family == StandardProtocolFamily.INET6) {
168             if (!Net.isIPv6Available()) {
169                 throw new UnsupportedOperationException("IPv6 not available");
170             }
171         }
172         this.family = family;
173         this.fd = Net.socket(family, false);
174         this.fdVal = IOUtil.fdVal(fd);
175         this.state = ST_UNCONNECTED;
176         // Android-changed: Add CloseGuard support.
177         // Net#socket will set |fd| if it succeeds.
178         if (fd != null && fd.valid()) {
179             guard.open("close");
180         }
181     }
182 
DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)183     public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
184         throws IOException
185     {
186         super(sp);
187         this.family = Net.isIPv6Available() ?
188             StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
189         this.fd = fd;
190         this.fdVal = IOUtil.fdVal(fd);
191         this.state = ST_UNCONNECTED;
192         this.localAddress = Net.localAddress(fd);
193         // Android-changed: Add CloseGuard support.
194         if (fd != null && fd.valid()) {
195             guard.open("close");
196         }
197     }
198 
socket()199     public DatagramSocket socket() {
200         synchronized (stateLock) {
201             if (socket == null)
202                 socket = DatagramSocketAdaptor.create(this);
203             return socket;
204         }
205     }
206 
207     @Override
getLocalAddress()208     public SocketAddress getLocalAddress() throws IOException {
209         synchronized (stateLock) {
210             if (!isOpen())
211                 throw new ClosedChannelException();
212             // Perform security check before returning address
213             return Net.getRevealedLocalAddress(localAddress);
214         }
215     }
216 
217     @Override
getRemoteAddress()218     public SocketAddress getRemoteAddress() throws IOException {
219         synchronized (stateLock) {
220             if (!isOpen())
221                 throw new ClosedChannelException();
222             return remoteAddress;
223         }
224     }
225 
226     @Override
setOption(SocketOption<T> name, T value)227     public <T> DatagramChannel setOption(SocketOption<T> name, T value)
228         throws IOException
229     {
230         if (name == null)
231             throw new NullPointerException();
232         if (!supportedOptions().contains(name))
233             throw new UnsupportedOperationException("'" + name + "' not supported");
234 
235         synchronized (stateLock) {
236             ensureOpen();
237 
238             if (name == StandardSocketOptions.IP_TOS ||
239                 name == StandardSocketOptions.IP_MULTICAST_TTL ||
240                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
241             {
242                 // options are protocol dependent
243                 Net.setSocketOption(fd, family, name, value);
244                 return this;
245             }
246 
247             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
248                 if (value == null)
249                     throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'");
250                 NetworkInterface interf = (NetworkInterface)value;
251                 if (family == StandardProtocolFamily.INET6) {
252                     int index = interf.getIndex();
253                     if (index == -1)
254                         throw new IOException("Network interface cannot be identified");
255                     Net.setInterface6(fd, index);
256                 } else {
257                     // need IPv4 address to identify interface
258                     Inet4Address target = Net.anyInet4Address(interf);
259                     if (target == null)
260                         throw new IOException("Network interface not configured for IPv4");
261                     int targetAddress = Net.inet4AsInt(target);
262                     Net.setInterface4(fd, targetAddress);
263                 }
264                 return this;
265             }
266             if (name == StandardSocketOptions.SO_REUSEADDR &&
267                     Net.useExclusiveBind() && localAddress != null)
268             {
269                 reuseAddressEmulated = true;
270                 this.isReuseAddress = (Boolean)value;
271             }
272 
273             // remaining options don't need any special handling
274             Net.setSocketOption(fd, Net.UNSPEC, name, value);
275             return this;
276         }
277     }
278 
279     @Override
280     @SuppressWarnings("unchecked")
getOption(SocketOption<T> name)281     public <T> T getOption(SocketOption<T> name)
282         throws IOException
283     {
284         if (name == null)
285             throw new NullPointerException();
286         if (!supportedOptions().contains(name))
287             throw new UnsupportedOperationException("'" + name + "' not supported");
288 
289         synchronized (stateLock) {
290             ensureOpen();
291 
292             if (name == StandardSocketOptions.IP_TOS ||
293                 name == StandardSocketOptions.IP_MULTICAST_TTL ||
294                 name == StandardSocketOptions.IP_MULTICAST_LOOP)
295             {
296                 return (T) Net.getSocketOption(fd, family, name);
297             }
298 
299             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
300                 if (family == StandardProtocolFamily.INET) {
301                     int address = Net.getInterface4(fd);
302                     if (address == 0)
303                         return null;    // default interface
304 
305                     InetAddress ia = Net.inet4FromInt(address);
306                     NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
307                     if (ni == null)
308                         throw new IOException("Unable to map address to interface");
309                     return (T) ni;
310                 } else {
311                     int index = Net.getInterface6(fd);
312                     if (index == 0)
313                         return null;    // default interface
314 
315                     NetworkInterface ni = NetworkInterface.getByIndex(index);
316                     if (ni == null)
317                         throw new IOException("Unable to map index to interface");
318                     return (T) ni;
319                 }
320             }
321 
322             if (name == StandardSocketOptions.SO_REUSEADDR &&
323                     reuseAddressEmulated)
324             {
325                 return (T)Boolean.valueOf(isReuseAddress);
326             }
327 
328             // no special handling
329             return (T) Net.getSocketOption(fd, Net.UNSPEC, name);
330         }
331     }
332 
333     private static class DefaultOptionsHolder {
334         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
335 
defaultOptions()336         private static Set<SocketOption<?>> defaultOptions() {
337             HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8);
338             set.add(StandardSocketOptions.SO_SNDBUF);
339             set.add(StandardSocketOptions.SO_RCVBUF);
340             set.add(StandardSocketOptions.SO_REUSEADDR);
341             set.add(StandardSocketOptions.SO_BROADCAST);
342             set.add(StandardSocketOptions.IP_TOS);
343             set.add(StandardSocketOptions.IP_MULTICAST_IF);
344             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
345             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
346             if (ExtendedOptionsImpl.flowSupported()) {
347                 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
348             }
349             return Collections.unmodifiableSet(set);
350         }
351     }
352 
353     @Override
supportedOptions()354     public final Set<SocketOption<?>> supportedOptions() {
355         return DefaultOptionsHolder.defaultOptions;
356     }
357 
ensureOpen()358     private void ensureOpen() throws ClosedChannelException {
359         if (!isOpen())
360             throw new ClosedChannelException();
361     }
362 
363     private SocketAddress sender;       // Set by receive0 (## ugh)
364 
receive(ByteBuffer dst)365     public SocketAddress receive(ByteBuffer dst) throws IOException {
366         if (dst.isReadOnly())
367             throw new IllegalArgumentException("Read-only buffer");
368         if (dst == null)
369             throw new NullPointerException();
370         // Android-changed: Do not attempt to bind to 0 (or 0.0.0.0) if there hasn't been
371         // an explicit call to bind() yet. Fail fast and return null.
372         if (localAddress == null)
373             return null;
374         synchronized (readLock) {
375             ensureOpen();
376             // Socket was not bound before attempting receive
377             // if (localAddress() == null)
378             //     bind(null);
379             int n = 0;
380             ByteBuffer bb = null;
381             try {
382                 begin();
383                 if (!isOpen())
384                     return null;
385                 SecurityManager security = System.getSecurityManager();
386                 readerThread = NativeThread.current();
387                 if (isConnected() || (security == null)) {
388                     do {
389                         n = receive(fd, dst);
390                     } while ((n == IOStatus.INTERRUPTED) && isOpen());
391                     if (n == IOStatus.UNAVAILABLE)
392                         return null;
393                 } else {
394                     bb = Util.getTemporaryDirectBuffer(dst.remaining());
395                     for (;;) {
396                         do {
397                             n = receive(fd, bb);
398                         } while ((n == IOStatus.INTERRUPTED) && isOpen());
399                         if (n == IOStatus.UNAVAILABLE)
400                             return null;
401                         InetSocketAddress isa = (InetSocketAddress)sender;
402                         try {
403                             security.checkAccept(
404                                 isa.getAddress().getHostAddress(),
405                                 isa.getPort());
406                         } catch (SecurityException se) {
407                             // Ignore packet
408                             bb.clear();
409                             n = 0;
410                             continue;
411                         }
412                         bb.flip();
413                         dst.put(bb);
414                         break;
415                     }
416                 }
417                 return sender;
418             } finally {
419                 if (bb != null)
420                     Util.releaseTemporaryDirectBuffer(bb);
421                 readerThread = 0;
422                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
423                 assert IOStatus.check(n);
424             }
425         }
426     }
427 
receive(FileDescriptor fd, ByteBuffer dst)428     private int receive(FileDescriptor fd, ByteBuffer dst)
429         throws IOException
430     {
431         int pos = dst.position();
432         int lim = dst.limit();
433         assert (pos <= lim);
434         int rem = (pos <= lim ? lim - pos : 0);
435         if (dst instanceof DirectBuffer && rem > 0)
436             return receiveIntoNativeBuffer(fd, dst, rem, pos);
437 
438         // Substitute a native buffer. If the supplied buffer is empty
439         // we must instead use a nonempty buffer, otherwise the call
440         // will not block waiting for a datagram on some platforms.
441         int newSize = Math.max(rem, 1);
442         ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
443         try {
444             BlockGuard.getThreadPolicy().onNetwork();
445 
446             int n = receiveIntoNativeBuffer(fd, bb, newSize, 0);
447             bb.flip();
448             if (n > 0 && rem > 0)
449                 dst.put(bb);
450             return n;
451         } finally {
452             Util.releaseTemporaryDirectBuffer(bb);
453         }
454     }
455 
receiveIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, int rem, int pos)456     private int receiveIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb,
457                                         int rem, int pos)
458         throws IOException
459     {
460         int n = receive0(fd, ((DirectBuffer)bb).address() + pos, rem,
461                          isConnected());
462         if (n > 0)
463             bb.position(pos + n);
464         return n;
465     }
466 
send(ByteBuffer src, SocketAddress target)467     public int send(ByteBuffer src, SocketAddress target)
468         throws IOException
469     {
470         if (src == null)
471             throw new NullPointerException();
472 
473         synchronized (writeLock) {
474             ensureOpen();
475             InetSocketAddress isa = Net.checkAddress(target);
476             InetAddress ia = isa.getAddress();
477             if (ia == null)
478                 throw new IOException("Target address not resolved");
479             synchronized (stateLock) {
480                 if (!isConnected()) {
481                     if (target == null)
482                         throw new NullPointerException();
483                     SecurityManager sm = System.getSecurityManager();
484                     if (sm != null) {
485                         if (ia.isMulticastAddress()) {
486                             sm.checkMulticast(ia);
487                         } else {
488                             sm.checkConnect(ia.getHostAddress(),
489                                             isa.getPort());
490                         }
491                     }
492                 } else { // Connected case; Check address then write
493                     if (!target.equals(remoteAddress)) {
494                         throw new IllegalArgumentException(
495                             "Connected address not equal to target address");
496                     }
497                     return write(src);
498                 }
499             }
500 
501             int n = 0;
502             try {
503                 begin();
504                 if (!isOpen())
505                     return 0;
506                 writerThread = NativeThread.current();
507                 BlockGuard.getThreadPolicy().onNetwork();
508 
509                 do {
510                     n = send(fd, src, isa);
511                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
512 
513                 synchronized (stateLock) {
514                     if (isOpen() && (localAddress == null)) {
515                         localAddress = Net.localAddress(fd);
516                     }
517                 }
518                 return IOStatus.normalize(n);
519             } finally {
520                 writerThread = 0;
521                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
522                 assert IOStatus.check(n);
523             }
524         }
525     }
526 
send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)527     private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
528         throws IOException
529     {
530         if (src instanceof DirectBuffer)
531             return sendFromNativeBuffer(fd, src, target);
532 
533         // Substitute a native buffer
534         int pos = src.position();
535         int lim = src.limit();
536         assert (pos <= lim);
537         int rem = (pos <= lim ? lim - pos : 0);
538 
539         ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
540         try {
541             bb.put(src);
542             bb.flip();
543             // Do not update src until we see how many bytes were written
544             src.position(pos);
545 
546             int n = sendFromNativeBuffer(fd, bb, target);
547             if (n > 0) {
548                 // now update src
549                 src.position(pos + n);
550             }
551             return n;
552         } finally {
553             Util.releaseTemporaryDirectBuffer(bb);
554         }
555     }
556 
sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, InetSocketAddress target)557     private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
558                                      InetSocketAddress target)
559         throws IOException
560     {
561         int pos = bb.position();
562         int lim = bb.limit();
563         assert (pos <= lim);
564         int rem = (pos <= lim ? lim - pos : 0);
565 
566         boolean preferIPv6 = (family != StandardProtocolFamily.INET);
567         int written;
568         try {
569             written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos,
570                             rem, target.getAddress(), target.getPort());
571         } catch (PortUnreachableException pue) {
572             if (isConnected())
573                 throw pue;
574             written = rem;
575         }
576         if (written > 0)
577             bb.position(pos + written);
578         return written;
579     }
580 
read(ByteBuffer buf)581     public int read(ByteBuffer buf) throws IOException {
582         if (buf == null)
583             throw new NullPointerException();
584         synchronized (readLock) {
585             synchronized (stateLock) {
586                 ensureOpen();
587                 if (!isConnected())
588                     throw new NotYetConnectedException();
589             }
590             int n = 0;
591             try {
592                 begin();
593                 if (!isOpen())
594                     return 0;
595                 readerThread = NativeThread.current();
596                 do {
597                     n = IOUtil.read(fd, buf, -1, nd);
598                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
599                 return IOStatus.normalize(n);
600             } finally {
601                 readerThread = 0;
602                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
603                 assert IOStatus.check(n);
604             }
605         }
606     }
607 
read(ByteBuffer[] dsts, int offset, int length)608     public long read(ByteBuffer[] dsts, int offset, int length)
609         throws IOException
610     {
611         if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
612             throw new IndexOutOfBoundsException();
613         synchronized (readLock) {
614             synchronized (stateLock) {
615                 ensureOpen();
616                 if (!isConnected())
617                     throw new NotYetConnectedException();
618             }
619             long n = 0;
620             try {
621                 begin();
622                 if (!isOpen())
623                     return 0;
624                 readerThread = NativeThread.current();
625                 do {
626                     n = IOUtil.read(fd, dsts, offset, length, nd);
627                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
628                 return IOStatus.normalize(n);
629             } finally {
630                 readerThread = 0;
631                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
632                 assert IOStatus.check(n);
633             }
634         }
635     }
636 
write(ByteBuffer buf)637     public int write(ByteBuffer buf) throws IOException {
638         if (buf == null)
639             throw new NullPointerException();
640         synchronized (writeLock) {
641             synchronized (stateLock) {
642                 ensureOpen();
643                 if (!isConnected())
644                     throw new NotYetConnectedException();
645             }
646             int n = 0;
647             try {
648                 begin();
649                 if (!isOpen())
650                     return 0;
651                 writerThread = NativeThread.current();
652                 do {
653                     n = IOUtil.write(fd, buf, -1, nd);
654                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
655                 return IOStatus.normalize(n);
656             } finally {
657                 writerThread = 0;
658                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
659                 assert IOStatus.check(n);
660             }
661         }
662     }
663 
write(ByteBuffer[] srcs, int offset, int length)664     public long write(ByteBuffer[] srcs, int offset, int length)
665         throws IOException
666     {
667         if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
668             throw new IndexOutOfBoundsException();
669         synchronized (writeLock) {
670             synchronized (stateLock) {
671                 ensureOpen();
672                 if (!isConnected())
673                     throw new NotYetConnectedException();
674             }
675             long n = 0;
676             try {
677                 begin();
678                 if (!isOpen())
679                     return 0;
680                 writerThread = NativeThread.current();
681                 do {
682                     n = IOUtil.write(fd, srcs, offset, length, nd);
683                 } while ((n == IOStatus.INTERRUPTED) && isOpen());
684                 return IOStatus.normalize(n);
685             } finally {
686                 writerThread = 0;
687                 end((n > 0) || (n == IOStatus.UNAVAILABLE));
688                 assert IOStatus.check(n);
689             }
690         }
691     }
692 
implConfigureBlocking(boolean block)693     protected void implConfigureBlocking(boolean block) throws IOException {
694         IOUtil.configureBlocking(fd, block);
695     }
696 
localAddress()697     public SocketAddress localAddress() {
698         synchronized (stateLock) {
699             return localAddress;
700         }
701     }
702 
remoteAddress()703     public SocketAddress remoteAddress() {
704         synchronized (stateLock) {
705             return remoteAddress;
706         }
707     }
708 
709     @Override
bind(SocketAddress local)710     public DatagramChannel bind(SocketAddress local) throws IOException {
711         synchronized (readLock) {
712             synchronized (writeLock) {
713                 synchronized (stateLock) {
714                     ensureOpen();
715                     if (localAddress != null)
716                         throw new AlreadyBoundException();
717                     InetSocketAddress isa;
718                     if (local == null) {
719                         // only Inet4Address allowed with IPv4 socket
720                         if (family == StandardProtocolFamily.INET) {
721                             isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
722                         } else {
723                             isa = new InetSocketAddress(0);
724                         }
725                     } else {
726                         isa = Net.checkAddress(local);
727 
728                         // only Inet4Address allowed with IPv4 socket
729                         if (family == StandardProtocolFamily.INET) {
730                             InetAddress addr = isa.getAddress();
731                             if (!(addr instanceof Inet4Address))
732                                 throw new UnsupportedAddressTypeException();
733                         }
734                     }
735                     SecurityManager sm = System.getSecurityManager();
736                     if (sm != null) {
737                         sm.checkListen(isa.getPort());
738                     }
739                     Net.bind(family, fd, isa.getAddress(), isa.getPort());
740                     localAddress = Net.localAddress(fd);
741                 }
742             }
743         }
744         return this;
745     }
746 
isConnected()747     public boolean isConnected() {
748         synchronized (stateLock) {
749             return (state == ST_CONNECTED);
750         }
751     }
752 
ensureOpenAndUnconnected()753     void ensureOpenAndUnconnected() throws IOException { // package-private
754         synchronized (stateLock) {
755             if (!isOpen())
756                 throw new ClosedChannelException();
757             if (state != ST_UNCONNECTED)
758                 throw new IllegalStateException("Connect already invoked");
759         }
760     }
761 
762     @Override
connect(SocketAddress sa)763     public DatagramChannel connect(SocketAddress sa) throws IOException {
764         int localPort = 0;
765 
766         synchronized(readLock) {
767             synchronized(writeLock) {
768                 synchronized (stateLock) {
769                     ensureOpenAndUnconnected();
770                     InetSocketAddress isa = Net.checkAddress(sa);
771                     SecurityManager sm = System.getSecurityManager();
772                     if (sm != null)
773                         sm.checkConnect(isa.getAddress().getHostAddress(),
774                                         isa.getPort());
775                     int n = Net.connect(family,
776                                         fd,
777                                         isa.getAddress(),
778                                         isa.getPort());
779                     if (n <= 0)
780                         throw new Error();      // Can't happen
781 
782                     // Connection succeeded; disallow further invocation
783                     state = ST_CONNECTED;
784                     remoteAddress = isa;
785                     sender = isa;
786                     cachedSenderInetAddress = isa.getAddress();
787                     cachedSenderPort = isa.getPort();
788 
789                     // set or refresh local address
790                     localAddress = Net.localAddress(fd);
791 
792                     // flush any packets already received.
793                     boolean blocking = false;
794                     synchronized (blockingLock()) {
795                         try {
796                             blocking = isBlocking();
797                             // remainder of each packet thrown away
798                             ByteBuffer tmpBuf = ByteBuffer.allocate(1);
799                             if (blocking) {
800                                 configureBlocking(false);
801                             }
802                             do {
803                                 tmpBuf.clear();
804                             } while (receive(tmpBuf) != null);
805                         } finally {
806                             if (blocking) {
807                                 configureBlocking(true);
808                             }
809                         }
810                     }
811                 }
812             }
813         }
814         return this;
815     }
816 
disconnect()817     public DatagramChannel disconnect() throws IOException {
818         synchronized(readLock) {
819             synchronized(writeLock) {
820                 synchronized (stateLock) {
821                     if (!isConnected() || !isOpen())
822                         return this;
823                     InetSocketAddress isa = remoteAddress;
824                     SecurityManager sm = System.getSecurityManager();
825                     if (sm != null)
826                         sm.checkConnect(isa.getAddress().getHostAddress(),
827                                         isa.getPort());
828                     boolean isIPv6 = (family == StandardProtocolFamily.INET6);
829                     disconnect0(fd, isIPv6);
830                     remoteAddress = null;
831                     state = ST_UNCONNECTED;
832 
833                     // refresh local address
834                     localAddress = Net.localAddress(fd);
835                 }
836             }
837         }
838         return this;
839     }
840 
841     /**
842      * Joins channel's socket to the given group/interface and
843      * optional source address.
844      */
innerJoin(InetAddress group, NetworkInterface interf, InetAddress source)845     private MembershipKey innerJoin(InetAddress group,
846                                     NetworkInterface interf,
847                                     InetAddress source)
848         throws IOException
849     {
850         if (!group.isMulticastAddress())
851             throw new IllegalArgumentException("Group not a multicast address");
852 
853         // check multicast address is compatible with this socket
854         if (group instanceof Inet4Address) {
855             if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
856                 throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group");
857         } else if (group instanceof Inet6Address) {
858             if (family != StandardProtocolFamily.INET6)
859                 throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group");
860         } else {
861             throw new IllegalArgumentException("Address type not supported");
862         }
863 
864         // check source address
865         if (source != null) {
866             if (source.isAnyLocalAddress())
867                 throw new IllegalArgumentException("Source address is a wildcard address");
868             if (source.isMulticastAddress())
869                 throw new IllegalArgumentException("Source address is multicast address");
870             if (source.getClass() != group.getClass())
871                 throw new IllegalArgumentException("Source address is different type to group");
872         }
873 
874         SecurityManager sm = System.getSecurityManager();
875         if (sm != null)
876             sm.checkMulticast(group);
877 
878         synchronized (stateLock) {
879             if (!isOpen())
880                 throw new ClosedChannelException();
881 
882             // check the registry to see if we are already a member of the group
883             if (registry == null) {
884                 registry = new MembershipRegistry();
885             } else {
886                 // return existing membership key
887                 MembershipKey key = registry.checkMembership(group, interf, source);
888                 if (key != null)
889                     return key;
890             }
891 
892             MembershipKeyImpl key;
893             if ((family == StandardProtocolFamily.INET6) &&
894                 ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
895             {
896                 int index = interf.getIndex();
897                 if (index == -1)
898                     throw new IOException("Network interface cannot be identified");
899 
900                 // need multicast and source address as byte arrays
901                 byte[] groupAddress = Net.inet6AsByteArray(group);
902                 byte[] sourceAddress = (source == null) ? null :
903                     Net.inet6AsByteArray(source);
904 
905                 // join the group
906                 int n = Net.join6(fd, groupAddress, index, sourceAddress);
907                 if (n == IOStatus.UNAVAILABLE)
908                     throw new UnsupportedOperationException();
909 
910                 key = new MembershipKeyImpl.Type6(this, group, interf, source,
911                                                   groupAddress, index, sourceAddress);
912 
913             } else {
914                 // need IPv4 address to identify interface
915                 Inet4Address target = Net.anyInet4Address(interf);
916                 if (target == null)
917                     throw new IOException("Network interface not configured for IPv4");
918 
919                 int groupAddress = Net.inet4AsInt(group);
920                 int targetAddress = Net.inet4AsInt(target);
921                 int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
922 
923                 // join the group
924                 int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
925                 if (n == IOStatus.UNAVAILABLE)
926                     throw new UnsupportedOperationException();
927 
928                 key = new MembershipKeyImpl.Type4(this, group, interf, source,
929                                                   groupAddress, targetAddress, sourceAddress);
930             }
931 
932             registry.add(key);
933             return key;
934         }
935     }
936 
937     @Override
join(InetAddress group, NetworkInterface interf)938     public MembershipKey join(InetAddress group,
939                               NetworkInterface interf)
940         throws IOException
941     {
942         return innerJoin(group, interf, null);
943     }
944 
945     @Override
join(InetAddress group, NetworkInterface interf, InetAddress source)946     public MembershipKey join(InetAddress group,
947                               NetworkInterface interf,
948                               InetAddress source)
949         throws IOException
950     {
951         if (source == null)
952             throw new NullPointerException("source address is null");
953         return innerJoin(group, interf, source);
954     }
955 
956     // package-private
drop(MembershipKeyImpl key)957     void drop(MembershipKeyImpl key) {
958         assert key.channel() == this;
959 
960         synchronized (stateLock) {
961             if (!key.isValid())
962                 return;
963 
964             try {
965                 if (key instanceof MembershipKeyImpl.Type6) {
966                     MembershipKeyImpl.Type6 key6 =
967                         (MembershipKeyImpl.Type6)key;
968                     Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
969                 } else {
970                     MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key;
971                     Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(),
972                         key4.source());
973                 }
974             } catch (IOException ioe) {
975                 // should not happen
976                 throw new AssertionError(ioe);
977             }
978 
979             key.invalidate();
980             registry.remove(key);
981         }
982     }
983 
984     /**
985      * Block datagrams from given source if a memory to receive all
986      * datagrams.
987      */
block(MembershipKeyImpl key, InetAddress source)988     void block(MembershipKeyImpl key, InetAddress source)
989         throws IOException
990     {
991         assert key.channel() == this;
992         assert key.sourceAddress() == null;
993 
994         synchronized (stateLock) {
995             if (!key.isValid())
996                 throw new IllegalStateException("key is no longer valid");
997             if (source.isAnyLocalAddress())
998                 throw new IllegalArgumentException("Source address is a wildcard address");
999             if (source.isMulticastAddress())
1000                 throw new IllegalArgumentException("Source address is multicast address");
1001             if (source.getClass() != key.group().getClass())
1002                 throw new IllegalArgumentException("Source address is different type to group");
1003 
1004             int n;
1005             if (key instanceof MembershipKeyImpl.Type6) {
1006                  MembershipKeyImpl.Type6 key6 =
1007                     (MembershipKeyImpl.Type6)key;
1008                 n = Net.block6(fd, key6.groupAddress(), key6.index(),
1009                                Net.inet6AsByteArray(source));
1010             } else {
1011                 MembershipKeyImpl.Type4 key4 =
1012                     (MembershipKeyImpl.Type4)key;
1013                 n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(),
1014                                Net.inet4AsInt(source));
1015             }
1016             if (n == IOStatus.UNAVAILABLE) {
1017                 // ancient kernel
1018                 throw new UnsupportedOperationException();
1019             }
1020         }
1021     }
1022 
1023     /**
1024      * Unblock given source.
1025      */
unblock(MembershipKeyImpl key, InetAddress source)1026     void unblock(MembershipKeyImpl key, InetAddress source) {
1027         assert key.channel() == this;
1028         assert key.sourceAddress() == null;
1029 
1030         synchronized (stateLock) {
1031             if (!key.isValid())
1032                 throw new IllegalStateException("key is no longer valid");
1033 
1034             try {
1035                 if (key instanceof MembershipKeyImpl.Type6) {
1036                     MembershipKeyImpl.Type6 key6 =
1037                         (MembershipKeyImpl.Type6)key;
1038                     Net.unblock6(fd, key6.groupAddress(), key6.index(),
1039                                  Net.inet6AsByteArray(source));
1040                 } else {
1041                     MembershipKeyImpl.Type4 key4 =
1042                         (MembershipKeyImpl.Type4)key;
1043                     Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(),
1044                                  Net.inet4AsInt(source));
1045                 }
1046             } catch (IOException ioe) {
1047                 // should not happen
1048                 throw new AssertionError(ioe);
1049             }
1050         }
1051     }
1052 
implCloseSelectableChannel()1053     protected void implCloseSelectableChannel() throws IOException {
1054         synchronized (stateLock) {
1055             // Android-changed: Add CloseGuard support.
1056             guard.close();
1057             if (state != ST_KILLED)
1058                 nd.preClose(fd);
1059             ResourceManager.afterUdpClose();
1060 
1061             // if member of mulitcast group then invalidate all keys
1062             if (registry != null)
1063                 registry.invalidateAll();
1064 
1065             long th;
1066             if ((th = readerThread) != 0)
1067                 NativeThread.signal(th);
1068             if ((th = writerThread) != 0)
1069                 NativeThread.signal(th);
1070             if (!isRegistered())
1071                 kill();
1072         }
1073     }
1074 
kill()1075     public void kill() throws IOException {
1076         synchronized (stateLock) {
1077             if (state == ST_KILLED)
1078                 return;
1079             if (state == ST_UNINITIALIZED) {
1080                 state = ST_KILLED;
1081                 return;
1082             }
1083             assert !isOpen() && !isRegistered();
1084             nd.close(fd);
1085             state = ST_KILLED;
1086         }
1087     }
1088 
finalize()1089     protected void finalize() throws Throwable {
1090         try {
1091             // Android-changed: Add CloseGuard support.
1092             if (guard != null) {
1093                 guard.warnIfOpen();
1094             }
1095             // fd is null if constructor threw exception
1096             if (fd != null)
1097                 close();
1098         } finally {
1099             super.finalize();
1100         }
1101     }
1102 
1103     /**
1104      * Translates native poll revent set into a ready operation set
1105      */
translateReadyOps(int ops, int initialOps, SelectionKeyImpl sk)1106     public boolean translateReadyOps(int ops, int initialOps,
1107                                      SelectionKeyImpl sk) {
1108         int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
1109         int oldOps = sk.nioReadyOps();
1110         int newOps = initialOps;
1111 
1112         if ((ops & Net.POLLNVAL) != 0) {
1113             // This should only happen if this channel is pre-closed while a
1114             // selection operation is in progress
1115             // ## Throw an error if this channel has not been pre-closed
1116             return false;
1117         }
1118 
1119         if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
1120             newOps = intOps;
1121             sk.nioReadyOps(newOps);
1122             return (newOps & ~oldOps) != 0;
1123         }
1124 
1125         if (((ops & Net.POLLIN) != 0) &&
1126             ((intOps & SelectionKey.OP_READ) != 0))
1127             newOps |= SelectionKey.OP_READ;
1128 
1129         if (((ops & Net.POLLOUT) != 0) &&
1130             ((intOps & SelectionKey.OP_WRITE) != 0))
1131             newOps |= SelectionKey.OP_WRITE;
1132 
1133         sk.nioReadyOps(newOps);
1134         return (newOps & ~oldOps) != 0;
1135     }
1136 
translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk)1137     public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
1138         return translateReadyOps(ops, sk.nioReadyOps(), sk);
1139     }
1140 
translateAndSetReadyOps(int ops, SelectionKeyImpl sk)1141     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
1142         return translateReadyOps(ops, 0, sk);
1143     }
1144 
1145     // package-private
poll(int events, long timeout)1146     int poll(int events, long timeout) throws IOException {
1147         assert Thread.holdsLock(blockingLock()) && !isBlocking();
1148 
1149         synchronized (readLock) {
1150             int n = 0;
1151             try {
1152                 begin();
1153                 synchronized (stateLock) {
1154                     if (!isOpen())
1155                         return 0;
1156                     readerThread = NativeThread.current();
1157                 }
1158                 n = Net.poll(fd, events, timeout);
1159             } finally {
1160                 readerThread = 0;
1161                 end(n > 0);
1162             }
1163             return n;
1164         }
1165     }
1166 
1167     /**
1168      * Translates an interest operation set into a native poll event set
1169      */
translateAndSetInterestOps(int ops, SelectionKeyImpl sk)1170     public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
1171         int newOps = 0;
1172 
1173         if ((ops & SelectionKey.OP_READ) != 0)
1174             newOps |= Net.POLLIN;
1175         if ((ops & SelectionKey.OP_WRITE) != 0)
1176             newOps |= Net.POLLOUT;
1177         if ((ops & SelectionKey.OP_CONNECT) != 0)
1178             newOps |= Net.POLLIN;
1179         sk.selector.putEventOps(sk, newOps);
1180     }
1181 
getFD()1182     public FileDescriptor getFD() {
1183         return fd;
1184     }
1185 
getFDVal()1186     public int getFDVal() {
1187         return fdVal;
1188     }
1189 
1190 
1191     // -- Native methods --
1192 
initIDs()1193     private static native void initIDs();
1194 
disconnect0(FileDescriptor fd, boolean isIPv6)1195     private static native void disconnect0(FileDescriptor fd, boolean isIPv6)
1196         throws IOException;
1197 
receive0(FileDescriptor fd, long address, int len, boolean connected)1198     private native int receive0(FileDescriptor fd, long address, int len,
1199                                 boolean connected)
1200         throws IOException;
1201 
send0(boolean preferIPv6, FileDescriptor fd, long address, int len, InetAddress addr, int port)1202     private native int send0(boolean preferIPv6, FileDescriptor fd, long address,
1203                              int len, InetAddress addr, int port)
1204         throws IOException;
1205 
1206     static {
initIDs()1207         initIDs();
1208     }
1209 
1210 }
1211