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/06/02 23:38:08 UTC

svn commit: r1683191 - in /tomcat/trunk/java/org/apache/coyote/http2: Http2UpgradeHandler.java Stream.java StreamStateMachine.java

Author: markt
Date: Tue Jun  2 21:38:07 2015
New Revision: 1683191

URL: http://svn.apache.org/r1683191
Log:
First pass at a state machine for tracking stream state.
Lots of TODOs and not yet fully integrated into the processing.

Added:
    tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java   (with props)
Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.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=1683191&r1=1683190&r2=1683191&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Tue Jun  2 21:38:07 2015
@@ -737,9 +737,10 @@ public class Http2UpgradeHandler extends
 
     @Override
     public void headersEnd(int streamId) {
+        Stream stream = getStream(streamId);
+        stream.headersEnd();
         // Process this stream on a container thread
-        StreamProcessor streamProcessor = new StreamProcessor(
-                getStream(streamId), adapter, socketWrapper);
+        StreamProcessor streamProcessor = new StreamProcessor(stream, adapter, socketWrapper);
         streamProcessor.setSslSupport(sslSupport);
         socketWrapper.getEndpoint().getExecutor().execute(streamProcessor);
     }

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=1683191&r1=1683190&r2=1683191&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Tue Jun  2 21:38:07 2015
@@ -42,6 +42,7 @@ public class Stream extends AbstractStre
     private final Response coyoteResponse = new Response();
     private final StreamInputBuffer inputBuffer = new StreamInputBuffer();
     private final StreamOutputBuffer outputBuffer = new StreamOutputBuffer();
+    private final StreamStateMachine state = new StreamStateMachine();
 
 
     public Stream(Integer identifier, Http2UpgradeHandler handler) {
@@ -58,6 +59,11 @@ public class Stream extends AbstractStre
         this.coyoteRequest.setInputBuffer(inputBuffer);
         this.coyoteResponse.setOutputBuffer(outputBuffer);
         this.coyoteRequest.setResponse(coyoteResponse);
+        if (coyoteRequest.isFinished()) {
+            // Update the state machine
+            state.receiveHeaders();
+            state.recieveEndOfStream();
+        }
     }
 
 
@@ -213,6 +219,11 @@ public class Stream extends AbstractStre
     }
 
 
+    void headersEnd() {
+        state.receiveHeaders();
+    }
+
+
     void setEndOfStream() {
         // TODO This is temporary until the state machine for a stream is
         // implemented

Added: 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=1683191&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java (added)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java Tue Jun  2 21:38:07 2015
@@ -0,0 +1,143 @@
+/*
+ *  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;
+
+/**
+ * See <a href="https://tools.ietf.org/html/rfc7540#section-5.1">state
+ * diagram</a> in RFC 7540.
+ * <br>
+ * The following additions are supported by this state machine:
+ * <ul>
+ * <li>differentiate between closed (normal) and closed caused by reset</li>
+ * <li>allow a transition from idle to closed if reset is sent or received</li>
+ * </ul>
+ *
+ */
+public class StreamStateMachine {
+
+    private State state = State.IDLE;
+
+
+    public synchronized void sendPushPromise() {
+        if (state == State.IDLE) {
+            state = State.RESERVED_LOCAL;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void receivePushPromis() {
+        if (state == State.IDLE) {
+            state = State.RESERVED_REMOTE;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void sendHeaders() {
+        if (state == State.IDLE) {
+            state = State.OPEN;
+        } else if (state == State.RESERVED_LOCAL) {
+            state = State.HALF_CLOSED_REMOTE;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void receiveHeaders() {
+        if (state == State.IDLE) {
+            state = State.OPEN;
+        } else if (state == State.RESERVED_REMOTE) {
+            state = State.HALF_CLOSED_LOCAL;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void sendEndOfStream() {
+        if (state == State.OPEN) {
+            state = State.HALF_CLOSED_LOCAL;
+        } else if (state == State.HALF_CLOSED_REMOTE) {
+            state = State.CLOSED;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void recieveEndOfStream() {
+        if (state == State.OPEN) {
+            state = State.HALF_CLOSED_REMOTE;
+        } else if (state == State.HALF_CLOSED_LOCAL) {
+            state = State.CLOSED;
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    public synchronized void sendReset() {
+        if (state == State.CLOSED) {
+            // This should never happen
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+        state = State.CLOSED_RESET;
+    }
+
+
+    public synchronized void recieveReset() {
+        state = State.CLOSED_RESET;
+    }
+
+
+    public synchronized void receiveHeader() {
+        // Doesn't change state (that happens at the end of the headers when
+        // receiveHeaders() is called. This just checks that the stream is in a
+        // valid state to receive headers.
+        if (state == State.CLOSED_RESET) {
+            // Allow this. Client may not know that stream has been reset.
+        } else if (state == State.IDLE || state == State.RESERVED_REMOTE) {
+            // Allow these. This is normal operation.
+        } else {
+            // TODO: ProtocolExcpetion? i18n
+            throw new IllegalStateException();
+        }
+    }
+
+
+    private enum State {
+        IDLE,
+        OPEN,
+        RESERVED_LOCAL,
+        RESERVED_REMOTE,
+        HALF_CLOSED_LOCAL,
+        HALF_CLOSED_REMOTE,
+        CLOSED,
+        CLOSED_RESET
+    }
+}

Propchange: tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java
------------------------------------------------------------------------------
    svn:eol-style = native



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