19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
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 |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 |
23 |
24 // SunJSSE does not support dynamic system properties, no way to re-use |
24 import java.io.FileInputStream; |
25 // system properties in samevm/agentvm mode. |
25 import java.io.IOException; |
|
26 import java.io.InputStream; |
|
27 import java.io.OutputStream; |
|
28 import java.net.InetSocketAddress; |
|
29 import java.net.SocketTimeoutException; |
|
30 import java.security.KeyStore; |
|
31 import java.security.Security; |
|
32 import java.util.concurrent.CountDownLatch; |
|
33 import java.util.concurrent.TimeUnit; |
|
34 import javax.net.ssl.SSLContext; |
|
35 import javax.net.ssl.SSLServerSocket; |
|
36 import javax.net.ssl.SSLServerSocketFactory; |
|
37 import javax.net.ssl.SSLSocket; |
|
38 import javax.net.ssl.SSLSocketFactory; |
|
39 |
|
40 /** |
|
41 * This class defines a framework for JSSE tests. |
|
42 * |
|
43 * Please run in othervm mode. SunJSSE does not support dynamic system |
|
44 * properties, no way to re-use system properties in samevm/agentvm mode. |
|
45 */ |
26 |
46 |
27 /* |
47 /* |
28 * @test |
48 * @test |
29 * @bug 1234567 |
49 * @bug 1234567 |
30 * @summary Use this template to help speed your client/server tests. |
50 * @summary Use this class for JSSE tests |
31 * @run main/othervm SSLSocketTemplate |
51 * @run main/othervm SSLSocketTemplate |
32 * @author Brad Wetmore |
52 * @author Brad Wetmore |
33 */ |
53 */ |
34 |
54 |
35 import java.io.*; |
|
36 import javax.net.ssl.*; |
|
37 |
|
38 public class SSLSocketTemplate { |
55 public class SSLSocketTemplate { |
39 |
56 |
40 /* |
57 public static final String TEST_SRC = System.getProperty("test.src", "."); |
41 * ============================================================= |
58 |
42 * Set the various variables needed for the tests, then |
59 /* |
43 * specify what tests to run on each side. |
60 * Where do we find the keystores? |
44 */ |
61 */ |
|
62 public static final String PATH_TO_STORES = "../etc"; |
|
63 public static final String KEY_STORE_FILE = "keystore"; |
|
64 public static final String TRUST_STORE_FILE = "truststore"; |
|
65 public static final String PASSWORD = "passphrase"; |
|
66 |
|
67 public static final int FREE_PORT = 0; |
|
68 |
|
69 // in seconds |
|
70 public static final long CLIENT_SIGNAL_TIMEOUT = 30L; |
|
71 public static final long SERVER_SIGNAL_TIMEOUT = 90L; |
|
72 |
|
73 // in millis |
|
74 public static final int CLIENT_TIMEOUT = 15000; |
|
75 public static final int SERVER_TIMEOUT = 30000; |
45 |
76 |
46 /* |
77 /* |
47 * Should we run the client or server in a separate thread? |
78 * Should we run the client or server in a separate thread? |
48 * Both sides can throw exceptions, but do you have a preference |
79 * Both sides can throw exceptions, but do you have a preference |
49 * as to which side should be the main thread. |
80 * as to which side should be the main thread. |
50 */ |
81 */ |
51 static boolean separateServerThread = false; |
82 private boolean separateServerThread = false; |
52 |
83 |
53 /* |
84 /* |
54 * Where do we find the keystores? |
85 * What's the server port? Use any free port by default |
55 */ |
86 */ |
56 static String pathToStores = "../etc"; |
87 private volatile int serverPort; |
57 static String keyStoreFile = "keystore"; |
88 |
58 static String trustStoreFile = "truststore"; |
89 private volatile Exception serverException; |
59 static String passwd = "passphrase"; |
90 private volatile Exception clientException; |
|
91 |
|
92 private Thread clientThread; |
|
93 private Thread serverThread; |
|
94 |
|
95 private Peer serverPeer; |
|
96 private Peer clientPeer; |
|
97 |
|
98 private Application serverApplication; |
|
99 private Application clientApplication; |
|
100 |
|
101 private SSLContext context; |
60 |
102 |
61 /* |
103 /* |
62 * Is the server ready to serve? |
104 * Is the server ready to serve? |
63 */ |
105 */ |
64 volatile static boolean serverReady = false; |
106 private final CountDownLatch serverReadyCondition = new CountDownLatch(1); |
65 |
107 |
66 /* |
108 /* |
67 * Turn on SSL debugging? |
109 * Is the client ready to handshake? |
68 */ |
110 */ |
69 static boolean debug = false; |
111 private final CountDownLatch clientReadyCondition = new CountDownLatch(1); |
70 |
112 |
71 /* |
113 /* |
72 * If the client or server is doing some kind of object creation |
114 * Is the server done? |
73 * that the other side depends on, and that thread prematurely |
115 */ |
74 * exits, you may experience a hang. The test harness will |
116 private final CountDownLatch serverDoneCondition = new CountDownLatch(1); |
75 * terminate all hung threads after its timeout has expired, |
117 |
76 * currently 3 minutes by default, but you might try to be |
118 /* |
77 * smart about it.... |
119 * Is the client done? |
|
120 */ |
|
121 private final CountDownLatch clientDoneCondition = new CountDownLatch(1); |
|
122 |
|
123 /* |
|
124 * Public API. |
|
125 */ |
|
126 |
|
127 public static interface Peer { |
|
128 void run(SSLSocketTemplate test) throws Exception; |
|
129 } |
|
130 |
|
131 public static interface Application { |
|
132 void run(SSLSocket socket, SSLSocketTemplate test) throws Exception; |
|
133 } |
|
134 |
|
135 public static void debug() { |
|
136 debug("ssl"); |
|
137 } |
|
138 |
|
139 public static void debug(String mode) { |
|
140 System.setProperty("javax.net.debug", mode); |
|
141 } |
|
142 |
|
143 public static void setup(String keyFilename, String trustFilename, |
|
144 String password) { |
|
145 |
|
146 System.setProperty("javax.net.ssl.keyStore", keyFilename); |
|
147 System.setProperty("javax.net.ssl.keyStorePassword", password); |
|
148 System.setProperty("javax.net.ssl.trustStore", trustFilename); |
|
149 System.setProperty("javax.net.ssl.trustStorePassword", password); |
|
150 } |
|
151 |
|
152 public static void setup() throws Exception { |
|
153 String keyFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" |
|
154 + KEY_STORE_FILE; |
|
155 String trustFilename = TEST_SRC + "/" + PATH_TO_STORES + "/" |
|
156 + TRUST_STORE_FILE; |
|
157 |
|
158 setup(keyFilename, trustFilename, PASSWORD); |
|
159 } |
|
160 |
|
161 public static void print(String message, Throwable... errors) { |
|
162 synchronized (System.out) { |
|
163 System.out.println(message); |
|
164 for (Throwable e : errors) { |
|
165 e.printStackTrace(System.out); |
|
166 } |
|
167 } |
|
168 } |
|
169 |
|
170 public static KeyStore loadJksKeyStore(String filename, String password) |
|
171 throws Exception { |
|
172 |
|
173 return loadKeyStore(filename, password, "JKS"); |
|
174 } |
|
175 |
|
176 public static KeyStore loadKeyStore(String filename, String password, |
|
177 String type) throws Exception { |
|
178 |
|
179 KeyStore keystore = KeyStore.getInstance(type); |
|
180 FileInputStream fis = new FileInputStream(filename); |
|
181 try { |
|
182 keystore.load(fis, password.toCharArray()); |
|
183 } finally { |
|
184 fis.close(); |
|
185 } |
|
186 return keystore; |
|
187 } |
|
188 |
|
189 // Try to accept a connection in 30 seconds. |
|
190 public static SSLSocket accept(SSLServerSocket sslServerSocket) |
|
191 throws IOException { |
|
192 |
|
193 return accept(sslServerSocket, SERVER_TIMEOUT); |
|
194 } |
|
195 |
|
196 public static SSLSocket accept(SSLServerSocket sslServerSocket, int timeout) |
|
197 throws IOException { |
|
198 |
|
199 try { |
|
200 sslServerSocket.setSoTimeout(timeout); |
|
201 return (SSLSocket) sslServerSocket.accept(); |
|
202 } catch (SocketTimeoutException ste) { |
|
203 print("Warning: ", ste); |
|
204 return null; |
|
205 } |
|
206 } |
|
207 |
|
208 public SSLSocketTemplate setSeparateServerThread( |
|
209 boolean separateServerThread) { |
|
210 |
|
211 this.separateServerThread = separateServerThread; |
|
212 return this; |
|
213 } |
|
214 |
|
215 public SSLSocketTemplate setServerPort(int serverPort) { |
|
216 this.serverPort = serverPort; |
|
217 return this; |
|
218 } |
|
219 |
|
220 public int getServerPort() { |
|
221 return serverPort; |
|
222 } |
|
223 |
|
224 public SSLSocketTemplate setSSLContext(SSLContext context) { |
|
225 this.context = context; |
|
226 return this; |
|
227 } |
|
228 |
|
229 public SSLContext getSSLContext() { |
|
230 return context; |
|
231 } |
|
232 |
|
233 public SSLServerSocketFactory getSSLServerSocketFactory() { |
|
234 if (context != null) { |
|
235 return context.getServerSocketFactory(); |
|
236 } |
|
237 |
|
238 return (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); |
|
239 } |
|
240 |
|
241 public SSLSocketFactory getSSLSocketFactory() { |
|
242 if (context != null) { |
|
243 return context.getSocketFactory(); |
|
244 } |
|
245 |
|
246 return (SSLSocketFactory) SSLSocketFactory.getDefault(); |
|
247 } |
|
248 |
|
249 public void signalServerReady() { |
|
250 serverReadyCondition.countDown(); |
|
251 } |
|
252 |
|
253 public void signalServerDone() { |
|
254 serverDoneCondition.countDown(); |
|
255 } |
|
256 |
|
257 public boolean waitForClientSignal(long timeout, TimeUnit unit) |
|
258 throws InterruptedException { |
|
259 |
|
260 return clientReadyCondition.await(timeout, unit); |
|
261 } |
|
262 |
|
263 public boolean waitForClientSignal() throws InterruptedException { |
|
264 return waitForClientSignal(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); |
|
265 } |
|
266 |
|
267 public boolean waitForClientDone(long timeout, TimeUnit unit) |
|
268 throws InterruptedException { |
|
269 |
|
270 return clientDoneCondition.await(timeout, unit); |
|
271 } |
|
272 |
|
273 public boolean waitForClientDone() throws InterruptedException { |
|
274 return waitForClientDone(CLIENT_SIGNAL_TIMEOUT, TimeUnit.SECONDS); |
|
275 } |
|
276 |
|
277 public void signalClientReady() { |
|
278 clientReadyCondition.countDown(); |
|
279 } |
|
280 |
|
281 public void signalClientDone() { |
|
282 clientDoneCondition.countDown(); |
|
283 } |
|
284 |
|
285 public boolean waitForServerSignal(long timeout, TimeUnit unit) |
|
286 throws InterruptedException { |
|
287 |
|
288 return serverReadyCondition.await(timeout, unit); |
|
289 } |
|
290 |
|
291 public boolean waitForServerSignal() throws InterruptedException { |
|
292 return waitForServerSignal(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); |
|
293 } |
|
294 |
|
295 public boolean waitForServerDone(long timeout, TimeUnit unit) |
|
296 throws InterruptedException { |
|
297 |
|
298 return serverDoneCondition.await(timeout, unit); |
|
299 } |
|
300 |
|
301 public boolean waitForServerDone() throws InterruptedException { |
|
302 return waitForServerDone(SERVER_SIGNAL_TIMEOUT, TimeUnit.SECONDS); |
|
303 } |
|
304 |
|
305 public SSLSocketTemplate setServerPeer(Peer serverPeer) { |
|
306 this.serverPeer = serverPeer; |
|
307 return this; |
|
308 } |
|
309 |
|
310 public Peer getServerPeer() { |
|
311 return serverPeer; |
|
312 } |
|
313 |
|
314 public SSLSocketTemplate setServerApplication( |
|
315 Application serverApplication) { |
|
316 |
|
317 this.serverApplication = serverApplication; |
|
318 return this; |
|
319 } |
|
320 |
|
321 public Application getServerApplication() { |
|
322 return serverApplication; |
|
323 } |
|
324 |
|
325 public SSLSocketTemplate setClientPeer(Peer clientPeer) { |
|
326 this.clientPeer = clientPeer; |
|
327 return this; |
|
328 } |
|
329 |
|
330 public Peer getClientPeer() { |
|
331 return clientPeer; |
|
332 } |
|
333 |
|
334 public SSLSocketTemplate setClientApplication( |
|
335 Application clientApplication) { |
|
336 |
|
337 this.clientApplication = clientApplication; |
|
338 return this; |
|
339 } |
|
340 |
|
341 public Application getClientApplication() { |
|
342 return clientApplication; |
|
343 } |
|
344 |
|
345 public void runTest() throws Exception { |
|
346 if (separateServerThread) { |
|
347 startServer(true, this); |
|
348 startClient(false, this); |
|
349 serverThread.join(); |
|
350 } else { |
|
351 startClient(true, this); |
|
352 startServer(false, this); |
|
353 clientThread.join(); |
|
354 } |
|
355 |
|
356 if (clientException != null || serverException != null) { |
|
357 throw new RuntimeException("Test failed"); |
|
358 } |
|
359 } |
|
360 |
|
361 public SSLSocketTemplate() { |
|
362 serverPeer = new Peer() { |
|
363 |
|
364 @Override |
|
365 public void run(SSLSocketTemplate test) throws Exception { |
|
366 doServerSide(test); |
|
367 } |
|
368 }; |
|
369 |
|
370 clientPeer = new Peer() { |
|
371 |
|
372 @Override |
|
373 public void run(SSLSocketTemplate test) throws Exception { |
|
374 doClientSide(test); |
|
375 } |
|
376 }; |
|
377 |
|
378 serverApplication = new Application() { |
|
379 |
|
380 @Override |
|
381 public void run(SSLSocket socket, SSLSocketTemplate test) |
|
382 throws Exception { |
|
383 |
|
384 runServerApplication(socket); |
|
385 } |
|
386 |
|
387 }; |
|
388 |
|
389 clientApplication = new Application() { |
|
390 |
|
391 @Override |
|
392 public void run(SSLSocket socket, SSLSocketTemplate test) |
|
393 throws Exception { |
|
394 |
|
395 runClientApplication(socket); |
|
396 } |
|
397 }; |
|
398 } |
|
399 |
|
400 public static void main(String args[]) throws Exception { |
|
401 // reset the security property to make sure that the algorithms |
|
402 // and keys used in this test are not disabled. |
|
403 Security.setProperty("jdk.tls.disabledAlgorithms", ""); |
|
404 |
|
405 // MD5 is used in this test case, don't disable MD5 algorithm. |
|
406 Security.setProperty( |
|
407 "jdk.certpath.disabledAlgorithms", "MD2, RSA keySize < 1024"); |
|
408 |
|
409 setup(); |
|
410 |
|
411 new SSLSocketTemplate().runTest(); |
|
412 } |
|
413 |
|
414 /* |
|
415 * Private part. |
78 */ |
416 */ |
79 |
417 |
80 /* |
418 /* |
81 * Define the server side of the test. |
419 * Define the server side of the test. |
82 * |
420 */ |
83 * If the server prematurely exits, serverReady will be set to true |
421 private static void doServerSide(SSLSocketTemplate test) throws Exception { |
84 * to avoid infinite hangs. |
422 SSLServerSocket sslServerSocket; |
85 */ |
423 |
86 void doServerSide() throws Exception { |
424 // kick start the server side service |
87 SSLServerSocketFactory sslssf = |
425 SSLServerSocketFactory sslssf = test.getSSLServerSocketFactory(); |
88 (SSLServerSocketFactory)SSLServerSocketFactory.getDefault(); |
426 sslServerSocket = (SSLServerSocket)sslssf.createServerSocket(FREE_PORT); |
89 try (SSLServerSocket sslServerSocket = |
427 |
90 (SSLServerSocket)sslssf.createServerSocket(serverPort)) { |
428 test.setServerPort(sslServerSocket.getLocalPort()); |
91 |
429 print("Server is listening on port " + test.getServerPort()); |
92 serverPort = sslServerSocket.getLocalPort(); |
430 |
93 |
431 // Signal the client, the server is ready to accept connection. |
94 /* |
432 test.signalServerReady(); |
95 * Signal Client, we're ready for his connect. |
433 |
96 */ |
434 // Try to accept a connection in 30 seconds. |
97 serverReady = true; |
435 SSLSocket sslSocket = accept(sslServerSocket); |
98 |
436 if (sslSocket == null) { |
99 try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { |
437 // Ignore the test case if no connection within 30 seconds. |
100 InputStream sslIS = sslSocket.getInputStream(); |
438 print("No incoming client connection in 30 seconds. " |
101 OutputStream sslOS = sslSocket.getOutputStream(); |
439 + "Ignore in server side."); |
102 |
440 return; |
103 sslIS.read(); |
441 } |
104 sslOS.write(85); |
442 print("Server accepted connection"); |
105 sslOS.flush(); |
443 |
106 } |
444 // handle the connection |
107 } |
445 try { |
|
446 // Is it the expected client connection? |
|
447 // |
|
448 // Naughty test cases or third party routines may try to |
|
449 // connection to this server port unintentionally. In |
|
450 // order to mitigate the impact of unexpected client |
|
451 // connections and avoid intermittent failure, it should |
|
452 // be checked that the accepted connection is really linked |
|
453 // to the expected client. |
|
454 boolean clientIsReady = test.waitForClientSignal(); |
|
455 |
|
456 if (clientIsReady) { |
|
457 // Run the application in server side. |
|
458 print("Run server application"); |
|
459 test.getServerApplication().run(sslSocket, test); |
|
460 } else { // Otherwise, ignore |
|
461 // We don't actually care about plain socket connections |
|
462 // for TLS communication testing generally. Just ignore |
|
463 // the test if the accepted connection is not linked to |
|
464 // the expected client or the client connection timeout |
|
465 // in 30 seconds. |
|
466 print("The client is not the expected one or timeout. " |
|
467 + "Ignore in server side."); |
|
468 } |
|
469 } finally { |
|
470 sslSocket.close(); |
|
471 sslServerSocket.close(); |
|
472 } |
|
473 |
|
474 test.signalServerDone(); |
|
475 } |
|
476 |
|
477 /* |
|
478 * Define the server side application of the test for the specified socket. |
|
479 */ |
|
480 private static void runServerApplication(SSLSocket socket) |
|
481 throws Exception { |
|
482 |
|
483 // here comes the test logic |
|
484 InputStream sslIS = socket.getInputStream(); |
|
485 OutputStream sslOS = socket.getOutputStream(); |
|
486 |
|
487 sslIS.read(); |
|
488 sslOS.write(85); |
|
489 sslOS.flush(); |
108 } |
490 } |
109 |
491 |
110 /* |
492 /* |
111 * Define the client side of the test. |
493 * Define the client side of the test. |
112 * |
494 */ |
113 * If the server prematurely exits, serverReady will be set to true |
495 private static void doClientSide(SSLSocketTemplate test) throws Exception { |
114 * to avoid infinite hangs. |
496 |
115 */ |
497 // Wait for server to get started. |
116 void doClientSide() throws Exception { |
498 // |
117 |
499 // The server side takes care of the issue if the server cannot |
118 /* |
500 // get started in 90 seconds. The client side would just ignore |
119 * Wait for server to get started. |
501 // the test case if the serer is not ready. |
120 */ |
502 boolean serverIsReady = test.waitForServerSignal(); |
121 while (!serverReady) { |
503 if (!serverIsReady) { |
122 Thread.sleep(50); |
504 print("The server is not ready yet in 90 seconds. " |
123 } |
505 + "Ignore in client side."); |
124 |
506 return; |
125 SSLSocketFactory sslsf = |
507 } |
126 (SSLSocketFactory)SSLSocketFactory.getDefault(); |
508 |
127 try (SSLSocket sslSocket = |
509 SSLSocketFactory sslsf = test.getSSLSocketFactory(); |
128 (SSLSocket)sslsf.createSocket("localhost", serverPort)) { |
510 SSLSocket sslSocket = (SSLSocket)sslsf.createSocket(); |
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 { |
511 try { |
184 if (separateServerThread) { |
512 try { |
185 startServer(true); |
513 sslSocket.connect( |
186 startClient(false); |
514 new InetSocketAddress("localhost", |
187 } else { |
515 test.getServerPort()), CLIENT_TIMEOUT); |
188 startClient(true); |
516 print("Client connected to server"); |
189 startServer(false); |
517 } catch (IOException ioe) { |
190 } |
518 // The server side may be impacted by naughty test cases or |
191 } catch (Exception e) { |
519 // third party routines, and cannot accept connections. |
192 startException = e; |
520 // |
193 } |
521 // Just ignore the test if the connection cannot be |
194 |
522 // established. |
195 /* |
523 print("Cannot make a connection in 15 seconds. " |
196 * Wait for other side to close down. |
524 + "Ignore in client side.", ioe); |
197 */ |
525 return; |
198 if (separateServerThread) { |
526 } |
199 if (serverThread != null) { |
527 |
200 serverThread.join(); |
528 // OK, here the client and server get connected. |
201 } |
529 |
202 } else { |
530 // Signal the server, the client is ready to communicate. |
203 if (clientThread != null) { |
531 test.signalClientReady(); |
204 clientThread.join(); |
532 |
205 } |
533 // There is still a chance in theory that the server thread may |
206 } |
534 // wait client-ready timeout and then quit. The chance should |
207 |
535 // be really rare so we don't consider it until it becomes a |
208 /* |
536 // real problem. |
209 * When we get here, the test is pretty much over. |
537 |
210 * Which side threw the error? |
538 // Run the application in client side. |
211 */ |
539 print("Run client application"); |
212 Exception local; |
540 test.getClientApplication().run(sslSocket, test); |
213 Exception remote; |
541 } finally { |
214 |
542 sslSocket.close(); |
215 if (separateServerThread) { |
543 } |
216 remote = serverException; |
544 |
217 local = clientException; |
545 test.signalClientDone(); |
218 } else { |
546 } |
219 remote = clientException; |
547 |
220 local = serverException; |
548 /* |
221 } |
549 * Define the client side application of the test for the specified socket. |
222 |
550 */ |
223 Exception exception = null; |
551 private static void runClientApplication(SSLSocket socket) |
224 |
552 throws Exception { |
225 /* |
553 |
226 * Check various exception conditions. |
554 InputStream sslIS = socket.getInputStream(); |
227 */ |
555 OutputStream sslOS = socket.getOutputStream(); |
228 if ((local != null) && (remote != null)) { |
556 |
229 // If both failed, return the curthread's exception. |
557 sslOS.write(280); |
230 local.initCause(remote); |
558 sslOS.flush(); |
231 exception = local; |
559 sslIS.read(); |
232 } else if (local != null) { |
560 } |
233 exception = local; |
561 |
234 } else if (remote != null) { |
562 private void startServer(boolean newThread, SSLSocketTemplate test) |
235 exception = remote; |
563 throws Exception { |
236 } else if (startException != null) { |
564 |
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) { |
565 if (newThread) { |
256 serverThread = new Thread() { |
566 serverThread = new Thread() { |
|
567 |
257 @Override |
568 @Override |
258 public void run() { |
569 public void run() { |
259 try { |
570 try { |
260 doServerSide(); |
571 serverPeer.run(test); |
261 } catch (Exception e) { |
572 } catch (Exception e) { |
262 /* |
573 /* |
263 * Our server thread just died. |
574 * Our server thread just died. |
264 * |
575 * |
265 * Release the client, if not active already... |
576 * Release the client, if not active already... |
266 */ |
577 */ |
267 System.err.println("Server died..."); |
578 print("Server died ...", e); |
268 serverReady = true; |
|
269 serverException = e; |
579 serverException = e; |
270 } |
580 } |
271 } |
581 } |
272 }; |
582 }; |
273 serverThread.start(); |
583 serverThread.start(); |
274 } else { |
584 } else { |
275 try { |
585 try { |
276 doServerSide(); |
586 serverPeer.run(test); |
277 } catch (Exception e) { |
587 } catch (Exception e) { |
|
588 print("Server failed ...", e); |
278 serverException = e; |
589 serverException = e; |
279 } finally { |
590 } |
280 serverReady = true; |
591 } |
281 } |
592 } |
282 } |
593 |
283 } |
594 private void startClient(boolean newThread, SSLSocketTemplate test) |
284 |
595 throws Exception { |
285 void startClient(boolean newThread) throws Exception { |
596 |
286 if (newThread) { |
597 if (newThread) { |
287 clientThread = new Thread() { |
598 clientThread = new Thread() { |
|
599 |
288 @Override |
600 @Override |
289 public void run() { |
601 public void run() { |
290 try { |
602 try { |
291 doClientSide(); |
603 clientPeer.run(test); |
292 } catch (Exception e) { |
604 } catch (Exception e) { |
293 /* |
605 /* |
294 * Our client thread just died. |
606 * Our client thread just died. |
295 */ |
607 */ |
296 System.err.println("Client died..."); |
608 print("Client died ...", e); |
297 clientException = e; |
609 clientException = e; |
298 } |
610 } |
299 } |
611 } |
300 }; |
612 }; |
301 clientThread.start(); |
613 clientThread.start(); |
302 } else { |
614 } else { |
303 try { |
615 try { |
304 doClientSide(); |
616 clientPeer.run(test); |
305 } catch (Exception e) { |
617 } catch (Exception e) { |
|
618 print("Client failed ...", e); |
306 clientException = e; |
619 clientException = e; |
307 } |
620 } |
308 } |
621 } |
309 } |
622 } |
310 } |
623 } |