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