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 2023/01/25 16:34:15 UTC
[tomcat] 04/05: Code clean-up (format). No functional change.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit aaff739f6345807a5b5afaa0e7bc4649c17c0d89
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jan 25 15:40:57 2023 +0000
Code clean-up (format). No functional change.
---
.../apache/coyote/http2/AbstractNonZeroStream.java | 12 +-
java/org/apache/coyote/http2/AbstractStream.java | 20 +-
java/org/apache/coyote/http2/ByteUtil.java | 9 +-
.../coyote/http2/ConnectionSettingsBase.java | 87 +++--
.../coyote/http2/ConnectionSettingsLocal.java | 19 +-
.../coyote/http2/ConnectionSettingsRemote.java | 3 +-
java/org/apache/coyote/http2/FrameType.java | 67 ++--
java/org/apache/coyote/http2/HPackHuffman.java | 77 ++--
java/org/apache/coyote/http2/HeaderSink.java | 5 +-
java/org/apache/coyote/http2/Hpack.java | 32 +-
java/org/apache/coyote/http2/HpackDecoder.java | 98 +++--
java/org/apache/coyote/http2/HpackEncoder.java | 123 +++---
java/org/apache/coyote/http2/HpackException.java | 4 +-
java/org/apache/coyote/http2/Http2AsyncParser.java | 105 ++---
.../coyote/http2/Http2AsyncUpgradeHandler.java | 153 ++++----
.../org/apache/coyote/http2/Http2OutputBuffer.java | 10 +-
java/org/apache/coyote/http2/Http2Parser.java | 302 +++++++--------
java/org/apache/coyote/http2/Http2Protocol.java | 7 +-
.../apache/coyote/http2/Http2UpgradeHandler.java | 405 ++++++++++----------
java/org/apache/coyote/http2/RecycledStream.java | 9 +-
java/org/apache/coyote/http2/Setting.java | 52 +--
java/org/apache/coyote/http2/Stream.java | 421 ++++++++++-----------
java/org/apache/coyote/http2/StreamProcessor.java | 89 ++---
.../apache/coyote/http2/StreamStateMachine.java | 31 +-
.../coyote/http2/WindowAllocationManager.java | 69 ++--
25 files changed, 1043 insertions(+), 1166 deletions(-)
diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
index f6a00e20e0..aae614f42c 100644
--- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java
+++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java
@@ -19,8 +19,8 @@ package org.apache.coyote.http2;
import java.nio.ByteBuffer;
/**
- * Base class for all streams other than stream 0, the connection. Primarily
- * provides functionality shared between full Stream and RecycledStream.
+ * Base class for all streams other than stream 0, the connection. Primarily provides functionality shared between full
+ * Stream and RecycledStream.
*/
abstract class AbstractNonZeroStream extends AbstractStream {
@@ -52,12 +52,10 @@ abstract class AbstractNonZeroStream extends AbstractStream {
/**
- * Obtain the ByteBuffer to store DATA frame payload data for this stream
- * that has been received from the client.
+ * Obtain the ByteBuffer to store DATA frame payload data for this stream that has been received from the client.
*
- * @return {@code null} if the DATA frame payload can be swallowed, or a
- * ByteBuffer with at least enough space remaining for the current
- * flow control window for stream data from the client.
+ * @return {@code null} if the DATA frame payload can be swallowed, or a ByteBuffer with at least enough space
+ * remaining for the current flow control window for stream data from the client.
*/
abstract ByteBuffer getInputByteBuffer();
diff --git a/java/org/apache/coyote/http2/AbstractStream.java b/java/org/apache/coyote/http2/AbstractStream.java
index d3533c5bd8..f332b8c593 100644
--- a/java/org/apache/coyote/http2/AbstractStream.java
+++ b/java/org/apache/coyote/http2/AbstractStream.java
@@ -21,8 +21,8 @@ import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
- * Base class for all streams including the connection (referred to as Stream 0)
- * and is used primarily when managing prioritization.
+ * Base class for all streams including the connection (referred to as Stream 0) and is used primarily when managing
+ * prioritization.
*/
abstract class AbstractStream {
@@ -71,9 +71,10 @@ abstract class AbstractStream {
/**
* Increment window size.
+ *
* @param increment The amount by which the window size should be increased
- * @throws Http2Exception If the window size is now higher than
- * the maximum allowed
+ *
+ * @throws Http2Exception If the window size is now higher than the maximum allowed
*/
synchronized void incrementWindowSize(int increment) throws Http2Exception {
// No need for overflow protection here.
@@ -82,8 +83,8 @@ abstract class AbstractStream {
windowSize += increment;
if (log.isDebugEnabled()) {
- log.debug(sm.getString("abstractStream.windowSizeInc", getConnectionId(),
- getIdAsString(), Integer.toString(increment), Long.toString(windowSize)));
+ log.debug(sm.getString("abstractStream.windowSizeInc", getConnectionId(), getIdAsString(),
+ Integer.toString(increment), Long.toString(windowSize)));
}
if (windowSize > ConnectionSettingsBase.MAX_WINDOW_SIZE) {
@@ -92,8 +93,7 @@ abstract class AbstractStream {
if (identifier.intValue() == 0) {
throw new ConnectionException(msg, Http2Error.FLOW_CONTROL_ERROR);
} else {
- throw new StreamException(
- msg, Http2Error.FLOW_CONTROL_ERROR, identifier.intValue());
+ throw new StreamException(msg, Http2Error.FLOW_CONTROL_ERROR, identifier.intValue());
}
}
}
@@ -105,8 +105,8 @@ abstract class AbstractStream {
// decrements are permitted
windowSize -= decrement;
if (log.isDebugEnabled()) {
- log.debug(sm.getString("abstractStream.windowSizeDec", getConnectionId(),
- getIdAsString(), Integer.toString(decrement), Long.toString(windowSize)));
+ log.debug(sm.getString("abstractStream.windowSizeDec", getConnectionId(), getIdAsString(),
+ Integer.toString(decrement), Long.toString(windowSize)));
}
}
diff --git a/java/org/apache/coyote/http2/ByteUtil.java b/java/org/apache/coyote/http2/ByteUtil.java
index 1cdbae2018..e8904c4a92 100644
--- a/java/org/apache/coyote/http2/ByteUtil.java
+++ b/java/org/apache/coyote/http2/ByteUtil.java
@@ -64,13 +64,12 @@ class ByteUtil {
static int getTwoBytes(byte[] input, int firstByte) {
- return ((input[firstByte] & 0xFF) << 8) + (input[firstByte + 1] & 0xFF);
+ return ((input[firstByte] & 0xFF) << 8) + (input[firstByte + 1] & 0xFF);
}
static int getThreeBytes(byte[] input, int firstByte) {
- return ((input[firstByte] & 0xFF) << 16) + ((input[firstByte + 1] & 0xFF) << 8) +
- (input[firstByte + 2] & 0xFF);
+ return ((input[firstByte] & 0xFF) << 16) + ((input[firstByte + 1] & 0xFF) << 8) + (input[firstByte + 2] & 0xFF);
}
@@ -94,13 +93,13 @@ class ByteUtil {
static long getFourBytes(byte[] input, int firstByte) {
- return ((long)(input[firstByte] & 0xFF) << 24) + ((input[firstByte + 1] & 0xFF) << 16) +
+ return ((long) (input[firstByte] & 0xFF) << 24) + ((input[firstByte + 1] & 0xFF) << 16) +
((input[firstByte + 2] & 0xFF) << 8) + (input[firstByte + 3] & 0xFF);
}
static void setFourBytes(byte[] output, int firstByte, long value) {
- output[firstByte] = (byte) ((value & 0xFF000000) >> 24);
+ output[firstByte] = (byte) ((value & 0xFF000000) >> 24);
output[firstByte + 1] = (byte) ((value & 0xFF0000) >> 16);
output[firstByte + 2] = (byte) ((value & 0xFF00) >> 8);
output[firstByte + 3] = (byte) (value & 0xFF);
diff --git a/java/org/apache/coyote/http2/ConnectionSettingsBase.java b/java/org/apache/coyote/http2/ConnectionSettingsBase.java
index bd880f669f..2fa4100f20 100644
--- a/java/org/apache/coyote/http2/ConnectionSettingsBase.java
+++ b/java/org/apache/coyote/http2/ConnectionSettingsBase.java
@@ -34,7 +34,7 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
static final int MAX_WINDOW_SIZE = (1 << 31) - 1;
static final int MIN_MAX_FRAME_SIZE = 1 << 14;
static final int MAX_MAX_FRAME_SIZE = (1 << 24) - 1;
- static final long UNLIMITED = ((long)1 << 32); // Use the maximum possible
+ static final long UNLIMITED = ((long) 1 << 32); // Use the maximum possible
static final int MAX_HEADER_TABLE_SIZE = 1 << 16;
// Defaults (defined by the specification)
@@ -55,47 +55,47 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
ConnectionSettingsBase(String connectionId) {
this.connectionId = connectionId;
// Set up the defaults
- current.put(Setting.HEADER_TABLE_SIZE, Long.valueOf(DEFAULT_HEADER_TABLE_SIZE));
- current.put(Setting.ENABLE_PUSH, Long.valueOf(DEFAULT_ENABLE_PUSH ? 1 : 0));
+ current.put(Setting.HEADER_TABLE_SIZE, Long.valueOf(DEFAULT_HEADER_TABLE_SIZE));
+ current.put(Setting.ENABLE_PUSH, Long.valueOf(DEFAULT_ENABLE_PUSH ? 1 : 0));
current.put(Setting.MAX_CONCURRENT_STREAMS, Long.valueOf(DEFAULT_MAX_CONCURRENT_STREAMS));
- current.put(Setting.INITIAL_WINDOW_SIZE, Long.valueOf(DEFAULT_INITIAL_WINDOW_SIZE));
- current.put(Setting.MAX_FRAME_SIZE, Long.valueOf(DEFAULT_MAX_FRAME_SIZE));
- current.put(Setting.MAX_HEADER_LIST_SIZE, Long.valueOf(DEFAULT_MAX_HEADER_LIST_SIZE));
- current.put(Setting.NO_RFC7540_PRIORITIES, Long.valueOf(DEFAULT_NO_RFC7540_PRIORITIES));
+ current.put(Setting.INITIAL_WINDOW_SIZE, Long.valueOf(DEFAULT_INITIAL_WINDOW_SIZE));
+ current.put(Setting.MAX_FRAME_SIZE, Long.valueOf(DEFAULT_MAX_FRAME_SIZE));
+ current.put(Setting.MAX_HEADER_LIST_SIZE, Long.valueOf(DEFAULT_MAX_HEADER_LIST_SIZE));
+ current.put(Setting.NO_RFC7540_PRIORITIES, Long.valueOf(DEFAULT_NO_RFC7540_PRIORITIES));
}
final void set(Setting setting, long value) throws T {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("connectionSettings.debug",
- connectionId, getEndpointName(), setting, Long.toString(value)));
+ log.debug(sm.getString("connectionSettings.debug", connectionId, getEndpointName(), setting,
+ Long.toString(value)));
}
- switch(setting) {
- case HEADER_TABLE_SIZE:
- validateHeaderTableSize(value);
- break;
- case ENABLE_PUSH:
- validateEnablePush(value);
- break;
- case MAX_CONCURRENT_STREAMS:
- // No further validation required
- break;
- case INITIAL_WINDOW_SIZE:
- validateInitialWindowSize(value);
- break;
- case MAX_FRAME_SIZE:
- validateMaxFrameSize(value);
- break;
- case MAX_HEADER_LIST_SIZE:
- // No further validation required
- break;
- case NO_RFC7540_PRIORITIES:
- validateNoRfc7540Priorities(value);
- break;
- case UNKNOWN:
- // Unrecognised. Ignore it.
- return;
+ switch (setting) {
+ case HEADER_TABLE_SIZE:
+ validateHeaderTableSize(value);
+ break;
+ case ENABLE_PUSH:
+ validateEnablePush(value);
+ break;
+ case MAX_CONCURRENT_STREAMS:
+ // No further validation required
+ break;
+ case INITIAL_WINDOW_SIZE:
+ validateInitialWindowSize(value);
+ break;
+ case MAX_FRAME_SIZE:
+ validateMaxFrameSize(value);
+ break;
+ case MAX_HEADER_LIST_SIZE:
+ // No further validation required
+ break;
+ case NO_RFC7540_PRIORITIES:
+ validateNoRfc7540Priorities(value);
+ break;
+ case UNKNOWN:
+ // Unrecognised. Ignore it.
+ return;
}
set(setting, Long.valueOf(value));
@@ -182,8 +182,8 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
private void validateHeaderTableSize(long headerTableSize) throws T {
if (headerTableSize > MAX_HEADER_TABLE_SIZE) {
- String msg = sm.getString("connectionSettings.headerTableSizeLimit",
- connectionId, Long.toString(headerTableSize));
+ String msg = sm.getString("connectionSettings.headerTableSizeLimit", connectionId,
+ Long.toString(headerTableSize));
throwException(msg, Http2Error.PROTOCOL_ERROR);
}
}
@@ -193,8 +193,7 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
// Can't be less than zero since the result of the byte->long conversion
// will never be negative
if (enablePush > 1) {
- String msg = sm.getString("connectionSettings.enablePushInvalid",
- connectionId, Long.toString(enablePush));
+ String msg = sm.getString("connectionSettings.enablePushInvalid", connectionId, Long.toString(enablePush));
throwException(msg, Http2Error.PROTOCOL_ERROR);
}
}
@@ -202,8 +201,8 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
private void validateInitialWindowSize(long initialWindowSize) throws T {
if (initialWindowSize > MAX_WINDOW_SIZE) {
- String msg = sm.getString("connectionSettings.windowSizeTooBig",
- connectionId, Long.toString(initialWindowSize), Long.toString(MAX_WINDOW_SIZE));
+ String msg = sm.getString("connectionSettings.windowSizeTooBig", connectionId,
+ Long.toString(initialWindowSize), Long.toString(MAX_WINDOW_SIZE));
throwException(msg, Http2Error.FLOW_CONTROL_ERROR);
}
}
@@ -211,8 +210,8 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
private void validateMaxFrameSize(long maxFrameSize) throws T {
if (maxFrameSize < MIN_MAX_FRAME_SIZE || maxFrameSize > MAX_MAX_FRAME_SIZE) {
- String msg = sm.getString("connectionSettings.maxFrameSizeInvalid",
- connectionId, Long.toString(maxFrameSize), Integer.toString(MIN_MAX_FRAME_SIZE),
+ String msg = sm.getString("connectionSettings.maxFrameSizeInvalid", connectionId,
+ Long.toString(maxFrameSize), Integer.toString(MIN_MAX_FRAME_SIZE),
Integer.toString(MAX_MAX_FRAME_SIZE));
throwException(msg, Http2Error.PROTOCOL_ERROR);
}
@@ -221,8 +220,8 @@ abstract class ConnectionSettingsBase<T extends Throwable> {
private void validateNoRfc7540Priorities(long noRfc7540Priorities) throws T {
if (noRfc7540Priorities < 0 || noRfc7540Priorities > 1) {
- String msg = sm.getString("connectionSettings.noRfc7540PrioritiesInvalid",
- connectionId, Long.toString(noRfc7540Priorities));
+ String msg = sm.getString("connectionSettings.noRfc7540PrioritiesInvalid", connectionId,
+ Long.toString(noRfc7540Priorities));
throwException(msg, Http2Error.PROTOCOL_ERROR);
}
}
diff --git a/java/org/apache/coyote/http2/ConnectionSettingsLocal.java b/java/org/apache/coyote/http2/ConnectionSettingsLocal.java
index 64e68bb1b8..8fecf37136 100644
--- a/java/org/apache/coyote/http2/ConnectionSettingsLocal.java
+++ b/java/org/apache/coyote/http2/ConnectionSettingsLocal.java
@@ -19,16 +19,13 @@ package org.apache.coyote.http2;
import java.util.Map;
/**
- * Represents the local connection settings i.e. the settings the client is
- * expected to use when communicating with the server. There will be a delay
- * between calling a setter and the setting taking effect at the client. When a
- * setter is called, the new value is added to the set of pending settings. Once
- * the ACK is received, the new value is moved to the current settings. While
- * waiting for the ACK, the getters will return the most lenient / generous /
- * relaxed of the current setting and the pending setting. This class does not
- * validate the values passed to the setters. If an invalid value is used the
- * client will respond (almost certainly by closing the connection) as defined
- * in the HTTP/2 specification.
+ * Represents the local connection settings i.e. the settings the client is expected to use when communicating with the
+ * server. There will be a delay between calling a setter and the setting taking effect at the client. When a setter is
+ * called, the new value is added to the set of pending settings. Once the ACK is received, the new value is moved to
+ * the current settings. While waiting for the ACK, the getters will return the most lenient / generous / relaxed of the
+ * current setting and the pending setting. This class does not validate the values passed to the setters. If an invalid
+ * value is used the client will respond (almost certainly by closing the connection) as defined in the HTTP/2
+ * specification.
*/
class ConnectionSettingsLocal extends ConnectionSettingsBase<IllegalArgumentException> {
@@ -64,7 +61,7 @@ class ConnectionSettingsLocal extends ConnectionSettingsBase<IllegalArgumentExce
// Stream is zero
// Payload
int pos = 9;
- for (Map.Entry<Setting,Long> setting : pending.entrySet()) {
+ for (Map.Entry<Setting, Long> setting : pending.entrySet()) {
ByteUtil.setTwoBytes(result, pos, setting.getKey().getId());
pos += 2;
ByteUtil.setFourBytes(result, pos, setting.getValue().longValue());
diff --git a/java/org/apache/coyote/http2/ConnectionSettingsRemote.java b/java/org/apache/coyote/http2/ConnectionSettingsRemote.java
index 235446a686..6b3c0aba2b 100644
--- a/java/org/apache/coyote/http2/ConnectionSettingsRemote.java
+++ b/java/org/apache/coyote/http2/ConnectionSettingsRemote.java
@@ -17,8 +17,7 @@
package org.apache.coyote.http2;
/**
- * Represents the remote connection settings: i.e. the settings the server must
- * use when communicating with the client.
+ * Represents the remote connection settings: i.e. the settings the server must use when communicating with the client.
*/
class ConnectionSettingsRemote extends ConnectionSettingsBase<ConnectionException> {
diff --git a/java/org/apache/coyote/http2/FrameType.java b/java/org/apache/coyote/http2/FrameType.java
index 64d1fd05f0..dd80903bd9 100644
--- a/java/org/apache/coyote/http2/FrameType.java
+++ b/java/org/apache/coyote/http2/FrameType.java
@@ -45,12 +45,12 @@ enum FrameType {
private final boolean payloadErrorFatal;
- private FrameType(int id, boolean streamZero, boolean streamNonZero,
- IntPredicate payloadSizeValidator, boolean payloadErrorFatal) {
+ private FrameType(int id, boolean streamZero, boolean streamNonZero, IntPredicate payloadSizeValidator,
+ boolean payloadErrorFatal) {
this.id = id;
this.streamZero = streamZero;
this.streamNonZero = streamNonZero;
- this.payloadSizeValidator = payloadSizeValidator;
+ this.payloadSizeValidator = payloadSizeValidator;
this.payloadErrorFatal = payloadErrorFatal;
}
@@ -68,19 +68,18 @@ enum FrameType {
void check(int streamId, int payloadSize) throws Http2Exception {
// Is FrameType valid for the given stream?
if (streamId == 0 && !streamZero || streamId != 0 && !streamNonZero) {
- throw new ConnectionException(sm.getString("frameType.checkStream", this),
- Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("frameType.checkStream", this), Http2Error.PROTOCOL_ERROR);
}
// Is the payload size valid for the given FrameType
if (payloadSizeValidator != null && !payloadSizeValidator.test(payloadSize)) {
if (payloadErrorFatal || streamId == 0) {
- throw new ConnectionException(sm.getString("frameType.checkPayloadSize",
- Integer.toString(payloadSize), this),
+ throw new ConnectionException(
+ sm.getString("frameType.checkPayloadSize", Integer.toString(payloadSize), this),
Http2Error.FRAME_SIZE_ERROR);
} else {
- throw new StreamException(sm.getString("frameType.checkPayloadSize",
- Integer.toString(payloadSize), this),
+ throw new StreamException(
+ sm.getString("frameType.checkPayloadSize", Integer.toString(payloadSize), this),
Http2Error.FRAME_SIZE_ERROR, streamId);
}
}
@@ -88,31 +87,31 @@ enum FrameType {
static FrameType valueOf(int i) {
- switch(i) {
- case 0:
- return DATA;
- case 1:
- return HEADERS;
- case 2:
- return PRIORITY;
- case 3:
- return RST;
- case 4:
- return SETTINGS;
- case 5:
- return PUSH_PROMISE;
- case 6:
- return PING;
- case 7:
- return GOAWAY;
- case 8:
- return WINDOW_UPDATE;
- case 9:
- return CONTINUATION;
- case 16:
- return PRIORITY_UPDATE;
- default:
- return UNKNOWN;
+ switch (i) {
+ case 0:
+ return DATA;
+ case 1:
+ return HEADERS;
+ case 2:
+ return PRIORITY;
+ case 3:
+ return RST;
+ case 4:
+ return SETTINGS;
+ case 5:
+ return PUSH_PROMISE;
+ case 6:
+ return PING;
+ case 7:
+ return GOAWAY;
+ case 8:
+ return WINDOW_UPDATE;
+ case 9:
+ return CONTINUATION;
+ case 16:
+ return PRIORITY_UPDATE;
+ default:
+ return UNKNOWN;
}
}
}
diff --git a/java/org/apache/coyote/http2/HPackHuffman.java b/java/org/apache/coyote/http2/HPackHuffman.java
index 1bdc9a0c9e..e5ce4826ba 100644
--- a/java/org/apache/coyote/http2/HPackHuffman.java
+++ b/java/org/apache/coyote/http2/HPackHuffman.java
@@ -32,8 +32,8 @@ public class HPackHuffman {
/**
* array based tree representation of a huffman code.
* <p/>
- * the high two bytes corresponds to the tree node if the bit is set, and the low two bytes for if it is clear
- * if the high bit is set it is a terminal node, otherwise it contains the next node position.
+ * the high two bytes corresponds to the tree node if the bit is set, and the low two bytes for if it is clear if
+ * the high bit is set it is a terminal node, otherwise it contains the next node position.
*/
private static final int[] DECODING_TABLE;
@@ -305,13 +305,13 @@ public class HPackHuffman {
codes[256] = new HuffmanCode(0x3fffffff, 30);
HUFFMAN_CODES = codes;
- //lengths determined by experimentation, just set it to something large then see how large it actually ends up
+ // lengths determined by experimentation, just set it to something large then see how large it actually ends up
int[] codingTree = new int[256];
- //the current position in the tree
+ // the current position in the tree
int pos = 0;
- int allocated = 1; //the next position to allocate to
- //map of the current state at a given position
- //only used while building the tree
+ int allocated = 1; // the next position to allocate to
+ // map of the current state at a given position
+ // only used while building the tree
HuffmanCode[] currentCode = new HuffmanCode[256];
currentCode[0] = new HuffmanCode(0, 0);
@@ -327,7 +327,7 @@ public class HPackHuffman {
int newVal = 0;
boolean highTerminal = allCodes.remove(high);
if (highTerminal) {
- //bah, linear search
+ // bah, linear search
int i = 0;
for (i = 0; i < codes.length; ++i) {
if (codes[i].equals(high)) {
@@ -343,7 +343,7 @@ public class HPackHuffman {
newVal <<= 16;
boolean lowTerminal = allCodes.remove(low);
if (lowTerminal) {
- //bah, linear search
+ // bah, linear search
int i = 0;
for (i = 0; i < codes.length; ++i) {
if (codes[i].equals(low)) {
@@ -363,18 +363,16 @@ public class HPackHuffman {
}
/**
- * Decodes a huffman encoded string into the target StringBuilder. There
- * must be enough space left in the buffer for this method to succeed.
+ * Decodes a huffman encoded string into the target StringBuilder. There must be enough space left in the buffer for
+ * this method to succeed.
*
* @param data The byte buffer
* @param length The length of data from the buffer to decode
* @param target The target for the decompressed data
*
- * @throws HpackException If the Huffman encoded value in HPACK headers did
- * not end with EOS padding
+ * @throws HpackException If the Huffman encoded value in HPACK headers did not end with EOS padding
*/
- public static void decode(ByteBuffer data, int length, StringBuilder target)
- throws HpackException {
+ public static void decode(ByteBuffer data, int length, StringBuilder target) throws HpackException {
assert data.remaining() >= length;
int treePos = 0;
boolean eosBits = true;
@@ -385,7 +383,7 @@ public class HPackHuffman {
while (bitPos >= 0) {
int val = DECODING_TABLE[treePos];
if (((1 << bitPos) & b) == 0) {
- //bit not set, we want the lower part of the tree
+ // bit not set, we want the lower part of the tree
if ((val & LOW_TERMINAL_BIT) == 0) {
treePos = val & LOW_MASK;
eosBits = false;
@@ -399,7 +397,7 @@ public class HPackHuffman {
if (eosBits) {
eosBitCount++;
}
- //bit not set, we want the lower part of the tree
+ // bit not set, we want the lower part of the tree
if ((val & HIGH_TERMINAL_BIT) == 0) {
treePos = (val >> 16) & LOW_MASK;
} else {
@@ -417,24 +415,22 @@ public class HPackHuffman {
}
}
if (eosBitCount > 7) {
- throw new HpackException(sm.getString(
- "hpackhuffman.stringLiteralTooMuchPadding"));
+ throw new HpackException(sm.getString("hpackhuffman.stringLiteralTooMuchPadding"));
}
if (!eosBits) {
- throw new HpackException(sm.getString(
- "hpackhuffman.huffmanEncodedHpackValueDidNotEndWithEOS"));
+ throw new HpackException(sm.getString("hpackhuffman.huffmanEncodedHpackValueDidNotEndWithEOS"));
}
}
/**
- * Encodes the given string into the buffer. If there is not enough space in
- * the buffer, or the encoded version is bigger than the original it will
- * return false and not modify the buffers position.
+ * Encodes the given string into the buffer. If there is not enough space in the buffer, or the encoded version is
+ * bigger than the original it will return false and not modify the buffers position.
*
- * @param buffer The buffer to encode into
- * @param toEncode The string to encode
+ * @param buffer The buffer to encode into
+ * @param toEncode The string to encode
* @param forceLowercase If the string should be encoded in lower case
+ *
* @return true if encoding succeeded
*/
public static boolean encode(ByteBuffer buffer, String toEncode, boolean forceLowercase) {
@@ -442,17 +438,17 @@ public class HPackHuffman {
return false;
}
int start = buffer.position();
- //this sucks, but we need to put the length first
- //and we don't really have any option but to calculate it in advance to make sure we have left enough room
- //so we end up iterating twice
+ // this sucks, but we need to put the length first
+ // and we don't really have any option but to calculate it in advance to make sure we have left enough room
+ // so we end up iterating twice
int length = 0;
for (int i = 0; i < toEncode.length(); ++i) {
char c = toEncode.charAt(i);
if (c > 255) {
- throw new IllegalArgumentException(sm.getString("hpack.invalidCharacter",
- Character.toString(c), Integer.valueOf(c)));
+ throw new IllegalArgumentException(
+ sm.getString("hpack.invalidCharacter", Character.toString(c), Integer.valueOf(c)));
}
- if(forceLowercase) {
+ if (forceLowercase) {
c = Hpack.toLower(c);
}
HuffmanCode code = HUFFMAN_CODES[c];
@@ -468,16 +464,16 @@ public class HPackHuffman {
byte currentBufferByte = 0;
for (int i = 0; i < toEncode.length(); ++i) {
char c = toEncode.charAt(i);
- if(forceLowercase) {
+ if (forceLowercase) {
c = Hpack.toLower(c);
}
HuffmanCode code = HUFFMAN_CODES[c];
if (code.length + bytePos <= 8) {
- //it fits in the current byte
+ // it fits in the current byte
currentBufferByte |= ((code.value & 0xFF) << 8 - (code.length + bytePos));
bytePos += code.length;
} else {
- //it does not fit, it may need up to 4 bytes
+ // it does not fit, it may need up to 4 bytes
int val = code.value;
int rem = code.length;
while (rem > 0) {
@@ -511,14 +507,14 @@ public class HPackHuffman {
bytePos = 0;
}
if (buffer.position() - start > toEncode.length()) {
- //the encoded version is longer than the original
- //just return false
+ // the encoded version is longer than the original
+ // just return false
buffer.position(start);
return false;
}
}
if (bytePos > 0) {
- //add the EOS bytes if we have not finished on a single byte
+ // add the EOS bytes if we have not finished on a single byte
if (!buffer.hasRemaining()) {
buffer.position(start);
return false;
@@ -583,10 +579,7 @@ public class HPackHuffman {
@Override
public String toString() {
- return "HuffmanCode{" +
- "value=" + value +
- ", length=" + length +
- '}';
+ return "HuffmanCode{" + "value=" + value + ", length=" + length + '}';
}
}
}
diff --git a/java/org/apache/coyote/http2/HeaderSink.java b/java/org/apache/coyote/http2/HeaderSink.java
index d9fe699f6c..791fe57d3f 100644
--- a/java/org/apache/coyote/http2/HeaderSink.java
+++ b/java/org/apache/coyote/http2/HeaderSink.java
@@ -19,9 +19,8 @@ package org.apache.coyote.http2;
import org.apache.coyote.http2.HpackDecoder.HeaderEmitter;
/**
- * Purpose of this class is to silently swallow any headers. It is used once
- * the connection close process has started if headers for new streams are
- * received.
+ * Purpose of this class is to silently swallow any headers. It is used once the connection close process has started if
+ * headers for new streams are received.
*/
class HeaderSink implements HeaderEmitter {
diff --git a/java/org/apache/coyote/http2/Hpack.java b/java/org/apache/coyote/http2/Hpack.java
index aa3ed7b37c..b0ec92e97c 100644
--- a/java/org/apache/coyote/http2/Hpack.java
+++ b/java/org/apache/coyote/http2/Hpack.java
@@ -26,11 +26,11 @@ final class Hpack {
private static final byte LOWER_DIFF = 'a' - 'A';
static final int DEFAULT_TABLE_SIZE = 4096;
- private static final int MAX_INTEGER_OCTETS = 8; //not sure what a good value for this is, but the spec says we need to provide an upper bound
+ private static final int MAX_INTEGER_OCTETS = 8; // not sure what a good value for this is, but the spec says we
+ // need to provide an upper bound
/**
- * table that contains powers of two,
- * used as both bitmask and to quickly calculate 2^n
+ * table that contains powers of two, used as both bitmask and to quickly calculate 2^n
*/
private static final int[] PREFIX_TABLE;
@@ -50,7 +50,7 @@ final class Hpack {
}
HeaderField[] fields = new HeaderField[62];
- //note that zero is not used
+ // note that zero is not used
fields[1] = new HeaderField(":authority", null);
fields[2] = new HeaderField(":method", "GET");
fields[3] = new HeaderField(":method", "POST");
@@ -133,14 +133,14 @@ final class Hpack {
}
/**
- * Decodes an integer in the HPACK prefix format. If the return value is -1
- * it means that there was not enough data in the buffer to complete the decoding
- * sequence.
+ * Decodes an integer in the HPACK prefix format. If the return value is -1 it means that there was not enough data
+ * in the buffer to complete the decoding sequence.
* <p/>
* If this method returns -1 then the source buffer will not have been modified.
*
* @param source The buffer that contains the integer
* @param n The encoding prefix length
+ *
* @return The encoded integer, or -1 if there was not enough data
*/
static int decodeInteger(ByteBuffer source, int n) throws HpackException {
@@ -158,13 +158,13 @@ final class Hpack {
} else {
int m = 0;
do {
- if(count++ > MAX_INTEGER_OCTETS) {
- throw new HpackException(sm.getString("hpack.integerEncodedOverTooManyOctets",
- Integer.valueOf(MAX_INTEGER_OCTETS)));
+ if (count++ > MAX_INTEGER_OCTETS) {
+ throw new HpackException(
+ sm.getString("hpack.integerEncodedOverTooManyOctets", Integer.valueOf(MAX_INTEGER_OCTETS)));
}
if (source.remaining() == 0) {
- //we have run out of data
- //reset
+ // we have run out of data
+ // reset
source.position(sp);
return -1;
}
@@ -179,9 +179,8 @@ final class Hpack {
/**
* Encodes an integer in the HPACK prefix format.
* <p/>
- * This method assumes that the buffer has already had the first 8-n bits filled.
- * As such it will modify the last byte that is already present in the buffer, and
- * potentially add more if required
+ * This method assumes that the buffer has already had the first 8-n bits filled. As such it will modify the last
+ * byte that is already present in the buffer, and potentially add more if required
*
* @param source The buffer that contains the integer
* @param value The integer to encode
@@ -211,6 +210,7 @@ final class Hpack {
return c;
}
- private Hpack() {}
+ private Hpack() {
+ }
}
diff --git a/java/org/apache/coyote/http2/HpackDecoder.java b/java/org/apache/coyote/http2/HpackDecoder.java
index 7cd5a13f0b..4372b3fa39 100644
--- a/java/org/apache/coyote/http2/HpackDecoder.java
+++ b/java/org/apache/coyote/http2/HpackDecoder.java
@@ -43,9 +43,8 @@ public class HpackDecoder {
private Hpack.HeaderField[] headerTable;
/**
- * The current HEAD position of the header table. We use a ring buffer type
- * construct as it would be silly to actually shuffle the items around in the
- * array.
+ * The current HEAD position of the header table. We use a ring buffer type construct as it would be silly to
+ * actually shuffle the items around in the array.
*/
private int firstSlotPosition = 0;
@@ -86,9 +85,8 @@ public class HpackDecoder {
}
/**
- * Decodes the provided frame data. If this method leaves data in the buffer
- * then this buffer should be compacted so this data is preserved, unless
- * there is no more data in which case this should be considered a protocol error.
+ * Decodes the provided frame data. If this method leaves data in the buffer then this buffer should be compacted so
+ * this data is preserved, unless there is no more data in which case this should be considered a protocol error.
*
* @param buffer The buffer
*
@@ -99,19 +97,18 @@ public class HpackDecoder {
int originalPos = buffer.position();
byte b = buffer.get();
if ((b & 0b10000000) != 0) {
- //if the first bit is set it is an indexed header field
- buffer.position(buffer.position() - 1); //unget the byte
- int index = Hpack.decodeInteger(buffer, 7); //prefix is 7
+ // if the first bit is set it is an indexed header field
+ buffer.position(buffer.position() - 1); // unget the byte
+ int index = Hpack.decodeInteger(buffer, 7); // prefix is 7
if (index == -1) {
buffer.position(originalPos);
return;
- } else if(index == 0) {
- throw new HpackException(
- sm.getString("hpackdecoder.zeroNotValidHeaderTableIndex"));
+ } else if (index == 0) {
+ throw new HpackException(sm.getString("hpackdecoder.zeroNotValidHeaderTableIndex"));
}
handleIndex(index);
} else if ((b & 0b01000000) != 0) {
- //Literal Header Field with Incremental Indexing
+ // Literal Header Field with Incremental Indexing
String headerName = readHeaderName(buffer, 6);
if (headerName == null) {
buffer.position(originalPos);
@@ -125,7 +122,7 @@ public class HpackDecoder {
emitHeader(headerName, headerValue);
addEntryToHeaderTable(new Hpack.HeaderField(headerName, headerValue));
} else if ((b & 0b11110000) == 0) {
- //Literal Header Field without Indexing
+ // Literal Header Field without Indexing
String headerName = readHeaderName(buffer, 4);
if (headerName == null) {
buffer.position(originalPos);
@@ -138,7 +135,7 @@ public class HpackDecoder {
}
emitHeader(headerName, headerValue);
} else if ((b & 0b11110000) == 0b00010000) {
- //Literal Header Field never indexed
+ // Literal Header Field never indexed
String headerName = readHeaderName(buffer, 4);
if (headerName == null) {
buffer.position(originalPos);
@@ -151,7 +148,7 @@ public class HpackDecoder {
}
emitHeader(headerName, headerValue);
} else if ((b & 0b11100000) == 0b00100000) {
- //context update max table size change
+ // context update max table size change
if (!handleMaxMemorySizeChange(buffer, originalPos)) {
return;
}
@@ -165,15 +162,15 @@ public class HpackDecoder {
if (headerCount != 0) {
throw new HpackException(sm.getString("hpackdecoder.tableSizeUpdateNotAtStart"));
}
- buffer.position(buffer.position() - 1); //unget the byte
+ buffer.position(buffer.position() - 1); // unget the byte
int size = Hpack.decodeInteger(buffer, 5);
if (size == -1) {
buffer.position(originalPos);
return false;
}
if (size > maxMemorySizeHard) {
- throw new HpackException(sm.getString("hpackdecoder.maxMemorySizeExceeded",
- Integer.valueOf(size), Integer.valueOf(maxMemorySizeHard)));
+ throw new HpackException(sm.getString("hpackdecoder.maxMemorySizeExceeded", Integer.valueOf(size),
+ Integer.valueOf(maxMemorySizeHard)));
}
maxMemorySizeSoft = size;
if (currentMemorySize > maxMemorySizeSoft) {
@@ -198,7 +195,7 @@ public class HpackDecoder {
}
private String readHeaderName(ByteBuffer buffer, int prefixLength) throws HpackException {
- buffer.position(buffer.position() - 1); //unget the byte
+ buffer.position(buffer.position() - 1); // unget the byte
int index = Hpack.decodeInteger(buffer, prefixLength);
if (index == -1) {
return null;
@@ -242,9 +239,8 @@ public class HpackDecoder {
} else {
// index is 1 based
if (index > Hpack.STATIC_TABLE_LENGTH + filledTableSlots) {
- throw new HpackException(sm.getString("hpackdecoder.headerTableIndexInvalid",
- Integer.valueOf(index), Integer.valueOf(Hpack.STATIC_TABLE_LENGTH),
- Integer.valueOf(filledTableSlots)));
+ throw new HpackException(sm.getString("hpackdecoder.headerTableIndexInvalid", Integer.valueOf(index),
+ Integer.valueOf(Hpack.STATIC_TABLE_LENGTH), Integer.valueOf(filledTableSlots)));
}
int adjustedIndex = getRealIndex(index - Hpack.STATIC_TABLE_LENGTH);
Hpack.HeaderField res = headerTable[adjustedIndex];
@@ -259,6 +255,7 @@ public class HpackDecoder {
* Handle an indexed header representation
*
* @param index The index
+ *
* @throws HpackException If an error occurs processing the given index
*/
private void handleIndex(int index) throws HpackException {
@@ -275,29 +272,29 @@ public class HpackDecoder {
}
/**
- * because we use a ring buffer type construct, and don't actually shuffle
- * items in the array, we need to figure out the real index to use.
+ * because we use a ring buffer type construct, and don't actually shuffle items in the array, we need to figure out
+ * the real index to use.
* <p/>
* package private for unit tests
*
* @param index The index from the hpack
+ *
* @return the real index into the array
*/
int getRealIndex(int index) throws HpackException {
- //the index is one based, but our table is zero based, hence -1
- //also because of our ring buffer setup the indexes are reversed
- //index = 1 is at position firstSlotPosition + filledSlots
+ // the index is one based, but our table is zero based, hence -1
+ // also because of our ring buffer setup the indexes are reversed
+ // index = 1 is at position firstSlotPosition + filledSlots
int realIndex = (firstSlotPosition + (filledTableSlots - index)) % headerTable.length;
if (realIndex < 0) {
- throw new HpackException(sm.getString("hpackdecoder.headerTableIndexInvalid",
- Integer.valueOf(index), Integer.valueOf(Hpack.STATIC_TABLE_LENGTH),
- Integer.valueOf(filledTableSlots)));
+ throw new HpackException(sm.getString("hpackdecoder.headerTableIndexInvalid", Integer.valueOf(index),
+ Integer.valueOf(Hpack.STATIC_TABLE_LENGTH), Integer.valueOf(filledTableSlots)));
}
return realIndex;
}
private void addStaticTableEntry(int index) throws HpackException {
- //adds an entry from the static table.
+ // adds an entry from the static table.
if (log.isDebugEnabled()) {
log.debug(sm.getString("hpackdecoder.useStatic", Integer.valueOf(index)));
}
@@ -310,7 +307,7 @@ public class HpackDecoder {
if (log.isDebugEnabled()) {
log.debug(sm.getString("hpackdecoder.clearDynamic"));
}
- //it is to big to fit, so we just completely clear the table.
+ // it is to big to fit, so we just completely clear the table.
while (filledTableSlots > 0) {
headerTable[firstSlotPosition] = null;
firstSlotPosition++;
@@ -347,9 +344,9 @@ public class HpackDecoder {
}
private void resizeIfRequired() {
- if(filledTableSlots == headerTable.length) {
- Hpack.HeaderField[] newArray = new Hpack.HeaderField[headerTable.length + 10]; //we only grow slowly
- for(int i = 0; i < headerTable.length; ++i) {
+ if (filledTableSlots == headerTable.length) {
+ Hpack.HeaderField[] newArray = new Hpack.HeaderField[headerTable.length + 10]; // we only grow slowly
+ for (int i = 0; i < headerTable.length; ++i) {
newArray[i] = headerTable[(firstSlotPosition + i) % headerTable.length];
}
firstSlotPosition = 0;
@@ -367,29 +364,26 @@ public class HpackDecoder {
*
* @param name Header name
* @param value Header value
- * @throws HpackException If a header is received that is not compliant
- * with the HTTP/2 specification
+ *
+ * @throws HpackException If a header is received that is not compliant with the HTTP/2 specification
*/
void emitHeader(String name, String value) throws HpackException;
/**
- * Inform the recipient of the headers that a stream error needs to be
- * triggered using the given message when {@link #validateHeaders()} is
- * called. This is used when the Parser becomes aware of an error that
- * is not visible to the recipient.
+ * Inform the recipient of the headers that a stream error needs to be triggered using the given message when
+ * {@link #validateHeaders()} is called. This is used when the Parser becomes aware of an error that is not
+ * visible to the recipient.
*
* @param streamException The exception to use when resetting the stream
*/
void setHeaderException(StreamException streamException);
/**
- * Are the headers pass to the recipient so far valid? The decoder needs
- * to process all the headers to maintain state even if there is a
- * problem. In addition, it is easy for the the intended recipient to
- * track if the complete set of headers is valid since to do that state
- * needs to be maintained between the parsing of the initial headers and
- * the parsing of any trailer headers. The recipient is the best place
- * to maintain that state.
+ * Are the headers pass to the recipient so far valid? The decoder needs to process all the headers to maintain
+ * state even if there is a problem. In addition, it is easy for the the intended recipient to track if the
+ * complete set of headers is valid since to do that state needs to be maintained between the parsing of the
+ * initial headers and the parsing of any trailer headers. The recipient is the best place to maintain that
+ * state.
*
* @throws StreamException If the headers received to date are not valid
*/
@@ -427,11 +421,11 @@ public class HpackDecoder {
// Only count the cookie header once since HTTP/2 splits it into
// multiple headers to aid compression
if (!countedCookie) {
- headerCount ++;
+ headerCount++;
countedCookie = true;
}
} else {
- headerCount ++;
+ headerCount++;
}
// Overhead will vary. The main concern is that lots of small headers
// trigger the limiting mechanism correctly. Therefore, use an overhead
@@ -472,7 +466,7 @@ public class HpackDecoder {
}
- //package private fields for unit tests
+ // package private fields for unit tests
int getFirstSlotPosition() {
return firstSlotPosition;
diff --git a/java/org/apache/coyote/http2/HpackEncoder.java b/java/org/apache/coyote/http2/HpackEncoder.java
index 1de32c632d..a6e92a97c9 100644
--- a/java/org/apache/coyote/http2/HpackEncoder.java
+++ b/java/org/apache/coyote/http2/HpackEncoder.java
@@ -42,8 +42,8 @@ class HpackEncoder {
private static final HpackHeaderFunction DEFAULT_HEADER_FUNCTION = new HpackHeaderFunction() {
@Override
public boolean shouldUseIndexing(String headerName, String value) {
- //content length and date change all the time
- //no need to index them, or they will churn the table
+ // content length and date change all the time
+ // no need to index them, or they will churn the table
switch (headerName) {
case "content-length":
case "date":
@@ -55,12 +55,12 @@ class HpackEncoder {
@Override
public boolean shouldUseHuffman(String header, String value) {
- return value.length() > 5; //TODO: figure out a good value for this
+ return value.length() > 5; // TODO: figure out a good value for this
}
@Override
public boolean shouldUseHuffman(String header) {
- return header.length() > 5; //TODO: figure out a good value for this
+ return header.length() > 5; // TODO: figure out a good value for this
}
@@ -73,13 +73,14 @@ class HpackEncoder {
private int entryPositionCounter;
- private int newMaxHeaderSize = -1; //if the max header size has been changed
- private int minNewMaxHeaderSize = -1; //records the smallest value of newMaxHeaderSize, as per section 4.1
+ private int newMaxHeaderSize = -1; // if the max header size has been changed
+ private int minNewMaxHeaderSize = -1; // records the smallest value of newMaxHeaderSize, as per section 4.1
private static final Map<String, TableEntry[]> ENCODING_STATIC_TABLE;
private final Deque<TableEntry> evictionQueue = new ArrayDeque<>();
- private final Map<String, List<TableEntry>> dynamicTable = new HashMap<>(); //TODO: use a custom data structure to reduce allocations
+ private final Map<String, List<TableEntry>> dynamicTable = new HashMap<>(); // TODO: use a custom data structure to
+ // reduce allocations
static {
Map<String, TableEntry[]> map = new HashMap<>();
@@ -87,7 +88,7 @@ class HpackEncoder {
Hpack.HeaderField m = Hpack.STATIC_TABLE[i];
TableEntry[] existing = map.get(m.name);
if (existing == null) {
- map.put(m.name, new TableEntry[]{new TableEntry(m.name, m.value, i)});
+ map.put(m.name, new TableEntry[] { new TableEntry(m.name, m.value, i) });
} else {
TableEntry[] newEntry = new TableEntry[existing.length + 1];
System.arraycopy(existing, 0, newEntry, 0, existing.length);
@@ -126,7 +127,7 @@ class HpackEncoder {
int it = headersIterator;
if (headersIterator == -1) {
handleTableSizeChange(target);
- //new headers map
+ // new headers map
it = 0;
currentHeaders = headers;
} else {
@@ -148,56 +149,56 @@ class HpackEncoder {
}
}
if (!skip) {
- String val = headers.getValue(it).toString();
+ String val = headers.getValue(it).toString();
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("hpackEncoder.encodeHeader", headerName, val));
- }
- TableEntry tableEntry = findInTable(headerName, val);
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("hpackEncoder.encodeHeader", headerName, val));
+ }
+ TableEntry tableEntry = findInTable(headerName, val);
- // We use 11 to make sure we have enough room for the
- // variable length integers
- int required = 11 + headerName.length() + 1 + val.length();
+ // We use 11 to make sure we have enough room for the
+ // variable length integers
+ int required = 11 + headerName.length() + 1 + val.length();
- if (target.remaining() < required) {
- this.headersIterator = it;
- return State.UNDERFLOW;
- }
- // Only index if it will fit
- boolean canIndex = hpackHeaderFunction.shouldUseIndexing(headerName, val) &&
- (headerName.length() + val.length() + 32) < maxTableSize;
- if (tableEntry == null && canIndex) {
- //add the entry to the dynamic table
- target.put((byte) (1 << 6));
- writeHuffmanEncodableName(target, headerName);
- writeHuffmanEncodableValue(target, headerName, val);
- addToDynamicTable(headerName, val);
- } else if (tableEntry == null) {
- //literal never indexed
- target.put((byte) (1 << 4));
- writeHuffmanEncodableName(target, headerName);
- writeHuffmanEncodableValue(target, headerName, val);
+ if (target.remaining() < required) {
+ this.headersIterator = it;
+ return State.UNDERFLOW;
+ }
+ // Only index if it will fit
+ boolean canIndex = hpackHeaderFunction.shouldUseIndexing(headerName, val) &&
+ (headerName.length() + val.length() + 32) < maxTableSize;
+ if (tableEntry == null && canIndex) {
+ // add the entry to the dynamic table
+ target.put((byte) (1 << 6));
+ writeHuffmanEncodableName(target, headerName);
+ writeHuffmanEncodableValue(target, headerName, val);
+ addToDynamicTable(headerName, val);
+ } else if (tableEntry == null) {
+ // literal never indexed
+ target.put((byte) (1 << 4));
+ writeHuffmanEncodableName(target, headerName);
+ writeHuffmanEncodableValue(target, headerName, val);
+ } else {
+ // so we know something is already in the table
+ if (val.equals(tableEntry.value)) {
+ // the whole thing is in the table
+ target.put((byte) (1 << 7));
+ Hpack.encodeInteger(target, tableEntry.getPosition(), 7);
} else {
- //so we know something is already in the table
- if (val.equals(tableEntry.value)) {
- //the whole thing is in the table
- target.put((byte) (1 << 7));
- Hpack.encodeInteger(target, tableEntry.getPosition(), 7);
+ if (canIndex) {
+ // add the entry to the dynamic table
+ target.put((byte) (1 << 6));
+ Hpack.encodeInteger(target, tableEntry.getPosition(), 6);
+ writeHuffmanEncodableValue(target, headerName, val);
+ addToDynamicTable(headerName, val);
+
} else {
- if (canIndex) {
- //add the entry to the dynamic table
- target.put((byte) (1 << 6));
- Hpack.encodeInteger(target, tableEntry.getPosition(), 6);
- writeHuffmanEncodableValue(target, headerName, val);
- addToDynamicTable(headerName, val);
-
- } else {
- target.put((byte) (1 << 4));
- Hpack.encodeInteger(target, tableEntry.getPosition(), 4);
- writeHuffmanEncodableValue(target, headerName, val);
- }
+ target.put((byte) (1 << 4));
+ Hpack.encodeInteger(target, tableEntry.getPosition(), 4);
+ writeHuffmanEncodableValue(target, headerName, val);
}
}
+ }
}
if (++it == currentHeaders.size() && firstPass) {
@@ -212,11 +213,11 @@ class HpackEncoder {
private void writeHuffmanEncodableName(ByteBuffer target, String headerName) {
if (hpackHeaderFunction.shouldUseHuffman(headerName)) {
- if(HPackHuffman.encode(target, headerName, true)) {
+ if (HPackHuffman.encode(target, headerName, true)) {
return;
}
}
- target.put((byte) 0); //to use encodeInteger we need to place the first byte in the buffer.
+ target.put((byte) 0); // to use encodeInteger we need to place the first byte in the buffer.
Hpack.encodeInteger(target, headerName.length(), 7);
for (int j = 0; j < headerName.length(); ++j) {
target.put((byte) Hpack.toLower(headerName.charAt(j)));
@@ -235,7 +236,7 @@ class HpackEncoder {
}
private void writeValueString(ByteBuffer target, String val) {
- target.put((byte) 0); //to use encodeInteger we need to place the first byte in the buffer.
+ target.put((byte) 0); // to use encodeInteger we need to place the first byte in the buffer.
Hpack.encodeInteger(target, val.length(), 7);
for (int j = 0; j < val.length(); ++j) {
target.put((byte) val.charAt(j));
@@ -250,7 +251,7 @@ class HpackEncoder {
currentTableSize += d.getSize();
runEvictionIfRequired();
if (entryPositionCounter == Integer.MAX_VALUE) {
- //prevent rollover
+ // prevent rollover
preventPositionRollover();
}
@@ -258,8 +259,8 @@ class HpackEncoder {
private void preventPositionRollover() {
- //if the position counter is about to roll over we iterate all the table entries
- //and set their position to their actual position
+ // if the position counter is about to roll over we iterate all the table entries
+ // and set their position to their actual position
for (List<TableEntry> tableEntries : dynamicTable.values()) {
for (TableEntry t : tableEntries) {
t.position = t.getPosition();
@@ -288,7 +289,7 @@ class HpackEncoder {
TableEntry[] staticTable = ENCODING_STATIC_TABLE.get(headerName);
if (staticTable != null) {
for (TableEntry st : staticTable) {
- if (st.value != null && st.value.equals(value)) { //todo: some form of lookup?
+ if (st.value != null && st.value.equals(value)) { // todo: some form of lookup?
return st;
}
}
@@ -296,7 +297,7 @@ class HpackEncoder {
List<TableEntry> dynamic = dynamicTable.get(headerName);
if (dynamic != null) {
for (TableEntry st : dynamic) {
- if (st.value.equals(value)) { //todo: some form of lookup?
+ if (st.value.equals(value)) { // todo: some form of lookup?
return st;
}
}
@@ -384,6 +385,7 @@ class HpackEncoder {
*
* @param header The header name
* @param value The header value to be encoded
+ *
* @return <code>true</code> if the value should be encoded
*/
boolean shouldUseHuffman(String header, String value);
@@ -392,6 +394,7 @@ class HpackEncoder {
* Returns true if huffman encoding should be used on the header name
*
* @param header The header name to be encoded
+ *
* @return <code>true</code> if the value should be encoded
*/
boolean shouldUseHuffman(String header);
diff --git a/java/org/apache/coyote/http2/HpackException.java b/java/org/apache/coyote/http2/HpackException.java
index f5dd55c56b..40629af6fa 100644
--- a/java/org/apache/coyote/http2/HpackException.java
+++ b/java/org/apache/coyote/http2/HpackException.java
@@ -17,8 +17,7 @@
package org.apache.coyote.http2;
/**
- * Exception that is thrown when the HPACK compress context is broken. In this
- * case the connection must be closed.
+ * Exception that is thrown when the HPACK compress context is broken. In this case the connection must be closed.
*/
class HpackException extends Exception {
@@ -27,6 +26,7 @@ class HpackException extends Exception {
HpackException(String message) {
super(message);
}
+
HpackException() {
super();
}
diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java
index e05eeea4a2..57f1cc27c0 100644
--- a/java/org/apache/coyote/http2/Http2AsyncParser.java
+++ b/java/org/apache/coyote/http2/Http2AsyncParser.java
@@ -37,7 +37,8 @@ class Http2AsyncParser extends Http2Parser {
private final Http2AsyncUpgradeHandler upgradeHandler;
private volatile Throwable error = null;
- Http2AsyncParser(String connectionId, Input input, Output output, SocketWrapperBase<?> socketWrapper, Http2AsyncUpgradeHandler upgradeHandler) {
+ Http2AsyncParser(String connectionId, Input input, Output output, SocketWrapperBase<?> socketWrapper,
+ Http2AsyncUpgradeHandler upgradeHandler) {
super(connectionId, input, output);
this.socketWrapper = socketWrapper;
socketWrapper.getSocketBufferHandler().expand(input.getMaxFrameSize());
@@ -51,9 +52,10 @@ class Http2AsyncParser extends Http2Parser {
ByteBuffer preface = ByteBuffer.wrap(prefaceData);
ByteBuffer header = ByteBuffer.allocate(9);
ByteBuffer framePayload = ByteBuffer.allocate(input.getMaxFrameSize());
- PrefaceCompletionHandler handler = new PrefaceCompletionHandler(webConnection, stream, prefaceData, preface, header, framePayload);
- socketWrapper.read(BlockingMode.NON_BLOCK, socketWrapper.getReadTimeout(), TimeUnit.MILLISECONDS, null,
- handler, handler, preface, header, framePayload);
+ PrefaceCompletionHandler handler = new PrefaceCompletionHandler(webConnection, stream, prefaceData, preface,
+ header, framePayload);
+ socketWrapper.read(BlockingMode.NON_BLOCK, socketWrapper.getReadTimeout(), TimeUnit.MILLISECONDS, null, handler,
+ handler, preface, header, framePayload);
}
@@ -65,7 +67,8 @@ class Http2AsyncParser extends Http2Parser {
private volatile boolean prefaceValidated = false;
- private PrefaceCompletionHandler(WebConnection webConnection, Stream stream, byte[] prefaceData, ByteBuffer... buffers) {
+ private PrefaceCompletionHandler(WebConnection webConnection, Stream stream, byte[] prefaceData,
+ ByteBuffer... buffers) {
super(FrameType.SETTINGS, buffers);
this.webConnection = webConnection;
this.stream = stream;
@@ -120,7 +123,8 @@ class Http2AsyncParser extends Http2Parser {
// Finish processing the connection
upgradeHandler.processConnectionCallback(webConnection, stream);
} else {
- upgradeHandler.closeConnection(new ConnectionException(error.getMessage(), Http2Error.PROTOCOL_ERROR, error));
+ upgradeHandler
+ .closeConnection(new ConnectionException(error.getMessage(), Http2Error.PROTOCOL_ERROR, error));
}
// Continue reading frames
upgradeHandler.upgradeDispatch(SocketEvent.OPEN_READ);
@@ -128,16 +132,14 @@ class Http2AsyncParser extends Http2Parser {
}
@Override
- protected boolean readFrame(boolean block, FrameType expected)
- throws IOException, Http2Exception {
+ protected boolean readFrame(boolean block, FrameType expected) throws IOException, Http2Exception {
handleAsyncException();
ByteBuffer header = ByteBuffer.allocate(9);
ByteBuffer framePayload = ByteBuffer.allocate(input.getMaxFrameSize());
FrameCompletionHandler handler = new FrameCompletionHandler(expected, header, framePayload);
- CompletionState state = socketWrapper.read(
- block ? BlockingMode.BLOCK : BlockingMode.NON_BLOCK,
- block ? socketWrapper.getReadTimeout() : 0,
- TimeUnit.MILLISECONDS, null, handler, handler, header, framePayload);
+ CompletionState state = socketWrapper.read(block ? BlockingMode.BLOCK : BlockingMode.NON_BLOCK,
+ block ? socketWrapper.getReadTimeout() : 0, TimeUnit.MILLISECONDS, null, handler, handler, header,
+ framePayload);
if (state == CompletionState.ERROR || state == CompletionState.INLINE) {
handleAsyncException();
return true;
@@ -146,8 +148,7 @@ class Http2AsyncParser extends Http2Parser {
}
}
- private void handleAsyncException()
- throws IOException, Http2Exception {
+ private void handleAsyncException() throws IOException, Http2Exception {
if (error != null) {
Throwable error = this.error;
this.error = null;
@@ -184,8 +185,7 @@ class Http2AsyncParser extends Http2Parser {
}
@Override
- public CompletionHandlerCall callHandler(CompletionState state,
- ByteBuffer[] buffers, int offset, int length) {
+ public CompletionHandlerCall callHandler(CompletionState state, ByteBuffer[] buffers, int offset, int length) {
if (offset != 0 || length != 2) {
try {
throw new IllegalArgumentException(sm.getString("http2Parser.invalidBuffers"));
@@ -197,7 +197,8 @@ class Http2AsyncParser extends Http2Parser {
return validate(state, buffers[0], buffers[1]);
}
- protected CompletionHandlerCall validate(CompletionState state, ByteBuffer frameHeaderBuffer, ByteBuffer payload) {
+ protected CompletionHandlerCall validate(CompletionState state, ByteBuffer frameHeaderBuffer,
+ ByteBuffer payload) {
if (!parsedFrameHeader) {
// The first buffer should be 9 bytes long
if (frameHeaderBuffer.position() < 9) {
@@ -246,41 +247,41 @@ class Http2AsyncParser extends Http2Parser {
swallowPayload(streamId, frameTypeId, payloadSize, false, payload);
} else {
switch (frameType) {
- case DATA:
- readDataFrame(streamId, flags, payloadSize, payload);
- break;
- case HEADERS:
- readHeadersFrame(streamId, flags, payloadSize, payload);
- break;
- case PRIORITY:
- readPriorityFrame(streamId, payload);
- break;
- case RST:
- readRstFrame(streamId, payload);
- break;
- case SETTINGS:
- readSettingsFrame(flags, payloadSize, payload);
- break;
- case PUSH_PROMISE:
- readPushPromiseFrame(streamId, flags, payloadSize, payload);
- break;
- case PING:
- readPingFrame(flags, payload);
- break;
- case GOAWAY:
- readGoawayFrame(payloadSize, payload);
- break;
- case WINDOW_UPDATE:
- readWindowUpdateFrame(streamId, payload);
- break;
- case CONTINUATION:
- readContinuationFrame(streamId, flags, payloadSize, payload);
- break;
- case PRIORITY_UPDATE:
- readPriorityUpdateFrame(payloadSize, payload);
- break;
- case UNKNOWN:
- readUnknownFrame(streamId, frameTypeId, flags, payloadSize, payload);
+ case DATA:
+ readDataFrame(streamId, flags, payloadSize, payload);
+ break;
+ case HEADERS:
+ readHeadersFrame(streamId, flags, payloadSize, payload);
+ break;
+ case PRIORITY:
+ readPriorityFrame(streamId, payload);
+ break;
+ case RST:
+ readRstFrame(streamId, payload);
+ break;
+ case SETTINGS:
+ readSettingsFrame(flags, payloadSize, payload);
+ break;
+ case PUSH_PROMISE:
+ readPushPromiseFrame(streamId, flags, payloadSize, payload);
+ break;
+ case PING:
+ readPingFrame(flags, payload);
+ break;
+ case GOAWAY:
+ readGoawayFrame(payloadSize, payload);
+ break;
+ case WINDOW_UPDATE:
+ readWindowUpdateFrame(streamId, payload);
+ break;
+ case CONTINUATION:
+ readContinuationFrame(streamId, flags, payloadSize, payload);
+ break;
+ case PRIORITY_UPDATE:
+ readPriorityUpdateFrame(payloadSize, payload);
+ break;
+ case UNKNOWN:
+ readUnknownFrame(streamId, frameTypeId, flags, payloadSize, payload);
}
}
// See if there is a new 9 byte header and continue parsing if possible
diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java
index ce230b7de5..1deee89072 100644
--- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java
@@ -50,8 +50,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
private final AtomicReference<Throwable> error = new AtomicReference<>();
private final AtomicReference<IOException> applicationIOE = new AtomicReference<>();
- public Http2AsyncUpgradeHandler(Http2Protocol protocol, Adapter adapter,
- Request coyoteRequest, SocketWrapperBase<?> socketWrapper) {
+ public Http2AsyncUpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest,
+ SocketWrapperBase<?> socketWrapper) {
super(protocol, adapter, coyoteRequest, socketWrapper);
}
@@ -59,6 +59,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
@Override
public void completed(Long result, Void attachment) {
}
+
@Override
public void failed(Throwable t, Void attachment) {
error.set(t);
@@ -68,6 +69,7 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
@Override
public void completed(Long result, Void attachment) {
}
+
@Override
public void failed(Throwable t, Void attachment) {
if (t instanceof IOException) {
@@ -96,21 +98,19 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
@Override
- protected void processConnection(WebConnection webConnection,
- Stream stream) {
+ protected void processConnection(WebConnection webConnection, Stream stream) {
// The end of the processing will instead be an async callback
}
- void processConnectionCallback(WebConnection webConnection,
- Stream stream) {
+ void processConnectionCallback(WebConnection webConnection, Stream stream) {
super.processConnection(webConnection, stream);
}
@Override
protected void writeSettings() {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
ByteBuffer.wrap(localSettings.getSettingsFrameForPending()),
ByteBuffer.wrap(createWindowUpdateForSettings()));
Throwable err = error.get();
@@ -127,8 +127,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
@Override
void sendStreamReset(StreamStateMachine state, StreamException se) throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.rst.debug", connectionId,
- Integer.toString(se.getStreamId()), se.getError(), se.getMessage()));
+ log.debug(sm.getString("upgradeHandler.rst.debug", connectionId, Integer.toString(se.getStreamId()),
+ se.getError(), se.getMessage()));
}
// Write a RST frame
byte[] rstFrame = new byte[13];
@@ -158,17 +158,15 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
}
}
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(rstFrame));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(rstFrame));
}
handleAsyncException();
}
@Override
- protected void writeGoAwayFrame(int maxStreamId, long errorCode, byte[] debugMsg)
- throws IOException {
+ protected void writeGoAwayFrame(int maxStreamId, long errorCode, byte[] debugMsg) throws IOException {
byte[] fixedPayload = new byte[8];
ByteUtil.set31Bits(fixedPayload, 0, maxStreamId);
ByteUtil.setFourBytes(fixedPayload, 4, errorCode);
@@ -179,30 +177,28 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
byte[] payloadLength = new byte[3];
ByteUtil.setThreeBytes(payloadLength, 0, len);
if (debugMsg != null) {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(payloadLength), ByteBuffer.wrap(GOAWAY),
- ByteBuffer.wrap(fixedPayload), ByteBuffer.wrap(debugMsg));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(payloadLength),
+ ByteBuffer.wrap(GOAWAY), ByteBuffer.wrap(fixedPayload), ByteBuffer.wrap(debugMsg));
} else {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(payloadLength), ByteBuffer.wrap(GOAWAY),
- ByteBuffer.wrap(fixedPayload));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(payloadLength),
+ ByteBuffer.wrap(GOAWAY), ByteBuffer.wrap(fixedPayload));
}
handleAsyncException();
}
@Override
- void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders,
- boolean endOfStream, int payloadSize) throws IOException {
+ void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize)
+ throws IOException {
synchronized (headerWriteLock) {
- AsyncHeaderFrameBuffers headerFrameBuffers = (AsyncHeaderFrameBuffers)
- doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize);
+ AsyncHeaderFrameBuffers headerFrameBuffers = (AsyncHeaderFrameBuffers) doWriteHeaders(stream,
+ pushedStreamId, mimeHeaders, endOfStream, payloadSize);
if (headerFrameBuffers != null) {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE,
- applicationErrorCompletion, headerFrameBuffers.bufs.toArray(BYTEBUFFER_ARRAY));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, applicationErrorCompletion,
+ headerFrameBuffers.bufs.toArray(BYTEBUFFER_ARRAY));
handleAsyncException();
}
}
@@ -240,9 +236,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
ByteUtil.set31Bits(header, 5, stream.getIdAsInt());
int orgLimit = data.limit();
data.limit(data.position() + len);
- socketWrapper.write(BlockingMode.BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE,
- applicationErrorCompletion, ByteBuffer.wrap(header), data);
+ socketWrapper.write(BlockingMode.BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, applicationErrorCompletion, ByteBuffer.wrap(header), data);
data.limit(orgLimit);
handleAsyncException();
}
@@ -253,12 +248,12 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
void writeWindowUpdate(AbstractNonZeroStream stream, int increment, boolean applicationInitiated)
throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.windowUpdateConnection",
- getConnectionId(), Integer.valueOf(increment)));
+ log.debug(sm.getString("upgradeHandler.windowUpdateConnection", getConnectionId(),
+ Integer.valueOf(increment)));
}
// Build window update frame for stream 0
byte[] frame = new byte[13];
- ByteUtil.setThreeBytes(frame, 0, 4);
+ ByteUtil.setThreeBytes(frame, 0, 4);
frame[3] = FrameType.WINDOW_UPDATE.getIdByte();
ByteUtil.set31Bits(frame, 9, increment);
boolean neetToWriteConnectionUpdate = true;
@@ -267,24 +262,23 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
int streamIncrement = ((Stream) stream).getWindowUpdateSizeToWrite(increment);
if (streamIncrement > 0) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.windowUpdateStream",
- getConnectionId(), getIdAsString(), Integer.valueOf(streamIncrement)));
+ log.debug(sm.getString("upgradeHandler.windowUpdateStream", getConnectionId(), getIdAsString(),
+ Integer.valueOf(streamIncrement)));
}
byte[] frame2 = new byte[13];
- ByteUtil.setThreeBytes(frame2, 0, 4);
+ ByteUtil.setThreeBytes(frame2, 0, 4);
frame2[3] = FrameType.WINDOW_UPDATE.getIdByte();
ByteUtil.set31Bits(frame2, 9, streamIncrement);
ByteUtil.set31Bits(frame2, 5, stream.getIdAsInt());
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(frame), ByteBuffer.wrap(frame2));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(frame),
+ ByteBuffer.wrap(frame2));
neetToWriteConnectionUpdate = false;
}
}
if (neetToWriteConnectionUpdate) {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(frame));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(frame));
}
handleAsyncException();
}
@@ -298,9 +292,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
log.warn(sm.getString("upgradeHandler.unexpectedAck", connectionId, getIdAsString()));
}
} else {
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion,
- ByteBuffer.wrap(SETTINGS_ACK));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(SETTINGS_ACK));
}
handleAsyncException();
}
@@ -330,22 +323,25 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
sendfile.mappedBuffer = channel.map(MapMode.READ_ONLY, sendfile.pos, sendfile.end - sendfile.pos);
}
// Reserve as much as possible right away
- int reservation = (sendfile.end - sendfile.pos > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) (sendfile.end - sendfile.pos);
- sendfile.streamReservation = sendfile.stream.reserveWindowSize(reservation, true);
+ int reservation = (sendfile.end - sendfile.pos > Integer.MAX_VALUE) ? Integer.MAX_VALUE
+ : (int) (sendfile.end - sendfile.pos);
+ sendfile.streamReservation = sendfile.stream.reserveWindowSize(reservation, true);
sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation, true);
} catch (IOException e) {
return SendfileState.ERROR;
}
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.sendfile.reservation", connectionId, sendfile.stream.getIdAsString(),
- Integer.valueOf(sendfile.connectionReservation), Integer.valueOf(sendfile.streamReservation)));
+ log.debug(sm.getString("upgradeHandler.sendfile.reservation", connectionId,
+ sendfile.stream.getIdAsString(), Integer.valueOf(sendfile.connectionReservation),
+ Integer.valueOf(sendfile.streamReservation)));
}
// connectionReservation will always be smaller than or the same as
// streamReservation
int frameSize = Integer.min(getMaxFrameSize(), sendfile.connectionReservation);
- boolean finished = (frameSize == sendfile.left) && sendfile.stream.getCoyoteResponse().getTrailerFields() == null;
+ boolean finished = (frameSize == sendfile.left) &&
+ sendfile.stream.getCoyoteResponse().getTrailerFields() == null;
// Need to check this now since sending end of stream will change this.
boolean writable = sendfile.stream.canWrite();
@@ -366,9 +362,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
}
ByteUtil.set31Bits(header, 5, sendfile.stream.getIdAsInt());
sendfile.mappedBuffer.limit(sendfile.mappedBuffer.position() + frameSize);
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, sendfile, SocketWrapperBase.COMPLETE_WRITE_WITH_COMPLETION,
- new SendfileCompletionHandler(), ByteBuffer.wrap(header), sendfile.mappedBuffer);
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS,
+ sendfile, SocketWrapperBase.COMPLETE_WRITE_WITH_COMPLETION, new SendfileCompletionHandler(),
+ ByteBuffer.wrap(header), sendfile.mappedBuffer);
try {
handleAsyncException();
} catch (IOException e) {
@@ -388,8 +384,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
long bytesWritten = nBytes.longValue() - 9;
/*
- * Loop for in-line writes only. Avoids a possible stack-overflow of
- * chained completion handlers with a long series of in-line writes.
+ * Loop for in-line writes only. Avoids a possible stack-overflow of chained completion handlers with a long
+ * series of in-line writes.
*/
do {
sendfile.left -= bytesWritten;
@@ -407,25 +403,29 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
try {
if (sendfile.connectionReservation == 0) {
if (sendfile.streamReservation == 0) {
- int reservation = (sendfile.end - sendfile.pos > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) (sendfile.end - sendfile.pos);
+ int reservation = (sendfile.end - sendfile.pos > Integer.MAX_VALUE) ? Integer.MAX_VALUE
+ : (int) (sendfile.end - sendfile.pos);
sendfile.streamReservation = sendfile.stream.reserveWindowSize(reservation, true);
}
- sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation, true);
+ sendfile.connectionReservation = reserveWindowSize(sendfile.stream, sendfile.streamReservation,
+ true);
}
} catch (IOException e) {
- failed (e, sendfile);
+ failed(e, sendfile);
return;
}
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.sendfile.reservation", connectionId, sendfile.stream.getIdAsString(),
- Integer.valueOf(sendfile.connectionReservation), Integer.valueOf(sendfile.streamReservation)));
+ log.debug(sm.getString("upgradeHandler.sendfile.reservation", connectionId,
+ sendfile.stream.getIdAsString(), Integer.valueOf(sendfile.connectionReservation),
+ Integer.valueOf(sendfile.streamReservation)));
}
// connectionReservation will always be smaller than or the same as
// streamReservation
int frameSize = Integer.min(getMaxFrameSize(), sendfile.connectionReservation);
- boolean finished = (frameSize == sendfile.left) && sendfile.stream.getCoyoteResponse().getTrailerFields() == null;
+ boolean finished = (frameSize == sendfile.left) &&
+ sendfile.stream.getCoyoteResponse().getTrailerFields() == null;
// Need to check this now since sending end of stream will change this.
boolean writable = sendfile.stream.canWrite();
@@ -441,17 +441,18 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
}
if (writable) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.writeBody", connectionId, sendfile.stream.getIdAsString(),
- Integer.toString(frameSize), Boolean.valueOf(finished)));
+ log.debug(
+ sm.getString("upgradeHandler.writeBody", connectionId, sendfile.stream.getIdAsString(),
+ Integer.toString(frameSize), Boolean.valueOf(finished)));
}
ByteUtil.set31Bits(header, 5, sendfile.stream.getIdAsInt());
sendfile.mappedBuffer.limit(sendfile.mappedBuffer.position() + frameSize);
// Note: Completion handler not called in the write
- // completes in-line. The wrote will continue via the
- // surrounding loop.
+ // completes in-line. The wrote will continue via the
+ // surrounding loop.
completionState = socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, sendfile, SocketWrapperBase.COMPLETE_WRITE,
- this, ByteBuffer.wrap(header), sendfile.mappedBuffer);
+ TimeUnit.MILLISECONDS, sendfile, SocketWrapperBase.COMPLETE_WRITE, this,
+ ByteBuffer.wrap(header), sendfile.mappedBuffer);
try {
handleAsyncException();
} catch (IOException e) {
@@ -484,9 +485,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
PingRecord pingRecord = new PingRecord(sentSequence, now);
inflightPings.add(pingRecord);
ByteUtil.set31Bits(payload, 4, sentSequence);
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE,
- errorCompletion, ByteBuffer.wrap(PING), ByteBuffer.wrap(payload));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(PING),
+ ByteBuffer.wrap(payload));
handleAsyncException();
}
}
@@ -497,9 +498,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler {
super.receivePing(payload, ack);
} else {
// Client originated ping. Echo it back.
- socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(),
- TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE,
- errorCompletion, ByteBuffer.wrap(PING_ACK), ByteBuffer.wrap(payload));
+ socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null,
+ SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(PING_ACK),
+ ByteBuffer.wrap(payload));
handleAsyncException();
}
}
diff --git a/java/org/apache/coyote/http2/Http2OutputBuffer.java b/java/org/apache/coyote/http2/Http2OutputBuffer.java
index c11596f1e3..1de4569900 100644
--- a/java/org/apache/coyote/http2/Http2OutputBuffer.java
+++ b/java/org/apache/coyote/http2/Http2OutputBuffer.java
@@ -31,13 +31,11 @@ public class Http2OutputBuffer implements HttpOutputBuffer {
/**
- * Add a filter at the start of the existing processing chain. Subsequent
- * calls to the {@link HttpOutputBuffer} methods of this object will be
- * passed to the filter. If appropriate, the filter will then call the same
- * method on the next HttpOutputBuffer in the chain until the call reaches
- * the StreamOutputBuffer.
+ * Add a filter at the start of the existing processing chain. Subsequent calls to the {@link HttpOutputBuffer}
+ * methods of this object will be passed to the filter. If appropriate, the filter will then call the same method on
+ * the next HttpOutputBuffer in the chain until the call reaches the StreamOutputBuffer.
*
- * @param filter The filter to add to the start of the processing chain
+ * @param filter The filter to add to the start of the processing chain
*/
public void addFilter(OutputFilter filter) {
filter.setBuffer(next);
diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java
index bf3689d9c0..267869e064 100644
--- a/java/org/apache/coyote/http2/Http2Parser.java
+++ b/java/org/apache/coyote/http2/Http2Parser.java
@@ -39,8 +39,7 @@ class Http2Parser {
protected static final Log log = LogFactory.getLog(Http2Parser.class);
protected static final StringManager sm = StringManager.getManager(Http2Parser.class);
- static final byte[] CLIENT_PREFACE_START =
- "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1);
+ static final byte[] CLIENT_PREFACE_START = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1);
protected final String connectionId;
protected final Input input;
@@ -48,8 +47,7 @@ class Http2Parser {
private final byte[] frameHeaderBuffer = new byte[9];
private volatile HpackDecoder hpackDecoder;
- private volatile ByteBuffer headerReadBuffer =
- ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE);
+ private volatile ByteBuffer headerReadBuffer = ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE);
private volatile int headersCurrentStream = -1;
private volatile boolean headersEndStream = false;
@@ -61,12 +59,10 @@ class Http2Parser {
/**
- * Read and process a single frame. The initial read is non-blocking to
- * determine if a frame is present. Once the start of a frame is read, the
- * remainder will be read using blocking IO.
+ * Read and process a single frame. The initial read is non-blocking to determine if a frame is present. Once the
+ * start of a frame is read, the remainder will be read using blocking IO.
*
- * @return <code>true</code> if a frame was read otherwise
- * <code>false</code>
+ * @return <code>true</code> if a frame was read otherwise <code>false</code>
*
* @throws IOException If an IO error occurs while trying to read a frame
*/
@@ -75,8 +71,7 @@ class Http2Parser {
}
- protected boolean readFrame(boolean block, FrameType expected)
- throws IOException, Http2Exception {
+ protected boolean readFrame(boolean block, FrameType expected) throws IOException, Http2Exception {
if (!input.fill(block, frameHeaderBuffer)) {
return false;
@@ -96,41 +91,41 @@ class Http2Parser {
}
switch (frameType) {
- case DATA:
- readDataFrame(streamId, flags, payloadSize, null);
- break;
- case HEADERS:
- readHeadersFrame(streamId, flags, payloadSize, null);
- break;
- case PRIORITY:
- readPriorityFrame(streamId, null);
- break;
- case RST:
- readRstFrame(streamId, null);
- break;
- case SETTINGS:
- readSettingsFrame(flags, payloadSize, null);
- break;
- case PUSH_PROMISE:
- readPushPromiseFrame(streamId, flags, payloadSize, null);
- break;
- case PING:
- readPingFrame(flags, null);
- break;
- case GOAWAY:
- readGoawayFrame(payloadSize, null);
- break;
- case WINDOW_UPDATE:
- readWindowUpdateFrame(streamId, null);
- break;
- case CONTINUATION:
- readContinuationFrame(streamId, flags, payloadSize, null);
- break;
- case PRIORITY_UPDATE:
- readPriorityUpdateFrame(payloadSize, null);
- break;
- case UNKNOWN:
- readUnknownFrame(streamId, frameTypeId, flags, payloadSize, null);
+ case DATA:
+ readDataFrame(streamId, flags, payloadSize, null);
+ break;
+ case HEADERS:
+ readHeadersFrame(streamId, flags, payloadSize, null);
+ break;
+ case PRIORITY:
+ readPriorityFrame(streamId, null);
+ break;
+ case RST:
+ readRstFrame(streamId, null);
+ break;
+ case SETTINGS:
+ readSettingsFrame(flags, payloadSize, null);
+ break;
+ case PUSH_PROMISE:
+ readPushPromiseFrame(streamId, flags, payloadSize, null);
+ break;
+ case PING:
+ readPingFrame(flags, null);
+ break;
+ case GOAWAY:
+ readGoawayFrame(payloadSize, null);
+ break;
+ case WINDOW_UPDATE:
+ readWindowUpdateFrame(streamId, null);
+ break;
+ case CONTINUATION:
+ readContinuationFrame(streamId, flags, payloadSize, null);
+ break;
+ case PRIORITY_UPDATE:
+ readPriorityUpdateFrame(payloadSize, null);
+ break;
+ case UNKNOWN:
+ readUnknownFrame(streamId, frameTypeId, flags, payloadSize, null);
}
return true;
@@ -156,8 +151,8 @@ class Http2Parser {
if (padLength >= payloadSize) {
throw new ConnectionException(
sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId,
- Integer.toString(streamId), Integer.toString(padLength),
- Integer.toString(payloadSize)), Http2Error.PROTOCOL_ERROR);
+ Integer.toString(streamId), Integer.toString(padLength), Integer.toString(payloadSize)),
+ Http2Error.PROTOCOL_ERROR);
}
// +1 is for the padding length byte we just read above
dataLength = payloadSize - (padLength + 1);
@@ -172,8 +167,8 @@ class Http2Parser {
} else {
padding = "none";
}
- log.debug(sm.getString("http2Parser.processFrameData.lengths", connectionId,
- Integer.toString(streamId), Integer.toString(dataLength), padding));
+ log.debug(sm.getString("http2Parser.processFrameData.lengths", connectionId, Integer.toString(streamId),
+ Integer.toString(dataLength), padding));
}
ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream);
@@ -256,10 +251,9 @@ class Http2Parser {
if (padding) {
padLength = ByteUtil.getOneByte(optional, optionalPos++);
if (padLength >= payloadSize) {
- throw new ConnectionException(
- sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId,
- Integer.toString(streamId), Integer.toString(padLength),
- Integer.toString(payloadSize)), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId,
+ Integer.toString(streamId), Integer.toString(padLength), Integer.toString(payloadSize)),
+ Http2Error.PROTOCOL_ERROR);
}
}
@@ -311,8 +305,7 @@ class Http2Parser {
protected void readSettingsFrame(int flags, int payloadSize, ByteBuffer buffer) throws Http2Exception, IOException {
boolean ack = Flags.isAck(flags);
if (payloadSize > 0 && ack) {
- throw new ConnectionException(sm.getString(
- "http2Parser.processFrameSettings.ackWithNonZeroPayload"),
+ throw new ConnectionException(sm.getString("http2Parser.processFrameSettings.ackWithNonZeroPayload"),
Http2Error.FRAME_SIZE_ERROR);
}
@@ -332,8 +325,8 @@ class Http2Parser {
long value = ByteUtil.getFourBytes(setting, 2);
Setting key = Setting.valueOf(id);
if (key == Setting.UNKNOWN) {
- log.warn(sm.getString("connectionSettings.unknown",
- connectionId, Integer.toString(id), Long.toString(value)));
+ log.warn(sm.getString("connectionSettings.unknown", connectionId, Integer.toString(id),
+ Long.toString(value)));
}
output.setting(key, value);
}
@@ -343,22 +336,22 @@ class Http2Parser {
/**
- * This default server side implementation always throws an exception. If
- * re-used for client side parsing, this method should be overridden with an
- * appropriate implementation.
+ * This default server side implementation always throws an exception. If re-used for client side parsing, this
+ * method should be overridden with an appropriate implementation.
*
- * @param streamId The pushed stream
- * @param flags The flags set in the frame header
- * @param payloadSize The size of the payload in bytes
- * @param buffer The payload, if available
+ * @param streamId The pushed stream
+ * @param flags The flags set in the frame header
+ * @param payloadSize The size of the payload in bytes
+ * @param buffer The payload, if available
*
* @throws Http2Exception Always
- * @throws IOException May be thrown by sub-classes that parse this frame
+ * @throws IOException May be thrown by sub-classes that parse this frame
*/
protected void readPushPromiseFrame(int streamId, int flags, int payloadSize, ByteBuffer buffer)
throws Http2Exception, IOException {
- throw new ConnectionException(sm.getString("http2Parser.processFramePushPromise",
- connectionId, Integer.valueOf(streamId)), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(
+ sm.getString("http2Parser.processFramePushPromise", connectionId, Integer.valueOf(streamId)),
+ Http2Error.PROTOCOL_ERROR);
}
@@ -409,15 +402,11 @@ class Http2Parser {
// Validate the data
if (windowSizeIncrement == 0) {
if (streamId == 0) {
- throw new ConnectionException(
- sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement",
- connectionId, Integer.toString(streamId)),
- Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement",
+ connectionId, Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
} else {
- throw new StreamException(
- sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement",
- connectionId, Integer.toString(streamId)),
- Http2Error.PROTOCOL_ERROR, streamId);
+ throw new StreamException(sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement",
+ connectionId, Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR, streamId);
}
}
@@ -429,8 +418,7 @@ class Http2Parser {
throws Http2Exception, IOException {
if (headersCurrentStream == -1) {
// No headers to continue
- throw new ConnectionException(sm.getString(
- "http2Parser.processFrameContinuation.notExpected", connectionId,
+ throw new ConnectionException(sm.getString("http2Parser.processFrameContinuation.notExpected", connectionId,
Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
}
@@ -461,8 +449,8 @@ class Http2Parser {
int prioritizedStreamID = ByteUtil.get31Bits(payload, 0);
if (prioritizedStreamID == 0) {
- throw new ConnectionException(
- sm.getString("http2Parser.processFramePriorityUpdate.streamZero"), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.processFramePriorityUpdate.streamZero"),
+ Http2Error.PROTOCOL_ERROR);
}
ByteArrayInputStream bais = new ByteArrayInputStream(payload, 4, payloadSize - 4);
@@ -483,8 +471,8 @@ class Http2Parser {
throws Http2Exception, IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("http2Parser.processFrameHeaders.payload", connectionId,
- Integer.valueOf(streamId), Integer.valueOf(payloadSize)));
+ log.debug(sm.getString("http2Parser.processFrameHeaders.payload", connectionId, Integer.valueOf(streamId),
+ Integer.valueOf(payloadSize)));
}
int remaining = payloadSize;
@@ -519,8 +507,7 @@ class Http2Parser {
try {
hpackDecoder.decode(headerReadBuffer);
} catch (HpackException hpe) {
- throw new ConnectionException(
- sm.getString("http2Parser.processFrameHeaders.decodingFailed"),
+ throw new ConnectionException(sm.getString("http2Parser.processFrameHeaders.decodingFailed"),
Http2Error.COMPRESSION_ERROR, hpe);
}
@@ -529,22 +516,23 @@ class Http2Parser {
remaining -= toRead;
if (hpackDecoder.isHeaderCountExceeded()) {
- StreamException headerException = new StreamException(sm.getString(
- "http2Parser.headerLimitCount", connectionId, Integer.valueOf(streamId)),
+ StreamException headerException = new StreamException(
+ sm.getString("http2Parser.headerLimitCount", connectionId, Integer.valueOf(streamId)),
Http2Error.ENHANCE_YOUR_CALM, streamId);
hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
}
if (hpackDecoder.isHeaderSizeExceeded(headerReadBuffer.position())) {
- StreamException headerException = new StreamException(sm.getString(
- "http2Parser.headerLimitSize", connectionId, Integer.valueOf(streamId)),
+ StreamException headerException = new StreamException(
+ sm.getString("http2Parser.headerLimitSize", connectionId, Integer.valueOf(streamId)),
Http2Error.ENHANCE_YOUR_CALM, streamId);
hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
}
if (hpackDecoder.isHeaderSwallowSizeExceeded(headerReadBuffer.position())) {
- throw new ConnectionException(sm.getString("http2Parser.headerLimitSize",
- connectionId, Integer.valueOf(streamId)), Http2Error.ENHANCE_YOUR_CALM);
+ throw new ConnectionException(
+ sm.getString("http2Parser.headerLimitSize", connectionId, Integer.valueOf(streamId)),
+ Http2Error.ENHANCE_YOUR_CALM);
}
}
}
@@ -566,24 +554,20 @@ class Http2Parser {
/**
* Swallow some or all of the bytes from the payload of an HTTP/2 frame.
*
- * @param streamId Stream being swallowed
- * @param frameTypeId Type of HTTP/2 frame for which the bytes will be
- * swallowed
- * @param len Number of bytes to swallow
- * @param isPadding Are the bytes to be swallowed padding bytes?
- * @param byteBuffer Used with {@link Http2AsyncParser} to access the
- * data that has already been read
+ * @param streamId Stream being swallowed
+ * @param frameTypeId Type of HTTP/2 frame for which the bytes will be swallowed
+ * @param len Number of bytes to swallow
+ * @param isPadding Are the bytes to be swallowed padding bytes?
+ * @param byteBuffer Used with {@link Http2AsyncParser} to access the data that has already been read
*
- * @throws IOException If an I/O error occurs reading additional bytes into
- * the input buffer.
- * @throws ConnectionException If the swallowed bytes are expected to have a
- * value of zero but do not
+ * @throws IOException If an I/O error occurs reading additional bytes into the input buffer.
+ * @throws ConnectionException If the swallowed bytes are expected to have a value of zero but do not
*/
protected void swallowPayload(int streamId, int frameTypeId, int len, boolean isPadding, ByteBuffer byteBuffer)
throws IOException, ConnectionException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("http2Parser.swallow.debug", connectionId,
- Integer.toString(streamId), Integer.toString(len)));
+ log.debug(sm.getString("http2Parser.swallow.debug", connectionId, Integer.toString(streamId),
+ Integer.toString(len)));
}
try {
if (len == 0) {
@@ -607,8 +591,8 @@ class Http2Parser {
// side bug.
for (int i = 0; i < thisTime; i++) {
if (buffer[i] != 0) {
- throw new ConnectionException(sm.getString("http2Parser.nonZeroPadding",
- connectionId, Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.nonZeroPadding", connectionId,
+ Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
}
}
}
@@ -633,8 +617,7 @@ class Http2Parser {
protected void onHeadersComplete(int streamId) throws Http2Exception {
// Any left over data is a compression error
if (headerReadBuffer.position() > 0) {
- throw new ConnectionException(
- sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"),
+ throw new ConnectionException(sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"),
Http2Error.COMPRESSION_ERROR);
}
@@ -660,46 +643,41 @@ class Http2Parser {
/*
- * Implementation note:
- * Validation applicable to all incoming frames should be implemented here.
- * Frame type specific validation should be performed in the appropriate
- * readXxxFrame() method.
- * For validation applicable to some but not all frame types, use your
- * judgement.
+ * Implementation note: Validation applicable to all incoming frames should be implemented here. Frame type specific
+ * validation should be performed in the appropriate readXxxFrame() method. For validation applicable to some but
+ * not all frame types, use your judgement.
*/
- protected void validateFrame(FrameType expected, FrameType frameType, int streamId, int flags,
- int payloadSize) throws Http2Exception {
+ protected void validateFrame(FrameType expected, FrameType frameType, int streamId, int flags, int payloadSize)
+ throws Http2Exception {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("http2Parser.processFrame", connectionId,
- Integer.toString(streamId), frameType, Integer.toString(flags),
- Integer.toString(payloadSize)));
+ log.debug(sm.getString("http2Parser.processFrame", connectionId, Integer.toString(streamId), frameType,
+ Integer.toString(flags), Integer.toString(payloadSize)));
}
if (expected != null && frameType != expected) {
- throw new StreamException(sm.getString("http2Parser.processFrame.unexpectedType",
- expected, frameType), Http2Error.PROTOCOL_ERROR, streamId);
+ throw new StreamException(sm.getString("http2Parser.processFrame.unexpectedType", expected, frameType),
+ Http2Error.PROTOCOL_ERROR, streamId);
}
int maxFrameSize = input.getMaxFrameSize();
if (payloadSize > maxFrameSize) {
- throw new ConnectionException(sm.getString("http2Parser.payloadTooBig",
- Integer.toString(payloadSize), Integer.toString(maxFrameSize)),
- Http2Error.FRAME_SIZE_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.payloadTooBig", Integer.toString(payloadSize),
+ Integer.toString(maxFrameSize)), Http2Error.FRAME_SIZE_ERROR);
}
if (headersCurrentStream != -1) {
if (headersCurrentStream != streamId) {
- throw new ConnectionException(sm.getString("http2Parser.headers.wrongStream",
- connectionId, Integer.toString(headersCurrentStream),
- Integer.toString(streamId)), Http2Error.COMPRESSION_ERROR);
+ throw new ConnectionException(
+ sm.getString("http2Parser.headers.wrongStream", connectionId,
+ Integer.toString(headersCurrentStream), Integer.toString(streamId)),
+ Http2Error.COMPRESSION_ERROR);
}
if (frameType == FrameType.RST) {
// NO-OP: RST is OK here
} else if (frameType != FrameType.CONTINUATION) {
- throw new ConnectionException(sm.getString("http2Parser.headers.wrongFrameType",
- connectionId, Integer.toString(headersCurrentStream),
- frameType), Http2Error.COMPRESSION_ERROR);
+ throw new ConnectionException(sm.getString("http2Parser.headers.wrongFrameType", connectionId,
+ Integer.toString(headersCurrentStream), frameType), Http2Error.COMPRESSION_ERROR);
}
}
@@ -709,8 +687,9 @@ class Http2Parser {
/**
* Read and validate the connection preface from input using blocking IO.
+ *
* @param webConnection The connection
- * @param stream The current stream
+ * @param stream The current stream
*/
void readConnectionPreface(WebConnection webConnection, Stream stream) throws Http2Exception {
byte[] data = new byte[CLIENT_PREFACE_START.length];
@@ -737,21 +716,17 @@ class Http2Parser {
static interface Input {
/**
- * Fill the given array with data unless non-blocking is requested and
- * no data is available. If any data is available then the buffer will
- * be filled using blocking I/O.
+ * Fill the given array with data unless non-blocking is requested and no data is available. If any data is
+ * available then the buffer will be filled using blocking I/O.
*
- * @param block Should the first read into the provided buffer be a
- * blocking read or not.
- * @param data Buffer to fill
+ * @param block Should the first read into the provided buffer be a blocking read or not.
+ * @param data Buffer to fill
* @param offset Position in buffer to start writing
* @param length Number of bytes to read
*
- * @return <code>true</code> if the buffer was filled otherwise
- * <code>false</code>
+ * @return <code>true</code> if the buffer was filled otherwise <code>false</code>
*
- * @throws IOException If an I/O occurred while obtaining data with
- * which to fill the buffer
+ * @throws IOException If an I/O occurred while obtaining data with which to fill the buffer
*/
boolean fill(boolean block, byte[] data, int offset, int length) throws IOException;
@@ -772,8 +747,7 @@ class Http2Parser {
/**
- * Interface that must be implemented to receive notifications from the
- * parser as it processes incoming frames.
+ * Interface that must be implemented to receive notifications from the parser as it processes incoming frames.
*/
static interface Output {
@@ -781,28 +755,29 @@ class Http2Parser {
// Data frames
ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception;
+
void endRequestBodyFrame(int streamId, int dataLength) throws Http2Exception, IOException;
+
void receivedEndOfStream(int streamId) throws ConnectionException;
+
/**
- * Notification triggered when the parser swallows some or all of a DATA
- * frame payload without writing it to the ByteBuffer returned by
- * {@link #startRequestBodyFrame(int, int, boolean)}.
+ * Notification triggered when the parser swallows some or all of a DATA frame payload without writing it to the
+ * ByteBuffer returned by {@link #startRequestBodyFrame(int, int, boolean)}.
*
- * @param streamId The stream on which the payload that has been
- * swallowed was received
- * @param swallowedDataBytesCount The number of bytes that the parser
- * swallowed.
+ * @param streamId The stream on which the payload that has been swallowed was received
+ * @param swallowedDataBytesCount The number of bytes that the parser swallowed.
*
- * @throws ConnectionException If an error fatal to the HTTP/2
- * connection occurs while swallowing the payload
- * @throws IOException If an I/O occurred while swallowing the payload
+ * @throws ConnectionException If an error fatal to the HTTP/2 connection occurs while swallowing the payload
+ * @throws IOException If an I/O occurred while swallowing the payload
*/
- void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException;
+ void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount)
+ throws ConnectionException, IOException;
// Header frames
- HeaderEmitter headersStart(int streamId, boolean headersEndStream)
- throws Http2Exception, IOException;
+ HeaderEmitter headersStart(int streamId, boolean headersEndStream) throws Http2Exception, IOException;
+
void headersContinue(int payloadSize, boolean endOfHeaders);
+
void headersEnd(int streamId) throws Http2Exception;
// Reset frames
@@ -810,6 +785,7 @@ class Http2Parser {
// Settings frames
void setting(Setting setting, long value) throws ConnectionException;
+
void settingsEnd(boolean ack) throws IOException;
// Ping frames
@@ -825,18 +801,14 @@ class Http2Parser {
void priorityUpdate(int prioritizedStreamID, Priority p) throws Http2Exception;
/**
- * Notification triggered when the parser swallows the payload of an
- * unknown frame.
+ * Notification triggered when the parser swallows the payload of an unknown frame.
*
- * @param streamId The stream on which the swallowed frame was
- * received
- * @param frameTypeId The (unrecognised) type of swallowed frame
- * @param flags The flags set in the header of the swallowed
- * frame
- * @param size The payload size of the swallowed frame
+ * @param streamId The stream on which the swallowed frame was received
+ * @param frameTypeId The (unrecognised) type of swallowed frame
+ * @param flags The flags set in the header of the swallowed frame
+ * @param size The payload size of the swallowed frame
*
- * @throws IOException If an I/O occurred while swallowing the unknown
- * frame
+ * @throws IOException If an I/O occurred while swallowing the unknown frame
*/
void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException;
diff --git a/java/org/apache/coyote/http2/Http2Protocol.java b/java/org/apache/coyote/http2/Http2Protocol.java
index 9df4e9f06c..08b4be2673 100644
--- a/java/org/apache/coyote/http2/Http2Protocol.java
+++ b/java/org/apache/coyote/http2/Http2Protocol.java
@@ -126,10 +126,9 @@ public class Http2Protocol implements UpgradeProtocol {
@Override
- public InternalHttpUpgradeHandler getInternalUpgradeHandler(SocketWrapperBase<?> socketWrapper,
- Adapter adapter, Request coyoteRequest) {
- return socketWrapper.hasAsyncIO()
- ? new Http2AsyncUpgradeHandler(this, adapter, coyoteRequest, socketWrapper)
+ public InternalHttpUpgradeHandler getInternalUpgradeHandler(SocketWrapperBase<?> socketWrapper, Adapter adapter,
+ Request coyoteRequest) {
+ return socketWrapper.hasAsyncIO() ? new Http2AsyncUpgradeHandler(this, adapter, coyoteRequest, socketWrapper)
: new Http2UpgradeHandler(this, adapter, coyoteRequest, socketWrapper);
}
diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
index 14e7d67327..cfd6b3ddef 100644
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -58,23 +58,16 @@ import org.apache.tomcat.util.net.SocketWrapperBase;
import org.apache.tomcat.util.res.StringManager;
/**
- * This represents an HTTP/2 connection from a client to Tomcat. It is designed
- * on the basis that there will never be more than one thread performing I/O at
- * a time.
- * <br>
- * For reading, this implementation is blocking within frames and non-blocking
- * between frames.
- * <br>
+ * This represents an HTTP/2 connection from a client to Tomcat. It is designed on the basis that there will never be
+ * more than one thread performing I/O at a time. <br>
+ * For reading, this implementation is blocking within frames and non-blocking between frames. <br>
* Note:
* <ul>
- * <li>You will need to nest an <UpgradeProtocol
- * className="org.apache.coyote.http2.Http2Protocol" /> element inside
- * a TLS enabled Connector element in server.xml to enable HTTP/2 support.
- * </li>
+ * <li>You will need to nest an <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> element
+ * inside a TLS enabled Connector element in server.xml to enable HTTP/2 support.</li>
* </ul>
*/
-class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeHandler,
- Input, Output {
+class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeHandler, Input, Output {
protected static final Log log = LogFactory.getLog(Http2UpgradeHandler.class);
protected static final StringManager sm = StringManager.getManager(Http2UpgradeHandler.class);
@@ -84,7 +77,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
protected static final int FLAG_END_OF_STREAM = 1;
protected static final int FLAG_END_OF_HEADERS = 4;
- protected static final byte[] PING = { 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00};
+ protected static final byte[] PING = { 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 };
protected static final byte[] PING_ACK = { 0x00, 0x00, 0x08, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 };
protected static final byte[] SETTINGS_ACK = { 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00 };
@@ -109,20 +102,20 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private volatile long pausedNanoTime = Long.MAX_VALUE;
/**
- * Remote settings are settings defined by the client and sent to Tomcat
- * that Tomcat must use when communicating with the client.
+ * Remote settings are settings defined by the client and sent to Tomcat that Tomcat must use when communicating
+ * with the client.
*/
private final ConnectionSettingsRemote remoteSettings;
/**
- * Local settings are settings defined by Tomcat and sent to the client that
- * the client must use when communicating with Tomcat.
+ * Local settings are settings defined by Tomcat and sent to the client that the client must use when communicating
+ * with Tomcat.
*/
protected final ConnectionSettingsLocal localSettings;
private HpackDecoder hpackDecoder;
private HpackEncoder hpackEncoder;
- private final ConcurrentNavigableMap<Integer,AbstractNonZeroStream> streams = new ConcurrentSkipListMap<>();
+ private final ConcurrentNavigableMap<Integer, AbstractNonZeroStream> streams = new ConcurrentSkipListMap<>();
protected final AtomicInteger activeRemoteStreamCount = new AtomicInteger(0);
// Start at -1 so the 'add 2' logic in closeIdleStreams() works
private volatile int maxActiveRemoteStreamId = -1;
@@ -148,8 +141,9 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
protected final UserDataHelper userDataHelper = new UserDataHelper(log);
- Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest, SocketWrapperBase<?> socketWrapper) {
- super (STREAM_ID_ZERO);
+ Http2UpgradeHandler(Http2Protocol protocol, Adapter adapter, Request coyoteRequest,
+ SocketWrapperBase<?> socketWrapper) {
+ super(STREAM_ID_ZERO);
this.protocol = protocol;
this.adapter = adapter;
this.socketWrapper = socketWrapper;
@@ -236,14 +230,13 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
long value = ByteUtil.getFourBytes(settings, (i * 6) + 2);
Setting key = Setting.valueOf(id);
if (key == Setting.UNKNOWN) {
- log.warn(sm.getString("connectionSettings.unknown",
- connectionId, Integer.toString(id), Long.toString(value)));
+ log.warn(sm.getString("connectionSettings.unknown", connectionId, Integer.toString(id),
+ Long.toString(value)));
}
remoteSettings.set(key, value);
}
} catch (Http2Exception e) {
- throw new ProtocolException(
- sm.getString("upgradeHandler.upgrade.fail", connectionId));
+ throw new ProtocolException(sm.getString("upgradeHandler.upgrade.fail", connectionId));
}
}
@@ -337,107 +330,107 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
SocketState result = SocketState.CLOSED;
try {
- switch(status) {
- case OPEN_READ:
- socketWrapper.getLock().lock();
- try {
- if (socketWrapper.canWrite()) {
- // Only send a ping if there is no other data waiting to be sent.
- // Ping manager will ensure they aren't sent too frequently.
- pingManager.sendPing(false);
+ switch (status) {
+ case OPEN_READ:
+ socketWrapper.getLock().lock();
+ try {
+ if (socketWrapper.canWrite()) {
+ // Only send a ping if there is no other data waiting to be sent.
+ // Ping manager will ensure they aren't sent too frequently.
+ pingManager.sendPing(false);
+ }
+ } finally {
+ socketWrapper.getLock().unlock();
}
- } finally {
- socketWrapper.getLock().unlock();
- }
- try {
- // Disable the connection timeout while frames are processed
- setConnectionTimeout(-1);
- while (true) {
- try {
- if (!parser.readFrame()) {
- break;
- }
- } catch (StreamException se) {
- // Log the Stream error but not necessarily all of
- // them
- UserDataHelper.Mode logMode = userDataHelper.getNextMode();
- if (logMode != null) {
- String message = sm.getString("upgradeHandler.stream.error",
- connectionId, Integer.toString(se.getStreamId()));
- switch (logMode) {
- case INFO_THEN_DEBUG:
- message += sm.getString("upgradeHandler.fallToDebug");
- //$FALL-THROUGH$
- case INFO:
- log.info(message, se);
- break;
- case DEBUG:
- log.debug(message, se);
+ try {
+ // Disable the connection timeout while frames are processed
+ setConnectionTimeout(-1);
+ while (true) {
+ try {
+ if (!parser.readFrame()) {
+ break;
+ }
+ } catch (StreamException se) {
+ // Log the Stream error but not necessarily all of
+ // them
+ UserDataHelper.Mode logMode = userDataHelper.getNextMode();
+ if (logMode != null) {
+ String message = sm.getString("upgradeHandler.stream.error", connectionId,
+ Integer.toString(se.getStreamId()));
+ switch (logMode) {
+ case INFO_THEN_DEBUG:
+ message += sm.getString("upgradeHandler.fallToDebug");
+ //$FALL-THROUGH$
+ case INFO:
+ log.info(message, se);
+ break;
+ case DEBUG:
+ log.debug(message, se);
+ }
+ }
+ // Stream errors are not fatal to the connection so
+ // continue reading frames
+ Stream stream = getStream(se.getStreamId(), false);
+ if (stream == null) {
+ sendStreamReset(null, se);
+ } else {
+ stream.close(se);
+ }
+ } finally {
+ if (overheadCount.get() > 0) {
+ throw new ConnectionException(
+ sm.getString("upgradeHandler.tooMuchOverhead", connectionId),
+ Http2Error.ENHANCE_YOUR_CALM);
}
- }
- // Stream errors are not fatal to the connection so
- // continue reading frames
- Stream stream = getStream(se.getStreamId(), false);
- if (stream == null) {
- sendStreamReset(null, se);
- } else {
- stream.close(se);
- }
- } finally {
- if (overheadCount.get() > 0) {
- throw new ConnectionException(
- sm.getString("upgradeHandler.tooMuchOverhead", connectionId),
- Http2Error.ENHANCE_YOUR_CALM);
}
}
- }
- // Need to know the correct timeout before starting the read
- // but that may not be known at this time if one or more
- // requests are currently being processed so don't set a
- // timeout for the socket...
- socketWrapper.setReadTimeout(-1);
+ // Need to know the correct timeout before starting the read
+ // but that may not be known at this time if one or more
+ // requests are currently being processed so don't set a
+ // timeout for the socket...
+ socketWrapper.setReadTimeout(-1);
- // ...set a timeout on the connection
- setConnectionTimeoutForStreamCount(activeRemoteStreamCount.get());
+ // ...set a timeout on the connection
+ setConnectionTimeoutForStreamCount(activeRemoteStreamCount.get());
- } catch (Http2Exception ce) {
- // Really ConnectionException
- if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.connectionError"), ce);
+ } catch (Http2Exception ce) {
+ // Really ConnectionException
+ if (log.isDebugEnabled()) {
+ log.debug(sm.getString("upgradeHandler.connectionError"), ce);
+ }
+ closeConnection(ce);
+ break;
+ }
+
+ if (connectionState.get() != ConnectionState.CLOSED) {
+ if (socketWrapper.hasAsyncIO()) {
+ result = SocketState.ASYNC_IO;
+ } else {
+ result = SocketState.UPGRADED;
+ }
}
- closeConnection(ce);
break;
- }
- if (connectionState.get() != ConnectionState.CLOSED) {
+ case OPEN_WRITE:
+ processWrites();
if (socketWrapper.hasAsyncIO()) {
result = SocketState.ASYNC_IO;
} else {
result = SocketState.UPGRADED;
}
- }
- break;
+ break;
- case OPEN_WRITE:
- processWrites();
- if (socketWrapper.hasAsyncIO()) {
- result = SocketState.ASYNC_IO;
- } else {
- result = SocketState.UPGRADED;
- }
- break;
-
- case TIMEOUT:
- closeConnection(null);
- break;
-
- case DISCONNECT:
- case ERROR:
- case STOP:
- case CONNECT_FAIL:
- close();
- break;
+ case TIMEOUT:
+ closeConnection(null);
+ break;
+
+ case DISCONNECT:
+ case ERROR:
+ case STOP:
+ case CONNECT_FAIL:
+ close();
+ break;
}
} catch (IOException ioe) {
if (log.isDebugEnabled()) {
@@ -454,8 +447,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/*
- * Sets the connection timeout based on the current number of active
- * streams.
+ * Sets the connection timeout based on the current number of active streams.
*/
protected void setConnectionTimeoutForStreamCount(int streamCount) {
if (streamCount == 0) {
@@ -572,8 +564,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
void sendStreamReset(StreamStateMachine state, StreamException se) throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.rst.debug", connectionId,
- Integer.toString(se.getStreamId()), se.getError(), se.getMessage()));
+ log.debug(sm.getString("upgradeHandler.rst.debug", connectionId, Integer.toString(se.getStreamId()),
+ se.getError(), se.getMessage()));
}
// Write a RST frame
@@ -633,9 +625,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/**
- * Write the initial settings frame and any necessary supporting frames. If
- * the initial settings increase the initial window size, it will also be
- * necessary to send a WINDOW_UPDATE frame to increase the size of the flow
+ * Write the initial settings frame and any necessary supporting frames. If the initial settings increase the
+ * initial window size, it will also be necessary to send a WINDOW_UPDATE frame to increase the size of the flow
* control window for the connection (stream 0).
*/
protected void writeSettings() {
@@ -645,7 +636,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
socketWrapper.write(true, settings, 0, settings.length);
byte[] windowUpdateFrame = createWindowUpdateForSettings();
if (windowUpdateFrame.length > 0) {
- socketWrapper.write(true, windowUpdateFrame, 0 , windowUpdateFrame.length);
+ socketWrapper.write(true, windowUpdateFrame, 0, windowUpdateFrame.length);
}
socketWrapper.flush(true);
} catch (IOException ioe) {
@@ -659,8 +650,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/**
- * @return The WINDOW_UPDATE frame if one is required or an empty array if
- * no WINDOW_UPDATE is required.
+ * @return The WINDOW_UPDATE frame if one is required or an empty array if no WINDOW_UPDATE is required.
*/
protected byte[] createWindowUpdateForSettings() {
// Build a WINDOW_UPDATE frame if one is required. If not, create an
@@ -670,7 +660,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
if (increment > 0) {
// Build window update frame for stream 0
windowUpdateFrame = new byte[13];
- ByteUtil.setThreeBytes(windowUpdateFrame, 0, 4);
+ ByteUtil.setThreeBytes(windowUpdateFrame, 0, 4);
windowUpdateFrame[3] = FrameType.WINDOW_UPDATE.getIdByte();
ByteUtil.set31Bits(windowUpdateFrame, 9, increment);
} else {
@@ -681,8 +671,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
- protected void writeGoAwayFrame(int maxStreamId, long errorCode, byte[] debugMsg)
- throws IOException {
+ protected void writeGoAwayFrame(int maxStreamId, long errorCode, byte[] debugMsg) throws IOException {
byte[] fixedPayload = new byte[8];
ByteUtil.set31Bits(fixedPayload, 0, maxStreamId);
ByteUtil.setFourBytes(fixedPayload, 4, errorCode);
@@ -707,8 +696,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
}
- void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders,
- boolean endOfStream, int payloadSize) throws IOException {
+ void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize)
+ throws IOException {
// This ensures the Stream processing thread has control of the socket.
socketWrapper.getLock().lock();
try {
@@ -724,20 +713,19 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/*
- * Separate method to allow Http2AsyncUpgradeHandler to call this code
- * without synchronizing on socketWrapper since it doesn't need to.
+ * Separate method to allow Http2AsyncUpgradeHandler to call this code without synchronizing on socketWrapper since
+ * it doesn't need to.
*/
- protected HeaderFrameBuffers doWriteHeaders(Stream stream, int pushedStreamId,
- MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize) throws IOException {
+ protected HeaderFrameBuffers doWriteHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders,
+ boolean endOfStream, int payloadSize) throws IOException {
if (log.isDebugEnabled()) {
if (pushedStreamId == 0) {
- log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
- stream.getIdAsString(), Boolean.valueOf(endOfStream)));
- } else {
- log.debug(sm.getString("upgradeHandler.writePushHeaders", connectionId,
- stream.getIdAsString(), Integer.valueOf(pushedStreamId),
+ log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId, stream.getIdAsString(),
Boolean.valueOf(endOfStream)));
+ } else {
+ log.debug(sm.getString("upgradeHandler.writePushHeaders", connectionId, stream.getIdAsString(),
+ Integer.valueOf(pushedStreamId), Boolean.valueOf(endOfStream)));
}
}
@@ -849,14 +837,11 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/*
- * Handles an I/O error on the socket underlying the HTTP/2 connection when
- * it is triggered by application code (usually reading the request or
- * writing the response). Such I/O errors are fatal so the connection is
- * closed. The exception is re-thrown to make the client code aware of the
- * problem.
+ * Handles an I/O error on the socket underlying the HTTP/2 connection when it is triggered by application code
+ * (usually reading the request or writing the response). Such I/O errors are fatal so the connection is closed. The
+ * exception is re-thrown to make the client code aware of the problem.
*
- * Note: We can not rely on this exception reaching the socket processor
- * since the application code may swallow it.
+ * Note: We can not rely on this exception reaching the socket processor since the application code may swallow it.
*/
protected void handleAppInitiatedIOException(IOException ioe) throws IOException {
close();
@@ -865,20 +850,19 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/*
- * Needs to know if this was application initiated since that affects the
- * error handling.
+ * Needs to know if this was application initiated since that affects the error handling.
*/
void writeWindowUpdate(AbstractNonZeroStream stream, int increment, boolean applicationInitiated)
throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.windowUpdateConnection",
- getConnectionId(), Integer.valueOf(increment)));
+ log.debug(sm.getString("upgradeHandler.windowUpdateConnection", getConnectionId(),
+ Integer.valueOf(increment)));
}
socketWrapper.getLock().lock();
try {
// Build window update frame for stream 0
byte[] frame = new byte[13];
- ByteUtil.setThreeBytes(frame, 0, 4);
+ ByteUtil.setThreeBytes(frame, 0, 4);
frame[3] = FrameType.WINDOW_UPDATE.getIdByte();
ByteUtil.set31Bits(frame, 9, increment);
socketWrapper.write(true, frame, 0, frame.length);
@@ -888,8 +872,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
int streamIncrement = ((Stream) stream).getWindowUpdateSizeToWrite(increment);
if (streamIncrement > 0) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.windowUpdateStream",
- getConnectionId(), getIdAsString(), Integer.valueOf(streamIncrement)));
+ log.debug(sm.getString("upgradeHandler.windowUpdateStream", getConnectionId(), getIdAsString(),
+ Integer.valueOf(streamIncrement)));
}
// Re-use buffer as connection update has already been written
ByteUtil.set31Bits(frame, 5, stream.getIdAsInt());
@@ -939,15 +923,16 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
synchronized (stream) {
synchronized (this) {
if (!stream.canWrite()) {
- stream.doStreamCancel(sm.getString("upgradeHandler.stream.notWritable",
- stream.getConnectionId(), stream.getIdAsString(), stream.state.getCurrentStateName() ),
+ stream.doStreamCancel(
+ sm.getString("upgradeHandler.stream.notWritable", stream.getConnectionId(),
+ stream.getIdAsString(), stream.state.getCurrentStateName()),
Http2Error.STREAM_CLOSED);
}
long windowSize = getWindowSize();
if (stream.getConnectionAllocationMade() > 0) {
allocation = stream.getConnectionAllocationMade();
stream.setConnectionAllocationMade(0);
- } else if (windowSize < 1) {
+ } else if (windowSize < 1) {
// Has this stream been granted an allocation
if (stream.getConnectionAllocationMade() == 0) {
stream.setConnectionAllocationRequested(reservation);
@@ -976,8 +961,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
Http2Error error;
if (stream.isActive()) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.noAllocation",
- connectionId, stream.getIdAsString()));
+ log.debug(sm.getString("upgradeHandler.noAllocation", connectionId,
+ stream.getIdAsString()));
}
// No allocation
// Close the connection. Do this first since
@@ -999,9 +984,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
stream.setConnectionAllocationMade(0);
}
} catch (InterruptedException e) {
- throw new IOException(sm.getString(
- "upgradeHandler.windowSizeReservationInterrupted", connectionId,
- stream.getIdAsString(), Integer.toString(reservation)), e);
+ throw new IOException(sm.getString("upgradeHandler.windowSizeReservationInterrupted",
+ connectionId, stream.getIdAsString(), Integer.toString(reservation)), e);
}
} else {
stream.waitForConnectionAllocationNonBlocking();
@@ -1013,7 +997,6 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
-
@SuppressWarnings("sync-override") // notify() needs to be outside sync
// to avoid deadlock
@Override
@@ -1025,7 +1008,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
if (windowSize < 1 && windowSize + increment > 0) {
// Connection window is exhausted. Assume there will be streams
// to notify. The overhead is minimal if there are none.
- streamsToNotify = releaseBackLog((int) (windowSize +increment));
+ streamsToNotify = releaseBackLog((int) (windowSize + increment));
} else {
super.incrementWindowSize(increment);
}
@@ -1034,8 +1017,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
if (streamsToNotify != null) {
for (AbstractStream stream : streamsToNotify) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.releaseBacklog",
- connectionId, stream.getIdAsString()));
+ log.debug(sm.getString("upgradeHandler.releaseBacklog", connectionId, stream.getIdAsString()));
}
// There is never any O/P on stream zero but it is included in
// the backlog as it simplifies the code. Skip it if it appears
@@ -1050,12 +1032,12 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
/**
- * Process send file (if supported) for the given stream. The appropriate
- * request attributes should be set before calling this method.
+ * Process send file (if supported) for the given stream. The appropriate request attributes should be set before
+ * calling this method.
*
- * @param sendfileData The stream and associated data to process
+ * @param sendfileData The stream and associated data to process
*
- * @return The result of the send file processing
+ * @return The result of the send file processing
*/
protected SendfileState processSendfile(SendfileData sendfileData) {
return SendfileState.DONE;
@@ -1144,7 +1126,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
break;
}
- int share = (int) (s.getConnectionAllocationRequested() * remaining / requestedAllocationForIncrementalStreams);
+ int share = (int) (s.getConnectionAllocationRequested() * remaining /
+ requestedAllocationForIncrementalStreams);
if (share == 0) {
share = 1;
}
@@ -1165,8 +1148,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private synchronized int allocate(AbstractStream stream, int allocation) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.allocate.debug", getConnectionId(),
- stream.getIdAsString(), Integer.toString(allocation)));
+ log.debug(sm.getString("upgradeHandler.allocate.debug", getConnectionId(), stream.getIdAsString(),
+ Integer.toString(allocation)));
}
int leftToAllocate = allocation;
@@ -1184,8 +1167,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.allocate.left",
- getConnectionId(), stream.getIdAsString(), Integer.toString(leftToAllocate)));
+ log.debug(sm.getString("upgradeHandler.allocate.left", getConnectionId(), stream.getIdAsString(),
+ Integer.toString(leftToAllocate)));
}
return leftToAllocate;
@@ -1234,9 +1217,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private Stream createRemoteStream(int streamId) throws ConnectionException {
Integer key = Integer.valueOf(streamId);
- if (streamId %2 != 1) {
- throw new ConnectionException(
- sm.getString("upgradeHandler.stream.even", key), Http2Error.PROTOCOL_ERROR);
+ if (streamId % 2 != 1) {
+ throw new ConnectionException(sm.getString("upgradeHandler.stream.even", key), Http2Error.PROTOCOL_ERROR);
}
pruneClosedStreams(streamId);
@@ -1306,8 +1288,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
final int size = streams.size();
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.pruneStart", connectionId,
- Long.toString(max), Integer.toString(size)));
+ log.debug(sm.getString("upgradeHandler.pruneStart", connectionId, Long.toString(max),
+ Integer.toString(size)));
}
int toClose = size - (int) max;
@@ -1331,8 +1313,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
}
if (toClose > 0) {
- log.warn(sm.getString("upgradeHandler.pruneIncomplete", connectionId,
- Integer.toString(streamId), Integer.toString(toClose)));
+ log.warn(sm.getString("upgradeHandler.pruneIncomplete", connectionId, Integer.toString(streamId),
+ Integer.toString(toClose)));
}
}
@@ -1353,8 +1335,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
socketWrapper.getLock().lock();
try {
pushStream = createLocalStream(request);
- writeHeaders(associatedStream, pushStream.getIdAsInt(), request.getMimeHeaders(),
- false, Constants.DEFAULT_HEADERS_FRAME_SIZE);
+ writeHeaders(associatedStream, pushStream.getIdAsInt(), request.getMimeHeaders(), false,
+ Constants.DEFAULT_HEADERS_FRAME_SIZE);
} finally {
socketWrapper.getLock().unlock();
}
@@ -1412,8 +1394,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private void updateOverheadCount(FrameType frameType, int increment) {
long newOverheadCount = overheadCount.addAndGet(increment);
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.overheadChange",
- connectionId, getIdAsString(), frameType.name(), Long.valueOf(newOverheadCount)));
+ log.debug(sm.getString("upgradeHandler.overheadChange", connectionId, getIdAsString(), frameType.name(),
+ Long.valueOf(newOverheadCount)));
}
}
@@ -1511,8 +1493,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
ByteBuffer result = abstractNonZeroStream.getInputByteBuffer();
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.startRequestBodyFrame.result",
- getConnectionId(), abstractNonZeroStream.getIdAsString(), result));
+ log.debug(sm.getString("upgradeHandler.startRequestBodyFrame.result", getConnectionId(),
+ abstractNonZeroStream.getIdAsString(), result));
}
return result;
@@ -1537,8 +1519,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
public void receivedEndOfStream(int streamId) throws ConnectionException {
- AbstractNonZeroStream abstractNonZeroStream =
- getAbstractNonZeroStream(streamId, connectionState.get().isNewStreamAllowed());
+ AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId,
+ connectionState.get().isNewStreamAllowed());
if (abstractNonZeroStream instanceof Stream) {
Stream stream = (Stream) abstractNonZeroStream;
stream.receivedEndOfStream();
@@ -1557,8 +1539,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
- public HeaderEmitter headersStart(int streamId, boolean headersEndStream)
- throws Http2Exception, IOException {
+ public HeaderEmitter headersStart(int streamId, boolean headersEndStream) throws Http2Exception, IOException {
// Check the pause state before processing headers since the pause state
// determines if a new stream is created or if this stream is ignored.
@@ -1570,9 +1551,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
stream = createRemoteStream(streamId);
}
if (streamId < maxActiveRemoteStreamId) {
- throw new ConnectionException(sm.getString("upgradeHandler.stream.old",
- Integer.valueOf(streamId), Integer.valueOf(maxActiveRemoteStreamId)),
- Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("upgradeHandler.stream.old", Integer.valueOf(streamId),
+ Integer.valueOf(maxActiveRemoteStreamId)), Http2Error.PROTOCOL_ERROR);
}
stream.checkState(FrameType.HEADERS);
stream.receivedStartOfHeaders(headersEndStream);
@@ -1580,8 +1560,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
return stream;
} else {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.noNewStreams",
- connectionId, Integer.toString(streamId)));
+ log.debug(sm.getString("upgradeHandler.noNewStreams", connectionId, Integer.toString(streamId)));
}
reduceOverheadCount(FrameType.HEADERS);
// Stateless so a static can be used to save on GC
@@ -1592,11 +1571,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
private void closeIdleStreams(int newMaxActiveRemoteStreamId) {
final ConcurrentNavigableMap<Integer, AbstractNonZeroStream> subMap = streams.subMap(
- Integer.valueOf(maxActiveRemoteStreamId), false,
- Integer.valueOf(newMaxActiveRemoteStreamId), false);
+ Integer.valueOf(maxActiveRemoteStreamId), false, Integer.valueOf(newMaxActiveRemoteStreamId), false);
for (AbstractNonZeroStream stream : subMap.values()) {
if (stream instanceof Stream) {
- ((Stream)stream).closeIfIdle();
+ ((Stream) stream).closeIfIdle();
}
}
maxActiveRemoteStreamId = newMaxActiveRemoteStreamId;
@@ -1624,8 +1602,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
public void headersEnd(int streamId) throws Http2Exception {
- AbstractNonZeroStream abstractNonZeroStream =
- getAbstractNonZeroStream(streamId, connectionState.get().isNewStreamAllowed());
+ AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId,
+ connectionState.get().isNewStreamAllowed());
if (abstractNonZeroStream instanceof Stream) {
setMaxProcessedStream(streamId);
Stream stream = (Stream) abstractNonZeroStream;
@@ -1636,8 +1614,9 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
setConnectionTimeoutForStreamCount(activeRemoteStreamCount.decrementAndGet());
// Ignoring maxConcurrentStreams increases the overhead count
increaseOverheadCount(FrameType.HEADERS);
- throw new StreamException(sm.getString("upgradeHandler.tooManyRemoteStreams",
- Long.toString(localSettings.getMaxConcurrentStreams())),
+ throw new StreamException(
+ sm.getString("upgradeHandler.tooManyRemoteStreams",
+ Long.toString(localSettings.getMaxConcurrentStreams())),
Http2Error.REFUSED_STREAM, streamId);
}
// Valid new stream reduces the overhead count
@@ -1658,7 +1637,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
- public void reset(int streamId, long errorCode) throws Http2Exception {
+ public void reset(int streamId, long errorCode) throws Http2Exception {
if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.reset.receive", getConnectionId(), Integer.toString(streamId),
Long.toString(errorCode)));
@@ -1696,16 +1675,16 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
try {
stream.incrementWindowSize(diff);
} catch (Http2Exception h2e) {
- ((Stream) stream).close(new StreamException(sm.getString(
- "upgradeHandler.windowSizeTooBig", connectionId,
- stream.getIdAsString()),
+ ((Stream) stream).close(new StreamException(
+ sm.getString("upgradeHandler.windowSizeTooBig", connectionId, stream.getIdAsString()),
h2e.getError(), stream.getIdAsInt()));
- }
+ }
}
} else if (setting == Setting.NO_RFC7540_PRIORITIES) {
// This should not be changed after the initial setting
if (value != ConnectionSettingsBase.DEFAULT_NO_RFC7540_PRIORITIES) {
- throw new ConnectionException(sm.getString("upgradeHandler.enableRfc7450Priorities", connectionId), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(sm.getString("upgradeHandler.enableRfc7450Priorities", connectionId),
+ Http2Error.PROTOCOL_ERROR);
}
} else {
remoteSettings.set(setting, value);
@@ -1718,8 +1697,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
if (ack) {
if (!localSettings.ack()) {
// Ack was unexpected
- log.warn(sm.getString(
- "upgradeHandler.unexpectedAck", connectionId, getIdAsString()));
+ log.warn(sm.getString("upgradeHandler.unexpectedAck", connectionId, getIdAsString()));
}
} else {
socketWrapper.getLock().lock();
@@ -1745,8 +1723,8 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
public void goaway(int lastStreamId, long errorCode, String debugData) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("upgradeHandler.goaway.debug", connectionId,
- Integer.toString(lastStreamId), Long.toHexString(errorCode), debugData));
+ log.debug(sm.getString("upgradeHandler.goaway.debug", connectionId, Integer.toString(lastStreamId),
+ Long.toHexString(errorCode), debugData));
}
close();
}
@@ -1807,8 +1785,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
@Override
- public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size)
- throws IOException {
+ public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException {
// NO-OP.
}
@@ -1892,8 +1869,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
roundTripTimes.poll();
}
if (log.isDebugEnabled()) {
- log.debug(sm.getString("pingManager.roundTripTime",
- connectionId, Long.valueOf(roundTripTime)));
+ log.debug(sm.getString("pingManager.roundTripTime", connectionId, Long.valueOf(roundTripTime)));
}
}
@@ -1958,10 +1934,15 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH
protected static interface HeaderFrameBuffers {
public void startFrame();
+
public void endFrame() throws IOException;
+
public void endHeaders() throws IOException;
+
public byte[] getHeader();
+
public ByteBuffer getPayload();
+
public void expandPayload();
}
diff --git a/java/org/apache/coyote/http2/RecycledStream.java b/java/org/apache/coyote/http2/RecycledStream.java
index 730936bb55..143ae1d371 100644
--- a/java/org/apache/coyote/http2/RecycledStream.java
+++ b/java/org/apache/coyote/http2/RecycledStream.java
@@ -19,8 +19,8 @@ package org.apache.coyote.http2;
import java.nio.ByteBuffer;
/**
- * Represents a closed stream in the priority tree. Used in preference to the
- * full {@link Stream} as has much lower memory usage.
+ * Represents a closed stream in the priority tree. Used in preference to the full {@link Stream} as has much lower
+ * memory usage.
*/
class RecycledStream extends AbstractNonZeroStream {
@@ -56,9 +56,8 @@ class RecycledStream extends AbstractNonZeroStream {
/**
* {@inheritDoc}
* <p>
- * This implementation will return an zero length ByteBuffer to trigger a
- * flow control error if more DATA frame payload than the remaining flow
- * control window is received for this recycled stream.
+ * This implementation will return an zero length ByteBuffer to trigger a flow control error if more DATA frame
+ * payload than the remaining flow control window is received for this recycled stream.
*/
@Override
ByteBuffer getInputByteBuffer() {
diff --git a/java/org/apache/coyote/http2/Setting.java b/java/org/apache/coyote/http2/Setting.java
index 29dc73f201..1ff490f48f 100644
--- a/java/org/apache/coyote/http2/Setting.java
+++ b/java/org/apache/coyote/http2/Setting.java
@@ -28,7 +28,7 @@ enum Setting {
private final int id;
- private Setting (int id) {
+ private Setting(int id) {
this.id = id;
}
@@ -42,31 +42,31 @@ enum Setting {
}
static final Setting valueOf(int i) {
- switch(i) {
- case 1: {
- return HEADER_TABLE_SIZE;
- }
- case 2: {
- return ENABLE_PUSH;
- }
- case 3: {
- return MAX_CONCURRENT_STREAMS;
- }
- case 4: {
- return INITIAL_WINDOW_SIZE;
- }
- case 5: {
- return MAX_FRAME_SIZE;
- }
- case 6: {
- return MAX_HEADER_LIST_SIZE;
- }
- case 9: {
- return NO_RFC7540_PRIORITIES;
- }
- default: {
- return Setting.UNKNOWN;
- }
+ switch (i) {
+ case 1: {
+ return HEADER_TABLE_SIZE;
+ }
+ case 2: {
+ return ENABLE_PUSH;
+ }
+ case 3: {
+ return MAX_CONCURRENT_STREAMS;
+ }
+ case 4: {
+ return INITIAL_WINDOW_SIZE;
+ }
+ case 5: {
+ return MAX_FRAME_SIZE;
+ }
+ case 6: {
+ return MAX_HEADER_LIST_SIZE;
+ }
+ case 9: {
+ return NO_RFC7540_PRIORITIES;
+ }
+ default: {
+ return Setting.UNKNOWN;
+ }
}
}
}
diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java
index 88017a7fb5..349e2f5942 100644
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -65,7 +65,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
private static final Set<String> HTTP_CONNECTION_SPECIFIC_HEADERS = new HashSet<>();
static {
- Response response = new Response();
+ Response response = new Response();
response.setStatus(100);
StreamProcessor.prepareHeaders(null, response, true, null, null);
ACK_HEADERS = response.getMimeHeaders();
@@ -188,8 +188,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
final void receiveReset(long errorCode) {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.reset.receive", getConnectionId(), getIdAsString(),
- Long.toString(errorCode)));
+ log.debug(
+ sm.getString("stream.reset.receive", getConnectionId(), getIdAsString(), Long.toString(errorCode)));
}
// Set the new state first since read and write both check this
state.receivedReset();
@@ -220,13 +220,11 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
- final synchronized int reserveWindowSize(int reservation, boolean block)
- throws IOException {
+ final synchronized int reserveWindowSize(int reservation, boolean block) throws IOException {
long windowSize = getWindowSize();
while (windowSize < 1) {
if (!canWrite()) {
- throw new CloseNowException(sm.getString("stream.notWritable",
- getConnectionId(), getIdAsString()));
+ throw new CloseNowException(sm.getString("stream.notWritable", getConnectionId(), getIdAsString()));
}
if (block) {
try {
@@ -289,25 +287,22 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
@Override
public final void emitHeader(String name, String value) throws HpackException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.header.debug", getConnectionId(), getIdAsString(),
- name, value));
+ log.debug(sm.getString("stream.header.debug", getConnectionId(), getIdAsString(), name, value));
}
// Header names must be lower case
if (!name.toLowerCase(Locale.US).equals(name)) {
- throw new HpackException(sm.getString("stream.header.case",
- getConnectionId(), getIdAsString(), name));
+ throw new HpackException(sm.getString("stream.header.case", getConnectionId(), getIdAsString(), name));
}
if (HTTP_CONNECTION_SPECIFIC_HEADERS.contains(name)) {
- throw new HpackException(sm.getString("stream.header.connection",
- getConnectionId(), getIdAsString(), name));
+ throw new HpackException(
+ sm.getString("stream.header.connection", getConnectionId(), getIdAsString(), name));
}
if ("te".equals(name)) {
if (!"trailers".equals(value)) {
- throw new HpackException(sm.getString("stream.header.te",
- getConnectionId(), getIdAsString(), value));
+ throw new HpackException(sm.getString("stream.header.te", getConnectionId(), getIdAsString(), value));
}
}
@@ -318,16 +313,15 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
if (name.length() == 0) {
- throw new HpackException(sm.getString("stream.header.empty",
- getConnectionId(), getIdAsString()));
+ throw new HpackException(sm.getString("stream.header.empty", getConnectionId(), getIdAsString()));
}
boolean pseudoHeader = name.charAt(0) == ':';
if (pseudoHeader && headerState != HEADER_STATE_PSEUDO) {
- headerException = new StreamException(sm.getString(
- "stream.header.unexpectedPseudoHeader", getConnectionId(), getIdAsString(),
- name), Http2Error.PROTOCOL_ERROR, getIdAsInt());
+ headerException = new StreamException(
+ sm.getString("stream.header.unexpectedPseudoHeader", getConnectionId(), getIdAsString(), name),
+ Http2Error.PROTOCOL_ERROR, getIdAsInt());
// No need for further processing. The stream will be reset.
return;
}
@@ -337,122 +331,120 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
switch (name) {
- case ":method": {
- if (coyoteRequest.method().isNull()) {
- coyoteRequest.method().setString(value);
- if ("HEAD".equals(value)) {
- addOutputFilter(new VoidOutputFilter());
- streamOutputBuffer.closed = true;
+ case ":method": {
+ if (coyoteRequest.method().isNull()) {
+ coyoteRequest.method().setString(value);
+ if ("HEAD".equals(value)) {
+ addOutputFilter(new VoidOutputFilter());
+ streamOutputBuffer.closed = true;
+ }
+ } else {
+ throw new HpackException(
+ sm.getString("stream.header.duplicate", getConnectionId(), getIdAsString(), ":method"));
}
- } else {
- throw new HpackException(sm.getString("stream.header.duplicate",
- getConnectionId(), getIdAsString(), ":method" ));
- }
- break;
- }
- case ":scheme": {
- if (coyoteRequest.scheme().isNull()) {
- coyoteRequest.scheme().setString(value);
- } else {
- throw new HpackException(sm.getString("stream.header.duplicate",
- getConnectionId(), getIdAsString(), ":scheme" ));
- }
- break;
- }
- case ":path": {
- if (!coyoteRequest.requestURI().isNull()) {
- throw new HpackException(sm.getString("stream.header.duplicate",
- getConnectionId(), getIdAsString(), ":path" ));
- }
- if (value.length() == 0) {
- throw new HpackException(sm.getString("stream.header.noPath",
- getConnectionId(), getIdAsString()));
- }
- int queryStart = value.indexOf('?');
- String uri;
- if (queryStart == -1) {
- uri = value;
- } else {
- uri = value.substring(0, queryStart);
- String query = value.substring(queryStart + 1);
- coyoteRequest.queryString().setString(query);
- }
- // Bug 61120. Set the URI as bytes rather than String so:
- // - any path parameters are correctly processed
- // - the normalization security checks are performed that prevent
- // directory traversal attacks
- byte[] uriBytes = uri.getBytes(StandardCharsets.ISO_8859_1);
- coyoteRequest.requestURI().setBytes(uriBytes, 0, uriBytes.length);
- break;
- }
- case ":authority": {
- if (coyoteRequest.serverName().isNull()) {
- parseAuthority(value, false);
- } else {
- throw new HpackException(sm.getString("stream.header.duplicate",
- getConnectionId(), getIdAsString(), ":authority" ));
+ break;
}
- break;
- }
- case "cookie": {
- // Cookie headers need to be concatenated into a single header
- // See RFC 7540 8.1.2.5
- if (cookieHeader == null) {
- cookieHeader = new StringBuilder();
- } else {
- cookieHeader.append("; ");
+ case ":scheme": {
+ if (coyoteRequest.scheme().isNull()) {
+ coyoteRequest.scheme().setString(value);
+ } else {
+ throw new HpackException(
+ sm.getString("stream.header.duplicate", getConnectionId(), getIdAsString(), ":scheme"));
+ }
+ break;
}
- cookieHeader.append(value);
- break;
- }
- case "host": {
- if (coyoteRequest.serverName().isNull()) {
- // No :authority header. This is first host header. Use it.
- hostHeaderSeen = true;
- parseAuthority(value, true);
- } else if (!hostHeaderSeen) {
- // First host header - must be consistent with :authority
- hostHeaderSeen = true;
- compareAuthority(value);
- } else {
- // Multiple hosts headers - illegal
- throw new HpackException(sm.getString("stream.header.duplicate",
- getConnectionId(), getIdAsString(), "host" ));
+ case ":path": {
+ if (!coyoteRequest.requestURI().isNull()) {
+ throw new HpackException(
+ sm.getString("stream.header.duplicate", getConnectionId(), getIdAsString(), ":path"));
+ }
+ if (value.length() == 0) {
+ throw new HpackException(sm.getString("stream.header.noPath", getConnectionId(), getIdAsString()));
+ }
+ int queryStart = value.indexOf('?');
+ String uri;
+ if (queryStart == -1) {
+ uri = value;
+ } else {
+ uri = value.substring(0, queryStart);
+ String query = value.substring(queryStart + 1);
+ coyoteRequest.queryString().setString(query);
+ }
+ // Bug 61120. Set the URI as bytes rather than String so:
+ // - any path parameters are correctly processed
+ // - the normalization security checks are performed that prevent
+ // directory traversal attacks
+ byte[] uriBytes = uri.getBytes(StandardCharsets.ISO_8859_1);
+ coyoteRequest.requestURI().setBytes(uriBytes, 0, uriBytes.length);
+ break;
}
- break;
- }
- case "priority": {
- try {
- Priority p = Priority.parsePriority(new StringReader(value));
- setUrgency(p.getUrgency());
- setIncremental(p.getIncremental());
- } catch (IOException ioe) {
- // Not possible with StringReader
+ case ":authority": {
+ if (coyoteRequest.serverName().isNull()) {
+ parseAuthority(value, false);
+ } else {
+ throw new HpackException(
+ sm.getString("stream.header.duplicate", getConnectionId(), getIdAsString(), ":authority"));
+ }
+ break;
}
- break;
- }
- default: {
- if (headerState == HEADER_STATE_TRAILER &&
- !handler.getProtocol().isTrailerHeaderAllowed(name)) {
+ case "cookie": {
+ // Cookie headers need to be concatenated into a single header
+ // See RFC 7540 8.1.2.5
+ if (cookieHeader == null) {
+ cookieHeader = new StringBuilder();
+ } else {
+ cookieHeader.append("; ");
+ }
+ cookieHeader.append(value);
break;
}
- if ("expect".equals(name) && "100-continue".equals(value)) {
- coyoteRequest.setExpectation(true);
+ case "host": {
+ if (coyoteRequest.serverName().isNull()) {
+ // No :authority header. This is first host header. Use it.
+ hostHeaderSeen = true;
+ parseAuthority(value, true);
+ } else if (!hostHeaderSeen) {
+ // First host header - must be consistent with :authority
+ hostHeaderSeen = true;
+ compareAuthority(value);
+ } else {
+ // Multiple hosts headers - illegal
+ throw new HpackException(
+ sm.getString("stream.header.duplicate", getConnectionId(), getIdAsString(), "host"));
+ }
+ break;
}
- if (pseudoHeader) {
- headerException = new StreamException(sm.getString(
- "stream.header.unknownPseudoHeader", getConnectionId(), getIdAsString(),
- name), Http2Error.PROTOCOL_ERROR, getIdAsInt());
+ case "priority": {
+ try {
+ Priority p = Priority.parsePriority(new StringReader(value));
+ setUrgency(p.getUrgency());
+ setIncremental(p.getIncremental());
+ } catch (IOException ioe) {
+ // Not possible with StringReader
+ }
+ break;
}
+ default: {
+ if (headerState == HEADER_STATE_TRAILER && !handler.getProtocol().isTrailerHeaderAllowed(name)) {
+ break;
+ }
+ if ("expect".equals(name) && "100-continue".equals(value)) {
+ coyoteRequest.setExpectation(true);
+ }
+ if (pseudoHeader) {
+ headerException = new StreamException(
+ sm.getString("stream.header.unknownPseudoHeader", getConnectionId(), getIdAsString(), name),
+ Http2Error.PROTOCOL_ERROR, getIdAsInt());
+ }
- if (headerState == HEADER_STATE_TRAILER) {
- // HTTP/2 headers are already always lower case
- coyoteRequest.getTrailerFields().put(name, value);
- } else {
- coyoteRequest.getMimeHeaders().addValue(name).setString(value);
+ if (headerState == HEADER_STATE_TRAILER) {
+ // HTTP/2 headers are already always lower case
+ coyoteRequest.getTrailerFields().put(name, value);
+ } else {
+ coyoteRequest.getMimeHeaders().addValue(name).setString(value);
+ }
}
}
- }
}
@@ -462,8 +454,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
i = Host.parse(value);
} catch (IllegalArgumentException iae) {
// Host value invalid
- throw new HpackException(sm.getString("stream.header.invalid",
- getConnectionId(), getIdAsString(), host ? "host" : ":authority", value));
+ throw new HpackException(sm.getString("stream.header.invalid", getConnectionId(), getIdAsString(),
+ host ? "host" : ":authority", value));
}
if (i > -1) {
coyoteRequest.serverName().setString(value.substring(0, i));
@@ -480,16 +472,15 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
i = Host.parse(value);
} catch (IllegalArgumentException iae) {
// Host value invalid
- throw new HpackException(sm.getString("stream.header.invalid",
- getConnectionId(), getIdAsString(), "host", value));
+ throw new HpackException(
+ sm.getString("stream.header.invalid", getConnectionId(), getIdAsString(), "host", value));
}
if (i == -1 && (!value.equals(coyoteRequest.serverName().getString()) || coyoteRequest.getServerPort() != -1) ||
i > -1 && ((!value.substring(0, i).equals(coyoteRequest.serverName().getString()) ||
- Integer.parseInt(value.substring(i + 1)) != coyoteRequest.getServerPort()))) {
+ Integer.parseInt(value.substring(i + 1)) != coyoteRequest.getServerPort()))) {
// Host value inconsistent
- throw new HpackException(sm.getString("stream.host.inconsistent",
- getConnectionId(), getIdAsString(), value, coyoteRequest.serverName().getString(),
- Integer.toString(coyoteRequest.getServerPort())));
+ throw new HpackException(sm.getString("stream.host.inconsistent", getConnectionId(), getIdAsString(), value,
+ coyoteRequest.serverName().getString(), Integer.toString(coyoteRequest.getServerPort())));
}
}
@@ -514,10 +505,9 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
final boolean receivedEndOfHeaders() throws ConnectionException {
- if (coyoteRequest.method().isNull() || coyoteRequest.scheme().isNull() ||
- coyoteRequest.requestURI().isNull()) {
- throw new ConnectionException(sm.getString("stream.header.required",
- getConnectionId(), getIdAsString()), Http2Error.PROTOCOL_ERROR);
+ if (coyoteRequest.method().isNull() || coyoteRequest.scheme().isNull() || coyoteRequest.requestURI().isNull()) {
+ throw new ConnectionException(sm.getString("stream.header.required", getConnectionId(), getIdAsString()),
+ Http2Error.PROTOCOL_ERROR);
}
// Cookie headers need to be concatenated into a single header
// See RFC 7540 8.1.2.5
@@ -530,9 +520,9 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
final void writeHeaders() throws IOException {
- boolean endOfStream = streamOutputBuffer.hasNoBody() &&
- coyoteResponse.getTrailerFields() == null;
- handler.writeHeaders(this, 0, coyoteResponse.getMimeHeaders(), endOfStream, Constants.DEFAULT_HEADERS_FRAME_SIZE);
+ boolean endOfStream = streamOutputBuffer.hasNoBody() && coyoteResponse.getTrailerFields() == null;
+ handler.writeHeaders(this, 0, coyoteResponse.getMimeHeaders(), endOfStream,
+ Constants.DEFAULT_HEADERS_FRAME_SIZE);
}
@@ -542,7 +532,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
final void writeTrailers() throws IOException {
- Supplier<Map<String,String>> supplier = coyoteResponse.getTrailerFields();
+ Supplier<Map<String, String>> supplier = coyoteResponse.getTrailerFields();
if (supplier == null) {
// No supplier was set, end of stream will already have been sent
return;
@@ -553,14 +543,14 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
MimeHeaders mimeHeaders = coyoteResponse.getMimeHeaders();
mimeHeaders.recycle();
- Map<String,String> headerMap = supplier.get();
+ Map<String, String> headerMap = supplier.get();
if (headerMap == null) {
headerMap = Collections.emptyMap();
}
// Copy the contents of the Map to the MimeHeaders
// TODO: Is there benefit in refactoring this? Is MimeHeaders too
- // heavyweight? Can we reduce the copy/conversions?
+ // heavyweight? Can we reduce the copy/conversions?
for (Map.Entry<String, String> headerEntry : headerMap.entrySet()) {
MessageBytes mb = mimeHeaders.addValue(headerEntry.getKey());
mb.setString(headerEntry.getValue());
@@ -612,13 +602,12 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
// Trailer headers MUST include the end of stream flag
if (headersEndStream) {
headerState = HEADER_STATE_TRAILER;
- handler.getHpackDecoder().setMaxHeaderCount(
- handler.getProtocol().getMaxTrailerCount());
- handler.getHpackDecoder().setMaxHeaderSize(
- handler.getProtocol().getMaxTrailerSize());
+ handler.getHpackDecoder().setMaxHeaderCount(handler.getProtocol().getMaxTrailerCount());
+ handler.getHpackDecoder().setMaxHeaderSize(handler.getProtocol().getMaxTrailerSize());
} else {
- throw new ConnectionException(sm.getString("stream.trailerHeader.noEndOfStream",
- getConnectionId(), getIdAsString()), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(
+ sm.getString("stream.trailerHeader.noEndOfStream", getConnectionId(), getIdAsString()),
+ Http2Error.PROTOCOL_ERROR);
}
}
// Parser will catch attempt to send a headers frame after the stream
@@ -632,19 +621,20 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
contentLengthReceived += payloadSize;
long contentLengthHeader = coyoteRequest.getContentLengthLong();
if (contentLengthHeader > -1 && contentLengthReceived > contentLengthHeader) {
- throw new ConnectionException(sm.getString("stream.header.contentLength",
- getConnectionId(), getIdAsString(), Long.valueOf(contentLengthHeader),
- Long.valueOf(contentLengthReceived)), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(
+ sm.getString("stream.header.contentLength", getConnectionId(), getIdAsString(),
+ Long.valueOf(contentLengthHeader), Long.valueOf(contentLengthReceived)),
+ Http2Error.PROTOCOL_ERROR);
}
}
final void receivedEndOfStream() throws ConnectionException {
if (isContentLengthInconsistent()) {
- throw new ConnectionException(sm.getString("stream.header.contentLength",
- getConnectionId(), getIdAsString(),
- Long.valueOf(coyoteRequest.getContentLengthLong()),
- Long.valueOf(contentLengthReceived)), Http2Error.PROTOCOL_ERROR);
+ throw new ConnectionException(
+ sm.getString("stream.header.contentLength", getConnectionId(), getIdAsString(),
+ Long.valueOf(coyoteRequest.getContentLengthLong()), Long.valueOf(contentLengthReceived)),
+ Http2Error.PROTOCOL_ERROR);
}
state.receivedEndOfStream();
if (inputBuffer != null) {
@@ -723,8 +713,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
try {
StreamException se = (StreamException) http2Exception;
if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.reset.send", getConnectionId(), getIdAsString(),
- se.getError()));
+ log.debug(sm.getString("stream.reset.send", getConnectionId(), getIdAsString(), se.getError()));
}
// Need to update state atomically with the sending of the RST
@@ -741,8 +730,9 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
inputBuffer.swallowUnread();
}
} catch (IOException ioe) {
- ConnectionException ce = new ConnectionException(sm.getString(
- "stream.reset.fail", getConnectionId(), getIdAsString()), Http2Error.PROTOCOL_ERROR, ioe);
+ ConnectionException ce = new ConnectionException(
+ sm.getString("stream.reset.fail", getConnectionId(), getIdAsString()),
+ Http2Error.PROTOCOL_ERROR, ioe);
handler.closeConnection(ce);
}
} else {
@@ -753,12 +743,10 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
/*
- * This method is called recycle for consistency with the rest of the Tomcat
- * code base. Currently, it calls the handler to replace this stream with an
- * implementation that uses less memory. It does not fully recycle the
- * Stream ready for re-use since Stream objects are not re-used. This is
- * useful because Stream instances are retained for a period after the
- * Stream closes.
+ * This method is called recycle for consistency with the rest of the Tomcat code base. Currently, it calls the
+ * handler to replace this stream with an implementation that uses less memory. It does not fully recycle the Stream
+ * ready for re-use since Stream objects are not re-used. This is useful because Stream instances are retained for a
+ * period after the Stream closes.
*/
final void recycle() {
if (log.isDebugEnabled()) {
@@ -800,8 +788,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
// being used.
if (!(request.scheme().equals("http") && request.getServerPort() == 80) &&
!(request.scheme().equals("https") && request.getServerPort() == 443)) {
- request.getMimeHeaders().addValue(":authority").setString(
- request.serverName().getString() + ":" + request.getServerPort());
+ request.getMimeHeaders().addValue(":authority")
+ .setString(request.serverName().getString() + ":" + request.getServerPort());
} else {
request.getMimeHeaders().addValue(":authority").duplicate(request.serverName());
}
@@ -881,16 +869,15 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
private volatile StreamException reset = null;
private volatile boolean endOfStreamSent = false;
- /* The write methods are synchronized to ensure that only one thread at
- * a time is able to access the buffer. Without this protection, a
- * client that performed concurrent writes could corrupt the buffer.
+ /*
+ * The write methods are synchronized to ensure that only one thread at a time is able to access the buffer.
+ * Without this protection, a client that performed concurrent writes could corrupt the buffer.
*/
@Override
public final synchronized int doWrite(ByteBuffer chunk) throws IOException {
if (closed) {
- throw new IOException (
- sm.getString("stream.closed", getConnectionId(), getIdAsString()));
+ throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString()));
}
// chunk is always fully written
int result = chunk.remaining();
@@ -920,12 +907,9 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
final synchronized boolean flush(boolean block) throws IOException {
/*
- * Need to ensure that there is exactly one call to flush even when
- * there is no data to write.
- * Too few calls (i.e. zero) and the end of stream message is not
- * sent for a completed asynchronous write.
- * Too many calls and the end of stream message is sent too soon and
- * trailer headers are not sent.
+ * Need to ensure that there is exactly one call to flush even when there is no data to write. Too few calls
+ * (i.e. zero) and the end of stream message is not sent for a completed asynchronous write. Too many calls
+ * and the end of stream message is sent too soon and trailer headers are not sent.
*/
boolean dataInBuffer = buffer.position() > 0;
boolean flushed = false;
@@ -953,19 +937,17 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
return dataLeft;
}
- private final synchronized boolean flush(boolean writeInProgress, boolean block)
- throws IOException {
+ private final synchronized boolean flush(boolean writeInProgress, boolean block) throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.outputBuffer.flush.debug", getConnectionId(),
- getIdAsString(), Integer.toString(buffer.position()),
- Boolean.toString(writeInProgress), Boolean.toString(closed)));
+ log.debug(sm.getString("stream.outputBuffer.flush.debug", getConnectionId(), getIdAsString(),
+ Integer.toString(buffer.position()), Boolean.toString(writeInProgress),
+ Boolean.toString(closed)));
}
if (buffer.position() == 0) {
if (closed && !endOfStreamSent) {
// Handling this special case here is simpler than trying
// to modify the following code to handle it.
- handler.writeBody(Stream.this, buffer, 0,
- coyoteResponse.getTrailerFields() == null);
+ handler.writeBody(Stream.this, buffer, 0, coyoteResponse.getTrailerFields() == null);
}
// Buffer is empty. Nothing to do.
return false;
@@ -974,7 +956,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
int left = buffer.remaining();
while (left > 0) {
if (streamReservation == 0) {
- streamReservation = reserveWindowSize(left, block);
+ streamReservation = reserveWindowSize(left, block);
if (streamReservation == 0) {
// Must be non-blocking.
// Note: Can't add to the writeBuffer here as the write
@@ -984,8 +966,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
}
while (streamReservation > 0) {
- int connectionReservation =
- handler.reserveWindowSize(Stream.this, streamReservation, block);
+ int connectionReservation = handler.reserveWindowSize(Stream.this, streamReservation, block);
if (connectionReservation == 0) {
// Must be non-blocking.
// Note: Can't add to the writeBuffer here as the write
@@ -994,9 +975,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
return true;
}
// Do the write
- handler.writeBody(Stream.this, buffer, connectionReservation,
- !writeInProgress && closed && left == connectionReservation &&
- coyoteResponse.getTrailerFields() == null);
+ handler.writeBody(Stream.this, buffer, connectionReservation, !writeInProgress && closed &&
+ left == connectionReservation && coyoteResponse.getTrailerFields() == null);
streamReservation -= connectionReservation;
left -= connectionReservation;
}
@@ -1010,8 +990,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
// Only want to return false if the window size is zero AND we are
// already waiting for an allocation.
if (getWindowSize() > 0 && allocationManager.isWaitingForStream() ||
- handler.getWindowSize() > 0 && allocationManager.isWaitingForConnection() ||
- dataLeft) {
+ handler.getWindowSize() > 0 && allocationManager.isWaitingForConnection() || dataLeft) {
return false;
} else {
return true;
@@ -1036,8 +1015,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
/**
- * @return <code>true</code> if it is certain that the associated
- * response has no body.
+ * @return <code>true</code> if it is certain that the associated response has no body.
*/
final boolean hasNoBody() {
return ((written == 0) && closed);
@@ -1046,13 +1024,10 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
@Override
public void flush() throws IOException {
/*
- * This method should only be called during blocking I/O. All the
- * Servlet API calls that end up here are illegal during
- * non-blocking I/O. Servlet 5.4.
- * However, the wording Servlet specification states that the
- * behaviour is undefined so we do the best we can which is to
- * perform a flush using blocking I/O or non-blocking I/O based
- * depending which is currently in use.
+ * This method should only be called during blocking I/O. All the Servlet API calls that end up here are
+ * illegal during non-blocking I/O. Servlet 5.4. However, the wording Servlet specification states that the
+ * behaviour is undefined so we do the best we can which is to perform a flush using blocking I/O or
+ * non-blocking I/O based depending which is currently in use.
*/
flush(getCoyoteResponse().getWriteListener() == null);
}
@@ -1096,23 +1071,18 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
class StandardStreamInputBuffer extends StreamInputBuffer {
- /* Two buffers are required to avoid various multi-threading issues.
- * These issues arise from the fact that the Stream (or the
- * Request/Response) used by the application is processed in one thread
- * but the connection is processed in another. Therefore it is possible
- * that a request body frame could be received before the application
- * is ready to read it. If it isn't buffered, processing of the
- * connection (and hence all streams) would block until the application
- * read the data. Hence the incoming data has to be buffered.
- * If only one buffer was used then it could become corrupted if the
- * connection thread is trying to add to it at the same time as the
- * application is read it. While it should be possible to avoid this
- * corruption by careful use of the buffer it would still require the
- * same copies as using two buffers and the behaviour would be less
- * clear.
+ /*
+ * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the
+ * Stream (or the Request/Response) used by the application is processed in one thread but the connection is
+ * processed in another. Therefore it is possible that a request body frame could be received before the
+ * application is ready to read it. If it isn't buffered, processing of the connection (and hence all streams)
+ * would block until the application read the data. Hence the incoming data has to be buffered. If only one
+ * buffer was used then it could become corrupted if the connection thread is trying to add to it at the same
+ * time as the application is read it. While it should be possible to avoid this corruption by careful use of
+ * the buffer it would still require the same copies as using two buffers and the behaviour would be less clear.
*
- * The buffers are created lazily because they quickly add up to a lot
- * of memory and most requests do not have bodies.
+ * The buffers are created lazily because they quickly add up to a lot of memory and most requests do not have
+ * bodies.
*/
// This buffer is used to populate the ByteChunk passed in to the read
// method
@@ -1125,8 +1095,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
private boolean resetReceived;
@Override
- public final int doRead(ApplicationBufferHandler applicationBufferHandler)
- throws IOException {
+ public final int doRead(ApplicationBufferHandler applicationBufferHandler) throws IOException {
ensureBuffersExist();
@@ -1166,8 +1135,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
if (inBuffer.position() == 0 && isActive() && !isInputFinished()) {
String msg = sm.getString("stream.inputBuffer.readTimeout");
- StreamException se = new StreamException(
- msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
+ StreamException se = new StreamException(msg, Http2Error.ENHANCE_YOUR_CALM, getIdAsInt());
// Trigger a reset once control returns to Tomcat
coyoteResponse.setError();
streamOutputBuffer.reset = se;
@@ -1187,8 +1155,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
inBuffer.flip();
written = inBuffer.remaining();
if (log.isDebugEnabled()) {
- log.debug(sm.getString("stream.inputBuffer.copy",
- Integer.toString(written)));
+ log.debug(sm.getString("stream.inputBuffer.copy", Integer.toString(written)));
}
inBuffer.get(outBuffer, 0, written);
inBuffer.clear();
@@ -1200,7 +1167,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
}
}
- applicationBufferHandler.setByteBuffer(ByteBuffer.wrap(outBuffer, 0, written));
+ applicationBufferHandler.setByteBuffer(ByteBuffer.wrap(outBuffer, 0, written));
// Increment client-side flow control windows by the number of bytes
// read
@@ -1279,7 +1246,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
@Override
final synchronized void insertReplayedBody(ByteChunk body) {
- inBuffer = ByteBuffer.wrap(body.getBytes(), body.getOffset(), body.getLength());
+ inBuffer = ByteBuffer.wrap(body.getBytes(), body.getOffset(), body.getLength());
}
@@ -1338,7 +1305,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter {
// Do this outside of the sync because:
// - it doesn't need to be inside the sync
// - if inside the sync it can trigger a deadlock
- // https://markmail.org/message/vbglzkvj6wxlhh3p
+ // https://markmail.org/message/vbglzkvj6wxlhh3p
if (unreadByteCount > 0) {
handler.onSwallowedDataFramePayload(getIdAsInt(), unreadByteCount);
}
diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java
index dba23bd09c..635949fa34 100644
--- a/java/org/apache/coyote/http2/StreamProcessor.java
+++ b/java/org/apache/coyote/http2/StreamProcessor.java
@@ -67,8 +67,7 @@ class StreamProcessor extends AbstractProcessor {
H2_PSEUDO_HEADERS_REQUEST.add(":path");
}
- StreamProcessor(Http2UpgradeHandler handler, Stream stream, Adapter adapter,
- SocketWrapperBase<?> socketWrapper) {
+ StreamProcessor(Http2UpgradeHandler handler, Stream stream, Adapter adapter, SocketWrapperBase<?> socketWrapper) {
super(adapter, stream.getCoyoteRequest(), stream.getCoyoteResponse());
this.handler = handler;
this.stream = stream;
@@ -95,22 +94,23 @@ class StreamProcessor extends AbstractProcessor {
// fully read. This typically occurs when Tomcat rejects an upload
// of some form (e.g. PUT or POST). Need to tell the client not to
// send any more data on this stream (reset).
- StreamException se = new StreamException(
- sm.getString("streamProcessor.cancel", stream.getConnectionId(),
- stream.getIdAsString()), Http2Error.NO_ERROR, stream.getIdAsInt());
+ StreamException se = new StreamException(sm.getString("streamProcessor.cancel",
+ stream.getConnectionId(), stream.getIdAsString()), Http2Error.NO_ERROR,
+ stream.getIdAsInt());
stream.close(se);
} else if (!getErrorState().isConnectionIoAllowed()) {
- ConnectionException ce = new ConnectionException(sm.getString(
- "streamProcessor.error.connection", stream.getConnectionId(),
- stream.getIdAsString()), Http2Error.INTERNAL_ERROR);
+ ConnectionException ce = new ConnectionException(
+ sm.getString("streamProcessor.error.connection", stream.getConnectionId(),
+ stream.getIdAsString()),
+ Http2Error.INTERNAL_ERROR);
stream.close(ce);
} else if (!getErrorState().isIoAllowed()) {
StreamException se = stream.getResetException();
if (se == null) {
- se = new StreamException(sm.getString(
- "streamProcessor.error.stream", stream.getConnectionId(),
- stream.getIdAsString()), Http2Error.INTERNAL_ERROR,
- stream.getIdAsInt());
+ se = new StreamException(
+ sm.getString("streamProcessor.error.stream", stream.getConnectionId(),
+ stream.getIdAsString()),
+ Http2Error.INTERNAL_ERROR, stream.getIdAsInt());
}
stream.close(se);
} else {
@@ -121,8 +121,8 @@ class StreamProcessor extends AbstractProcessor {
}
}
} catch (Exception e) {
- String msg = sm.getString("streamProcessor.error.connection",
- stream.getConnectionId(), stream.getIdAsString());
+ String msg = sm.getString("streamProcessor.error.connection", stream.getConnectionId(),
+ stream.getIdAsString());
if (log.isDebugEnabled()) {
log.debug(msg, e);
}
@@ -153,15 +153,15 @@ class StreamProcessor extends AbstractProcessor {
private void prepareSendfile() {
- String fileName = (String) stream.getCoyoteRequest().getAttribute(
- org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR);
+ String fileName = (String) stream.getCoyoteRequest()
+ .getAttribute(org.apache.coyote.Constants.SENDFILE_FILENAME_ATTR);
if (fileName != null) {
sendfileData = new SendfileData();
sendfileData.path = new File(fileName).toPath();
- sendfileData.pos = ((Long) stream.getCoyoteRequest().getAttribute(
- org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR)).longValue();
- sendfileData.end = ((Long) stream.getCoyoteRequest().getAttribute(
- org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR)).longValue();
+ sendfileData.pos = ((Long) stream.getCoyoteRequest()
+ .getAttribute(org.apache.coyote.Constants.SENDFILE_FILE_START_ATTR)).longValue();
+ sendfileData.end = ((Long) stream.getCoyoteRequest()
+ .getAttribute(org.apache.coyote.Constants.SENDFILE_FILE_END_ATTR)).longValue();
sendfileData.left = sendfileData.end - sendfileData.pos;
sendfileData.stream = stream;
}
@@ -182,8 +182,7 @@ class StreamProcessor extends AbstractProcessor {
// Compression can't be used with sendfile
// Need to check for compression (and set headers appropriately) before
// adding headers below
- if (noSendfile && protocol != null &&
- protocol.useCompression(coyoteRequest, coyoteResponse)) {
+ if (noSendfile && protocol != null && protocol.useCompression(coyoteRequest, coyoteResponse)) {
// Enable compression. Headers will have been set. Need to configure
// output filter at this point.
stream.addOutputFilter(new GzipOutputFilter());
@@ -333,22 +332,18 @@ class StreamProcessor extends AbstractProcessor {
protected final void executeDispatches() {
Iterator<DispatchType> dispatches = getIteratorAndClearDispatches();
/*
- * Compare with superclass that uses SocketWrapper
- * A sync is not necessary here as the window sizes are updated with
- * syncs before the dispatches are executed and it is the window size
- * updates that need to be complete before the dispatch executes.
+ * Compare with superclass that uses SocketWrapper A sync is not necessary here as the window sizes are updated
+ * with syncs before the dispatches are executed and it is the window size updates that need to be complete
+ * before the dispatch executes.
*/
while (dispatches != null && dispatches.hasNext()) {
DispatchType dispatchType = dispatches.next();
/*
- * Dispatch on new thread.
- * Firstly, this avoids a deadlock on the SocketWrapper as Streams
- * being processed by container threads lock the SocketProcessor
- * before they lock the SocketWrapper which is the opposite order to
- * container threads processing via Http2UpgrageHandler.
- * Secondly, this code executes after a Window update has released
- * one or more Streams. By dispatching each Stream to a dedicated
- * thread, those Streams may progress concurrently.
+ * Dispatch on new thread. Firstly, this avoids a deadlock on the SocketWrapper as Streams being processed
+ * by container threads lock the SocketProcessor before they lock the SocketWrapper which is the opposite
+ * order to container threads processing via Http2UpgrageHandler. Secondly, this code executes after a
+ * Window update has released one or more Streams. By dispatching each Stream to a dedicated thread, those
+ * Streams may progress concurrently.
*/
processSocketEvent(dispatchType.getSocketStatus(), true);
}
@@ -461,21 +456,17 @@ class StreamProcessor extends AbstractProcessor {
/*
- * In HTTP/1.1 some aspects of the request are validated as the request is
- * parsed and the request rejected immediately with a 400 response. These
- * checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2
- * implementation, incoming frames are processed on one thread while the
- * corresponding request/response is processed on a separate thread,
- * rejecting invalid requests is more involved.
+ * In HTTP/1.1 some aspects of the request are validated as the request is parsed and the request rejected
+ * immediately with a 400 response. These checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2
+ * implementation, incoming frames are processed on one thread while the corresponding request/response is processed
+ * on a separate thread, rejecting invalid requests is more involved.
*
- * One approach would be to validate the request during parsing, note any
- * validation errors and then generate a 400 response once processing moves
- * to the separate request/response thread. This would require refactoring
- * to track the validation errors.
+ * One approach would be to validate the request during parsing, note any validation errors and then generate a 400
+ * response once processing moves to the separate request/response thread. This would require refactoring to track
+ * the validation errors.
*
- * A second approach, and the one currently adopted, is to perform the
- * validation shortly after processing of the received request passes to the
- * separate thread and to generate a 400 response if validation fails.
+ * A second approach, and the one currently adopted, is to perform the validation shortly after processing of the
+ * received request passes to the separate thread and to generate a 400 response if validation fails.
*
* The checks performed below are based on the checks in Http11InputBuffer.
*/
@@ -532,8 +523,8 @@ class StreamProcessor extends AbstractProcessor {
@Override
protected final boolean flushBufferedWrite() throws IOException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("streamProcessor.flushBufferedWrite.entry",
- stream.getConnectionId(), stream.getIdAsString()));
+ log.debug(sm.getString("streamProcessor.flushBufferedWrite.entry", stream.getConnectionId(),
+ stream.getIdAsString()));
}
if (stream.flush(false)) {
// The buffer wasn't fully flushed so re-register the
diff --git a/java/org/apache/coyote/http2/StreamStateMachine.java b/java/org/apache/coyote/http2/StreamStateMachine.java
index acc6687d36..389f4e5c6c 100644
--- a/java/org/apache/coyote/http2/StreamStateMachine.java
+++ b/java/org/apache/coyote/http2/StreamStateMachine.java
@@ -25,14 +25,11 @@ import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
- * See <a href="https://tools.ietf.org/html/rfc7540#section-5.1">state
- * diagram</a> in RFC 7540.
- * <br>
+ * 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>
* </ul>
- *
*/
class StreamStateMachine {
@@ -82,20 +79,18 @@ class StreamStateMachine {
/**
- * Marks the stream as reset. This method will not change the stream state
- * if:
+ * 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>
* </ul>
*
- * @throws IllegalStateException If the stream is in a state that does not
- * permit resets
+ * @throws IllegalStateException If the stream is in a state that does not permit resets
*/
public synchronized void sendReset() {
if (state == State.IDLE) {
- throw new IllegalStateException(sm.getString("streamStateMachine.debug.change",
- connectionId, streamId, state));
+ throw new IllegalStateException(
+ sm.getString("streamStateMachine.debug.change", connectionId, streamId, state));
}
if (state.canReset()) {
stateChange(state, State.CLOSED_RST_TX);
@@ -112,8 +107,7 @@ class StreamStateMachine {
if (state == oldState) {
state = newState;
if (log.isDebugEnabled()) {
- log.debug(sm.getString("streamStateMachine.debug.change", connectionId,
- streamId, oldState, newState));
+ log.debug(sm.getString("streamStateMachine.debug.change", connectionId, streamId, oldState, newState));
}
}
}
@@ -124,12 +118,12 @@ class StreamStateMachine {
// the current state of this stream.
if (!isFrameTypePermitted(frameType)) {
if (state.connectionErrorForInvalidFrame) {
- throw new ConnectionException(sm.getString("streamStateMachine.invalidFrame",
- connectionId, streamId, state, frameType),
+ throw new ConnectionException(
+ sm.getString("streamStateMachine.invalidFrame", connectionId, streamId, state, frameType),
state.errorCodeForInvalidFrame);
} else {
- throw new StreamException(sm.getString("streamStateMachine.invalidFrame",
- connectionId, streamId, state, frameType),
+ throw new StreamException(
+ sm.getString("streamStateMachine.invalidFrame", connectionId, streamId, state, frameType),
state.errorCodeForInvalidFrame, Integer.parseInt(streamId));
}
}
@@ -225,9 +219,8 @@ class StreamStateMachine {
private final Http2Error errorCodeForInvalidFrame;
private final Set<FrameType> frameTypesPermitted;
- private State(boolean canRead, boolean canWrite, boolean canReset,
- boolean connectionErrorForInvalidFrame, Http2Error errorCode,
- FrameType... frameTypes) {
+ private State(boolean canRead, boolean canWrite, boolean canReset, boolean connectionErrorForInvalidFrame,
+ Http2Error errorCode, FrameType... frameTypes) {
this.canRead = canRead;
this.canWrite = canWrite;
this.canReset = canReset;
diff --git a/java/org/apache/coyote/http2/WindowAllocationManager.java b/java/org/apache/coyote/http2/WindowAllocationManager.java
index 47d0d1ac1f..94558b15b1 100644
--- a/java/org/apache/coyote/http2/WindowAllocationManager.java
+++ b/java/org/apache/coyote/http2/WindowAllocationManager.java
@@ -23,30 +23,25 @@ import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
/**
- * Tracks whether the stream is waiting for an allocation to the stream flow
- * control window, to the connection flow control window or not waiting for an
- * allocation and only issues allocation notifications when the stream is known
- * to be waiting for the notification.
- *
- * <p>It is possible for a stream to be waiting for a connection allocation when
- * a stream allocation is made. Therefore this class tracks the type of
- * allocation that the stream is waiting for to ensure that notifications are
- * correctly triggered.
- *
- * <p>With the implementation at the time of writing, it is not possible for a
- * stream to receive an unexpected connection notification as these are only
- * issues to streams in the backlog and a stream must be waiting for a
- * connection allocation in order to be placed on the backlog. However, as a
- * precaution, this class protects against unexpected connection notifications.
- *
- * <p>It is important for asynchronous processing not to notify unless a
- * notification is expected else a dispatch will be performed unnecessarily
- * which may lead to unexpected results.
- *
- * <p>A previous implementation used separate locks for the stream and connection
- * notifications. However, correct handling of allocation waiting requires
- * holding the stream lock when making the decision to wait. Therefore both
- * allocations need to wait on the Stream.
+ * Tracks whether the stream is waiting for an allocation to the stream flow control window, to the connection flow
+ * control window or not waiting for an allocation and only issues allocation notifications when the stream is known to
+ * be waiting for the notification.
+ * <p>
+ * It is possible for a stream to be waiting for a connection allocation when a stream allocation is made. Therefore
+ * this class tracks the type of allocation that the stream is waiting for to ensure that notifications are correctly
+ * triggered.
+ * <p>
+ * With the implementation at the time of writing, it is not possible for a stream to receive an unexpected connection
+ * notification as these are only issues to streams in the backlog and a stream must be waiting for a connection
+ * allocation in order to be placed on the backlog. However, as a precaution, this class protects against unexpected
+ * connection notifications.
+ * <p>
+ * It is important for asynchronous processing not to notify unless a notification is expected else a dispatch will be
+ * performed unnecessarily which may lead to unexpected results.
+ * <p>
+ * A previous implementation used separate locks for the stream and connection notifications. However, correct handling
+ * of allocation waiting requires holding the stream lock when making the decision to wait. Therefore both allocations
+ * need to wait on the Stream.
*/
class WindowAllocationManager {
@@ -67,8 +62,8 @@ class WindowAllocationManager {
void waitForStream(long timeout) throws InterruptedException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.waitFor.stream",
- stream.getConnectionId(), stream.getIdAsString(), Long.toString(timeout)));
+ log.debug(sm.getString("windowAllocationManager.waitFor.stream", stream.getConnectionId(),
+ stream.getIdAsString(), Long.toString(timeout)));
}
waitFor(STREAM, timeout);
@@ -77,9 +72,9 @@ class WindowAllocationManager {
void waitForConnection(long timeout) throws InterruptedException {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.waitFor.connection",
- stream.getConnectionId(), stream.getIdAsString(),
- Integer.toString(stream.getConnectionAllocationRequested()), Long.toString(timeout)));
+ log.debug(sm.getString("windowAllocationManager.waitFor.connection", stream.getConnectionId(),
+ stream.getIdAsString(), Integer.toString(stream.getConnectionAllocationRequested()),
+ Long.toString(timeout)));
}
waitFor(CONNECTION, timeout);
@@ -88,8 +83,8 @@ class WindowAllocationManager {
void waitForStreamNonBlocking() {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.waitForNonBlocking.stream",
- stream.getConnectionId(), stream.getIdAsString()));
+ log.debug(sm.getString("windowAllocationManager.waitForNonBlocking.stream", stream.getConnectionId(),
+ stream.getIdAsString()));
}
waitForNonBlocking(STREAM);
@@ -98,8 +93,8 @@ class WindowAllocationManager {
void waitForConnectionNonBlocking() {
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.waitForNonBlocking.connection",
- stream.getConnectionId(), stream.getIdAsString()));
+ log.debug(sm.getString("windowAllocationManager.waitForNonBlocking.connection", stream.getConnectionId(),
+ stream.getIdAsString()));
}
waitForNonBlocking(CONNECTION);
@@ -192,15 +187,15 @@ class WindowAllocationManager {
if (response.getWriteListener() == null) {
// Blocking, so use notify to release StreamOutputBuffer
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.notified",
- stream.getConnectionId(), stream.getIdAsString()));
+ log.debug(sm.getString("windowAllocationManager.notified", stream.getConnectionId(),
+ stream.getIdAsString()));
}
stream.notify();
} else {
// Non-blocking so dispatch
if (log.isDebugEnabled()) {
- log.debug(sm.getString("windowAllocationManager.dispatched",
- stream.getConnectionId(), stream.getIdAsString()));
+ log.debug(sm.getString("windowAllocationManager.dispatched", stream.getConnectionId(),
+ stream.getIdAsString()));
}
response.action(ActionCode.DISPATCH_WRITE, null);
// Need to explicitly execute dispatches on the StreamProcessor
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org