Author: markt
Date: Tue Oct 13 16:25:44 2015
New Revision: 1708458

URL: http://svn.apache.org/viewvc?rev=1708458&view=rev
Log:
Start to refactor reset and error handling.
Add flags to each state for:
 - able to read (request body)
 - able to write (response body)
 - able to reset stream
Ensure that a stream is only reset once.

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

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=1708458&r1=1708457&r2=1708458&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Tue Oct 
13 16:25:44 2015
@@ -81,6 +81,7 @@ streamProcessor.ssl.error=Unable to retr
 
 streamStateMachine.debug.change=Connection [{0}], Stream [{1}], State changed 
from [{2}] to [{3}]
 streamStateMachine.invalidFrame=Connection [{0}], Stream [{1}], State [{2}], 
Frame type [{3}]
+streamStateMachine.invalidReset=Connection [{0}], Stream [{1}], State [{2}], 
Reset is not permitted in this state
 
 upgradeHandler.allocate.debug=Connection [{0}], Stream [{1}], allocated [{2}] 
bytes
 upgradeHandler.allocate.left=Connection [{0}], Stream [{1}], [{2}] bytes 
unallocated - trying to allocate to children

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=1708458&r1=1708457&r2=1708458&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamStateMachine.java Tue Oct 
13 16:25:44 2015
@@ -82,8 +82,30 @@ public class StreamStateMachine {
     }
 
 
-    public synchronized void sendReset() {
-        stateChange(state, State.CLOSED_RST_TX);
+    /**
+     * Marks the stream as reset. This method will not change the stream state
+     * if:
+     * <ul>
+     * <li>The stream is already reset</li>
+     * <li>The stream is already closed</li>
+     *
+     * @return <code>true</code> if a reset frame needs to be sent to the peer,
+     *         otherwise <code>false</code>
+     *
+     * @throws IllegalStateException If the stream is in a state that does not
+     *         permit resets
+     */
+    public synchronized boolean sendReset() {
+        if (state == State.IDLE) {
+            throw new 
IllegalStateException(sm.getString("streamStateMachine.debug.change",
+                    stream.getConnectionId(), stream.getIdentifier(), state));
+        }
+        if (state.canReset()) {
+            stateChange(state, State.CLOSED_RST_TX);
+            return true;
+        } else {
+            return false;
+        }
     }
 
 
@@ -130,6 +152,16 @@ public class StreamStateMachine {
     }
 
 
+    public synchronized boolean canRead() {
+        return state.canRead();
+    }
+
+
+    public synchronized boolean canWrite() {
+        return state.canWrite();
+    }
+
+
     public synchronized boolean isClosedFinal() {
         return state == State.CLOSED_FINAL;
     }
@@ -140,50 +172,66 @@ public class StreamStateMachine {
 
 
     private enum State {
-        IDLE               (false, true,  Http2Error.PROTOCOL_ERROR, 
FrameType.HEADERS,
-                                                                     
FrameType.PRIORITY),
-        OPEN               (true,  true,  Http2Error.PROTOCOL_ERROR, 
FrameType.DATA,
-                                                                     
FrameType.HEADERS,
-                                                                     
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.PUSH_PROMISE,
-                                                                     
FrameType.WINDOW_UPDATE),
-        RESERVED_LOCAL     (false, true,  Http2Error.PROTOCOL_ERROR, 
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.WINDOW_UPDATE),
-        RESERVED_REMOTE    (false, true,  Http2Error.PROTOCOL_ERROR, 
FrameType.HEADERS,
-                                                                     
FrameType.PRIORITY,
-                                                                     
FrameType.RST),
-        HALF_CLOSED_LOCAL  (true,  true,  Http2Error.PROTOCOL_ERROR, 
FrameType.DATA,
-                                                                     
FrameType.HEADERS,
-                                                                     
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.PUSH_PROMISE,
-                                                                     
FrameType.WINDOW_UPDATE),
-        HALF_CLOSED_REMOTE (true,  true,  Http2Error.STREAM_CLOSED,  
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.WINDOW_UPDATE),
-        CLOSED_RX          (false, true,  Http2Error.STREAM_CLOSED,  
FrameType.PRIORITY),
-        CLOSED_TX          (false, true,  Http2Error.STREAM_CLOSED,  
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.WINDOW_UPDATE),
-        CLOSED_RST_RX      (false, false, Http2Error.STREAM_CLOSED,  
FrameType.PRIORITY),
-        CLOSED_RST_TX      (false, false, Http2Error.STREAM_CLOSED,  
FrameType.DATA,
-                                                                     
FrameType.HEADERS,
-                                                                     
FrameType.PRIORITY,
-                                                                     
FrameType.RST,
-                                                                     
FrameType.PUSH_PROMISE,
-                                                                     
FrameType.WINDOW_UPDATE),
-        CLOSED_FINAL       (false, true,  Http2Error.PROTOCOL_ERROR, 
FrameType.PRIORITY);
-
-        private final boolean active;
+        IDLE               (false, false, false, true,
+                            Http2Error.PROTOCOL_ERROR, FrameType.HEADERS,
+                                                       FrameType.PRIORITY),
+        OPEN               (true,  true,  true,  true,
+                            Http2Error.PROTOCOL_ERROR, FrameType.DATA,
+                                                       FrameType.HEADERS,
+                                                       FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       FrameType.PUSH_PROMISE,
+                                                       
FrameType.WINDOW_UPDATE),
+        RESERVED_LOCAL     (false, false, true,  true,
+                            Http2Error.PROTOCOL_ERROR, FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       
FrameType.WINDOW_UPDATE),
+        RESERVED_REMOTE    (false, false, true,  true,
+                            Http2Error.PROTOCOL_ERROR, FrameType.HEADERS,
+                                                       FrameType.PRIORITY,
+                                                       FrameType.RST),
+        HALF_CLOSED_LOCAL  (true,  false, true,  true,
+                            Http2Error.PROTOCOL_ERROR, FrameType.DATA,
+                                                       FrameType.HEADERS,
+                                                       FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       FrameType.PUSH_PROMISE,
+                                                       
FrameType.WINDOW_UPDATE),
+        HALF_CLOSED_REMOTE (false, true,  true,  true,
+                            Http2Error.STREAM_CLOSED,  FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       
FrameType.WINDOW_UPDATE),
+        CLOSED_RX          (false, false, false, true,
+                            Http2Error.STREAM_CLOSED,  FrameType.PRIORITY),
+        CLOSED_TX          (false, false, false, true,
+                            Http2Error.STREAM_CLOSED,  FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       
FrameType.WINDOW_UPDATE),
+        CLOSED_RST_RX      (false, false, false, false,
+                            Http2Error.STREAM_CLOSED,  FrameType.PRIORITY),
+        CLOSED_RST_TX      (false, false, false, false,
+                            Http2Error.STREAM_CLOSED,  FrameType.DATA,
+                                                       FrameType.HEADERS,
+                                                       FrameType.PRIORITY,
+                                                       FrameType.RST,
+                                                       FrameType.PUSH_PROMISE,
+                                                       
FrameType.WINDOW_UPDATE),
+        CLOSED_FINAL       (false, false, false, false,
+                            Http2Error.PROTOCOL_ERROR, FrameType.PRIORITY);
+
+        private final boolean canRead;
+        private final boolean canWrite;
+        private final boolean canReset;
         private final boolean connectionErrorForInvalidFrame;
         private final Http2Error errorCodeForInvalidFrame;
         private final Set<FrameType> frameTypesPermitted = new HashSet<>();
 
-        private State(boolean active, boolean connectionErrorForInvalidFrame,
-                Http2Error errorCode, FrameType... frameTypes) {
-            this.active = active;
+        private State(boolean canRead, boolean canWrite, boolean canReset,
+                boolean connectionErrorForInvalidFrame, Http2Error errorCode,
+                FrameType... frameTypes) {
+            this.canRead = canRead;
+            this.canWrite = canWrite;
+            this.canReset = canReset;
             this.connectionErrorForInvalidFrame = 
connectionErrorForInvalidFrame;
             this.errorCodeForInvalidFrame = errorCode;
             for (FrameType frameType : frameTypes) {
@@ -192,7 +240,19 @@ public class StreamStateMachine {
         }
 
         public boolean isActive() {
-            return active;
+            return canWrite || canRead;
+        }
+
+        public boolean canRead() {
+            return canRead;
+        }
+
+        public boolean canWrite() {
+            return canWrite;
+        }
+
+        public boolean canReset() {
+            return canReset;
         }
 
         public boolean isFrameTypePermitted(FrameType frameType) {



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

Reply via email to