1 /* 2 * Copyright (c) 2001, 2012, 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 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 = 0; 62 private volatile long writerThread = 0; 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 return Net.getRevealedLocalAddress(localAddress); 173 } 174 } 175 176 @Override 177 public SocketAddress getRemoteAddress() throws IOException { 178 synchronized (stateLock) { 179 if (!isOpen()) 180 throw new ClosedChannelException(); 181 return remoteAddress; 182 } 183 } 184 185 @Override 186 public <T> DatagramChannel setOption(SocketOption<T> name, T value) 187 throws IOException 188 { 189 if (name == null) 190 throw new NullPointerException(); 191 if (!supportedOptions().contains(name)) 192 throw new UnsupportedOperationException("'" + name + "' not supported"); 193 194 synchronized (stateLock) { 195 ensureOpen(); 196 197 if (name == StandardSocketOptions.IP_TOS) { 198 // IPv4 only; no-op for IPv6 199 if (family == StandardProtocolFamily.INET) { 200 Net.setSocketOption(fd, family, name, value); 201 } 202 return this; 203 } 204 205 if (name == StandardSocketOptions.IP_MULTICAST_TTL || 206 name == StandardSocketOptions.IP_MULTICAST_LOOP) 207 { 208 // options are protocol dependent 209 Net.setSocketOption(fd, family, name, value); 210 return this; 211 } 212 213 if (name == StandardSocketOptions.IP_MULTICAST_IF) { 214 if (value == null) 215 throw new IllegalArgumentException("Cannot set IP_MULTICAST_IF to 'null'"); 216 NetworkInterface interf = (NetworkInterface)value; 217 if (family == StandardProtocolFamily.INET6) { 218 int index = interf.getIndex(); 219 if (index == -1) 220 throw new IOException("Network interface cannot be identified"); 221 Net.setInterface6(fd, index); 222 } else { 223 // need IPv4 address to identify interface 224 Inet4Address target = Net.anyInet4Address(interf); 225 if (target == null) 226 throw new IOException("Network interface not configured for IPv4"); 227 int targetAddress = Net.inet4AsInt(target); 228 Net.setInterface4(fd, targetAddress); 229 } 230 return this; 231 } 232 if (name == StandardSocketOptions.SO_REUSEADDR && 233 Net.useExclusiveBind() && localAddress != null) 234 { 235 reuseAddressEmulated = true; 236 this.isReuseAddress = (Boolean)value; 237 } 238 239 // remaining options don't need any special handling 240 Net.setSocketOption(fd, Net.UNSPEC, name, value); 241 return this; 242 } 243 } 244 245 @Override 246 @SuppressWarnings("unchecked") 247 public <T> T getOption(SocketOption<T> name) 248 throws IOException 249 { 250 if (name == null) 251 throw new NullPointerException(); 252 if (!supportedOptions().contains(name)) 253 throw new UnsupportedOperationException("'" + name + "' not supported"); 254 255 synchronized (stateLock) { 256 ensureOpen(); 257 258 if (name == StandardSocketOptions.IP_TOS) { 259 // IPv4 only; always return 0 on IPv6 260 if (family == StandardProtocolFamily.INET) { 261 return (T) Net.getSocketOption(fd, family, name); 262 } else { 263 return (T) Integer.valueOf(0); 264 } 265 } 266 267 if (name == StandardSocketOptions.IP_MULTICAST_TTL || 268 name == StandardSocketOptions.IP_MULTICAST_LOOP) 269 { 270 return (T) Net.getSocketOption(fd, family, name); 271 } 272 273 if (name == StandardSocketOptions.IP_MULTICAST_IF) { 274 if (family == StandardProtocolFamily.INET) { 275 int address = Net.getInterface4(fd); 276 if (address == 0) 277 return null; // default interface 278 279 InetAddress ia = Net.inet4FromInt(address); 280 NetworkInterface ni = NetworkInterface.getByInetAddress(ia); 281 if (ni == null) 282 throw new IOException("Unable to map address to interface"); 283 return (T) ni; 284 } else { 285 int index = Net.getInterface6(fd); 286 if (index == 0) 287 return null; // default interface 288 289 NetworkInterface ni = NetworkInterface.getByIndex(index); 290 if (ni == null) 291 throw new IOException("Unable to map index to interface"); 292 return (T) ni; 293 } 294 } 295 296 if (name == StandardSocketOptions.SO_REUSEADDR && 297 reuseAddressEmulated) 298 { 299 return (T)Boolean.valueOf(isReuseAddress); 300 } 301 302 // no special handling 303 return (T) Net.getSocketOption(fd, Net.UNSPEC, name); 304 } 305 } 306 307 private static class DefaultOptionsHolder { 308 static final Set<SocketOption<?>> defaultOptions = defaultOptions(); 309 310 private static Set<SocketOption<?>> defaultOptions() { 311 HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(8); 312 set.add(StandardSocketOptions.SO_SNDBUF); 313 set.add(StandardSocketOptions.SO_RCVBUF); 314 set.add(StandardSocketOptions.SO_REUSEADDR); 315 set.add(StandardSocketOptions.SO_BROADCAST); 316 set.add(StandardSocketOptions.IP_TOS); 317 set.add(StandardSocketOptions.IP_MULTICAST_IF); 318 set.add(StandardSocketOptions.IP_MULTICAST_TTL); 319 set.add(StandardSocketOptions.IP_MULTICAST_LOOP); 320 return Collections.unmodifiableSet(set); 321 } 322 } 323 324 @Override 325 public final Set<SocketOption<?>> supportedOptions() { 326 return DefaultOptionsHolder.defaultOptions; 327 } 328 329 private void ensureOpen() throws ClosedChannelException { 330 if (!isOpen()) 331 throw new ClosedChannelException(); 332 } 333 334 private SocketAddress sender; // Set by receive0 (## ugh) 335 336 public SocketAddress receive(ByteBuffer dst) throws IOException { 337 if (dst.isReadOnly()) 338 throw new IllegalArgumentException("Read-only buffer"); 339 if (dst == null) 340 throw new NullPointerException(); 341 synchronized (readLock) { 342 ensureOpen(); 343 // Socket was not bound before attempting receive 344 if (localAddress() == null) 345 bind(null); 346 int n = 0; 347 ByteBuffer bb = null; 348 try { 349 begin(); 350 if (!isOpen()) 351 return null; 352 SecurityManager security = System.getSecurityManager(); 353 readerThread = NativeThread.current(); 354 if (isConnected() || (security == null)) { 355 do { 356 n = receive(fd, dst); 357 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 358 if (n == IOStatus.UNAVAILABLE) 359 return null; 360 } else { 361 bb = Util.getTemporaryDirectBuffer(dst.remaining()); 362 for (;;) { 363 do { 364 n = receive(fd, bb); 365 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 366 if (n == IOStatus.UNAVAILABLE) 367 return null; 368 InetSocketAddress isa = (InetSocketAddress)sender; 369 try { 370 security.checkAccept( 371 isa.getAddress().getHostAddress(), 372 isa.getPort()); 373 } catch (SecurityException se) { 374 // Ignore packet 375 bb.clear(); 376 n = 0; 377 continue; 378 } 379 bb.flip(); 380 dst.put(bb); 381 break; 382 } 383 } 384 return sender; 385 } finally { 386 if (bb != null) 387 Util.releaseTemporaryDirectBuffer(bb); 388 readerThread = 0; 389 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 390 assert IOStatus.check(n); 391 } 392 } 393 } 394 395 private int receive(FileDescriptor fd, ByteBuffer dst) 396 throws IOException 397 { 398 int pos = dst.position(); 399 int lim = dst.limit(); 400 assert (pos <= lim); 401 int rem = (pos <= lim ? lim - pos : 0); 402 if (dst instanceof DirectBuffer && rem > 0) 403 return receiveIntoNativeBuffer(fd, dst, rem, pos); 404 405 // Substitute a native buffer. If the supplied buffer is empty 406 // we must instead use a nonempty buffer, otherwise the call 407 // will not block waiting for a datagram on some platforms. 408 int newSize = Math.max(rem, 1); 409 ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize); 410 try { 411 int n = receiveIntoNativeBuffer(fd, bb, newSize, 0); 412 bb.flip(); 413 if (n > 0 && rem > 0) 414 dst.put(bb); 415 return n; 416 } finally { 417 Util.releaseTemporaryDirectBuffer(bb); 418 } 419 } 420 421 private int receiveIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, 422 int rem, int pos) 423 throws IOException 424 { 425 int n = receive0(fd, ((DirectBuffer)bb).address() + pos, rem, 426 isConnected()); 427 if (n > 0) 428 bb.position(pos + n); 429 return n; 430 } 431 432 public int send(ByteBuffer src, SocketAddress target) 433 throws IOException 434 { 435 if (src == null) 436 throw new NullPointerException(); 437 438 synchronized (writeLock) { 439 ensureOpen(); 440 InetSocketAddress isa = Net.checkAddress(target); 441 InetAddress ia = isa.getAddress(); 442 if (ia == null) 443 throw new IOException("Target address not resolved"); 444 synchronized (stateLock) { 445 if (!isConnected()) { 446 if (target == null) 447 throw new NullPointerException(); 448 SecurityManager sm = System.getSecurityManager(); 449 if (sm != null) { 450 if (ia.isMulticastAddress()) { 451 sm.checkMulticast(ia); 452 } else { 453 sm.checkConnect(ia.getHostAddress(), 454 isa.getPort()); 455 } 456 } 457 } else { // Connected case; Check address then write 458 if (!target.equals(remoteAddress)) { 459 throw new IllegalArgumentException( 460 "Connected address not equal to target address"); 461 } 462 return write(src); 463 } 464 } 465 466 int n = 0; 467 try { 468 begin(); 469 if (!isOpen()) 470 return 0; 471 writerThread = NativeThread.current(); 472 do { 473 n = send(fd, src, isa); 474 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 475 476 synchronized (stateLock) { 477 if (isOpen() && (localAddress == null)) { 478 localAddress = Net.localAddress(fd); 479 } 480 } 481 return IOStatus.normalize(n); 482 } finally { 483 writerThread = 0; 484 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 485 assert IOStatus.check(n); 486 } 487 } 488 } 489 490 private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target) 491 throws IOException 492 { 493 if (src instanceof DirectBuffer) 494 return sendFromNativeBuffer(fd, src, target); 495 496 // Substitute a native buffer 497 int pos = src.position(); 498 int lim = src.limit(); 499 assert (pos <= lim); 500 int rem = (pos <= lim ? lim - pos : 0); 501 502 ByteBuffer bb = Util.getTemporaryDirectBuffer(rem); 503 try { 504 bb.put(src); 505 bb.flip(); 506 // Do not update src until we see how many bytes were written 507 src.position(pos); 508 509 int n = sendFromNativeBuffer(fd, bb, target); 510 if (n > 0) { 511 // now update src 512 src.position(pos + n); 513 } 514 return n; 515 } finally { 516 Util.releaseTemporaryDirectBuffer(bb); 517 } 518 } 519 520 private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, 521 InetSocketAddress target) 522 throws IOException 523 { 524 int pos = bb.position(); 525 int lim = bb.limit(); 526 assert (pos <= lim); 527 int rem = (pos <= lim ? lim - pos : 0); 528 529 boolean preferIPv6 = (family != StandardProtocolFamily.INET); 530 int written; 531 try { 532 written = send0(preferIPv6, fd, ((DirectBuffer)bb).address() + pos, 533 rem, target.getAddress(), target.getPort()); 534 } catch (PortUnreachableException pue) { 535 if (isConnected()) 536 throw pue; 537 written = rem; 538 } 539 if (written > 0) 540 bb.position(pos + written); 541 return written; 542 } 543 544 public int read(ByteBuffer buf) throws IOException { 545 if (buf == null) 546 throw new NullPointerException(); 547 synchronized (readLock) { 548 synchronized (stateLock) { 549 ensureOpen(); 550 if (!isConnected()) 551 throw new NotYetConnectedException(); 552 } 553 int n = 0; 554 try { 555 begin(); 556 if (!isOpen()) 557 return 0; 558 readerThread = NativeThread.current(); 559 do { 560 n = IOUtil.read(fd, buf, -1, nd); 561 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 562 return IOStatus.normalize(n); 563 } finally { 564 readerThread = 0; 565 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 566 assert IOStatus.check(n); 567 } 568 } 569 } 570 571 public long read(ByteBuffer[] dsts, int offset, int length) 572 throws IOException 573 { 574 if ((offset < 0) || (length < 0) || (offset > dsts.length - length)) 575 throw new IndexOutOfBoundsException(); 576 synchronized (readLock) { 577 synchronized (stateLock) { 578 ensureOpen(); 579 if (!isConnected()) 580 throw new NotYetConnectedException(); 581 } 582 long n = 0; 583 try { 584 begin(); 585 if (!isOpen()) 586 return 0; 587 readerThread = NativeThread.current(); 588 do { 589 n = IOUtil.read(fd, dsts, offset, length, nd); 590 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 591 return IOStatus.normalize(n); 592 } finally { 593 readerThread = 0; 594 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 595 assert IOStatus.check(n); 596 } 597 } 598 } 599 600 public int write(ByteBuffer buf) throws IOException { 601 if (buf == null) 602 throw new NullPointerException(); 603 synchronized (writeLock) { 604 synchronized (stateLock) { 605 ensureOpen(); 606 if (!isConnected()) 607 throw new NotYetConnectedException(); 608 } 609 int n = 0; 610 try { 611 begin(); 612 if (!isOpen()) 613 return 0; 614 writerThread = NativeThread.current(); 615 do { 616 n = IOUtil.write(fd, buf, -1, nd); 617 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 618 return IOStatus.normalize(n); 619 } finally { 620 writerThread = 0; 621 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 622 assert IOStatus.check(n); 623 } 624 } 625 } 626 627 public long write(ByteBuffer[] srcs, int offset, int length) 628 throws IOException 629 { 630 if ((offset < 0) || (length < 0) || (offset > srcs.length - length)) 631 throw new IndexOutOfBoundsException(); 632 synchronized (writeLock) { 633 synchronized (stateLock) { 634 ensureOpen(); 635 if (!isConnected()) 636 throw new NotYetConnectedException(); 637 } 638 long n = 0; 639 try { 640 begin(); 641 if (!isOpen()) 642 return 0; 643 writerThread = NativeThread.current(); 644 do { 645 n = IOUtil.write(fd, srcs, offset, length, nd); 646 } while ((n == IOStatus.INTERRUPTED) && isOpen()); 647 return IOStatus.normalize(n); 648 } finally { 649 writerThread = 0; 650 end((n > 0) || (n == IOStatus.UNAVAILABLE)); 651 assert IOStatus.check(n); 652 } 653 } 654 } 655 656 protected void implConfigureBlocking(boolean block) throws IOException { 657 IOUtil.configureBlocking(fd, block); 658 } 659 660 public SocketAddress localAddress() { 661 synchronized (stateLock) { 662 return localAddress; 663 } 664 } 665 666 public SocketAddress remoteAddress() { 667 synchronized (stateLock) { 668 return remoteAddress; 669 } 670 } 671 672 @Override 673 public DatagramChannel bind(SocketAddress local) throws IOException { 674 synchronized (readLock) { 675 synchronized (writeLock) { 676 synchronized (stateLock) { 677 ensureOpen(); 678 if (localAddress != null) 679 throw new AlreadyBoundException(); 680 InetSocketAddress isa; 681 if (local == null) { 682 // only Inet4Address allowed with IPv4 socket 683 if (family == StandardProtocolFamily.INET) { 684 isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0); 685 } else { 686 isa = new InetSocketAddress(0); 687 } 688 } else { 689 isa = Net.checkAddress(local); 690 691 // only Inet4Address allowed with IPv4 socket 692 if (family == StandardProtocolFamily.INET) { 693 InetAddress addr = isa.getAddress(); 694 if (!(addr instanceof Inet4Address)) 695 throw new UnsupportedAddressTypeException(); 696 } 697 } 698 SecurityManager sm = System.getSecurityManager(); 699 if (sm != null) { 700 sm.checkListen(isa.getPort()); 701 } 702 Net.bind(family, fd, isa.getAddress(), isa.getPort()); 703 localAddress = Net.localAddress(fd); 704 } 705 } 706 } 707 return this; 708 } 709 710 public boolean isConnected() { 711 synchronized (stateLock) { 712 return (state == ST_CONNECTED); 713 } 714 } 715 716 void ensureOpenAndUnconnected() throws IOException { // package-private 717 synchronized (stateLock) { 718 if (!isOpen()) 719 throw new ClosedChannelException(); 720 if (state != ST_UNCONNECTED) 721 throw new IllegalStateException("Connect already invoked"); 722 } 723 } 724 725 @Override 726 public DatagramChannel connect(SocketAddress sa) throws IOException { 727 int localPort = 0; 728 729 synchronized(readLock) { 730 synchronized(writeLock) { 731 synchronized (stateLock) { 732 ensureOpenAndUnconnected(); 733 InetSocketAddress isa = Net.checkAddress(sa); 734 SecurityManager sm = System.getSecurityManager(); 735 if (sm != null) 736 sm.checkConnect(isa.getAddress().getHostAddress(), 737 isa.getPort()); 738 int n = Net.connect(family, 739 fd, 740 isa.getAddress(), 741 isa.getPort()); 742 if (n <= 0) 743 throw new Error(); // Can't happen 744 745 // Connection succeeded; disallow further invocation 746 state = ST_CONNECTED; 747 remoteAddress = isa; 748 sender = isa; 749 cachedSenderInetAddress = isa.getAddress(); 750 cachedSenderPort = isa.getPort(); 751 752 // set or refresh local address 753 localAddress = Net.localAddress(fd); 754 } 755 } 756 } 757 return this; 758 } 759 760 public DatagramChannel disconnect() throws IOException { 761 synchronized(readLock) { 762 synchronized(writeLock) { 763 synchronized (stateLock) { 764 if (!isConnected() || !isOpen()) 765 return this; 766 InetSocketAddress isa = remoteAddress; 767 SecurityManager sm = System.getSecurityManager(); 768 if (sm != null) 769 sm.checkConnect(isa.getAddress().getHostAddress(), 770 isa.getPort()); 771 boolean isIPv6 = (family == StandardProtocolFamily.INET6); 772 disconnect0(fd, isIPv6); 773 remoteAddress = null; 774 state = ST_UNCONNECTED; 775 776 // refresh local address 777 localAddress = Net.localAddress(fd); 778 } 779 } 780 } 781 return this; 782 } 783 784 /** 785 * Joins channel's socket to the given group/interface and 786 * optional source address. 787 */ 788 private MembershipKey innerJoin(InetAddress group, 789 NetworkInterface interf, 790 InetAddress source) 791 throws IOException 792 { 793 if (!group.isMulticastAddress()) 794 throw new IllegalArgumentException("Group not a multicast address"); 795 796 // check multicast address is compatible with this socket 797 if (group instanceof Inet4Address) { 798 if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) 799 throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); 800 } else if (group instanceof Inet6Address) { 801 if (family != StandardProtocolFamily.INET6) 802 throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); 803 } else { 804 throw new IllegalArgumentException("Address type not supported"); 805 } 806 807 // check source address 808 if (source != null) { 809 if (source.isAnyLocalAddress()) 810 throw new IllegalArgumentException("Source address is a wildcard address"); 811 if (source.isMulticastAddress()) 812 throw new IllegalArgumentException("Source address is multicast address"); 813 if (source.getClass() != group.getClass()) 814 throw new IllegalArgumentException("Source address is different type to group"); 815 } 816 817 SecurityManager sm = System.getSecurityManager(); 818 if (sm != null) 819 sm.checkMulticast(group); 820 821 synchronized (stateLock) { 822 if (!isOpen()) 823 throw new ClosedChannelException(); 824 825 // check the registry to see if we are already a member of the group 826 if (registry == null) { 827 registry = new MembershipRegistry(); 828 } else { 829 // return existing membership key 830 MembershipKey key = registry.checkMembership(group, interf, source); 831 if (key != null) 832 return key; 833 } 834 835 MembershipKeyImpl key; 836 if ((family == StandardProtocolFamily.INET6) && 837 ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) 838 { 839 int index = interf.getIndex(); 840 if (index == -1) 841 throw new IOException("Network interface cannot be identified"); 842 843 // need multicast and source address as byte arrays 844 byte[] groupAddress = Net.inet6AsByteArray(group); 845 byte[] sourceAddress = (source == null) ? null : 846 Net.inet6AsByteArray(source); 847 848 // join the group 849 int n = Net.join6(fd, groupAddress, index, sourceAddress); 850 if (n == IOStatus.UNAVAILABLE) 851 throw new UnsupportedOperationException(); 852 853 key = new MembershipKeyImpl.Type6(this, group, interf, source, 854 groupAddress, index, sourceAddress); 855 856 } else { 857 // need IPv4 address to identify interface 858 Inet4Address target = Net.anyInet4Address(interf); 859 if (target == null) 860 throw new IOException("Network interface not configured for IPv4"); 861 862 int groupAddress = Net.inet4AsInt(group); 863 int targetAddress = Net.inet4AsInt(target); 864 int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); 865 866 // join the group 867 int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); 868 if (n == IOStatus.UNAVAILABLE) 869 throw new UnsupportedOperationException(); 870 871 key = new MembershipKeyImpl.Type4(this, group, interf, source, 872 groupAddress, targetAddress, sourceAddress); 873 } 874 875 registry.add(key); 876 return key; 877 } 878 } 879 880 @Override 881 public MembershipKey join(InetAddress group, 882 NetworkInterface interf) 883 throws IOException 884 { 885 return innerJoin(group, interf, null); 886 } 887 888 @Override 889 public MembershipKey join(InetAddress group, 890 NetworkInterface interf, 891 InetAddress source) 892 throws IOException 893 { 894 if (source == null) 895 throw new NullPointerException("source address is null"); 896 return innerJoin(group, interf, source); 897 } 898 899 // package-private 900 void drop(MembershipKeyImpl key) { 901 assert key.channel() == this; 902 903 synchronized (stateLock) { 904 if (!key.isValid()) 905 return; 906 907 try { 908 if (key instanceof MembershipKeyImpl.Type6) { 909 MembershipKeyImpl.Type6 key6 = 910 (MembershipKeyImpl.Type6)key; 911 Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); 912 } else { 913 MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; 914 Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), 915 key4.source()); 916 } 917 } catch (IOException ioe) { 918 // should not happen 919 throw new AssertionError(ioe); 920 } 921 922 key.invalidate(); 923 registry.remove(key); 924 } 925 } 926 927 /** 928 * Block datagrams from given source if a memory to receive all 929 * datagrams. 930 */ 931 void block(MembershipKeyImpl key, InetAddress source) 932 throws IOException 933 { 934 assert key.channel() == this; 935 assert key.sourceAddress() == null; 936 937 synchronized (stateLock) { 938 if (!key.isValid()) 939 throw new IllegalStateException("key is no longer valid"); 940 if (source.isAnyLocalAddress()) 941 throw new IllegalArgumentException("Source address is a wildcard address"); 942 if (source.isMulticastAddress()) 943 throw new IllegalArgumentException("Source address is multicast address"); 944 if (source.getClass() != key.group().getClass()) 945 throw new IllegalArgumentException("Source address is different type to group"); 946 947 int n; 948 if (key instanceof MembershipKeyImpl.Type6) { 949 MembershipKeyImpl.Type6 key6 = 950 (MembershipKeyImpl.Type6)key; 951 n = Net.block6(fd, key6.groupAddress(), key6.index(), 952 Net.inet6AsByteArray(source)); 953 } else { 954 MembershipKeyImpl.Type4 key4 = 955 (MembershipKeyImpl.Type4)key; 956 n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), 957 Net.inet4AsInt(source)); 958 } 959 if (n == IOStatus.UNAVAILABLE) { 960 // ancient kernel 961 throw new UnsupportedOperationException(); 962 } 963 } 964 } 965 966 /** 967 * Unblock given source. 968 */ 969 void unblock(MembershipKeyImpl key, InetAddress source) { 970 assert key.channel() == this; 971 assert key.sourceAddress() == null; 972 973 synchronized (stateLock) { 974 if (!key.isValid()) 975 throw new IllegalStateException("key is no longer valid"); 976 977 try { 978 if (key instanceof MembershipKeyImpl.Type6) { 979 MembershipKeyImpl.Type6 key6 = 980 (MembershipKeyImpl.Type6)key; 981 Net.unblock6(fd, key6.groupAddress(), key6.index(), 982 Net.inet6AsByteArray(source)); 983 } else { 984 MembershipKeyImpl.Type4 key4 = 985 (MembershipKeyImpl.Type4)key; 986 Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), 987 Net.inet4AsInt(source)); 988 } 989 } catch (IOException ioe) { 990 // should not happen 991 throw new AssertionError(ioe); 992 } 993 } 994 } 995 996 protected void implCloseSelectableChannel() throws IOException { 997 synchronized (stateLock) { 998 if (state != ST_KILLED) 999 nd.preClose(fd); 1000 ResourceManager.afterUdpClose(); 1001 1002 // if member of mulitcast group then invalidate all keys 1003 if (registry != null) 1004 registry.invalidateAll(); 1005 1006 long th; 1007 if ((th = readerThread) != 0) 1008 NativeThread.signal(th); 1009 if ((th = writerThread) != 0) 1010 NativeThread.signal(th); 1011 if (!isRegistered()) 1012 kill(); 1013 } 1014 } 1015 1016 public void kill() throws IOException { 1017 synchronized (stateLock) { 1018 if (state == ST_KILLED) 1019 return; 1020 if (state == ST_UNINITIALIZED) { 1021 state = ST_KILLED; 1022 return; 1023 } 1024 assert !isOpen() && !isRegistered(); 1025 nd.close(fd); 1026 state = ST_KILLED; 1027 } 1028 } 1029 1030 protected void finalize() throws IOException { 1031 // fd is null if constructor threw exception 1032 if (fd != null) 1033 close(); 1034 } 1035 1036 /** 1037 * Translates native poll revent set into a ready operation set 1038 */ 1039 public boolean translateReadyOps(int ops, int initialOps, 1040 SelectionKeyImpl sk) { 1041 int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes 1042 int oldOps = sk.nioReadyOps(); 1043 int newOps = initialOps; 1044 1045 if ((ops & PollArrayWrapper.POLLNVAL) != 0) { 1046 // This should only happen if this channel is pre-closed while a 1047 // selection operation is in progress 1048 // ## Throw an error if this channel has not been pre-closed 1049 return false; 1050 } 1051 1052 if ((ops & (PollArrayWrapper.POLLERR 1053 | PollArrayWrapper.POLLHUP)) != 0) { 1054 newOps = intOps; 1055 sk.nioReadyOps(newOps); 1056 return (newOps & ~oldOps) != 0; 1057 } 1058 1059 if (((ops & PollArrayWrapper.POLLIN) != 0) && 1060 ((intOps & SelectionKey.OP_READ) != 0)) 1061 newOps |= SelectionKey.OP_READ; 1062 1063 if (((ops & PollArrayWrapper.POLLOUT) != 0) && 1064 ((intOps & SelectionKey.OP_WRITE) != 0)) 1065 newOps |= SelectionKey.OP_WRITE; 1066 1067 sk.nioReadyOps(newOps); 1068 return (newOps & ~oldOps) != 0; 1069 } 1070 1071 public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { 1072 return translateReadyOps(ops, sk.nioReadyOps(), sk); 1073 } 1074 1075 public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { 1076 return translateReadyOps(ops, 0, sk); 1077 } 1078 1079 /** 1080 * Translates an interest operation set into a native poll event set 1081 */ 1082 public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { 1083 int newOps = 0; 1084 1085 if ((ops & SelectionKey.OP_READ) != 0) 1086 newOps |= PollArrayWrapper.POLLIN; 1087 if ((ops & SelectionKey.OP_WRITE) != 0) 1088 newOps |= PollArrayWrapper.POLLOUT; 1089 if ((ops & SelectionKey.OP_CONNECT) != 0) 1090 newOps |= PollArrayWrapper.POLLIN; 1091 sk.selector.putEventOps(sk, newOps); 1092 } 1093 1094 public FileDescriptor getFD() { 1095 return fd; 1096 } 1097 1098 public int getFDVal() { 1099 return fdVal; 1100 } 1101 1102 1103 // -- Native methods -- 1104 1105 private static native void initIDs(); 1106 1107 private static native void disconnect0(FileDescriptor fd, boolean isIPv6) 1108 throws IOException; 1109 1110 private native int receive0(FileDescriptor fd, long address, int len, 1111 boolean connected) 1112 throws IOException; 1113 1114 private native int send0(boolean preferIPv6, FileDescriptor fd, long address, 1115 int len, InetAddress addr, int port) 1116 throws IOException; 1117 1118 static { 1119 Util.load(); 1120 initIDs(); 1121 } 1122 1123 }