Author: markt
Date: Wed May 13 12:45:56 2015
New Revision: 1679196
URL: http://svn.apache.org/r1679196
Log:
Add processing support for window update frames (required initial support for
streams)
Added:
tomcat/trunk/java/org/apache/coyote/http2/Stream.java (with props)
Modified:
tomcat/trunk/java/org/apache/coyote/http2/ConnectionSettings.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/ConnectionSettings.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/ConnectionSettings.java?rev=1679196&r1=1679195&r2=1679196&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/ConnectionSettings.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/ConnectionSettings.java Wed May
13 12:45:56 2015
@@ -27,6 +27,7 @@ public class ConnectionSettings {
private final Log log = LogFactory.getLog(ConnectionSettings.class);
private final StringManager sm =
StringManager.getManager(ConnectionSettings.class);
+ public static final long DEFAULT_WINDOW_SIZE = (1 << 16) - 1;
private static final long UNLIMITED = 1 << 32; // Use the maximum possible
private static final long MAX_WINDOW_SIZE = (1 << 31) - 1;
private static final long MIN_MAX_FRAME_SIZE = 1 << 14;
@@ -35,7 +36,7 @@ public class ConnectionSettings {
private volatile long headerTableSize = 4096;
private volatile long enablePush = 1;
private volatile long maxConcurrentStreams = UNLIMITED;
- private volatile long initialWindowSize = (1 << 16) - 1;
+ private volatile long initialWindowSize = DEFAULT_WINDOW_SIZE;
private volatile long maxFrameSize = MIN_MAX_FRAME_SIZE;
private volatile long maxHeaderListSize = UNLIMITED;
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=1679196&r1=1679195&r2=1679196&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed May
13 12:45:56 2015
@@ -19,6 +19,8 @@ package org.apache.coyote.http2;
import java.io.EOFException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
import javax.servlet.http.WebConnection;
@@ -48,11 +50,12 @@ public class Http2UpgradeHandler impleme
private static final Log log =
LogFactory.getLog(Http2UpgradeHandler.class);
private static final StringManager sm =
StringManager.getManager(Http2UpgradeHandler.class);
- private static final int FRAME_SETTINGS = 4;
+ private static final int FRAME_TYPE_SETTINGS = 4;
+ private static final int FRAME_TYPE_WINDOW_UPDATE = 8;
private static final byte[] SETTINGS_EMPTY = { 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00 };
private static final byte[] SETTINGS_ACK = { 0x00, 0x00, 0x00, 0x04, 0x01,
0x00, 0x00, 0x00, 0x00 };
- private static final byte[] GOAWAY = { 0x07, 0x00, 0x00, 0x00 };
+ private static final byte[] GOAWAY = { 0x07, 0x00, 0x00, 0x00, 0x00 };
private volatile SocketWrapperBase<?> socketWrapper;
private volatile boolean initialized = false;
@@ -61,6 +64,9 @@ public class Http2UpgradeHandler impleme
private volatile boolean firstFrame = true;
private final ConnectionSettings remoteSettings = new ConnectionSettings();
+ private volatile long flowControlWindowSize =
ConnectionSettings.DEFAULT_WINDOW_SIZE;
+
+ private final Map<Integer,Stream> streams = new HashMap<>();
@Override
public void init(WebConnection unused) {
@@ -172,9 +178,12 @@ public class Http2UpgradeHandler impleme
int payloadSize = getPayloadSize(streamId, frameHeader);
switch (frameType) {
- case FRAME_SETTINGS:
+ case FRAME_TYPE_SETTINGS:
processFrameSettings(flags, streamId, payloadSize);
break;
+ case FRAME_TYPE_WINDOW_UPDATE:
+ processFrameWindowUpdate(flags, streamId, payloadSize);
+ break;
default:
// Unknown frame type.
processFrameUnknown(streamId, frameType, payloadSize);
@@ -185,7 +194,8 @@ public class Http2UpgradeHandler impleme
private void processFrameSettings(int flags, int streamId, int
payloadSize) throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.processFrameSettings",
Integer.toString(flags),
+ log.debug(sm.getString("upgradeHandler.processFrame",
+ Integer.toString(FRAME_TYPE_SETTINGS),
Integer.toString(flags),
Integer.toString(streamId),
Integer.toString(payloadSize)));
}
// Validate the frame
@@ -211,14 +221,7 @@ public class Http2UpgradeHandler impleme
// Process the settings
byte[] setting = new byte[6];
for (int i = 0; i < payloadSize / 6; i++) {
- int read = 0;
- while (read < 6) {
- int thisTime = socketWrapper.read(true, setting, read,
setting.length - read);
- if (thisTime == -1) {
- throw new
EOFException(sm.getString("upgradeHandler.unexpectedEos"));
- }
- read += thisTime;
- }
+ readFully(setting);
int id = ((setting[0] & 0xFF) << 8) + (setting[1] & 0xFF);
long value = ((setting[2] & 0xFF) << 24) + ((setting[3] &
0xFF) << 16) +
((setting[4] & 0xFF) << 8) + (setting[5] & 0xFF);
@@ -233,6 +236,43 @@ public class Http2UpgradeHandler impleme
}
+ private void processFrameWindowUpdate(int flags, int streamId, int
payloadSize)
+ throws IOException {
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("upgradeHandler.processFrame",
+ Integer.toString(FRAME_TYPE_WINDOW_UPDATE),
Integer.toString(flags),
+ Integer.toString(streamId),
Integer.toString(payloadSize)));
+ }
+ // Validate the frame
+ if (payloadSize != 4) {
+ // TODO i18n
+ // Use stream 0 since this is always a connection error
+ throw new Http2Exception("", 0, Http2Exception.FRAME_SIZE_ERROR);
+ }
+
+ byte[] payload = new byte[4];
+ readFully(payload);
+ int windowSizeIncrement = ((payload[0] & 0x7F) << 24) + ((payload[1] &
0xFF) << 16) +
+ ((payload[2] & 0xFF) << 8) + (payload[3] & 0xFF);
+
+ // Validate the data
+ if (windowSizeIncrement == 0) {
+ // TODO i18n
+ throw new Http2Exception("", streamId,
Http2Exception.PROTOCOL_ERROR);
+ }
+ if (streamId == 0) {
+ flowControlWindowSize += windowSizeIncrement;
+ } else {
+ Integer key = Integer.valueOf(streamId);
+ Stream stream = streams.get(key);
+ if (stream == null) {
+ stream = new Stream(key,
remoteSettings.getInitialWindowSize());
+ }
+ 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 +
@@ -282,7 +322,7 @@ public class Http2UpgradeHandler impleme
int frameType = frameHeader[3] & 0xFF;
// Make sure the first frame is a settings frame
if (firstFrame) {
- if (frameType != FRAME_SETTINGS) {
+ if (frameType != FRAME_TYPE_SETTINGS) {
throw new
Http2Exception(sm.getString("upgradeHandler.receivePrefaceNotSettings"),
0, Http2Exception.PROTOCOL_ERROR);
} else {
@@ -296,7 +336,7 @@ public class Http2UpgradeHandler impleme
private int getStreamIdentifier(byte[] frameHeader) {
// MSB of [5] is reserved and must be ignored.
return ((frameHeader[5] & 0x7F) << 24) + ((frameHeader[6] & 0xFF) <<
16) +
- ((frameHeader[7] & 0xFF) << 6) + (frameHeader[8] & 0xFF);
+ ((frameHeader[7] & 0xFF) << 8) + (frameHeader[8] & 0xFF);
}
@@ -353,6 +393,19 @@ public class Http2UpgradeHandler impleme
return result;
}
+
+ private void readFully(byte[] dest) throws IOException {
+ int read = 0;
+ while (read < dest.length) {
+ int thisTime = socketWrapper.read(true, dest, read, dest.length -
read);
+ if (thisTime == -1) {
+ throw new
EOFException(sm.getString("upgradeHandler.unexpectedEos"));
+ }
+ read += thisTime;
+ }
+ }
+
+
private void close() {
try {
socketWrapper.close();
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=1679196&r1=1679195&r2=1679196&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Wed May
13 12:45:56 2015
@@ -30,8 +30,8 @@ hpackhuffman.huffmanEncodedHpackValueDid
upgradeHandler.connectionError=An error occurred that requires the HTTP/2
connection to be closed.
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.processFrameSettings=Processing settings frame for stream [{1}]
with flags [{0}] and payload size [{2}]
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}]
Added: 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=1679196&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (added)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed May 13 12:45:56
2015
@@ -0,0 +1,39 @@
+/*
+ * 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 Stream {
+
+ private final Integer identifier;
+
+ private volatile long flowControlWindowSize;
+
+ public Stream(Integer identifier, long intitalWindowSize) {
+ this.identifier = identifier;
+ flowControlWindowSize = intitalWindowSize;
+ }
+
+
+ public Integer getIdentifier() {
+ return identifier;
+ }
+
+
+ public void incrementWindowSize(int windowSizeIncrement) {
+ flowControlWindowSize += windowSizeIncrement;
+ }
+}
Propchange: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
------------------------------------------------------------------------------
svn:eol-style = native
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]