< prev index next >

src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java

Print this page




  35 import java.net.InetAddress;
  36 import java.net.InetSocketAddress;
  37 import java.net.ProtocolFamily;
  38 import java.net.SocketAddress;
  39 import java.net.SocketException;
  40 import java.net.SocketImpl;
  41 import java.net.SocketOption;
  42 import java.net.SocketTimeoutException;
  43 import java.net.StandardProtocolFamily;
  44 import java.net.StandardSocketOptions;
  45 import java.net.UnknownHostException;
  46 import java.nio.ByteBuffer;
  47 import java.util.Collections;
  48 import java.util.HashSet;
  49 import java.util.Objects;
  50 import java.util.Set;
  51 import java.util.concurrent.TimeUnit;
  52 import java.util.concurrent.locks.ReentrantLock;
  53 
  54 import jdk.internal.ref.CleanerFactory;


  55 import sun.net.ConnectionResetException;
  56 import sun.net.NetHooks;
  57 import sun.net.PlatformSocketImpl;
  58 import sun.net.ResourceManager;
  59 import sun.net.ext.ExtendedSocketOptions;
  60 import sun.net.util.SocketExceptions;
  61 
  62 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  63 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  64 
  65 /**
  66  * NIO based SocketImpl.
  67  *
  68  * This implementation attempts to be compatible with legacy PlainSocketImpl,
  69  * including behavior and exceptions that are not specified by SocketImpl.
  70  *
  71  * The underlying socket used by this SocketImpl is initially configured
  72  * blocking. If the connect method is used to establish a connection with a
  73  * timeout then the socket is configured non-blocking for the connect attempt,
  74  * and then restored to blocking mode when the connection is established.
  75  * If the accept or read methods are used with a timeout then the socket is
  76  * configured non-blocking and is never restored. When in non-blocking mode,
  77  * operations that don't complete immediately will poll the socket and preserve
  78  * the semantics of blocking operations.
  79  */
  80 
  81 public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
  82     private static final NativeDispatcher nd = new SocketDispatcher();
  83 
  84     // The maximum number of bytes to read/write per syscall to avoid needing
  85     // a huge buffer from the temporary buffer cache
  86     private static final int MAX_BUFFER_SIZE = 128 * 1024;
  87 
  88     // true if this is a SocketImpl for a ServerSocket
  89     private final boolean server;
  90 
  91     // Lock held when reading (also used when accepting or connecting)
  92     private final ReentrantLock readLock = new ReentrantLock();
  93 
  94     // Lock held when writing
  95     private final ReentrantLock writeLock = new ReentrantLock();
  96 
  97     // The stateLock for read/changing state
  98     private final Object stateLock = new Object();


 150     private void ensureOpen() throws SocketException {
 151         int state = this.state;
 152         if (state == ST_NEW)
 153             throw new SocketException("Socket not created");
 154         if (state >= ST_CLOSING)
 155             throw new SocketException("Socket closed");
 156     }
 157 
 158     /**
 159      * Throws SocketException if the socket is not open and connected.
 160      */
 161     private void ensureOpenAndConnected() throws SocketException {
 162         int state = this.state;
 163         if (state < ST_CONNECTED)
 164             throw new SocketException("Not connected");
 165         if (state > ST_CONNECTED)
 166             throw new SocketException("Socket closed");
 167     }
 168 
 169     /**
 170      * Disables the current thread for scheduling purposes until the socket is
 171      * ready for I/O, or is asynchronously closed, for up to the specified
 172      * waiting time.
 173      * @throws IOException if an I/O error occurs
 174      */
 175     private void park(FileDescriptor fd, int event, long nanos) throws IOException {
 176         long millis;
 177         if (nanos == 0) {
 178             millis = -1;
















 179         } else {
 180             millis = NANOSECONDS.toMillis(nanos);






 181         }
 182         Net.poll(fd, event, millis);
 183     }
 184 
 185     /**
 186      * Disables the current thread for scheduling purposes until the socket is
 187      * ready for I/O or is asynchronously closed.
 188      * @throws IOException if an I/O error occurs
 189      */
 190     private void park(FileDescriptor fd, int event) throws IOException {
 191         park(fd, event, 0);
 192     }
 193 
 194     /**
 195      * Configures the socket to blocking mode. This method is a no-op if the
 196      * socket is already in blocking mode.
 197      * @throws IOException if closed or there is an I/O error changing the mode
 198      */
 199     private void configureBlocking(FileDescriptor fd) throws IOException {
 200         assert readLock.isHeldByCurrentThread();
 201         if (nonBlocking) {
 202             synchronized (stateLock) {
 203                 ensureOpen();
 204                 IOUtil.configureBlocking(fd, true);
 205                 nonBlocking = false;
 206             }
 207         }
 208     }
 209 
 210     /**
 211      * Configures the socket to non-blocking mode. This method is a no-op if the
 212      * socket is already in non-blocking mode.
 213      * @throws IOException if closed or there is an I/O error changing the mode
 214      */
 215     private void configureNonBlocking(FileDescriptor fd) throws IOException {
 216         assert readLock.isHeldByCurrentThread();
 217         if (!nonBlocking) {
 218             synchronized (stateLock) {
 219                 ensureOpen();
 220                 IOUtil.configureBlocking(fd, false);
 221                 nonBlocking = true;
 222             }
 223         }
 224     }
 225 
 226     /**
 227      * Marks the beginning of a read operation that might block.
 228      * @throws SocketException if the socket is closed or not connected
 229      */
 230     private FileDescriptor beginRead() throws SocketException {
 231         synchronized (stateLock) {
 232             ensureOpenAndConnected();
 233             readerThread = NativeThread.current();
 234             return fd;
 235         }
 236     }
 237 
 238     /**
 239      * Marks the end of a read operation that may have blocked.
 240      * @throws SocketException is the socket is closed
 241      */
 242     private void endRead(boolean completed) throws SocketException {


 287             n = tryRead(fd, b, off, len);
 288         }
 289         return n;
 290     }
 291 
 292     /**
 293      * Reads bytes from the socket into the given byte array.
 294      * @return the number of bytes read or -1 at EOF
 295      * @throws SocketException if the socket is closed or a socket I/O error occurs
 296      * @throws SocketTimeoutException if the read timeout elapses
 297      */
 298     private int implRead(byte[] b, int off, int len) throws IOException {
 299         int n = 0;
 300         FileDescriptor fd = beginRead();
 301         try {
 302             if (connectionReset)
 303                 throw new SocketException("Connection reset");
 304             if (isInputClosed)
 305                 return -1;
 306             int timeout = this.timeout;

 307             if (timeout > 0) {
 308                 // read with timeout
 309                 configureNonBlocking(fd);
 310                 n = timedRead(fd, b, off, len, MILLISECONDS.toNanos(timeout));
 311             } else {
 312                 // read, no timeout
 313                 n = tryRead(fd, b, off, len);
 314                 while (IOStatus.okayToRetry(n) && isOpen()) {
 315                     park(fd, Net.POLLIN);
 316                     n = tryRead(fd, b, off, len);
 317                 }
 318             }
 319             return n;
 320         } catch (SocketTimeoutException e) {
 321             throw e;
 322         } catch (ConnectionResetException e) {
 323             connectionReset = true;
 324             throw new SocketException("Connection reset");
 325         } catch (IOException ioe) {
 326             throw new SocketException(ioe.getMessage());
 327         } finally {
 328             endRead(n > 0);
 329         }


 394     {
 395         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
 396         assert src.position() == 0;
 397         try {
 398             src.put(b, off, len);
 399             return nd.write(fd, ((DirectBuffer)src).address(), len);
 400         } finally {
 401             Util.offerFirstTemporaryDirectBuffer(src);
 402         }
 403     }
 404 
 405     /**
 406      * Writes a sequence of bytes to the socket from the given byte array.
 407      * @return the number of bytes written
 408      * @throws SocketException if the socket is closed or a socket I/O error occurs
 409      */
 410     private int implWrite(byte[] b, int off, int len) throws IOException {
 411         int n = 0;
 412         FileDescriptor fd = beginWrite();
 413         try {

 414             n = tryWrite(fd, b, off, len);
 415             while (IOStatus.okayToRetry(n) && isOpen()) {
 416                 park(fd, Net.POLLOUT);
 417                 n = tryWrite(fd, b, off, len);
 418             }
 419             return n;
 420         } catch (IOException ioe) {
 421             throw new SocketException(ioe.getMessage());
 422         } finally {
 423             endWrite(n > 0);
 424         }
 425     }
 426 
 427     /**
 428      * Writes a sequence of bytes to the socket from the given byte array.
 429      * @throws SocketException if the socket is closed or a socket I/O error occurs
 430      */
 431     private void write(byte[] b, int off, int len) throws IOException {
 432         Objects.checkFromIndexSize(off, len, b.length);
 433         if (len > 0) {


 562         // SocketImpl connect only specifies IOException
 563         if (!(remote instanceof InetSocketAddress))
 564             throw new IOException("Unsupported address type");
 565         InetSocketAddress isa = (InetSocketAddress) remote;
 566         if (isa.isUnresolved()) {
 567             throw new UnknownHostException(isa.getHostName());
 568         }
 569 
 570         InetAddress address = isa.getAddress();
 571         if (address.isAnyLocalAddress())
 572             address = InetAddress.getLocalHost();
 573         int port = isa.getPort();
 574 
 575         ReentrantLock connectLock = readLock;
 576         try {
 577             connectLock.lock();
 578             try {
 579                 boolean connected = false;
 580                 FileDescriptor fd = beginConnect(address, port);
 581                 try {
 582 
 583                     // configure socket to non-blocking mode when there is a timeout
 584                     if (millis > 0) {
 585                         configureNonBlocking(fd);
 586                     }
 587 
 588                     int n = Net.connect(fd, address, port);
 589                     if (n > 0) {
 590                         // connection established
 591                         connected = true;
 592                     } else {
 593                         assert IOStatus.okayToRetry(n);
 594                         if (millis > 0) {
 595                             // finish connect with timeout
 596                             long nanos = MILLISECONDS.toNanos(millis);
 597                             connected = timedFinishConnect(fd, nanos);
 598                         } else {
 599                             // finish connect, no timeout
 600                             boolean polled = false;
 601                             while (!polled && isOpen()) {
 602                                 park(fd, Net.POLLOUT);
 603                                 polled = Net.pollConnectNow(fd);
 604                             }
 605                             connected = polled && isOpen();
 606                         }
 607                     }
 608 
 609                     // restore socket to blocking mode
 610                     if (connected && millis > 0) {
 611                         configureBlocking(fd);
 612                     }
 613 
 614                 } finally {
 615                     endConnect(fd, connected);
 616                 }
 617             } finally {
 618                 connectLock.unlock();
 619             }
 620         } catch (IOException ioe) {
 621             close();
 622             throw SocketExceptions.of(ioe, isa);
 623         }
 624     }
 625 
 626     @Override
 627     protected void connect(String host, int port) throws IOException {
 628         connect(new InetSocketAddress(host, port), 0);
 629     }
 630 
 631     @Override
 632     protected void connect(InetAddress address, int port) throws IOException {
 633         connect(new InetSocketAddress(address, port), 0);


 729         // acquire the lock, adjusting the timeout for cases where several
 730         // threads are accepting connections and there is a timeout set
 731         ReentrantLock acceptLock = readLock;
 732         int timeout = this.timeout;
 733         long remainingNanos = 0;
 734         if (timeout > 0) {
 735             remainingNanos = tryLock(acceptLock, timeout, MILLISECONDS);
 736             if (remainingNanos <= 0) {
 737                 assert !acceptLock.isHeldByCurrentThread();
 738                 throw new SocketTimeoutException("Accept timed out");
 739             }
 740         } else {
 741             acceptLock.lock();
 742         }
 743 
 744         // accept a connection
 745         try {
 746             int n = 0;
 747             FileDescriptor fd = beginAccept();
 748             try {

 749                 if (remainingNanos > 0) {
 750                     // accept with timeout
 751                     configureNonBlocking(fd);
 752                     n = timedAccept(fd, newfd, isaa, remainingNanos);
 753                 } else {
 754                     // accept, no timeout
 755                     n = Net.accept(fd, newfd, isaa);
 756                     while (IOStatus.okayToRetry(n) && isOpen()) {
 757                         park(fd, Net.POLLIN);
 758                         n = Net.accept(fd, newfd, isaa);
 759                     }
 760                 }
 761             } finally {
 762                 endAccept(n > 0);
 763                 assert IOStatus.check(n);
 764             }
 765         } finally {
 766             acceptLock.unlock();
 767         }
 768 
 769         // get local address and configure accepted socket to blocking mode
 770         InetSocketAddress localAddress;
 771         try {


 886                 return;
 887             if (state == ST_NEW) {
 888                 // stillborn
 889                 this.state = ST_CLOSED;
 890                 return;
 891             }
 892             this.state = ST_CLOSING;
 893 
 894             // shutdown output when linger interval not set to 0
 895             try {
 896                 var SO_LINGER = StandardSocketOptions.SO_LINGER;
 897                 if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
 898                     Net.shutdown(fd, Net.SHUT_WR);
 899                 }
 900             } catch (IOException ignore) { }
 901 
 902             // attempt to close the socket. If there are I/O operations in progress
 903             // then the socket is pre-closed and the thread(s) signalled. The
 904             // last thread will close the file descriptor.
 905             if (!tryClose()) {
 906                 nd.preClose(fd);
 907                 long reader = readerThread;
 908                 if (reader != 0)
 909                     NativeThread.signal(reader);
 910                 long writer = writerThread;
 911                 if (writer != 0)





 912                     NativeThread.signal(writer);
 913             }
 914         }
 915     }
 916 
 917     // the socket options supported by client and server sockets
 918     private static volatile Set<SocketOption<?>> clientSocketOptions;
 919     private static volatile Set<SocketOption<?>> serverSocketOptions;
 920 
 921     @Override
 922     protected Set<SocketOption<?>> supportedOptions() {
 923         Set<SocketOption<?>> options = (server) ? serverSocketOptions : clientSocketOptions;
 924         if (options == null) {
 925             options = new HashSet<>();
 926             options.add(StandardSocketOptions.SO_RCVBUF);
 927             options.add(StandardSocketOptions.SO_REUSEADDR);
 928             if (server) {
 929                 // IP_TOS added for server socket to maintain compatibility
 930                 options.add(StandardSocketOptions.IP_TOS);
 931                 options.addAll(ExtendedSocketOptions.serverSocketOptions());


1133                     if (!Net.isReusePortAvailable())
1134                         throw new SocketException("SO_REUSEPORT not supported");
1135                     return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1136                 default:
1137                     throw new SocketException("Unknown option " + opt);
1138                 }
1139             } catch (SocketException e) {
1140                 throw e;
1141             } catch (IllegalArgumentException | IOException e) {
1142                 throw new SocketException(e.getMessage());
1143             }
1144         }
1145     }
1146 
1147     @Override
1148     protected void shutdownInput() throws IOException {
1149         synchronized (stateLock) {
1150             ensureOpenAndConnected();
1151             if (!isInputClosed) {
1152                 Net.shutdown(fd, Net.SHUT_RD);



1153                 isInputClosed = true;
1154             }
1155         }
1156     }
1157 
1158     @Override
1159     protected void shutdownOutput() throws IOException {
1160         synchronized (stateLock) {
1161             ensureOpenAndConnected();
1162             if (!isOutputClosed) {
1163                 Net.shutdown(fd, Net.SHUT_WR);



1164                 isOutputClosed = true;
1165             }
1166         }
1167     }
1168 
1169     @Override
1170     protected boolean supportsUrgentData() {
1171         return true;
1172     }
1173 
1174     @Override
1175     protected void sendUrgentData(int data) throws IOException {
1176         writeLock.lock();
1177         try {
1178             int n = 0;
1179             FileDescriptor fd = beginWrite();
1180             try {

1181                 do {
1182                     n = Net.sendOOB(fd, (byte) data);
1183                 } while (n == IOStatus.INTERRUPTED && isOpen());
1184                 if (n == IOStatus.UNAVAILABLE) {
1185                     throw new SocketException("No buffer space available");
1186                 }
1187             } finally {
1188                 endWrite(n > 0);
1189             }
1190         } finally {
1191             writeLock.unlock();
1192         }
1193     }
1194 
1195     /**
1196      * A task that closes a SocketImpl's file descriptor. The task runs when the
1197      * SocketImpl is explicitly closed and when the SocketImpl becomes phantom
1198      * reachable.
1199      */
1200     private static class FileDescriptorCloser implements Runnable {


1263             }
1264             remainingNanos = nanos - (System.nanoTime() - startNanos);
1265         }
1266         if (acquired && remainingNanos <= 0L)
1267             lock.unlock();  // release lock if timeout has expired
1268         if (interrupted)
1269             Thread.currentThread().interrupt();
1270         return remainingNanos;
1271     }
1272 
1273     /**
1274      * Returns the socket protocol family.
1275      */
1276     private static ProtocolFamily family() {
1277         if (Net.isIPv6Available()) {
1278             return StandardProtocolFamily.INET6;
1279         } else {
1280             return StandardProtocolFamily.INET;
1281         }
1282     }
1283 }











  35 import java.net.InetAddress;
  36 import java.net.InetSocketAddress;
  37 import java.net.ProtocolFamily;
  38 import java.net.SocketAddress;
  39 import java.net.SocketException;
  40 import java.net.SocketImpl;
  41 import java.net.SocketOption;
  42 import java.net.SocketTimeoutException;
  43 import java.net.StandardProtocolFamily;
  44 import java.net.StandardSocketOptions;
  45 import java.net.UnknownHostException;
  46 import java.nio.ByteBuffer;
  47 import java.util.Collections;
  48 import java.util.HashSet;
  49 import java.util.Objects;
  50 import java.util.Set;
  51 import java.util.concurrent.TimeUnit;
  52 import java.util.concurrent.locks.ReentrantLock;
  53 
  54 import jdk.internal.ref.CleanerFactory;
  55 import jdk.internal.access.SharedSecrets;
  56 import jdk.internal.misc.Strands;
  57 import sun.net.ConnectionResetException;
  58 import sun.net.NetHooks;
  59 import sun.net.PlatformSocketImpl;
  60 import sun.net.ResourceManager;
  61 import sun.net.ext.ExtendedSocketOptions;
  62 import sun.net.util.SocketExceptions;
  63 
  64 import static java.util.concurrent.TimeUnit.MILLISECONDS;
  65 import static java.util.concurrent.TimeUnit.NANOSECONDS;
  66 
  67 /**
  68  * NIO based SocketImpl.
  69  *
  70  * This implementation attempts to be compatible with legacy PlainSocketImpl,
  71  * including behavior and exceptions that are not specified by SocketImpl.
  72  *
  73  * The underlying socket used by this SocketImpl is initially configured
  74  * blocking. If a connect, accept or read is attempted with a timeout, or a
  75  * fiber invokes a blocking operation, then the socket is changed to non-blocking
  76  * When in non-blocking mode, operations that don't complete immediately will
  77  * poll the socket (or park the fiber when invoked on a fiber) and preserve the
  78  * semantics of blocking operations.


  79  */
  80 
  81 public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl {
  82     private static final NativeDispatcher nd = new SocketDispatcher();
  83 
  84     // The maximum number of bytes to read/write per syscall to avoid needing
  85     // a huge buffer from the temporary buffer cache
  86     private static final int MAX_BUFFER_SIZE = 128 * 1024;
  87 
  88     // true if this is a SocketImpl for a ServerSocket
  89     private final boolean server;
  90 
  91     // Lock held when reading (also used when accepting or connecting)
  92     private final ReentrantLock readLock = new ReentrantLock();
  93 
  94     // Lock held when writing
  95     private final ReentrantLock writeLock = new ReentrantLock();
  96 
  97     // The stateLock for read/changing state
  98     private final Object stateLock = new Object();


 150     private void ensureOpen() throws SocketException {
 151         int state = this.state;
 152         if (state == ST_NEW)
 153             throw new SocketException("Socket not created");
 154         if (state >= ST_CLOSING)
 155             throw new SocketException("Socket closed");
 156     }
 157 
 158     /**
 159      * Throws SocketException if the socket is not open and connected.
 160      */
 161     private void ensureOpenAndConnected() throws SocketException {
 162         int state = this.state;
 163         if (state < ST_CONNECTED)
 164             throw new SocketException("Not connected");
 165         if (state > ST_CONNECTED)
 166             throw new SocketException("Socket closed");
 167     }
 168 
 169     /**
 170      * Disables the current thread or fiber for scheduling purposes until the
 171      * socket is ready for I/O or is asynchronously closed, for up to the
 172      * specified waiting time.
 173      * @throws IOException if an I/O error occurs or the fiber is interrupted
 174      */
 175     private void park(FileDescriptor fd, int event, long nanos) throws IOException {
 176         Object strand = Strands.currentStrand();
 177         if (PollerProvider.available() && (strand instanceof Fiber)) {
 178             int fdVal = fdVal(fd);
 179             Poller.register(strand, fdVal, event);
 180             if (isOpen()) {
 181                 try {
 182                     if (nanos == 0) {
 183                         Strands.parkFiber();
 184                     } else {
 185                         Strands.parkFiber(nanos);
 186                     }
 187                     // throw SocketException with interrupt status set for now
 188                     if (Strands.isInterrupted()) {
 189                         throw new SocketException("I/O operation interrupted");
 190                     }
 191                 } finally {
 192                     Poller.deregister(strand, fdVal, event);
 193                 }
 194             }
 195         } else {
 196             long millis;
 197             if (nanos == 0) {
 198                 millis = -1;
 199             } else {
 200                 millis = NANOSECONDS.toMillis(nanos);
 201             }
 202             Net.poll(fd, event, millis);
 203         }

 204     }
 205 
 206     /**
 207      * Disables the current thread for scheduling purposes until the socket is
 208      * ready for I/O or is asynchronously closed.
 209      * @throws IOException if an I/O error occurs or the fiber is interrupted
 210      */
 211     private void park(FileDescriptor fd, int event) throws IOException {
 212         park(fd, event, 0);
 213     }
 214 
 215     /**
 216      * Ensures that the socket is configured non-blocking when the current
 217      * strand is a fiber or the operation has a timeout
 218      * @throws IOException if there is an I/O error changing the blocking mode
 219      */
 220     private void configureNonBlockingIfNeeded(FileDescriptor fd, boolean timed)
 221         throws IOException
 222     {
 223         if (!nonBlocking
 224             && (timed || Strands.currentStrand() instanceof Fiber)) {
 225             assert readLock.isHeldByCurrentThread() || writeLock.isHeldByCurrentThread();
 226             IOUtil.configureBlocking(fd, false);
 227             nonBlocking = true;
















 228         }
 229     }
 230 
 231     /**
 232      * Marks the beginning of a read operation that might block.
 233      * @throws SocketException if the socket is closed or not connected
 234      */
 235     private FileDescriptor beginRead() throws SocketException {
 236         synchronized (stateLock) {
 237             ensureOpenAndConnected();
 238             readerThread = NativeThread.current();
 239             return fd;
 240         }
 241     }
 242 
 243     /**
 244      * Marks the end of a read operation that may have blocked.
 245      * @throws SocketException is the socket is closed
 246      */
 247     private void endRead(boolean completed) throws SocketException {


 292             n = tryRead(fd, b, off, len);
 293         }
 294         return n;
 295     }
 296 
 297     /**
 298      * Reads bytes from the socket into the given byte array.
 299      * @return the number of bytes read or -1 at EOF
 300      * @throws SocketException if the socket is closed or a socket I/O error occurs
 301      * @throws SocketTimeoutException if the read timeout elapses
 302      */
 303     private int implRead(byte[] b, int off, int len) throws IOException {
 304         int n = 0;
 305         FileDescriptor fd = beginRead();
 306         try {
 307             if (connectionReset)
 308                 throw new SocketException("Connection reset");
 309             if (isInputClosed)
 310                 return -1;
 311             int timeout = this.timeout;
 312             configureNonBlockingIfNeeded(fd, timeout > 0);
 313             if (timeout > 0) {
 314                 // read with timeout

 315                 n = timedRead(fd, b, off, len, MILLISECONDS.toNanos(timeout));
 316             } else {
 317                 // read, no timeout
 318                 n = tryRead(fd, b, off, len);
 319                 while (IOStatus.okayToRetry(n) && isOpen()) {
 320                     park(fd, Net.POLLIN);
 321                     n = tryRead(fd, b, off, len);
 322                 }
 323             }
 324             return n;
 325         } catch (SocketTimeoutException e) {
 326             throw e;
 327         } catch (ConnectionResetException e) {
 328             connectionReset = true;
 329             throw new SocketException("Connection reset");
 330         } catch (IOException ioe) {
 331             throw new SocketException(ioe.getMessage());
 332         } finally {
 333             endRead(n > 0);
 334         }


 399     {
 400         ByteBuffer src = Util.getTemporaryDirectBuffer(len);
 401         assert src.position() == 0;
 402         try {
 403             src.put(b, off, len);
 404             return nd.write(fd, ((DirectBuffer)src).address(), len);
 405         } finally {
 406             Util.offerFirstTemporaryDirectBuffer(src);
 407         }
 408     }
 409 
 410     /**
 411      * Writes a sequence of bytes to the socket from the given byte array.
 412      * @return the number of bytes written
 413      * @throws SocketException if the socket is closed or a socket I/O error occurs
 414      */
 415     private int implWrite(byte[] b, int off, int len) throws IOException {
 416         int n = 0;
 417         FileDescriptor fd = beginWrite();
 418         try {
 419             configureNonBlockingIfNeeded(fd, false);
 420             n = tryWrite(fd, b, off, len);
 421             while (IOStatus.okayToRetry(n) && isOpen()) {
 422                 park(fd, Net.POLLOUT);
 423                 n = tryWrite(fd, b, off, len);
 424             }
 425             return n;
 426         } catch (IOException ioe) {
 427             throw new SocketException(ioe.getMessage());
 428         } finally {
 429             endWrite(n > 0);
 430         }
 431     }
 432 
 433     /**
 434      * Writes a sequence of bytes to the socket from the given byte array.
 435      * @throws SocketException if the socket is closed or a socket I/O error occurs
 436      */
 437     private void write(byte[] b, int off, int len) throws IOException {
 438         Objects.checkFromIndexSize(off, len, b.length);
 439         if (len > 0) {


 568         // SocketImpl connect only specifies IOException
 569         if (!(remote instanceof InetSocketAddress))
 570             throw new IOException("Unsupported address type");
 571         InetSocketAddress isa = (InetSocketAddress) remote;
 572         if (isa.isUnresolved()) {
 573             throw new UnknownHostException(isa.getHostName());
 574         }
 575 
 576         InetAddress address = isa.getAddress();
 577         if (address.isAnyLocalAddress())
 578             address = InetAddress.getLocalHost();
 579         int port = isa.getPort();
 580 
 581         ReentrantLock connectLock = readLock;
 582         try {
 583             connectLock.lock();
 584             try {
 585                 boolean connected = false;
 586                 FileDescriptor fd = beginConnect(address, port);
 587                 try {
 588                     configureNonBlockingIfNeeded(fd, millis > 0);





 589                     int n = Net.connect(fd, address, port);
 590                     if (n > 0) {
 591                         // connection established
 592                         connected = true;
 593                     } else {
 594                         assert IOStatus.okayToRetry(n);
 595                         if (millis > 0) {
 596                             // finish connect with timeout
 597                             long nanos = MILLISECONDS.toNanos(millis);
 598                             connected = timedFinishConnect(fd, nanos);
 599                         } else {
 600                             // finish connect, no timeout
 601                             boolean polled = false;
 602                             while (!polled && isOpen()) {
 603                                 park(fd, Net.POLLOUT);
 604                                 polled = Net.pollConnectNow(fd);
 605                             }
 606                             connected = polled && isOpen();
 607                         }
 608                     }






 609                 } finally {
 610                     endConnect(fd, connected);
 611                 }
 612             } finally {
 613                 connectLock.unlock();
 614             }
 615         } catch (IOException ioe) {
 616             close();
 617             throw SocketExceptions.of(ioe, isa);
 618         }
 619     }
 620 
 621     @Override
 622     protected void connect(String host, int port) throws IOException {
 623         connect(new InetSocketAddress(host, port), 0);
 624     }
 625 
 626     @Override
 627     protected void connect(InetAddress address, int port) throws IOException {
 628         connect(new InetSocketAddress(address, port), 0);


 724         // acquire the lock, adjusting the timeout for cases where several
 725         // threads are accepting connections and there is a timeout set
 726         ReentrantLock acceptLock = readLock;
 727         int timeout = this.timeout;
 728         long remainingNanos = 0;
 729         if (timeout > 0) {
 730             remainingNanos = tryLock(acceptLock, timeout, MILLISECONDS);
 731             if (remainingNanos <= 0) {
 732                 assert !acceptLock.isHeldByCurrentThread();
 733                 throw new SocketTimeoutException("Accept timed out");
 734             }
 735         } else {
 736             acceptLock.lock();
 737         }
 738 
 739         // accept a connection
 740         try {
 741             int n = 0;
 742             FileDescriptor fd = beginAccept();
 743             try {
 744                 configureNonBlockingIfNeeded(fd, remainingNanos > 0);
 745                 if (remainingNanos > 0) {
 746                     // accept with timeout

 747                     n = timedAccept(fd, newfd, isaa, remainingNanos);
 748                 } else {
 749                     // accept, no timeout
 750                     n = Net.accept(fd, newfd, isaa);
 751                     while (IOStatus.okayToRetry(n) && isOpen()) {
 752                         park(fd, Net.POLLIN);
 753                         n = Net.accept(fd, newfd, isaa);
 754                     }
 755                 }
 756             } finally {
 757                 endAccept(n > 0);
 758                 assert IOStatus.check(n);
 759             }
 760         } finally {
 761             acceptLock.unlock();
 762         }
 763 
 764         // get local address and configure accepted socket to blocking mode
 765         InetSocketAddress localAddress;
 766         try {


 881                 return;
 882             if (state == ST_NEW) {
 883                 // stillborn
 884                 this.state = ST_CLOSED;
 885                 return;
 886             }
 887             this.state = ST_CLOSING;
 888 
 889             // shutdown output when linger interval not set to 0
 890             try {
 891                 var SO_LINGER = StandardSocketOptions.SO_LINGER;
 892                 if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) {
 893                     Net.shutdown(fd, Net.SHUT_WR);
 894                 }
 895             } catch (IOException ignore) { }
 896 
 897             // attempt to close the socket. If there are I/O operations in progress
 898             // then the socket is pre-closed and the thread(s) signalled. The
 899             // last thread will close the file descriptor.
 900             if (!tryClose()) {

 901                 long reader = readerThread;


 902                 long writer = writerThread;
 903                 if (NativeThread.isFiber(reader) || NativeThread.isFiber(writer))
 904                     Poller.stopPoll(fdVal(fd));
 905                 nd.preClose(fd);
 906                 if (NativeThread.isKernelThread(reader))
 907                     NativeThread.signal(reader);
 908                 if (NativeThread.isKernelThread(writer))
 909                     NativeThread.signal(writer);
 910             }
 911         }
 912     }
 913 
 914     // the socket options supported by client and server sockets
 915     private static volatile Set<SocketOption<?>> clientSocketOptions;
 916     private static volatile Set<SocketOption<?>> serverSocketOptions;
 917 
 918     @Override
 919     protected Set<SocketOption<?>> supportedOptions() {
 920         Set<SocketOption<?>> options = (server) ? serverSocketOptions : clientSocketOptions;
 921         if (options == null) {
 922             options = new HashSet<>();
 923             options.add(StandardSocketOptions.SO_RCVBUF);
 924             options.add(StandardSocketOptions.SO_REUSEADDR);
 925             if (server) {
 926                 // IP_TOS added for server socket to maintain compatibility
 927                 options.add(StandardSocketOptions.IP_TOS);
 928                 options.addAll(ExtendedSocketOptions.serverSocketOptions());


1130                     if (!Net.isReusePortAvailable())
1131                         throw new SocketException("SO_REUSEPORT not supported");
1132                     return Net.getSocketOption(fd, StandardSocketOptions.SO_REUSEPORT);
1133                 default:
1134                     throw new SocketException("Unknown option " + opt);
1135                 }
1136             } catch (SocketException e) {
1137                 throw e;
1138             } catch (IllegalArgumentException | IOException e) {
1139                 throw new SocketException(e.getMessage());
1140             }
1141         }
1142     }
1143 
1144     @Override
1145     protected void shutdownInput() throws IOException {
1146         synchronized (stateLock) {
1147             ensureOpenAndConnected();
1148             if (!isInputClosed) {
1149                 Net.shutdown(fd, Net.SHUT_RD);
1150                 if (NativeThread.isFiber(readerThread)) {
1151                     Poller.stopPoll(fdVal(fd), Net.POLLIN);
1152                 }
1153                 isInputClosed = true;
1154             }
1155         }
1156     }
1157 
1158     @Override
1159     protected void shutdownOutput() throws IOException {
1160         synchronized (stateLock) {
1161             ensureOpenAndConnected();
1162             if (!isOutputClosed) {
1163                 Net.shutdown(fd, Net.SHUT_WR);
1164                 if (NativeThread.isFiber(writerThread)) {
1165                     Poller.stopPoll(fdVal(fd), Net.POLLOUT);
1166                 }
1167                 isOutputClosed = true;
1168             }
1169         }
1170     }
1171 
1172     @Override
1173     protected boolean supportsUrgentData() {
1174         return true;
1175     }
1176 
1177     @Override
1178     protected void sendUrgentData(int data) throws IOException {
1179         writeLock.lock();
1180         try {
1181             int n = 0;
1182             FileDescriptor fd = beginWrite();
1183             try {
1184                 configureNonBlockingIfNeeded(fd, false);
1185                 do {
1186                     n = Net.sendOOB(fd, (byte) data);
1187                 } while (n == IOStatus.INTERRUPTED && isOpen());
1188                 if (n == IOStatus.UNAVAILABLE) {
1189                     throw new SocketException("No buffer space available");
1190                 }
1191             } finally {
1192                 endWrite(n > 0);
1193             }
1194         } finally {
1195             writeLock.unlock();
1196         }
1197     }
1198 
1199     /**
1200      * A task that closes a SocketImpl's file descriptor. The task runs when the
1201      * SocketImpl is explicitly closed and when the SocketImpl becomes phantom
1202      * reachable.
1203      */
1204     private static class FileDescriptorCloser implements Runnable {


1267             }
1268             remainingNanos = nanos - (System.nanoTime() - startNanos);
1269         }
1270         if (acquired && remainingNanos <= 0L)
1271             lock.unlock();  // release lock if timeout has expired
1272         if (interrupted)
1273             Thread.currentThread().interrupt();
1274         return remainingNanos;
1275     }
1276 
1277     /**
1278      * Returns the socket protocol family.
1279      */
1280     private static ProtocolFamily family() {
1281         if (Net.isIPv6Available()) {
1282             return StandardProtocolFamily.INET6;
1283         } else {
1284             return StandardProtocolFamily.INET;
1285         }
1286     }
1287 
1288     /**
1289      * Returns the native file descriptor
1290      */
1291     private static int fdVal(FileDescriptor fd) {
1292         int fdVal = SharedSecrets.getJavaIOFileDescriptorAccess().get(fd);
1293         assert fdVal == IOUtil.fdVal(fd);
1294         return fdVal;
1295     }
1296 }
< prev index next >