src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java
Print this page
8167680 DTLS implementation bugs
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
@@ -992,20 +992,35 @@
fatal(Alerts.alert_unexpected_message, ioe);
}
// plainText should never be null for TLS protocols
HandshakeStatus hsStatus = null;
- if (!isDTLS || plainText != null) {
+ if (plainText == Plaintext.PLAINTEXT_NULL) {
+ // Only happens for DTLS protocols.
+ //
+ // Received a retransmitted flight, and need to retransmit the
+ // previous delivered handshake flight messages.
+ if (enableRetransmissions) {
+ if (debug != null && Debug.isOn("verbose")) {
+ Debug.log(
+ "Retransmit the previous handshake flight messages.");
+ }
+
+ synchronized (this) {
+ outputRecord.launchRetransmission();
+ }
+ } // Otherwise, discard the retransmitted flight.
+ } else if (!isDTLS || plainText != null) {
hsStatus = processInputRecord(plainText, appData, offset, length);
}
if (hsStatus == null) {
hsStatus = getHSStatus(null);
}
if (plainText == null) {
- plainText = new Plaintext();
+ plainText = Plaintext.PLAINTEXT_NULL;
}
plainText.handshakeStatus = hsStatus;
return plainText;
}
@@ -1376,11 +1391,12 @@
Ciphertext ciphertext = null;
try {
// Acquire the buffered to-be-delivered records or retransmissions.
//
// May have buffered records, or need retransmission if handshaking.
- if (!outputRecord.isEmpty() || (handshaker != null)) {
+ if (!outputRecord.isEmpty() ||
+ (enableRetransmissions && handshaker != null)) {
ciphertext = outputRecord.acquireCiphertext(netData);
}
if ((ciphertext == null) && (appData != null)) {
ciphertext = outputRecord.encode(
@@ -1401,17 +1417,40 @@
return Ciphertext.CIPHERTEXT_NULL;
}
HandshakeStatus hsStatus = null;
Ciphertext.RecordType recordType = ciphertext.recordType;
- if ((handshaker != null) &&
- (recordType.contentType == Record.ct_handshake) &&
+ if ((recordType.contentType == Record.ct_handshake) &&
(recordType.handshakeType == HandshakeMessage.ht_finished) &&
- handshaker.isDone() && outputRecord.isEmpty()) {
+ outputRecord.isEmpty()) {
+ if (handshaker == null) {
+ hsStatus = HandshakeStatus.FINISHED;
+ } else if (handshaker.isDone()) {
hsStatus = finishHandshake();
connectionState = cs_DATA;
+
+ // Retransmit the last flight twice.
+ //
+ // The application data transactions may begin immediately
+ // after the last flight. If the last flight get lost, the
+ // application data may be discarded accordingly. As could
+ // be an issue for some applications. This impact can be
+ // mitigated by sending the last fligth twice.
+ if (isDTLS && enableRetransmissions) {
+ if (debug != null && Debug.isOn("verbose")) {
+ Debug.log(
+ "Retransmit the last flight messages.");
+ }
+
+ synchronized (this) {
+ outputRecord.launchRetransmission();
+ }
+
+ hsStatus = HandshakeStatus.NEED_WRAP;
+ }
+ }
} // Otherwise, the followed call to getHSStatus() will help.
/*
* We only need to check the sequence number state for
* non-handshaking record.