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: [email protected]
For additional commands, e-mail: [email protected]