--- /dev/null 2019-01-25 09:29:23.983999937 +0100 +++ new/test/jdk/javax/net/ssl/SSLSocket/SSLSocketShutdownInput.java 2019-01-25 14:23:04.153644769 +0100 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 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 + * 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 + * @bug 8215102 + * @summary Test that SSLSocket.shutdownInput() doesn't throw unexpected SSLException + * @library /javax/net/ssl/templates + * + * @run main/othervm -Djavax.net.debug=ssl SSLSocketShutdownInput false + * @run main/othervm -Djavax.net.debug=ssl SSLSocketShutdownInput true + */ + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSocket; + +public class SSLSocketShutdownInput implements SSLContextTemplate { + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + throw new Exception("Usage: " + SSLSocketShutdownInput.class.getName() + " {true|false}"); + } + boolean isInputShutdown = Boolean.parseBoolean(args[0]); + new SSLSocketShutdownInput().test(isInputShutdown); + } + + /** + * - Starts a server listening on a SSLServerSocket + * - Creates a (client) SSLSocket to communicate with that server + * - Client sends data to the server + * - Client then initiates a SSLSocket.shutdownInput() + * (Note: Server just receives data and doesn't write back or respond back + * to the client, so this is essentially a one-way communication) + * + * @throws Exception + */ + private void test(final boolean isInputShutdown) throws Exception { + ExecutorService service = Executors.newSingleThreadExecutor(); + final String data = "hello world"; + final Future serverTaskResult; + final SSLServerSocketFactory serversocketfactory = createServerSSLContext().getServerSocketFactory(); + try (final SSLServerSocket serverSocket = (SSLServerSocket) serversocketfactory.createServerSocket(0)) { + serverSocket.setNeedClientAuth(false); + serverSocket.setUseClientMode(false); + // start a thread which waits for client connection + serverTaskResult = service.submit(new Server(serverSocket)); + // create a client socket and communicate with the server + final String serverHost = InetAddress.getLocalHost().getHostName(); + final int serverPort = serverSocket.getLocalPort(); + SSLSocket clientSocket = (SSLSocket) createClientSSLContext().getSocketFactory().createSocket( + serverHost, serverPort); + // send data to server + final BufferedWriter os = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())); + os.write(data); + os.newLine(); + os.flush(); + if (isInputShutdown) { + // This provokes the Exception + clientSocket.shutdownInput(); + } else { + clientSocket.getInputStream().close(); + } + + // verify that the server did receive the (right) data + final String dataReceivedByServer = serverTaskResult.get(1, TimeUnit.SECONDS); + if (!dataReceivedByServer.equals(data)) { + throw new Exception("Server did not receive the expected data"); + } + serverSocket.close(); + } finally { + service.shutdown(); + } + } + + private static final class Server implements Callable { + private final SSLServerSocket listenSocket; + + private Server(final SSLServerSocket listenSocket) { + this.listenSocket = listenSocket; + } + + @Override + public String call() throws Exception { + // wait for connection + try (final SSLSocket socket = (SSLSocket) listenSocket.accept()) { + // read any data from client + final BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String line = reader.readLine(); + System.out.println("DEBUG: Data is: " + line); + return line; + } + } + + } + +} +