1 /*
   2  * Copyright (c) 2001, 2021, 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.io.InterruptedIOException;
  31 import java.io.UncheckedIOException;
  32 import java.lang.invoke.MethodHandles;
  33 import java.lang.invoke.VarHandle;
  34 import java.lang.ref.Cleaner.Cleanable;
  35 import java.lang.reflect.Method;
  36 import java.net.DatagramSocket;
  37 import java.net.Inet4Address;
  38 import java.net.Inet6Address;
  39 import java.net.InetAddress;
  40 import java.net.InetSocketAddress;
  41 import java.net.NetworkInterface;
  42 import java.net.PortUnreachableException;
  43 import java.net.ProtocolFamily;
  44 import java.net.SocketAddress;
  45 import java.net.SocketException;
  46 import java.net.SocketOption;
  47 import java.net.SocketTimeoutException;
  48 import java.net.StandardProtocolFamily;
  49 import java.net.StandardSocketOptions;
  50 import java.nio.ByteBuffer;
  51 import java.nio.channels.AlreadyBoundException;
  52 import java.nio.channels.AlreadyConnectedException;
  53 import java.nio.channels.AsynchronousCloseException;
  54 import java.nio.channels.ClosedChannelException;
  55 import java.nio.channels.DatagramChannel;
  56 import java.nio.channels.IllegalBlockingModeException;
  57 import java.nio.channels.MembershipKey;
  58 import java.nio.channels.NotYetConnectedException;
  59 import java.nio.channels.SelectionKey;
  60 import java.nio.channels.spi.AbstractSelectableChannel;
  61 import java.nio.channels.spi.SelectorProvider;
  62 import java.security.AccessController;
  63 import java.security.PrivilegedExceptionAction;
  64 import java.util.Collections;
  65 import java.util.HashMap;
  66 import java.util.HashSet;
  67 import java.util.Map;
  68 import java.util.Objects;
  69 import java.util.Set;
  70 import java.util.concurrent.TimeUnit;
  71 import java.util.concurrent.locks.ReentrantLock;
  72 import java.util.function.Consumer;
  73 
  74 import jdk.internal.misc.VirtualThreads;
  75 import jdk.internal.ref.CleanerFactory;
  76 import sun.net.ResourceManager;
  77 import sun.net.ext.ExtendedSocketOptions;
  78 import sun.net.util.IPAddressUtil;
  79 
  80 /**
  81  * An implementation of DatagramChannels.
  82  */
  83 
  84 class DatagramChannelImpl
  85     extends DatagramChannel
  86     implements SelChImpl
  87 {
  88     // Used to make native read and write calls
  89     private static final NativeDispatcher nd = new DatagramDispatcher();
  90 
  91     // true if interruptible (can be false to emulate legacy DatagramSocket)
  92     private final boolean interruptible;
  93 
  94     // The protocol family of the socket
  95     private final ProtocolFamily family;
  96 
  97     // Our file descriptor
  98     private final FileDescriptor fd;
  99     private final int fdVal;
 100 
 101     // Native sockaddrs and cached InetSocketAddress for receive, protected by readLock
 102     private NativeSocketAddress sourceSockAddr;
 103     private NativeSocketAddress cachedSockAddr;
 104     private InetSocketAddress cachedInetSocketAddress;
 105 
 106     // Native sockaddr and cached objects for send, protected by writeLock
 107     private final NativeSocketAddress targetSockAddr;
 108     private InetSocketAddress previousTarget;
 109     private int previousSockAddrLength;
 110 
 111     // Cleaner to close file descriptor and free native socket address
 112     private final Cleanable cleaner;
 113 
 114     // Lock held by current reading or connecting thread
 115     private final ReentrantLock readLock = new ReentrantLock();
 116 
 117     // Lock held by current writing or connecting thread
 118     private final ReentrantLock writeLock = new ReentrantLock();
 119 
 120     // Lock held by any thread that modifies the state fields declared below
 121     // DO NOT invoke a blocking I/O operation while holding this lock!
 122     private final Object stateLock = new Object();
 123 
 124     // -- The following fields are protected by stateLock
 125 
 126     // State (does not necessarily increase monotonically)
 127     private static final int ST_UNCONNECTED = 0;
 128     private static final int ST_CONNECTED = 1;
 129     private static final int ST_CLOSING = 2;
 130     private static final int ST_CLOSED = 3;
 131     private int state;
 132 
 133     // IDs of native threads doing reads and writes, for signalling
 134     private long readerThread;
 135     private long writerThread;
 136 
 137     // Local and remote (connected) address
 138     private InetSocketAddress localAddress;
 139     private InetSocketAddress remoteAddress;
 140 
 141     // Local address prior to connecting
 142     private InetSocketAddress initialLocalAddress;
 143 
 144     // Socket adaptor, created lazily
 145     private static final VarHandle SOCKET;
 146     static {
 147         try {
 148             MethodHandles.Lookup l = MethodHandles.lookup();
 149             SOCKET = l.findVarHandle(DatagramChannelImpl.class, "socket", DatagramSocket.class);
 150         } catch (Exception e) {
 151             throw new InternalError(e);
 152         }
 153     }
 154     private volatile DatagramSocket socket;
 155 
 156     // Multicast support
 157     private MembershipRegistry registry;
 158 
 159     // set true when socket is bound and SO_REUSEADDRESS is emulated
 160     private boolean reuseAddressEmulated;
 161 
 162     // set true/false when socket is already bound and SO_REUSEADDR is emulated
 163     private boolean isReuseAddress;
 164 
 165     // lazily set to true when the socket is configured non-blocking
 166     private volatile boolean nonBlocking;
 167 
 168     // -- End of fields protected by stateLock
 169 
 170 
 171     DatagramChannelImpl(SelectorProvider sp, boolean interruptible) throws IOException {
 172         this(sp, (Net.isIPv6Available()
 173                 ? StandardProtocolFamily.INET6
 174                 : StandardProtocolFamily.INET),
 175                 interruptible);
 176     }
 177 
 178     DatagramChannelImpl(SelectorProvider sp, ProtocolFamily family, boolean interruptible)
 179         throws IOException
 180     {
 181         super(sp);
 182 
 183         Objects.requireNonNull(family, "'family' is null");
 184         if ((family != StandardProtocolFamily.INET) &&
 185                 (family != StandardProtocolFamily.INET6)) {
 186             throw new UnsupportedOperationException("Protocol family not supported");
 187         }
 188         if (family == StandardProtocolFamily.INET6 && !Net.isIPv6Available()) {
 189             throw new UnsupportedOperationException("IPv6 not available");
 190         }
 191 
 192         FileDescriptor fd = null;
 193         NativeSocketAddress[] sockAddrs = null;
 194 
 195         ResourceManager.beforeUdpCreate();
 196         boolean initialized = false;
 197         try {
 198             this.interruptible = interruptible;
 199             this.family = family;
 200             this.fd = fd = Net.socket(family, false);
 201             this.fdVal = IOUtil.fdVal(fd);
 202 
 203             sockAddrs = NativeSocketAddress.allocate(3);
 204             readLock.lock();
 205             try {
 206                 this.sourceSockAddr = sockAddrs[0];
 207                 this.cachedSockAddr = sockAddrs[1];
 208             } finally {
 209                 readLock.unlock();
 210             }
 211             this.targetSockAddr = sockAddrs[2];
 212 
 213             initialized = true;
 214         } finally {
 215             if (!initialized) {
 216                 if (sockAddrs != null) NativeSocketAddress.freeAll(sockAddrs);
 217                 if (fd != null) nd.close(fd);
 218                 ResourceManager.afterUdpClose();
 219             }
 220         }
 221 
 222         Runnable releaser = releaserFor(fd, sockAddrs);
 223         this.cleaner = CleanerFactory.cleaner().register(this, releaser);
 224     }
 225 
 226     DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
 227         throws IOException
 228     {
 229         super(sp);
 230 
 231         NativeSocketAddress[] sockAddrs = null;
 232 
 233         ResourceManager.beforeUdpCreate();
 234         boolean initialized = false;
 235         try {
 236             this.interruptible = true;
 237             this.family = Net.isIPv6Available()
 238                     ? StandardProtocolFamily.INET6
 239                     : StandardProtocolFamily.INET;
 240             this.fd = fd;
 241             this.fdVal = IOUtil.fdVal(fd);
 242 
 243             sockAddrs = NativeSocketAddress.allocate(3);
 244             readLock.lock();
 245             try {
 246                 this.sourceSockAddr = sockAddrs[0];
 247                 this.cachedSockAddr = sockAddrs[1];
 248             } finally {
 249                 readLock.unlock();
 250             }
 251             this.targetSockAddr = sockAddrs[2];
 252 
 253             initialized = true;
 254         } finally {
 255             if (!initialized) {
 256                 if (sockAddrs != null) NativeSocketAddress.freeAll(sockAddrs);
 257                 nd.close(fd);
 258                 ResourceManager.afterUdpClose();
 259             }
 260         }
 261 
 262         Runnable releaser = releaserFor(fd, sockAddrs);
 263         this.cleaner = CleanerFactory.cleaner().register(this, releaser);
 264 
 265         synchronized (stateLock) {
 266             this.localAddress = Net.localAddress(fd);
 267         }
 268     }
 269 
 270     // @throws ClosedChannelException if channel is closed
 271     private void ensureOpen() throws ClosedChannelException {
 272         if (!isOpen())
 273             throw new ClosedChannelException();
 274     }
 275 
 276     @Override
 277     public DatagramSocket socket() {
 278         DatagramSocket socket = this.socket;
 279         if (socket == null) {
 280             socket = DatagramSocketAdaptor.create(this);
 281             if (!SOCKET.compareAndSet(this, null, socket)) {
 282                 socket = this.socket;
 283             }
 284         }
 285         return socket;
 286     }
 287 
 288     @Override
 289     public SocketAddress getLocalAddress() throws IOException {
 290         synchronized (stateLock) {
 291             ensureOpen();
 292             // Perform security check before returning address
 293             return Net.getRevealedLocalAddress(localAddress);
 294         }
 295     }
 296 
 297     @Override
 298     public SocketAddress getRemoteAddress() throws IOException {
 299         synchronized (stateLock) {
 300             ensureOpen();
 301             return remoteAddress;
 302         }
 303     }
 304 
 305     /**
 306      * Returns the protocol family to specify to set/getSocketOption for the
 307      * given socket option.
 308      */
 309     private ProtocolFamily familyFor(SocketOption<?> name) {
 310         assert Thread.holdsLock(stateLock);
 311 
 312         // unspecified (most options)
 313         if (SocketOptionRegistry.findOption(name, Net.UNSPEC) != null)
 314             return Net.UNSPEC;
 315 
 316         // IPv4 socket
 317         if (family == StandardProtocolFamily.INET)
 318             return StandardProtocolFamily.INET;
 319 
 320         // IPv6 socket that is unbound
 321         if (localAddress == null)
 322             return StandardProtocolFamily.INET6;
 323 
 324         // IPv6 socket bound to wildcard or IPv6 address
 325         InetAddress address = localAddress.getAddress();
 326         if (address.isAnyLocalAddress() || (address instanceof Inet6Address))
 327             return StandardProtocolFamily.INET6;
 328 
 329         // IPv6 socket bound to IPv4 address
 330         if (Net.canUseIPv6OptionsWithIPv4LocalAddress()) {
 331             // IPV6_XXX options can be used
 332             return StandardProtocolFamily.INET6;
 333         } else {
 334             // IPV6_XXX options cannot be used
 335             return StandardProtocolFamily.INET;
 336         }
 337     }
 338 
 339     @Override
 340     public <T> DatagramChannel setOption(SocketOption<T> name, T value)
 341         throws IOException
 342     {
 343         Objects.requireNonNull(name);
 344         if (!supportedOptions().contains(name))
 345             throw new UnsupportedOperationException("'" + name + "' not supported");
 346         if (!name.type().isInstance(value))
 347             throw new IllegalArgumentException("Invalid value '" + value + "'");
 348 
 349         synchronized (stateLock) {
 350             ensureOpen();
 351 
 352             ProtocolFamily family = familyFor(name);
 353 
 354             // Some platforms require both IPV6_XXX and IP_XXX socket options to
 355             // be set when the channel's socket is IPv6 and it is used to send
 356             // IPv4 multicast datagrams. The IP_XXX socket options are set on a
 357             // best effort basis.
 358             boolean needToSetIPv4Option = (family != Net.UNSPEC)
 359                     && (this.family == StandardProtocolFamily.INET6)
 360                     && Net.shouldSetBothIPv4AndIPv6Options();
 361 
 362             // outgoing multicast interface
 363             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 364                 assert family != Net.UNSPEC;
 365                 NetworkInterface interf = (NetworkInterface) value;
 366                 if (family == StandardProtocolFamily.INET6) {
 367                     int index = interf.getIndex();
 368                     if (index == -1)
 369                         throw new IOException("Network interface cannot be identified");
 370                     Net.setInterface6(fd, index);
 371                 }
 372                 if (family == StandardProtocolFamily.INET || needToSetIPv4Option) {
 373                     // need IPv4 address to identify interface
 374                     Inet4Address target = Net.anyInet4Address(interf);
 375                     if (target != null) {
 376                         try {
 377                             Net.setInterface4(fd, Net.inet4AsInt(target));
 378                         } catch (IOException ioe) {
 379                             if (family == StandardProtocolFamily.INET) throw ioe;
 380                         }
 381                     } else if (family == StandardProtocolFamily.INET) {
 382                         throw new IOException("Network interface not configured for IPv4");
 383                     }
 384                 }
 385                 return this;
 386             }
 387 
 388             // SO_REUSEADDR needs special handling as it may be emulated
 389             if (name == StandardSocketOptions.SO_REUSEADDR
 390                 && Net.useExclusiveBind() && localAddress != null) {
 391                 reuseAddressEmulated = true;
 392                 this.isReuseAddress = (Boolean)value;
 393             }
 394 
 395             // remaining options don't need any special handling
 396             Net.setSocketOption(fd, family, name, value);
 397             if (needToSetIPv4Option && family != StandardProtocolFamily.INET) {
 398                 try {
 399                     Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value);
 400                 } catch (IOException ignore) { }
 401             }
 402 
 403             return this;
 404         }
 405     }
 406 
 407     @Override
 408     @SuppressWarnings("unchecked")
 409     public <T> T getOption(SocketOption<T> name)
 410         throws IOException
 411     {
 412         Objects.requireNonNull(name);
 413         if (!supportedOptions().contains(name))
 414             throw new UnsupportedOperationException("'" + name + "' not supported");
 415 
 416         synchronized (stateLock) {
 417             ensureOpen();
 418 
 419             ProtocolFamily family = familyFor(name);
 420 
 421             if (name == StandardSocketOptions.IP_MULTICAST_IF) {
 422                 if (family == StandardProtocolFamily.INET) {
 423                     int address = Net.getInterface4(fd);
 424                     if (address == 0)
 425                         return null;    // default interface
 426 
 427                     InetAddress ia = Net.inet4FromInt(address);
 428                     NetworkInterface ni = NetworkInterface.getByInetAddress(ia);
 429                     if (ni == null)
 430                         throw new IOException("Unable to map address to interface");
 431                     return (T) ni;
 432                 } else {
 433                     int index = Net.getInterface6(fd);
 434                     if (index == 0)
 435                         return null;    // default interface
 436 
 437                     NetworkInterface ni = NetworkInterface.getByIndex(index);
 438                     if (ni == null)
 439                         throw new IOException("Unable to map index to interface");
 440                     return (T) ni;
 441                 }
 442             }
 443 
 444             if (name == StandardSocketOptions.SO_REUSEADDR && reuseAddressEmulated) {
 445                 return (T) Boolean.valueOf(isReuseAddress);
 446             }
 447 
 448             // no special handling
 449             return (T) Net.getSocketOption(fd, family, name);
 450         }
 451     }
 452 
 453     private static class DefaultOptionsHolder {
 454         static final Set<SocketOption<?>> defaultOptions = defaultOptions();
 455 
 456         private static Set<SocketOption<?>> defaultOptions() {
 457             HashSet<SocketOption<?>> set = new HashSet<>();
 458             set.add(StandardSocketOptions.SO_SNDBUF);
 459             set.add(StandardSocketOptions.SO_RCVBUF);
 460             set.add(StandardSocketOptions.SO_REUSEADDR);
 461             if (Net.isReusePortAvailable()) {
 462                 set.add(StandardSocketOptions.SO_REUSEPORT);
 463             }
 464             set.add(StandardSocketOptions.SO_BROADCAST);
 465             set.add(StandardSocketOptions.IP_TOS);
 466             set.add(StandardSocketOptions.IP_MULTICAST_IF);
 467             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
 468             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
 469             set.addAll(ExtendedSocketOptions.datagramSocketOptions());
 470             return Collections.unmodifiableSet(set);
 471         }
 472     }
 473 
 474     @Override
 475     public final Set<SocketOption<?>> supportedOptions() {
 476         return DefaultOptionsHolder.defaultOptions;
 477     }
 478 
 479     @Override
 480     public void park(int event, long nanos) throws IOException {
 481         Thread thread = Thread.currentThread();
 482         if (thread.isVirtual()) {
 483             Poller.register(getFDVal(), event);
 484             try {
 485                 if (isOpen()) {
 486                     if (nanos == 0) {
 487                         VirtualThreads.park();
 488                     } else {
 489                         VirtualThreads.park(nanos);
 490                     }
 491                     if (!interruptible && thread.isInterrupted()) {
 492                         throw new InterruptedIOException();
 493                     }
 494                 }
 495             } finally {
 496                 Poller.deregister(getFDVal(), event);
 497             }
 498         } else {
 499             long millis;
 500             if (nanos == 0) {
 501                 millis = -1;
 502             } else {
 503                 millis = TimeUnit.NANOSECONDS.toMillis(nanos);
 504             }
 505             Net.poll(getFD(), event, millis);
 506         }
 507     }
 508 
 509     /**
 510      * Marks the beginning of a read operation that might block.
 511      *
 512      * @param blocking true if configured blocking
 513      * @param mustBeConnected true if the socket must be connected
 514      * @return remote address if connected
 515      * @throws ClosedChannelException if the channel is closed
 516      * @throws NotYetConnectedException if mustBeConnected and not connected
 517      * @throws IOException if socket not bound and cannot be bound
 518      */
 519     private SocketAddress beginRead(boolean blocking, boolean mustBeConnected)
 520         throws IOException
 521     {
 522         if (blocking && interruptible) {
 523             // set hook for Thread.interrupt
 524             begin();
 525         }
 526         SocketAddress remote;
 527         synchronized (stateLock) {
 528             ensureOpen();
 529             remote = remoteAddress;
 530             if ((remote == null) && mustBeConnected)
 531                 throw new NotYetConnectedException();
 532             if (localAddress == null)
 533                 bindInternal(null);
 534             if (blocking)
 535                 readerThread = NativeThread.current();
 536         }
 537         return remote;
 538     }
 539 
 540     /**
 541      * Marks the end of a read operation that may have blocked.
 542      *
 543      * @throws AsynchronousCloseException if the channel was closed asynchronously
 544      */
 545     private void endRead(boolean blocking, boolean completed)
 546         throws AsynchronousCloseException
 547     {
 548         if (blocking) {
 549             synchronized (stateLock) {
 550                 readerThread = 0;
 551                 if (state == ST_CLOSING) {
 552                     tryFinishClose();
 553                 }
 554             }
 555             if (interruptible) {
 556                 // remove hook for Thread.interrupt (may throw AsynchronousCloseException)
 557                 end(completed);
 558             } else if (!completed && !isOpen()) {
 559                 throw new AsynchronousCloseException();
 560             }
 561         }
 562     }
 563 
 564     @Override
 565     public SocketAddress receive(ByteBuffer dst) throws IOException {
 566         if (dst.isReadOnly())
 567             throw new IllegalArgumentException("Read-only buffer");
 568         readLock.lock();
 569         try {
 570             boolean blocking = isBlocking();
 571             SocketAddress sender = null;
 572             try {
 573                 SocketAddress remote = beginRead(blocking, false);
 574                 lockedConfigureNonBlockingIfNeeded();
 575                 boolean connected = (remote != null);
 576                 @SuppressWarnings("removal")
 577                 SecurityManager sm = System.getSecurityManager();
 578                 if (connected || (sm == null)) {
 579                     // connected or no security manager
 580                     int n = receive(dst, connected);
 581                     if (blocking) {
 582                         while (IOStatus.okayToRetry(n) && isOpen()) {
 583                             park(Net.POLLIN);
 584                             n = receive(dst, connected);
 585                         }
 586                     }
 587                     if (n >= 0) {
 588                         // sender address is in socket address buffer
 589                         sender = sourceSocketAddress();
 590                     }
 591                 } else {
 592                     // security manager and unconnected
 593                     sender = untrustedReceive(dst);
 594                 }
 595                 return sender;
 596             } finally {
 597                 endRead(blocking, (sender != null));
 598             }
 599         } finally {
 600             readLock.unlock();
 601         }
 602     }
 603 
 604     /**
 605      * Receives a datagram into an untrusted buffer. When there is a security
 606      * manager set, and the socket is not connected, datagrams have to be received
 607      * into a buffer that is not accessible to the user. The datagram is copied
 608      * into the user's buffer when the sender address is accepted by the security
 609      * manager.
 610      */
 611     private SocketAddress untrustedReceive(ByteBuffer dst) throws IOException {
 612         @SuppressWarnings("removal")
 613         SecurityManager sm = System.getSecurityManager();
 614         assert readLock.isHeldByCurrentThread()
 615                 && sm != null && remoteAddress == null;
 616 
 617         ByteBuffer bb = Util.getTemporaryDirectBuffer(dst.remaining());
 618         try {
 619             boolean blocking = isBlocking();
 620             for (;;) {
 621                 int n = receive(bb, false);
 622                 if (blocking) {
 623                     while (IOStatus.okayToRetry(n) && isOpen()) {
 624                         park(Net.POLLIN);
 625                         n = receive(bb, false);
 626                     }
 627                 }
 628                 if (n >= 0) {
 629                     // sender address is in socket address buffer
 630                     InetSocketAddress isa = sourceSocketAddress();
 631                     try {
 632                         sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
 633                         bb.flip();
 634                         dst.put(bb);
 635                         return isa;
 636                     } catch (SecurityException se) {
 637                         // ignore datagram
 638                         bb.clear();
 639                     }
 640                 } else {
 641                     return null;
 642                 }
 643             }
 644         } finally {
 645             Util.releaseTemporaryDirectBuffer(bb);
 646         }
 647     }
 648 
 649     /**
 650      * Receives a datagram into the given buffer.
 651      *
 652      * @apiNote This method is for use by the socket adaptor. The buffer is
 653      * assumed to be trusted, meaning it is not accessible to user code.
 654      *
 655      * @throws IllegalBlockingModeException if the channel is non-blocking
 656      * @throws SocketTimeoutException if the timeout elapses
 657      */
 658     SocketAddress blockingReceive(ByteBuffer dst, long nanos) throws IOException {
 659         readLock.lock();
 660         try {
 661             ensureOpen();
 662             if (!isBlocking())
 663                 throw new IllegalBlockingModeException();
 664             @SuppressWarnings("removal")
 665             SecurityManager sm = System.getSecurityManager();
 666             boolean connected = isConnected();
 667             SocketAddress sender;
 668             do {
 669                 if (nanos > 0) {
 670                     sender = trustedBlockingReceive(dst, nanos);
 671                 } else {
 672                     sender = trustedBlockingReceive(dst);
 673                 }
 674                 // check sender when security manager set and not connected
 675                 if (sm != null && !connected) {
 676                     InetSocketAddress isa = (InetSocketAddress) sender;
 677                     try {
 678                         sm.checkAccept(isa.getAddress().getHostAddress(), isa.getPort());
 679                     } catch (SecurityException e) {
 680                         sender = null;
 681                     }
 682                 }
 683             } while (sender == null);
 684             return sender;
 685         } finally {
 686             readLock.unlock();
 687         }
 688     }
 689 
 690     /**
 691      * Receives a datagram into given buffer. This method is used to support
 692      * the socket adaptor. The buffer is assumed to be trusted.
 693      * @throws SocketTimeoutException if the timeout elapses
 694      */
 695     private SocketAddress trustedBlockingReceive(ByteBuffer dst)
 696         throws IOException
 697     {
 698         assert readLock.isHeldByCurrentThread() && isBlocking();
 699         SocketAddress sender = null;
 700         try {
 701             SocketAddress remote = beginRead(true, false);
 702             boolean connected = (remote != null);
 703             lockedConfigureNonBlockingIfNeeded();
 704             int n = receive(dst, connected);
 705             while (IOStatus.okayToRetry(n) && isOpen()) {
 706                 park(Net.POLLIN);
 707                 n = receive(dst, connected);
 708             }
 709             if (n >= 0) {
 710                 // sender address is in socket address buffer
 711                 sender = sourceSocketAddress();
 712             }
 713             return sender;
 714         } finally {
 715             endRead(true, (sender != null));
 716         }
 717     }
 718 
 719     /**
 720      * Receives a datagram into given buffer with a timeout. This method is
 721      * used to support the socket adaptor. The buffer is assumed to be trusted.
 722      * @throws SocketTimeoutException if the timeout elapses
 723      */
 724     private SocketAddress trustedBlockingReceive(ByteBuffer dst, long nanos)
 725         throws IOException
 726     {
 727         assert readLock.isHeldByCurrentThread() && isBlocking();
 728         SocketAddress sender = null;
 729         try {
 730             SocketAddress remote = beginRead(true, false);
 731             boolean connected = (remote != null);
 732 
 733             // change socket to non-blocking
 734             lockedConfigureBlocking(false);
 735             try {
 736                 long startNanos = System.nanoTime();
 737                 int n = receive(dst, connected);
 738                 while (n == IOStatus.UNAVAILABLE && isOpen()) {
 739                     long remainingNanos = nanos - (System.nanoTime() - startNanos);
 740                     if (remainingNanos <= 0) {
 741                         throw new SocketTimeoutException("Receive timed out");
 742                     }
 743                     park(Net.POLLIN, remainingNanos);
 744                     n = receive(dst, connected);
 745                 }
 746                 if (n >= 0) {
 747                     // sender address is in socket address buffer
 748                     sender = sourceSocketAddress();
 749                 }
 750                 return sender;
 751             } finally {
 752                 // restore socket to blocking mode (if channel is open)
 753                 tryLockedConfigureBlocking(true);
 754             }
 755         } finally {
 756             endRead(true, (sender != null));
 757         }
 758     }
 759 
 760     private int receive(ByteBuffer dst, boolean connected) throws IOException {
 761         int pos = dst.position();
 762         int lim = dst.limit();
 763         assert (pos <= lim);
 764         int rem = (pos <= lim ? lim - pos : 0);
 765         if (dst instanceof DirectBuffer && rem > 0)
 766             return receiveIntoNativeBuffer(dst, rem, pos, connected);
 767 
 768         // Substitute a native buffer. If the supplied buffer is empty
 769         // we must instead use a nonempty buffer, otherwise the call
 770         // will not block waiting for a datagram on some platforms.
 771         int newSize = Math.max(rem, 1);
 772         ByteBuffer bb = Util.getTemporaryDirectBuffer(newSize);
 773         try {
 774             int n = receiveIntoNativeBuffer(bb, newSize, 0, connected);
 775             bb.flip();
 776             if (n > 0 && rem > 0)
 777                 dst.put(bb);
 778             return n;
 779         } finally {
 780             Util.releaseTemporaryDirectBuffer(bb);
 781         }
 782     }
 783 
 784     private int receiveIntoNativeBuffer(ByteBuffer bb, int rem, int pos,
 785                                         boolean connected)
 786         throws IOException
 787     {
 788         int n = receive0(fd,
 789                          ((DirectBuffer)bb).address() + pos, rem,
 790                          sourceSockAddr.address(),
 791                          connected);
 792         if (n > 0)
 793             bb.position(pos + n);
 794         return n;
 795     }
 796 
 797     /**
 798      * Return an InetSocketAddress to represent the source/sender socket address
 799      * in sourceSockAddr. Returns the cached InetSocketAddress if the source
 800      * address is the same as the cached address.
 801      */
 802     private InetSocketAddress sourceSocketAddress() throws IOException {
 803         assert readLock.isHeldByCurrentThread();
 804         if (cachedInetSocketAddress != null && sourceSockAddr.equals(cachedSockAddr)) {
 805             return cachedInetSocketAddress;
 806         }
 807         InetSocketAddress isa = sourceSockAddr.decode();
 808         // swap sourceSockAddr and cachedSockAddr
 809         NativeSocketAddress tmp = cachedSockAddr;
 810         cachedSockAddr = sourceSockAddr;
 811         sourceSockAddr = tmp;
 812         cachedInetSocketAddress = isa;
 813         return isa;
 814     }
 815 
 816     @Override
 817     public int send(ByteBuffer src, SocketAddress target)
 818         throws IOException
 819     {
 820         Objects.requireNonNull(src);
 821         InetSocketAddress isa = Net.checkAddress(target, family);
 822 
 823         writeLock.lock();
 824         try {
 825             boolean blocking = isBlocking();
 826             int n;
 827             boolean completed = false;
 828             try {
 829                 SocketAddress remote = beginWrite(blocking, false);
 830                 lockedConfigureNonBlockingIfNeeded();
 831                 if (remote != null) {
 832                     // connected
 833                     if (!target.equals(remote)) {
 834                         throw new AlreadyConnectedException();
 835                     }
 836                     n = IOUtil.write(fd, src, -1, nd);
 837                     if (blocking) {
 838                         while (IOStatus.okayToRetry(n) && isOpen()) {
 839                             park(Net.POLLOUT);
 840                             n = IOUtil.write(fd, src, -1, nd);
 841                         }
 842                     }
 843                     completed = (n > 0);
 844                 } else {
 845                     // not connected
 846                     @SuppressWarnings("removal")
 847                     SecurityManager sm = System.getSecurityManager();
 848                     InetAddress ia = isa.getAddress();
 849                     if (sm != null) {
 850                         if (ia.isMulticastAddress()) {
 851                             sm.checkMulticast(ia);
 852                         } else {
 853                             sm.checkConnect(ia.getHostAddress(), isa.getPort());
 854                         }
 855                     }
 856                     if (ia.isLinkLocalAddress())
 857                         isa = IPAddressUtil.toScopedAddress(isa);
 858                     if (isa.getPort() == 0)
 859                         throw new SocketException("Can't send to port 0");
 860                     n = send(fd, src, isa);
 861                     if (blocking) {
 862                         while (IOStatus.okayToRetry(n) && isOpen()) {
 863                             park(Net.POLLOUT);
 864                             n = send(fd, src, isa);
 865                         }
 866                     }
 867                     completed = (n >= 0);
 868                 }
 869             } finally {
 870                 endWrite(blocking, completed);
 871             }
 872             assert n >= 0 || n == IOStatus.UNAVAILABLE;
 873             return IOStatus.normalize(n);
 874         } finally {
 875             writeLock.unlock();
 876         }
 877     }
 878 
 879     /**
 880      * Sends a datagram from the bytes in given buffer.
 881      *
 882      * @apiNote This method is for use by the socket adaptor.
 883      *
 884      * @throws IllegalBlockingModeException if the channel is non-blocking
 885      */
 886     void blockingSend(ByteBuffer src, SocketAddress target) throws IOException {
 887         writeLock.lock();
 888         try {
 889             ensureOpen();
 890             if (!isBlocking())
 891                 throw new IllegalBlockingModeException();
 892             send(src, target);
 893         } finally {
 894             writeLock.unlock();
 895         }
 896     }
 897 
 898     private int send(FileDescriptor fd, ByteBuffer src, InetSocketAddress target)
 899         throws IOException
 900     {
 901         if (src instanceof DirectBuffer)
 902             return sendFromNativeBuffer(fd, src, target);
 903 
 904         // Substitute a native buffer
 905         int pos = src.position();
 906         int lim = src.limit();
 907         assert (pos <= lim);
 908         int rem = (pos <= lim ? lim - pos : 0);
 909 
 910         ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
 911         try {
 912             bb.put(src);
 913             bb.flip();
 914             // Do not update src until we see how many bytes were written
 915             src.position(pos);
 916 
 917             int n = sendFromNativeBuffer(fd, bb, target);
 918             if (n > 0) {
 919                 // now update src
 920                 src.position(pos + n);
 921             }
 922             return n;
 923         } finally {
 924             Util.releaseTemporaryDirectBuffer(bb);
 925         }
 926     }
 927 
 928     private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb,
 929                                      InetSocketAddress target)
 930         throws IOException
 931     {
 932         int pos = bb.position();
 933         int lim = bb.limit();
 934         assert (pos <= lim);
 935         int rem = (pos <= lim ? lim - pos : 0);
 936 
 937         int written;
 938         try {
 939             int addressLen = targetSocketAddress(target);
 940             written = send0(fd, ((DirectBuffer)bb).address() + pos, rem,
 941                             targetSockAddr.address(), addressLen);
 942         } catch (PortUnreachableException pue) {
 943             if (isConnected())
 944                 throw pue;
 945             written = rem;
 946         }
 947         if (written > 0)
 948             bb.position(pos + written);
 949         return written;
 950     }
 951 
 952     /**
 953      * Encodes the given InetSocketAddress into targetSockAddr, returning the
 954      * length of the sockaddr structure (sizeof struct sockaddr or sockaddr6).
 955      */
 956     private int targetSocketAddress(InetSocketAddress isa) {
 957         assert writeLock.isHeldByCurrentThread();
 958         // Nothing to do if target address is already in the buffer. Use
 959         // identity rather than equals as Inet6Address.equals ignores scope_id.
 960         if (isa == previousTarget)
 961             return previousSockAddrLength;
 962         previousTarget = null;
 963         int len = targetSockAddr.encode(family, isa);
 964         previousTarget = isa;
 965         previousSockAddrLength = len;
 966         return len;
 967     }
 968 
 969     @Override
 970     public int read(ByteBuffer buf) throws IOException {
 971         Objects.requireNonNull(buf);
 972 
 973         readLock.lock();
 974         try {
 975             boolean blocking = isBlocking();
 976             int n = 0;
 977             try {
 978                 beginRead(blocking, true);
 979                 lockedConfigureNonBlockingIfNeeded();
 980                 n = IOUtil.read(fd, buf, -1, nd);
 981                 if (blocking) {
 982                     while (IOStatus.okayToRetry(n) && isOpen()) {
 983                         park(Net.POLLIN);
 984                         n = IOUtil.read(fd, buf, -1, nd);
 985                     }
 986                 }
 987             } finally {
 988                 endRead(blocking, n > 0);
 989                 assert IOStatus.check(n);
 990             }
 991             return IOStatus.normalize(n);
 992         } finally {
 993             readLock.unlock();
 994         }
 995     }
 996 
 997     @Override
 998     public long read(ByteBuffer[] dsts, int offset, int length)
 999         throws IOException
1000     {
1001         Objects.checkFromIndexSize(offset, length, dsts.length);
1002 
1003         readLock.lock();
1004         try {
1005             boolean blocking = isBlocking();
1006             long n = 0;
1007             try {
1008                 beginRead(blocking, true);
1009                 lockedConfigureNonBlockingIfNeeded();
1010                 n = IOUtil.read(fd, dsts, offset, length, nd);
1011                 if (blocking) {
1012                     while (IOStatus.okayToRetry(n)  && isOpen()) {
1013                         park(Net.POLLIN);
1014                         n = IOUtil.read(fd, dsts, offset, length, nd);
1015                     }
1016                 }
1017             } finally {
1018                 endRead(blocking, n > 0);
1019                 assert IOStatus.check(n);
1020             }
1021             return IOStatus.normalize(n);
1022         } finally {
1023             readLock.unlock();
1024         }
1025     }
1026 
1027     /**
1028      * Marks the beginning of a write operation that might block.
1029      * @param blocking true if configured blocking
1030      * @param mustBeConnected true if the socket must be connected
1031      * @return remote address if connected
1032      * @throws ClosedChannelException if the channel is closed
1033      * @throws NotYetConnectedException if mustBeConnected and not connected
1034      * @throws IOException if socket not bound and cannot be bound
1035      */
1036     private SocketAddress beginWrite(boolean blocking, boolean mustBeConnected)
1037         throws IOException
1038     {
1039         if (blocking && interruptible) {
1040             // set hook for Thread.interrupt
1041             begin();
1042         }
1043         SocketAddress remote;
1044         synchronized (stateLock) {
1045             ensureOpen();
1046             remote = remoteAddress;
1047             if ((remote == null) && mustBeConnected)
1048                 throw new NotYetConnectedException();
1049             if (localAddress == null)
1050                 bindInternal(null);
1051             if (blocking)
1052                 writerThread = NativeThread.current();
1053         }
1054         return remote;
1055     }
1056 
1057     /**
1058      * Marks the end of a write operation that may have blocked.
1059      *
1060      * @throws AsynchronousCloseException if the channel was closed asynchronously
1061      */
1062     private void endWrite(boolean blocking, boolean completed)
1063         throws AsynchronousCloseException
1064     {
1065         if (blocking) {
1066             synchronized (stateLock) {
1067                 writerThread = 0;
1068                 if (state == ST_CLOSING) {
1069                     tryFinishClose();
1070                 }
1071             }
1072 
1073             if (interruptible) {
1074                 // remove hook for Thread.interrupt (may throw AsynchronousCloseException)
1075                 end(completed);
1076             } else if (!completed && !isOpen()) {
1077                 throw new AsynchronousCloseException();
1078             }
1079         }
1080     }
1081 
1082     @Override
1083     public int write(ByteBuffer buf) throws IOException {
1084         Objects.requireNonNull(buf);
1085 
1086         writeLock.lock();
1087         try {
1088             boolean blocking = isBlocking();
1089             int n = 0;
1090             try {
1091                 beginWrite(blocking, true);
1092                 lockedConfigureNonBlockingIfNeeded();
1093                 n = IOUtil.write(fd, buf, -1, nd);
1094                 if (blocking) {
1095                     while (IOStatus.okayToRetry(n) && isOpen()) {
1096                         park(Net.POLLOUT);
1097                         n = IOUtil.write(fd, buf, -1, nd);
1098                     }
1099                 }
1100             } finally {
1101                 endWrite(blocking, n > 0);
1102                 assert IOStatus.check(n);
1103             }
1104             return IOStatus.normalize(n);
1105         } finally {
1106             writeLock.unlock();
1107         }
1108     }
1109 
1110     @Override
1111     public long write(ByteBuffer[] srcs, int offset, int length)
1112         throws IOException
1113     {
1114         Objects.checkFromIndexSize(offset, length, srcs.length);
1115 
1116         writeLock.lock();
1117         try {
1118             boolean blocking = isBlocking();
1119             long n = 0;
1120             try {
1121                 beginWrite(blocking, true);
1122                 lockedConfigureNonBlockingIfNeeded();
1123                 n = IOUtil.write(fd, srcs, offset, length, nd);
1124                 if (blocking) {
1125                     while (IOStatus.okayToRetry(n) && isOpen()) {
1126                         park(Net.POLLOUT);
1127                         n = IOUtil.write(fd, srcs, offset, length, nd);
1128                     }
1129                 }
1130             } finally {
1131                 endWrite(blocking, n > 0);
1132                 assert IOStatus.check(n);
1133             }
1134             return IOStatus.normalize(n);
1135         } finally {
1136             writeLock.unlock();
1137         }
1138     }
1139 
1140     @Override
1141     protected void implConfigureBlocking(boolean block) throws IOException {
1142         readLock.lock();
1143         try {
1144             writeLock.lock();
1145             try {
1146                 lockedConfigureBlocking(block);
1147             } finally {
1148                 writeLock.unlock();
1149             }
1150         } finally {
1151             readLock.unlock();
1152         }
1153     }
1154 
1155     /**
1156      * Adjusts the blocking mode. readLock or writeLock must already be held.
1157      */
1158     private void lockedConfigureBlocking(boolean block) throws IOException {
1159         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
1160         synchronized (stateLock) {
1161             ensureOpen();
1162             // do nothing if virtual thread has forced the socket to be non-blocking
1163             if (!nonBlocking) {
1164                 IOUtil.configureBlocking(fd, block);
1165             }
1166         }
1167     }
1168 
1169     /**
1170      * Attempts to adjusts the blocking mode if the channel is open.
1171      * @return {@code true} if the blocking mode was adjusted
1172      */
1173     private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
1174         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
1175         synchronized (stateLock) {
1176             if (!nonBlocking && isOpen()) {
1177                 IOUtil.configureBlocking(fd, block);
1178                 return true;
1179             } else {
1180                 return false;
1181             }
1182         }
1183     }
1184 
1185     /**
1186      * Ensures that the socket is configured non-blocking when on a virtual
1187      * thread or a timeout is specified.
1188      * @throws IOException if there is an I/O error changing the blocking mode
1189      */
1190     private void lockedConfigureNonBlockingIfNeeded() throws IOException {
1191         assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
1192         if (!nonBlocking && Thread.currentThread().isVirtual()) {
1193             synchronized (stateLock) {
1194                 ensureOpen();
1195                 IOUtil.configureBlocking(fd, false);
1196                 nonBlocking = true;
1197             }
1198         }
1199     }
1200 
1201     InetSocketAddress localAddress() {
1202         synchronized (stateLock) {
1203             return localAddress;
1204         }
1205     }
1206 
1207     InetSocketAddress remoteAddress() {
1208         synchronized (stateLock) {
1209             return remoteAddress;
1210         }
1211     }
1212 
1213     @Override
1214     public DatagramChannel bind(SocketAddress local) throws IOException {
1215         readLock.lock();
1216         try {
1217             writeLock.lock();
1218             try {
1219                 synchronized (stateLock) {
1220                     ensureOpen();
1221                     if (localAddress != null)
1222                         throw new AlreadyBoundException();
1223                     bindInternal(local);
1224                 }
1225             } finally {
1226                 writeLock.unlock();
1227             }
1228         } finally {
1229             readLock.unlock();
1230         }
1231         return this;
1232     }
1233 
1234     private void bindInternal(SocketAddress local) throws IOException {
1235         assert Thread.holdsLock(stateLock )&& (localAddress == null);
1236 
1237         InetSocketAddress isa;
1238         if (local == null) {
1239             // only Inet4Address allowed with IPv4 socket
1240             if (family == StandardProtocolFamily.INET) {
1241                 isa = new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
1242             } else {
1243                 isa = new InetSocketAddress(0);
1244             }
1245         } else {
1246             isa = Net.checkAddress(local, family);
1247         }
1248         @SuppressWarnings("removal")
1249         SecurityManager sm = System.getSecurityManager();
1250         if (sm != null)
1251             sm.checkListen(isa.getPort());
1252 
1253         Net.bind(family, fd, isa.getAddress(), isa.getPort());
1254         localAddress = Net.localAddress(fd);
1255     }
1256 
1257     @Override
1258     public boolean isConnected() {
1259         synchronized (stateLock) {
1260             return (state == ST_CONNECTED);
1261         }
1262     }
1263 
1264     @Override
1265     public DatagramChannel connect(SocketAddress sa) throws IOException {
1266         return connect(sa, true);
1267     }
1268 
1269     /**
1270      * Connects the channel's socket.
1271      *
1272      * @param sa the remote address to which this channel is to be connected
1273      * @param check true to check if the channel is already connected.
1274      */
1275     DatagramChannel connect(SocketAddress sa, boolean check) throws IOException {
1276         InetSocketAddress isa = Net.checkAddress(sa, family);
1277         @SuppressWarnings("removal")
1278         SecurityManager sm = System.getSecurityManager();
1279         if (sm != null) {
1280             InetAddress ia = isa.getAddress();
1281             if (ia.isMulticastAddress()) {
1282                 sm.checkMulticast(ia);
1283             } else {
1284                 sm.checkConnect(ia.getHostAddress(), isa.getPort());
1285                 sm.checkAccept(ia.getHostAddress(), isa.getPort());
1286             }
1287         }
1288 
1289         readLock.lock();
1290         try {
1291             writeLock.lock();
1292             try {
1293                 synchronized (stateLock) {
1294                     ensureOpen();
1295                     if (check && state == ST_CONNECTED)
1296                         throw new AlreadyConnectedException();
1297                     if (isa.getPort() == 0)
1298                         throw new SocketException("Can't connect to port 0");
1299 
1300                     // ensure that the socket is bound
1301                     if (localAddress == null) {
1302                         bindInternal(null);
1303                     }
1304 
1305                     // capture local address before connect
1306                     initialLocalAddress = localAddress;
1307 
1308                     int n = Net.connect(family,
1309                                         fd,
1310                                         isa.getAddress(),
1311                                         isa.getPort());
1312                     if (n <= 0)
1313                         throw new Error();      // Can't happen
1314 
1315                     // connected
1316                     remoteAddress = isa;
1317                     state = ST_CONNECTED;
1318 
1319                     // refresh local address
1320                     localAddress = Net.localAddress(fd);
1321 
1322                     // flush any packets already received.
1323                     boolean blocking = isBlocking();
1324                     if (blocking) {
1325                         lockedConfigureBlocking(false);
1326                     }
1327                     try {
1328                         ByteBuffer buf = ByteBuffer.allocate(100);
1329                         while (receive(buf, false) >= 0) {
1330                             buf.clear();
1331                         }
1332                     } finally {
1333                         if (blocking) {
1334                             tryLockedConfigureBlocking(true);
1335                         }
1336                     }
1337                 }
1338             } finally {
1339                 writeLock.unlock();
1340             }
1341         } finally {
1342             readLock.unlock();
1343         }
1344         return this;
1345     }
1346 
1347     @Override
1348     public DatagramChannel disconnect() throws IOException {
1349         readLock.lock();
1350         try {
1351             writeLock.lock();
1352             try {
1353                 synchronized (stateLock) {
1354                     if (!isOpen() || (state != ST_CONNECTED))
1355                         return this;
1356 
1357                     // disconnect socket
1358                     boolean isIPv6 = (family == StandardProtocolFamily.INET6);
1359                     disconnect0(fd, isIPv6);
1360 
1361                     // no longer connected
1362                     remoteAddress = null;
1363                     state = ST_UNCONNECTED;
1364 
1365                     // refresh localAddress, should be same as it was prior to connect
1366                     localAddress = Net.localAddress(fd);
1367                     try {
1368                         if (!localAddress.equals(initialLocalAddress)) {
1369                             // Workaround connect(2) issues on Linux and macOS
1370                             repairSocket(initialLocalAddress);
1371                             assert (localAddress != null)
1372                                     && localAddress.equals(Net.localAddress(fd))
1373                                     && localAddress.equals(initialLocalAddress);
1374                         }
1375                     } finally {
1376                         initialLocalAddress = null;
1377                     }
1378                 }
1379             } finally {
1380                 writeLock.unlock();
1381             }
1382         } finally {
1383             readLock.unlock();
1384         }
1385         return this;
1386     }
1387 
1388     /**
1389      * "Repair" the channel's socket after a disconnect that didn't restore the
1390      * local address.
1391      *
1392      * On Linux, connect(2) dissolves the association but changes the local port
1393      * to 0 when it was initially bound to an ephemeral port. The workaround here
1394      * is to rebind to the original port.
1395      *
1396      * On macOS, connect(2) dissolves the association but rebinds the socket to
1397      * the wildcard address when it was initially bound to a specific address.
1398      * The workaround here is to re-create the socket.
1399      */
1400     private void repairSocket(InetSocketAddress target)
1401         throws IOException
1402     {
1403         assert Thread.holdsLock(stateLock);
1404 
1405         // Linux: try to bind the socket to the original address/port
1406         if (localAddress.getPort() == 0) {
1407             assert localAddress.getAddress().equals(target.getAddress());
1408             Net.bind(family, fd, target.getAddress(), target.getPort());
1409             localAddress = Net.localAddress(fd);
1410             return;
1411         }
1412 
1413         // capture the value of all existing socket options
1414         Map<SocketOption<?>, Object> map = new HashMap<>();
1415         for (SocketOption<?> option : supportedOptions()) {
1416             Object value = getOption(option);
1417             if (value != null) {
1418                 map.put(option, value);
1419             }
1420         }
1421 
1422         // macOS: re-create the socket.
1423         FileDescriptor newfd = Net.socket(family, false);
1424         try {
1425             // copy the socket options that are protocol family agnostic
1426             for (Map.Entry<SocketOption<?>, Object> e : map.entrySet()) {
1427                 SocketOption<?> option = e.getKey();
1428                 if (SocketOptionRegistry.findOption(option, Net.UNSPEC) != null) {
1429                     Object value = e.getValue();
1430                     try {
1431                         Net.setSocketOption(newfd, Net.UNSPEC, option, value);
1432                     } catch (IOException ignore) { }
1433                 }
1434             }
1435 
1436             // copy the blocking mode
1437             if (!isBlocking()) {
1438                 IOUtil.configureBlocking(newfd, false);
1439             }
1440 
1441             // dup this channel's socket to the new socket. If this succeeds then
1442             // fd will reference the new socket. If it fails then it will still
1443             // reference the old socket.
1444             nd.dup(newfd, fd);
1445         } finally {
1446             // release the file descriptor
1447             nd.close(newfd);
1448         }
1449 
1450         // bind to the original local address
1451         try {
1452             Net.bind(family, fd, target.getAddress(), target.getPort());
1453         } catch (IOException ioe) {
1454             // bind failed, socket is left unbound
1455             localAddress = null;
1456             throw ioe;
1457         }
1458 
1459         // restore local address
1460         localAddress = Net.localAddress(fd);
1461 
1462         // restore all socket options (including those set in first pass)
1463         for (Map.Entry<SocketOption<?>, Object> e : map.entrySet()) {
1464             @SuppressWarnings("unchecked")
1465             SocketOption<Object> option = (SocketOption<Object>) e.getKey();
1466             Object value = e.getValue();
1467             try {
1468                 setOption(option, value);
1469             } catch (IOException ignore) { }
1470         }
1471 
1472         // restore multicast group membership
1473         MembershipRegistry registry = this.registry;
1474         if (registry != null) {
1475             registry.forEach(k -> {
1476                 if (k instanceof MembershipKeyImpl.Type6) {
1477                     MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6) k;
1478                     Net.join6(fd, key6.groupAddress(), key6.index(), key6.source());
1479                 } else {
1480                     MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4) k;
1481                     Net.join4(fd, key4.groupAddress(), key4.interfaceAddress(), key4.source());
1482                 }
1483             });
1484         }
1485 
1486         // reset registration in all Selectors that this channel is registered with
1487         AbstractSelectableChannels.forEach(this, SelectionKeyImpl::reset);
1488     }
1489 
1490     /**
1491      * Defines static methods to access AbstractSelectableChannel non-public members.
1492      */
1493     @SuppressWarnings("removal")
1494     private static class AbstractSelectableChannels {
1495         private static final Method FOREACH;
1496         static {
1497             try {
1498                 PrivilegedExceptionAction<Method> pae = () -> {
1499                     Method m = AbstractSelectableChannel.class.getDeclaredMethod("forEach", Consumer.class);
1500                     m.setAccessible(true);
1501                     return m;
1502                 };
1503                 FOREACH = AccessController.doPrivileged(pae);
1504             } catch (Exception e) {
1505                 throw new InternalError(e);
1506             }
1507         }
1508         static void forEach(AbstractSelectableChannel ch, Consumer<SelectionKeyImpl> action) {
1509             try {
1510                 FOREACH.invoke(ch, action);
1511             } catch (Exception e) {
1512                 throw new InternalError(e);
1513             }
1514         }
1515     }
1516 
1517     /**
1518      * Joins channel's socket to the given group/interface and
1519      * optional source address.
1520      */
1521     private MembershipKey innerJoin(InetAddress group,
1522                                     NetworkInterface interf,
1523                                     InetAddress source)
1524         throws IOException
1525     {
1526         if (!group.isMulticastAddress())
1527             throw new IllegalArgumentException("Group not a multicast address");
1528 
1529         // check multicast address is compatible with this socket
1530         if (group instanceof Inet4Address) {
1531             if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
1532                 throw new IllegalArgumentException("IPv6 socket cannot join IPv4 multicast group");
1533         } else if (group instanceof Inet6Address) {
1534             if (family != StandardProtocolFamily.INET6)
1535                 throw new IllegalArgumentException("Only IPv6 sockets can join IPv6 multicast group");
1536         } else {
1537             throw new IllegalArgumentException("Address type not supported");
1538         }
1539 
1540         // check source address
1541         if (source != null) {
1542             if (source.isAnyLocalAddress())
1543                 throw new IllegalArgumentException("Source address is a wildcard address");
1544             if (source.isMulticastAddress())
1545                 throw new IllegalArgumentException("Source address is multicast address");
1546             if (source.getClass() != group.getClass())
1547                 throw new IllegalArgumentException("Source address is different type to group");
1548         }
1549 
1550         @SuppressWarnings("removal")
1551         SecurityManager sm = System.getSecurityManager();
1552         if (sm != null)
1553             sm.checkMulticast(group);
1554 
1555         synchronized (stateLock) {
1556             ensureOpen();
1557 
1558             // check the registry to see if we are already a member of the group
1559             if (registry == null) {
1560                 registry = new MembershipRegistry();
1561             } else {
1562                 // return existing membership key
1563                 MembershipKey key = registry.checkMembership(group, interf, source);
1564                 if (key != null)
1565                     return key;
1566             }
1567 
1568             MembershipKeyImpl key;
1569             if ((family == StandardProtocolFamily.INET6) &&
1570                 ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
1571             {
1572                 int index = interf.getIndex();
1573                 if (index == -1)
1574                     throw new IOException("Network interface cannot be identified");
1575 
1576                 // need multicast and source address as byte arrays
1577                 byte[] groupAddress = Net.inet6AsByteArray(group);
1578                 byte[] sourceAddress = (source == null) ? null :
1579                     Net.inet6AsByteArray(source);
1580 
1581                 // join the group
1582                 int n = Net.join6(fd, groupAddress, index, sourceAddress);
1583                 if (n == IOStatus.UNAVAILABLE)
1584                     throw new UnsupportedOperationException();
1585 
1586                 key = new MembershipKeyImpl.Type6(this, group, interf, source,
1587                                                   groupAddress, index, sourceAddress);
1588 
1589             } else {
1590                 // need IPv4 address to identify interface
1591                 Inet4Address target = Net.anyInet4Address(interf);
1592                 if (target == null)
1593                     throw new IOException("Network interface not configured for IPv4");
1594 
1595                 int groupAddress = Net.inet4AsInt(group);
1596                 int targetAddress = Net.inet4AsInt(target);
1597                 int sourceAddress = (source == null) ? 0 : Net.inet4AsInt(source);
1598 
1599                 // join the group
1600                 int n = Net.join4(fd, groupAddress, targetAddress, sourceAddress);
1601                 if (n == IOStatus.UNAVAILABLE)
1602                     throw new UnsupportedOperationException();
1603 
1604                 key = new MembershipKeyImpl.Type4(this, group, interf, source,
1605                                                   groupAddress, targetAddress, sourceAddress);
1606             }
1607 
1608             registry.add(key);
1609             return key;
1610         }
1611     }
1612 
1613     @Override
1614     public MembershipKey join(InetAddress group,
1615                               NetworkInterface interf)
1616         throws IOException
1617     {
1618         return innerJoin(group, interf, null);
1619     }
1620 
1621     @Override
1622     public MembershipKey join(InetAddress group,
1623                               NetworkInterface interf,
1624                               InetAddress source)
1625         throws IOException
1626     {
1627         Objects.requireNonNull(source);
1628         return innerJoin(group, interf, source);
1629     }
1630 
1631     // package-private
1632     void drop(MembershipKeyImpl key) {
1633         assert key.channel() == this;
1634 
1635         synchronized (stateLock) {
1636             if (!key.isValid())
1637                 return;
1638 
1639             try {
1640                 if (key instanceof MembershipKeyImpl.Type6) {
1641                     MembershipKeyImpl.Type6 key6 =
1642                         (MembershipKeyImpl.Type6)key;
1643                     Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
1644                 } else {
1645                     MembershipKeyImpl.Type4 key4 = (MembershipKeyImpl.Type4)key;
1646                     Net.drop4(fd, key4.groupAddress(), key4.interfaceAddress(),
1647                         key4.source());
1648                 }
1649             } catch (IOException ioe) {
1650                 // should not happen
1651                 throw new AssertionError(ioe);
1652             }
1653 
1654             key.invalidate();
1655             registry.remove(key);
1656         }
1657     }
1658 
1659     /**
1660      * Finds an existing membership of a multicast group. Returns null if this
1661      * channel's socket is not a member of the group.
1662      *
1663      * @apiNote This method is for use by the socket adaptor
1664      */
1665     MembershipKey findMembership(InetAddress group, NetworkInterface interf) {
1666         synchronized (stateLock) {
1667             if (registry != null) {
1668                 return registry.checkMembership(group, interf, null);
1669             } else {
1670                 return null;
1671             }
1672         }
1673     }
1674 
1675     /**
1676      * Block datagrams from the given source.
1677      */
1678     void block(MembershipKeyImpl key, InetAddress source)
1679         throws IOException
1680     {
1681         assert key.channel() == this;
1682         assert key.sourceAddress() == null;
1683 
1684         synchronized (stateLock) {
1685             if (!key.isValid())
1686                 throw new IllegalStateException("key is no longer valid");
1687             if (source.isAnyLocalAddress())
1688                 throw new IllegalArgumentException("Source address is a wildcard address");
1689             if (source.isMulticastAddress())
1690                 throw new IllegalArgumentException("Source address is multicast address");
1691             if (source.getClass() != key.group().getClass())
1692                 throw new IllegalArgumentException("Source address is different type to group");
1693 
1694             int n;
1695             if (key instanceof MembershipKeyImpl.Type6) {
1696                  MembershipKeyImpl.Type6 key6 =
1697                     (MembershipKeyImpl.Type6)key;
1698                 n = Net.block6(fd, key6.groupAddress(), key6.index(),
1699                                Net.inet6AsByteArray(source));
1700             } else {
1701                 MembershipKeyImpl.Type4 key4 =
1702                     (MembershipKeyImpl.Type4)key;
1703                 n = Net.block4(fd, key4.groupAddress(), key4.interfaceAddress(),
1704                                Net.inet4AsInt(source));
1705             }
1706             if (n == IOStatus.UNAVAILABLE) {
1707                 // ancient kernel
1708                 throw new UnsupportedOperationException();
1709             }
1710         }
1711     }
1712 
1713     /**
1714      * Unblock the given source.
1715      */
1716     void unblock(MembershipKeyImpl key, InetAddress source) {
1717         assert key.channel() == this;
1718         assert key.sourceAddress() == null;
1719 
1720         synchronized (stateLock) {
1721             if (!key.isValid())
1722                 throw new IllegalStateException("key is no longer valid");
1723 
1724             try {
1725                 if (key instanceof MembershipKeyImpl.Type6) {
1726                     MembershipKeyImpl.Type6 key6 =
1727                         (MembershipKeyImpl.Type6)key;
1728                     Net.unblock6(fd, key6.groupAddress(), key6.index(),
1729                                  Net.inet6AsByteArray(source));
1730                 } else {
1731                     MembershipKeyImpl.Type4 key4 =
1732                         (MembershipKeyImpl.Type4)key;
1733                     Net.unblock4(fd, key4.groupAddress(), key4.interfaceAddress(),
1734                                  Net.inet4AsInt(source));
1735                 }
1736             } catch (IOException ioe) {
1737                 // should not happen
1738                 throw new AssertionError(ioe);
1739             }
1740         }
1741     }
1742 
1743     /**
1744      * Closes the socket if there are no I/O operations in progress and the
1745      * channel is not registered with a Selector.
1746      */
1747     private boolean tryClose() throws IOException {
1748         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
1749         if ((readerThread == 0) && (writerThread == 0) && !isRegistered()) {
1750             state = ST_CLOSED;
1751             try {
1752                 // close socket
1753                 cleaner.clean();
1754             } catch (UncheckedIOException ioe) {
1755                 throw ioe.getCause();
1756             }
1757             return true;
1758         } else {
1759             return false;
1760         }
1761     }
1762 
1763     /**
1764      * Invokes tryClose to attempt to close the socket.
1765      *
1766      * This method is used for deferred closing by I/O and Selector operations.
1767      */
1768     private void tryFinishClose() {
1769         try {
1770             tryClose();
1771         } catch (IOException ignore) { }
1772     }
1773 
1774     /**
1775      * Closes this channel when configured in blocking mode.
1776      *
1777      * If there is an I/O operation in progress then the socket is pre-closed
1778      * and the I/O threads signalled, in which case the final close is deferred
1779      * until all I/O operations complete.
1780      */
1781     private void implCloseBlockingMode() throws IOException {
1782         synchronized (stateLock) {
1783             assert state < ST_CLOSING;
1784             state = ST_CLOSING;
1785 
1786             // if member of any multicast groups then invalidate the keys
1787             if (registry != null)
1788                 registry.invalidateAll();
1789 
1790             if (!tryClose()) {
1791                 long reader = readerThread;
1792                 long writer = writerThread;
1793                 if (reader != 0 || writer != 0) {
1794                     if (NativeThread.isVirtualThread(reader)
1795                             || NativeThread.isVirtualThread(writer)) {
1796                         Poller.stopPoll(fdVal);
1797                     }
1798                     if (NativeThread.isKernelThread(reader)
1799                             || NativeThread.isKernelThread(writer)) {
1800                         nd.preClose(fd);
1801                         if (NativeThread.isKernelThread(reader))
1802                             NativeThread.signal(reader);
1803                         if (NativeThread.isKernelThread(writer))
1804                             NativeThread.signal(writer);
1805                     }
1806                 }
1807             }
1808         }
1809     }
1810 
1811     /**
1812      * Closes this channel when configured in non-blocking mode.
1813      *
1814      * If the channel is registered with a Selector then the close is deferred
1815      * until the channel is flushed from all Selectors.
1816      */
1817     private void implCloseNonBlockingMode() throws IOException {
1818         synchronized (stateLock) {
1819             assert state < ST_CLOSING;
1820             state = ST_CLOSING;
1821 
1822             // if member of any multicast groups then invalidate the keys
1823             if (registry != null)
1824                 registry.invalidateAll();
1825         }
1826 
1827         // wait for any read/write operations to complete before trying to close
1828         readLock.lock();
1829         readLock.unlock();
1830         writeLock.lock();
1831         writeLock.unlock();
1832         synchronized (stateLock) {
1833             if (state == ST_CLOSING) {
1834                 tryClose();
1835             }
1836         }
1837     }
1838 
1839     /**
1840      * Invoked by implCloseChannel to close the channel.
1841      */
1842     @Override
1843     protected void implCloseSelectableChannel() throws IOException {
1844         assert !isOpen();
1845         if (isBlocking()) {
1846             implCloseBlockingMode();
1847         } else {
1848             implCloseNonBlockingMode();
1849         }
1850     }
1851 
1852     @Override
1853     public void kill() {
1854         synchronized (stateLock) {
1855             if (state == ST_CLOSING) {
1856                 tryFinishClose();
1857             }
1858         }
1859     }
1860 
1861     /**
1862      * Translates native poll revent set into a ready operation set
1863      */
1864     public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
1865         int intOps = ski.nioInterestOps();
1866         int oldOps = ski.nioReadyOps();
1867         int newOps = initialOps;
1868 
1869         if ((ops & Net.POLLNVAL) != 0) {
1870             // This should only happen if this channel is pre-closed while a
1871             // selection operation is in progress
1872             // ## Throw an error if this channel has not been pre-closed
1873             return false;
1874         }
1875 
1876         if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
1877             newOps = intOps;
1878             ski.nioReadyOps(newOps);
1879             return (newOps & ~oldOps) != 0;
1880         }
1881 
1882         if (((ops & Net.POLLIN) != 0) &&
1883             ((intOps & SelectionKey.OP_READ) != 0))
1884             newOps |= SelectionKey.OP_READ;
1885 
1886         if (((ops & Net.POLLOUT) != 0) &&
1887             ((intOps & SelectionKey.OP_WRITE) != 0))
1888             newOps |= SelectionKey.OP_WRITE;
1889 
1890         ski.nioReadyOps(newOps);
1891         return (newOps & ~oldOps) != 0;
1892     }
1893 
1894     public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
1895         return translateReadyOps(ops, ski.nioReadyOps(), ski);
1896     }
1897 
1898     public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
1899         return translateReadyOps(ops, 0, ski);
1900     }
1901 
1902     /**
1903      * Translates an interest operation set into a native poll event set
1904      */
1905     public int translateInterestOps(int ops) {
1906         int newOps = 0;
1907         if ((ops & SelectionKey.OP_READ) != 0)
1908             newOps |= Net.POLLIN;
1909         if ((ops & SelectionKey.OP_WRITE) != 0)
1910             newOps |= Net.POLLOUT;
1911         if ((ops & SelectionKey.OP_CONNECT) != 0)
1912             newOps |= Net.POLLIN;
1913         return newOps;
1914     }
1915 
1916     public FileDescriptor getFD() {
1917         return fd;
1918     }
1919 
1920     public int getFDVal() {
1921         return fdVal;
1922     }
1923 
1924     /**
1925      * Returns an action to release the given file descriptor and socket addresses.
1926      */
1927     private static Runnable releaserFor(FileDescriptor fd, NativeSocketAddress... sockAddrs) {
1928         return () -> {
1929             try {
1930                 nd.close(fd);
1931             } catch (IOException ioe) {
1932                 throw new UncheckedIOException(ioe);
1933             } finally {
1934                 // decrement socket count and release memory
1935                 ResourceManager.afterUdpClose();
1936                 NativeSocketAddress.freeAll(sockAddrs);
1937             }
1938         };
1939     }
1940 
1941     // -- Native methods --
1942 
1943     private static native void disconnect0(FileDescriptor fd, boolean isIPv6)
1944         throws IOException;
1945 
1946     private static native int receive0(FileDescriptor fd, long address, int len,
1947                                        long senderAddress, boolean connected)
1948         throws IOException;
1949 
1950     private static native int send0(FileDescriptor fd, long address, int len,
1951                                     long targetAddress, int targetAddressLen)
1952         throws IOException;
1953 
1954     static {
1955         IOUtil.load();
1956     }
1957 }