Path: blob/master/test/jdk/sun/security/ssl/SSLSocketImpl/SSLSocketCloseHang.java
41152 views
/*1* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 8184328 8253368 826092326* @summary JDK8u131-b34-socketRead0 hang at SSL read27* @run main/othervm SSLSocketCloseHang TLSv1.228* @run main/othervm SSLSocketCloseHang TLSv1.2 shutdownInput29* @run main/othervm SSLSocketCloseHang TLSv1.2 shutdownOutput30* @run main/othervm SSLSocketCloseHang TLSv1.331* @run main/othervm SSLSocketCloseHang TLSv1.3 shutdownInput32* @run main/othervm SSLSocketCloseHang TLSv1.3 shutdownOutput33*/343536import java.io.*;37import java.net.*;38import java.util.*;39import java.security.*;40import javax.net.ssl.*;4142public class SSLSocketCloseHang {43/*44* =============================================================45* Set the various variables needed for the tests, then46* specify what tests to run on each side.47*/4849/*50* Should we run the client or server in a separate thread?51* Both sides can throw exceptions, but do you have a preference52* as to which side should be the main thread.53*/54static boolean separateServerThread = true;5556/*57* Where do we find the keystores?58*/59static String pathToStores = "../../../../javax/net/ssl/etc";60static String keyStoreFile = "keystore";61static String trustStoreFile = "truststore";62static String passwd = "passphrase";6364/*65* Is the server ready to serve?66*/67volatile static boolean serverReady = false;6869/*70* Was the client responsible for closing the socket71*/72volatile static boolean clientClosed = false;7374/*75* Turn on SSL debugging?76*/77static boolean debug = false;7879static String socketCloseType;8081/*82* If the client or server is doing some kind of object creation83* that the other side depends on, and that thread prematurely84* exits, you may experience a hang. The test harness will85* terminate all hung threads after its timeout has expired,86* currently 3 minutes by default, but you might try to be87* smart about it....88*/8990/*91* Define the server side of the test.92*93* If the server prematurely exits, serverReady will be set to true94* to avoid infinite hangs.95*/96void doServerSide() throws Exception {97SSLServerSocketFactory sslssf =98(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();99SSLServerSocket sslServerSocket =100(SSLServerSocket) sslssf.createServerSocket(serverPort);101102serverPort = sslServerSocket.getLocalPort();103104/*105* Signal Client, we're ready for his connect.106*/107serverReady = true;108109System.err.println("Server accepting: " + System.nanoTime());110SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();111System.err.println("Server accepted: " + System.nanoTime());112sslSocket.startHandshake();113System.err.println("Server handshake complete: " + System.nanoTime());114while (!clientClosed) {115Thread.sleep(500);116}117}118119/*120* Define the client side of the test.121*122* If the server prematurely exits, serverReady will be set to true123* to avoid infinite hangs.124*/125void doClientSide() throws Exception {126boolean caught = false;127128/*129* Wait for server to get started.130*/131System.out.println("waiting on server");132while (!serverReady) {133Thread.sleep(50);134}135Thread.sleep(500);136System.out.println("server ready");137138Socket baseSocket = new Socket("localhost", serverPort);139baseSocket.setSoTimeout(1000);140141SSLSocketFactory sslsf =142(SSLSocketFactory) SSLSocketFactory.getDefault();143SSLSocket sslSocket = (SSLSocket)144sslsf.createSocket(baseSocket, "localhost", serverPort, false);145146// handshaking147System.err.println("Client starting handshake: " + System.nanoTime());148sslSocket.startHandshake();149System.err.println("Client handshake done: " + System.nanoTime());150151Thread.sleep(500);152System.err.println("Client closing: " + System.nanoTime());153154closeConnection(sslSocket);155156clientClosed = true;157System.err.println("Client closed: " + System.nanoTime());158}159160private void closeConnection(SSLSocket sslSocket) throws IOException {161if ("shutdownInput".equals(socketCloseType)) {162shutdownInput(sslSocket);163// second call to shutdownInput() should just return,164// shouldn't throw any exception165sslSocket.shutdownInput();166// invoking shutdownOutput() just after shutdownInput()167sslSocket.shutdownOutput();168} else if ("shutdownOutput".equals(socketCloseType)) {169sslSocket.shutdownOutput();170// second call to shutdownInput() should just return,171// shouldn't throw any exception172sslSocket.shutdownOutput();173// invoking shutdownInput() just after shutdownOutput()174shutdownInput(sslSocket);175} else {176sslSocket.close();177}178}179180private void shutdownInput(SSLSocket sslSocket) throws IOException {181try {182sslSocket.shutdownInput();183} catch (SSLException e) {184if (!e.getMessage().contains185("closing inbound before receiving peer's close_notify")) {186throw new RuntimeException("expected different exception "187+ "message. " + e.getMessage());188}189}190if (!sslSocket.getSession().isValid()) {191throw new RuntimeException("expected session to remain valid");192}193}194195/*196* =============================================================197* The remainder is just support stuff198*/199200// use any free port by default201volatile int serverPort = 0;202203volatile Exception serverException = null;204volatile Exception clientException = null;205206volatile byte[] serverDigest = null;207208public static void main(String[] args) throws Exception {209String keyFilename =210System.getProperty("test.src", "./") + "/" + pathToStores +211"/" + keyStoreFile;212String trustFilename =213System.getProperty("test.src", "./") + "/" + pathToStores +214"/" + trustStoreFile;215216System.setProperty("javax.net.ssl.keyStore", keyFilename);217System.setProperty("javax.net.ssl.keyStorePassword", passwd);218System.setProperty("javax.net.ssl.trustStore", trustFilename);219System.setProperty("javax.net.ssl.trustStorePassword", passwd);220System.setProperty("jdk.tls.client.protocols", args[0]);221222if (debug)223System.setProperty("javax.net.debug", "all");224225socketCloseType = args.length > 1 ? args[1] : "";226227228/*229* Start the tests.230*/231new SSLSocketCloseHang();232}233234Thread clientThread = null;235Thread serverThread = null;236237/*238* Primary constructor, used to drive remainder of the test.239*240* Fork off the other side, then do your work.241*/242SSLSocketCloseHang() throws Exception {243if (separateServerThread) {244startServer(true);245startClient(false);246} else {247startClient(true);248startServer(false);249}250251/*252* Wait for other side to close down.253*/254if (separateServerThread) {255serverThread.join();256} else {257clientThread.join();258}259260/*261* When we get here, the test is pretty much over.262*263* If the main thread excepted, that propagates back264* immediately. If the other thread threw an exception, we265* should report back.266*/267if (serverException != null) {268System.out.print("Server Exception:");269throw serverException;270}271if (clientException != null) {272System.out.print("Client Exception:");273throw clientException;274}275}276277void startServer(boolean newThread) throws Exception {278if (newThread) {279serverThread = new Thread() {280public void run() {281try {282doServerSide();283} catch (Exception e) {284/*285* Our server thread just died.286*287* Release the client, if not active already...288*/289System.err.println("Server died...");290System.err.println(e);291serverReady = true;292serverException = e;293}294}295};296serverThread.start();297} else {298doServerSide();299}300}301302void startClient(boolean newThread) throws Exception {303if (newThread) {304clientThread = new Thread() {305public void run() {306try {307doClientSide();308} catch (Exception e) {309/*310* Our client thread just died.311*/312System.err.println("Client died...");313clientException = e;314}315}316};317clientThread.start();318} else {319doClientSide();320}321}322}323324325