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