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 2020/12/02 10:42:36 UTC
[httpcomponents-core] branch master updated: Bug fix: do not
attempt to shut down non-blocking TLS session gracefully in case the TLS
handshake has not been fully completed
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/master by this push:
new 21d06c4 Bug fix: do not attempt to shut down non-blocking TLS session gracefully in case the TLS handshake has not been fully completed
21d06c4 is described below
commit 21d06c483a2a2624d17c769aef8ea3b0604714b9
Author: Oleg Kalnichevski <ol...@apache.org>
AuthorDate: Sun Nov 29 11:41:41 2020 +0100
Bug fix: do not attempt to shut down non-blocking TLS session gracefully in case the TLS handshake has not been fully completed
---
.../hc/core5/testing/nio/H2TLSIntegrationTest.java | 11 -----------
.../apache/hc/core5/reactor/ssl/SSLIOSession.java | 22 ++++++++++++++--------
2 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
index 5dcc7f8..0833c57 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/H2TLSIntegrationTest.java
@@ -70,12 +70,9 @@ import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.testing.SSLTestContexts;
import org.apache.hc.core5.testing.classic.LoggingConnPoolListener;
-import org.apache.hc.core5.util.ReflectionUtils;
import org.apache.hc.core5.util.Timeout;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;
@@ -118,13 +115,6 @@ public class H2TLSIntegrationTest {
};
- private static int javaVersion;
-
- @BeforeClass
- public static void determineJavaVersion() {
- javaVersion = ReflectionUtils.determineJRELevel();
- }
-
@Test
public void testTLSSuccess() throws Exception {
server = AsyncServerBootstrap.bootstrap()
@@ -387,7 +377,6 @@ public class H2TLSIntegrationTest {
@Test
public void testWeakCiphersDisabledByDefault() throws Exception {
- Assume.assumeTrue("Java version must be 1.8 or lesser", javaVersion <= 8);
requester = H2RequesterBootstrap.bootstrap()
.setIOReactorConfig(IOReactorConfig.custom()
.setSoTimeout(TIMEOUT)
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 8530858..b5d34a9 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
@@ -35,6 +35,7 @@ import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import javax.net.ssl.SSLContext;
@@ -70,6 +71,8 @@ import org.apache.hc.core5.util.Timeout;
@Internal
public class SSLIOSession implements IOSession {
+ enum TLSHandShakeState { READY, INITIALIZED, HANDSHAKING, COMPLETE }
+
private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
private final NamedEndpoint targetEndpoint;
@@ -85,13 +88,13 @@ public class SSLIOSession implements IOSession {
private final Timeout connectTimeout;
private final SSLMode sslMode;
private final AtomicInteger outboundClosedCount;
+ private final AtomicReference<TLSHandShakeState> handshakeStateRef;
private final IOEventHandler internalEventHandler;
private int appEventMask;
private volatile boolean endOfStream;
private volatile Status status = Status.ACTIVE;
- private volatile boolean initialized;
private volatile Timeout socketTimeout;
private volatile TlsDetails tlsDetails;
@@ -148,19 +151,20 @@ public class SSLIOSession implements IOSession {
final int appBufferSize = sslSession.getApplicationBufferSize();
this.inPlain = SSLManagedBuffer.create(sslBufferMode, appBufferSize);
this.outboundClosedCount = new AtomicInteger(0);
+ this.handshakeStateRef = new AtomicReference<>(TLSHandShakeState.READY);
this.connectTimeout = connectTimeout;
this.internalEventHandler = new IOEventHandler() {
@Override
public void connected(final IOSession protocolSession) throws IOException {
- if (!initialized) {
+ if (handshakeStateRef.compareAndSet(TLSHandShakeState.READY, TLSHandShakeState.INITIALIZED)) {
initialize();
}
}
@Override
public void inputReady(final IOSession protocolSession, final ByteBuffer src) throws IOException {
- if (!initialized) {
+ if (handshakeStateRef.compareAndSet(TLSHandShakeState.READY, TLSHandShakeState.INITIALIZED)) {
initialize();
}
receiveEncryptedData();
@@ -171,7 +175,7 @@ public class SSLIOSession implements IOSession {
@Override
public void outputReady(final IOSession protocolSession) throws IOException {
- if (!initialized) {
+ if (handshakeStateRef.compareAndSet(TLSHandShakeState.READY, TLSHandShakeState.INITIALIZED)) {
initialize();
}
encryptData();
@@ -192,6 +196,10 @@ public class SSLIOSession implements IOSession {
@Override
public void exception(final IOSession protocolSession, final Exception cause) {
final IOEventHandler handler = session.getHandler();
+ if (handshakeStateRef.get() != TLSHandShakeState.COMPLETE) {
+ session.close(CloseMode.GRACEFUL);
+ close(CloseMode.IMMEDIATE);
+ }
if (handler != null) {
handler.exception(SSLIOSession.this, cause);
}
@@ -221,8 +229,6 @@ public class SSLIOSession implements IOSession {
}
private void initialize() throws IOException {
- Asserts.check(!this.initialized, "SSL I/O session already initialized");
-
// Save the initial socketTimeout of the underlying IOSession, to be restored after the handshake is finished
this.socketTimeout = this.session.getSocketTimeout();
if (connectTimeout != null) {
@@ -245,7 +251,7 @@ public class SSLIOSession implements IOSession {
if (this.initializer != null) {
this.initializer.initialize(this.targetEndpoint, this.sslEngine);
}
- this.initialized = true;
+ this.handshakeStateRef.set(TLSHandShakeState.HANDSHAKING);
this.sslEngine.beginHandshake();
this.inEncrypted.release();
@@ -592,7 +598,7 @@ public class SSLIOSession implements IOSession {
if (this.status != Status.ACTIVE) {
throw new ClosedChannelException();
}
- if (!this.initialized) {
+ if (this.handshakeStateRef.get() == TLSHandShakeState.READY) {
return 0;
}
final ByteBuffer outEncryptedBuf = this.outEncrypted.acquire();