You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2015/05/13 20:18:08 UTC

svn commit: r1679255 - in /tomcat/trunk/java/org/apache/coyote/http2: AbstractStream.java Constants.java Http2UpgradeHandler.java LocalStrings.properties

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