(tomcat) 03/04: Refactor chunked input filter to use common HTTP header/trailer parser

2024-04-26 Thread markt
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 92e3c7a7adc574a859ab70333bf930561dcf1e9d
Author: Mark Thomas 
AuthorDate: Fri Apr 26 15:58:37 2024 +0100

Refactor chunked input filter to use common HTTP header/trailer parser

This adds non-blocking read support for chunked request bodies
---
 java/org/apache/coyote/http11/Http11Processor.java |   2 +-
 .../coyote/http11/filters/ChunkedInputFilter.java  | 576 -
 webapps/docs/changelog.xml |   3 +
 3 files changed, 233 insertions(+), 348 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11Processor.java 
b/java/org/apache/coyote/http11/Http11Processor.java
index 0692b8da4e..c75243e369 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -169,7 +169,7 @@ public class Http11Processor extends AbstractProcessor {
 
 // Create and add the chunked filters.
 inputBuffer.addFilter(
-new ChunkedInputFilter(protocol.getMaxTrailerSize(), 
protocol.getAllowedTrailerHeadersInternal(),
+new ChunkedInputFilter(request, protocol.getMaxTrailerSize(), 
protocol.getAllowedTrailerHeadersInternal(),
 protocol.getMaxExtensionSize(), 
protocol.getMaxSwallowSize()));
 outputBuffer.addFilter(new ChunkedOutputFilter());
 
diff --git a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 
b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
index 741cd1078b..f350487771 100644
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -16,11 +16,9 @@
  */
 package org.apache.coyote.http11.filters;
 
-import java.io.EOFException;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
-import java.util.Locale;
 import java.util.Set;
 
 import org.apache.coyote.ActionCode;
@@ -31,8 +29,9 @@ import org.apache.coyote.http11.Constants;
 import org.apache.coyote.http11.InputFilter;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.MimeHeaders;
-import org.apache.tomcat.util.http.parser.HttpParser;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser.HeaderDataSource;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser.HeaderParseStatus;
 import org.apache.tomcat.util.net.ApplicationBufferHandler;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -42,7 +41,7 @@ import org.apache.tomcat.util.res.StringManager;
  *
  * @author Remy Maucherat
  */
-public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler {
+public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler, HeaderDataSource {
 
 private static final StringManager sm = 
StringManager.getManager(ChunkedInputFilter.class);
 
@@ -82,28 +81,15 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
 
 
 /**
- * Flag set to true when the end chunk has been read.
+ * Buffer used to store trailing headers. Is normally in read mode.
  */
-protected boolean endChunk = false;
-
-
-/**
- * Byte chunk used to store trailing headers.
- */
-protected final ByteChunk trailingHeaders = new ByteChunk();
-
-
-/**
- * Flag set to true if the next call to doRead() must parse a CRLF pair
- * before doing anything else.
- */
-protected boolean needCRLFParse = false;
+protected final ByteBuffer trailingHeaders;
 
 
 /**
  * Request being parsed.
  */
-private Request request;
+private final Request request;
 
 
 /**
@@ -112,38 +98,31 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
 private final long maxExtensionSize;
 
 
-/**
- * Limit for trailer size.
- */
-private final int maxTrailerSize;
-
-
-/**
- * Size of extensions processed for this request.
- */
-private long extensionSize;
-
-
 private final int maxSwallowSize;
 
+private final Set allowedTrailerHeaders;
 
-/**
- * Flag that indicates if an error has occurred.
+/*
+ * Parsing state.
  */
-private boolean error;
-
-
-private final Set allowedTrailerHeaders;
+private volatile ParseState parseState = ParseState.CHUNK_HEADER;
+private volatile boolean crFound = false;
+private volatile int chunkSizeDigitsRead = 0;
+private volatile boolean parsingExtension = false;
+private volatile long extensionSize;
+private final HttpHeaderParser httpHeaderParser;
 
 // --- Constructors
 
-public ChunkedInputFilter(int 

(tomcat) 03/04: Refactor chunked input filter to use common HTTP header/trailer parser

2024-04-26 Thread markt
This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit cbed8e1836962d43120b81ae99d8d1b349265749
Author: Mark Thomas 
AuthorDate: Fri Apr 26 15:58:37 2024 +0100

Refactor chunked input filter to use common HTTP header/trailer parser

This adds non-blocking read support for chunked request bodies
---
 java/org/apache/coyote/http11/Http11Processor.java |   2 +-
 .../coyote/http11/filters/ChunkedInputFilter.java  | 576 -
 2 files changed, 230 insertions(+), 348 deletions(-)

diff --git a/java/org/apache/coyote/http11/Http11Processor.java 
b/java/org/apache/coyote/http11/Http11Processor.java
index 3a1897a84b..b2fac4af8c 100644
--- a/java/org/apache/coyote/http11/Http11Processor.java
+++ b/java/org/apache/coyote/http11/Http11Processor.java
@@ -167,7 +167,7 @@ public class Http11Processor extends AbstractProcessor {
 
 // Create and add the chunked filters.
 inputBuffer.addFilter(
-new ChunkedInputFilter(protocol.getMaxTrailerSize(), 
protocol.getAllowedTrailerHeadersInternal(),
+new ChunkedInputFilter(request, protocol.getMaxTrailerSize(), 
protocol.getAllowedTrailerHeadersInternal(),
 protocol.getMaxExtensionSize(), 
protocol.getMaxSwallowSize()));
 outputBuffer.addFilter(new ChunkedOutputFilter());
 
diff --git a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java 
b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
index 741cd1078b..f350487771 100644
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -16,11 +16,9 @@
  */
 package org.apache.coyote.http11.filters;
 
-import java.io.EOFException;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
-import java.util.Locale;
 import java.util.Set;
 
 import org.apache.coyote.ActionCode;
@@ -31,8 +29,9 @@ import org.apache.coyote.http11.Constants;
 import org.apache.coyote.http11.InputFilter;
 import org.apache.tomcat.util.buf.ByteChunk;
 import org.apache.tomcat.util.buf.HexUtils;
-import org.apache.tomcat.util.http.MimeHeaders;
-import org.apache.tomcat.util.http.parser.HttpParser;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser.HeaderDataSource;
+import org.apache.tomcat.util.http.parser.HttpHeaderParser.HeaderParseStatus;
 import org.apache.tomcat.util.net.ApplicationBufferHandler;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -42,7 +41,7 @@ import org.apache.tomcat.util.res.StringManager;
  *
  * @author Remy Maucherat
  */
-public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler {
+public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler, HeaderDataSource {
 
 private static final StringManager sm = 
StringManager.getManager(ChunkedInputFilter.class);
 
@@ -82,28 +81,15 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
 
 
 /**
- * Flag set to true when the end chunk has been read.
+ * Buffer used to store trailing headers. Is normally in read mode.
  */
-protected boolean endChunk = false;
-
-
-/**
- * Byte chunk used to store trailing headers.
- */
-protected final ByteChunk trailingHeaders = new ByteChunk();
-
-
-/**
- * Flag set to true if the next call to doRead() must parse a CRLF pair
- * before doing anything else.
- */
-protected boolean needCRLFParse = false;
+protected final ByteBuffer trailingHeaders;
 
 
 /**
  * Request being parsed.
  */
-private Request request;
+private final Request request;
 
 
 /**
@@ -112,38 +98,31 @@ public class ChunkedInputFilter implements InputFilter, 
ApplicationBufferHandler
 private final long maxExtensionSize;
 
 
-/**
- * Limit for trailer size.
- */
-private final int maxTrailerSize;
-
-
-/**
- * Size of extensions processed for this request.
- */
-private long extensionSize;
-
-
 private final int maxSwallowSize;
 
+private final Set allowedTrailerHeaders;
 
-/**
- * Flag that indicates if an error has occurred.
+/*
+ * Parsing state.
  */
-private boolean error;
-
-
-private final Set allowedTrailerHeaders;
+private volatile ParseState parseState = ParseState.CHUNK_HEADER;
+private volatile boolean crFound = false;
+private volatile int chunkSizeDigitsRead = 0;
+private volatile boolean parsingExtension = false;
+private volatile long extensionSize;
+private final HttpHeaderParser httpHeaderParser;
 
 // --- Constructors
 
-public ChunkedInputFilter(int maxTrailerSize, Set 
allowedTrailerHeaders,
+public