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