Author: markt
Date: Wed Jun 10 19:43:10 2015
New Revision: 1684752

URL: http://svn.apache.org/r1684752
Log:
Add the plumbing required for HTTP/2 5.1.1 and 5.1.2

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java
    tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java

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=1684752&r1=1684751&r2=1684752&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed Jun 
10 19:43:10 2015
@@ -107,7 +107,6 @@ public class Http2UpgradeHandler extends
 
     private final ConnectionSettings remoteSettings = new ConnectionSettings();
     private final ConnectionSettings localSettings = new ConnectionSettings();
-    private volatile int maxRemoteStreamId = 0;
 
     private HpackDecoder hpackDecoder;
     private HpackEncoder hpackEncoder;
@@ -118,7 +117,9 @@ public class Http2UpgradeHandler extends
     private long writeTimeout = 10000;
 
     private final Map<Integer,Stream> streams = new HashMap<>();
-    private int maxStreamId = -1;
+    private volatile int activeRemoteStreamCount = 0;
+    private volatile int maxRemoteStreamId = 0;
+    private volatile int maxActiveRemoteStreamId = 0;
 
     // Tracking for when the connection is blocked (windowSize < 1)
     private final Object backLogLock = new Object();
@@ -140,6 +141,7 @@ public class Http2UpgradeHandler extends
             Stream stream = new Stream(key, this, coyoteRequest);
             streams.put(key, stream);
             maxRemoteStreamId = 1;
+            activeRemoteStreamCount = 1;
         }
     }
 
@@ -632,7 +634,8 @@ public class Http2UpgradeHandler extends
         Stream result = streams.get(key);
         if (result == null && unknownIsError) {
             // Stream has been closed and removed from the map
-            throw new 
ConnectionException(sm.getString("upgradeHandler.stream.closed", key), 
Http2Error.PROTOCOL_ERROR);
+            throw new 
ConnectionException(sm.getString("upgradeHandler.stream.closed", key),
+                    Http2Error.PROTOCOL_ERROR);
         }
         return result;
     }
@@ -651,6 +654,8 @@ public class Http2UpgradeHandler extends
                     Integer.valueOf(maxRemoteStreamId)), 
Http2Error.PROTOCOL_ERROR);
         }
 
+        // TODO Implement periodic pruning of closed streams
+
         Stream result = new Stream(key, this);
         streams.put(key, result);
         maxRemoteStreamId = streamId;
@@ -761,9 +766,6 @@ public class Http2UpgradeHandler extends
     @Override
     public ByteBuffer getInputByteBuffer(int streamId, int payloadSize) throws 
Http2Exception {
         Stream stream = getStream(streamId, true);
-        if (stream == null) {
-            return null;
-        }
         stream.checkState(FrameType.DATA);
         return stream.getInputByteBuffer();
     }
@@ -772,9 +774,10 @@ public class Http2UpgradeHandler extends
     @Override
     public void receiveEndOfStream(int streamId) throws ConnectionException {
         Stream stream = getStream(streamId, true);
-        if (stream != null) {
-            stream.receivedEndOfStream();
+        if (stream.isActive()) {
+            activeRemoteStreamCount--;
         }
+        stream.receivedEndOfStream();
     }
 
 
@@ -786,10 +789,29 @@ public class Http2UpgradeHandler extends
         }
         stream.checkState(FrameType.HEADERS);
         stream.receivedStartOfHeaders();
+        closeIdleStreams(streamId);
+        if (localSettings.getMaxConcurrentStreams() > activeRemoteStreamCount) 
{
+            activeRemoteStreamCount++;
+        } else {
+            throw new 
StreamException(sm.getString("upgradeHandler.tooManyRemoteStreams",
+                    Long.toString(localSettings.getMaxConcurrentStreams())),
+                    Http2Error.REFUSED_STREAM, streamId);
+        }
         return stream;
     }
 
 
+    private void closeIdleStreams(int newMaxActiveRemoteStreamId) throws 
Http2Exception {
+        for (int i = maxActiveRemoteStreamId + 2; i < 
newMaxActiveRemoteStreamId; i += 2) {
+            Stream stream = getStream(newMaxActiveRemoteStreamId, false);
+            if (stream != null) {
+                stream.closeIfIdle();
+            }
+        }
+        maxActiveRemoteStreamId = newMaxActiveRemoteStreamId;
+    }
+
+
     @Override
     public void reprioritise(int streamId, int parentStreamId,
             boolean exclusive, int weight) throws Http2Exception {
@@ -820,10 +842,8 @@ public class Http2UpgradeHandler extends
     @Override
     public void reset(int streamId, long errorCode) throws Http2Exception  {
         Stream stream = getStream(streamId, true);
-        if (stream != null) {
-            stream.checkState(FrameType.RST);
-            stream.reset(errorCode);
-        }
+        stream.checkState(FrameType.RST);
+        stream.reset(errorCode);
     }
 
 
@@ -869,9 +889,6 @@ public class Http2UpgradeHandler extends
             log.debug(sm.getString("upgradeHandler.goaway.debug", connectionId,
                     Integer.toString(lastStreamId), 
Long.toHexString(errorCode), debugData));
         }
-
-        // TODO: Do more than just record this
-        maxStreamId = lastStreamId;
     }
 
 

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=1684752&r1=1684751&r2=1684752&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Wed Jun 
10 19:43:10 2015
@@ -72,6 +72,7 @@ upgradeHandler.socketCloseFailed=Error c
 upgradeHandler.stream.closed=Stream [{0}] has been closed for some time
 upgradeHandler.stream.even=A new remote stream ID of [{0}] was requested but 
all remote streams must use odd identifiers
 upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but 
the most recent stream was [{1}]
+upgradeHandler.tooManyRemoteStreams=The client attempted to use more than 
[{0}] active streams
 upgradeHandler.swallow.eos=End of stream found while trying to swallow [{0}] 
bytes
 upgradeHandler.unexpectedEos=Unexpected end of stream
 upgradeHandler.unexpectedStatus=An unexpected value of status ([{0}]) was 
passed to this method

Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1684752&r1=1684751&r2=1684752&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Jun 10 19:43:10 
2015
@@ -38,11 +38,12 @@ public class Stream extends AbstractStre
     private volatile int weight = Constants.DEFAULT_WEIGHT;
 
     private final Http2UpgradeHandler handler;
+    private final StreamStateMachine state;
+    // TODO: Only create these objects if needed and null them when finished
     private final Request coyoteRequest;
     private final Response coyoteResponse = new Response();
     private final StreamInputBuffer inputBuffer;
     private final StreamOutputBuffer outputBuffer = new StreamOutputBuffer();
-    private final StreamStateMachine state;
 
 
     public Stream(Integer identifier, Http2UpgradeHandler handler) {
@@ -260,6 +261,16 @@ public class Stream extends AbstractStre
     }
 
 
+    boolean isActive() {
+        return state.isActive();
+    }
+
+
+    void closeIfIdle() {
+        state.closeIfIdle();
+    }
+
+
     class StreamOutputBuffer implements OutputBuffer {
 
         private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024);

Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java?rev=1684752&r1=1684751&r2=1684752&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java Wed Jun 
10 19:43:10 2015
@@ -130,6 +130,13 @@ public class StreamStateMachine {
     }
 
 
+    public synchronized void closeIfIdle() {
+        if (state == State.IDLE) {
+            state = State.CLOSED_FINAL;
+        }
+    }
+
+
     private enum State {
         IDLE               (false, true,  Http2Error.PROTOCOL_ERROR, 
FrameType.HEADERS,
                                                                      
FrameType.PRIORITY),



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to