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