8297798: Timeout with DTLSOverDatagram test template
Reviewed-by: jnimeh, rhalade
This commit is contained in:
parent
ae8988e834
commit
4b313b51b1
test/jdk
@ -586,8 +586,6 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-
|
||||
|
||||
sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all
|
||||
|
||||
javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64
|
||||
|
||||
sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all
|
||||
|
||||
sun/security/smartcardio/TestChannel.java 8039280 generic-all
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -33,6 +33,7 @@
|
||||
* @run main/othervm DTLSOverDatagram
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
@ -42,6 +43,7 @@ import jdk.test.lib.security.KeyStoreUtils;
|
||||
import jdk.test.lib.security.SSLContextBuilder;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import jdk.test.lib.hexdump.HexPrinter;
|
||||
|
||||
@ -50,8 +52,6 @@ import jdk.test.lib.hexdump.HexPrinter;
|
||||
*/
|
||||
public class DTLSOverDatagram {
|
||||
|
||||
private static final int MAX_HANDSHAKE_LOOPS = 200;
|
||||
private static final int MAX_APP_READ_LOOPS = 60;
|
||||
private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis
|
||||
private static final int BUFFER_SIZE = 1024;
|
||||
private static final int MAXIMUM_PACKET_SIZE = 1024;
|
||||
@ -75,8 +75,9 @@ public class DTLSOverDatagram {
|
||||
private static final ByteBuffer CLIENT_APP =
|
||||
ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
|
||||
|
||||
private static Exception clientException = null;
|
||||
private static Exception serverException = null;
|
||||
private final AtomicBoolean exceptionOccurred = new AtomicBoolean(false);
|
||||
|
||||
private final CountDownLatch serverStarted = new CountDownLatch(1);
|
||||
/*
|
||||
* =============================================================
|
||||
* The test case
|
||||
@ -148,18 +149,12 @@ public class DTLSOverDatagram {
|
||||
SocketAddress peerAddr, String side) throws Exception {
|
||||
|
||||
boolean endLoops = false;
|
||||
int loops = MAX_HANDSHAKE_LOOPS;
|
||||
int loops = 0;
|
||||
engine.beginHandshake();
|
||||
while (!endLoops &&
|
||||
(serverException == null) && (clientException == null)) {
|
||||
|
||||
if (--loops < 0) {
|
||||
throw new RuntimeException(
|
||||
"Too many loops to produce handshake packets");
|
||||
}
|
||||
while (!endLoops && !exceptionOccurred.get()) {
|
||||
|
||||
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
|
||||
log(side, "=======handshake(" + loops + ", " + hs + ")=======");
|
||||
log(side, "=======handshake(" + ++loops + ", " + hs + ")=======");
|
||||
|
||||
switch (hs) {
|
||||
case NEED_UNWRAP, NEED_UNWRAP_AGAIN -> {
|
||||
@ -313,16 +308,10 @@ public class DTLSOverDatagram {
|
||||
void receiveAppData(SSLEngine engine,
|
||||
DatagramSocket socket, ByteBuffer expectedApp) throws Exception {
|
||||
|
||||
int loops = MAX_APP_READ_LOOPS;
|
||||
while ((serverException == null) && (clientException == null)) {
|
||||
if (--loops < 0) {
|
||||
throw new RuntimeException(
|
||||
"Too much loops to receive application data");
|
||||
}
|
||||
|
||||
while (!exceptionOccurred.get()) {
|
||||
byte[] buf = new byte[BUFFER_SIZE];
|
||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||
socket.receive(packet);
|
||||
DatagramPacket packet = readFromSocket(socket, buf);
|
||||
|
||||
ByteBuffer netBuffer = ByteBuffer.wrap(buf, 0, packet.getLength());
|
||||
ByteBuffer recBuffer = ByteBuffer.allocate(BUFFER_SIZE);
|
||||
SSLEngineResult rs = engine.unwrap(netBuffer, recBuffer);
|
||||
@ -338,19 +327,31 @@ public class DTLSOverDatagram {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Some tests failed with receive time-out errors when the client tried to read
|
||||
from the server. The server thread had exited normally so the read _should_
|
||||
succeed. So let's try to read a couple of times before giving up.
|
||||
*/
|
||||
DatagramPacket readFromSocket(DatagramSocket socket, byte[] buffer) throws IOException {
|
||||
for (int i = 1 ; i <= 2 ; ++i) {
|
||||
try {
|
||||
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
|
||||
socket.receive(packet);
|
||||
return packet;
|
||||
} catch (SocketTimeoutException exc) {
|
||||
System.out.println("Attempt " + i + ": Timeout occurred reading from socket.");
|
||||
}
|
||||
}
|
||||
throw new IOException("Did not receive data after 2 attempts.");
|
||||
}
|
||||
|
||||
// produce handshake packets
|
||||
boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr,
|
||||
String side, List<DatagramPacket> packets) throws Exception {
|
||||
|
||||
boolean endLoops = false;
|
||||
int loops = MAX_HANDSHAKE_LOOPS / 2;
|
||||
while (!endLoops &&
|
||||
(serverException == null) && (clientException == null)) {
|
||||
|
||||
if (--loops < 0) {
|
||||
throw new RuntimeException(
|
||||
"Too many loops to produce handshake packets");
|
||||
}
|
||||
int loops = 0;
|
||||
while (!endLoops && !exceptionOccurred.get()) {
|
||||
|
||||
ByteBuffer oNet = ByteBuffer.allocate(32768);
|
||||
ByteBuffer oApp = ByteBuffer.allocate(0);
|
||||
@ -360,7 +361,7 @@ public class DTLSOverDatagram {
|
||||
SSLEngineResult.Status rs = r.getStatus();
|
||||
SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus();
|
||||
log(side, "----produce handshake packet(" +
|
||||
loops + ", " + rs + ", " + hs + ")----");
|
||||
++loops + ", " + rs + ", " + hs + ")----");
|
||||
|
||||
verifySSLEngineResultStatus(r, side);
|
||||
|
||||
@ -518,10 +519,6 @@ public class DTLSOverDatagram {
|
||||
* The remainder is support stuff to kickstart the testing.
|
||||
*/
|
||||
|
||||
// Will the handshaking and application data exchange succeed?
|
||||
public boolean isGoodJob() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public final void runTest(DTLSOverDatagram testCase) throws Exception {
|
||||
InetSocketAddress serverSocketAddress = new InetSocketAddress
|
||||
@ -541,97 +538,51 @@ public class DTLSOverDatagram {
|
||||
InetSocketAddress clientSocketAddr = new InetSocketAddress(
|
||||
InetAddress.getLoopbackAddress(), clientSocket.getLocalPort());
|
||||
|
||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||
Future<String> server, client;
|
||||
ExecutorService pool = Executors.newFixedThreadPool(1);
|
||||
Future<Void> server;
|
||||
|
||||
try {
|
||||
server = pool.submit(new ServerCallable(
|
||||
server = pool.submit(() -> runServer(
|
||||
testCase, serverSocket, clientSocketAddr));
|
||||
client = pool.submit(new ClientCallable(
|
||||
testCase, clientSocket, serverSocketAddr));
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
pool.shutdown();
|
||||
|
||||
boolean failed = false;
|
||||
|
||||
// wait for client to finish
|
||||
try {
|
||||
System.out.println("Client finished: " + client.get());
|
||||
} catch (CancellationException | InterruptedException
|
||||
| ExecutionException e) {
|
||||
System.out.println("Exception on client side: ");
|
||||
e.printStackTrace(System.out);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// wait for server to finish
|
||||
try {
|
||||
System.out.println("Client finished: " + server.get());
|
||||
} catch (CancellationException | InterruptedException
|
||||
| ExecutionException e) {
|
||||
System.out.println("Exception on server side: ");
|
||||
e.printStackTrace(System.out);
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
runClient(testCase, clientSocket, serverSocketAddr);
|
||||
server.get();
|
||||
}
|
||||
}
|
||||
|
||||
record ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||
InetSocketAddress clientSocketAddr) implements Callable<String> {
|
||||
Void runServer(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||
InetSocketAddress clientSocketAddr) throws Exception {
|
||||
try {
|
||||
serverStarted.countDown();
|
||||
testCase.doServerSide(socket, clientSocketAddr);
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
try {
|
||||
testCase.doServerSide(socket, clientSocketAddr);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception in ServerCallable.call():");
|
||||
e.printStackTrace(System.out);
|
||||
serverException = e;
|
||||
} catch (Exception exc) {
|
||||
exceptionOccurred.set(true);
|
||||
|
||||
if (testCase.isGoodJob()) {
|
||||
throw e;
|
||||
} else {
|
||||
return "Well done, server!";
|
||||
}
|
||||
}
|
||||
|
||||
if (testCase.isGoodJob()) {
|
||||
return "Well done, server!";
|
||||
} else {
|
||||
throw new Exception("No expected exception");
|
||||
}
|
||||
// log for debugging clarity
|
||||
System.out.println("Unexpected exception in server");
|
||||
exc.printStackTrace(System.err);
|
||||
throw exc;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
record ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||
InetSocketAddress serverSocketAddr) implements Callable<String> {
|
||||
private void runClient(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||
InetSocketAddress serverSocketAddr) throws Exception {
|
||||
if(!serverStarted.await(5, TimeUnit.SECONDS)) {
|
||||
throw new Exception("Server did not start within 5 seconds.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
try {
|
||||
testCase.doClientSide(socket, serverSocketAddr);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception in ClientCallable.call():");
|
||||
e.printStackTrace(System.out);
|
||||
clientException = e;
|
||||
try {
|
||||
testCase.doClientSide(socket, serverSocketAddr);
|
||||
} catch (Exception exc) {
|
||||
exceptionOccurred.set(true);
|
||||
|
||||
if (testCase.isGoodJob()) {
|
||||
throw e;
|
||||
} else {
|
||||
return "Well done, client!";
|
||||
}
|
||||
}
|
||||
|
||||
if (testCase.isGoodJob()) {
|
||||
return "Well done, client!";
|
||||
} else {
|
||||
throw new Exception("No expected exception");
|
||||
}
|
||||
// log for debugging clarity
|
||||
System.out.println("Unexpected exception in client.");
|
||||
exc.printStackTrace(System.err);
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -36,27 +36,32 @@
|
||||
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Test that if handshake messages are crasged, the handshake would fail
|
||||
* Test that if handshake messages are changed, the handshake would fail
|
||||
* because of handshaking hash verification.
|
||||
*/
|
||||
public class InvalidRecords extends DTLSOverDatagram {
|
||||
boolean needInvalidRecords = true;
|
||||
private static final AtomicBoolean needInvalidRecords = new AtomicBoolean(true);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
InvalidRecords testCase = new InvalidRecords();
|
||||
testCase.runTest(testCase);
|
||||
|
||||
if (needInvalidRecords.get()) {
|
||||
// if this is true, the createHandshakePacket() method
|
||||
// was NOT called twice to create ClientHello messages
|
||||
throw new RuntimeException(
|
||||
"The invalid handshake packet was not"
|
||||
+ " rejected as it should have been.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGoodJob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) {
|
||||
if ((ba.length >= 60) &&
|
||||
if (needInvalidRecords.get() && (ba.length >= 60) &&
|
||||
(ba[0x00] == (byte)0x16) && (ba[0x0D] == (byte)0x01) &&
|
||||
(ba[0x3B] == (byte)0x00) && (ba[0x3C] > 0)) {
|
||||
|
||||
@ -65,18 +70,8 @@ public class InvalidRecords extends DTLSOverDatagram {
|
||||
// ba[0x3B]: length of session ID
|
||||
// ba[0x3C]: length of cookie
|
||||
|
||||
if (!needInvalidRecords) {
|
||||
// The 2nd ClientHello with cookie. The 1st one should be
|
||||
// rejected as expected.
|
||||
//
|
||||
// This may happen if the last few bytes of the packet are
|
||||
// for supported_version extension.
|
||||
throw new RuntimeException(
|
||||
"the crashed handshake message was rejected as expected");
|
||||
}
|
||||
|
||||
// ClientHello with cookie
|
||||
needInvalidRecords = false;
|
||||
needInvalidRecords.set(false);
|
||||
System.out.println("invalidate ClientHello message");
|
||||
if (ba[ba.length - 1] == (byte)0xFF) {
|
||||
ba[ba.length - 1] = (byte)0xFE;
|
||||
|
Loading…
x
Reference in New Issue
Block a user