8264152: javax/net/ssl/DTLS/RespondToRetransmit.java timed out
Reviewed-by: xuelei
This commit is contained in:
parent
1c3fd46d7d
commit
79adc16fd8
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -50,33 +50,33 @@ import jdk.test.lib.hexdump.HexPrinter;
|
|||||||
*/
|
*/
|
||||||
public class DTLSOverDatagram {
|
public class DTLSOverDatagram {
|
||||||
|
|
||||||
private static int MAX_HANDSHAKE_LOOPS = 200;
|
private static final int MAX_HANDSHAKE_LOOPS = 200;
|
||||||
private static int MAX_APP_READ_LOOPS = 60;
|
private static final int MAX_APP_READ_LOOPS = 60;
|
||||||
private static int SOCKET_TIMEOUT = 10 * 1000; // in millis
|
private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis
|
||||||
private static int BUFFER_SIZE = 1024;
|
private static final int BUFFER_SIZE = 1024;
|
||||||
private static int MAXIMUM_PACKET_SIZE = 1024;
|
private static final int MAXIMUM_PACKET_SIZE = 1024;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following is to set up the keystores.
|
* The following is to set up the keystores.
|
||||||
*/
|
*/
|
||||||
private static String pathToStores = "../etc";
|
private static final String PATH_TO_STORES = "../etc";
|
||||||
private static String keyStoreFile = "keystore";
|
private static final String KEY_STORE_FILE = "keystore";
|
||||||
private static String trustStoreFile = "truststore";
|
private static final String TRUST_STORE_FILE = "truststore";
|
||||||
|
|
||||||
private static String keyFilename =
|
private static final String KEY_FILENAME =
|
||||||
System.getProperty("test.src", ".") + "/" + pathToStores +
|
System.getProperty("test.src", ".") + "/" + PATH_TO_STORES +
|
||||||
"/" + keyStoreFile;
|
"/" + KEY_STORE_FILE;
|
||||||
private static String trustFilename =
|
private static final String TRUST_FILENAME =
|
||||||
System.getProperty("test.src", ".") + "/" + pathToStores +
|
System.getProperty("test.src", ".") + "/" + PATH_TO_STORES +
|
||||||
"/" + trustStoreFile;
|
"/" + TRUST_STORE_FILE;
|
||||||
private static Exception clientException = null;
|
|
||||||
private static Exception serverException = null;
|
|
||||||
|
|
||||||
private static ByteBuffer serverApp =
|
private static final ByteBuffer SERVER_APP =
|
||||||
ByteBuffer.wrap("Hi Client, I'm Server".getBytes());
|
ByteBuffer.wrap("Hi Client, I'm Server".getBytes());
|
||||||
private static ByteBuffer clientApp =
|
private static final ByteBuffer CLIENT_APP =
|
||||||
ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
|
ByteBuffer.wrap("Hi Server, I'm Client".getBytes());
|
||||||
|
|
||||||
|
private static Exception clientException = null;
|
||||||
|
private static Exception serverException = null;
|
||||||
/*
|
/*
|
||||||
* =============================================================
|
* =============================================================
|
||||||
* The test case
|
* The test case
|
||||||
@ -91,18 +91,19 @@ public class DTLSOverDatagram {
|
|||||||
*/
|
*/
|
||||||
void doServerSide(DatagramSocket socket, InetSocketAddress clientSocketAddr)
|
void doServerSide(DatagramSocket socket, InetSocketAddress clientSocketAddr)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
String side = "Server";
|
||||||
|
|
||||||
// create SSLEngine
|
// create SSLEngine
|
||||||
SSLEngine engine = createSSLEngine(false);
|
SSLEngine engine = createSSLEngine(false);
|
||||||
|
|
||||||
// handshaking
|
// handshaking
|
||||||
handshake(engine, socket, clientSocketAddr, "Server");
|
handshake(engine, socket, clientSocketAddr, side);
|
||||||
|
|
||||||
// read client application data
|
// read client application data
|
||||||
receiveAppData(engine, socket, clientApp);
|
receiveAppData(engine, socket, CLIENT_APP);
|
||||||
|
|
||||||
// write server application data
|
// write server application data
|
||||||
deliverAppData(engine, socket, serverApp, clientSocketAddr);
|
deliverAppData(engine, socket, SERVER_APP, clientSocketAddr, side);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -110,18 +111,19 @@ public class DTLSOverDatagram {
|
|||||||
*/
|
*/
|
||||||
void doClientSide(DatagramSocket socket, InetSocketAddress serverSocketAddr)
|
void doClientSide(DatagramSocket socket, InetSocketAddress serverSocketAddr)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
String side = "Client";
|
||||||
|
|
||||||
// create SSLEngine
|
// create SSLEngine
|
||||||
SSLEngine engine = createSSLEngine(true);
|
SSLEngine engine = createSSLEngine(true);
|
||||||
|
|
||||||
// handshaking
|
// handshaking
|
||||||
handshake(engine, socket, serverSocketAddr, "Client");
|
handshake(engine, socket, serverSocketAddr, side);
|
||||||
|
|
||||||
// write client application data
|
// write client application data
|
||||||
deliverAppData(engine, socket, clientApp, serverSocketAddr);
|
deliverAppData(engine, socket, CLIENT_APP, serverSocketAddr, side);
|
||||||
|
|
||||||
// read server application data
|
// read server application data
|
||||||
receiveAppData(engine, socket, serverApp);
|
receiveAppData(engine, socket, SERVER_APP);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -153,117 +155,94 @@ public class DTLSOverDatagram {
|
|||||||
|
|
||||||
if (--loops < 0) {
|
if (--loops < 0) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Too much loops to produce handshake packets");
|
"Too many loops to produce handshake packets");
|
||||||
}
|
}
|
||||||
|
|
||||||
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
|
SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
|
||||||
log(side, "=======handshake(" + loops + ", " + hs + ")=======");
|
log(side, "=======handshake(" + loops + ", " + hs + ")=======");
|
||||||
if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ||
|
|
||||||
hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
|
|
||||||
|
|
||||||
log(side, "Receive DTLS records, handshake status is " + hs);
|
switch (hs) {
|
||||||
|
case NEED_UNWRAP, NEED_UNWRAP_AGAIN -> {
|
||||||
|
log(side, "Receive DTLS records, handshake status is " + hs);
|
||||||
|
|
||||||
ByteBuffer iNet;
|
ByteBuffer iNet;
|
||||||
ByteBuffer iApp;
|
ByteBuffer iApp;
|
||||||
if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
|
|
||||||
byte[] buf = new byte[BUFFER_SIZE];
|
|
||||||
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
|
||||||
try {
|
|
||||||
socket.receive(packet);
|
|
||||||
} catch (SocketTimeoutException ste) {
|
|
||||||
log(side, "Warning: " + ste);
|
|
||||||
|
|
||||||
List<DatagramPacket> packets = new ArrayList<>();
|
if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) {
|
||||||
boolean finished = onReceiveTimeout(
|
byte[] buf = new byte[BUFFER_SIZE];
|
||||||
engine, peerAddr, side, packets);
|
DatagramPacket packet = new DatagramPacket(buf, buf.length);
|
||||||
|
try {
|
||||||
|
socket.receive(packet);
|
||||||
|
} catch (SocketTimeoutException ste) {
|
||||||
|
log(side, "Warning: " + ste);
|
||||||
|
|
||||||
log(side, "Reproduced " + packets.size() + " packets");
|
List<DatagramPacket> packets = new ArrayList<>();
|
||||||
for (DatagramPacket p : packets) {
|
boolean finished = onReceiveTimeout(
|
||||||
printHex("Reproduced packet",
|
engine, peerAddr, side, packets);
|
||||||
p.getData(), p.getOffset(), p.getLength());
|
|
||||||
socket.send(p);
|
log(side, "Reproduced " + packets.size() + " packets");
|
||||||
|
for (DatagramPacket p : packets) {
|
||||||
|
printHex("Reproduced packet",
|
||||||
|
p.getData(), p.getOffset(), p.getLength());
|
||||||
|
socket.send(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finished) {
|
||||||
|
log(side, "Handshake status is FINISHED "
|
||||||
|
+ "after calling onReceiveTimeout(), "
|
||||||
|
+ "finish the loop");
|
||||||
|
endLoops = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
log(side, "New handshake status is "
|
||||||
|
+ engine.getHandshakeStatus());
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (finished) {
|
iNet = ByteBuffer.wrap(buf, 0, packet.getLength());
|
||||||
log(side, "Handshake status is FINISHED "
|
} else {
|
||||||
+ "after calling onReceiveTimeout(), "
|
iNet = ByteBuffer.allocate(0);
|
||||||
+ "finish the loop");
|
|
||||||
endLoops = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
log(side, "New handshake status is "
|
|
||||||
+ engine.getHandshakeStatus());
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iNet = ByteBuffer.wrap(buf, 0, packet.getLength());
|
|
||||||
iApp = ByteBuffer.allocate(BUFFER_SIZE);
|
|
||||||
} else {
|
|
||||||
iNet = ByteBuffer.allocate(0);
|
|
||||||
iApp = ByteBuffer.allocate(BUFFER_SIZE);
|
iApp = ByteBuffer.allocate(BUFFER_SIZE);
|
||||||
|
|
||||||
|
SSLEngineResult r = engine.unwrap(iNet, iApp);
|
||||||
|
hs = r.getHandshakeStatus();
|
||||||
|
|
||||||
|
verifySSLEngineResultStatus(r, side);
|
||||||
|
if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {
|
||||||
|
log(side, "Handshake status is FINISHED, finish the loop");
|
||||||
|
endLoops = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
case NEED_WRAP -> {
|
||||||
|
List<DatagramPacket> packets = new ArrayList<>();
|
||||||
|
boolean finished = produceHandshakePackets(
|
||||||
|
engine, peerAddr, side, packets);
|
||||||
|
|
||||||
SSLEngineResult r = engine.unwrap(iNet, iApp);
|
log(side, "Produced " + packets.size() + " packets");
|
||||||
SSLEngineResult.Status rs = r.getStatus();
|
for (DatagramPacket p : packets) {
|
||||||
hs = r.getHandshakeStatus();
|
socket.send(p);
|
||||||
if (rs == SSLEngineResult.Status.OK) {
|
}
|
||||||
// OK
|
|
||||||
} else if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {
|
|
||||||
log(side, "BUFFER_OVERFLOW, handshake status is " + hs);
|
|
||||||
|
|
||||||
// the client maximum fragment size config does not work?
|
if (finished) {
|
||||||
throw new Exception("Buffer overflow: " +
|
log(side, "Handshake status is FINISHED "
|
||||||
"incorrect client maximum fragment size");
|
+ "after producing handshake packets, "
|
||||||
} else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
|
+ "finish the loop");
|
||||||
log(side, "BUFFER_UNDERFLOW, handshake status is " + hs);
|
endLoops = true;
|
||||||
|
}
|
||||||
// bad packet, or the client maximum fragment size
|
|
||||||
// config does not work?
|
|
||||||
if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
|
|
||||||
throw new Exception("Buffer underflow: " +
|
|
||||||
"incorrect client maximum fragment size");
|
|
||||||
} // otherwise, ignore this packet
|
|
||||||
} else if (rs == SSLEngineResult.Status.CLOSED) {
|
|
||||||
throw new Exception(
|
|
||||||
"SSL engine closed, handshake status is " + hs);
|
|
||||||
} else {
|
|
||||||
throw new Exception("Can't reach here, result is " + rs);
|
|
||||||
}
|
}
|
||||||
|
case NEED_TASK -> runDelegatedTasks(engine);
|
||||||
if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {
|
case NOT_HANDSHAKING -> {
|
||||||
log(side, "Handshake status is FINISHED, finish the loop");
|
log(side,
|
||||||
|
"Handshake status is NOT_HANDSHAKING, finish the loop");
|
||||||
endLoops = true;
|
endLoops = true;
|
||||||
}
|
}
|
||||||
} else if (hs == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
|
case FINISHED -> throw new Exception( "Unexpected status, " +
|
||||||
List<DatagramPacket> packets = new ArrayList<>();
|
"SSLEngine.getHandshakeStatus() shouldn't return FINISHED");
|
||||||
boolean finished = produceHandshakePackets(
|
default -> throw new Exception("Can't reach here, " +
|
||||||
engine, peerAddr, side, packets);
|
"handshake status is " + hs);
|
||||||
|
|
||||||
log(side, "Produced " + packets.size() + " packets");
|
|
||||||
for (DatagramPacket p : packets) {
|
|
||||||
socket.send(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (finished) {
|
|
||||||
log(side, "Handshake status is FINISHED "
|
|
||||||
+ "after producing handshake packets, "
|
|
||||||
+ "finish the loop");
|
|
||||||
endLoops = true;
|
|
||||||
}
|
|
||||||
} else if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) {
|
|
||||||
runDelegatedTasks(engine);
|
|
||||||
} else if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
|
|
||||||
log(side,
|
|
||||||
"Handshake status is NOT_HANDSHAKING, finish the loop");
|
|
||||||
endLoops = true;
|
|
||||||
} else if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {
|
|
||||||
throw new Exception(
|
|
||||||
"Unexpected status, SSLEngine.getHandshakeStatus() "
|
|
||||||
+ "shouldn't return FINISHED");
|
|
||||||
} else {
|
|
||||||
throw new Exception(
|
|
||||||
"Can't reach here, handshake status is " + hs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,13 +270,39 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void verifySSLEngineResultStatus(SSLEngineResult r, String side) throws Exception {
|
||||||
|
SSLEngineResult.Status rs = r.getStatus();
|
||||||
|
SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus();
|
||||||
|
switch (rs) {
|
||||||
|
case OK -> log(side, "SSLEngineResult status OK");
|
||||||
|
case BUFFER_OVERFLOW -> {
|
||||||
|
log(side, "BUFFER_OVERFLOW, handshake status is " + hs);
|
||||||
|
// the client maximum fragment size config does not work?
|
||||||
|
throw new Exception("Buffer overflow: " +
|
||||||
|
"incorrect client maximum fragment size");
|
||||||
|
}
|
||||||
|
case BUFFER_UNDERFLOW -> {
|
||||||
|
log(side, "BUFFER_UNDERFLOW, handshake status is " + hs);
|
||||||
|
// bad packet, or the client maximum fragment size
|
||||||
|
// config does not work?
|
||||||
|
if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
|
||||||
|
throw new Exception("Buffer underflow: " +
|
||||||
|
"incorrect client maximum fragment size");
|
||||||
|
} // otherwise, ignore this packet
|
||||||
|
}
|
||||||
|
case CLOSED -> throw new Exception(
|
||||||
|
"SSL engine closed, handshake status is " + hs);
|
||||||
|
default -> throw new Exception("Can't reach here, result is " + rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// deliver application data
|
// deliver application data
|
||||||
void deliverAppData(SSLEngine engine, DatagramSocket socket,
|
void deliverAppData(SSLEngine engine, DatagramSocket socket,
|
||||||
ByteBuffer appData, SocketAddress peerAddr) throws Exception {
|
ByteBuffer appData, SocketAddress peerAddr, String side) throws Exception {
|
||||||
|
|
||||||
// Note: have not consider the packet loses
|
// Note: have not consider the packet loses
|
||||||
List<DatagramPacket> packets =
|
List<DatagramPacket> packets =
|
||||||
produceApplicationPackets(engine, appData, peerAddr);
|
produceApplicationPackets(engine, appData, peerAddr, side);
|
||||||
appData.flip();
|
appData.flip();
|
||||||
for (DatagramPacket p : packets) {
|
for (DatagramPacket p : packets) {
|
||||||
socket.send(p);
|
socket.send(p);
|
||||||
@ -344,7 +349,7 @@ public class DTLSOverDatagram {
|
|||||||
|
|
||||||
if (--loops < 0) {
|
if (--loops < 0) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException(
|
||||||
"Too much loops to produce handshake packets");
|
"Too many loops to produce handshake packets");
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer oNet = ByteBuffer.allocate(32768);
|
ByteBuffer oNet = ByteBuffer.allocate(32768);
|
||||||
@ -356,30 +361,9 @@ public class DTLSOverDatagram {
|
|||||||
SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus();
|
SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus();
|
||||||
log(side, "----produce handshake packet(" +
|
log(side, "----produce handshake packet(" +
|
||||||
loops + ", " + rs + ", " + hs + ")----");
|
loops + ", " + rs + ", " + hs + ")----");
|
||||||
if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {
|
|
||||||
// the client maximum fragment size config does not work?
|
|
||||||
throw new Exception("Buffer overflow: " +
|
|
||||||
"incorrect server maximum fragment size");
|
|
||||||
} else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
|
|
||||||
log(side,
|
|
||||||
"Produce handshake packets: BUFFER_UNDERFLOW occured");
|
|
||||||
log(side,
|
|
||||||
"Produce handshake packets: Handshake status: " + hs);
|
|
||||||
// bad packet, or the client maximum fragment size
|
|
||||||
// config does not work?
|
|
||||||
if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
|
|
||||||
throw new Exception("Buffer underflow: " +
|
|
||||||
"incorrect server maximum fragment size");
|
|
||||||
} // otherwise, ignore this packet
|
|
||||||
} else if (rs == SSLEngineResult.Status.CLOSED) {
|
|
||||||
throw new Exception("SSLEngine has closed");
|
|
||||||
} else if (rs == SSLEngineResult.Status.OK) {
|
|
||||||
// OK
|
|
||||||
} else {
|
|
||||||
throw new Exception("Can't reach here, result is " + rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSLEngineResult.Status.OK:
|
verifySSLEngineResultStatus(r, side);
|
||||||
|
|
||||||
if (oNet.hasRemaining()) {
|
if (oNet.hasRemaining()) {
|
||||||
byte[] ba = new byte[oNet.remaining()];
|
byte[] ba = new byte[oNet.remaining()];
|
||||||
oNet.get(ba);
|
oNet.get(ba);
|
||||||
@ -396,24 +380,20 @@ public class DTLSOverDatagram {
|
|||||||
boolean endInnerLoop = false;
|
boolean endInnerLoop = false;
|
||||||
SSLEngineResult.HandshakeStatus nhs = hs;
|
SSLEngineResult.HandshakeStatus nhs = hs;
|
||||||
while (!endInnerLoop) {
|
while (!endInnerLoop) {
|
||||||
if (nhs == SSLEngineResult.HandshakeStatus.NEED_TASK) {
|
switch (nhs) {
|
||||||
runDelegatedTasks(engine);
|
case NEED_TASK -> runDelegatedTasks(engine);
|
||||||
} else if (nhs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ||
|
case NEED_UNWRAP, NEED_UNWRAP_AGAIN, NOT_HANDSHAKING -> {
|
||||||
nhs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN ||
|
endInnerLoop = true;
|
||||||
nhs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
|
endLoops = true;
|
||||||
|
}
|
||||||
endInnerLoop = true;
|
case NEED_WRAP -> endInnerLoop = true;
|
||||||
endLoops = true;
|
case FINISHED -> throw new Exception(
|
||||||
} else if (nhs == SSLEngineResult.HandshakeStatus.NEED_WRAP) {
|
|
||||||
endInnerLoop = true;
|
|
||||||
} else if (nhs == SSLEngineResult.HandshakeStatus.FINISHED) {
|
|
||||||
throw new Exception(
|
|
||||||
"Unexpected status, SSLEngine.getHandshakeStatus() "
|
"Unexpected status, SSLEngine.getHandshakeStatus() "
|
||||||
+ "shouldn't return FINISHED");
|
+ "should not return FINISHED");
|
||||||
} else {
|
default -> throw new Exception("Can't reach here, handshake status is "
|
||||||
throw new Exception("Can't reach here, handshake status is "
|
|
||||||
+ nhs);
|
+ nhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
nhs = engine.getHandshakeStatus();
|
nhs = engine.getHandshakeStatus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -428,30 +408,15 @@ public class DTLSOverDatagram {
|
|||||||
// produce application packets
|
// produce application packets
|
||||||
List<DatagramPacket> produceApplicationPackets(
|
List<DatagramPacket> produceApplicationPackets(
|
||||||
SSLEngine engine, ByteBuffer source,
|
SSLEngine engine, ByteBuffer source,
|
||||||
SocketAddress socketAddr) throws Exception {
|
SocketAddress socketAddr, String side) throws Exception {
|
||||||
|
|
||||||
List<DatagramPacket> packets = new ArrayList<>();
|
List<DatagramPacket> packets = new ArrayList<>();
|
||||||
ByteBuffer appNet = ByteBuffer.allocate(32768);
|
ByteBuffer appNet = ByteBuffer.allocate(32768);
|
||||||
SSLEngineResult r = engine.wrap(source, appNet);
|
SSLEngineResult r = engine.wrap(source, appNet);
|
||||||
appNet.flip();
|
appNet.flip();
|
||||||
|
|
||||||
SSLEngineResult.Status rs = r.getStatus();
|
verifySSLEngineResultStatus(r, side);
|
||||||
if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {
|
|
||||||
// the client maximum fragment size config does not work?
|
|
||||||
throw new Exception("Buffer overflow: " +
|
|
||||||
"incorrect server maximum fragment size");
|
|
||||||
} else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
|
|
||||||
// unlikely
|
|
||||||
throw new Exception("Buffer underflow during wraping");
|
|
||||||
} else if (rs == SSLEngineResult.Status.CLOSED) {
|
|
||||||
throw new Exception("SSLEngine has closed");
|
|
||||||
} else if (rs == SSLEngineResult.Status.OK) {
|
|
||||||
// OK
|
|
||||||
} else {
|
|
||||||
throw new Exception("Can't reach here, result is " + rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SSLEngineResult.Status.OK:
|
|
||||||
if (appNet.hasRemaining()) {
|
if (appNet.hasRemaining()) {
|
||||||
byte[] ba = new byte[appNet.remaining()];
|
byte[] ba = new byte[appNet.remaining()];
|
||||||
appNet.get(ba);
|
appNet.get(ba);
|
||||||
@ -472,7 +437,7 @@ public class DTLSOverDatagram {
|
|||||||
int offset = packet.getOffset();
|
int offset = packet.getOffset();
|
||||||
int length = packet.getLength();
|
int length = packet.getLength();
|
||||||
|
|
||||||
// Normally, this pakcet should be a handshake message
|
// Normally, this packet should be a handshake message
|
||||||
// record. However, even if the underlying platform
|
// record. However, even if the underlying platform
|
||||||
// splits the record more, we don't really worry about
|
// splits the record more, we don't really worry about
|
||||||
// the improper packet loss because DTLS implementation
|
// the improper packet loss because DTLS implementation
|
||||||
@ -490,12 +455,12 @@ public class DTLSOverDatagram {
|
|||||||
if (data[offset + 4] == 0x00) { // plaintext
|
if (data[offset + 4] == 0x00) { // plaintext
|
||||||
matched =
|
matched =
|
||||||
(data[offset + 13] == handshakeType);
|
(data[offset + 13] == handshakeType);
|
||||||
} else { // cipherext
|
} else { // ciphertext
|
||||||
// The 1st ciphertext is a Finished message.
|
// The 1st ciphertext is a Finished message.
|
||||||
//
|
//
|
||||||
// If it is not proposed to loss the Finished
|
// If it is not proposed to loss the Finished
|
||||||
// message, it is not necessary to check the
|
// message, it is not necessary to check the
|
||||||
// following packets any mroe as a Finished
|
// following packets any more as a Finished
|
||||||
// message is the last handshake message.
|
// message is the last handshake message.
|
||||||
matched = (handshakeType == 20);
|
matched = (handshakeType == 20);
|
||||||
}
|
}
|
||||||
@ -540,8 +505,8 @@ public class DTLSOverDatagram {
|
|||||||
SSLContext getDTLSContext() throws Exception {
|
SSLContext getDTLSContext() throws Exception {
|
||||||
String passphrase = "passphrase";
|
String passphrase = "passphrase";
|
||||||
return SSLContextBuilder.builder()
|
return SSLContextBuilder.builder()
|
||||||
.trustStore(KeyStoreUtils.loadKeyStore(trustFilename, passphrase))
|
.trustStore(KeyStoreUtils.loadKeyStore(TRUST_FILENAME, passphrase))
|
||||||
.keyStore(KeyStoreUtils.loadKeyStore(keyFilename, passphrase))
|
.keyStore(KeyStoreUtils.loadKeyStore(KEY_FILENAME, passphrase))
|
||||||
.kmfPassphrase(passphrase)
|
.kmfPassphrase(passphrase)
|
||||||
.protocol("DTLS")
|
.protocol("DTLS")
|
||||||
.build();
|
.build();
|
||||||
@ -559,17 +524,22 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final void runTest(DTLSOverDatagram testCase) throws Exception {
|
public final void runTest(DTLSOverDatagram testCase) throws Exception {
|
||||||
try (DatagramSocket serverSocket = new DatagramSocket();
|
InetSocketAddress serverSocketAddress = new InetSocketAddress
|
||||||
DatagramSocket clientSocket = new DatagramSocket()) {
|
(InetAddress.getLoopbackAddress(), 0);
|
||||||
|
InetSocketAddress clientSocketAddress = new InetSocketAddress
|
||||||
|
(InetAddress.getLoopbackAddress(), 0);
|
||||||
|
|
||||||
|
try (DatagramSocket serverSocket = new DatagramSocket(serverSocketAddress);
|
||||||
|
DatagramSocket clientSocket = new DatagramSocket(clientSocketAddress)) {
|
||||||
|
|
||||||
serverSocket.setSoTimeout(SOCKET_TIMEOUT);
|
serverSocket.setSoTimeout(SOCKET_TIMEOUT);
|
||||||
clientSocket.setSoTimeout(SOCKET_TIMEOUT);
|
clientSocket.setSoTimeout(SOCKET_TIMEOUT);
|
||||||
|
|
||||||
InetSocketAddress serverSocketAddr = new InetSocketAddress(
|
InetSocketAddress serverSocketAddr = new InetSocketAddress(
|
||||||
InetAddress.getLocalHost(), serverSocket.getLocalPort());
|
InetAddress.getLoopbackAddress(), serverSocket.getLocalPort());
|
||||||
|
|
||||||
InetSocketAddress clientSocketAddr = new InetSocketAddress(
|
InetSocketAddress clientSocketAddr = new InetSocketAddress(
|
||||||
InetAddress.getLocalHost(), clientSocket.getLocalPort());
|
InetAddress.getLoopbackAddress(), clientSocket.getLocalPort());
|
||||||
|
|
||||||
ExecutorService pool = Executors.newFixedThreadPool(2);
|
ExecutorService pool = Executors.newFixedThreadPool(2);
|
||||||
Future<String> server, client;
|
Future<String> server, client;
|
||||||
@ -611,19 +581,8 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static class ServerCallable implements Callable<String> {
|
record ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||||
|
InetSocketAddress clientSocketAddr) implements Callable<String> {
|
||||||
private final DTLSOverDatagram testCase;
|
|
||||||
private final DatagramSocket socket;
|
|
||||||
private final InetSocketAddress clientSocketAddr;
|
|
||||||
|
|
||||||
ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
|
||||||
InetSocketAddress clientSocketAddr) {
|
|
||||||
|
|
||||||
this.testCase = testCase;
|
|
||||||
this.socket = socket;
|
|
||||||
this.clientSocketAddr = clientSocketAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
@ -649,19 +608,8 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static class ClientCallable implements Callable<String> {
|
record ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
||||||
|
InetSocketAddress serverSocketAddr) implements Callable<String> {
|
||||||
private final DTLSOverDatagram testCase;
|
|
||||||
private final DatagramSocket socket;
|
|
||||||
private final InetSocketAddress serverSocketAddr;
|
|
||||||
|
|
||||||
ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket,
|
|
||||||
InetSocketAddress serverSocketAddr) {
|
|
||||||
|
|
||||||
this.testCase = testCase;
|
|
||||||
this.socket = socket;
|
|
||||||
this.serverSocketAddr = serverSocketAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
@ -687,7 +635,7 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static void printHex(String prefix, ByteBuffer bb) {
|
static void printHex(String prefix, ByteBuffer bb) {
|
||||||
|
|
||||||
synchronized (System.out) {
|
synchronized (System.out) {
|
||||||
System.out.println(prefix);
|
System.out.println(prefix);
|
||||||
@ -700,7 +648,7 @@ public class DTLSOverDatagram {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final static void printHex(String prefix,
|
static void printHex(String prefix,
|
||||||
byte[] bytes, int offset, int length) {
|
byte[] bytes, int offset, int length) {
|
||||||
|
|
||||||
synchronized (System.out) {
|
synchronized (System.out) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -84,7 +84,7 @@ public class PacketLossRetransmission extends DTLSOverDatagram {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
isClient = args[0].equals("client");
|
isClient = args[0].equals("client");
|
||||||
handshakeType = Byte.valueOf(args[1]);
|
handshakeType = Byte.parseByte(args[1]);
|
||||||
|
|
||||||
PacketLossRetransmission testCase = new PacketLossRetransmission();
|
PacketLossRetransmission testCase = new PacketLossRetransmission();
|
||||||
testCase.runTest(testCase);
|
testCase.runTest(testCase);
|
||||||
@ -97,7 +97,7 @@ public class PacketLossRetransmission extends DTLSOverDatagram {
|
|||||||
boolean finished = super.produceHandshakePackets(
|
boolean finished = super.produceHandshakePackets(
|
||||||
engine, socketAddr, side, packets);
|
engine, socketAddr, side, packets);
|
||||||
|
|
||||||
if (needPacketLoss && (!(isClient ^ engine.getUseClientMode()))) {
|
if (needPacketLoss && (isClient == engine.getUseClientMode())) {
|
||||||
DatagramPacket packet = getPacket(packets, handshakeType);
|
DatagramPacket packet = getPacket(packets, handshakeType);
|
||||||
if (packet != null) {
|
if (packet != null) {
|
||||||
needPacketLoss = false;
|
needPacketLoss = false;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -85,7 +85,7 @@ public class RespondToRetransmit extends DTLSOverDatagram {
|
|||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
isClient = args[0].equals("client");
|
isClient = args[0].equals("client");
|
||||||
handshakeType = Byte.valueOf(args[1]);
|
handshakeType = Byte.parseByte(args[1]);
|
||||||
|
|
||||||
RespondToRetransmit testCase = new RespondToRetransmit();
|
RespondToRetransmit testCase = new RespondToRetransmit();
|
||||||
testCase.runTest(testCase);
|
testCase.runTest(testCase);
|
||||||
@ -98,7 +98,7 @@ public class RespondToRetransmit extends DTLSOverDatagram {
|
|||||||
boolean finished = super.produceHandshakePackets(
|
boolean finished = super.produceHandshakePackets(
|
||||||
engine, socketAddr, side, packets);
|
engine, socketAddr, side, packets);
|
||||||
|
|
||||||
if (needPacketDuplicate && (!(isClient ^ engine.getUseClientMode()))) {
|
if (needPacketDuplicate && (isClient == engine.getUseClientMode())) {
|
||||||
DatagramPacket packet = getPacket(packets, handshakeType);
|
DatagramPacket packet = getPacket(packets, handshakeType);
|
||||||
if (packet != null) {
|
if (packet != null) {
|
||||||
needPacketDuplicate = false;
|
needPacketDuplicate = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user