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