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/02 16:46:30 UTC
svn commit: r1741984 - in /tomcat/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: Mon May 2 14:46:29 2016
New Revision: 1741984
URL: http://svn.apache.org/viewvc?rev=1741984&view=rev
Log:
59421: Allow direct (plain text most likely) connection to HTTP/2. The performance cost of the preface matching at this stage should be minimal.
Probably not polished enough, so no 8.5 port for now.
Modified:
tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java
tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java
tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java
tomcat/trunk/java/org/apache/coyote/http2/Http2Protocol.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Mon May 2 14:46:29 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,44 @@ 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 {
- 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/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/ajp/AbstractAjpProtocol.java Mon May 2 14:46:29 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/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Mon May 2 14:46:29 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/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11InputBuffer.java Mon May 2 14:46:29 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,25 @@ public class Http11InputBuffer implement
// Switch to the socket timeout.
wrapper.setReadTimeout(wrapper.getEndpoint().getSoTimeout());
}
+ if (!keptAlive) {
+ for (int i = 0; i < CLIENT_PREFACE_START.length; i++) {
+ if (i == lastValid) {
+ // Need more data to know if this is HTTP/2
+ if (!fill(false)) {
+ // A read is pending, so no longer in initial state
+ parsingRequestLinePhase = 1;
+ return false;
+ }
+ }
+ if (CLIENT_PREFACE_START[i] != buf[i]) {
+ break;
+ } else if (i == CLIENT_PREFACE_START.length - 1) {
+ // 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/trunk/java/org/apache/coyote/http11/Http11Processor.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/Http11Processor.java Mon May 2 14:46:29 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/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorBase.java Mon May 2 14:46:29 2016
@@ -33,10 +33,9 @@ public abstract class UpgradeProcessorBa
private final UpgradeToken upgradeToken;
- public UpgradeProcessorBase(SocketWrapperBase<?> wrapper, ByteBuffer leftOverInput,
+ public UpgradeProcessorBase(SocketWrapperBase<?> wrapper,
UpgradeToken upgradeToken) {
this.upgradeToken = upgradeToken;
- wrapper.unRead(leftOverInput);
}
Modified: tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorExternal.java Mon May 2 14:46:29 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(wrapper, 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/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http11/upgrade/UpgradeProcessorInternal.java Mon May 2 14:46:29 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(wrapper, upgradeToken);
this.internalHttpUpgradeHandler = (InternalHttpUpgradeHandler) upgradeToken.getHttpUpgradeHandler();
/*
* Leave timeouts in the hands of the upgraded protocol.
Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2Protocol.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2Protocol.java?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2Protocol.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2Protocol.java Mon May 2 14:46:29 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/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1741984&r1=1741983&r2=1741984&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon May 2 14:46:29 2016
@@ -219,6 +219,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
Re: svn commit: r1741984 - in /tomcat/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/
Posted by jean-frederic clere <jf...@gmail.com>.
Cool now the following h2 proxy configuration of httpd (trunk) works:
+++
<VirtualHost *:8006>
Protocols h2 http/1.1
ProtocolsHonorOrder on
SSLEngine on
....
ProxyPass "/" "h2c://localhost:8003/"
</VirtualHost>
+++
and h2load http://localhost:8003/ works too.
On 8003 I have the tomcat running configured as:
+++
<Connector
port="8003"
protocol="org.apache.coyote.http11.Http11AprProtocol">
<UpgradeProtocol
className="org.apache.coyote.http2.Http2Protocol" />
</Connector>
+++
thanks
Jean-Frederic
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
Re: svn commit: r1741984 - in /tomcat/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/
Posted by Rémy Maucherat <re...@apache.org>.
2016-05-02 16:46 GMT+02:00 <re...@apache.org>:
> Author: remm
> Date: Mon May 2 14:46:29 2016
> New Revision: 1741984
>
> URL: http://svn.apache.org/viewvc?rev=1741984&view=rev
> Log:
> 59421: Allow direct (plain text most likely) connection to HTTP/2. The
> performance cost of the preface matching at this stage should be minimal.
> Probably not polished enough, so no 8.5 port for now.
>
> I also refactored leftover bytes handling, since passing that parameter
around no longer made sense as it all ended up with an optional
wrapper.unRead(leftOverInput).
Rémy