[tomcat] branch master updated: Refactor read and write methods
This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/master by this push: new 436f7a3 Refactor read and write methods 436f7a3 is described below commit 436f7a3989e4edf79dd8bd5ca36826a561d7c9c9 Author: remm AuthorDate: Mon Mar 15 10:31:58 2021 +0100 Refactor read and write methods Remove static to allow including the OpenSSL call error checking on all <= 0 results, as this is much less error prone this way. --- .../tomcat/util/net/openssl/OpenSSLEngine.java | 55 +- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java index 99720f3..a12074a 100644 --- a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java +++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java @@ -234,8 +234,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn * Write plain text data to the OpenSSL internal BIO * * Calling this function with src.remaining == 0 is undefined. + * @throws SSLException if the OpenSSL error check fails */ -private static int writePlaintextData(final long ssl, final ByteBuffer src) { +private int writePlaintextData(final long ssl, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int limit = src.limit(); final int len = Math.min(limit - pos, MAX_PLAINTEXT_LENGTH); @@ -244,6 +246,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (src.isDirect()) { final long addr = Buffer.address(src) + pos; sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -259,6 +264,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn src.limit(limit); sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -277,13 +285,18 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Write encrypted data to the OpenSSL network BIO. + * @throws SSLException if the OpenSSL error check fails */ -private static int writeEncryptedData(final long networkBIO, final ByteBuffer src) { +private int writeEncryptedData(final long networkBIO, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int len = src.remaining(); if (src.isDirect()) { final long addr = Buffer.address(src) + pos; final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -296,6 +309,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn buf.put(src); final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -313,8 +329,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Read plain text data from the OpenSSL internal BIO + * @throws SSLException if the OpenSSL error check fails */ -private static int readPlaintextData(final long ssl, final ByteBuffer dst) { +private int readPlaintextData(final long ssl, final ByteBuffer dst) throws SSLException { +clearLastError(); if (dst.isDirect()) { final int pos = dst.position(); final long addr = Buffer.address(dst) + pos; @@ -323,6 +341,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (sslRead > 0) { dst.position(pos + sslRead); return sslRead; +} else { +checkLastError(); } } else { final int pos = dst.position(); @@ -339,6 +359,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn dst.put(buf);
[tomcat] branch 9.0.x updated: Refactor read and write methods
This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 47981a5 Refactor read and write methods 47981a5 is described below commit 47981a5f09e8caf696ded01cc532cbd0cbb0af88 Author: remm AuthorDate: Mon Mar 15 10:31:58 2021 +0100 Refactor read and write methods Remove static to allow including the OpenSSL call error checking on all <= 0 results, as this is much less error prone this way. --- .../tomcat/util/net/openssl/OpenSSLEngine.java | 55 +- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java index 99720f3..a12074a 100644 --- a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java +++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java @@ -234,8 +234,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn * Write plain text data to the OpenSSL internal BIO * * Calling this function with src.remaining == 0 is undefined. + * @throws SSLException if the OpenSSL error check fails */ -private static int writePlaintextData(final long ssl, final ByteBuffer src) { +private int writePlaintextData(final long ssl, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int limit = src.limit(); final int len = Math.min(limit - pos, MAX_PLAINTEXT_LENGTH); @@ -244,6 +246,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (src.isDirect()) { final long addr = Buffer.address(src) + pos; sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -259,6 +264,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn src.limit(limit); sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -277,13 +285,18 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Write encrypted data to the OpenSSL network BIO. + * @throws SSLException if the OpenSSL error check fails */ -private static int writeEncryptedData(final long networkBIO, final ByteBuffer src) { +private int writeEncryptedData(final long networkBIO, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int len = src.remaining(); if (src.isDirect()) { final long addr = Buffer.address(src) + pos; final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -296,6 +309,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn buf.put(src); final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -313,8 +329,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Read plain text data from the OpenSSL internal BIO + * @throws SSLException if the OpenSSL error check fails */ -private static int readPlaintextData(final long ssl, final ByteBuffer dst) { +private int readPlaintextData(final long ssl, final ByteBuffer dst) throws SSLException { +clearLastError(); if (dst.isDirect()) { final int pos = dst.position(); final long addr = Buffer.address(dst) + pos; @@ -323,6 +341,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (sslRead > 0) { dst.position(pos + sslRead); return sslRead; +} else { +checkLastError(); } } else { final int pos = dst.position(); @@ -339,6 +359,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn dst.put(buf);
[tomcat] branch 8.5.x updated: Refactor read and write methods
This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new 3caab53 Refactor read and write methods 3caab53 is described below commit 3caab53c8e48e9d9fc680f696c42f90461676482 Author: remm AuthorDate: Mon Mar 15 10:31:58 2021 +0100 Refactor read and write methods Remove static to allow including the OpenSSL call error checking on all <= 0 results, as this is much less error prone this way. --- .../tomcat/util/net/openssl/OpenSSLEngine.java | 55 +- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java index 99720f3..a12074a 100644 --- a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java +++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java @@ -234,8 +234,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn * Write plain text data to the OpenSSL internal BIO * * Calling this function with src.remaining == 0 is undefined. + * @throws SSLException if the OpenSSL error check fails */ -private static int writePlaintextData(final long ssl, final ByteBuffer src) { +private int writePlaintextData(final long ssl, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int limit = src.limit(); final int len = Math.min(limit - pos, MAX_PLAINTEXT_LENGTH); @@ -244,6 +246,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (src.isDirect()) { final long addr = Buffer.address(src) + pos; sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -259,6 +264,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn src.limit(limit); sslWrote = SSL.writeToSSL(ssl, addr, len); +if (sslWrote <= 0) { +checkLastError(); +} if (sslWrote >= 0) { src.position(pos + sslWrote); return sslWrote; @@ -277,13 +285,18 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Write encrypted data to the OpenSSL network BIO. + * @throws SSLException if the OpenSSL error check fails */ -private static int writeEncryptedData(final long networkBIO, final ByteBuffer src) { +private int writeEncryptedData(final long networkBIO, final ByteBuffer src) throws SSLException { +clearLastError(); final int pos = src.position(); final int len = src.remaining(); if (src.isDirect()) { final long addr = Buffer.address(src) + pos; final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -296,6 +309,9 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn buf.put(src); final int netWrote = SSL.writeToBIO(networkBIO, addr, len); +if (netWrote <= 0) { +checkLastError(); +} if (netWrote >= 0) { src.position(pos + netWrote); return netWrote; @@ -313,8 +329,10 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn /** * Read plain text data from the OpenSSL internal BIO + * @throws SSLException if the OpenSSL error check fails */ -private static int readPlaintextData(final long ssl, final ByteBuffer dst) { +private int readPlaintextData(final long ssl, final ByteBuffer dst) throws SSLException { +clearLastError(); if (dst.isDirect()) { final int pos = dst.position(); final long addr = Buffer.address(dst) + pos; @@ -323,6 +341,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn if (sslRead > 0) { dst.position(pos + sslRead); return sslRead; +} else { +checkLastError(); } } else { final int pos = dst.position(); @@ -339,6 +359,8 @@ public final class OpenSSLEngine extends SSLEngine implements SSLUtil.ProtocolIn dst.put(buf);
Re: Back-port asyncIO support for HTTP/2 to 8.5.x
On Thu, Mar 11, 2021 at 5:39 PM Mark Thomas wrote: > On 11/03/2021 16:11, Rémy Maucherat wrote: > > On Thu, Mar 11, 2021 at 3:17 PM Mark Thomas wrote: > > > >> A question mainly for Rémy I guess. > >> > >> Any reason not to back-port the asyncIO HTTP/2 implementation to 8.5.x? > >> > > > > Today's my lucky day it seems :) > > > > Ok, so there's a balance between the usefulness of the feature, the > > complexity of the changes, the risk introduced and the stability of more > > ancient branches. The older the branch, the higher the expected stability > > IMO. There's often the scenario of backporting too early: the feature > seems > > fine, but actually it's just not been tested enough yet. > > > > Here, I was thinking the feature is not a must have, and 8.5 is supposed > to > > be really stable now, so I limited the backport to 9 and never considered > > 8.5. I understand the increased usefulness it has if the idea is to > really > > harmonize the h2 code. > > Yes, it is a balance. > > Given the recent flurry of HTTP/2 issues that have affected 8.5.x, 9.0.x > and 10.0.x, I think there is more benefit in harmonization than there is > risk in introducing the async code. > > I think I have most of the alignment complete apart from the async > stuff. I'll try and keep that in a separate commit in case it causes > problems. > After checking, +1 for fully harmonizing the HTTP/2 code, the bug reports are now quite limited and less serious, while we can assume there's significant use of HTTP/2. I looked at the connector code and the backports seem to be there. Rémy
[tomcat] branch master updated (436f7a3 -> 7621923)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git. from 436f7a3 Refactor read and write methods add 7621923 Make fields final after new approach to recycling No new revisions were added by this update. Summary of changes: java/org/apache/coyote/http2/Stream.java | 20 +--- 1 file changed, 5 insertions(+), 15 deletions(-) - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Make fields final after new approach to recycling
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new 4f105d7 Make fields final after new approach to recycling 4f105d7 is described below commit 4f105d7d4f05a34bfc9643032726b619b94bd1bd Author: Mark Thomas AuthorDate: Mon Mar 15 13:55:50 2021 + Make fields final after new approach to recycling The new approach to recycling replaces a Stream instance with a RecycledStream instance. Therefore, the fields that were made non-final so they could be set to null in the old approach to recycling can be restored to being final. --- java/org/apache/coyote/http2/Stream.java | 20 +--- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 8f29489..788bf27 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -67,20 +67,17 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { private final Http2UpgradeHandler handler; private final WindowAllocationManager allocationManager = new WindowAllocationManager(this); +private final Request coyoteRequest; +private final Response coyoteResponse = new Response(); +private final StreamInputBuffer inputBuffer; +private final StreamOutputBuffer streamOutputBuffer = new StreamOutputBuffer(); +private final Http2OutputBuffer http2OutputBuffer = new Http2OutputBuffer(coyoteResponse, streamOutputBuffer); // State machine would be too much overhead private int headerState = HEADER_STATE_START; private StreamException headerException = null; -// These will be set to null once the Stream closes to reduce the memory -// footprint. -private volatile Request coyoteRequest; private volatile StringBuilder cookieHeader = null; -private volatile Response coyoteResponse = new Response(); -private volatile StreamInputBuffer inputBuffer; -private volatile StreamOutputBuffer streamOutputBuffer = new StreamOutputBuffer(); -private volatile Http2OutputBuffer http2OutputBuffer = -new Http2OutputBuffer(coyoteResponse, streamOutputBuffer); Stream(Integer identifier, Http2UpgradeHandler handler) { @@ -482,8 +479,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final ByteBuffer getInputByteBuffer() { -// Avoid NPE if Stream has been closed on Stream specific thread -StreamInputBuffer inputBuffer = this.inputBuffer; if (inputBuffer == null) { return null; } @@ -515,11 +510,6 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final void receivedData(int payloadSize) throws ConnectionException { contentLengthReceived += payloadSize; -Request coyoteRequest = this.coyoteRequest; -// Avoid NPE if Stream has been closed on Stream specific thread -if (coyoteRequest == null) { -return; -} long contentLengthHeader = coyoteRequest.getContentLengthLong(); if (contentLengthHeader > -1 && contentLengthReceived > contentLengthHeader) { throw new ConnectionException(sm.getString("stream.header.contentLength", - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated (47981a5 -> 3a6729a)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git. from 47981a5 Refactor read and write methods add 3a6729a Make fields final after new approach to recycling No new revisions were added by this update. Summary of changes: java/org/apache/coyote/http2/Stream.java | 20 +--- 1 file changed, 5 insertions(+), 15 deletions(-) - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
buildbot failure in on tomcat-85-trunk
The Buildbot has detected a new failure on builder tomcat-85-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-85-trunk/builds/2645 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-85-commit' triggered this build Build Source Stamp: [branch 8.5.x] 4f105d7d4f05a34bfc9643032726b619b94bd1bd Blamelist: Mark Thomas BUILD FAILED: failed shell_8 Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch master updated (7621923 -> 1a7b9d8)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git. from 7621923 Make fields final after new approach to recycling new f4381f7 Rename Output.swallowedPadding to onSwallowedDataFramePayload new db907f9 Rename swallow() -> swallowPayload() new 02c202a Add frameTypeId parameter to swallowedPayload() new 87bb2e0 Expose the actual frameTypeId for unknown frames new 76115a2 Fix BZ 65179 - avoid flow control window exhaustion new 1a7b9d8 Fix failing test after flow control updates The 6 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/FrameType.java| 5 + java/org/apache/coyote/http2/Http2AsyncParser.java | 13 +- java/org/apache/coyote/http2/Http2Parser.java | 149 + .../apache/coyote/http2/Http2UpgradeHandler.java | 24 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 -- test/org/apache/coyote/http2/Http2TestBase.java| 13 +- .../apache/coyote/http2/TestCancelledUpload.java | 73 -- test/org/apache/coyote/http2/TestFlowControl.java | 131 ++ webapps/docs/changelog.xml | 6 + 11 files changed, 362 insertions(+), 140 deletions(-) create mode 100644 test/org/apache/coyote/http2/TestFlowControl.java - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 02/06: Rename swallow() -> swallowPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit db907f9d3cbf604754728e0b4a7e635c1f34299a Author: Mark Thomas AuthorDate: Mon Mar 15 18:01:01 2021 + Rename swallow() -> swallowPayload() --- java/org/apache/coyote/http2/Http2AsyncParser.java | 4 ++-- java/org/apache/coyote/http2/Http2Parser.java | 18 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index ed565fd..ad2ba10 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -106,7 +106,7 @@ class Http2AsyncParser extends Http2Parser { payload.flip(); try { if (streamException) { -swallow(streamId, payloadSize, false, payload); +swallowPayload(streamId, payloadSize, false, payload); } else { readSettingsFrame(flags, payloadSize, payload); } @@ -239,7 +239,7 @@ class Http2AsyncParser extends Http2Parser { do { continueParsing = false; if (streamException) { -swallow(streamId, payloadSize, false, payload); +swallowPayload(streamId, payloadSize, false, payload); } else { switch (frameType) { case DATA: diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 8a852bf..a90028a 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -87,7 +87,7 @@ class Http2Parser { try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallow(streamId, payloadSize, false, null); +swallowPayload(streamId, payloadSize, false, null); throw se; } @@ -171,11 +171,11 @@ class Http2Parser { ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream); if (dest == null) { -swallow(streamId, dataLength, false, buffer); +swallowPayload(streamId, dataLength, false, buffer); // Process padding before sending any notifications in case padding // is invalid. if (padLength > 0) { -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -183,7 +183,7 @@ class Http2Parser { } else { synchronized (dest) { if (dest.remaining() < dataLength) { -swallow(streamId, dataLength, false, buffer); +swallowPayload(streamId, dataLength, false, buffer); // Client has sent more data than permitted by Window size throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); @@ -199,7 +199,7 @@ class Http2Parser { // Process padding before sending any notifications in case // padding is invalid. if (padLength > 0) { -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -224,7 +224,7 @@ class Http2Parser { try { hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); } catch (StreamException se) { -swallow(streamId, payloadSize, false, buffer); +swallowPayload(streamId, payloadSize, false, buffer); throw se; } @@ -268,7 +268,7 @@ class Http2Parser { readHeaderPayload(streamId, payloadSize, buffer); -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); if (Flags.isEndOfHeaders(flags)) { onHeadersComplete(streamId); @@ -518,7 +518,7 @@ class Http2Parser { protected void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) throws IOException { try { -swallow(streamId, payloadSize, false, buffer); +swallowPayload(streamId, payloadSize, false, buffer); } catch (ConnectionException e) { // Will nev
[tomcat] 05/06: Fix BZ 65179 - avoid flow control window exhaustion
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 76115a2a8681e5951aef9037120fa3babeffd9d3 Author: Mark Thomas AuthorDate: Mon Mar 15 17:57:41 2021 + Fix BZ 65179 - avoid flow control window exhaustion Ensure that the connection level flow control window from the client to the server is updated when handling DATA frames received for completed streams else the flow control window may become exhausted https://bz.apache.org/bugzilla/show_bug.cgi?id=65179 --- .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/Http2Parser.java | 82 +++-- .../apache/coyote/http2/Http2UpgradeHandler.java | 22 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 +-- test/org/apache/coyote/http2/Http2TestBase.java| 7 +- test/org/apache/coyote/http2/TestFlowControl.java | 131 + webapps/docs/changelog.xml | 6 + 8 files changed, 271 insertions(+), 65 deletions(-) diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java index 38761ad..0368c4f 100644 --- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java +++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java @@ -16,6 +16,7 @@ */ package org.apache.coyote.http2; +import java.nio.ByteBuffer; import java.util.Iterator; import org.apache.juli.logging.Log; @@ -31,6 +32,8 @@ abstract class AbstractNonZeroStream extends AbstractStream { private static final Log log = LogFactory.getLog(AbstractNonZeroStream.class); private static final StringManager sm = StringManager.getManager(AbstractNonZeroStream.class); +protected static final ByteBuffer ZERO_LENGTH_BYTEBUFFER = ByteBuffer.allocate(0); + protected final StreamStateMachine state; private volatile int weight = Constants.DEFAULT_WEIGHT; @@ -140,4 +143,17 @@ abstract class AbstractNonZeroStream extends AbstractStream { final void checkState(FrameType frameType) throws Http2Exception { state.checkFrameType(frameType); } + + +/** + * 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. + */ +abstract ByteBuffer getInputByteBuffer(); + +abstract void receivedData(int payloadSize) throws Http2Exception; } diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 7e3a86d..0895668 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -175,7 +175,7 @@ class Http2Parser { swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); // Process padding before sending any notifications in case padding // is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); } if (endOfStream) { @@ -183,9 +183,12 @@ class Http2Parser { } } else { synchronized (dest) { -if (dest.remaining() < dataLength) { -swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); +if (dest.remaining() < payloadSize) { // Client has sent more data than permitted by Window size +swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); +if (Flags.hasPadding(flags)) { +swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); +} throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); } @@ -199,7 +202,7 @@ class Http2Parser { } // Process padding before sending any notifications in case // padding is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); } if (endOfStream) { @@ -208,9 +211,6 @@ class Http2Parser { output.endRequestBodyFrame(streamId); } } -if (Flags.hasPadding(flags)) { -output.o
[tomcat] 01/06: Rename Output.swallowedPadding to onSwallowedDataFramePayload
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit f4381f77289554dd01b97d3c8cac08da1832 Author: Mark Thomas AuthorDate: Fri Mar 12 09:55:38 2021 + Rename Output.swallowedPadding to onSwallowedDataFramePayload This change is in preparation for fixes to BZ 65179 --- java/org/apache/coyote/http2/Http2Parser.java | 17 +++-- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 ++-- test/org/apache/coyote/http2/Http2TestBase.java | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 6b2369b..8a852bf 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -208,7 +208,7 @@ class Http2Parser { } } if (Flags.hasPadding(flags)) { -output.swallowedPadding(streamId, padLength); +output.onSwallowedDataFramePayload(streamId, padLength); } } @@ -731,7 +731,20 @@ class Http2Parser { ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception; void endRequestBodyFrame(int streamId) throws Http2Exception; void receivedEndOfStream(int streamId) throws ConnectionException; -void swallowedPadding(int streamId, int paddingLength) throws ConnectionException, IOException; +/** + * 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. + * + * @throws ConnectionException + * @throws IOException + */ +void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException; // Header frames HeaderEmitter headersStart(int streamId, boolean headersEndStream) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index c02d3b0..f39c3c1 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1503,11 +1503,11 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowedPadding(int streamId, int paddingLength) throws +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException { AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId, true); // +1 is for the payload byte used to define the padding length -writeWindowUpdate(abstractNonZeroStream, paddingLength + 1, false); +writeWindowUpdate(abstractNonZeroStream, swallowedDataBytesCount + 1, false); } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index e15c444..ea1a9ac 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1185,10 +1185,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowedPadding(int streamId, int paddingLength) { +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) { trace.append(streamId); -trace.append("-SwallowedPadding-["); -trace.append(paddingLength); +trace.append("-SwallowedDataFramePayload-["); +trace.append(swallowedDataBytesCount); trace.append("]\n"); } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 04/06: Expose the actual frameTypeId for unknown frames
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 87bb2e0f0c2d97d4be050702c06aff45eaf9bee6 Author: Mark Thomas AuthorDate: Mon Mar 15 18:57:37 2021 + Expose the actual frameTypeId for unknown frames --- java/org/apache/coyote/http2/Http2AsyncParser.java | 2 +- java/org/apache/coyote/http2/Http2Parser.java | 24 -- .../apache/coyote/http2/Http2UpgradeHandler.java | 2 +- test/org/apache/coyote/http2/Http2TestBase.java| 4 ++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index 754cc96..f1b1f2d 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -275,7 +275,7 @@ class Http2AsyncParser extends Http2Parser { readContinuationFrame(streamId, flags, payloadSize, payload); break; case UNKNOWN: -readUnknownFrame(streamId, frameType, flags, payloadSize, payload); +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/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index b1c8e15..7e3a86d 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -124,7 +124,7 @@ class Http2Parser { readContinuationFrame(streamId, flags, payloadSize, null); break; case UNKNOWN: -readUnknownFrame(streamId, frameType, flags, payloadSize, null); +readUnknownFrame(streamId, frameTypeId, flags, payloadSize, null); } return true; @@ -516,15 +516,15 @@ class Http2Parser { } -protected void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) +protected void readUnknownFrame(int streamId, int frameTypeId, int flags, int payloadSize, ByteBuffer buffer) throws IOException { try { -swallowPayload(streamId, frameType.getId(), payloadSize, false, buffer); +swallowPayload(streamId, frameTypeId, payloadSize, false, buffer); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false } -output.swallowed(streamId, frameType, flags, payloadSize); +output.onSwallowedUnknownFrame(streamId, frameTypeId, flags, payloadSize); } @@ -776,7 +776,19 @@ class Http2Parser { // Window size void incrementWindowSize(int streamId, int increment) throws Http2Exception; -// Testing -void swallowed(int streamId, FrameType frameType, int flags, int size) throws IOException; +/** + * 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 + * + * @throws IOException + */ +void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } } diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index f39c3c1..1a38f4d 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1768,7 +1768,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) +public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException { // NO-OP. } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index ea1a9ac..012064b 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1172,10 +1172,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) { +
[tomcat] 06/06: Fix failing test after flow control updates
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 1a7b9d8db55c974403a355b04eca563b63e4a5d6 Author: Mark Thomas AuthorDate: Mon Mar 15 19:24:08 2021 + Fix failing test after flow control updates --- .../apache/coyote/http2/TestCancelledUpload.java | 73 -- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index ebaaec0..77c31ba 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -74,26 +74,6 @@ public class TestCancelledUpload extends Http2TestBase { // - reset the stream if further DATA frames are received parser.readFrame(true); -// If reset is first frame received end test here -if (checkReset()) { -return; -} - -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - // Check for reset and exit if found if (checkReset()) { return; @@ -107,58 +87,57 @@ public class TestCancelledUpload extends Http2TestBase { "3-HeadersEnd\n", output.getTrace()); output.clearTrace(); - parser.readFrame(true); + // Check for reset and exit if found if (checkReset()) { return; } -// Not reset, must be request body +// Not window update, not reset, must be the response body Assert.assertEquals("3-Body-0\n" + "3-EndOfStream\n", output.getTrace()); output.clearTrace(); - -// There must be a reset. There may be some WindowSize frames parser.readFrame(true); -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - -// This should be the reset -checkReset(); -Assert.assertEquals("3-RST-[3]\n", output.getTrace()); +Assert.assertTrue(checkReset()); // If there are any more frames after this, ignore them } /* - * Depending on timing, several resets may be sent. + * Looking for a RST frame with error type 3 (flow control error). + * + * If there is a flow control window update for stream 0 it may be followed + * by one for stream 3. + * + * If there is a flow control window update for stream 3 it will always be + * preceded by one for stream 0. */ private boolean checkReset() throws IOException, Http2Exception { +int lastConnectionFlowControlWindowUpdate = -1; while (true) { -if (output.getTrace().startsWith("3-RST-[3]\n")) { +String trace = output.getTrace(); +if (trace.startsWith("3-RST-[3]\n")) { +// This is the reset we are looking for return true; -} else if (output.getTrace().startsWith("3-RST-[")) { -output.clearTrace(); -parser.readFrame(true); +} else if (trace.startsWith("3-RST-[")) { +// Probably error type 8 (cancel) - ignore +} else if (trace.startsWith("0-WindowSize-[")) { +// Connection flow control window update +lastConnectionFlowControlWindowUpdate = Integer.parseInt(trace.substring(14, trace.length() - 2)); +} else if (trace.startsWith("3-WindowSize-[")) { +// Stream flow control window update +// Must be same size as last connection flow control window +// update. True for Tomcat anyway. +Assert.assertEquals("3-WindowSize-[" + lastCon
[tomcat] 03/06: Add frameTypeId parameter to swallowedPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 02c202aae1789ac532e63894a9317bcda7f1fcec Author: Mark Thomas AuthorDate: Mon Mar 15 18:50:29 2021 + Add frameTypeId parameter to swallowedPayload() --- java/org/apache/coyote/http2/FrameType.java| 5 +++ java/org/apache/coyote/http2/Http2AsyncParser.java | 11 --- java/org/apache/coyote/http2/Http2Parser.java | 38 -- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/java/org/apache/coyote/http2/FrameType.java b/java/org/apache/coyote/http2/FrameType.java index 0f17f6f..8734944 100644 --- a/java/org/apache/coyote/http2/FrameType.java +++ b/java/org/apache/coyote/http2/FrameType.java @@ -53,6 +53,11 @@ enum FrameType { } +int getId() { +return id; +} + + byte getIdByte() { return (byte) id; } diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index ad2ba10..754cc96 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -106,7 +106,7 @@ class Http2AsyncParser extends Http2Parser { payload.flip(); try { if (streamException) { -swallowPayload(streamId, payloadSize, false, payload); +swallowPayload(streamId, frameTypeId, payloadSize, false, payload); } else { readSettingsFrame(flags, payloadSize, payload); } @@ -170,6 +170,7 @@ class Http2AsyncParser extends Http2Parser { private boolean validated = false; private CompletionState state = null; protected int payloadSize; +protected int frameTypeId; protected FrameType frameType; protected int flags; protected int streamId; @@ -202,7 +203,8 @@ class Http2AsyncParser extends Http2Parser { } parsedFrameHeader = true; payloadSize = ByteUtil.getThreeBytes(frameHeaderBuffer, 0); -frameType = FrameType.valueOf(ByteUtil.getOneByte(frameHeaderBuffer, 3)); +frameTypeId = ByteUtil.getOneByte(frameHeaderBuffer, 3); +frameType = FrameType.valueOf(frameTypeId); flags = ByteUtil.getOneByte(frameHeaderBuffer, 4); streamId = ByteUtil.get31Bits(frameHeaderBuffer, 5); } @@ -239,7 +241,7 @@ class Http2AsyncParser extends Http2Parser { do { continueParsing = false; if (streamException) { -swallowPayload(streamId, payloadSize, false, payload); +swallowPayload(streamId, frameTypeId, payloadSize, false, payload); } else { switch (frameType) { case DATA: @@ -280,7 +282,8 @@ class Http2AsyncParser extends Http2Parser { if (payload.remaining() >= 9) { int position = payload.position(); payloadSize = ByteUtil.getThreeBytes(payload, position); -frameType = FrameType.valueOf(ByteUtil.getOneByte(payload, position + 3)); +frameTypeId = ByteUtil.getOneByte(payload, position + 3); +frameType = FrameType.valueOf(frameTypeId); flags = ByteUtil.getOneByte(payload, position + 4); streamId = ByteUtil.get31Bits(payload, position + 5); streamException = false; diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index a90028a..b1c8e15 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -80,14 +80,15 @@ class Http2Parser { } int payloadSize = ByteUtil.getThreeBytes(frameHeaderBuffer, 0); -FrameType frameType = FrameType.valueOf(ByteUtil.getOneByte(frameHeaderBuffer, 3)); +int frameTypeId = ByteUtil.getOneByte(frameHeaderBuffer, 3); +FrameType frameType = FrameType.valueOf(frameTypeId); int flags = ByteUtil.getOneByte(frameHeaderBuffer, 4); int streamId = ByteUtil.get31Bits(frameHeaderBuffer, 5); try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallowPayload(streamId, payloadSize, false, null); +swallowPayload(streamId, frameTypeId, payloadSize, false, null); throw se; } @@ -171,11 +172,11 @@ class Http2Parser { ByteBuffer dest = outpu
[tomcat] branch 9.0.x updated (3a6729a -> f65825a)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git. from 3a6729a Make fields final after new approach to recycling new 659d29d Rename Output.swallowedPadding to onSwallowedDataFramePayload new 6cbbcc1 Rename swallow() -> swallowPayload() new 597dc90 Add frameTypeId parameter to swallowedPayload() new 74fe53d Expose the actual frameTypeId for unknown frames new c8034ba Fix BZ 65179 - avoid flow control window exhaustion new f65825a Fix failing test after flow control updates The 6 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/FrameType.java| 5 + java/org/apache/coyote/http2/Http2AsyncParser.java | 13 +- java/org/apache/coyote/http2/Http2Parser.java | 149 + .../apache/coyote/http2/Http2UpgradeHandler.java | 24 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 -- test/org/apache/coyote/http2/Http2TestBase.java| 13 +- .../apache/coyote/http2/TestCancelledUpload.java | 73 -- test/org/apache/coyote/http2/TestFlowControl.java | 131 ++ webapps/docs/changelog.xml | 6 + 11 files changed, 362 insertions(+), 140 deletions(-) create mode 100644 test/org/apache/coyote/http2/TestFlowControl.java - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 03/06: Add frameTypeId parameter to swallowedPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 597dc90fb703d74d3778c1a2ee4f9dbd531581b8 Author: Mark Thomas AuthorDate: Mon Mar 15 18:50:29 2021 + Add frameTypeId parameter to swallowedPayload() --- java/org/apache/coyote/http2/FrameType.java| 5 +++ java/org/apache/coyote/http2/Http2AsyncParser.java | 11 --- java/org/apache/coyote/http2/Http2Parser.java | 38 -- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/java/org/apache/coyote/http2/FrameType.java b/java/org/apache/coyote/http2/FrameType.java index 0f17f6f..8734944 100644 --- a/java/org/apache/coyote/http2/FrameType.java +++ b/java/org/apache/coyote/http2/FrameType.java @@ -53,6 +53,11 @@ enum FrameType { } +int getId() { +return id; +} + + byte getIdByte() { return (byte) id; } diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index 76dd855..296b84e 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -106,7 +106,7 @@ class Http2AsyncParser extends Http2Parser { payload.flip(); try { if (streamException) { -swallowPayload(streamId, payloadSize, false, payload); +swallowPayload(streamId, frameTypeId, payloadSize, false, payload); } else { readSettingsFrame(flags, payloadSize, payload); } @@ -170,6 +170,7 @@ class Http2AsyncParser extends Http2Parser { private boolean validated = false; private CompletionState state = null; protected int payloadSize; +protected int frameTypeId; protected FrameType frameType; protected int flags; protected int streamId; @@ -202,7 +203,8 @@ class Http2AsyncParser extends Http2Parser { } parsedFrameHeader = true; payloadSize = ByteUtil.getThreeBytes(frameHeaderBuffer, 0); -frameType = FrameType.valueOf(ByteUtil.getOneByte(frameHeaderBuffer, 3)); +frameTypeId = ByteUtil.getOneByte(frameHeaderBuffer, 3); +frameType = FrameType.valueOf(frameTypeId); flags = ByteUtil.getOneByte(frameHeaderBuffer, 4); streamId = ByteUtil.get31Bits(frameHeaderBuffer, 5); } @@ -239,7 +241,7 @@ class Http2AsyncParser extends Http2Parser { do { continueParsing = false; if (streamException) { -swallowPayload(streamId, payloadSize, false, payload); +swallowPayload(streamId, frameTypeId, payloadSize, false, payload); } else { switch (frameType) { case DATA: @@ -280,7 +282,8 @@ class Http2AsyncParser extends Http2Parser { if (payload.remaining() >= 9) { int position = payload.position(); payloadSize = ByteUtil.getThreeBytes(payload, position); -frameType = FrameType.valueOf(ByteUtil.getOneByte(payload, position + 3)); +frameTypeId = ByteUtil.getOneByte(payload, position + 3); +frameType = FrameType.valueOf(frameTypeId); flags = ByteUtil.getOneByte(payload, position + 4); streamId = ByteUtil.get31Bits(payload, position + 5); streamException = false; diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 6082edf..32d8205 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -80,14 +80,15 @@ class Http2Parser { } int payloadSize = ByteUtil.getThreeBytes(frameHeaderBuffer, 0); -FrameType frameType = FrameType.valueOf(ByteUtil.getOneByte(frameHeaderBuffer, 3)); +int frameTypeId = ByteUtil.getOneByte(frameHeaderBuffer, 3); +FrameType frameType = FrameType.valueOf(frameTypeId); int flags = ByteUtil.getOneByte(frameHeaderBuffer, 4); int streamId = ByteUtil.get31Bits(frameHeaderBuffer, 5); try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallowPayload(streamId, payloadSize, false, null); +swallowPayload(streamId, frameTypeId, payloadSize, false, null); throw se; } @@ -171,11 +172,11 @@ class Http2Parser { ByteBuffer dest = output
[tomcat] 02/06: Rename swallow() -> swallowPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 6cbbcc149466a95bd2ee3bb4efacdc0723b683ad Author: Mark Thomas AuthorDate: Mon Mar 15 18:01:01 2021 + Rename swallow() -> swallowPayload() --- java/org/apache/coyote/http2/Http2AsyncParser.java | 4 ++-- java/org/apache/coyote/http2/Http2Parser.java | 18 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index 12fa3bb..76dd855 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -106,7 +106,7 @@ class Http2AsyncParser extends Http2Parser { payload.flip(); try { if (streamException) { -swallow(streamId, payloadSize, false, payload); +swallowPayload(streamId, payloadSize, false, payload); } else { readSettingsFrame(flags, payloadSize, payload); } @@ -239,7 +239,7 @@ class Http2AsyncParser extends Http2Parser { do { continueParsing = false; if (streamException) { -swallow(streamId, payloadSize, false, payload); +swallowPayload(streamId, payloadSize, false, payload); } else { switch (frameType) { case DATA: diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 7299ba6..6082edf 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -87,7 +87,7 @@ class Http2Parser { try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallow(streamId, payloadSize, false, null); +swallowPayload(streamId, payloadSize, false, null); throw se; } @@ -171,11 +171,11 @@ class Http2Parser { ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream); if (dest == null) { -swallow(streamId, dataLength, false, buffer); +swallowPayload(streamId, dataLength, false, buffer); // Process padding before sending any notifications in case padding // is invalid. if (padLength > 0) { -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -183,7 +183,7 @@ class Http2Parser { } else { synchronized (dest) { if (dest.remaining() < dataLength) { -swallow(streamId, dataLength, false, buffer); +swallowPayload(streamId, dataLength, false, buffer); // Client has sent more data than permitted by Window size throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); @@ -199,7 +199,7 @@ class Http2Parser { // Process padding before sending any notifications in case // padding is invalid. if (padLength > 0) { -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -224,7 +224,7 @@ class Http2Parser { try { hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); } catch (StreamException se) { -swallow(streamId, payloadSize, false, buffer); +swallowPayload(streamId, payloadSize, false, buffer); throw se; } @@ -268,7 +268,7 @@ class Http2Parser { readHeaderPayload(streamId, payloadSize, buffer); -swallow(streamId, padLength, true, buffer); +swallowPayload(streamId, padLength, true, buffer); if (Flags.isEndOfHeaders(flags)) { onHeadersComplete(streamId); @@ -518,7 +518,7 @@ class Http2Parser { protected void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) throws IOException { try { -swallow(streamId, payloadSize, false, buffer); +swallowPayload(streamId, payloadSize, false, buffer); } catch (ConnectionException e) { // Will neve
[tomcat] 05/06: Fix BZ 65179 - avoid flow control window exhaustion
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit c8034ba400680ef49c1887df7da93472543d2aac Author: Mark Thomas AuthorDate: Mon Mar 15 17:57:41 2021 + Fix BZ 65179 - avoid flow control window exhaustion Ensure that the connection level flow control window from the client to the server is updated when handling DATA frames received for completed streams else the flow control window may become exhausted https://bz.apache.org/bugzilla/show_bug.cgi?id=65179 --- .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/Http2Parser.java | 82 +++-- .../apache/coyote/http2/Http2UpgradeHandler.java | 22 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 +-- test/org/apache/coyote/http2/Http2TestBase.java| 7 +- test/org/apache/coyote/http2/TestFlowControl.java | 131 + webapps/docs/changelog.xml | 6 + 8 files changed, 271 insertions(+), 65 deletions(-) diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java index 38761ad..0368c4f 100644 --- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java +++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java @@ -16,6 +16,7 @@ */ package org.apache.coyote.http2; +import java.nio.ByteBuffer; import java.util.Iterator; import org.apache.juli.logging.Log; @@ -31,6 +32,8 @@ abstract class AbstractNonZeroStream extends AbstractStream { private static final Log log = LogFactory.getLog(AbstractNonZeroStream.class); private static final StringManager sm = StringManager.getManager(AbstractNonZeroStream.class); +protected static final ByteBuffer ZERO_LENGTH_BYTEBUFFER = ByteBuffer.allocate(0); + protected final StreamStateMachine state; private volatile int weight = Constants.DEFAULT_WEIGHT; @@ -140,4 +143,17 @@ abstract class AbstractNonZeroStream extends AbstractStream { final void checkState(FrameType frameType) throws Http2Exception { state.checkFrameType(frameType); } + + +/** + * 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. + */ +abstract ByteBuffer getInputByteBuffer(); + +abstract void receivedData(int payloadSize) throws Http2Exception; } diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index cad0fd4..0550496 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -175,7 +175,7 @@ class Http2Parser { swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); // Process padding before sending any notifications in case padding // is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); } if (endOfStream) { @@ -183,9 +183,12 @@ class Http2Parser { } } else { synchronized (dest) { -if (dest.remaining() < dataLength) { -swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); +if (dest.remaining() < payloadSize) { // Client has sent more data than permitted by Window size +swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false, buffer); +if (Flags.hasPadding(flags)) { +swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); +} throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); } @@ -199,7 +202,7 @@ class Http2Parser { } // Process padding before sending any notifications in case // padding is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true, buffer); } if (endOfStream) { @@ -208,9 +211,6 @@ class Http2Parser { output.endRequestBodyFrame(streamId); } } -if (Flags.hasPadding(flags)) { -output.on
[tomcat] 01/06: Rename Output.swallowedPadding to onSwallowedDataFramePayload
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 659d29df58be5c87793a0435f5b84e8fa8820140 Author: Mark Thomas AuthorDate: Fri Mar 12 09:55:38 2021 + Rename Output.swallowedPadding to onSwallowedDataFramePayload This change is in preparation for fixes to BZ 65179 --- java/org/apache/coyote/http2/Http2Parser.java | 17 +++-- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 ++-- test/org/apache/coyote/http2/Http2TestBase.java | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 4725a1f..7299ba6 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -208,7 +208,7 @@ class Http2Parser { } } if (Flags.hasPadding(flags)) { -output.swallowedPadding(streamId, padLength); +output.onSwallowedDataFramePayload(streamId, padLength); } } @@ -731,7 +731,20 @@ class Http2Parser { ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception; void endRequestBodyFrame(int streamId) throws Http2Exception; void receivedEndOfStream(int streamId) throws ConnectionException; -void swallowedPadding(int streamId, int paddingLength) throws ConnectionException, IOException; +/** + * 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. + * + * @throws ConnectionException + * @throws IOException + */ +void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException; // Header frames HeaderEmitter headersStart(int streamId, boolean headersEndStream) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index 6c59771..ea43873 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1503,11 +1503,11 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowedPadding(int streamId, int paddingLength) throws +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException { AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId, true); // +1 is for the payload byte used to define the padding length -writeWindowUpdate(abstractNonZeroStream, paddingLength + 1, false); +writeWindowUpdate(abstractNonZeroStream, swallowedDataBytesCount + 1, false); } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index 7e04cfc..eb9f83b 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1182,10 +1182,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowedPadding(int streamId, int paddingLength) { +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) { trace.append(streamId); -trace.append("-SwallowedPadding-["); -trace.append(paddingLength); +trace.append("-SwallowedDataFramePayload-["); +trace.append(swallowedDataBytesCount); trace.append("]\n"); } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 04/06: Expose the actual frameTypeId for unknown frames
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 74fe53dfe91412f75e69b5522def4bb752fab3b4 Author: Mark Thomas AuthorDate: Mon Mar 15 18:57:37 2021 + Expose the actual frameTypeId for unknown frames --- java/org/apache/coyote/http2/Http2AsyncParser.java | 2 +- java/org/apache/coyote/http2/Http2Parser.java | 24 -- .../apache/coyote/http2/Http2UpgradeHandler.java | 2 +- test/org/apache/coyote/http2/Http2TestBase.java| 4 ++-- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncParser.java b/java/org/apache/coyote/http2/Http2AsyncParser.java index 296b84e..eefc4c7 100644 --- a/java/org/apache/coyote/http2/Http2AsyncParser.java +++ b/java/org/apache/coyote/http2/Http2AsyncParser.java @@ -275,7 +275,7 @@ class Http2AsyncParser extends Http2Parser { readContinuationFrame(streamId, flags, payloadSize, payload); break; case UNKNOWN: -readUnknownFrame(streamId, frameType, flags, payloadSize, payload); +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/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 32d8205..cad0fd4 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -124,7 +124,7 @@ class Http2Parser { readContinuationFrame(streamId, flags, payloadSize, null); break; case UNKNOWN: -readUnknownFrame(streamId, frameType, flags, payloadSize, null); +readUnknownFrame(streamId, frameTypeId, flags, payloadSize, null); } return true; @@ -516,15 +516,15 @@ class Http2Parser { } -protected void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize, ByteBuffer buffer) +protected void readUnknownFrame(int streamId, int frameTypeId, int flags, int payloadSize, ByteBuffer buffer) throws IOException { try { -swallowPayload(streamId, frameType.getId(), payloadSize, false, buffer); +swallowPayload(streamId, frameTypeId, payloadSize, false, buffer); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false } -output.swallowed(streamId, frameType, flags, payloadSize); +output.onSwallowedUnknownFrame(streamId, frameTypeId, flags, payloadSize); } @@ -776,7 +776,19 @@ class Http2Parser { // Window size void incrementWindowSize(int streamId, int increment) throws Http2Exception; -// Testing -void swallowed(int streamId, FrameType frameType, int flags, int size) throws IOException; +/** + * 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 + * + * @throws IOException + */ +void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } } diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index ea43873..ca6b7a7 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1768,7 +1768,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) +public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException { // NO-OP. } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index eb9f83b..ef1ccbe 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1169,10 +1169,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) { +
[tomcat] 06/06: Fix failing test after flow control updates
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit f65825a77fdbcc225c895c43c371674ae87c3b79 Author: Mark Thomas AuthorDate: Mon Mar 15 19:24:08 2021 + Fix failing test after flow control updates --- .../apache/coyote/http2/TestCancelledUpload.java | 73 -- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index 9964aa4..accd4b3 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -73,26 +73,6 @@ public class TestCancelledUpload extends Http2TestBase { // - reset the stream if further DATA frames are received parser.readFrame(true); -// If reset is first frame received end test here -if (checkReset()) { -return; -} - -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - // Check for reset and exit if found if (checkReset()) { return; @@ -106,58 +86,57 @@ public class TestCancelledUpload extends Http2TestBase { "3-HeadersEnd\n", output.getTrace()); output.clearTrace(); - parser.readFrame(true); + // Check for reset and exit if found if (checkReset()) { return; } -// Not reset, must be request body +// Not window update, not reset, must be the response body Assert.assertEquals("3-Body-0\n" + "3-EndOfStream\n", output.getTrace()); output.clearTrace(); - -// There must be a reset. There may be some WindowSize frames parser.readFrame(true); -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - -// This should be the reset -checkReset(); -Assert.assertEquals("3-RST-[3]\n", output.getTrace()); +Assert.assertTrue(checkReset()); // If there are any more frames after this, ignore them } /* - * Depending on timing, several resets may be sent. + * Looking for a RST frame with error type 3 (flow control error). + * + * If there is a flow control window update for stream 0 it may be followed + * by one for stream 3. + * + * If there is a flow control window update for stream 3 it will always be + * preceded by one for stream 0. */ private boolean checkReset() throws IOException, Http2Exception { +int lastConnectionFlowControlWindowUpdate = -1; while (true) { -if (output.getTrace().startsWith("3-RST-[3]\n")) { +String trace = output.getTrace(); +if (trace.startsWith("3-RST-[3]\n")) { +// This is the reset we are looking for return true; -} else if (output.getTrace().startsWith("3-RST-[")) { -output.clearTrace(); -parser.readFrame(true); +} else if (trace.startsWith("3-RST-[")) { +// Probably error type 8 (cancel) - ignore +} else if (trace.startsWith("0-WindowSize-[")) { +// Connection flow control window update +lastConnectionFlowControlWindowUpdate = Integer.parseInt(trace.substring(14, trace.length() - 2)); +} else if (trace.startsWith("3-WindowSize-[")) { +// Stream flow control window update +// Must be same size as last connection flow control window +// update. True for Tomcat anyway. +Assert.assertEquals("3-WindowSize-[" + lastConn
buildbot failure in on tomcat-trunk
The Buildbot has detected a new failure on builder tomcat-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-trunk/builds/5728 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-commit' triggered this build Build Source Stamp: [branch master] 1a7b9d8db55c974403a355b04eca563b63e4a5d6 Blamelist: Mark Thomas BUILD FAILED: failed compile Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
buildbot failure in on tomcat-9-trunk
The Buildbot has detected a new failure on builder tomcat-9-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-9-trunk/builds/681 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-9-commit' triggered this build Build Source Stamp: [branch 9.0.x] f65825a77fdbcc225c895c43c371674ae87c3b79 Blamelist: Mark Thomas BUILD FAILED: failed compile Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch master updated: Fix Javadoc errors
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/master by this push: new ea3c2b5 Fix Javadoc errors ea3c2b5 is described below commit ea3c2b57e6c8ae5bbdaee2ea0f77d965653e654f Author: Mark Thomas AuthorDate: Mon Mar 15 19:46:10 2021 + Fix Javadoc errors --- java/org/apache/coyote/http2/Http2Parser.java | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 0895668..bf0565d 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -759,8 +759,9 @@ class Http2Parser { * @param swallowedDataBytesCount The number of bytes that the parser * swallowed. * - * @throws ConnectionException - * @throws IOException + * @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; @@ -801,7 +802,8 @@ class Http2Parser { * frame * @param size The payload size of the swallowed frame * - * @throws IOException + * @throws IOException If an I/O occurred while swallowing the unknown + * frame */ void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Fix Javadoc errors
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 8ed432b Fix Javadoc errors 8ed432b is described below commit 8ed432b3a62157ce766dc76c4deb8579bd1e6bba Author: Mark Thomas AuthorDate: Mon Mar 15 19:46:10 2021 + Fix Javadoc errors --- java/org/apache/coyote/http2/Http2Parser.java | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 0550496..65be925 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -759,8 +759,9 @@ class Http2Parser { * @param swallowedDataBytesCount The number of bytes that the parser * swallowed. * - * @throws ConnectionException - * @throws IOException + * @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; @@ -801,7 +802,8 @@ class Http2Parser { * frame * @param size The payload size of the swallowed frame * - * @throws IOException + * @throws IOException If an I/O occurred while swallowing the unknown + * frame */ void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated (4f105d7 -> 14adbe2)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git. from 4f105d7 Make fields final after new approach to recycling new 26a5bfc Rename Output.swallowedPadding to onSwallowedDataFramePayload new 8f40712 Rename swallow() -> swallowPayload() new 6a52ef0 Add frameTypeId parameter to swallowedPayload() new adeb053 Expose the actual frameTypeId for unknown frames new f32ecf4 Fix BZ 65179 - avoid flow control window exhaustion new 8a7407e Fix failing test after flow control updates new 554bbd9 Fix failing test new 14adbe2 Fix Javadoc errors The 8 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/FrameType.java| 5 + java/org/apache/coyote/http2/Http2Parser.java | 136 +++-- .../apache/coyote/http2/Http2UpgradeHandler.java | 24 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 +-- test/org/apache/coyote/http2/Http2TestBase.java| 13 +- .../apache/coyote/http2/TestCancelledUpload.java | 73 --- test/org/apache/coyote/http2/TestFlowControl.java | 131 webapps/docs/changelog.xml | 6 + 10 files changed, 355 insertions(+), 121 deletions(-) create mode 100644 test/org/apache/coyote/http2/TestFlowControl.java - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 01/08: Rename Output.swallowedPadding to onSwallowedDataFramePayload
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 26a5bfc64c9e67f71180104a41e922a82cb187ad Author: Mark Thomas AuthorDate: Fri Mar 12 09:55:38 2021 + Rename Output.swallowedPadding to onSwallowedDataFramePayload This change is in preparation for fixes to BZ 65179 --- java/org/apache/coyote/http2/Http2Parser.java | 17 +++-- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 4 ++-- test/org/apache/coyote/http2/Http2TestBase.java | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index a20ee33..6552d23 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -196,7 +196,7 @@ class Http2Parser { } } if (Flags.hasPadding(flags)) { -output.swallowedPadding(streamId, padLength); +output.onSwallowedDataFramePayload(streamId, padLength); } } @@ -641,7 +641,20 @@ class Http2Parser { ByteBuffer startRequestBodyFrame(int streamId, int payloadSize, boolean endOfStream) throws Http2Exception; void endRequestBodyFrame(int streamId) throws Http2Exception; void receivedEndOfStream(int streamId) throws ConnectionException; -void swallowedPadding(int streamId, int paddingLength) throws ConnectionException, IOException; +/** + * 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. + * + * @throws ConnectionException + * @throws IOException + */ +void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException; // Header frames HeaderEmitter headersStart(int streamId, boolean headersEndStream) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index 149ec79..02e6b9d 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1610,11 +1610,11 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowedPadding(int streamId, int paddingLength) throws +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) throws ConnectionException, IOException { AbstractNonZeroStream abstractNonZeroStream = getAbstractNonZeroStream(streamId, true); // +1 is for the payload byte used to define the padding length -writeWindowUpdate(abstractNonZeroStream, paddingLength + 1, false); +writeWindowUpdate(abstractNonZeroStream, swallowedDataBytesCount + 1, false); } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index 332a2f7..bb3f145 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1197,10 +1197,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowedPadding(int streamId, int paddingLength) { +public void onSwallowedDataFramePayload(int streamId, int swallowedDataBytesCount) { trace.append(streamId); -trace.append("-SwallowedPadding-["); -trace.append(paddingLength); +trace.append("-SwallowedDataFramePayload-["); +trace.append(swallowedDataBytesCount); trace.append("]\n"); } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 05/08: Fix BZ 65179 - avoid flow control window exhaustion
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit f32ecf47dde6a452559065ad999db7a75eb7ecd4 Author: Mark Thomas AuthorDate: Mon Mar 15 17:57:41 2021 + Fix BZ 65179 - avoid flow control window exhaustion Ensure that the connection level flow control window from the client to the server is updated when handling DATA frames received for completed streams else the flow control window may become exhausted https://bz.apache.org/bugzilla/show_bug.cgi?id=65179 --- .../apache/coyote/http2/AbstractNonZeroStream.java | 16 +++ java/org/apache/coyote/http2/Http2Parser.java | 66 +++ .../apache/coyote/http2/Http2UpgradeHandler.java | 22 ++-- java/org/apache/coyote/http2/RecycledStream.java | 30 - java/org/apache/coyote/http2/Stream.java | 42 +-- test/org/apache/coyote/http2/Http2TestBase.java| 7 +- test/org/apache/coyote/http2/TestFlowControl.java | 131 + webapps/docs/changelog.xml | 6 + 8 files changed, 264 insertions(+), 56 deletions(-) diff --git a/java/org/apache/coyote/http2/AbstractNonZeroStream.java b/java/org/apache/coyote/http2/AbstractNonZeroStream.java index 38761ad..0368c4f 100644 --- a/java/org/apache/coyote/http2/AbstractNonZeroStream.java +++ b/java/org/apache/coyote/http2/AbstractNonZeroStream.java @@ -16,6 +16,7 @@ */ package org.apache.coyote.http2; +import java.nio.ByteBuffer; import java.util.Iterator; import org.apache.juli.logging.Log; @@ -31,6 +32,8 @@ abstract class AbstractNonZeroStream extends AbstractStream { private static final Log log = LogFactory.getLog(AbstractNonZeroStream.class); private static final StringManager sm = StringManager.getManager(AbstractNonZeroStream.class); +protected static final ByteBuffer ZERO_LENGTH_BYTEBUFFER = ByteBuffer.allocate(0); + protected final StreamStateMachine state; private volatile int weight = Constants.DEFAULT_WEIGHT; @@ -140,4 +143,17 @@ abstract class AbstractNonZeroStream extends AbstractStream { final void checkState(FrameType frameType) throws Http2Exception { state.checkFrameType(frameType); } + + +/** + * 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. + */ +abstract ByteBuffer getInputByteBuffer(); + +abstract void receivedData(int payloadSize) throws Http2Exception; } diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 1cf6f77..3f0e1b8 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -170,7 +170,7 @@ class Http2Parser { swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false); // Process padding before sending any notifications in case padding // is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true); } if (endOfStream) { @@ -178,16 +178,19 @@ class Http2Parser { } } else { synchronized (dest) { -if (dest.remaining() < dataLength) { -swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false); +if (dest.remaining() < payloadSize) { // Client has sent more data than permitted by Window size +swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false); +if (Flags.hasPadding(flags)) { +swallowPayload(streamId, FrameType.DATA.getId(), padLength, true); +} throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); } input.fill(true, dest, dataLength); // Process padding before sending any notifications in case // padding is invalid. -if (padLength > 0) { +if (Flags.hasPadding(flags)) { swallowPayload(streamId, FrameType.DATA.getId(), padLength, true); } if (endOfStream) { @@ -196,9 +199,6 @@ class Http2Parser { output.endRequestBodyFrame(streamId); } } -if (Flags.hasPadding(flags)) { -output.onSwallowedDataFramePayload(streamId, padLength); -
[tomcat] 04/08: Expose the actual frameTypeId for unknown frames
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit adeb0533b3f67d172df73692344b51fe69fb6a16 Author: Mark Thomas AuthorDate: Mon Mar 15 18:57:37 2021 + Expose the actual frameTypeId for unknown frames --- java/org/apache/coyote/http2/Http2Parser.java | 24 -- .../apache/coyote/http2/Http2UpgradeHandler.java | 2 +- test/org/apache/coyote/http2/Http2TestBase.java| 4 ++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 42647c8..1cf6f77 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -122,7 +122,7 @@ class Http2Parser { readContinuationFrame(streamId, flags, payloadSize); break; case UNKNOWN: -readUnknownFrame(streamId, frameType, flags, payloadSize); +readUnknownFrame(streamId, frameTypeId, flags, payloadSize); } return true; @@ -459,15 +459,15 @@ class Http2Parser { } -private void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize) +protected void readUnknownFrame(int streamId, int frameTypeId, int flags, int payloadSize) throws IOException { try { -swallowPayload(streamId, frameType.getId(), payloadSize, false); +swallowPayload(streamId, frameTypeId, payloadSize, false); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false } -output.swallowed(streamId, frameType, flags, payloadSize); +output.onSwallowedUnknownFrame(streamId, frameTypeId, flags, payloadSize); } @@ -697,7 +697,19 @@ class Http2Parser { // Window size void incrementWindowSize(int streamId, int increment) throws Http2Exception; -// Testing -void swallowed(int streamId, FrameType frameType, int flags, int size) throws IOException; +/** + * 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 + * + * @throws IOException + */ +void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } } diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index 02e6b9d..3c82718 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1875,7 +1875,7 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) +public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException { // NO-OP. } diff --git a/test/org/apache/coyote/http2/Http2TestBase.java b/test/org/apache/coyote/http2/Http2TestBase.java index bb3f145..f459a40 100644 --- a/test/org/apache/coyote/http2/Http2TestBase.java +++ b/test/org/apache/coyote/http2/Http2TestBase.java @@ -1184,10 +1184,10 @@ public abstract class Http2TestBase extends TomcatBaseTest { @Override -public void swallowed(int streamId, FrameType frameType, int flags, int size) { +public void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) { trace.append(streamId); trace.append(","); -trace.append(frameType); +trace.append(frameTypeId); trace.append(","); trace.append(flags); trace.append(","); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 07/08: Fix failing test
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 554bbd95c43b2ab0251a32c6b01de5d950f60cf7 Author: Mark Thomas AuthorDate: Mon Mar 15 19:47:05 2021 + Fix failing test --- test/org/apache/coyote/http2/TestFlowControl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/org/apache/coyote/http2/TestFlowControl.java b/test/org/apache/coyote/http2/TestFlowControl.java index 3841a1d..f49c13c 100644 --- a/test/org/apache/coyote/http2/TestFlowControl.java +++ b/test/org/apache/coyote/http2/TestFlowControl.java @@ -87,10 +87,10 @@ public class TestFlowControl extends Http2TestBase { "3-Header-[:status]-[404]\n" + "3-Header-[content-type]-[text/html;charset=utf-8]\n" + "3-Header-[content-language]-[en]\n" + -"3-Header-[content-length]-[692]\n" + +"3-Header-[content-length]-[691]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + -"3-Body-692\n" + +"3-Body-691\n" + "3-EndOfStream\n" + "3-RST-[8]\n", output.getTrace()); output.clearTrace(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 02/08: Rename swallow() -> swallowPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 8f407126031d8a8b8b0ed3de24ef58f01697139e Author: Mark Thomas AuthorDate: Mon Mar 15 19:29:57 2021 + Rename swallow() -> swallowPayload() --- java/org/apache/coyote/http2/Http2Parser.java | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 6552d23..2bcfb2a 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -85,7 +85,7 @@ class Http2Parser { try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallow(streamId, payloadSize, false); +swallowPayload(streamId, payloadSize, false); throw se; } @@ -166,11 +166,11 @@ class Http2Parser { ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream); if (dest == null) { -swallow(streamId, dataLength, false); +swallowPayload(streamId, dataLength, false); // Process padding before sending any notifications in case padding // is invalid. if (padLength > 0) { -swallow(streamId, padLength, true); +swallowPayload(streamId, padLength, true); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -178,7 +178,7 @@ class Http2Parser { } else { synchronized (dest) { if (dest.remaining() < dataLength) { -swallow(streamId, dataLength, false); +swallowPayload(streamId, dataLength, false); // Client has sent more data than permitted by Window size throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); @@ -187,7 +187,7 @@ class Http2Parser { // Process padding before sending any notifications in case // padding is invalid. if (padLength > 0) { -swallow(streamId, padLength, true); +swallowPayload(streamId, padLength, true); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -212,7 +212,7 @@ class Http2Parser { try { hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); } catch (StreamException se) { -swallow(streamId, payloadSize, false); +swallowPayload(streamId, payloadSize, false); throw se; } @@ -252,7 +252,7 @@ class Http2Parser { readHeaderPayload(streamId, payloadSize); -swallow(streamId, padLength, true); +swallowPayload(streamId, padLength, true); if (Flags.isEndOfHeaders(flags)) { onHeadersComplete(streamId); @@ -461,7 +461,7 @@ class Http2Parser { private void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize) throws IOException { try { -swallow(streamId, payloadSize, false); +swallowPayload(streamId, payloadSize, false); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false @@ -470,7 +470,7 @@ class Http2Parser { } -private void swallow(int streamId, int len, boolean mustBeZero) +private void swallowPayload(int streamId, int len, boolean mustBeZero) throws IOException, ConnectionException { if (log.isDebugEnabled()) { log.debug(sm.getString("http2Parser.swallow.debug", connectionId, - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 08/08: Fix Javadoc errors
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 14adbe2e8e69bf6b10718145d35ff87dc8f3084d Author: Mark Thomas AuthorDate: Mon Mar 15 19:46:10 2021 + Fix Javadoc errors --- java/org/apache/coyote/http2/Http2Parser.java | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 3f0e1b8..2da5049 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -682,8 +682,9 @@ class Http2Parser { * @param swallowedDataBytesCount The number of bytes that the parser * swallowed. * - * @throws ConnectionException - * @throws IOException + * @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; @@ -724,7 +725,8 @@ class Http2Parser { * frame * @param size The payload size of the swallowed frame * - * @throws IOException + * @throws IOException If an I/O occurred while swallowing the unknown + * frame */ void onSwallowedUnknownFrame(int streamId, int frameTypeId, int flags, int size) throws IOException; } - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 06/08: Fix failing test after flow control updates
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 8a7407e057213dd0a6440633c9027d37bc5e9bc7 Author: Mark Thomas AuthorDate: Mon Mar 15 19:24:08 2021 + Fix failing test after flow control updates --- .../apache/coyote/http2/TestCancelledUpload.java | 73 -- 1 file changed, 26 insertions(+), 47 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index 9964aa4..accd4b3 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -73,26 +73,6 @@ public class TestCancelledUpload extends Http2TestBase { // - reset the stream if further DATA frames are received parser.readFrame(true); -// If reset is first frame received end test here -if (checkReset()) { -return; -} - -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - // Check for reset and exit if found if (checkReset()) { return; @@ -106,58 +86,57 @@ public class TestCancelledUpload extends Http2TestBase { "3-HeadersEnd\n", output.getTrace()); output.clearTrace(); - parser.readFrame(true); + // Check for reset and exit if found if (checkReset()) { return; } -// Not reset, must be request body +// Not window update, not reset, must be the response body Assert.assertEquals("3-Body-0\n" + "3-EndOfStream\n", output.getTrace()); output.clearTrace(); - -// There must be a reset. There may be some WindowSize frames parser.readFrame(true); -// Validate any WindowSize frames. Usually arrive in pairs. Depending on -// timing, can see a reset rather than than stream update. -while (output.getTrace().startsWith("0-WindowSize-[")) { -String trace = output.getTrace(); -int size = Integer.parseInt(trace.substring(14, trace.length() - 2)); -output.clearTrace(); -parser.readFrame(true); -if (checkReset()) { -return; -} -Assert.assertEquals("3-WindowSize-[" + size + "]\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(true); -} - -// This should be the reset -checkReset(); -Assert.assertEquals("3-RST-[3]\n", output.getTrace()); +Assert.assertTrue(checkReset()); // If there are any more frames after this, ignore them } /* - * Depending on timing, several resets may be sent. + * Looking for a RST frame with error type 3 (flow control error). + * + * If there is a flow control window update for stream 0 it may be followed + * by one for stream 3. + * + * If there is a flow control window update for stream 3 it will always be + * preceded by one for stream 0. */ private boolean checkReset() throws IOException, Http2Exception { +int lastConnectionFlowControlWindowUpdate = -1; while (true) { -if (output.getTrace().startsWith("3-RST-[3]\n")) { +String trace = output.getTrace(); +if (trace.startsWith("3-RST-[3]\n")) { +// This is the reset we are looking for return true; -} else if (output.getTrace().startsWith("3-RST-[")) { -output.clearTrace(); -parser.readFrame(true); +} else if (trace.startsWith("3-RST-[")) { +// Probably error type 8 (cancel) - ignore +} else if (trace.startsWith("0-WindowSize-[")) { +// Connection flow control window update +lastConnectionFlowControlWindowUpdate = Integer.parseInt(trace.substring(14, trace.length() - 2)); +} else if (trace.startsWith("3-WindowSize-[")) { +// Stream flow control window update +// Must be same size as last connection flow control window +// update. True for Tomcat anyway. +Assert.assertEquals("3-WindowSize-[" + lastConn
[tomcat] 03/08: Add frameTypeId parameter to swallowedPayload()
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git commit 6a52ef0613c418a9ba0bb74c46ca90ee510a9069 Author: Mark Thomas AuthorDate: Mon Mar 15 18:50:29 2021 + Add frameTypeId parameter to swallowedPayload() --- java/org/apache/coyote/http2/FrameType.java | 5 java/org/apache/coyote/http2/Http2Parser.java | 37 +++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/java/org/apache/coyote/http2/FrameType.java b/java/org/apache/coyote/http2/FrameType.java index d671f10..44e5b55 100644 --- a/java/org/apache/coyote/http2/FrameType.java +++ b/java/org/apache/coyote/http2/FrameType.java @@ -51,6 +51,11 @@ enum FrameType { } +int getId() { +return id; +} + + byte getIdByte() { return (byte) id; } diff --git a/java/org/apache/coyote/http2/Http2Parser.java b/java/org/apache/coyote/http2/Http2Parser.java index 2bcfb2a..42647c8 100644 --- a/java/org/apache/coyote/http2/Http2Parser.java +++ b/java/org/apache/coyote/http2/Http2Parser.java @@ -78,14 +78,15 @@ class Http2Parser { } int payloadSize = ByteUtil.getThreeBytes(frameHeaderBuffer, 0); -FrameType frameType = FrameType.valueOf(ByteUtil.getOneByte(frameHeaderBuffer, 3)); +int frameTypeId = ByteUtil.getOneByte(frameHeaderBuffer, 3); +FrameType frameType = FrameType.valueOf(frameTypeId); int flags = ByteUtil.getOneByte(frameHeaderBuffer, 4); int streamId = ByteUtil.get31Bits(frameHeaderBuffer, 5); try { validateFrame(expected, frameType, streamId, flags, payloadSize); } catch (StreamException se) { -swallowPayload(streamId, payloadSize, false); +swallowPayload(streamId, frameTypeId, payloadSize, false); throw se; } @@ -166,11 +167,11 @@ class Http2Parser { ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize, endOfStream); if (dest == null) { -swallowPayload(streamId, dataLength, false); +swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false); // Process padding before sending any notifications in case padding // is invalid. if (padLength > 0) { -swallowPayload(streamId, padLength, true); +swallowPayload(streamId, FrameType.DATA.getId(), padLength, true); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -178,7 +179,7 @@ class Http2Parser { } else { synchronized (dest) { if (dest.remaining() < dataLength) { -swallowPayload(streamId, dataLength, false); +swallowPayload(streamId, FrameType.DATA.getId(), dataLength, false); // Client has sent more data than permitted by Window size throw new StreamException(sm.getString("http2Parser.processFrameData.window", connectionId), Http2Error.FLOW_CONTROL_ERROR, streamId); @@ -187,7 +188,7 @@ class Http2Parser { // Process padding before sending any notifications in case // padding is invalid. if (padLength > 0) { -swallowPayload(streamId, padLength, true); +swallowPayload(streamId, FrameType.DATA.getId(), padLength, true); } if (endOfStream) { output.receivedEndOfStream(streamId); @@ -212,7 +213,7 @@ class Http2Parser { try { hpackDecoder.setHeaderEmitter(output.headersStart(streamId, headersEndStream)); } catch (StreamException se) { -swallowPayload(streamId, payloadSize, false); +swallowPayload(streamId, FrameType.HEADERS.getId(), payloadSize, false); throw se; } @@ -252,7 +253,7 @@ class Http2Parser { readHeaderPayload(streamId, payloadSize); -swallowPayload(streamId, padLength, true); +swallowPayload(streamId, FrameType.HEADERS.getId(), padLength, true); if (Flags.isEndOfHeaders(flags)) { onHeadersComplete(streamId); @@ -461,7 +462,7 @@ class Http2Parser { private void readUnknownFrame(int streamId, FrameType frameType, int flags, int payloadSize) throws IOException { try { -swallowPayload(streamId, payloadSize, false); +swallowPayload(streamId, frameType.getId(), payloadSize, false); } catch (ConnectionException e) { // Will never happen because swallow() is called with mustBeZero set // to false @@ -470,7 +471,21 @@ class Http2Parser { } -private void swallowPayload(int streamId, int len, boolean mustBeZero) +/** + * Swallow some or a
[tomcat] branch 9.0.x updated: Fix failing test
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 646b802 Fix failing test 646b802 is described below commit 646b8023f7f77a05914423a8c954234227ca8cdb Author: Mark Thomas AuthorDate: Mon Mar 15 19:50:54 2021 + Fix failing test --- test/org/apache/coyote/http2/TestFlowControl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/org/apache/coyote/http2/TestFlowControl.java b/test/org/apache/coyote/http2/TestFlowControl.java index 3841a1d..f49c13c 100644 --- a/test/org/apache/coyote/http2/TestFlowControl.java +++ b/test/org/apache/coyote/http2/TestFlowControl.java @@ -87,10 +87,10 @@ public class TestFlowControl extends Http2TestBase { "3-Header-[:status]-[404]\n" + "3-Header-[content-type]-[text/html;charset=utf-8]\n" + "3-Header-[content-language]-[en]\n" + -"3-Header-[content-length]-[692]\n" + +"3-Header-[content-length]-[691]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + -"3-Body-692\n" + +"3-Body-691\n" + "3-EndOfStream\n" + "3-RST-[8]\n", output.getTrace()); output.clearTrace(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch master updated: Allow for variations in content length
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/master by this push: new 8e22617 Allow for variations in content length 8e22617 is described below commit 8e22617f9abf090481abea578cf4689cebc4901f Author: Mark Thomas AuthorDate: Mon Mar 15 20:54:26 2021 + Allow for variations in content length --- test/org/apache/coyote/http2/TestFlowControl.java | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/org/apache/coyote/http2/TestFlowControl.java b/test/org/apache/coyote/http2/TestFlowControl.java index 3841a1d..950a790 100644 --- a/test/org/apache/coyote/http2/TestFlowControl.java +++ b/test/org/apache/coyote/http2/TestFlowControl.java @@ -79,18 +79,26 @@ public class TestFlowControl extends Http2TestBase { parser.readFrame(true); // body parser.readFrame(true); -// reset (becasue the request body was not fully read) +// reset (because the request body was not fully read) parser.readFrame(true); + // Validate response +// Response size varies as error page is generated and includes version +// number +String trace = output.getTrace(); +int start = trace.indexOf("[content-length]-[") + 18; +int end = trace.indexOf("]", start); +String contentLength = trace.substring(start, end); + Assert.assertEquals( "3-HeadersStart\n" + "3-Header-[:status]-[404]\n" + "3-Header-[content-type]-[text/html;charset=utf-8]\n" + "3-Header-[content-language]-[en]\n" + -"3-Header-[content-length]-[692]\n" + +"3-Header-[content-length]-[" + contentLength + "]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + -"3-Body-692\n" + +"3-Body-" + contentLength + "\n" + "3-EndOfStream\n" + "3-RST-[8]\n", output.getTrace()); output.clearTrace(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Allow for variations in content length
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 8a5bf93 Allow for variations in content length 8a5bf93 is described below commit 8a5bf934ea2a37a37a541db20b97aff53c4919c6 Author: Mark Thomas AuthorDate: Mon Mar 15 20:54:26 2021 + Allow for variations in content length --- test/org/apache/coyote/http2/TestFlowControl.java | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/org/apache/coyote/http2/TestFlowControl.java b/test/org/apache/coyote/http2/TestFlowControl.java index f49c13c..950a790 100644 --- a/test/org/apache/coyote/http2/TestFlowControl.java +++ b/test/org/apache/coyote/http2/TestFlowControl.java @@ -79,18 +79,26 @@ public class TestFlowControl extends Http2TestBase { parser.readFrame(true); // body parser.readFrame(true); -// reset (becasue the request body was not fully read) +// reset (because the request body was not fully read) parser.readFrame(true); + // Validate response +// Response size varies as error page is generated and includes version +// number +String trace = output.getTrace(); +int start = trace.indexOf("[content-length]-[") + 18; +int end = trace.indexOf("]", start); +String contentLength = trace.substring(start, end); + Assert.assertEquals( "3-HeadersStart\n" + "3-Header-[:status]-[404]\n" + "3-Header-[content-type]-[text/html;charset=utf-8]\n" + "3-Header-[content-language]-[en]\n" + -"3-Header-[content-length]-[691]\n" + +"3-Header-[content-length]-[" + contentLength + "]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + -"3-Body-691\n" + +"3-Body-" + contentLength + "\n" + "3-EndOfStream\n" + "3-RST-[8]\n", output.getTrace()); output.clearTrace(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Allow for variations in content length
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new d0634ea Allow for variations in content length d0634ea is described below commit d0634ea1f86abbb2fe70e7e08d59d2da7ccd10c0 Author: Mark Thomas AuthorDate: Mon Mar 15 20:54:26 2021 + Allow for variations in content length --- test/org/apache/coyote/http2/TestFlowControl.java | 14 +++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/org/apache/coyote/http2/TestFlowControl.java b/test/org/apache/coyote/http2/TestFlowControl.java index f49c13c..950a790 100644 --- a/test/org/apache/coyote/http2/TestFlowControl.java +++ b/test/org/apache/coyote/http2/TestFlowControl.java @@ -79,18 +79,26 @@ public class TestFlowControl extends Http2TestBase { parser.readFrame(true); // body parser.readFrame(true); -// reset (becasue the request body was not fully read) +// reset (because the request body was not fully read) parser.readFrame(true); + // Validate response +// Response size varies as error page is generated and includes version +// number +String trace = output.getTrace(); +int start = trace.indexOf("[content-length]-[") + 18; +int end = trace.indexOf("]", start); +String contentLength = trace.substring(start, end); + Assert.assertEquals( "3-HeadersStart\n" + "3-Header-[:status]-[404]\n" + "3-Header-[content-type]-[text/html;charset=utf-8]\n" + "3-Header-[content-language]-[en]\n" + -"3-Header-[content-length]-[691]\n" + +"3-Header-[content-length]-[" + contentLength + "]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + -"3-Body-691\n" + +"3-Body-" + contentLength + "\n" + "3-EndOfStream\n" + "3-RST-[8]\n", output.getTrace()); output.clearTrace(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
buildbot success in on tomcat-trunk
The Buildbot has detected a restored build on builder tomcat-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-trunk/builds/5730 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-commit' triggered this build Build Source Stamp: [branch master] 8e22617f9abf090481abea578cf4689cebc4901f Blamelist: Mark Thomas Build succeeded! Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
buildbot success in on tomcat-9-trunk
The Buildbot has detected a restored build on builder tomcat-9-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-9-trunk/builds/683 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-9-commit' triggered this build Build Source Stamp: [branch 9.0.x] 8a5bf934ea2a37a37a541db20b97aff53c4919c6 Blamelist: Mark Thomas Build succeeded! Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
buildbot success in on tomcat-85-trunk
The Buildbot has detected a restored build on builder tomcat-85-trunk while building tomcat. Full details are available at: https://ci.apache.org/builders/tomcat-85-trunk/builds/2647 Buildbot URL: https://ci.apache.org/ Buildslave for this Build: asf946_ubuntu Build Reason: The AnyBranchScheduler scheduler named 'on-tomcat-85-commit' triggered this build Build Source Stamp: [branch 8.5.x] d0634ea1f86abbb2fe70e7e08d59d2da7ccd10c0 Blamelist: Mark Thomas Build succeeded! Sincerely, -The Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[Bug 65179] HTTP2:WINDOW_UPDATE not sent when receiving http2 requests over unknown url
https://bz.apache.org/bugzilla/show_bug.cgi?id=65179 Mark Thomas changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #1 from Mark Thomas --- Fixed in: - 10.0.x for 10.0.5 onwards - 9.0.x for 9.0.45 onwards - 8.5.x for 8.5.65 onwards -- You are receiving this mail because: You are the assignee for the bug. - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org