1 /*
   2  * Copyright (c) 2019, 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.InputStream;
  31 import java.io.OutputStream;
  32 import java.io.UncheckedIOException;
  33 import java.lang.ref.Cleaner.Cleanable;
  34 import java.net.InetAddress;
  35 import java.net.InetSocketAddress;
  36 import java.net.ProtocolFamily;
  37 import java.net.SocketAddress;
  38 import java.net.SocketException;
  39 import java.net.SocketImpl;
  40 import java.net.SocketOption;
  41 import java.net.SocketTimeoutException;
  42 import java.net.StandardProtocolFamily;
  43 import java.net.StandardSocketOptions;
  44 import java.net.UnknownHostException;
  45 import java.nio.ByteBuffer;
  46 import java.util.Collections;
  47 import java.util.HashSet;
  48 import java.util.Objects;
  49 import java.util.Set;
  50 import java.util.concurrent.TimeUnit;
  51 import java.util.concurrent.locks.ReentrantLock;
  52 
  53 import jdk.internal.ref.CleanerFactory;
  54 import sun.net.ConnectionResetException;
  55 import sun.net.NetHooks;
  56 import sun.net.PlatformSocketImpl;
  57 import sun.net.ResourceManager;
  58 import sun.net.ext.ExtendedSocketOptions;
  59 import sun.net.util.SocketExceptions;
  60 
  61 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  62 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  63 
  64 /**
  65  * NIO based SocketImpl.
  66  *
  67  * The underlying socket used by this SocketImpl is initially configured
  68  * blocking. If the connect method is used to establish a connection with a
  69  * timeout then the socket is configured non-blocking for the connect attempt,
  70  * and then restored to blocking mode when the connection is established.
  71  * If the accept or read methods are used with a timeout then the socket is
  72  * configured non-blocking and is never restored. When in non-blocking mode,
  73  * operations that don't complete immediately will poll the socket and preserve
  74  * the semantics of blocking operations.
  75  */
  76 
  77 public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
  78     private static final NativeDispatcher nd = new SocketDispatcher();
  79 
  80     // The maximum number of bytes to read/write per syscall to avoid needing
  81     // a huge buffer from the temporary buffer cache
  82     private static final int MAX_BUFFER_SIZE = 128 * 1024;
  83 
  84     // true if this is a SocketImpl for a ServerSocket
  85     private final boolean server;
  86 
  87     // Lock held when reading (also used when accepting or connecting)
  88     private final ReentrantLock readLock = new ReentrantLock();
  89 
  90     // Lock held when writing
  91     private final ReentrantLock writeLock = new ReentrantLock();
  92 
  93     // The stateLock for read/changing state
  94     private final Object stateLock = new Object();
  95     private static final int ST_NEW = 0;
  96     private static final int ST_UNCONNECTED = 1;
  97     private static final int ST_CONNECTING = 2;
  98     private static final int ST_CONNECTED = 3;
  99     private static final int ST_CLOSING = 4;
 100     private static final int ST_CLOSED = 5;
 101     private volatile int state;  // need stateLock to change
 102 
 103     // set by SocketImpl.create, protected by stateLock
 104     private boolean stream;
 105     private Cleanable cleaner;
 106 
 107     // set to true when the socket is in non-blocking mode
 108     private volatile boolean nonBlocking;
 109 
 110     // used by connect/read/write/accept, protected by stateLock
 111     private long readerThread;
 112     private long writerThread;
 113 
 114     // used when SO_REUSEADDR is emulated, protected by stateLock
 115     private boolean isReuseAddress;
 116 
 117     // read or accept timeout in millis
 118     private volatile int timeout;
 119 
 120     // flags to indicate if the connection is shutdown for input and output
 121     private volatile boolean isInputClosed;
 122     private volatile boolean isOutputClosed;
 123 
 124     // used by read to emulate legacy behavior, protected by readLock
 125     private boolean readEOF;
 126     private boolean connectionReset;
 127 
 128     /**
 129      * Creates an instance of this SocketImpl.
 130      * @param server true if this is a SocketImpl for a ServerSocket
 131      */
 132     public NioSocketImpl(boolean server) {
 133         this.server = server;
 134     }
 135 
 136     /**
 137      * Returns true if the socket is open.
 138      */
 139     private boolean isOpen() {
 140         return state < ST_CLOSING;
 141     }
 142 
 143     /**
 144      * Throws SocketException if the socket is not open.
 145      */
 146     private void ensureOpen() throws SocketException {
 147         int state = this.state;
 148         if (state == ST_NEW)
 149             throw new SocketException("Socket not created");
 150         if (state >= ST_CLOSING)
 151             throw new SocketException("Socket closed");
 152     }
 153 
 154     /**
 155      * Throws SocketException if the socket is not open and connected.
 156      */
 157     private void ensureOpenAndConnected() throws SocketException {
 158         int state = this.state;
 159         if (state < ST_CONNECTED)
 160             throw new SocketException("Not connected");
 161         if (state > ST_CONNECTED)
 162             throw new SocketException("Socket closed");
 163     }
 164 
 165     /**
 166      * Disables the current thread for scheduling purposes until the socket is
 167      * ready for I/O, or is asynchronously closed, for up to the specified
 168      * waiting time.
 169      * @throws IOException if an I/O error occurs
 170      */
 171     private void park(FileDescriptor fd, int event, long nanos) throws IOException {
 172         long millis;
 173         if (nanos == 0) {
 174             millis = -1;
 175         } else {
 176             millis = NANOSECONDS.toMillis(nanos);
 177         }
 178         Net.poll(fd, event, millis);
 179     }
 180 
 181     /**
 182      * Disables the current thread for scheduling purposes until the socket is
 183      * ready for I/O or is asynchronously closed.
 184      * @throws IOException if an I/O error occurs
 185      */
 186     private void park(FileDescriptor fd, int event) throws IOException {
 187         park(fd, event, 0);
 188     }
 189 
 190     /**
 191      * Configures the socket to blocking mode. This method is a no-op if the
 192      * socket is already in blocking mode.
 193      * @throws IOException if closed or there is an I/O error changing the mode
 194      */
 195     private void configureBlocking(FileDescriptor fd) throws IOException {
 196         assert readLock.isHeldByCurrentThread();
 197         if (nonBlocking) {
 198             synchronized (stateLock) {
 199                 ensureOpen();
 200                 IOUtil.configureBlocking(fd, true);
 201                 nonBlocking = false;
 202             }
 203         }
 204     }
 205 
 206     /**
 207      * Configures the socket to non-blocking mode. This method is a no-op if the
 208      * socket is already in non-blocking mode.
 209      * @throws IOException if closed or there is an I/O error changing the mode
 210      */
 211     private void configureNonBlocking(FileDescriptor fd) throws IOException {
 212         assert readLock.isHeldByCurrentThread();
 213         if (!nonBlocking) {
 214             synchronized (stateLock) {
 215                 ensureOpen();
 216                 IOUtil.configureBlocking(fd, false);
 217                 nonBlocking = true;
 218             }
 219         }
 220     }
 221 
 222     /**
 223      * Marks the beginning of a read operation that might block.
 224      * @throws SocketException if the socket is closed or not connected
 225      */
 226     private FileDescriptor beginRead() throws SocketException {
 227         synchronized (stateLock) {
 228             ensureOpenAndConnected();
 229             readerThread = NativeThread.current();
 230             return fd;
 231         }
 232     }
 233 
 234     /**
 235      * Marks the end of a read operation that may have blocked.
 236      * @throws SocketException is the socket is closed
 237      */
 238     private void endRead(boolean completed) throws SocketException {
 239         synchronized (stateLock) {
 240             readerThread = 0;
 241             int state = this.state;
 242             if (state == ST_CLOSING)
 243                 tryFinishClose();
 244             if (!completed && state >= ST_CLOSING)
 245                 throw new SocketException("Socket closed");
 246         }
 247     }
 248 
 249     /**
 250      * Attempts to read bytes from the socket into the given byte array.
 251      */
 252     private int tryRead(FileDescriptor fd, byte[] b, int off, int len)
 253         throws IOException
 254     {
 255         ByteBuffer dst = Util.getTemporaryDirectBuffer(len);
 256         assert dst.position() == 0;
 257         try {
 258             int n = nd.read(fd, ((DirectBuffer)dst).address(), len);
 259             if (n > 0) {
 260                 dst.get(b, off, n);
 261             }
 262             return n;
 263         } finally {
 264             Util.offerFirstTemporaryDirectBuffer(dst);
 265         }
 266     }
 267 
 268     /**
 269      * Reads bytes from the socket into the given byte array with a timeout.
 270      * @throws SocketTimeoutException if the read timeout elapses
 271      */
 272     private int timedRead(FileDescriptor fd, byte[] b, int off, int len, long nanos)
 273         throws IOException
 274     {
 275         long startNanos = System.nanoTime();
 276         int n = tryRead(fd, b, off, len);
 277         while (n == IOStatus.UNAVAILABLE && isOpen()) {
 278             long remainingNanos = nanos - (System.nanoTime() - startNanos);
 279             if (remainingNanos <= 0) {
 280                 throw new SocketTimeoutException("Read timed out");
 281             }
 282             park(fd, Net.POLLIN, remainingNanos);
 283             n = tryRead(fd, b, off, len);
 284         }
 285         return n;
 286     }
 287 
 288     /**
 289      * Reads bytes from the socket into the given byte array.
 290      * @return the number of bytes read or -1 at EOF
 291      * @throws SocketException if the socket is closed or a socket I/O error occurs
 292      * @throws SocketTimeoutException if the read timeout elapses
 293      */
 294     private int implRead(byte[] b, int off, int len) throws IOException {
 295         int n = 0;
 296         FileDescriptor fd = beginRead();
 297         try {
 298             if (connectionReset)
 299                 throw new SocketException("Connection reset");
 300             if (isInputClosed)
 301                 return -1;
 302             int timeout = this.timeout;
 303             if (timeout > 0) {
 304                 // read with timeout
 305                 configureNonBlocking(fd);
 306                 n = timedRead(fd, b, off, len, MILLISECONDS.toNanos(timeout));
 307             } else {
 308                 // read, no timeout
 309                 n = tryRead(fd, b, off, len);
 310                 while (IOStatus.okayToRetry(n) && isOpen()) {
 311                     park(fd, Net.POLLIN);
 312                     n = tryRead(fd, b, off, len);
 313                 }
 314             }
 315             return n;
 316         } catch (SocketTimeoutException e) {
 317             throw e;
 318         } catch (ConnectionResetException e) {
 319             connectionReset = true;
 320             throw new SocketException("Connection reset");
 321         } catch (IOException ioe) {
 322             throw new SocketException(ioe.getMessage());
 323         } finally {
 324             endRead(n > 0);
 325         }
 326     }
 327 
 328     /**
 329      * Reads bytes from the socket into the given byte array.
 330      * @return the number of bytes read or -1 at EOF
 331      * @throws IndexOutOfBoundsException if the bound checks fail
 332      * @throws SocketException if the socket is closed or a socket I/O error occurs
 333      * @throws SocketTimeoutException if the read timeout elapses
 334      */
 335     private int read(byte[] b, int off, int len) throws IOException {
 336         Objects.checkFromIndexSize(off, len, b.length);
 337         if (len == 0) {
 338             return 0;
 339         } else {
 340             readLock.lock();
 341             try {
 342                 // emulate legacy behavior to return -1, even if socket is closed
 343                 if (readEOF)
 344                     return -1;
 345                 // read up to MAX_BUFFER_SIZE bytes
 346                 int size = Math.min(len, MAX_BUFFER_SIZE);
 347                 int n = implRead(b, off, size);
 348                 if (n == -1)
 349                     readEOF = true;
 350                 return n;
 351             } finally {
 352                 readLock.unlock();
 353             }
 354         }
 355     }
 356 
 357     /**
 358      * Marks the beginning of a write operation that might block.
 359      * @throws SocketException if the socket is closed or not connected
 360      */
 361     private FileDescriptor beginWrite() throws SocketException {
 362         synchronized (stateLock) {
 363             ensureOpenAndConnected();
 364             writerThread = NativeThread.current();
 365             return fd;
 366         }
 367     }
 368 
 369     /**
 370      * Marks the end of a write operation that may have blocked.
 371      * @throws SocketException is the socket is closed
 372      */
 373     private void endWrite(boolean completed) throws SocketException {
 374         synchronized (stateLock) {
 375             writerThread = 0;
 376             int state = this.state;
 377             if (state == ST_CLOSING)
 378                 tryFinishClose();
 379             if (!completed && state >= ST_CLOSING)
 380                 throw new SocketException("Socket closed");
 381         }
 382     }
 383 
 384     /**
 385      * Attempts to write a sequence of bytes to the socket from the given
 386      * byte array.
 387      */
 388     private int tryWrite(FileDescriptor fd, byte[] b, int off, int len)
 389         throws IOException
 390     {
 391         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
 392         assert src.position() == 0;
 393         try {
 394             src.put(b, off, len);
 395             return nd.write(fd, ((DirectBuffer)src).address(), len);
 396         } finally {
 397             Util.offerFirstTemporaryDirectBuffer(src);
 398         }
 399     }
 400 
 401     /**
 402      * Writes a sequence of bytes to the socket from the given byte array.
 403      * @return the number of bytes written
 404      * @throws SocketException if the socket is closed or a socket I/O error occurs
 405      */
 406     private int implWrite(byte[] b, int off, int len) throws IOException {
 407         int n = 0;
 408         FileDescriptor fd = beginWrite();
 409         try {
 410             n = tryWrite(fd, b, off, len);
 411             while (IOStatus.okayToRetry(n) && isOpen()) {
 412                 park(fd, Net.POLLOUT);
 413                 n = tryWrite(fd, b, off, len);
 414             }
 415             return n;
 416         } catch (IOException ioe) {
 417             throw new SocketException(ioe.getMessage());
 418         } finally {
 419             endWrite(n > 0);
 420         }
 421     }
 422 
 423     /**
 424      * Writes a sequence of bytes to the socket from the given byte array.
 425      * @throws SocketException if the socket is closed or a socket I/O error occurs
 426      */
 427     private void write(byte[] b, int off, int len) throws IOException {
 428         Objects.checkFromIndexSize(off, len, b.length);
 429         if (len > 0) {
 430             writeLock.lock();
 431             try {
 432                 int pos = off;
 433                 int end = off + len;
 434                 while (pos < end) {
 435                     // write up to MAX_BUFFER_SIZE bytes
 436                     int size = Math.min((end - pos), MAX_BUFFER_SIZE);
 437                     int n = implWrite(b, pos, size);
 438                     pos += n;
 439                 }
 440             } finally {
 441                 writeLock.unlock();
 442             }
 443         }
 444     }
 445 
 446     /**
 447      * Creates the socket.
 448      * @param stream {@code true} for a streams socket
 449      */
 450     @Override
 451     protected void create(boolean stream) throws IOException {
 452         synchronized (stateLock) {
 453             if (state != ST_NEW)
 454                 throw new IOException("Already created");
 455             if (!stream)
 456                 ResourceManager.beforeUdpCreate();
 457             FileDescriptor fd;
 458             try {
 459                 if (server) {
 460                     assert stream;
 461                     fd = Net.serverSocket(true);
 462                 } else {
 463                     fd = Net.socket(stream);
 464                 }
 465             } catch (IOException ioe) {
 466                 if (!stream)
 467                     ResourceManager.afterUdpClose();
 468                 throw ioe;
 469             }
 470             Runnable closer = closerFor(fd, stream);
 471             this.fd = fd;
 472             this.stream = stream;
 473             this.cleaner = CleanerFactory.cleaner().register(this, closer);
 474             this.state = ST_UNCONNECTED;
 475         }
 476     }
 477 
 478     /**
 479      * Marks the beginning of a connect operation that might block.
 480      * @throws SocketException if the socket is closed or already connected
 481      */
 482     private FileDescriptor beginConnect(InetAddress address, int port)
 483         throws IOException
 484     {
 485         synchronized (stateLock) {
 486             int state = this.state;
 487             if (state != ST_UNCONNECTED) {
 488                 if (state == ST_NEW)
 489                     throw new SocketException("Not created");
 490                 if (state == ST_CONNECTING)
 491                     throw new SocketException("Connection in progress");
 492                 if (state == ST_CONNECTED)
 493                     throw new SocketException("Already connected");
 494                 if (state >= ST_CLOSING)
 495                     throw new SocketException("Socket closed");
 496                 assert false;
 497             }
 498             this.state = ST_CONNECTING;
 499 
 500             // invoke beforeTcpConnect hook if not already bound
 501             if (localport == 0) {
 502                 NetHooks.beforeTcpConnect(fd, address, port);
 503             }
 504 
 505             // save the remote address/port
 506             this.address = address;
 507             this.port = port;
 508 
 509             readerThread = NativeThread.current();
 510             return fd;
 511         }
 512     }
 513 
 514     /**
 515      * Marks the end of a connect operation that may have blocked.
 516      * @throws SocketException is the socket is closed
 517      */
 518     private void endConnect(FileDescriptor fd, boolean completed) throws IOException {
 519         synchronized (stateLock) {
 520             readerThread = 0;
 521             int state = this.state;
 522             if (state == ST_CLOSING)
 523                 tryFinishClose();
 524             if (completed && state == ST_CONNECTING) {
 525                 this.state = ST_CONNECTED;
 526                 localport = Net.localAddress(fd).getPort();
 527             } else if (!completed && state >= ST_CLOSING) {
 528                 throw new SocketException("Socket closed");
 529             }
 530         }
 531     }
 532 
 533     /**
 534      * Waits for a connection attempt to finish with a timeout
 535      * @throws SocketTimeoutException if the connect timeout elapses
 536      */
 537     private boolean timedFinishConnect(FileDescriptor fd, long nanos) throws IOException {
 538         long startNanos = System.nanoTime();
 539         boolean polled = Net.pollConnectNow(fd);
 540         while (!polled && isOpen()) {
 541             long remainingNanos = nanos - (System.nanoTime() - startNanos);
 542             if (remainingNanos <= 0) {
 543                 throw new SocketTimeoutException("Connect timed out");
 544             }
 545             park(fd, Net.POLLOUT, remainingNanos);
 546             polled = Net.pollConnectNow(fd);
 547         }
 548         return polled && isOpen();
 549     }
 550 
 551     /**
 552      * Attempts to establish a connection to the given socket address with a
 553      * timeout. Closes the socket if connection cannot be established.
 554      * @throws IOException if the address is not a resolved InetSocketAddress or
 555      *         the connection cannot be established
 556      */
 557     @Override
 558     protected void connect(SocketAddress remote, int millis) throws IOException {
 559         // SocketImpl connect only specifies IOException
 560         if (!(remote instanceof InetSocketAddress))
 561             throw new IOException("Unsupported address type");
 562         InetSocketAddress isa = (InetSocketAddress) remote;
 563         if (isa.isUnresolved()) {
 564             throw new UnknownHostException(isa.getHostName());
 565         }
 566 
 567         InetAddress address = isa.getAddress();
 568         if (address.isAnyLocalAddress())
 569             address = InetAddress.getLocalHost();
 570         int port = isa.getPort();
 571 
 572         ReentrantLock connectLock = readLock;
 573         try {
 574             connectLock.lock();
 575             try {
 576                 boolean connected = false;
 577                 FileDescriptor fd = beginConnect(address, port);
 578                 try {
 579 
 580                     // configure socket to non-blocking mode when there is a timeout
 581                     if (millis > 0) {
 582                         configureNonBlocking(fd);
 583                     }
 584 
 585                     int n = Net.connect(fd, address, port);
 586                     if (n > 0) {
 587                         // connection established
 588                         connected = true;
 589                     } else {
 590                         assert IOStatus.okayToRetry(n);
 591                         if (millis > 0) {
 592                             // finish connect with timeout
 593                             long nanos = MILLISECONDS.toNanos(millis);
 594                             connected = timedFinishConnect(fd, nanos);
 595                         } else {
 596                             // finish connect, no timeout
 597                             boolean polled = false;
 598                             while (!polled && isOpen()) {
 599                                 park(fd, Net.POLLOUT);
 600                                 polled = Net.pollConnectNow(fd);
 601                             }
 602                             connected = polled && isOpen();
 603                         }
 604                     }
 605 
 606                     // restore socket to blocking mode
 607                     if (connected && millis > 0) {
 608                         configureBlocking(fd);
 609                     }
 610 
 611                 } finally {
 612                     endConnect(fd, connected);
 613                 }
 614             } finally {
 615                 connectLock.unlock();
 616             }
 617         } catch (IOException ioe) {
 618             close();
 619             throw SocketExceptions.of(ioe, isa);
 620         }
 621     }
 622 
 623     @Override
 624     protected void connect(String host, int port) throws IOException {
 625         connect(new InetSocketAddress(host, port), 0);
 626     }
 627 
 628     @Override
 629     protected void connect(InetAddress address, int port) throws IOException {
 630         connect(new InetSocketAddress(address, port), 0);
 631     }
 632 
 633     @Override
 634     protected void bind(InetAddress host, int port) throws IOException {
 635         synchronized (stateLock) {
 636             ensureOpen();
 637             if (localport != 0)
 638                 throw new SocketException("Already bound");
 639             NetHooks.beforeTcpBind(fd, host, port);
 640             Net.bind(fd, host, port);
 641             // set the address field to the given host address to
 642             // maintain long standing behavior. When binding to 0.0.0.0
 643             // then the actual local address will be ::0 when IPv6 is enabled.
 644             address = host;
 645             localport = Net.localAddress(fd).getPort();
 646         }
 647     }
 648 
 649     @Override
 650     protected void listen(int backlog) throws IOException {
 651         synchronized (stateLock) {
 652             ensureOpen();
 653             if (localport == 0)
 654                 throw new SocketException("Not bound");
 655             Net.listen(fd, backlog < 1 ? 50 : backlog);
 656         }
 657     }
 658 
 659     /**
 660      * Marks the beginning of an accept operation that might block.
 661      * @throws SocketException if the socket is closed
 662      */
 663     private FileDescriptor beginAccept() throws SocketException {
 664         synchronized (stateLock) {
 665             ensureOpen();
 666             if (!stream)
 667                 throw new SocketException("Not a stream socket");
 668             if (localport == 0)
 669                 throw new SocketException("Not bound");
 670             readerThread = NativeThread.current();
 671             return fd;
 672         }
 673     }
 674 
 675     /**
 676      * Marks the end of an accept operation that may have blocked.
 677      * @throws SocketException is the socket is closed
 678      */
 679     private void endAccept(boolean completed) throws SocketException {
 680         synchronized (stateLock) {
 681             int state = this.state;
 682             readerThread = 0;
 683             if (state == ST_CLOSING)
 684                 tryFinishClose();
 685             if (!completed && state >= ST_CLOSING)
 686                 throw new SocketException("Socket closed");
 687         }
 688     }
 689 
 690     /**
 691      * Accepts a new connection with a timeout.
 692      * @throws SocketTimeoutException if the accept timeout elapses
 693      */
 694     private int timedAccept(FileDescriptor fd,
 695                             FileDescriptor newfd,
 696                             InetSocketAddress[] isaa,
 697                             long nanos)
 698         throws IOException
 699     {
 700         long startNanos = System.nanoTime();
 701         int n = Net.accept(fd, newfd, isaa);
 702         while (n == IOStatus.UNAVAILABLE && isOpen()) {
 703             long remainingNanos = nanos - (System.nanoTime() - startNanos);
 704             if (remainingNanos <= 0) {
 705                 throw new SocketTimeoutException("Accept timed out");
 706             }
 707             park(fd, Net.POLLIN, remainingNanos);
 708             n = Net.accept(fd, newfd, isaa);
 709         }
 710         return n;
 711     }
 712 
 713     /**
 714      * Accepts a new connection so that the given SocketImpl is connected to
 715      * the peer. The SocketImpl must be a newly created NioSocketImpl.
 716      */
 717     @Override
 718     protected void accept(SocketImpl si) throws IOException {
 719         NioSocketImpl nsi = (NioSocketImpl) si;
 720         if (nsi.state != ST_NEW)
 721             throw new SocketException("Not a newly created SocketImpl");
 722 
 723         FileDescriptor newfd = new FileDescriptor();
 724         InetSocketAddress[] isaa = new InetSocketAddress[1];
 725 
 726         // acquire the lock, adjusting the timeout for cases where several
 727         // threads are accepting connections and there is a timeout set
 728         ReentrantLock acceptLock = readLock;
 729         int timeout = this.timeout;
 730         long remainingNanos = 0;
 731         if (timeout > 0) {
 732             remainingNanos = tryLock(acceptLock, timeout, MILLISECONDS);
 733             if (remainingNanos <= 0) {
 734                 assert !acceptLock.isHeldByCurrentThread();
 735                 throw new SocketTimeoutException("Accept timed out");
 736             }
 737         } else {
 738             acceptLock.lock();
 739         }
 740 
 741         // accept a connection
 742         try {
 743             int n = 0;
 744             FileDescriptor fd = beginAccept();
 745             try {
 746                 if (remainingNanos > 0) {
 747                     // accept with timeout
 748                     configureNonBlocking(fd);
 749                     n = timedAccept(fd, newfd, isaa, remainingNanos);
 750                 } else {
 751                     // accept, no timeout
 752                     n = Net.accept(fd, newfd, isaa);
 753                     while (IOStatus.okayToRetry(n) && isOpen()) {
 754                         park(fd, Net.POLLIN);
 755                         n = Net.accept(fd, newfd, isaa);
 756                     }
 757                 }
 758             } finally {
 759                 endAccept(n > 0);
 760                 assert IOStatus.check(n);
 761             }
 762         } finally {
 763             acceptLock.unlock();
 764         }
 765 
 766         // get local address and configure accepted socket to blocking mode
 767         InetSocketAddress localAddress;
 768         try {
 769             localAddress = Net.localAddress(newfd);
 770             IOUtil.configureBlocking(newfd, true);
 771         } catch (IOException ioe) {
 772             nd.close(newfd);
 773             throw ioe;
 774         }
 775 
 776         // set the fields
 777         Runnable closer = closerFor(newfd, true);
 778         synchronized (nsi.stateLock) {
 779             nsi.fd = newfd;
 780             nsi.stream = true;
 781             nsi.cleaner = CleanerFactory.cleaner().register(nsi, closer);
 782             nsi.localport = localAddress.getPort();
 783             nsi.address = isaa[0].getAddress();
 784             nsi.port = isaa[0].getPort();
 785             nsi.state = ST_CONNECTED;
 786         }
 787     }
 788 
 789     @Override
 790     protected InputStream getInputStream() {
 791         return new InputStream() {
 792             @Override
 793             public int read() throws IOException {
 794                 byte[] a = new byte[1];
 795                 int n = read(a, 0, 1);
 796                 return (n > 0) ? (a[0] & 0xff) : -1;
 797             }
 798             @Override
 799             public int read(byte[] b, int off, int len) throws IOException {
 800                 return NioSocketImpl.this.read(b, off, len);
 801             }
 802             @Override
 803             public int available() throws IOException {
 804                 return NioSocketImpl.this.available();
 805             }
 806             @Override
 807             public void close() throws IOException {
 808                 NioSocketImpl.this.close();
 809             }
 810         };
 811     }
 812 
 813     @Override
 814     protected OutputStream getOutputStream() {
 815         return new OutputStream() {
 816             @Override
 817             public void write(int b) throws IOException {
 818                 byte[] a = new byte[]{(byte) b};
 819                 write(a, 0, 1);
 820             }
 821             @Override
 822             public void write(byte[] b, int off, int len) throws IOException {
 823                 NioSocketImpl.this.write(b, off, len);
 824             }
 825             @Override
 826             public void close() throws IOException {
 827                 NioSocketImpl.this.close();
 828             }
 829         };
 830     }
 831 
 832     @Override
 833     protected int available() throws IOException {
 834         synchronized (stateLock) {
 835             ensureOpenAndConnected();
 836             if (isInputClosed) {
 837                 return 0;
 838             } else {
 839                 return Net.available(fd);
 840             }
 841         }
 842     }
 843 
 844     /**
 845      * Closes the socket if there are no I/O operations in progress.
 846      */
 847     private boolean tryClose() throws IOException {
 848         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
 849         if (readerThread == 0 && writerThread == 0) {
 850             try {
 851                 cleaner.clean();
 852             } catch (UncheckedIOException ioe) {
 853                 throw ioe.getCause();
 854             } finally {
 855                 state = ST_CLOSED;
 856             }
 857             return true;
 858         } else {
 859             return false;
 860         }
 861     }
 862 
 863     /**
 864      * Invokes tryClose to attempt to close the socket.
 865      *
 866      * This method is used for deferred closing by I/O operations.
 867      */
 868     private void tryFinishClose() {
 869         try {
 870             tryClose();
 871         } catch (IOException ignore) { }
 872     }
 873 
 874     /**
 875      * Closes the socket. If there are I/O operations in progress then the
 876      * socket is pre-closed and the threads are signalled. The socket will be
 877      * closed when the last I/O operation aborts.
 878      */
 879     @Override
 880     protected void close() throws IOException {
 881         synchronized (stateLock) {
 882             int state = this.state;
 883             if (state >= ST_CLOSING)
 884                 return;
 885             if (state == ST_NEW) {
 886                 // stillborn
 887                 this.state = ST_CLOSED;
 888                 return;
 889             }
 890             this.state = ST_CLOSING;
 891 
 892             // shutdown output when linger interval not set to 0
 893             try {
 894                 var SO_LINGER = StandardSocketOptions.SO_LINGER;
 895                 if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
 896                     Net.shutdown(fd, Net.SHUT_WR);
 897                 }
 898             } catch (IOException ignore) { }
 899 
 900             // attempt to close the socket. If there are I/O operations in progress
 901             // then the socket is pre-closed and the thread(s) signalled. The
 902             // last thread will close the file descriptor.
 903             if (!tryClose()) {
 904                 nd.preClose(fd);
 905                 long reader = readerThread;
 906                 if (reader != 0)
 907                     NativeThread.signal(reader);
 908                 long writer = writerThread;
 909                 if (writer != 0)
 910                     NativeThread.signal(writer);
 911             }
 912         }
 913     }
 914 
 915     // the socket options supported by client and server sockets
 916     private static volatile Set<SocketOption<?>> clientSocketOptions;
 917     private static volatile Set<SocketOption<?>> serverSocketOptions;
 918 
 919     @Override
 920     protected Set<SocketOption<?>> supportedOptions() {
 921         Set<SocketOption<?>> options = (server) ? serverSocketOptions : clientSocketOptions;
 922         if (options == null) {
 923             options = new HashSet<>();
 924             options.add(StandardSocketOptions.SO_RCVBUF);
 925             options.add(StandardSocketOptions.SO_REUSEADDR);
 926             if (server) {
 927                 // IP_TOS added for server socket to maintain compatibility
 928                 options.add(StandardSocketOptions.IP_TOS);
 929                 options.addAll(ExtendedSocketOptions.serverSocketOptions());
 930             } else {
 931                 options.add(StandardSocketOptions.IP_TOS);
 932                 options.add(StandardSocketOptions.SO_KEEPALIVE);
 933                 options.add(StandardSocketOptions.SO_SNDBUF);
 934                 options.add(StandardSocketOptions.SO_LINGER);
 935                 options.add(StandardSocketOptions.TCP_NODELAY);
 936                 options.addAll(ExtendedSocketOptions.clientSocketOptions());
 937             }
 938             if (Net.isReusePortAvailable())
 939                 options.add(StandardSocketOptions.SO_REUSEPORT);
 940             options = Collections.unmodifiableSet(options);
 941             if (server) {
 942                 serverSocketOptions = options;
 943             } else {
 944                 clientSocketOptions = options;
 945             }
 946         }
 947         return options;
 948     }
 949 
 950     @Override
 951     protected <T> void setOption(SocketOption<T> opt, T value) throws IOException {
 952         if (!supportedOptions().contains(opt))
 953             throw new UnsupportedOperationException("'" + opt + "' not supported");
 954         if (!opt.type().isInstance(value))
 955             throw new IllegalArgumentException("Invalid value '" + value + "'");
 956         synchronized (stateLock) {
 957             ensureOpen();
 958             if (opt == StandardSocketOptions.IP_TOS) {
 959                 // maps to IP_TOS or IPV6_TCLASS
 960                 Net.setSocketOption(fd, family(), opt, value);
 961             } else if (opt == StandardSocketOptions.SO_REUSEADDR) {
 962                 boolean b = (boolean) value;
 963                 if (Net.useExclusiveBind()) {
 964                     isReuseAddress = b;
 965                 } else {
 966                     Net.setSocketOption(fd, opt, b);
 967                 }
 968             } else {
 969                 // option does not need special handling
 970                 Net.setSocketOption(fd, opt, value);
 971             }
 972         }
 973     }
 974 
 975     @SuppressWarnings("unchecked")
 976     protected <T> T getOption(SocketOption<T> opt) throws IOException {
 977         if (!supportedOptions().contains(opt))
 978             throw new UnsupportedOperationException("'" + opt + "' not supported");
 979         synchronized (stateLock) {
 980             ensureOpen();
 981             if (opt == StandardSocketOptions.IP_TOS) {
 982                 return (T) Net.getSocketOption(fd, family(), opt);
 983             } else if (opt == StandardSocketOptions.SO_REUSEADDR) {
 984                 if (Net.useExclusiveBind()) {
 985                     return (T) Boolean.valueOf(isReuseAddress);
 986                 } else {
 987                     return (T) Net.getSocketOption(fd, opt);
 988                 }
 989             } else {
 990                 // option does not need special handling
 991                 return (T) Net.getSocketOption(fd, opt);
 992             }
 993         }
 994     }
 995 
 996     private boolean booleanValue(Object value, String desc) throws SocketException {
 997         if (!(value instanceof Boolean))
 998             throw new SocketException("Bad value for " + desc);
 999         return (boolean) value;
1000     }
1001 
1002     private int intValue(Object value, String desc) throws SocketException {
1003         if (!(value instanceof Integer))
1004             throw new SocketException("Bad value for " + desc);
1005         return (int) value;
1006     }
1007 
1008     @Override
1009     public void setOption(int opt, Object value) throws SocketException {
1010         synchronized (stateLock) {
1011             ensureOpen();
1012             try {
1013                 switch (opt) {
1014                 case SO_LINGER: {
1015                     // the value is "false" to disable, or linger interval to enable
1016                     int i;
1017                     if (value instanceof Boolean && ((boolean) value) == false) {
1018                         i = -1;
1019                     } else {
1020                         i = intValue(value, "SO_LINGER");
1021                     }
1022                     Net.setSocketOption(fd, StandardSocketOptions.SO_LINGER, i);
1023                     break;
1024                 }
1025                 case SO_TIMEOUT: {
1026                     int i = intValue(value, "SO_TIMEOUT");
1027                     if (i < 0)
1028                         throw new IllegalArgumentException("timeout < 0");
1029                     timeout = i;
1030                     break;
1031                 }
1032                 case IP_TOS: {
1033                     int i = intValue(value, "IP_TOS");
1034                     Net.setSocketOption(fd, family(), StandardSocketOptions.IP_TOS, i);
1035                     break;
1036                 }
1037                 case TCP_NODELAY: {
1038                     boolean b = booleanValue(value, "TCP_NODELAY");
1039                     Net.setSocketOption(fd, StandardSocketOptions.TCP_NODELAY, b);
1040                     break;
1041                 }
1042                 case SO_SNDBUF: {
1043                     int i = intValue(value, "SO_SNDBUF");
1044                     if (i <= 0)
1045                         throw new SocketException("SO_SNDBUF <= 0");
1046                     Net.setSocketOption(fd, StandardSocketOptions.SO_SNDBUF, i);
1047                     break;
1048                 }
1049                 case SO_RCVBUF: {
1050                     int i = intValue(value, "SO_RCVBUF");
1051                     if (i <= 0)
1052                         throw new SocketException("SO_RCVBUF <= 0");
1053                     Net.setSocketOption(fd, StandardSocketOptions.SO_RCVBUF, i);
1054                     break;
1055                 }
1056                 case SO_KEEPALIVE: {
1057                     boolean b = booleanValue(value, "SO_KEEPALIVE");
1058                     Net.setSocketOption(fd, StandardSocketOptions.SO_KEEPALIVE, b);
1059                     break;
1060                 }
1061                 case SO_OOBINLINE: {
1062                     boolean b = booleanValue(value, "SO_OOBINLINE");
1063                     Net.setSocketOption(fd, ExtendedSocketOption.SO_OOBINLINE, b);
1064                     break;
1065                 }
1066                 case SO_REUSEADDR: {
1067                     boolean b = booleanValue(value, "SO_REUSEADDR");
1068                     if (Net.useExclusiveBind()) {
1069                         isReuseAddress = b;
1070                     } else {
1071                         Net.setSocketOption(fd, StandardSocketOptions.SO_REUSEADDR, b);
1072                     }
1073                     break;
1074                 }
1075                 case SO_REUSEPORT: {
1076                     if (!Net.isReusePortAvailable())
1077                         throw new SocketException("SO_REUSEPORT not supported");
1078                     boolean b = booleanValue(value, "SO_REUSEPORT");
1079                     Net.setSocketOption(fd, StandardSocketOptions.SO_REUSEPORT, b);
1080                     break;
1081                 }
1082                 default:
1083                     throw new SocketException("Unknown option " + opt);
1084                 }
1085             } catch (SocketException e) {
1086                 throw e;
1087             } catch (IllegalArgumentException | IOException e) {
1088                 throw new SocketException(e.getMessage());
1089             }
1090         }
1091     }
1092 
1093     @Override
1094     public Object getOption(int opt) throws SocketException {
1095         synchronized (stateLock) {
1096             ensureOpen();
1097             try {
1098                 switch (opt) {
1099                 case SO_TIMEOUT:
1100                     return timeout;
1101                 case TCP_NODELAY:
1102                     return Net.getSocketOption(fd, StandardSocketOptions.TCP_NODELAY);
1103                 case SO_OOBINLINE:
1104                     return Net.getSocketOption(fd, ExtendedSocketOption.SO_OOBINLINE);
1105                 case SO_LINGER: {
1106                     // return "false" when disabled, linger interval when enabled
1107                     int i = (int) Net.getSocketOption(fd, StandardSocketOptions.SO_LINGER);
1108                     if (i == -1) {
1109                         return Boolean.FALSE;
1110                     } else {
1111                         return i;
1112                     }
1113                 }
1114                 case SO_REUSEADDR:
1115                     if (Net.useExclusiveBind()) {
1116                         return isReuseAddress;
1117                     } else {
1118                         return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEADDR);
1119                     }
1120                 case SO_BINDADDR:
1121                     return Net.localAddress(fd).getAddress();
1122                 case SO_SNDBUF:
1123                     return Net.getSocketOption(fd, StandardSocketOptions.SO_SNDBUF);
1124                 case SO_RCVBUF:
1125                     return Net.getSocketOption(fd, StandardSocketOptions.SO_RCVBUF);
1126                 case IP_TOS:
1127                     return Net.getSocketOption(fd, family(), StandardSocketOptions.IP_TOS);
1128                 case SO_KEEPALIVE:
1129                     return Net.getSocketOption(fd, StandardSocketOptions.SO_KEEPALIVE);
1130                 case SO_REUSEPORT:
1131                     if (!Net.isReusePortAvailable())
1132                         throw new SocketException("SO_REUSEPORT not supported");
1133                     return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1134                 default:
1135                     throw new SocketException("Unknown option " + opt);
1136                 }
1137             } catch (SocketException e) {
1138                 throw e;
1139             } catch (IllegalArgumentException | IOException e) {
1140                 throw new SocketException(e.getMessage());
1141             }
1142         }
1143     }
1144 
1145     @Override
1146     protected void shutdownInput() throws IOException {
1147         synchronized (stateLock) {
1148             ensureOpenAndConnected();
1149             if (!isInputClosed) {
1150                 Net.shutdown(fd, Net.SHUT_RD);
1151                 isInputClosed = true;
1152             }
1153         }
1154     }
1155 
1156     @Override
1157     protected void shutdownOutput() throws IOException {
1158         synchronized (stateLock) {
1159             ensureOpenAndConnected();
1160             if (!isOutputClosed) {
1161                 Net.shutdown(fd, Net.SHUT_WR);
1162                 isOutputClosed = true;
1163             }
1164         }
1165     }
1166 
1167     @Override
1168     protected boolean supportsUrgentData() {
1169         return true;
1170     }
1171 
1172     @Override
1173     protected void sendUrgentData(int data) throws IOException {
1174         writeLock.lock();
1175         try {
1176             int n = 0;
1177             FileDescriptor fd = beginWrite();
1178             try {
1179                 do {
1180                     n = Net.sendOOB(fd, (byte) data);
1181                 } while (n == IOStatus.INTERRUPTED && isOpen());
1182                 if (n == IOStatus.UNAVAILABLE) {
1183                     throw new SocketException("No buffer space available");
1184                 }
1185             } finally {
1186                 endWrite(n > 0);
1187             }
1188         } finally {
1189             writeLock.unlock();
1190         }
1191     }
1192 
1193     /**
1194      * Returns an action to close the given file descriptor.
1195      */
1196     private static Runnable closerFor(FileDescriptor fd, boolean stream) {
1197         if (stream) {
1198             return () -> {
1199                 try {
1200                     nd.close(fd);
1201                 } catch (IOException ioe) {
1202                     throw new UncheckedIOException(ioe);
1203                 }
1204             };
1205         } else {
1206             return () -> {
1207                 try {
1208                     nd.close(fd);
1209                 } catch (IOException ioe) {
1210                     throw new UncheckedIOException(ioe);
1211                 } finally {
1212                     // decrement
1213                     ResourceManager.afterUdpClose();
1214                 }
1215             };
1216         }
1217     }
1218 
1219     /**
1220      * Attempts to acquire the given lock within the given waiting time.
1221      * @return the remaining time in nanoseconds when the lock is acquired, zero
1222      *         or less if the lock was not acquired before the timeout expired
1223      */
1224     private static long tryLock(ReentrantLock lock, long timeout, TimeUnit unit) {
1225         assert timeout > 0;
1226         boolean interrupted = false;
1227         long nanos = NANOSECONDS.convert(timeout, unit);
1228         long remainingNanos = nanos;
1229         long startNanos = System.nanoTime();
1230         boolean acquired = false;
1231         while (!acquired && (remainingNanos > 0)) {
1232             try {
1233                 acquired = lock.tryLock(remainingNanos, NANOSECONDS);
1234             } catch (InterruptedException e) {
1235                 interrupted = true;
1236             }
1237             remainingNanos = nanos - (System.nanoTime() - startNanos);
1238         }
1239         if (acquired && remainingNanos <= 0L)
1240             lock.unlock();  // release lock if timeout has expired
1241         if (interrupted)
1242             Thread.currentThread().interrupt();
1243         return remainingNanos;
1244     }
1245 
1246     /**
1247      * Returns the socket protocol family.
1248      */
1249     private static ProtocolFamily family() {
1250         if (Net.isIPv6Available()) {
1251             return StandardProtocolFamily.INET6;
1252         } else {
1253             return StandardProtocolFamily.INET;
1254         }
1255     }
1256 }