hc-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ol...@apache.org
Subject httpcomponents-client git commit: Fixed ALPN handshake failure in HTTP/2 integration tests
Date Tue, 14 Nov 2017 18:30:22 GMT
Repository: httpcomponents-client
Updated Branches:
  refs/heads/master 6228a7361 -> e3cd57a57


Fixed ALPN handshake failure in HTTP/2 integration tests


Project: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/repo
Commit: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/commit/e3cd57a5
Tree: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/tree/e3cd57a5
Diff: http://git-wip-us.apache.org/repos/asf/httpcomponents-client/diff/e3cd57a5

Branch: refs/heads/master
Commit: e3cd57a5701b88e54c25a24e4e170cb405da9ee1
Parents: 6228a73
Author: Oleg Kalnichevski <olegk@apache.org>
Authored: Tue Nov 14 19:26:05 2017 +0100
Committer: Oleg Kalnichevski <olegk@apache.org>
Committed: Tue Nov 14 19:27:25 2017 +0100

----------------------------------------------------------------------
 .../client5/testing/async/TestHttp2Async.java   |   4 +-
 .../Http2AsyncClientEventHandlerFactory.java    |   5 +-
 .../InternalHttp2ClientProtocolNegotiator.java  | 230 +++++++++++++++++++
 3 files changed, 234 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/e3cd57a5/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp2Async.java
----------------------------------------------------------------------
diff --git a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp2Async.java
b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp2Async.java
index b0035e9..e64cbdd 100644
--- a/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp2Async.java
+++ b/httpclient5-testing/src/test/java/org/apache/hc/client5/testing/async/TestHttp2Async.java
@@ -32,10 +32,10 @@ import java.util.Collection;
 import org.apache.hc.client5.http.config.RequestConfig;
 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
 import org.apache.hc.client5.http.impl.async.Http2AsyncClientBuilder;
-import org.apache.hc.client5.http.ssl.H2TlsStrategy;
 import org.apache.hc.client5.testing.SSLTestContexts;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.URIScheme;
+import org.apache.hc.core5.http.nio.ssl.BasicClientTlsStrategy;
 import org.apache.hc.core5.http2.config.H2Config;
 import org.junit.Rule;
 import org.junit.rules.ExternalResource;
@@ -66,7 +66,7 @@ public class TestHttp2Async extends AbstractHttpAsyncFundamentalsTest<CloseableH
                             .setConnectTimeout(TIMEOUT)
                             .setConnectionRequestTimeout(TIMEOUT)
                             .build())
-                    .setTlsStrategy(new H2TlsStrategy(SSLTestContexts.createClientSSLContext()));
+                    .setTlsStrategy(new BasicClientTlsStrategy(SSLTestContexts.createClientSSLContext()));
         }
 
     };

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/e3cd57a5/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/Http2AsyncClientEventHandlerFactory.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/Http2AsyncClientEventHandlerFactory.java
b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/Http2AsyncClientEventHandlerFactory.java
index 52f399c..564a561 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/Http2AsyncClientEventHandlerFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/Http2AsyncClientEventHandlerFactory.java
@@ -43,7 +43,6 @@ import org.apache.hc.core5.http2.config.H2Config;
 import org.apache.hc.core5.http2.frame.FramePrinter;
 import org.apache.hc.core5.http2.frame.RawFrame;
 import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexerFactory;
-import org.apache.hc.core5.http2.impl.nio.Http2OnlyClientProtocolNegotiator;
 import org.apache.hc.core5.http2.impl.nio.Http2StreamListener;
 import org.apache.hc.core5.reactor.IOEventHandler;
 import org.apache.hc.core5.reactor.IOEventHandlerFactory;
@@ -179,7 +178,7 @@ class Http2AsyncClientEventHandlerFactory implements IOEventHandlerFactory
{
 
                     });
             final LoggingIOSession loggingIOSession = new LoggingIOSession(ioSession, id,
sessionLog, wireLog);
-            return new Http2OnlyClientProtocolNegotiator(loggingIOSession, http2StreamHandlerFactory);
+            return new InternalHttp2ClientProtocolNegotiator(loggingIOSession, http2StreamHandlerFactory);
         } else {
             final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientHttp2StreamMultiplexerFactory(
                     httpProcessor,
@@ -187,7 +186,7 @@ class Http2AsyncClientEventHandlerFactory implements IOEventHandlerFactory
{
                     h2Config,
                     charCodingConfig,
                     null);
-            return new Http2OnlyClientProtocolNegotiator(ioSession, http2StreamHandlerFactory);
+            return new InternalHttp2ClientProtocolNegotiator(ioSession, http2StreamHandlerFactory);
         }
    }
 

http://git-wip-us.apache.org/repos/asf/httpcomponents-client/blob/e3cd57a5/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttp2ClientProtocolNegotiator.java
----------------------------------------------------------------------
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttp2ClientProtocolNegotiator.java
b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttp2ClientProtocolNegotiator.java
new file mode 100644
index 0000000..b7f6b2e
--- /dev/null
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/impl/async/InternalHttp2ClientProtocolNegotiator.java
@@ -0,0 +1,230 @@
+/*
+ * ====================================================================
+ * 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.client5.http.impl.async;
+
+import java.io.IOException;
+import java.net.SocketAddress;
+import java.net.SocketTimeoutException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+
+import javax.net.ssl.SSLSession;
+
+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.impl.nio.HttpConnectionEventHandler;
+import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
+import org.apache.hc.core5.http.nio.command.ExecutionCommand;
+import org.apache.hc.core5.http2.impl.nio.ClientHttp2IOEventHandler;
+import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexer;
+import org.apache.hc.core5.http2.impl.nio.ClientHttp2StreamMultiplexerFactory;
+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.TextUtils;
+
+/**
+ * TODO: replace with Http2OnlyClientProtocolNegotiator after HttpCore 5.0b2
+ */
+final class InternalHttp2ClientProtocolNegotiator implements HttpConnectionEventHandler {
+
+    // PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n
+    final static byte[] PREFACE = new byte[] {
+            0x50, 0x52, 0x49, 0x20, 0x2a, 0x20, 0x48, 0x54, 0x54, 0x50,
+            0x2f, 0x32, 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d,
+            0x0d, 0x0a, 0x0d, 0x0a};
+
+    private final TlsCapableIOSession ioSession;
+    private final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory;
+
+    private final ByteBuffer preface;
+
+    public InternalHttp2ClientProtocolNegotiator(
+            final TlsCapableIOSession ioSession,
+            final ClientHttp2StreamMultiplexerFactory http2StreamHandlerFactory) {
+        this.ioSession = ioSession;
+        this.http2StreamHandlerFactory = http2StreamHandlerFactory;
+        this.preface = ByteBuffer.wrap(PREFACE);
+    }
+
+    @Override
+    public void connected(final IOSession session) {
+        try {
+            final TlsDetails tlsDetails = ioSession.getTlsDetails();
+            if (tlsDetails != null) {
+                final String applicationProtocol = tlsDetails.getApplicationProtocol();
+                if (!TextUtils.isEmpty(applicationProtocol)) {
+                    if (!ApplicationProtocols.HTTP_2.id.equals(applicationProtocol)) {
+                        throw new HttpException("Unexpected application protocol: " + applicationProtocol);
+                    }
+                }
+            }
+            writePreface(session);
+        } catch (final Exception ex) {
+            session.shutdown(ShutdownType.IMMEDIATE);
+            exception(session, ex);
+        }
+    }
+
+    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) {
+        try {
+            if (preface != null) {
+                writePreface(session);
+            } else {
+                session.shutdown(ShutdownType.IMMEDIATE);
+            }
+        } catch (final IOException ex) {
+            session.shutdown(ShutdownType.IMMEDIATE);
+            exception(session, ex);
+        }
+    }
+
+    @Override
+    public void timeout(final IOSession session) {
+        exception(session, new SocketTimeoutException());
+    }
+
+    @Override
+    public void exception(final IOSession session, final Exception cause) {
+        try {
+            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);
+        }
+    }
+
+    @Override
+    public void disconnected(final IOSession session) {
+        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() {
+        final TlsDetails tlsDetails = ioSession.getTlsDetails();
+        return tlsDetails != null ? tlsDetails.getSSLSession() : null;
+    }
+
+    @Override
+    public EndpointDetails getEndpointDetails() {
+        return null;
+    }
+
+    @Override
+    public void setSocketTimeout(final int timeout) {
+        ioSession.setSocketTimeout(timeout);
+    }
+
+    @Override
+    public int getSocketTimeout() {
+        return ioSession.getSocketTimeout();
+    }
+
+    @Override
+    public ProtocolVersion getProtocolVersion() {
+        return null;
+    }
+
+    @Override
+    public SocketAddress getRemoteAddress() {
+        return ioSession.getRemoteAddress();
+    }
+
+    @Override
+    public SocketAddress getLocalAddress() {
+        return ioSession.getLocalAddress();
+    }
+
+    @Override
+    public boolean isOpen() {
+        return !ioSession.isClosed();
+    }
+
+    @Override
+    public void close() throws IOException {
+        ioSession.close();
+    }
+
+    @Override
+    public void shutdown(final ShutdownType shutdownType) {
+        ioSession.shutdown(shutdownType);
+    }
+
+}


Mime
View raw message