src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java
branchniosocketimpl-branch
changeset 57207 30695f27d7ea
parent 57189 c56554b46dec
child 57211 4503441bec2e
--- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java	Thu Feb 21 20:20:11 2019 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java	Fri Feb 22 17:03:09 2019 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -248,6 +248,30 @@
     }
 
     /**
+     * Reads bytes from the socket into the given byte array with a timeout.
+     * @throws SocketTimeoutException if the read timeout elapses
+     */
+    private int timedRead(FileDescriptor fd, byte[] b, int off, int len, int millis)
+        throws IOException
+    {
+        long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
+        long remainingNanos = nanos;
+        long startNanos = System.nanoTime();
+        int n;
+        do {
+            park(fd, Net.POLLIN, remainingNanos);
+            n = tryRead(fd, b, off, len);
+            if (n == IOStatus.UNAVAILABLE) {
+                remainingNanos = nanos - (System.nanoTime() - startNanos);
+                if (remainingNanos <= 0) {
+                    throw new SocketTimeoutException("Read timed out");
+                }
+            }
+        } while (n == IOStatus.UNAVAILABLE && isOpen());
+        return n;
+    }
+
+    /**
      * Reads bytes from the socket into the given byte array.
      * @return the number of bytes read
      * @throws IOException if the socket is closed or an I/O occurs
@@ -256,28 +280,18 @@
     private int read(byte[] b, int off, int len) throws IOException {
         readLock.lock();
         try {
-            int timeout = this.timeout;
             int n = 0;
             FileDescriptor fd = beginRead();
             try {
                 if (isInputClosed)
                     return IOStatus.EOF;
+                int timeout = this.timeout;
                 configureNonBlockingIfNeeded(fd, timeout);
                 n = tryRead(fd, b, off, len);
                 if (IOStatus.okayToRetry(n) && isOpen()) {
                     if (timeout > 0) {
                         // read with timeout
-                        long nanos = NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);
-                        do {
-                            long startTime = System.nanoTime();
-                            park(fd, Net.POLLIN, nanos);
-                            n = tryRead(fd, b, off, len);
-                            if (n == IOStatus.UNAVAILABLE) {
-                                nanos -= System.nanoTime() - startTime;
-                                if (nanos <= 0)
-                                    throw new SocketTimeoutException("Read timed out");
-                            }
-                        } while (n == IOStatus.UNAVAILABLE && isOpen());
+                        n = timedRead(fd, b, off, len, timeout);
                     } else {
                         // read, no timeout
                         do {
@@ -526,6 +540,28 @@
     }
 
     /**
+     * Waits for a connection attempt to finish with a timeout
+     * @throws SocketTimeoutException if the connect timeout elapses
+     */
+    private int timedFinishConnect(FileDescriptor fd, int millis) throws IOException {
+        long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
+        long remainingNanos = nanos;
+        long startNanos = System.nanoTime();
+        int n;
+        do {
+            park(fd, Net.POLLOUT, remainingNanos);
+            n = Net.pollConnectNow(fd);
+            if (n == 0) {
+                remainingNanos = nanos - (System.nanoTime() - startNanos);
+                if (remainingNanos <= 0) {
+                    throw new SocketTimeoutException("Connect timed out");
+                }
+            }
+        } while (n == 0 && isOpen());
+        return n;
+    }
+
+    /**
      * Connect the socket. Closes the socket if connection cannot be established.
      * @throws IllegalArgumentException if the address is not an InetSocketAddress
      * @throws UnknownHostException if the InetSocketAddress is not resolved
@@ -555,21 +591,10 @@
                     int n = Net.connect(fd, address, port);
                     if (IOStatus.okayToRetry(n) && isOpen()) {
                         if (millis > 0) {
-                            // connect with timeout
-                            assert nonBlocking;
-                            long nanos = NANOSECONDS.convert(millis, MILLISECONDS);
-                            do {
-                                long startTime = System.nanoTime();
-                                park(fd, Net.POLLOUT, nanos);
-                                n = Net.pollConnectNow(fd);
-                                if (n == 0) {
-                                    nanos -= System.nanoTime() - startTime;
-                                    if (nanos <= 0)
-                                        throw new SocketTimeoutException("Connect timed out");
-                                }
-                            } while (n == 0 && isOpen());
+                            // finish connect with timeout
+                            n = timedFinishConnect(fd, millis);
                         } else {
-                            // connect, no timeout
+                            // finish connect, no timeout
                             do {
                                 park(fd, Net.POLLOUT);
                                 n = Net.pollConnectNow(fd);
@@ -661,6 +686,33 @@
         }
     }
 
+    /**
+     * Accepts a new connection with a timeout
+     * @throws SocketTimeoutException if the accept timeout elapses
+     */
+    private int timedAccept(FileDescriptor fd,
+                            FileDescriptor newfd,
+                            InetSocketAddress[] isaa,
+                            int millis)
+        throws IOException
+    {
+        long nanos = NANOSECONDS.convert(millis, TimeUnit.MILLISECONDS);
+        long remainingNanos = nanos;
+        long startNanos = System.nanoTime();
+        int n;
+        do {
+            park(fd, Net.POLLIN, remainingNanos);
+            n = ServerSocketChannelImpl.accept0(fd, newfd, isaa);
+            if (n == IOStatus.UNAVAILABLE) {
+                remainingNanos = nanos - (System.nanoTime() - startNanos);
+                if (remainingNanos <= 0) {
+                    throw new SocketTimeoutException("Accept timed out");
+                }
+            }
+        } while (n == IOStatus.UNAVAILABLE && isOpen());
+        return n;
+    }
+
     @Override
     protected void accept(SocketImpl si) throws IOException {
         // accept a connection
@@ -679,18 +731,7 @@
                 if (IOStatus.okayToRetry(n) && isOpen()) {
                     if (timeout > 0) {
                         // accept with timeout
-                        assert nonBlocking;
-                        long nanos = NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS);
-                        do {
-                            long startTime = System.nanoTime();
-                            park(fd, Net.POLLIN, nanos);
-                            n = ServerSocketChannelImpl.accept0(fd, newfd, isaa);
-                            if (n == IOStatus.UNAVAILABLE) {
-                                nanos -= System.nanoTime() - startTime;
-                                if (nanos <= 0)
-                                    throw new SocketTimeoutException("Accept timed out");
-                            }
-                        } while (n == IOStatus.UNAVAILABLE && isOpen());
+                        n = timedAccept(fd, newfd, isaa, timeout);
                     } else {
                         // accept, no timeout
                         do {
@@ -756,6 +797,7 @@
                 if (eof) {
                     return -1;
                 } else if (reset) {
+                    NioSocketImpl.this.ensureOpen();
                     throw new SocketException("Connection reset");
                 } else if (len == 0) {
                     return 0;
@@ -1153,7 +1195,7 @@
                     n = Net.sendOOB(fd, (byte) data);
                 } while (n == IOStatus.INTERRUPTED && isOpen());
                 if (n == IOStatus.UNAVAILABLE) {
-                    throw new RuntimeException("not implemented yet");
+                    throw new SocketException("No buffer space available");
                 }
             } finally {
                 endWrite(n > 0);