11/*
2- * Copyright (c) 2015, 2021 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2015, 2022 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
3333 * @run main/othervm DTLSOverDatagram
3434 */
3535
36+ import java .io .IOException ;
3637import java .nio .*;
3738import java .net .*;
3839import java .util .*;
4243import jdk .test .lib .security .SSLContextBuilder ;
4344
4445import java .util .concurrent .*;
46+ import java .util .concurrent .atomic .AtomicBoolean ;
4547
4648import jdk .test .lib .hexdump .HexPrinter ;
4749
5052 */
5153public class DTLSOverDatagram {
5254
53- private static final int MAX_HANDSHAKE_LOOPS = 200 ;
54- private static final int MAX_APP_READ_LOOPS = 60 ;
5555 private static final int SOCKET_TIMEOUT = 10 * 1000 ; // in millis
5656 private static final int BUFFER_SIZE = 1024 ;
5757 private static final int MAXIMUM_PACKET_SIZE = 1024 ;
@@ -75,8 +75,9 @@ public class DTLSOverDatagram {
7575 private static final ByteBuffer CLIENT_APP =
7676 ByteBuffer .wrap ("Hi Server, I'm Client" .getBytes ());
7777
78- private static Exception clientException = null ;
79- private static Exception serverException = null ;
78+ private final AtomicBoolean exceptionOccurred = new AtomicBoolean (false );
79+
80+ private final CountDownLatch serverStarted = new CountDownLatch (1 );
8081 /*
8182 * =============================================================
8283 * The test case
@@ -148,18 +149,12 @@ void handshake(SSLEngine engine, DatagramSocket socket,
148149 SocketAddress peerAddr , String side ) throws Exception {
149150
150151 boolean endLoops = false ;
151- int loops = MAX_HANDSHAKE_LOOPS ;
152+ int loops = 0 ;
152153 engine .beginHandshake ();
153- while (!endLoops &&
154- (serverException == null ) && (clientException == null )) {
155-
156- if (--loops < 0 ) {
157- throw new RuntimeException (
158- "Too many loops to produce handshake packets" );
159- }
154+ while (!endLoops && !exceptionOccurred .get ()) {
160155
161156 SSLEngineResult .HandshakeStatus hs = engine .getHandshakeStatus ();
162- log (side , "=======handshake(" + loops + ", " + hs + ")=======" );
157+ log (side , "=======handshake(" + ++ loops + ", " + hs + ")=======" );
163158
164159 switch (hs ) {
165160 case NEED_UNWRAP :
@@ -314,16 +309,10 @@ void deliverAppData(SSLEngine engine, DatagramSocket socket,
314309 void receiveAppData (SSLEngine engine ,
315310 DatagramSocket socket , ByteBuffer expectedApp ) throws Exception {
316311
317- int loops = MAX_APP_READ_LOOPS ;
318- while ((serverException == null ) && (clientException == null )) {
319- if (--loops < 0 ) {
320- throw new RuntimeException (
321- "Too much loops to receive application data" );
322- }
323-
312+ while (!exceptionOccurred .get ()) {
324313 byte [] buf = new byte [BUFFER_SIZE ];
325- DatagramPacket packet = new DatagramPacket ( buf , buf . length );
326- socket . receive ( packet );
314+ DatagramPacket packet = readFromSocket ( socket , buf );
315+
327316 ByteBuffer netBuffer = ByteBuffer .wrap (buf , 0 , packet .getLength ());
328317 ByteBuffer recBuffer = ByteBuffer .allocate (BUFFER_SIZE );
329318 SSLEngineResult rs = engine .unwrap (netBuffer , recBuffer );
@@ -339,19 +328,31 @@ void receiveAppData(SSLEngine engine,
339328 }
340329 }
341330
331+ /*
332+ Some tests failed with receive time-out errors when the client tried to read
333+ from the server. The server thread had exited normally so the read _should_
334+ succeed. So let's try to read a couple of times before giving up.
335+ */
336+ DatagramPacket readFromSocket (DatagramSocket socket , byte [] buffer ) throws IOException {
337+ for (int i = 1 ; i <= 2 ; ++i ) {
338+ try {
339+ DatagramPacket packet = new DatagramPacket (buffer , buffer .length );
340+ socket .receive (packet );
341+ return packet ;
342+ } catch (SocketTimeoutException exc ) {
343+ System .out .println ("Attempt " + i + ": Timeout occurred reading from socket." );
344+ }
345+ }
346+ throw new IOException ("Did not receive data after 2 attempts." );
347+ }
348+
342349 // produce handshake packets
343350 boolean produceHandshakePackets (SSLEngine engine , SocketAddress socketAddr ,
344351 String side , List <DatagramPacket > packets ) throws Exception {
345352
346353 boolean endLoops = false ;
347- int loops = MAX_HANDSHAKE_LOOPS / 2 ;
348- while (!endLoops &&
349- (serverException == null ) && (clientException == null )) {
350-
351- if (--loops < 0 ) {
352- throw new RuntimeException (
353- "Too many loops to produce handshake packets" );
354- }
354+ int loops = 0 ;
355+ while (!endLoops && !exceptionOccurred .get ()) {
355356
356357 ByteBuffer oNet = ByteBuffer .allocate (32768 );
357358 ByteBuffer oApp = ByteBuffer .allocate (0 );
@@ -361,7 +362,7 @@ boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr,
361362 SSLEngineResult .Status rs = r .getStatus ();
362363 SSLEngineResult .HandshakeStatus hs = r .getHandshakeStatus ();
363364 log (side , "----produce handshake packet(" +
364- loops + ", " + rs + ", " + hs + ")----" );
365+ ++ loops + ", " + rs + ", " + hs + ")----" );
365366
366367 verifySSLEngineResultStatus (r , side );
367368
@@ -521,10 +522,6 @@ SSLContext getDTLSContext() throws Exception {
521522 * The remainder is support stuff to kickstart the testing.
522523 */
523524
524- // Will the handshaking and application data exchange succeed?
525- public boolean isGoodJob () {
526- return true ;
527- }
528525
529526 public final void runTest (DTLSOverDatagram testCase ) throws Exception {
530527 InetSocketAddress serverSocketAddress = new InetSocketAddress
@@ -544,119 +541,51 @@ public final void runTest(DTLSOverDatagram testCase) throws Exception {
544541 InetSocketAddress clientSocketAddr = new InetSocketAddress (
545542 InetAddress .getLoopbackAddress (), clientSocket .getLocalPort ());
546543
547- ExecutorService pool = Executors .newFixedThreadPool (2 );
548- Future <String > server , client ;
544+ ExecutorService pool = Executors .newFixedThreadPool (1 );
545+ Future <Void > server ;
549546
550- try {
551- server = pool .submit (new ServerCallable (
547+ server = pool .submit (() -> runServer (
552548 testCase , serverSocket , clientSocketAddr ));
553- client = pool .submit (new ClientCallable (
554- testCase , clientSocket , serverSocketAddr ));
555- } finally {
556- pool .shutdown ();
557- }
558-
559- boolean failed = false ;
560-
561- // wait for client to finish
562- try {
563- System .out .println ("Client finished: " + client .get ());
564- } catch (CancellationException | InterruptedException
565- | ExecutionException e ) {
566- System .out .println ("Exception on client side: " );
567- e .printStackTrace (System .out );
568- failed = true ;
569- }
570-
571- // wait for server to finish
572- try {
573- System .out .println ("Client finished: " + server .get ());
574- } catch (CancellationException | InterruptedException
575- | ExecutionException e ) {
576- System .out .println ("Exception on server side: " );
577- e .printStackTrace (System .out );
578- failed = true ;
579- }
549+ pool .shutdown ();
580550
581- if (failed ) {
582- throw new RuntimeException ("Test failed" );
583- }
551+ runClient (testCase , clientSocket , serverSocketAddr );
552+ server .get ();
584553 }
585554 }
586555
587- final static class ServerCallable implements Callable < String > {
588-
589- private final DTLSOverDatagram testCase ;
590- private final DatagramSocket socket ;
591- private final InetSocketAddress clientSocketAddr ;
556+ Void runServer ( DTLSOverDatagram testCase , DatagramSocket socket ,
557+ InetSocketAddress clientSocketAddr ) throws Exception {
558+ try {
559+ serverStarted . countDown () ;
560+ testCase . doServerSide ( socket , clientSocketAddr ) ;
592561
593- ServerCallable ( DTLSOverDatagram testCase , DatagramSocket socket ,
594- InetSocketAddress clientSocketAddr ) {
562+ } catch ( Exception exc ) {
563+ exceptionOccurred . set ( true );
595564
596- this .testCase = testCase ;
597- this .socket = socket ;
598- this .clientSocketAddr = clientSocketAddr ;
565+ // log for debugging clarity
566+ System .out .println ("Unexpected exception in server" );
567+ exc .printStackTrace (System .err );
568+ throw exc ;
599569 }
600570
601- @ Override
602- public String call () throws Exception {
603- try {
604- testCase .doServerSide (socket , clientSocketAddr );
605- } catch (Exception e ) {
606- System .out .println ("Exception in ServerCallable.call():" );
607- e .printStackTrace (System .out );
608- serverException = e ;
609-
610- if (testCase .isGoodJob ()) {
611- throw e ;
612- } else {
613- return "Well done, server!" ;
614- }
615- }
616-
617- if (testCase .isGoodJob ()) {
618- return "Well done, server!" ;
619- } else {
620- throw new Exception ("No expected exception" );
621- }
622- }
571+ return null ;
623572 }
624573
625- final static class ClientCallable implements Callable <String > {
626-
627- private final DTLSOverDatagram testCase ;
628- private final DatagramSocket socket ;
629- private final InetSocketAddress serverSocketAddr ;
630-
631- ClientCallable (DTLSOverDatagram testCase , DatagramSocket socket ,
632- InetSocketAddress serverSocketAddr ) {
633-
634- this .testCase = testCase ;
635- this .socket = socket ;
636- this .serverSocketAddr = serverSocketAddr ;
574+ private void runClient (DTLSOverDatagram testCase , DatagramSocket socket ,
575+ InetSocketAddress serverSocketAddr ) throws Exception {
576+ if (!serverStarted .await (5 , TimeUnit .SECONDS )) {
577+ throw new Exception ("Server did not start within 5 seconds." );
637578 }
638579
639- @ Override
640- public String call () throws Exception {
641- try {
642- testCase .doClientSide (socket , serverSocketAddr );
643- } catch (Exception e ) {
644- System .out .println ("Exception in ClientCallable.call():" );
645- e .printStackTrace (System .out );
646- clientException = e ;
647-
648- if (testCase .isGoodJob ()) {
649- throw e ;
650- } else {
651- return "Well done, client!" ;
652- }
653- }
580+ try {
581+ testCase .doClientSide (socket , serverSocketAddr );
582+ } catch (Exception exc ) {
583+ exceptionOccurred .set (true );
654584
655- if (testCase .isGoodJob ()) {
656- return "Well done, client!" ;
657- } else {
658- throw new Exception ("No expected exception" );
659- }
585+ // log for debugging clarity
586+ System .out .println ("Unexpected exception in client." );
587+ exc .printStackTrace (System .err );
588+ throw exc ;
660589 }
661590 }
662591
0 commit comments