1 /* 2 * Copyright (c) 2001, 2013, 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 * 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 // 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 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 // flush any packets already received. 745 boolean blocking = false; 746 synchronized (blockingLock()) { 747 try { 748 blocking = isBlocking(); 749 ByteBuffer tmpBuf = ByteBuffer.allocate(100); 750 if (blocking) { 751 configureBlocking(false); 752 } 753 do { 754 tmpBuf.clear(); 755 } while (receive(tmpBuf) != null); 756 } finally { 757 if (blocking) { 758 configureBlocking(true); 759 } 760 } 761 } 762 } 763 } 764 } 765 return this; 766 } 767 768 public DatagramChannel disconnect() throws IOException { 769 synchronized(readLock) { 770 synchronized(writeLock) { 771 synchronized (stateLock) { 772 if (!isConnected() || !isOpen()) 773 return this; 774 InetSocketAddress isa = remoteAddress; 775 SecurityManager sm = System.getSecurityManager(); 776 if (sm != null) 777 sm.checkConnect(isa.getAddress().getHostAddress(), 778 isa.getPort()); 779 boolean isIPv6 = (family == StandardProtocolFamily.INET6); 780 disconnect0(fd, isIPv6); 781 remoteAddress = null; 782 state = ST_UNCONNECTED; 783 784 // refresh local address 785 localAddress = Net.localAddress(fd); 786 } 787 } 788 } 789 return this; 790 } 791 792 /** 793 * Joins channel's socket to the given group/interface and 794 * optional source address. 795 */ 796 private MembershipKey innerJoin(InetAddress group, 797 NetworkInterface interf, 798 InetAddress source) 799 throws IOException 800 { 801 if (!group.isMulticastAddress()) 802 throw new IllegalArgumentException("Group not a multicast address"); 803 804 // check multicast address is compatible with this socket 805 if (group instanceof Inet4Address) { 806 if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) 807 throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group"); 808 } else if (group instanceof Inet6Address) { 809 if (family != StandardProtocolFamily.INET6) 810 throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group"); 811 } else { 812 throw new IllegalArgumentException("Address type not supported"); 813 } 814 815 // check source address 816 if (source != null) { 817 if (source.isAnyLocalAddress()) 818 throw new IllegalArgumentException("Source address is a wildcard address"); 819 if (source.isMulticastAddress()) 820 throw new IllegalArgumentException("Source address is multicast address"); 821 if (source.getClass() != group.getClass()) 822 throw new IllegalArgumentException("Source address is different type to group"); 823 } 824 825 SecurityManager sm = System.getSecurityManager(); 826 if (sm != null) 827 sm.checkMulticast(group); 828 829 synchronized (stateLock) { 830 if (!isOpen()) 831 throw new ClosedChannelException(); 832 833 // check the registry to see if we are already a member of the group 834 if (registry == null) { 835 registry = new MembershipRegistry(); 836 } else { 837 // return existing membership key 838 MembershipKey key = registry.checkMembership(group, interf, source); 839 if (key != null) 840 return key; 841 } 842 843 MembershipKeyImpl key; 844 if ((family == StandardProtocolFamily.INET6) && 845 ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) 846 { 847 int index = interf.getIndex(); 848 if (index == -1) 849 throw new IOException("Network interface cannot be identified"); 850 851 // need multicast and source address as byte arrays 852 byte[] groupAddress = Net.inet6AsByteArray(group); 853 byte[] sourceAddress = (source == null) ? null : 854 Net.inet6AsByteArray(source); 855 856 // join the group 857 int n = Net.join6(fd, groupAddress, index, sourceAddress); 858 if (n == IOStatus.UNAVAILABLE) 859 throw new UnsupportedOperationException(); 860 861 key = new MembershipKeyImpl.Type6(this, group, interf, source, 862 groupAddress, index, sourceAddress); 863 864 } else { 865 // need IPv4 address to identify interface 866 Inet4Address target = Net.anyInet4Address(interf); 867 if (target == null) 868 throw new IOException("Network interface not configured for IPv4"); 869 870 int groupAddress = Net.inet4AsInt(group); 871 int targetAddress = Net.inet4AsInt(target); 872 int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source); 873 874 // join the group 875 int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress); 876 if (n == IOStatus.UNAVAILABLE) 877 throw new UnsupportedOperationException(); 878 879 key = new MembershipKeyImpl.Type4(this, group, interf, source, 880 groupAddress, targetAddress, sourceAddress); 881 } 882 883 registry.add(key); 884 return key; 885 } 886 } 887 888 @Override 889 public MembershipKey join(InetAddress group, 890 NetworkInterface interf) 891 throws IOException 892 { 893 return innerJoin(group, interf, null); 894 } 895 896 @Override 897 public MembershipKey join(InetAddress group, 898 NetworkInterface interf, 899 InetAddress source) 900 throws IOException 901 { 902 if (source == null) 903 throw new NullPointerException("source address is null"); 904 return innerJoin(group, interf, source); 905 } 906 907 // package-private 908 void drop(MembershipKeyImpl key) { 909 assert key.channel() == this; 910 911 synchronized (stateLock) { 912 if (!key.isValid()) 913 return; 914 915 try { 916 if (key instanceof MembershipKeyImpl.Type6) { 917 MembershipKeyImpl.Type6 key6 = 918 (MembershipKeyImpl.Type6)key; 919 Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); 920 } else { 921 MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key; 922 Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(), 923 key4.source()); 924 } 925 } catch (IOException ioe) { 926 // should not happen 927 throw new AssertionError(ioe); 928 } 929 930 key.invalidate(); 931 registry.remove(key); 932 } 933 } 934 935 /** 936 * Block datagrams from given source if a memory to receive all 937 * datagrams. 938 */ 939 void block(MembershipKeyImpl key, InetAddress source) 940 throws IOException 941 { 942 assert key.channel() == this; 943 assert key.sourceAddress() == null; 944 945 synchronized (stateLock) { 946 if (!key.isValid()) 947 throw new IllegalStateException("key is no longer valid"); 948 if (source.isAnyLocalAddress()) 949 throw new IllegalArgumentException("Source address is a wildcard address"); 950 if (source.isMulticastAddress()) 951 throw new IllegalArgumentException("Source address is multicast address"); 952 if (source.getClass() != key.group().getClass()) 953 throw new IllegalArgumentException("Source address is different type to group"); 954 955 int n; 956 if (key instanceof MembershipKeyImpl.Type6) { 957 MembershipKeyImpl.Type6 key6 = 958 (MembershipKeyImpl.Type6)key; 959 n = Net.block6(fd, key6.groupAddress(), key6.index(), 960 Net.inet6AsByteArray(source)); 961 } else { 962 MembershipKeyImpl.Type4 key4 = 963 (MembershipKeyImpl.Type4)key; 964 n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(), 965 Net.inet4AsInt(source)); 966 } 967 if (n == IOStatus.UNAVAILABLE) { 968 // ancient kernel 969 throw new UnsupportedOperationException(); 970 } 971 } 972 } 973 974 /** 975 * Unblock given source. 976 */ 977 void unblock(MembershipKeyImpl key, InetAddress source) { 978 assert key.channel() == this; 979 assert key.sourceAddress() == null; 980 981 synchronized (stateLock) { 982 if (!key.isValid()) 983 throw new IllegalStateException("key is no longer valid"); 984 985 try { 986 if (key instanceof MembershipKeyImpl.Type6) { 987 MembershipKeyImpl.Type6 key6 = 988 (MembershipKeyImpl.Type6)key; 989 Net.unblock6(fd, key6.groupAddress(), key6.index(), 990 Net.inet6AsByteArray(source)); 991 } else { 992 MembershipKeyImpl.Type4 key4 = 993 (MembershipKeyImpl.Type4)key; 994 Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(), 995 Net.inet4AsInt(source)); 996 } 997 } catch (IOException ioe) { 998 // should not happen 999 throw new AssertionError(ioe); 1000 } 1001 } 1002 } 1003 1004 protected void implCloseSelectableChannel() throws IOException { 1005 synchronized (stateLock) { 1006 if (state != ST_KILLED) 1007 nd.preClose(fd); 1008 ResourceManager.afterUdpClose(); 1009 1010 // if member of mulitcast group then invalidate all keys 1011 if (registry != null) 1012 registry.invalidateAll(); 1013 1014 long th; 1015 if ((th = readerThread) != 0) 1016 NativeThread.signal(th); 1017 if ((th = writerThread) != 0) 1018 NativeThread.signal(th); 1019 if (!isRegistered()) 1020 kill(); 1021 } 1022 } 1023 1024 public void kill() throws IOException { 1025 synchronized (stateLock) { 1026 if (state == ST_KILLED) 1027 return; 1028 if (state == ST_UNINITIALIZED) { 1029 state = ST_KILLED; 1030 return; 1031 } 1032 assert !isOpen() && !isRegistered(); 1033 nd.close(fd); 1034 state = ST_KILLED; 1035 } 1036 } 1037 1038 protected void finalize() throws IOException { 1039 // fd is null if constructor threw exception 1040 if (fd != null) 1041 close(); 1042 } 1043 1044 /** 1045 * Translates native poll revent set into a ready operation set 1046 */ 1047 public boolean translateReadyOps(int ops, int initialOps, 1048 SelectionKeyImpl sk) { 1049 int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes 1050 int oldOps = sk.nioReadyOps(); 1051 int newOps = initialOps; 1052 1053 if ((ops & Net.POLLNVAL) != 0) { 1054 // This should only happen if this channel is pre-closed while a 1055 // selection operation is in progress 1056 // ## Throw an error if this channel has not been pre-closed 1057 return false; 1058 } 1059 1060 if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) { 1061 newOps = intOps; 1062 sk.nioReadyOps(newOps); 1063 return (newOps & ~oldOps) != 0; 1064 } 1065 1066 if (((ops & Net.POLLIN) != 0) && 1067 ((intOps & SelectionKey.OP_READ) != 0)) 1068 newOps |= SelectionKey.OP_READ; 1069 1070 if (((ops & Net.POLLOUT) != 0) && 1071 ((intOps & SelectionKey.OP_WRITE) != 0)) 1072 newOps |= SelectionKey.OP_WRITE; 1073 1074 sk.nioReadyOps(newOps); 1075 return (newOps & ~oldOps) != 0; 1076 } 1077 1078 public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) { 1079 return translateReadyOps(ops, sk.nioReadyOps(), sk); 1080 } 1081 1082 public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) { 1083 return translateReadyOps(ops, 0, sk); 1084 } 1085 1086 // package-private 1087 int poll(int events, long timeout) throws IOException { 1088 assert Thread.holdsLock(blockingLock()) && !isBlocking(); 1089 1090 synchronized (readLock) { 1091 int n = 0; 1092 try { 1093 begin(); 1094 synchronized (stateLock) { 1095 if (!isOpen()) 1096 return 0; 1097 readerThread = NativeThread.current(); 1098 } 1099 n = Net.poll(fd, events, timeout); 1100 } finally { 1101 readerThread = 0; 1102 end(n > 0); 1103 } 1104 return n; 1105 } 1106 } 1107 1108 /** 1109 * Translates an interest operation set into a native poll event set 1110 */ 1111 public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) { 1112 int newOps = 0; 1113 1114 if ((ops & SelectionKey.OP_READ) != 0) 1115 newOps |= Net.POLLIN; 1116 if ((ops & SelectionKey.OP_WRITE) != 0) 1117 newOps |= Net.POLLOUT; 1118 if ((ops & SelectionKey.OP_CONNECT) != 0) 1119 newOps |= Net.POLLIN; 1120 sk.selector.putEventOps(sk, newOps); 1121 } 1122 1123 public FileDescriptor getFD() { 1124 return fd; 1125 } 1126 1127 public int getFDVal() { 1128 return fdVal; 1129 } 1130 1131 1132 // -- Native methods -- 1133 1134 private static native void initIDs(); 1135 1136 private static native void disconnect0(FileDescriptor fd, boolean isIPv6) 1137 throws IOException; 1138 1139 private native int receive0(FileDescriptor fd, long address, int len, 1140 boolean connected) 1141 throws IOException; 1142 1143 private native int send0(boolean preferIPv6, FileDescriptor fd, long address, 1144 int len, InetAddress addr, int port) 1145 throws IOException; 1146 1147 static { 1148 IOUtil.load(); 1149 initIDs(); 1150 } 1151 1152 }