| /* |
| * Copyright (c) 2018, 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 |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* @test |
| * @requires (os.family == "linux" | os.family == "mac") |
| * @bug 8203937 |
| * @summary Test reading bytes from a socket after the connection has been |
| * reset by the peer |
| */ |
| |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.net.InetAddress; |
| import java.net.InetSocketAddress; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| |
| /** |
| * This test exercises platform specific and unspecified behavior. It exists |
| * only to ensure that the behavior doesn't change between JDK releases. |
| */ |
| |
| public class ReadAfterReset { |
| private static final PrintStream out = System.out; |
| |
| // number of bytes to write before the connection reset |
| private static final int NUM_BYTES_TO_WRITE = 1000; |
| |
| public static void main(String[] args) throws IOException { |
| try (ServerSocket ss = new ServerSocket()) { |
| ss.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); |
| |
| /** |
| * Connect to the server which will write some bytes and reset the |
| * connection. The client then attempts to read the bytes sent by |
| * the server before it closed the connection. |
| */ |
| out.println("Test connection ..."); |
| try (Socket s = new Socket()) { |
| s.connect(ss.getLocalSocketAddress()); |
| int nwrote = acceptAndResetConnection(ss); |
| int nread = readUntilIOException(s); |
| if (nread != nwrote) { |
| throw new RuntimeException("Client read " + nread + ", expected " + nwrote); |
| } |
| } |
| |
| /** |
| * Connect to the server which will write some bytes and reset the |
| * connection. The client then writes to its end of the connection, |
| * failing as the connection is reset. It then attempts to read the |
| * bytes sent by the server before it closed the connection. |
| */ |
| out.println(); |
| out.println("Test connection ..."); |
| try (Socket s = new Socket()) { |
| s.connect(ss.getLocalSocketAddress()); |
| int nwrote = acceptAndResetConnection(ss); |
| writeUntilIOException(s); |
| int nread = readUntilIOException(s); |
| if (nread != nwrote) { |
| throw new RuntimeException("Client read " + nread + ", expected " + nwrote); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Accept a connection, write bytes, and then reset the connection |
| */ |
| static int acceptAndResetConnection(ServerSocket ss) throws IOException { |
| int count = NUM_BYTES_TO_WRITE; |
| try (Socket peer = ss.accept()) { |
| peer.getOutputStream().write(new byte[count]); |
| peer.setSoLinger(true, 0); |
| out.format("Server wrote %d bytes and reset connection%n", count); |
| } |
| return count; |
| } |
| |
| /** |
| * Write bytes to a socket until I/O exception is thrown |
| */ |
| static void writeUntilIOException(Socket s) { |
| try { |
| byte[] bytes = new byte[100]; |
| while (true) { |
| s.getOutputStream().write(bytes); |
| out.format("Client wrote %d bytes%n", bytes.length); |
| } |
| } catch (IOException ioe) { |
| out.format("Client write failed: %s (expected)%n", ioe); |
| } |
| } |
| |
| /** |
| * Read bytes from a socket until I/O exception is thrown. |
| * |
| * @return the number of bytes read before the I/O exception was thrown |
| */ |
| static int readUntilIOException(Socket s) { |
| int nread = 0; |
| try { |
| byte[] bytes = new byte[100]; |
| while (true) { |
| int n = s.getInputStream().read(bytes); |
| if (n < 0) { |
| out.println("Client read EOF"); |
| break; |
| } else { |
| out.format("Client read %s bytes%n", n); |
| nread += n; |
| } |
| } |
| } catch (IOException ioe) { |
| out.format("Client read failed: %s (expected)%n", ioe); |
| } |
| return nread; |
| } |
| } |