You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2016/05/03 18:32:26 UTC

svn commit: r1742141 - in /tomcat/tc8.5.x/trunk: ./ java/org/apache/coyote/ java/org/apache/coyote/ajp/ java/org/apache/coyote/http11/ java/org/apache/coyote/http11/upgrade/ java/org/apache/coyote/http2/ webapps/docs/

Author: remm
Date: Tue May  3 16:32:26 2016
New Revision: 1742141

URL: http://svn.apache.org/viewvc?rev=1742141&view=rev
Log:
59421: Allow direct (plain text most likely) connection to HTTP/2.

Modified:
    tomcat/tc8.5.x/trunk/   (props changed)
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/AbstractProtocol.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java
    tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Http2Protocol.java
    tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc8.5.x/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue May  3 16:32:26 2016
@@ -1 +1 @@
-/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501,1741677
 ,1741892,1741896,1742090
+/tomcat/trunk:1734785,1734799,1734845,1734928,1735041,1735044,1735480,1735577,1735597,1735599-1735600,1735615,1736145,1736162,1736209,1736280,1736297,1736299,1736489,1736646,1736703,1736836,1736849,1737104-1737105,1737112,1737117,1737119-1737120,1737155,1737157,1737192,1737280,1737339,1737632,1737664,1737715,1737748,1737785,1737834,1737860,1737959,1738005,1738007,1738014-1738015,1738018,1738022,1738039,1738043,1738059-1738060,1738147,1738149,1738174-1738175,1738261,1738589,1738623-1738625,1738643,1738816,1738850,1738855,1738946-1738948,1738953-1738954,1738979,1738982,1739079-1739081,1739087,1739113,1739153,1739172,1739176,1739191,1739474,1739726,1739762,1739775,1739814,1739817-1739818,1739975,1740131,1740324,1740465,1740495,1740508-1740509,1740520,1740535,1740707,1740803,1740810,1740969,1740980,1740991,1740997,1741015,1741033,1741036,1741058,1741060,1741080,1741147,1741159,1741164,1741173,1741181,1741190,1741197,1741202,1741208,1741213,1741221,1741225,1741232,1741409,1741501,1741677
 ,1741892,1741896,1741984,1742023,1742042,1742090,1742139

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/AbstractProtocol.java Tue May  3 16:32:26 2016
@@ -424,6 +424,16 @@ public abstract class AbstractProtocol<S
 
 
     /**
+     * Find a suitable handler for the protocol upgraded name specified. This
+     * is used for direct connection protocol selection.
+     * @param name The name of the requested negotiated protocol.
+     * @return The instance where {@link UpgradeProtocol#getAlpnName()} matches
+     *         the requested protocol
+     */
+    protected abstract UpgradeProtocol getUpgradeProtocol(String name);
+
+
+    /**
      * Create and configure a new Processor instance for the current protocol
      * implementation.
      *
@@ -433,7 +443,7 @@ public abstract class AbstractProtocol<S
 
 
     protected abstract Processor createUpgradeProcessor(
-            SocketWrapperBase<?> socket, ByteBuffer leftoverInput,
+            SocketWrapperBase<?> socket,
             UpgradeToken upgradeToken);
 
 
@@ -780,32 +790,51 @@ public abstract class AbstractProtocol<S
                     if (state == SocketState.UPGRADING) {
                         // Get the HTTP upgrade handler
                         UpgradeToken upgradeToken = processor.getUpgradeToken();
-                        HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler();
                         // Retrieve leftover input
-                        ByteBuffer leftoverInput = processor.getLeftoverInput();
-                        // Release the Http11 processor to be re-used
-                        release(processor);
-                        // Create the upgrade processor
-                        processor = getProtocol().createUpgradeProcessor(
-                                wrapper, leftoverInput, upgradeToken);
-                        // Mark the connection as upgraded
-                        wrapper.setUpgraded(true);
-                        // Associate with the processor with the connection
-                        connections.put(socket, processor);
-                        // Initialise the upgrade handler (which may trigger
-                        // some IO using the new protocol which is why the lines
-                        // above are necessary)
-                        // This cast should be safe. If it fails the error
-                        // handling for the surrounding try/catch will deal with
-                        // it.
-                        if (upgradeToken.getInstanceManager() == null) {
-                            httpUpgradeHandler.init((WebConnection) processor);
+                        ByteBuffer leftOverInput = processor.getLeftoverInput();
+                        if (upgradeToken == null) {
+                            // Assume direct HTTP/2 connection
+                            UpgradeProtocol upgradeProtocol = getProtocol().getUpgradeProtocol("h2c");
+                            if (upgradeProtocol != null) {
+                                processor = upgradeProtocol.getProcessor(
+                                        wrapper, getProtocol().getAdapter());
+                                wrapper.unRead(leftOverInput);
+                                // Associate with the processor with the connection
+                                connections.put(socket, processor);
+                            } else {
+                                if (getLog().isDebugEnabled()) {
+                                    getLog().debug(sm.getString(
+                                        "abstractConnectionHandler.negotiatedProcessor.fail",
+                                        "h2c"));
+                                }
+                                return SocketState.CLOSED;
+                            }
                         } else {
-                            ClassLoader oldCL = upgradeToken.getContextBind().bind(false, null);
-                            try {
+                            HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler();
+                            // Release the Http11 processor to be re-used
+                            release(processor);
+                            // Create the upgrade processor
+                            processor = getProtocol().createUpgradeProcessor(wrapper, upgradeToken);
+                            wrapper.unRead(leftOverInput);
+                            // Mark the connection as upgraded
+                            wrapper.setUpgraded(true);
+                            // Associate with the processor with the connection
+                            connections.put(socket, processor);
+                            // Initialise the upgrade handler (which may trigger
+                            // some IO using the new protocol which is why the lines
+                            // above are necessary)
+                            // This cast should be safe. If it fails the error
+                            // handling for the surrounding try/catch will deal with
+                            // it.
+                            if (upgradeToken.getInstanceManager() == null) {
                                 httpUpgradeHandler.init((WebConnection) processor);
-                            } finally {
-                                upgradeToken.getContextBind().unbind(false, oldCL);
+                            } else {
+                                ClassLoader oldCL = upgradeToken.getContextBind().bind(false, null);
+                                try {
+                                    httpUpgradeHandler.init((WebConnection) processor);
+                                } finally {
+                                    upgradeToken.getContextBind().unbind(false, oldCL);
+                                }
                             }
                         }
                     }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Tue May  3 16:32:26 2016
@@ -16,8 +16,6 @@
  */
 package org.apache.coyote.ajp;
 
-import java.nio.ByteBuffer;
-
 import org.apache.coyote.AbstractProtocol;
 import org.apache.coyote.Processor;
 import org.apache.coyote.UpgradeProtocol;
@@ -82,6 +80,16 @@ public abstract class AbstractAjpProtoco
     }
 
 
+    /**
+     * {@inheritDoc}
+     *
+     * AJP does not support protocol upgrade so this always returns null.
+     */
+    @Override
+    protected UpgradeProtocol getUpgradeProtocol(String name) {
+        return null;
+    }
+
     // ------------------------------------------------- AJP specific properties
     // ------------------------------------------ managed in the ProtocolHandler
 
@@ -190,7 +198,7 @@ public abstract class AbstractAjpProtoco
 
     @Override
     protected Processor createUpgradeProcessor(SocketWrapperBase<?> socket,
-            ByteBuffer leftoverInput, UpgradeToken upgradeToken) {
+            UpgradeToken upgradeToken) {
         throw new IllegalStateException(sm.getString("ajpprotocol.noUpgradeHandler",
                 upgradeToken.getHttpUpgradeHandler().getClass().getName()));
     }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Tue May  3 16:32:26 2016
@@ -16,7 +16,6 @@
  */
 package org.apache.coyote.http11;
 
-import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -351,6 +350,10 @@ public abstract class AbstractHttp11Prot
     public UpgradeProtocol getNegotiatedProtocol(String negotiatedName) {
         return negotiatedProtocols.get(negotiatedName);
     }
+    @Override
+    public UpgradeProtocol getUpgradeProtocol(String upgradedName) {
+        return httpUpgradeProtocols.get(upgradedName);
+    }
 
 
     // ------------------------------------------------ HTTP specific properties
@@ -643,13 +646,13 @@ public abstract class AbstractHttp11Prot
 
     @Override
     protected Processor createUpgradeProcessor(
-            SocketWrapperBase<?> socket, ByteBuffer leftoverInput,
+            SocketWrapperBase<?> socket,
             UpgradeToken upgradeToken) {
         HttpUpgradeHandler httpUpgradeHandler = upgradeToken.getHttpUpgradeHandler();
         if (httpUpgradeHandler instanceof InternalHttpUpgradeHandler) {
-            return new UpgradeProcessorInternal(socket, leftoverInput, upgradeToken);
+            return new UpgradeProcessorInternal(socket, upgradeToken);
         } else {
-            return new UpgradeProcessorExternal(socket, leftoverInput, upgradeToken);
+            return new UpgradeProcessorExternal(socket, upgradeToken);
         }
     }
 }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java Tue May  3 16:32:26 2016
@@ -97,6 +97,9 @@ public class Http11InputBuffer implement
     }
 
 
+    private static final byte[] CLIENT_PREFACE_START =
+            "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1);
+
     /**
      * Associated Coyote request.
      */
@@ -407,6 +410,19 @@ public class Http11InputBuffer implement
                     // Switch to the socket timeout.
                     wrapper.setReadTimeout(wrapper.getEndpoint().getSoTimeout());
                 }
+                if (!keptAlive && pos == 0 && lastValid >= CLIENT_PREFACE_START.length - 1) {
+                    boolean prefaceMatch = true;
+                    for (int i = 0; i < CLIENT_PREFACE_START.length; i++) {
+                        if (CLIENT_PREFACE_START[i] != buf[i]) {
+                            prefaceMatch = false;
+                        }
+                    }
+                    if (prefaceMatch) {
+                        // HTTP/2 preface matched
+                        parsingRequestLinePhase = -1;
+                        return false;
+                    }
+                }
                 // Set the start time once we start reading data (even if it is
                 // just skipping blank lines)
                 if (request.getStartTime() < 0) {

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/Http11Processor.java Tue May  3 16:32:26 2016
@@ -984,7 +984,9 @@ public class Http11Processor extends Abs
             // Parsing the request header
             try {
                 if (!inputBuffer.parseRequestLine(keptAlive)) {
-                    if (handleIncompleteRequestLineRead()) {
+                    if (inputBuffer.getParsingRequestLinePhase() == -1) {
+                        return SocketState.UPGRADING;
+                    } else if (handleIncompleteRequestLineRead()) {
                         break;
                     }
                 }

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java Tue May  3 16:32:26 2016
@@ -33,10 +33,8 @@ public abstract class UpgradeProcessorBa
 
     private final UpgradeToken upgradeToken;
 
-    public UpgradeProcessorBase(SocketWrapperBase<?> wrapper, ByteBuffer leftOverInput,
-            UpgradeToken upgradeToken) {
+    public UpgradeProcessorBase(UpgradeToken upgradeToken) {
         this.upgradeToken = upgradeToken;
-        wrapper.unRead(leftOverInput);
     }
 
 

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java Tue May  3 16:32:26 2016
@@ -17,7 +17,6 @@
 package org.apache.coyote.http11.upgrade;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 
 import javax.servlet.ServletInputStream;
 import javax.servlet.ServletOutputStream;
@@ -40,13 +39,12 @@ public class UpgradeProcessorExternal ex
     private final UpgradeServletOutputStream upgradeServletOutputStream;
 
 
-    public UpgradeProcessorExternal(SocketWrapperBase<?> wrapper, ByteBuffer leftOverInput,
+    public UpgradeProcessorExternal(SocketWrapperBase<?> wrapper,
             UpgradeToken upgradeToken) {
-        super(wrapper, leftOverInput, upgradeToken);
+        super(upgradeToken);
         this.upgradeServletInputStream = new UpgradeServletInputStream(this, wrapper);
         this.upgradeServletOutputStream = new UpgradeServletOutputStream(this, wrapper);
 
-        wrapper.unRead(leftOverInput);
         /*
          * Leave timeouts in the hands of the upgraded protocol.
          */

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java Tue May  3 16:32:26 2016
@@ -17,7 +17,6 @@
 package org.apache.coyote.http11.upgrade;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 
 import javax.servlet.ServletInputStream;
 import javax.servlet.ServletOutputStream;
@@ -36,9 +35,9 @@ public class UpgradeProcessorInternal ex
 
     private final InternalHttpUpgradeHandler internalHttpUpgradeHandler;
 
-    public UpgradeProcessorInternal(SocketWrapperBase<?> wrapper, ByteBuffer leftOverInput,
+    public UpgradeProcessorInternal(SocketWrapperBase<?> wrapper,
             UpgradeToken upgradeToken) {
-        super(wrapper, leftOverInput, upgradeToken);
+        super(upgradeToken);
         this.internalHttpUpgradeHandler = (InternalHttpUpgradeHandler) upgradeToken.getHttpUpgradeHandler();
         /*
          * Leave timeouts in the hands of the upgraded protocol.

Modified: tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Http2Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Http2Protocol.java?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Http2Protocol.java (original)
+++ tomcat/tc8.5.x/trunk/java/org/apache/coyote/http2/Http2Protocol.java Tue May  3 16:32:26 2016
@@ -72,7 +72,7 @@ public class Http2Protocol implements Up
 
     @Override
     public Processor getProcessor(SocketWrapperBase<?> socketWrapper, Adapter adapter) {
-        UpgradeProcessorInternal processor = new UpgradeProcessorInternal(socketWrapper, null,
+        UpgradeProcessorInternal processor = new UpgradeProcessorInternal(socketWrapper,
                 new UpgradeToken(getInternalUpgradeHandler(adapter, null), null, null));
         return processor;
     }

Modified: tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml?rev=1742141&r1=1742140&r2=1742141&view=diff
==============================================================================
--- tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc8.5.x/trunk/webapps/docs/changelog.xml Tue May  3 16:32:26 2016
@@ -212,6 +212,9 @@
         known issue in OpenSSL</a> that does not permit the TLS handshake to be
         failed if the ALPN negotiation fails. (markt)
       </fix>
+      <update>
+        <bug>59421</bug>: Add direct HTTP/2 connection support. (remm)
+      </update>
     </changelog>
   </subsection>
   <subsection name="WebSocket">



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org