Path: blob/master/test/jdk/sun/security/ssl/SSLSocketImpl/ClientTimeout.java
41152 views
/*1* Copyright (c) 2005, 2011, 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// SunJSSE does not support dynamic system properties, no way to re-use24// system properties in samevm/agentvm mode.2526/*27* @test28* @bug 4836493 823979829* @summary Socket timeouts for SSLSockets causes data corruption.30* @run main/othervm ClientTimeout31*/3233import java.io.*;34import java.net.*;35import java.util.*;36import java.security.*;37import javax.net.ssl.*;3839public class ClientTimeout {4041/*42* =============================================================43* Set the various variables needed for the tests, then44* specify what tests to run on each side.45*/4647/*48* Should we run the client or server in a separate thread?49* Both sides can throw exceptions, but do you have a preference50* as to which side should be the main thread.51*/52static boolean separateServerThread = true;5354/*55* Where do we find the keystores?56*/57static String pathToStores = "../../../../javax/net/ssl/etc";58static String keyStoreFile = "keystore";59static String trustStoreFile = "truststore";60static String passwd = "passphrase";6162/*63* Is the server ready to serve?64*/65volatile static boolean serverReady = false;6667/*68* Turn on SSL debugging?69*/70static boolean debug = false;717273/*74* define the rhythm of timeout exception75*/76static boolean rhythm = true;7778/*79* If the client or server is doing some kind of object creation80* that the other side depends on, and that thread prematurely81* exits, you may experience a hang. The test harness will82* terminate all hung threads after its timeout has expired,83* currently 3 minutes by default, but you might try to be84* smart about it....85*/8687/*88* Define the server side of the test.89*90* If the server prematurely exits, serverReady will be set to true91* to avoid infinite hangs.92*/93void doServerSide() throws Exception {94SSLServerSocketFactory sslssf =95(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();96SSLServerSocket sslServerSocket =97(SSLServerSocket) sslssf.createServerSocket(serverPort);9899serverPort = sslServerSocket.getLocalPort();100101/*102* Signal Client, we're ready for his connect.103*/104serverReady = true;105106SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();107InputStream sslIS = sslSocket.getInputStream();108OutputStream sslOS = sslSocket.getOutputStream();109sslSocket.startHandshake();110111// transfer a file to client.112String transFilename =113System.getProperty("test.src", "./") + "/" +114this.getClass().getName() + ".java";115MessageDigest md = MessageDigest.getInstance("SHA");116DigestInputStream transIns = new DigestInputStream(117new FileInputStream(transFilename), md);118119byte[] bytes = new byte[2000];120int i = 0;121while (true) {122// reset the cycle123if (i >= bytes.length) {124i = 0;125}126127int length = 0;128if ((length = transIns.read(bytes, 0, i++)) == -1) {129break;130} else {131sslOS.write(bytes, 0, length);132sslOS.flush();133134if (i % 3 == 0) {135Thread.sleep(300); // Stall past the timeout...136}137}138}139serverDigest = md.digest();140transIns.close();141sslSocket.close();142}143144/*145* Define the client side of the test.146*147* If the server prematurely exits, serverReady will be set to true148* to avoid infinite hangs.149*/150void doClientSide() throws Exception {151boolean caught = false;152153/*154* Wait for server to get started.155*/156while (!serverReady) {157Thread.sleep(50);158}159160Socket baseSocket = new Socket("localhost", serverPort) {161MyInputStream ins = null;162163public InputStream getInputStream() throws IOException {164if (ins != null) {165return ins;166} else {167ins = new MyInputStream(super.getInputStream());168return ins;169}170}171};172173SSLSocketFactory sslsf =174(SSLSocketFactory) SSLSocketFactory.getDefault();175SSLSocket sslSocket = (SSLSocket)176sslsf.createSocket(baseSocket, "localhost", serverPort, true);177178InputStream sslIS = sslSocket.getInputStream();179OutputStream sslOS = sslSocket.getOutputStream();180181// handshaking182sslSocket.setSoTimeout(100); // The stall timeout.183while (true) {184try {185rhythm = true;186sslSocket.startHandshake();187break;188} catch (SocketTimeoutException e) {189System.out.println("Handshaker exception: "190+ e.getMessage());191}192}193194// read application data from server195MessageDigest md = MessageDigest.getInstance("SHA");196DigestInputStream transIns = new DigestInputStream(sslIS, md);197byte[] bytes = new byte[2000];198while (true) {199try {200rhythm = true;201202while (transIns.read(bytes, 0, 17) != -1) {203rhythm = true;204}205break;206} catch (SocketTimeoutException e) {207System.out.println("InputStream Exception: "208+ e.getMessage());209}210}211// Wait for server to get ready.212while (serverDigest == null) {213Thread.sleep(20);214}215216byte[] cliDigest = md.digest();217if (!Arrays.equals(cliDigest, serverDigest)) {218throw new Exception("Application data trans error");219}220221transIns.close();222sslSocket.close();223}224225/*226* =============================================================227* The remainder is just support stuff228*/229230static class MyInputStream extends InputStream {231InputStream ins = null;232233public MyInputStream(InputStream ins) {234this.ins = ins;235}236237public int read() throws IOException {238return read(new byte[1], 0, 1);239}240241public int read(byte[] data, int offset, int len) throws IOException {242if (!ClientTimeout.rhythm) {243throw new SocketTimeoutException(244"Throwing a timeout exception");245}246ClientTimeout.rhythm = false;247return ins.read(data, offset, len);248}249}250251// use any free port by default252volatile int serverPort = 0;253254volatile Exception serverException = null;255volatile Exception clientException = null;256257volatile byte[] serverDigest = null;258259public static void main(String[] args) throws Exception {260String keyFilename =261System.getProperty("test.src", "./") + "/" + pathToStores +262"/" + keyStoreFile;263String trustFilename =264System.getProperty("test.src", "./") + "/" + pathToStores +265"/" + trustStoreFile;266267System.setProperty("javax.net.ssl.keyStore", keyFilename);268System.setProperty("javax.net.ssl.keyStorePassword", passwd);269System.setProperty("javax.net.ssl.trustStore", trustFilename);270System.setProperty("javax.net.ssl.trustStorePassword", passwd);271272if (debug)273System.setProperty("javax.net.debug", "all");274275/*276* Start the tests.277*/278new ClientTimeout();279}280281Thread clientThread = null;282Thread serverThread = null;283284/*285* Primary constructor, used to drive remainder of the test.286*287* Fork off the other side, then do your work.288*/289ClientTimeout() throws Exception {290if (separateServerThread) {291startServer(true);292startClient(false);293} else {294startClient(true);295startServer(false);296}297298/*299* Wait for other side to close down.300*/301if (separateServerThread) {302serverThread.join();303} else {304clientThread.join();305}306307/*308* When we get here, the test is pretty much over.309*310* If the main thread excepted, that propagates back311* immediately. If the other thread threw an exception, we312* should report back.313*/314if (serverException != null) {315System.out.print("Server Exception:");316throw serverException;317}318if (clientException != null) {319System.out.print("Client Exception:");320throw clientException;321}322}323324void startServer(boolean newThread) throws Exception {325if (newThread) {326serverThread = new Thread() {327public void run() {328try {329doServerSide();330} catch (Exception e) {331/*332* Our server thread just died.333*334* Release the client, if not active already...335*/336System.err.println("Server died...");337System.err.println(e);338serverReady = true;339serverException = e;340}341}342};343serverThread.start();344} else {345doServerSide();346}347}348349void startClient(boolean newThread) throws Exception {350if (newThread) {351clientThread = new Thread() {352public void run() {353try {354doClientSide();355} catch (Exception e) {356/*357* Our client thread just died.358*/359System.err.println("Client died...");360clientException = e;361}362}363};364clientThread.start();365} else {366doClientSide();367}368}369}370371372