You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2024/07/08 13:57:25 UTC
(httpcomponents-core) branch 5.2.x updated: Attempt to shut down the connection gracefully in case of a TLS handshake exception
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch 5.2.x
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/5.2.x by this push:
new 8be0cf2ad Attempt to shut down the connection gracefully in case of a TLS handshake exception
8be0cf2ad is described below
commit 8be0cf2ad1cde0776da5cfb508240c42d77e1e2d
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Fri Jul 5 16:57:15 2024 +0200
Attempt to shut down the connection gracefully in case of a TLS handshake exception
---
.../impl/nio/AbstractH2StreamMultiplexer.java | 3 +++
.../http/impl/nio/AbstractHttp1StreamDuplexer.java | 3 +++
.../apache/hc/core5/reactor/ssl/SSLIOSession.java | 22 ++++++++++++++++------
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
index 03ac7302e..3066cc346 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractH2StreamMultiplexer.java
@@ -42,6 +42,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import org.apache.hc.core5.concurrent.CancellableDependency;
@@ -698,6 +699,8 @@ abstract class AbstractH2StreamMultiplexer implements Identifiable, HttpConnecti
final CloseMode closeMode;
if (cause instanceof ConnectionClosedException) {
closeMode = CloseMode.GRACEFUL;
+ } else if (cause instanceof SSLHandshakeException) {
+ closeMode = CloseMode.GRACEFUL;
} else if (cause instanceof IOException) {
closeMode = CloseMode.IMMEDIATE;
} else {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
index 90684952f..60fb8f886 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/AbstractHttp1StreamDuplexer.java
@@ -36,6 +36,7 @@ import java.nio.channels.WritableByteChannel;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import org.apache.hc.core5.http.ConnectionClosedException;
@@ -165,6 +166,8 @@ abstract class AbstractHttp1StreamDuplexer<IncomingMessage extends HttpMessage,
final CloseMode closeMode;
if (cause instanceof ConnectionClosedException) {
closeMode = CloseMode.GRACEFUL;
+ } else if (cause instanceof SSLHandshakeException) {
+ closeMode = CloseMode.GRACEFUL;
} else if (cause instanceof IOException) {
closeMode = CloseMode.IMMEDIATE;
} else {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
index ae0c1882b..b48c49543 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java
@@ -232,8 +232,12 @@ public class SSLIOSession implements IOSession {
}
final IOEventHandler handler = session.getHandler();
if (handshakeStateRef.get() != TLSHandShakeState.COMPLETE) {
- session.close(CloseMode.GRACEFUL);
- close(CloseMode.IMMEDIATE);
+ if (cause instanceof SSLHandshakeException) {
+ close(CloseMode.GRACEFUL);
+ } else {
+ session.close(CloseMode.GRACEFUL);
+ close(CloseMode.IMMEDIATE);
+ }
}
if (handler != null) {
handler.exception(protocolSession, cause);
@@ -467,13 +471,17 @@ public class SSLIOSession implements IOSession {
this.sslEngine.closeOutbound();
this.outboundClosedCount.incrementAndGet();
}
- if (this.status == Status.CLOSING && this.sslEngine.isOutboundDone()
+ final HandshakeStatus handshakeStatus = this.sslEngine.getHandshakeStatus();
+ if (this.status == Status.CLOSING
+ && (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING || handshakeStatus == HandshakeStatus.FINISHED)
+ && !this.outEncrypted.hasData()
+ && this.sslEngine.isOutboundDone()
&& (this.endOfStream || this.sslEngine.isInboundDone())) {
this.status = Status.CLOSED;
}
// Abnormal session termination
if (this.status.compareTo(Status.CLOSING) <= 0 && this.endOfStream
- && this.sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) {
+ && handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
this.status = Status.CLOSED;
}
if (this.status == Status.CLOSED) {
@@ -484,7 +492,7 @@ public class SSLIOSession implements IOSession {
return;
}
// Is there a task pending?
- if (this.sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
+ if (handshakeStatus == HandshakeStatus.NEED_TASK) {
doRunTask();
}
// Need to toggle the event mask for this channel?
@@ -527,7 +535,7 @@ public class SSLIOSession implements IOSession {
private int sendEncryptedData() throws IOException {
this.session.getLock().lock();
try {
- if (!this.outEncrypted.hasData()) {
+ if (this.status == Status.ACTIVE && !this.outEncrypted.hasData()) {
// If the buffer isn't acquired or is empty, call write() with an empty buffer.
// This will ensure that tests performed by write() still take place without
// having to acquire and release an empty buffer (e.g. connection closed,
@@ -719,6 +727,8 @@ public class SSLIOSession implements IOSession {
// in the JSSE provider. For instance
// com.android.org.conscrypt.NativeCrypto#SSL_get_shutdown can
// throw NPE at this point
+ doHandshake(this);
+ sendEncryptedData();
updateEventMask();
} catch (final CancelledKeyException ex) {
this.session.close(CloseMode.GRACEFUL);