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 2017/11/14 16:56:44 UTC
[4/4] httpcomponents-core git commit: Fixed incorrect handing of
premature i/o session termination by the server side application protocol
negotiator
Fixed incorrect handing of premature i/o session termination by the server side application protocol negotiator
Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/502f9d9a
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/502f9d9a
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/502f9d9a
Branch: refs/heads/master
Commit: 502f9d9acd674708ace6765e4845d9a4371a72d9
Parents: 001c901
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Tue Nov 14 17:00:27 2017 +0100
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Tue Nov 14 17:00:27 2017 +0100
----------------------------------------------------------------------
.../impl/nio/ServerHttpProtocolNegotiator.java | 16 +++++--
.../hc/core5/testing/nio/Http2ALPNTest.java | 47 ++++++++++++++++++++
2 files changed, 59 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/502f9d9a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
index 64fba27..e90d825 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiator.java
@@ -36,15 +36,15 @@ import javax.net.ssl.SSLSession;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.ConnectionClosedException;
import org.apache.hc.core5.http.EndpointDetails;
+import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.ProtocolVersion;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
import org.apache.hc.core5.http.impl.nio.ServerHttp1IOEventHandler;
import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexer;
import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
-import org.apache.hc.core5.http2.H2ConnectionException;
-import org.apache.hc.core5.http2.H2Error;
import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.io.ShutdownType;
@@ -111,8 +111,12 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public void inputReady(final IOSession session) {
try {
+ boolean endOfStream = false;
if (bytebuf.position() < PREFACE.length) {
- session.channel().read(bytebuf);
+ final int bytesRead = session.channel().read(bytebuf);
+ if (bytesRead == -1) {
+ endOfStream = true;
+ }
}
if (bytebuf.position() >= PREFACE.length) {
bytebuf.flip();
@@ -121,7 +125,7 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
for (int i = 0; i < PREFACE.length; i++) {
if (bytebuf.get() != PREFACE[i]) {
if (expectValidH2Preface) {
- throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Unexpected HTTP/2 preface");
+ throw new HttpException("Unexpected HTTP/2 preface");
} else {
validH2Preface = false;
}
@@ -142,6 +146,10 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
http1StreamHandler.onConnect(bytebuf);
http1StreamHandler.onInput();
}
+ } else {
+ if (endOfStream) {
+ throw new ConnectionClosedException("Connection closed");
+ }
}
} catch (final Exception ex) {
exception(session, ex);
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/502f9d9a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ALPNTest.java
----------------------------------------------------------------------
diff --git a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ALPNTest.java b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ALPNTest.java
index bae22f4..3f29e26 100644
--- a/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ALPNTest.java
+++ b/httpcore5-testing/src/test/java/org/apache/hc/core5/testing/nio/Http2ALPNTest.java
@@ -30,10 +30,12 @@ package org.apache.hc.core5.testing.nio;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.ContentType;
+import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.HttpStatus;
@@ -67,6 +69,7 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.ExternalResource;
public class Http2ALPNTest {
@@ -159,6 +162,9 @@ public class Http2ALPNTest {
};
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
private static int javaVersion;
@BeforeClass
@@ -204,4 +210,45 @@ public class Http2ALPNTest {
Assert.assertThat(body1, CoreMatchers.equalTo("some stuff"));
}
+ @Test()
+ public void testALPNStrict() throws Exception {
+
+ thrown.expect(HttpException.class);
+ thrown.expectMessage("ALPN: missing application protocol");
+
+ log.debug("Starting up test client");
+ requester = Http2MultiplexingRequesterBootstrap.bootstrap()
+ .setIOReactorConfig(IOReactorConfig.custom()
+ .setSoTimeout(TIMEOUT)
+ .build())
+ .setTlsStrategy(new H2ClientTlsStrategy(SSLTestContexts.createClientSSLContext()))
+ .setStrictALPNHandshake(true)
+ .setIOSessionListener(LoggingIOSessionListener.INSTANCE)
+ .setIOSessionDecorator(LoggingIOSessionDecorator.INSTANCE)
+ .setStreamListener(LoggingHttp2StreamListener.INSTANCE)
+ .create();
+
+ server.start();
+ final Future<ListenerEndpoint> future = server.listen(new InetSocketAddress(0));
+ final ListenerEndpoint listener = future.get();
+ final InetSocketAddress address = (InetSocketAddress) listener.getAddress();
+ requester.start();
+
+ final HttpHost target = new HttpHost("localhost", address.getPort(), URIScheme.HTTPS.id);
+ final Future<Message<HttpResponse, String>> resultFuture1 = requester.execute(
+ new BasicRequestProducer("POST", target, "/stuff",
+ new StringAsyncEntityProducer("some stuff", ContentType.TEXT_PLAIN)),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()), TIMEOUT, null);
+ try {
+ resultFuture1.get();
+ Assert.fail("ExecutionException expected");
+ } catch (final ExecutionException ex) {
+ if (ex.getCause() instanceof HttpException) {
+ throw (Exception) ex.getCause();
+ } else {
+ throw ex;
+ }
+ }
+ }
+
}