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