Skip to content

Commit 0073602

Browse files
committed
8297798: Timeout with DTLSOverDatagram test template
Reviewed-by: mbaesken Backport-of: 23457a664ce00de33fdb6846ff31f489e6dd2177
1 parent 979daf5 commit 0073602

File tree

2 files changed

+77
-153
lines changed

2 files changed

+77
-153
lines changed

test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java

Lines changed: 63 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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
@@ -33,6 +33,7 @@
3333
* @run main/othervm DTLSOverDatagram
3434
*/
3535

36+
import java.io.IOException;
3637
import java.nio.*;
3738
import java.net.*;
3839
import java.util.*;
@@ -42,6 +43,7 @@
4243
import jdk.test.lib.security.SSLContextBuilder;
4344

4445
import java.util.concurrent.*;
46+
import java.util.concurrent.atomic.AtomicBoolean;
4547

4648
import jdk.test.lib.hexdump.HexPrinter;
4749

@@ -50,8 +52,6 @@
5052
*/
5153
public 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

test/jdk/javax/net/ssl/DTLS/InvalidRecords.java

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2019, 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
@@ -36,27 +36,32 @@
3636

3737
import java.net.DatagramPacket;
3838
import java.net.SocketAddress;
39+
import java.util.concurrent.atomic.AtomicBoolean;
3940

4041
/**
41-
* Test that if handshake messages are crasged, the handshake would fail
42+
* Test that if handshake messages are changed, the handshake would fail
4243
* because of handshaking hash verification.
4344
*/
4445
public class InvalidRecords extends DTLSOverDatagram {
45-
boolean needInvalidRecords = true;
46+
private static final AtomicBoolean needInvalidRecords = new AtomicBoolean(true);
4647

4748
public static void main(String[] args) throws Exception {
4849
InvalidRecords testCase = new InvalidRecords();
4950
testCase.runTest(testCase);
50-
}
5151

52-
@Override
53-
public boolean isGoodJob() {
54-
return false;
52+
if (needInvalidRecords.get()) {
53+
// if this is true, the createHandshakePacket() method
54+
// was NOT called twice to create ClientHello messages
55+
throw new RuntimeException(
56+
"The invalid handshake packet was not"
57+
+ " rejected as it should have been.");
58+
}
5559
}
5660

61+
5762
@Override
5863
DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) {
59-
if ((ba.length >= 60) &&
64+
if (needInvalidRecords.get() && (ba.length >= 60) &&
6065
(ba[0x00] == (byte)0x16) && (ba[0x0D] == (byte)0x01) &&
6166
(ba[0x3B] == (byte)0x00) && (ba[0x3C] > 0)) {
6267

@@ -65,18 +70,8 @@ DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) {
6570
// ba[0x3B]: length of session ID
6671
// ba[0x3C]: length of cookie
6772

68-
if (!needInvalidRecords) {
69-
// The 2nd ClientHello with cookie. The 1st one should be
70-
// rejected as expected.
71-
//
72-
// This may happen if the last few bytes of the packet are
73-
// for supported_version extension.
74-
throw new RuntimeException(
75-
"the crashed handshake message was rejected as expected");
76-
}
77-
7873
// ClientHello with cookie
79-
needInvalidRecords = false;
74+
needInvalidRecords.set(false);
8075
System.out.println("invalidate ClientHello message");
8176
if (ba[ba.length - 1] == (byte)0xFF) {
8277
ba[ba.length - 1] = (byte)0xFE;

0 commit comments

Comments
 (0)