--- old/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java 2016-10-20 21:51:13.185728306 -0700 +++ new/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java 2016-10-20 21:51:13.041728308 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, 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 @@ -34,9 +34,13 @@ */ import java.io.*; -import java.net.*; +import java.net.InetSocketAddress; +import java.net.SocketTimeoutException; + import javax.net.ssl.*; import java.security.Security; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class AnonCipherWithWantClientAuth { @@ -62,14 +66,24 @@ static String passwd = "passphrase"; /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* * Is the server ready to serve? */ - volatile static boolean serverReady = false; + private static final CountDownLatch serverCondition = new CountDownLatch(1); /* - * Turn on SSL debugging? + * Is the client ready to handshake? */ - static boolean debug = false; + private static final CountDownLatch clientCondition = new CountDownLatch(1); + + /* + * use any free port by default + */ + private volatile int serverPort = 0; /* * If the client or server is doing some kind of object creation @@ -97,20 +111,44 @@ "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"}; sslServerSocket.setEnabledCipherSuites(ciphers); sslServerSocket.setWantClientAuth(true); - /* - * Signal Client, we're ready for his connect. - */ - serverReady = true; - SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); + // Signal the client, the server is ready to accept connection. + serverCondition.countDown(); - sslIS.read(); - sslOS.write(85); - sslOS.flush(); + // Try to accept a connection in 30 seconds. + SSLSocket sslSocket; + try { + sslServerSocket.setSoTimeout(30000); + sslSocket = (SSLSocket)sslServerSocket.accept(); + } catch (SocketTimeoutException ste) { + sslServerSocket.close(); + + // Ignore the test case if no connection within 30 seconds. + System.out.println( + "No incoming client connection in 30 seconds. " + + "Ignore in server side."); + return; + } - sslSocket.close(); + try { + boolean clientIsReady = clientCondition.await(30L, + TimeUnit.SECONDS); + if (clientIsReady) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + } else { + System.out.println( + "The client is not the expected one or timeout. " + + "Ignore in server side."); + } + } finally { + sslSocket.close(); + sslServerSocket.close(); + } } /* @@ -124,27 +162,49 @@ /* * Wait for server to get started. */ - while (!serverReady) { - Thread.sleep(50); + boolean serverIsReady = + serverCondition.await(90L, TimeUnit.SECONDS); + if (!serverIsReady) { + System.out.println( + "The server is not ready yet in 90 seconds. " + + "Ignore in client side."); + return; } SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault(); - SSLSocket sslSocket = (SSLSocket) - sslsf.createSocket("localhost", serverPort); - String ciphers[] = {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"}; - sslSocket.setEnabledCipherSuites(ciphers); - sslSocket.setUseClientMode(true); - - InputStream sslIS = sslSocket.getInputStream(); - OutputStream sslOS = sslSocket.getOutputStream(); - - sslOS.write(280); - sslOS.flush(); - sslIS.read(); - - sslSocket.close(); + try (SSLSocket sslSocket = (SSLSocket) sslsf.createSocket("localhost", + serverPort)) { + try { + sslSocket.connect( + new InetSocketAddress("localhost", serverPort), 15000); + } catch (IOException ioe) { + // The server side may be impacted by naughty test cases or + // third party routines, and cannot accept connections. + // + // Just ignore the test if the connection cannot be + // established. + System.out.println( + "Cannot make a connection in 15 seconds. " + + "Ignore in client side."); + return; + } + + String ciphers[] = { "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" }; + sslSocket.setEnabledCipherSuites(ciphers); + sslSocket.setUseClientMode(true); + + // Signal the server, the client is ready to communicate. + clientCondition.countDown(); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + } } /* @@ -152,9 +212,6 @@ * The remainder is just support stuff */ - // use any free port by default - volatile int serverPort = 0; - volatile Exception serverException = null; volatile Exception clientException = null; @@ -193,35 +250,77 @@ * * Fork off the other side, then do your work. */ - AnonCipherWithWantClientAuth () throws Exception { - if (separateServerThread) { - startServer(true); - startClient(false); - } else { - startClient(true); - startServer(false); + AnonCipherWithWantClientAuth() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; } /* * Wait for other side to close down. */ if (separateServerThread) { - serverThread.join(); + if (serverThread != null) { + serverThread.join(); + } } else { - clientThread.join(); + if (clientThread != null) { + clientThread.join(); + } } /* * When we get here, the test is pretty much over. - * - * If the main thread excepted, that propagates back - * immediately. If the other thread threw an exception, we - * should report back. + * Which side threw the error? */ - if (serverException != null) - throw serverException; - if (clientException != null) - throw clientException; + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! } void startServer(boolean newThread) throws Exception { @@ -235,14 +334,18 @@ * Our server thread just died. */ System.err.println("Server died..."); - serverReady = true; serverException = e; } } }; serverThread.start(); } else { - doServerSide(); + try { + doServerSide(); + } catch (Exception e) { + System.out.println("Server failed: " + e); + serverException = e; + } } } @@ -263,7 +366,13 @@ }; clientThread.start(); } else { - doClientSide(); + try { + doClientSide(); + } catch (Exception e) { + System.out.println("Client failed: " + e); + clientException = e; + } } } } +