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/05/09 19:58:05 UTC
[13/50] [abbrv] httpcomponents-core git commit: HTTP protocol version
negotiation
HTTP protocol version negotiation
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk@1792442 13f79535-47bb-0310-9956-ffa450edef68
Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/commit/ed4b808c
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/tree/ed4b808c
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-core/diff/ed4b808c
Branch: refs/heads/trunk
Commit: ed4b808c0d0c6e9754bf5f4e226f055c367b8372
Parents: 3d507fc
Author: Oleg Kalnichevski <ol...@apache.org>
Authored: Mon Apr 24 09:23:56 2017 +0000
Committer: Oleg Kalnichevski <ol...@apache.org>
Committed: Mon Apr 24 09:23:56 2017 +0000
----------------------------------------------------------------------
.../Http2SSLRequestExecutionExample.java | 196 +++++++++++++
.../hc/core5/http2/HttpVersionPolicy.java | 33 +++
.../nio/AbstractHttp2StreamMultiplexer.java | 4 +-
.../impl/nio/ClientHttp2StreamMultiplexer.java | 16 +-
.../ClientHttp2StreamMultiplexerFactory.java | 90 ++++++
.../impl/nio/ClientHttpProtocolNegotiator.java | 167 ++++++-----
.../ClientHttpProtocolNegotiatorFactory.java | 56 ++--
.../ServerHttp2StreamMultiplexerFactory.java | 82 ++++++
.../impl/nio/ServerHttpProtocolNegotiator.java | 109 ++++---
.../ServerHttpProtocolNegotiatorFactory.java | 52 ++--
.../nio/bootstrap/H2RequesterBootstrap.java | 56 +++-
.../impl/nio/bootstrap/H2ServerBootstrap.java | 71 ++++-
.../impl/nio/bootstrap/Http2AsyncRequester.java | 73 +++++
.../core5/http2/ssl/ApplicationProtocols.java | 50 ++++
.../hc/core5/http2/ssl/FixedPortStrategy.java | 56 ++++
.../hc/core5/http2/ssl/H2ClientTlsStrategy.java | 4 +-
.../hc/core5/http2/ssl/H2ServerTlsStrategy.java | 35 +--
.../apache/hc/core5/http2/ssl/H2TlsSupport.java | 63 ++--
.../hc/core5/http2/ssl/SecurePortStrategy.java | 41 +++
.../hc/core5/testing/nio/Http2TestClient.java | 21 +-
.../hc/core5/testing/nio/Http2TestServer.java | 11 +-
.../InternalClientHttp1EventHandlerFactory.java | 69 +----
.../InternalClientHttp2EventHandlerFactory.java | 80 +++---
.../testing/nio/InternalConnectionListener.java | 67 +++++
.../nio/InternalHttp1StreamListener.java | 96 +++++++
.../InternalServerHttp1EventHandlerFactory.java | 69 +----
.../InternalServerHttp2EventHandlerFactory.java | 82 +++---
.../hc/core5/testing/nio/LoggingIOSession.java | 12 +-
.../hc/core5/testing/SSLTestContexts.java | 55 ++++
.../core5/testing/nio/Http1IntegrationTest.java | 5 +-
.../core5/testing/nio/Http2IntegrationTest.java | 3 +-
.../nio/Http2ProtocolNegotiationTest.java | 251 ++++++++++++++++
.../nio/Http2ServerAndRequesterTest.java | 288 +++++++++++++++++++
.../nio/InternalHttp1ServerTestBase.java | 25 +-
.../nio/InternalHttp2ServerTestBase.java | 25 +-
.../http/examples/AsyncReverseProxyExample.java | 2 +-
.../http/impl/bootstrap/AsyncRequester.java | 5 +-
.../impl/bootstrap/AsyncRequesterBootstrap.java | 30 +-
.../impl/bootstrap/AsyncServerBootstrap.java | 21 +-
.../http/impl/bootstrap/HttpAsyncRequester.java | 28 +-
.../impl/nio/AbstractHttp1IOEventHandler.java | 2 +-
.../impl/nio/AbstractHttp1StreamDuplexer.java | 14 +-
.../nio/ClientHttp1IOEventHandlerFactory.java | 92 +-----
.../nio/ClientHttp1StreamDuplexerFactory.java | 137 +++++++++
.../nio/ServerHttp1IOEventHandlerFactory.java | 109 +------
.../nio/ServerHttp1StreamDuplexerFactory.java | 136 +++++++++
.../http/impl/nio/SessionInputBufferImpl.java | 8 +
.../http/nio/ssl/BasicClientTlsStrategy.java | 2 +-
.../http/nio/ssl/BasicServerTlsStrategy.java | 2 +-
.../hc/core5/http/nio/ssl/TlsStrategy.java | 2 +-
.../hc/core5/reactor/InternalIOSession.java | 6 +-
.../hc/core5/reactor/ssl/SSLIOSession.java | 20 +-
.../reactor/ssl/SSLSessionInitializer.java | 9 +-
.../core5/reactor/ssl/SSLSessionVerifier.java | 8 +-
.../apache/hc/core5/reactor/ssl/TlsDetails.java | 63 ++++
.../reactor/ssl/TransportSecurityLayer.java | 3 +-
.../apache/hc/core5/ssl/ReflectionSupport.java | 54 ++++
57 files changed, 2385 insertions(+), 781 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2SSLRequestExecutionExample.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2SSLRequestExecutionExample.java b/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2SSLRequestExecutionExample.java
new file mode 100644
index 0000000..0463420
--- /dev/null
+++ b/httpcore5-h2/src/examples/org/apache/hc/core5/http/examples/Http2SSLRequestExecutionExample.java
@@ -0,0 +1,196 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.core5.http.examples;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLException;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpConnection;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.Message;
+import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
+import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
+import org.apache.hc.core5.http.nio.BasicRequestProducer;
+import org.apache.hc.core5.http.nio.BasicResponseConsumer;
+import org.apache.hc.core5.http.nio.entity.StringAsyncEntityConsumer;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.frame.RawFrame;
+import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.bootstrap.H2RequesterBootstrap;
+import org.apache.hc.core5.http2.ssl.H2ClientTlsStrategy;
+import org.apache.hc.core5.io.ShutdownType;
+import org.apache.hc.core5.net.NamedEndpoint;
+import org.apache.hc.core5.reactor.ssl.SSLSessionVerifier;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
+import org.apache.hc.core5.ssl.SSLContexts;
+import org.apache.hc.core5.ssl.TrustStrategy;
+import org.apache.hc.core5.util.TimeValue;
+
+/**
+ * This example demonstrates how to execute HTTP/2 requests over TLS connections.
+ */
+public class Http2SSLRequestExecutionExample {
+
+ public final static void main(final String[] args) throws Exception {
+ // Trust standard CA and those trusted by our custom strategy
+ final SSLContext sslcontext = SSLContexts.custom()
+ .loadTrustMaterial(new TrustStrategy() {
+
+ @Override
+ public boolean isTrusted(
+ final X509Certificate[] chain,
+ final String authType) throws CertificateException {
+ final X509Certificate cert = chain[0];
+ return "CN=http2bin.org".equalsIgnoreCase(cert.getSubjectDN().getName());
+ }
+
+ })
+ .build();
+
+ // Create and start requester
+ H2Config h2Config = H2Config.custom()
+ .setPushEnabled(false)
+ .build();
+
+ final HttpAsyncRequester requester = H2RequesterBootstrap.bootstrap()
+ .setH2Config(h2Config)
+ .setTlsStrategy(new H2ClientTlsStrategy(sslcontext, new SSLSessionVerifier() {
+
+ @Override
+ public TlsDetails verify(final NamedEndpoint endpoint, final SSLEngine sslEngine) throws SSLException {
+ // IMPORTANT
+ // In order for HTTP/2 protocol negotiation to succeed one must allow access
+ // to Java 9 specific properties of SSLEngine via reflection
+ // by adding the following line to the JVM arguments
+ //
+ // --add-opens java.base/sun.security.ssl=ALL-UNNAMED
+ //
+ // or uncomment the method below
+
+ // return new TlsDetails(sslEngine.getSession(), sslEngine.getApplicationProtocol());
+ return null;
+ }
+
+ }))
+ .setStreamListener(new Http2StreamListener() {
+
+ @Override
+ public void onHeaderInput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") << " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onHeaderOutput(final HttpConnection connection, final int streamId, final List<? extends Header> headers) {
+ for (int i = 0; i < headers.size(); i++) {
+ System.out.println(connection + " (" + streamId + ") >> " + headers.get(i));
+ }
+ }
+
+ @Override
+ public void onFrameInput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onFrameOutput(final HttpConnection connection, final int streamId, final RawFrame frame) {
+ }
+
+ @Override
+ public void onInputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ @Override
+ public void onOutputFlowControl(final HttpConnection connection, final int streamId, final int delta, final int actualSize) {
+ }
+
+ })
+ .create();
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ System.out.println("HTTP requester shutting down");
+ requester.shutdown(ShutdownType.GRACEFUL);
+ }
+ });
+ requester.start();
+
+ HttpHost target = new HttpHost("http2bin.org", 443, "https");
+ String[] requestUris = new String[] {"/", "/ip", "/user-agent", "/headers"};
+
+ final CountDownLatch latch = new CountDownLatch(requestUris.length);
+ for (final String requestUri: requestUris) {
+ final Future<AsyncClientEndpoint> future = requester.connect(target, TimeValue.ofSeconds(5));
+ final AsyncClientEndpoint clientEndpoint = future.get();
+ clientEndpoint.execute(
+ new BasicRequestProducer("GET", target, requestUri),
+ new BasicResponseConsumer<>(new StringAsyncEntityConsumer()),
+ new FutureCallback<Message<HttpResponse, String>>() {
+
+ @Override
+ public void completed(final Message<HttpResponse, String> message) {
+ clientEndpoint.releaseAndReuse();
+ HttpResponse response = message.getHead();
+ String body = message.getBody();
+ System.out.println(requestUri + "->" + response.getCode() + " " + response.getVersion());
+ System.out.println(body);
+ latch.countDown();
+ }
+
+ @Override
+ public void failed(final Exception ex) {
+ clientEndpoint.releaseAndDiscard();
+ System.out.println(requestUri + "->" + ex);
+ latch.countDown();
+ }
+
+ @Override
+ public void cancelled() {
+ clientEndpoint.releaseAndDiscard();
+ System.out.println(requestUri + " cancelled");
+ latch.countDown();
+ }
+
+ });
+ }
+
+ latch.await();
+ System.out.println("Shutting down I/O reactor");
+ requester.initiateShutdown();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/HttpVersionPolicy.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/HttpVersionPolicy.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/HttpVersionPolicy.java
new file mode 100644
index 0000000..237c864
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/HttpVersionPolicy.java
@@ -0,0 +1,33 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+package org.apache.hc.core5.http2;
+
+public enum HttpVersionPolicy {
+
+ FORCE_HTTP_1, FORCE_HTTP_2, NEGOTIATE
+
+};
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
index 61c7fb9..697560b 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/AbstractHttp2StreamMultiplexer.java
@@ -84,6 +84,7 @@ import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.net.InetAddressUtils;
import org.apache.hc.core5.reactor.Command;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.ByteArrayBuffer;
@@ -1188,7 +1189,8 @@ abstract class AbstractHttp2StreamMultiplexer implements HttpConnection {
@Override
public SSLSession getSSLSession() {
- return ioSession.getSSLSession();
+ final TlsDetails tlsDetails = ioSession.getTlsDetails();
+ return tlsDetails != null ? tlsDetails.getSSLSession() : null;
}
@Override
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
index 89e47d5..985fed7 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexer.java
@@ -55,8 +55,8 @@ public class ClientHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
final FrameFactory frameFactory,
final HttpProcessor httpProcessor,
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
- final CharCodingConfig charCodingConfig,
final H2Config h2Config,
+ final CharCodingConfig charCodingConfig,
final ConnectionListener connectionListener,
final Http2StreamListener streamListener) {
super(Mode.CLIENT, ioSession, frameFactory, StreamIdGenerator.ODD, httpProcessor, charCodingConfig,
@@ -68,18 +68,18 @@ public class ClientHttp2StreamMultiplexer extends AbstractHttp2StreamMultiplexer
final TlsCapableIOSession ioSession,
final HttpProcessor httpProcessor,
final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config) {
- this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory, charCodingConfig,
- h2Config, null, null);
+ final H2Config h2Config,
+ final CharCodingConfig charCodingConfig) {
+ this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory,
+ h2Config, charCodingConfig, null, null);
}
public ClientHttp2StreamMultiplexer(
final TlsCapableIOSession ioSession,
final HttpProcessor httpProcessor,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config) {
- this(ioSession, httpProcessor, null, charCodingConfig, h2Config);
+ final H2Config h2Config,
+ final CharCodingConfig charCodingConfig) {
+ this(ioSession, httpProcessor, null, h2Config, charCodingConfig);
}
@Override
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
new file mode 100644
index 0000000..0f15bc0
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttp2StreamMultiplexerFactory.java
@@ -0,0 +1,90 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.impl.nio;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncPushConsumer;
+import org.apache.hc.core5.http.nio.HandlerFactory;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
+import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public final class ClientHttp2StreamMultiplexerFactory {
+
+ private final HttpProcessor httpProcessor;
+ private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
+ private final H2Config h2Config;
+ private final CharCodingConfig charCodingConfig;
+ private final ConnectionListener connectionListener;
+ private final Http2StreamListener streamListener;
+
+ public ClientHttp2StreamMultiplexerFactory(
+ final HttpProcessor httpProcessor,
+ final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
+ final H2Config h2Config,
+ final CharCodingConfig charCodingConfig,
+ final ConnectionListener connectionListener,
+ final Http2StreamListener streamListener) {
+ this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+ this.pushHandlerFactory = pushHandlerFactory;
+ this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
+ this.connectionListener = connectionListener;
+ this.streamListener = streamListener;
+ }
+
+ public ClientHttp2StreamMultiplexerFactory(
+ final HttpProcessor httpProcessor,
+ final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
+ final ConnectionListener connectionListener,
+ final Http2StreamListener streamListener) {
+ this(httpProcessor, pushHandlerFactory, null, null, connectionListener, streamListener);
+ }
+
+ public ClientHttp2StreamMultiplexerFactory(
+ final HttpProcessor httpProcessor,
+ final ConnectionListener connectionListener,
+ final Http2StreamListener streamListener) {
+ this(httpProcessor, null, connectionListener, streamListener);
+ }
+
+ public ClientHttp2StreamMultiplexer create(final TlsCapableIOSession ioSession) {
+ return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
+ pushHandlerFactory, h2Config, charCodingConfig, connectionListener, streamListener);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
index b2f80cc..320b949 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiator.java
@@ -37,23 +37,24 @@ 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.ProtocolVersion;
-import org.apache.hc.core5.http.config.CharCodingConfig;
import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1IOEventHandler;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexer;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
-import org.apache.hc.core5.http.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http.nio.HandlerFactory;
import org.apache.hc.core5.http.nio.command.ExecutionCommand;
-import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.config.H2Config;
-import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.reactor.Command;
import org.apache.hc.core5.reactor.IOEventHandler;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.util.Args;
/**
@@ -69,65 +70,85 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
0x0d, 0x0a, 0x0d, 0x0a};
private final TlsCapableIOSession ioSession;
- private final HttpProcessor httpProcessor;
- private final CharCodingConfig charCodingConfig;
- private final H2Config h2Config;
- private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
+ private final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory;
+ private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
+ private final HttpVersionPolicy versionPolicy;
private final ConnectionListener connectionListener;
- private final Http2StreamListener streamListener;
- private final ByteBuffer preface;
+
+ private volatile ByteBuffer preface;
public ClientHttpProtocolNegotiator(
final TlsCapableIOSession ioSession,
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
+ final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory,
+ final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
+ final HttpVersionPolicy versionPolicy,
+ final ConnectionListener connectionListener) {
this.ioSession = Args.notNull(ioSession, "I/O session");
- this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
- this.pushHandlerFactory = pushHandlerFactory;
- this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
- this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
- this.streamListener = streamListener;
+ this.http1StreamHandlerFactory = Args.notNull(http1StreamHandlerFactory, "HTTP/1.1 stream handler factory");
+ this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.connectionListener = connectionListener;
- this.preface = ByteBuffer.wrap(PREFACE);
}
- protected ClientHttp2StreamMultiplexer createStreamMultiplexer(final TlsCapableIOSession ioSession) {
- return new ClientHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
- pushHandlerFactory, charCodingConfig, h2Config, connectionListener, streamListener);
+ @Override
+ public void connected(final IOSession session) {
+ try {
+ switch (versionPolicy) {
+ case NEGOTIATE:
+ final TlsDetails tlsDetails = ioSession.getTlsDetails();
+ if (tlsDetails != null) {
+ if (ApplicationProtocols.HTTP_2.id.equals(tlsDetails.getApplicationProtocol())) {
+ // Proceed with the H2 preface
+ preface = ByteBuffer.wrap(PREFACE);
+ }
+ }
+ break;
+ case FORCE_HTTP_2:
+ preface = ByteBuffer.wrap(PREFACE);
+ break;
+ }
+ if (preface == null) {
+ final ClientHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(ioSession);
+ session.setHandler(new ClientHttp1IOEventHandler(http1StreamHandler));
+ http1StreamHandler.onConnect(null);
+ } else {
+ writePreface(session);
+ }
+ } catch (final Exception ex) {
+ session.shutdown(ShutdownType.IMMEDIATE);
+ exception(session, ex);
+ }
}
- @Override
- public void connected(final IOSession ioSession) {
- outputReady(ioSession);
+ private void writePreface(final IOSession session) throws IOException {
+ if (preface.hasRemaining()) {
+ final ByteChannel channel = session.channel();
+ channel.write(preface);
+ }
+ if (!preface.hasRemaining()) {
+ final ClientHttp2StreamMultiplexer streamMultiplexer = http2StreamHandlerFactory.create(ioSession);
+ final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
+ newHandler.connected(session);
+ session.setHandler(newHandler);
+ }
}
@Override
public void inputReady(final IOSession session) {
+ outputReady(session);
}
@Override
public void outputReady(final IOSession session) {
- if (preface.hasRemaining()) {
- try {
- final ByteChannel channel = ioSession.channel();
- channel.write(preface);
- } catch (final IOException ex) {
- ioSession.shutdown(ShutdownType.IMMEDIATE);
- if (connectionListener != null) {
- connectionListener.onError(this, ex);
- }
- return;
+ try {
+ if (preface != null) {
+ writePreface(session);
+ } else {
+ session.shutdown(ShutdownType.IMMEDIATE);
}
- }
- if (!preface.hasRemaining()) {
- final ClientHttp2StreamMultiplexer streamMultiplexer = createStreamMultiplexer(ioSession);
- final IOEventHandler newHandler = new ClientHttp2IOEventHandler(streamMultiplexer);
- newHandler.connected(ioSession);
- ioSession.setHandler(newHandler);
+ } catch (final IOException ex) {
+ session.shutdown(ShutdownType.IMMEDIATE);
+ exception(session, ex);
}
}
@@ -136,30 +157,27 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
exception(session, new SocketTimeoutException());
}
- private void failPendingCommands(final Exception cause) {
- for (;;) {
- final Command command = ioSession.getCommand();
- if (command != null) {
- if (command instanceof ExecutionCommand) {
- final ExecutionCommand executionCommand = (ExecutionCommand) command;
- final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
- exchangeHandler.failed(cause);
- } else {
- command.cancel();
- }
- } else {
- break;
- }
- }
- }
-
@Override
public void exception(final IOSession session, final Exception cause) {
if (connectionListener != null) {
connectionListener.onError(this, new SocketTimeoutException());
}
try {
- failPendingCommands(cause);
+ for (;;) {
+ final Command command = ioSession.getCommand();
+ if (command != null) {
+ if (command instanceof ExecutionCommand) {
+ final ExecutionCommand executionCommand = (ExecutionCommand) command;
+ final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
+ exchangeHandler.failed(cause);
+ exchangeHandler.releaseResources();
+ } else {
+ command.cancel();
+ }
+ } else {
+ break;
+ }
+ }
} finally {
session.shutdown(ShutdownType.IMMEDIATE);
}
@@ -167,11 +185,30 @@ public class ClientHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public void disconnected(final IOSession session) {
+ if (connectionListener != null) {
+ connectionListener.onDisconnect(this);
+ }
+ for (;;) {
+ final Command command = ioSession.getCommand();
+ if (command != null) {
+ if (command instanceof ExecutionCommand) {
+ final ExecutionCommand executionCommand = (ExecutionCommand) command;
+ final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
+ exchangeHandler.failed(new ConnectionClosedException("Connection closed"));
+ exchangeHandler.releaseResources();
+ } else {
+ command.cancel();
+ }
+ } else {
+ break;
+ }
+ }
}
@Override
public SSLSession getSSLSession() {
- return ioSession.getSSLSession();
+ final TlsDetails tlsDetails = ioSession.getTlsDetails();
+ return tlsDetails != null ? tlsDetails.getSSLSession() : null;
}
@Override
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
index d99e46c..9a5d2e1 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ClientHttpProtocolNegotiatorFactory.java
@@ -29,12 +29,9 @@ package org.apache.hc.core5.http2.impl.nio;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.config.CharCodingConfig;
import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.nio.AsyncPushConsumer;
-import org.apache.hc.core5.http.nio.HandlerFactory;
-import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
import org.apache.hc.core5.util.Args;
@@ -45,47 +42,30 @@ import org.apache.hc.core5.util.Args;
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class ClientHttpProtocolNegotiatorFactory implements IOEventHandlerFactory {
- private final HttpProcessor httpProcessor;
- private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
- private final CharCodingConfig charCodingConfig;
- private final H2Config h2Config;
+ private final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory;
+ private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
+ private final HttpVersionPolicy versionPolicy;
private final ConnectionListener connectionListener;
- private final Http2StreamListener streamListener;
public ClientHttpProtocolNegotiatorFactory(
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
- this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
- this.pushHandlerFactory = pushHandlerFactory;
- this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
- this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory,
+ final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
+ final HttpVersionPolicy versionPolicy,
+ final ConnectionListener connectionListener) {
+ this.http1StreamHandlerFactory = Args.notNull(http1StreamHandlerFactory, "HTTP/1.1 stream handler factory");
+ this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.connectionListener = connectionListener;
- this.streamListener = streamListener;
- }
-
- public ClientHttpProtocolNegotiatorFactory(
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
- this(httpProcessor, pushHandlerFactory, null, null, connectionListener, streamListener);
- }
-
- public ClientHttpProtocolNegotiatorFactory(
- final HttpProcessor httpProcessor,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
- this(httpProcessor, null, connectionListener, streamListener);
}
@Override
public ClientHttpProtocolNegotiator createHandler(final TlsCapableIOSession ioSession, final Object attachment) {
- return new ClientHttpProtocolNegotiator(ioSession, httpProcessor, pushHandlerFactory,
- charCodingConfig, h2Config, connectionListener, streamListener);
+ return new ClientHttpProtocolNegotiator(
+ ioSession,
+ http1StreamHandlerFactory,
+ http2StreamHandlerFactory,
+ attachment instanceof HttpVersionPolicy ? (HttpVersionPolicy) attachment : versionPolicy,
+ connectionListener);
}
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
new file mode 100644
index 0000000..0d21874
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttp2StreamMultiplexerFactory.java
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.impl.nio;
+
+import org.apache.hc.core5.annotation.Contract;
+import org.apache.hc.core5.annotation.ThreadingBehavior;
+import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
+import org.apache.hc.core5.http.nio.HandlerFactory;
+import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
+import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+@Contract(threading = ThreadingBehavior.IMMUTABLE)
+public final class ServerHttp2StreamMultiplexerFactory {
+
+ private final HttpProcessor httpProcessor;
+ private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
+ private final H2Config h2Config;
+ private final CharCodingConfig charCodingConfig;
+ private final ConnectionListener connectionListener;
+ private final Http2StreamListener streamListener;
+
+ public ServerHttp2StreamMultiplexerFactory(
+ final HttpProcessor httpProcessor,
+ final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
+ final H2Config h2Config,
+ final CharCodingConfig charCodingConfig,
+ final ConnectionListener connectionListener,
+ final Http2StreamListener streamListener) {
+ this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
+ this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
+ this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
+ this.connectionListener = connectionListener;
+ this.streamListener = streamListener;
+ }
+
+ public ServerHttp2StreamMultiplexer create(final TlsCapableIOSession ioSession) {
+ return new ServerHttp2StreamMultiplexer(
+ ioSession,
+ DefaultFrameFactory.INSTANCE,
+ httpProcessor,
+ exchangeHandlerFactory,
+ charCodingConfig,
+ h2Config,
+ connectionListener,
+ streamListener);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/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 65b1430..50c5f4c 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
@@ -38,19 +38,19 @@ import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
import org.apache.hc.core5.http.EndpointDetails;
import org.apache.hc.core5.http.ProtocolVersion;
-import org.apache.hc.core5.http.config.CharCodingConfig;
import org.apache.hc.core5.http.impl.ConnectionListener;
import org.apache.hc.core5.http.impl.nio.HttpConnectionEventHandler;
-import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http.nio.HandlerFactory;
-import org.apache.hc.core5.http.protocol.HttpProcessor;
+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.config.H2Config;
-import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.http2.ssl.ApplicationProtocols;
import org.apache.hc.core5.io.ShutdownType;
import org.apache.hc.core5.reactor.IOSession;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
+import org.apache.hc.core5.reactor.ssl.TlsDetails;
import org.apache.hc.core5.util.Args;
/**
@@ -62,39 +62,51 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
final static byte[] PREFACE = ClientHttpProtocolNegotiator.PREFACE;
private final TlsCapableIOSession ioSession;
- private final HttpProcessor httpProcessor;
- private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
- private final CharCodingConfig charCodingConfig;
- private final H2Config h2Config;
- private final ByteBuffer bytebuf;
+ private final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory;
+ private final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
+ private final HttpVersionPolicy versionPolicy;
private final ConnectionListener connectionListener;
- private final Http2StreamListener streamListener;
+ private final ByteBuffer bytebuf;
+
+ private volatile boolean expectValidH2Preface;
public ServerHttpProtocolNegotiator(
final TlsCapableIOSession ioSession,
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
+ final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory,
+ final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory,
+ final HttpVersionPolicy versionPolicy,
+ final ConnectionListener connectionListener) {
this.ioSession = Args.notNull(ioSession, "I/O session");
- this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
- this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
- this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
- this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
- this.bytebuf = ByteBuffer.allocate(1024);
+ this.http1StreamHandlerFactory = Args.notNull(http1StreamHandlerFactory, "HTTP/1.1 stream handler factory");
+ this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.connectionListener = connectionListener;
- this.streamListener = streamListener;
- }
-
- protected ServerHttp2StreamMultiplexer createStreamMultiplexer(final TlsCapableIOSession ioSession) {
- return new ServerHttp2StreamMultiplexer(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor,
- exchangeHandlerFactory, charCodingConfig, h2Config, connectionListener, streamListener);
+ this.bytebuf = ByteBuffer.allocate(1024);
}
@Override
public void connected(final IOSession session) {
+ try {
+ switch (versionPolicy) {
+ case NEGOTIATE:
+ final TlsDetails tlsDetails = ioSession.getTlsDetails();
+ if (tlsDetails != null) {
+ if (ApplicationProtocols.HTTP_2.id.equals(tlsDetails.getApplicationProtocol())) {
+ expectValidH2Preface = true;
+ // Proceed with the H2 preface
+ break;
+ }
+ }
+ break;
+ case FORCE_HTTP_1:
+ final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(ioSession);
+ session.setHandler(new ServerHttp1IOEventHandler(http1StreamHandler));
+ http1StreamHandler.onConnect(null);
+ break;
+ }
+ } catch (final Exception ex) {
+ exception(session, ex);
+ }
}
@Override
@@ -105,21 +117,32 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
}
if (bytebuf.position() >= PREFACE.length) {
bytebuf.flip();
+
+ boolean validH2Preface = true;
for (int i = 0; i < PREFACE.length; i++) {
if (bytebuf.get() != PREFACE[i]) {
- throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Unexpected HTTP/2 preface");
+ if (expectValidH2Preface) {
+ throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Unexpected HTTP/2 preface");
+ } else {
+ validH2Preface = false;
+ }
}
}
- final ServerHttp2StreamMultiplexer streamMultiplexer = createStreamMultiplexer(ioSession);
- streamMultiplexer.onConnect(bytebuf.hasRemaining() ? bytebuf : null);
- streamMultiplexer.onInput();
- session.setHandler(new ServerHttp2IOEventHandler(streamMultiplexer));
+ if (validH2Preface) {
+ final ServerHttp2StreamMultiplexer http2StreamHandler = http2StreamHandlerFactory.create(ioSession);
+ session.setHandler(new ServerHttp2IOEventHandler(http2StreamHandler));
+ http2StreamHandler.onConnect(bytebuf.hasRemaining() ? bytebuf : null);
+ http2StreamHandler.onInput();
+ } else {
+ final ServerHttp1StreamDuplexer http1StreamHandler = http1StreamHandlerFactory.create(ioSession);
+ session.setHandler(new ServerHttp1IOEventHandler(http1StreamHandler));
+ bytebuf.rewind();
+ http1StreamHandler.onConnect(bytebuf);
+ http1StreamHandler.onInput();
+ }
}
} catch (final Exception ex) {
- session.close();
- if (connectionListener != null) {
- connectionListener.onError(this, ex);
- }
+ exception(session, ex);
}
}
@@ -134,19 +157,23 @@ public class ServerHttpProtocolNegotiator implements HttpConnectionEventHandler
@Override
public void exception(final IOSession session, final Exception cause) {
- session.close();
+ session.shutdown(ShutdownType.IMMEDIATE);
if (connectionListener != null) {
- connectionListener.onError(this, new SocketTimeoutException());
+ connectionListener.onError(this, cause);
}
}
@Override
public void disconnected(final IOSession session) {
+ if (connectionListener != null) {
+ connectionListener.onDisconnect(this);
+ }
}
@Override
public SSLSession getSSLSession() {
- return ioSession.getSSLSession();
+ final TlsDetails tlsDetails = ioSession.getTlsDetails();
+ return tlsDetails != null ? tlsDetails.getSSLSession() : null;
}
@Override
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
index 7394281..ee2873c 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/ServerHttpProtocolNegotiatorFactory.java
@@ -29,13 +29,10 @@ package org.apache.hc.core5.http2.impl.nio;
import org.apache.hc.core5.annotation.Contract;
import org.apache.hc.core5.annotation.ThreadingBehavior;
-import org.apache.hc.core5.http.config.CharCodingConfig;
import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
-import org.apache.hc.core5.http.nio.HandlerFactory;
+import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
-import org.apache.hc.core5.http.protocol.HttpProcessor;
-import org.apache.hc.core5.http2.config.H2Config;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.reactor.IOEventHandlerFactory;
import org.apache.hc.core5.reactor.TlsCapableIOSession;
import org.apache.hc.core5.util.Args;
@@ -46,38 +43,23 @@ import org.apache.hc.core5.util.Args;
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class ServerHttpProtocolNegotiatorFactory implements IOEventHandlerFactory {
- private final HttpProcessor httpProcessor;
- private final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory;
- private final CharCodingConfig charCodingConfig;
- private final H2Config h2Config;
+ private final ServerHttp1StreamDuplexerFactory http1StreamDuplexerFactory;
+ private final ServerHttp2StreamMultiplexerFactory http2StreamMultiplexerFactory;
+ private final HttpVersionPolicy versionPolicy;
private final TlsStrategy tlsStrategy;
private final ConnectionListener connectionListener;
- private final Http2StreamListener streamListener;
public ServerHttpProtocolNegotiatorFactory(
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
- final CharCodingConfig charCodingConfig,
- final H2Config h2Config,
+ final ServerHttp1StreamDuplexerFactory http1StreamDuplexerFactory,
+ final ServerHttp2StreamMultiplexerFactory http2StreamMultiplexerFactory,
+ final HttpVersionPolicy versionPolicy,
final TlsStrategy tlsStrategy,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
- this.httpProcessor = Args.notNull(httpProcessor, "HTTP processor");
- this.exchangeHandlerFactory = Args.notNull(exchangeHandlerFactory, "Exchange handler factory");
- this.charCodingConfig = charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT;
- this.h2Config = h2Config != null ? h2Config : H2Config.DEFAULT;
+ final ConnectionListener connectionListener) {
+ this.http1StreamDuplexerFactory = Args.notNull(http1StreamDuplexerFactory, "HTTP/1.1 stream handler factory");
+ this.http2StreamMultiplexerFactory = Args.notNull(http2StreamMultiplexerFactory, "HTTP/2 stream handler factory");
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
this.tlsStrategy = tlsStrategy;
this.connectionListener = connectionListener;
- this.streamListener = streamListener;
- }
-
- public ServerHttpProtocolNegotiatorFactory(
- final HttpProcessor httpProcessor,
- final HandlerFactory<AsyncServerExchangeHandler> exchangeHandlerFactory,
- final TlsStrategy tlsStrategy,
- final ConnectionListener connectionListener,
- final Http2StreamListener streamListener) {
- this(httpProcessor, exchangeHandlerFactory, null, null, tlsStrategy, connectionListener, streamListener);
}
@Override
@@ -87,10 +69,14 @@ public class ServerHttpProtocolNegotiatorFactory implements IOEventHandlerFactor
ioSession,
null,
ioSession.getLocalAddress(),
- ioSession.getRemoteAddress());
+ ioSession.getRemoteAddress(),
+ attachment != null ? attachment : versionPolicy);
}
- return new ServerHttpProtocolNegotiator(ioSession, httpProcessor, exchangeHandlerFactory,
- charCodingConfig, h2Config, connectionListener, streamListener);
+ return new ServerHttpProtocolNegotiator(ioSession,
+ http1StreamDuplexerFactory,
+ http2StreamMultiplexerFactory,
+ versionPolicy,
+ connectionListener);
}
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
index a6b0b35..e856800 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2RequesterBootstrap.java
@@ -33,13 +33,18 @@ import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.ExceptionListener;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
import org.apache.hc.core5.http.impl.ConnectionListener;
-import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
+import org.apache.hc.core5.http.impl.HttpProcessors;
+import org.apache.hc.core5.http.impl.nio.ClientHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.nio.AsyncPushConsumer;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.http2.impl.Http2Processors;
+import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexerFactory;
import org.apache.hc.core5.http2.impl.nio.ClientHttpProtocolNegotiatorFactory;
import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
import org.apache.hc.core5.http2.ssl.H2ClientTlsStrategy;
@@ -62,7 +67,9 @@ public class H2RequesterBootstrap {
private IOReactorConfig ioReactorConfig;
private HttpProcessor httpProcessor;
private CharCodingConfig charCodingConfig;
+ private HttpVersionPolicy versionPolicy;
private H2Config h2Config;
+ private H1Config h1Config;
private int defaultMaxPerRoute;
private int maxTotal;
private TimeValue timeToLive;
@@ -71,6 +78,7 @@ public class H2RequesterBootstrap {
private ExceptionListener exceptionListener;
private ConnectionListener connectionListener;
private Http2StreamListener streamListener;
+ private Http1StreamListener http1StreamListener;
private ConnPoolListener<HttpHost> connPoolListener;
private H2RequesterBootstrap() {
@@ -98,6 +106,14 @@ public class H2RequesterBootstrap {
}
/**
+ * Sets HTTP protocol version policy
+ */
+ public final H2RequesterBootstrap setVersionPolicy(final HttpVersionPolicy versionPolicy) {
+ this.versionPolicy = versionPolicy;
+ return this;
+ }
+
+ /**
* Sets HTTP/2 protocol parameters
*/
public final H2RequesterBootstrap setH2Config(final H2Config h2Config) {
@@ -106,7 +122,15 @@ public class H2RequesterBootstrap {
}
/**
- * Sets char coding for HTTP/2 messages.
+ * Sets HTTP/1.1 protocol parameters
+ */
+ public final H2RequesterBootstrap setH1Config(final H1Config h1Config) {
+ this.h1Config = h1Config;
+ return this;
+ }
+
+ /**
+ * Sets message char coding.
*/
public final H2RequesterBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
this.charCodingConfig = charCodingConfig;
@@ -169,6 +193,14 @@ public class H2RequesterBootstrap {
}
/**
+ * Assigns {@link Http1StreamListener} instance.
+ */
+ public final H2RequesterBootstrap setStreamListener(final Http1StreamListener http1StreamListener) {
+ this.http1StreamListener = http1StreamListener;
+ return this;
+ }
+
+ /**
* Assigns {@link ConnPoolListener} instance.
*/
public final H2RequesterBootstrap setConnPoolListener(final ConnPoolListener<HttpHost> connPoolListener) {
@@ -191,7 +223,7 @@ public class H2RequesterBootstrap {
return this;
}
- public HttpAsyncRequester create() {
+ public Http2AsyncRequester create() {
final StrictConnPool<HttpHost, IOSession> connPool = new StrictConnPool<>(
defaultMaxPerRoute > 0 ? defaultMaxPerRoute : 20,
maxTotal > 0 ? maxTotal : 50,
@@ -202,15 +234,27 @@ public class H2RequesterBootstrap {
for (final PushConsumerEntry entry: pushConsumerList) {
pushConsumerRegistry.register(entry.hostname, entry.uriPattern, entry.supplier);
}
- final ClientHttpProtocolNegotiatorFactory ioEventHandlerFactory = new ClientHttpProtocolNegotiatorFactory(
+ final ClientHttp1StreamDuplexerFactory http1StreamHandlerFactory = new ClientHttp1StreamDuplexerFactory(
+ httpProcessor != null ? httpProcessor : HttpProcessors.client(),
+ h1Config != null ? h1Config : H1Config.DEFAULT,
+ charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
+ connectionListener,
+ http1StreamListener);
+ final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientHttp2StreamMultiplexerFactory(
httpProcessor != null ? httpProcessor : Http2Processors.client(),
pushConsumerRegistry,
- charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
h2Config != null ? h2Config : H2Config.DEFAULT,
+ charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
connectionListener,
streamListener);
+ final ClientHttpProtocolNegotiatorFactory ioEventHandlerFactory = new ClientHttpProtocolNegotiatorFactory(
+ http1StreamHandlerFactory,
+ http2StreamHandlerFactory,
+ versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
+ connectionListener);
try {
- return new HttpAsyncRequester(
+ return new Http2AsyncRequester(
+ versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
ioReactorConfig,
ioEventHandlerFactory,
connPool,
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
index 23d62a1..60eff6f 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/H2ServerBootstrap.java
@@ -32,21 +32,32 @@ import java.util.List;
import org.apache.hc.core5.function.Supplier;
import org.apache.hc.core5.http.ExceptionListener;
import org.apache.hc.core5.http.config.CharCodingConfig;
+import org.apache.hc.core5.http.config.H1Config;
import org.apache.hc.core5.http.impl.ConnectionListener;
+import org.apache.hc.core5.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.hc.core5.http.impl.DefaultContentLengthStrategy;
+import org.apache.hc.core5.http.impl.Http1StreamListener;
+import org.apache.hc.core5.http.impl.HttpProcessors;
import org.apache.hc.core5.http.impl.bootstrap.AsyncServerExchangeHandlerRegistry;
import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncServer;
+import org.apache.hc.core5.http.impl.nio.DefaultHttpRequestParserFactory;
+import org.apache.hc.core5.http.impl.nio.DefaultHttpResponseWriterFactory;
+import org.apache.hc.core5.http.impl.nio.ServerHttp1StreamDuplexerFactory;
import org.apache.hc.core5.http.nio.AsyncServerExchangeHandler;
import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
import org.apache.hc.core5.http.nio.support.BasicServerExchangeHandler;
import org.apache.hc.core5.http.nio.support.RequestConsumerSupplier;
import org.apache.hc.core5.http.nio.support.ResponseHandler;
import org.apache.hc.core5.http.protocol.HttpProcessor;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
import org.apache.hc.core5.http2.config.H2Config;
import org.apache.hc.core5.http2.impl.Http2Processors;
import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
+import org.apache.hc.core5.http2.impl.nio.ServerHttp2StreamMultiplexerFactory;
import org.apache.hc.core5.http2.impl.nio.ServerHttpProtocolNegotiatorFactory;
import org.apache.hc.core5.http2.ssl.H2ServerTlsStrategy;
import org.apache.hc.core5.net.InetAddressUtils;
+import org.apache.hc.core5.reactor.IOEventHandlerFactory;
import org.apache.hc.core5.reactor.IOReactorConfig;
import org.apache.hc.core5.reactor.IOReactorException;
import org.apache.hc.core5.util.Args;
@@ -61,11 +72,14 @@ public class H2ServerBootstrap {
private IOReactorConfig ioReactorConfig;
private HttpProcessor httpProcessor;
private CharCodingConfig charCodingConfig;
+ private HttpVersionPolicy versionPolicy;
private H2Config h2Config;
+ private H1Config h1Config;
private TlsStrategy tlsStrategy;
private ExceptionListener exceptionListener;
private ConnectionListener connectionListener;
- private Http2StreamListener streamListener;
+ private Http2StreamListener http2StreamListener;
+ private Http1StreamListener http1StreamListener;
private H2ServerBootstrap() {
this.handlerList = new ArrayList<>();
@@ -102,6 +116,14 @@ public class H2ServerBootstrap {
}
/**
+ * Sets HTTP protocol version policy
+ */
+ public final H2ServerBootstrap setVersionPolicy(final HttpVersionPolicy versionPolicy) {
+ this.versionPolicy = versionPolicy;
+ return this;
+ }
+
+ /**
* Sets HTTP/2 protocol parameters
*/
public final H2ServerBootstrap setH2Config(final H2Config h2Config) {
@@ -110,7 +132,15 @@ public class H2ServerBootstrap {
}
/**
- * Sets char coding for HTTP/2 messages.
+ * Sets HTTP/1.1 protocol parameters
+ */
+ public final H2ServerBootstrap setH1Config(final H1Config h1Config) {
+ this.h1Config = h1Config;
+ return this;
+ }
+
+ /**
+ * Sets message char coding.
*/
public final H2ServerBootstrap setCharset(final CharCodingConfig charCodingConfig) {
this.charCodingConfig = charCodingConfig;
@@ -144,8 +174,16 @@ public class H2ServerBootstrap {
/**
* Assigns {@link Http2StreamListener} instance.
*/
- public final H2ServerBootstrap setStreamListener(final Http2StreamListener streamListener) {
- this.streamListener = streamListener;
+ public final H2ServerBootstrap setStreamListener(final Http2StreamListener http2StreamListener) {
+ this.http2StreamListener = http2StreamListener;
+ return this;
+ }
+
+ /**
+ * Assigns {@link Http1StreamListener} instance.
+ */
+ public final H2ServerBootstrap setStreamListener(final Http1StreamListener http1StreamListener) {
+ this.http1StreamListener = http1StreamListener;
return this;
}
@@ -201,14 +239,31 @@ public class H2ServerBootstrap {
for (final HandlerEntry entry: handlerList) {
exchangeHandlerFactory.register(entry.hostname, entry.uriPattern, entry.supplier);
}
- final ServerHttpProtocolNegotiatorFactory ioEventHandlerFactory = new ServerHttpProtocolNegotiatorFactory(
+ final ServerHttp2StreamMultiplexerFactory http2StreamHandlerFactory = new ServerHttp2StreamMultiplexerFactory(
httpProcessor != null ? httpProcessor : Http2Processors.server(),
exchangeHandlerFactory,
- charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
h2Config != null ? h2Config : H2Config.DEFAULT,
- tlsStrategy != null ? tlsStrategy : new H2ServerTlsStrategy(new int[] {443, 8443}),
+ charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
connectionListener,
- streamListener);
+ http2StreamListener);
+ final ServerHttp1StreamDuplexerFactory http1StreamHandlerFactory = new ServerHttp1StreamDuplexerFactory(
+ httpProcessor != null ? httpProcessor : HttpProcessors.server(),
+ exchangeHandlerFactory,
+ h1Config != null ? h1Config : H1Config.DEFAULT,
+ charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
+ DefaultConnectionReuseStrategy.INSTANCE,
+ DefaultHttpRequestParserFactory.INSTANCE,
+ DefaultHttpResponseWriterFactory.INSTANCE,
+ DefaultContentLengthStrategy.INSTANCE,
+ DefaultContentLengthStrategy.INSTANCE,
+ connectionListener,
+ http1StreamListener);
+ final IOEventHandlerFactory ioEventHandlerFactory = new ServerHttpProtocolNegotiatorFactory(
+ http1StreamHandlerFactory,
+ http2StreamHandlerFactory,
+ versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE,
+ tlsStrategy != null ? tlsStrategy : new H2ServerTlsStrategy(new int[] {443, 8443}),
+ connectionListener);
try {
return new HttpAsyncServer(
ioEventHandlerFactory,
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2AsyncRequester.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2AsyncRequester.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2AsyncRequester.java
new file mode 100644
index 0000000..5594fea
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/impl/nio/bootstrap/Http2AsyncRequester.java
@@ -0,0 +1,73 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.impl.nio.bootstrap;
+
+import java.util.concurrent.Future;
+
+import org.apache.hc.core5.concurrent.FutureCallback;
+import org.apache.hc.core5.http.ExceptionListener;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.impl.bootstrap.HttpAsyncRequester;
+import org.apache.hc.core5.http.nio.AsyncClientEndpoint;
+import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
+import org.apache.hc.core5.http2.HttpVersionPolicy;
+import org.apache.hc.core5.pool.ControlledConnPool;
+import org.apache.hc.core5.reactor.IOEventHandlerFactory;
+import org.apache.hc.core5.reactor.IOReactorConfig;
+import org.apache.hc.core5.reactor.IOReactorException;
+import org.apache.hc.core5.reactor.IOSession;
+import org.apache.hc.core5.util.TimeValue;
+
+/**
+ * @since 5.0
+ */
+public class Http2AsyncRequester extends HttpAsyncRequester {
+
+ private final HttpVersionPolicy versionPolicy;
+
+ public Http2AsyncRequester(
+ final HttpVersionPolicy versionPolicy,
+ final IOReactorConfig ioReactorConfig,
+ final IOEventHandlerFactory eventHandlerFactory,
+ final ControlledConnPool<HttpHost, IOSession> connPool,
+ final TlsStrategy tlsStrategy,
+ final ExceptionListener exceptionListener) throws IOReactorException {
+ super(ioReactorConfig, eventHandlerFactory, connPool, tlsStrategy, exceptionListener);
+ this.versionPolicy = versionPolicy != null ? versionPolicy : HttpVersionPolicy.NEGOTIATE;
+ }
+
+ @Override
+ protected Future<AsyncClientEndpoint> doConnect(
+ final HttpHost host,
+ final TimeValue timeout,
+ final Object attachment,
+ final FutureCallback<AsyncClientEndpoint> callback) {
+ return super.doConnect(host, timeout, attachment != null ? attachment : versionPolicy, callback);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/ApplicationProtocols.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/ApplicationProtocols.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/ApplicationProtocols.java
new file mode 100644
index 0000000..29f90c9
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/ApplicationProtocols.java
@@ -0,0 +1,50 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.ssl;
+
+/**
+ * Supported application protocols.
+ *
+ * @since 5.0
+ */
+public enum ApplicationProtocols {
+
+ HTTP_2("h2"), HTTP_1_1("http/1.1");
+
+ public final String id;
+
+ ApplicationProtocols(final String id) {
+ this.id = id;
+ }
+
+ @Override
+ public String toString() {
+ return id;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/FixedPortStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/FixedPortStrategy.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/FixedPortStrategy.java
new file mode 100644
index 0000000..35ebe2b
--- /dev/null
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/FixedPortStrategy.java
@@ -0,0 +1,56 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.hc.core5.http2.ssl;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import org.apache.hc.core5.util.Args;
+
+/**
+ * @since 5.0
+ */
+public final class FixedPortStrategy implements SecurePortStrategy {
+
+ private final int[] securePorts;
+
+ public FixedPortStrategy(final int[] securePorts) {
+ this.securePorts = Args.notNull(securePorts, "Secure ports");
+ }
+
+ public boolean isSecure(final SocketAddress localAddress) {
+ final int port = ((InetSocketAddress) localAddress).getPort();
+ for (final int securePort: securePorts) {
+ if (port == securePort) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ClientTlsStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ClientTlsStrategy.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ClientTlsStrategy.java
index b517459..4d3e24b 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ClientTlsStrategy.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ClientTlsStrategy.java
@@ -91,11 +91,11 @@ public class H2ClientTlsStrategy implements TlsStrategy {
final HttpHost host,
final SocketAddress localAddress,
final SocketAddress remoteAddress,
- final String... parameters) {
+ final Object attachment) {
final String scheme = host != null ? host.getSchemeName() : null;
if ("https".equalsIgnoreCase(scheme)) {
tlsSession.startTls(sslContext, sslBufferManagement,
- H2TlsSupport.enforceRequirements(initializer),
+ H2TlsSupport.enforceRequirements(attachment, initializer),
verifier);
}
}
http://git-wip-us.apache.org/repos/asf/httpcomponents-core/blob/ed4b808c/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ServerTlsStrategy.java
----------------------------------------------------------------------
diff --git a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ServerTlsStrategy.java b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ServerTlsStrategy.java
index f449767..2cceb77 100644
--- a/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ServerTlsStrategy.java
+++ b/httpcore5-h2/src/main/java/org/apache/hc/core5/http2/ssl/H2ServerTlsStrategy.java
@@ -27,7 +27,6 @@
package org.apache.hc.core5.http2.ssl;
-import java.net.InetSocketAddress;
import java.net.SocketAddress;
import javax.net.ssl.SSLContext;
@@ -49,46 +48,46 @@ import org.apache.hc.core5.util.Args;
*/
public class H2ServerTlsStrategy implements TlsStrategy {
- private final int[] securePorts;
private final SSLContext sslContext;
+ private final SecurePortStrategy securePortStrategy;
private final SSLBufferManagement sslBufferManagement;
private final SSLSessionInitializer initializer;
private final SSLSessionVerifier verifier;
public H2ServerTlsStrategy(
- final int[] securePorts,
final SSLContext sslContext,
+ final SecurePortStrategy securePortStrategy,
final SSLBufferManagement sslBufferManagement,
final SSLSessionInitializer initializer,
final SSLSessionVerifier verifier) {
- this.securePorts = Args.notNull(securePorts, "Array of ports");
this.sslContext = Args.notNull(sslContext, "SSL context");
+ this.securePortStrategy = securePortStrategy;
this.sslBufferManagement = sslBufferManagement;
this.initializer = initializer;
this.verifier = verifier;
}
public H2ServerTlsStrategy(
- final int[] securePorts,
final SSLContext sslContext,
+ final SecurePortStrategy securePortStrategy,
final SSLSessionInitializer initializer,
final SSLSessionVerifier verifier) {
- this(securePorts, sslContext, null, initializer, verifier);
+ this(sslContext, securePortStrategy, null, initializer, verifier);
}
public H2ServerTlsStrategy(
- final int[] securePorts,
final SSLContext sslContext,
+ final SecurePortStrategy securePortStrategy,
final SSLSessionVerifier verifier) {
- this(securePorts, sslContext, null, null, verifier);
+ this(sslContext, securePortStrategy, null, null, verifier);
}
- public H2ServerTlsStrategy(final int[] securePorts, final SSLContext sslContext) {
- this(securePorts, sslContext, null, null, null);
+ public H2ServerTlsStrategy(final SSLContext sslContext, final SecurePortStrategy securePortStrategy) {
+ this(sslContext, securePortStrategy, null, null, null);
}
public H2ServerTlsStrategy(final int[] securePorts) {
- this(securePorts, SSLContexts.createSystemDefault());
+ this(SSLContexts.createSystemDefault(), new FixedPortStrategy(securePorts));
}
@Override
@@ -97,15 +96,11 @@ public class H2ServerTlsStrategy implements TlsStrategy {
final HttpHost host,
final SocketAddress localAddress,
final SocketAddress remoteAddress,
- final String... parameters) {
- final int port = ((InetSocketAddress) localAddress).getPort();
- for (final int securePort: securePorts) {
- if (port == securePort) {
- tlsSession.startTls(sslContext, sslBufferManagement,
- H2TlsSupport.enforceRequirements(initializer),
- verifier);
- break;
- }
+ final Object attachment) {
+ if (securePortStrategy != null && securePortStrategy.isSecure(localAddress)) {
+ tlsSession.startTls(sslContext, sslBufferManagement,
+ H2TlsSupport.enforceRequirements(attachment, initializer),
+ verifier);
}
}