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