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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org