Author: markt Date: Tue May 12 20:16:58 2015 New Revision: 1679047 URL: http://svn.apache.org/r1679047 Log: Refactor connection preface handling into a separate class.
Added: tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java (with props) Modified: tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties 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=1679047&r1=1679046&r2=1679047&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java (original) +++ tomcat/trunk/java/org/apache/coyote/http11/AbstractHttp11Protocol.java Tue May 12 20:16:58 2015 @@ -37,6 +37,7 @@ import org.apache.coyote.UpgradeProtocol import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler; import org.apache.coyote.http11.upgrade.UpgradeProcessorExternal; import org.apache.coyote.http11.upgrade.UpgradeProcessorInternal; +import org.apache.coyote.http2.Http2Protocol; import org.apache.tomcat.util.net.AbstractEndpoint; import org.apache.tomcat.util.net.SSLHostConfig; import org.apache.tomcat.util.net.SocketWrapperBase; @@ -52,7 +53,7 @@ public abstract class AbstractHttp11Prot // This is disabled by default otherwise it will break the // APR/native connector with clients that support h2 with ALPN // (because the Http2Protocol is only stubbed out) - //addUpgradeProtocol(new Http2Protocol()); + addUpgradeProtocol(new Http2Protocol()); } Added: tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java?rev=1679047&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java (added) +++ tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java Tue May 12 20:16:58 2015 @@ -0,0 +1,77 @@ +/* + * 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. + */ +package org.apache.coyote.http2; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.net.SocketWrapperBase; +import org.apache.tomcat.util.res.StringManager; + +/** + * Parser for the initial part of the client connection preface received by the + * server. + */ +public class ConnectionPrefaceParser { + + private static final Log log = LogFactory.getLog(ConnectionPrefaceParser.class); + private static final StringManager sm = StringManager.getManager(ConnectionPrefaceParser.class); + + private static final byte[] EXPECTED = + "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1); + + private volatile byte[] data = new byte[EXPECTED.length]; + private volatile int pos = 0; + private volatile boolean error = false; + + + public boolean parse(SocketWrapperBase<?> socketWrapper) { + int read = 0; + try { + read = socketWrapper.read(false, data, pos, EXPECTED.length - pos); + } catch (IOException ioe) { + log.error(sm.getString("connectionPrefaceParser.ioError"), ioe); + error = true; + return false; + } + + if (read == -1) { + log.error(sm.getString("connectionPrefaceParser.eos", Integer.toString(pos))); + error = true; + return false; + } + + for (int i = pos; i < (pos + read); i++) { + if (data[i] != EXPECTED[i]) { + log.error(sm.getString("connectionPrefaceParser.mismatch", + new String(data, StandardCharsets.ISO_8859_1))); + error = true; + return false; + } + } + + pos += read; + return pos == EXPECTED.length; + } + + + public boolean isError() { + return error; + } +} Propchange: tomcat/trunk/java/org/apache/coyote/http2/ConnectionPrefaceParser.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1679047&r1=1679046&r2=1679047&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Tue May 12 20:16:58 2015 @@ -17,7 +17,6 @@ package org.apache.coyote.http2; import java.io.IOException; -import java.nio.charset.StandardCharsets; import javax.servlet.http.WebConnection; @@ -43,21 +42,14 @@ public class Http2UpgradeHandler impleme private static final Log log = LogFactory.getLog(Http2UpgradeHandler.class); private static final StringManager sm = StringManager.getManager(Http2UpgradeHandler.class); - private static final byte[] CLIENT_PREFACE_START_EXPECTED; private volatile SocketWrapperBase<?> socketWrapper; private volatile boolean initialized = false; - private volatile byte[] clientPrefaceStartData = new byte[CLIENT_PREFACE_START_EXPECTED.length]; - private volatile int clientPrefaceStartBytesRead = 0; + private volatile ConnectionPrefaceParser connectionPrefaceParser = + new ConnectionPrefaceParser(); private volatile boolean readFirstFrame = false; - static { - CLIENT_PREFACE_START_EXPECTED = - "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1); - } - - @Override public void init(WebConnection unused) { initialized = true; @@ -79,17 +71,21 @@ public class Http2UpgradeHandler impleme switch(status) { case OPEN_READ: - if (clientPrefaceStartBytesRead < CLIENT_PREFACE_START_EXPECTED.length) { - readClientPrefaceStart(); - if (clientPrefaceStartBytesRead == -1) { - // A fatal (for this connection) error occurred - close(); - return SocketState.CLOSED; + // Gets set to null once the connection preface has been + // successfully parsed. + if (connectionPrefaceParser != null) { + if (!connectionPrefaceParser.parse(socketWrapper)) { + if (connectionPrefaceParser.isError()) { + close(); + return SocketState.CLOSED; + } else { + // Incomplete + return SocketState.LONG; + } } - // Preface start has been read and validated. No need to keep this - // buffer hanging around in memory. - clientPrefaceStartData = null; } + connectionPrefaceParser = null; + // TODO process frames break; case OPEN_WRITE: @@ -133,34 +129,4 @@ public class Http2UpgradeHandler impleme log.debug(sm.getString("upgradeHandler.socketCloseFailed"), ioe); } } - - - private void readClientPrefaceStart() { - int read = 0; - try { - read = socketWrapper.read(false, clientPrefaceStartData, clientPrefaceStartBytesRead, - clientPrefaceStartData.length - clientPrefaceStartBytesRead); - } catch (IOException ioe) { - log.error(sm.getString("upgradeHandler.prefaceErrorIo"), ioe); - clientPrefaceStartBytesRead = -1; - return; - } - - if (read == -1) { - log.error(sm.getString("upgradeHandler.prefaceErrorEos", - Integer.toString(clientPrefaceStartBytesRead))); - clientPrefaceStartBytesRead = -1; - return; - } - - for (int i = clientPrefaceStartBytesRead; i < (clientPrefaceStartBytesRead + read); i++) { - if (clientPrefaceStartData[i] != CLIENT_PREFACE_START_EXPECTED[i]) { - log.error(sm.getString("upgradeHandler.prefaceErrorMismatch", - new String(clientPrefaceStartData, StandardCharsets.ISO_8859_1))); - clientPrefaceStartBytesRead = -1; - return; - } - } - clientPrefaceStartBytesRead += read; - } } Modified: tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties?rev=1679047&r1=1679046&r2=1679047&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Tue May 12 20:16:58 2015 @@ -13,6 +13,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +connectionPrefaceParser.eos=Unexpected end of stream while reading opening client preface byte sequence. Only [{0}] bytes read. +connectionPrefaceParser.ioError=Failed to read opening client preface byte sequence +connectionPrefaceParser.mismatch=An unexpected byte sequence was received at the start of the client preface [{0}] + hpack.integerEncodedOverTooManyOctets=HPACK variable length integer encoded over too many octets, max is {0} hpackdecoder.zeroNotValidHeaderTableIndex=Zero is not a valid header table index @@ -20,6 +24,4 @@ hpackdecoder.zeroNotValidHeaderTableInde hpackhuffman.huffmanEncodedHpackValueDidNotEndWithEOS=Huffman encoded value in HPACK headers did not end with EOS padding upgradeHandler.socketCloseFailed=Error closing socket -upgradeHandler.prefaceErrorEos=Unexpected end of stream while reading opening client preface byte sequence. Only [{0}] bytes read. -upgradeHandler.prefaceErrorIo=Failed to read opening client preface byte sequence -upgradeHandler.prefaceErrorMismatch=An unexpected byte sequence was received at the start of the client preface [{0}] \ No newline at end of file +upgradeHandler.unexpectedStatus=An unexpected value of status ([{0}]) was passed to this method \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org