SSLSocketTemplate.java revision 13924:a025c940d090
1/*
2 * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24// SunJSSE does not support dynamic system properties, no way to re-use
25// system properties in samevm/agentvm mode.
26
27/*
28 * @test
29 * @bug 1234567
30 * @summary Use this template to help speed your client/server tests.
31 * @run main/othervm SSLSocketTemplate
32 * @author Brad Wetmore
33 */
34
35import java.io.*;
36import javax.net.ssl.*;
37
38public class SSLSocketTemplate {
39
40    /*
41     * =============================================================
42     * Set the various variables needed for the tests, then
43     * specify what tests to run on each side.
44     */
45
46    /*
47     * Should we run the client or server in a separate thread?
48     * Both sides can throw exceptions, but do you have a preference
49     * as to which side should be the main thread.
50     */
51    static boolean separateServerThread = false;
52
53    /*
54     * Where do we find the keystores?
55     */
56    static String pathToStores = "../etc";
57    static String keyStoreFile = "keystore";
58    static String trustStoreFile = "truststore";
59    static String passwd = "passphrase";
60
61    /*
62     * Is the server ready to serve?
63     */
64    volatile static boolean serverReady = false;
65
66    /*
67     * Turn on SSL debugging?
68     */
69    static boolean debug = false;
70
71    /*
72     * If the client or server is doing some kind of object creation
73     * that the other side depends on, and that thread prematurely
74     * exits, you may experience a hang.  The test harness will
75     * terminate all hung threads after its timeout has expired,
76     * currently 3 minutes by default, but you might try to be
77     * smart about it....
78     */
79
80    /*
81     * Define the server side of the test.
82     *
83     * If the server prematurely exits, serverReady will be set to true
84     * to avoid infinite hangs.
85     */
86    void doServerSide() throws Exception {
87        SSLServerSocketFactory sslssf =
88            (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
89        try (SSLServerSocket sslServerSocket =
90                (SSLServerSocket)sslssf.createServerSocket(serverPort)) {
91
92            serverPort = sslServerSocket.getLocalPort();
93
94            /*
95             * Signal Client, we're ready for his connect.
96             */
97            serverReady = true;
98
99            try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
100                InputStream sslIS = sslSocket.getInputStream();
101                OutputStream sslOS = sslSocket.getOutputStream();
102
103                sslIS.read();
104                sslOS.write(85);
105                sslOS.flush();
106            }
107        }
108    }
109
110    /*
111     * Define the client side of the test.
112     *
113     * If the server prematurely exits, serverReady will be set to true
114     * to avoid infinite hangs.
115     */
116    void doClientSide() throws Exception {
117
118        /*
119         * Wait for server to get started.
120         */
121        while (!serverReady) {
122            Thread.sleep(50);
123        }
124
125        SSLSocketFactory sslsf =
126            (SSLSocketFactory)SSLSocketFactory.getDefault();
127        try (SSLSocket sslSocket =
128                (SSLSocket)sslsf.createSocket("localhost", serverPort)) {
129
130            InputStream sslIS = sslSocket.getInputStream();
131            OutputStream sslOS = sslSocket.getOutputStream();
132
133            sslOS.write(280);
134            sslOS.flush();
135            sslIS.read();
136        }
137    }
138
139    /*
140     * =============================================================
141     * The remainder is just support stuff
142     */
143
144    // use any free port by default
145    volatile int serverPort = 0;
146
147    volatile Exception serverException = null;
148    volatile Exception clientException = null;
149
150    public static void main(String[] args) throws Exception {
151        String keyFilename =
152            System.getProperty("test.src", ".") + "/" + pathToStores +
153                "/" + keyStoreFile;
154        String trustFilename =
155            System.getProperty("test.src", ".") + "/" + pathToStores +
156                "/" + trustStoreFile;
157
158        System.setProperty("javax.net.ssl.keyStore", keyFilename);
159        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
160        System.setProperty("javax.net.ssl.trustStore", trustFilename);
161        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
162
163        if (debug) {
164            System.setProperty("javax.net.debug", "all");
165        }
166
167        /*
168         * Start the tests.
169         */
170        new SSLSocketTemplate();
171    }
172
173    Thread clientThread = null;
174    Thread serverThread = null;
175
176    /*
177     * Primary constructor, used to drive remainder of the test.
178     *
179     * Fork off the other side, then do your work.
180     */
181    SSLSocketTemplate() throws Exception {
182        Exception startException = null;
183        try {
184            if (separateServerThread) {
185                startServer(true);
186                startClient(false);
187            } else {
188                startClient(true);
189                startServer(false);
190            }
191        } catch (Exception e) {
192            startException = e;
193        }
194
195        /*
196         * Wait for other side to close down.
197         */
198        if (separateServerThread) {
199            if (serverThread != null) {
200                serverThread.join();
201            }
202        } else {
203            if (clientThread != null) {
204                clientThread.join();
205            }
206        }
207
208        /*
209         * When we get here, the test is pretty much over.
210         * Which side threw the error?
211         */
212        Exception local;
213        Exception remote;
214
215        if (separateServerThread) {
216            remote = serverException;
217            local = clientException;
218        } else {
219            remote = clientException;
220            local = serverException;
221        }
222
223        Exception exception = null;
224
225        /*
226         * Check various exception conditions.
227         */
228        if ((local != null) && (remote != null)) {
229            // If both failed, return the curthread's exception.
230            local.initCause(remote);
231            exception = local;
232        } else if (local != null) {
233            exception = local;
234        } else if (remote != null) {
235            exception = remote;
236        } else if (startException != null) {
237            exception = startException;
238        }
239
240        /*
241         * If there was an exception *AND* a startException,
242         * output it.
243         */
244        if (exception != null) {
245            if (exception != startException && startException != null) {
246                exception.addSuppressed(startException);
247            }
248            throw exception;
249        }
250
251        // Fall-through: no exception to throw!
252    }
253
254    void startServer(boolean newThread) throws Exception {
255        if (newThread) {
256            serverThread = new Thread() {
257                @Override
258                public void run() {
259                    try {
260                        doServerSide();
261                    } catch (Exception e) {
262                        /*
263                         * Our server thread just died.
264                         *
265                         * Release the client, if not active already...
266                         */
267                        System.err.println("Server died...");
268                        serverReady = true;
269                        serverException = e;
270                    }
271                }
272            };
273            serverThread.start();
274        } else {
275            try {
276                doServerSide();
277            } catch (Exception e) {
278                serverException = e;
279            } finally {
280                serverReady = true;
281            }
282        }
283    }
284
285    void startClient(boolean newThread) throws Exception {
286        if (newThread) {
287            clientThread = new Thread() {
288                @Override
289                public void run() {
290                    try {
291                        doClientSide();
292                    } catch (Exception e) {
293                        /*
294                         * Our client thread just died.
295                         */
296                        System.err.println("Client died...");
297                        clientException = e;
298                    }
299                }
300            };
301            clientThread.start();
302        } else {
303            try {
304                doClientSide();
305            } catch (Exception e) {
306                clientException = e;
307            }
308        }
309    }
310}
311