Author: markt Date: Wed May 13 18:18:07 2015 New Revision: 1679255 URL: http://svn.apache.org/r1679255 Log: Process priority frames
Added: tomcat/trunk/java/org/apache/coyote/http2/Constants.java (with props) Modified: tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.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/http2/AbstractStream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java?rev=1679255&r1=1679254&r2=1679255&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/AbstractStream.java Wed May 13 18:18:07 2015 @@ -20,18 +20,23 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import org.apache.juli.logging.Log; +import org.apache.juli.logging.LogFactory; +import org.apache.tomcat.util.res.StringManager; + /** * Used to managed prioritisation. */ abstract class AbstractStream { - private static final int DEFAULT_WEIGHT = 16; + private static final Log log = LogFactory.getLog(AbstractStream.class); + private static final StringManager sm = StringManager.getManager(AbstractStream.class); private final Integer identifier; private volatile AbstractStream parentStream = null; private final Set<AbstractStream> childStreams = new HashSet<>(); - private volatile int weight = DEFAULT_WEIGHT; + private volatile int weight = Constants.DEFAULT_WEIGHT; public Integer getIdentifier() { return identifier; @@ -43,7 +48,12 @@ abstract class AbstractStream { } - public void rePrioritise(Stream parent, boolean exclusive, int weight) { + public void rePrioritise(AbstractStream parent, boolean exclusive, int weight) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("abstractStream.reprioritisation.debug", identifier, + Boolean.toString(exclusive), parent.getIdentifier(), Integer.toString(weight))); + } + // Check if new parent is a descendant of this stream if (isDescendant(parent)) { parent.detachFromParent(); Added: tomcat/trunk/java/org/apache/coyote/http2/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Constants.java?rev=1679255&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Constants.java (added) +++ tomcat/trunk/java/org/apache/coyote/http2/Constants.java Wed May 13 18:18:07 2015 @@ -0,0 +1,23 @@ +/* + * 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; + +public class Constants { + + // Prioritisation + public static final int DEFAULT_WEIGHT = 16; +} Propchange: tomcat/trunk/java/org/apache/coyote/http2/Constants.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=1679255&r1=1679254&r2=1679255&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed May 13 18:18:07 2015 @@ -52,6 +52,7 @@ public class Http2UpgradeHandler extends private static final Integer STREAM_ID_ZERO = Integer.valueOf(0); + private static final int FRAME_TYPE_PRIORITY = 2; private static final int FRAME_TYPE_SETTINGS = 4; private static final int FRAME_TYPE_WINDOW_UPDATE = 8; @@ -67,6 +68,7 @@ public class Http2UpgradeHandler extends private final ConnectionSettings remoteSettings = new ConnectionSettings(); private volatile long flowControlWindowSize = ConnectionSettings.DEFAULT_WINDOW_SIZE; + private volatile int maxRemoteStreamId = 0; private final Map<Integer,Stream> streams = new HashMap<>(); @@ -186,6 +188,9 @@ public class Http2UpgradeHandler extends int payloadSize = getPayloadSize(streamId, frameHeader); switch (frameType) { + case FRAME_TYPE_PRIORITY: + processFramePriority(flags, streamId, payloadSize); + break; case FRAME_TYPE_SETTINGS: processFrameSettings(flags, streamId, payloadSize); break; @@ -200,6 +205,51 @@ public class Http2UpgradeHandler extends } + private void processFramePriority(int flags, int streamId, int payloadSize) throws IOException { + if (log.isDebugEnabled()) { + log.debug(sm.getString("upgradeHandler.processFrame", + Integer.toString(FRAME_TYPE_PRIORITY), Integer.toString(flags), + Integer.toString(streamId), Integer.toString(payloadSize))); + } + // Validate the frame + if (streamId == 0) { + throw new Http2Exception(sm.getString("upgradeHandler.processFramePriority.invalidStream"), + 0, Http2Exception.PROTOCOL_ERROR); + } + if (payloadSize != 5) { + throw new Http2Exception(sm.getString("upgradeHandler.processFramePriority.invalidPayloadSize", + Integer.toString(payloadSize)), streamId, Http2Exception.FRAME_SIZE_ERROR); + } + + byte[] payload = new byte[5]; + readFully(payload); + + boolean exclusive = (payload[0] & 0x80) > 0; + int parentStreamId = ((payload[0] & 0x7F) << 24) + ((payload[1] & 0xFF) << 16) + + ((payload[2] & 0xFF) << 8) + (payload[3] & 0xFF); + int weight = (payload[4] & 0xFF) + 1; + + Stream stream = getStream(streamId); + AbstractStream parentStream; + if (parentStreamId == 0) { + parentStream = this; + } else { + parentStream = getStream(parentStreamId); + if (parentStream == null) { + parentStream = this; + weight = Constants.DEFAULT_WEIGHT; + exclusive = false; + } + } + + if (stream == null) { + // Old stream. Already closed and dropped from the stream map. + } else { + stream.rePrioritise(parentStream, exclusive, weight); + } + } + + private void processFrameSettings(int flags, int streamId, int payloadSize) throws IOException { if (log.isDebugEnabled()) { log.debug(sm.getString("upgradeHandler.processFrame", @@ -276,19 +326,20 @@ public class Http2UpgradeHandler extends if (streamId == 0) { flowControlWindowSize += windowSizeIncrement; } else { - Integer key = Integer.valueOf(streamId); - Stream stream = streams.get(key); + Stream stream = getStream(streamId); if (stream == null) { - stream = new Stream(key, this); + // Old stream already closed. + // Ignore + } else { + stream.incrementWindowSize(windowSizeIncrement); } - stream.incrementWindowSize(windowSizeIncrement); } } private void processFrameUnknown(int streamId, int type, int payloadSize) throws IOException { // Swallow the payload - log.info("Swallowing [" + payloadSize + "] bytes of unknown frame type + [" + type + + log.info("Swallowing [" + payloadSize + "] bytes of unknown frame type [" + type + "] from stream [" + streamId + "]"); swallowPayload(payloadSize); } @@ -423,6 +474,21 @@ public class Http2UpgradeHandler extends } } + + private Stream getStream(int streamId) { + Integer key = Integer.valueOf(streamId); + + if (streamId > maxRemoteStreamId) { + // Must be a new stream + maxRemoteStreamId = streamId; + Stream stream = new Stream(key, this); + streams.put(key, stream); + return stream; + } else { + return streams.get(key); + } + } + private void close() { try { 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=1679255&r1=1679254&r2=1679255&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Wed May 13 18:18:07 2015 @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +abstractStream.reprioritisation.debug=Reprioritising stream [{0}] with exclusive [{1}], parent [{2}] and weight [{3}] 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}] @@ -33,6 +34,8 @@ upgradeHandler.connectionError=An error upgradeHandler.payloadTooBig=The payload is [{0}] bytes long but the maximum frame size is [{1}] upgradeHandler.processFrame=Processing frame of type [{0}] for stream [{2}] with flags [{1}] and payload size [{3}] upgradeHandler.processFrame.ioerror=An I/O error occurred while reading an incoming HTTP/2 frame +upgradeHandler.processFramePriority.invalidPayloadSize=Settings frame received with an invalid payload size of [{0}] (should be 5) +upgradeHandler.processFramePriority.invalidStream=Settings frame received for stream [0] upgradeHandler.processFrameSettings.ackWithNonZeroPayload=Settings frame received with the ACK flag set and payload present upgradeHandler.processFrameSettings.invalidPayloadSize=Settings frame received with a payload size of [{0}] which is not a multiple of 6 upgradeHandler.processFrameSettings.invalidStream=Settings frame received for stream [{0}] --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org