Author: markt
Date: Wed Oct 19 13:31:26 2016
New Revision: 1765589

URL: http://svn.apache.org/viewvc?rev=1765589&view=rev
Log:
Add initial support for trailer headers

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java
    tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
    tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java

Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed Oct 
19 13:31:26 2016
@@ -1247,8 +1247,9 @@ class Http2UpgradeHandler extends Abstra
         setMaxProcessedStream(streamId);
         Stream stream = getStream(streamId, 
connectionState.get().isNewStreamAllowed());
         if (stream != null && stream.isActive()) {
-            stream.receivedEndOfHeaders();
-            processStreamOnContainerThread(stream);
+            if (stream.receivedEndOfHeaders()) {
+                processStreamOnContainerThread(stream);
+            }
         }
     }
 

Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Oct 19 13:31:26 
2016
@@ -293,13 +293,14 @@ class Stream extends AbstractStream impl
     }
 
 
-    final void receivedEndOfHeaders() {
+    final boolean receivedEndOfHeaders() {
         // Cookie headers need to be concatenated into a single header
         // See RFC 7540 8.1.2.5
         // Can only do this once the headers are fully received
         if (cookieHeader != null) {
             
coyoteRequest.getMimeHeaders().addValue("cookie").setString(cookieHeader.toString());
         }
+        return headerState == HEADER_STATE_REGULAR || headerState == 
HEADER_STATE_PSEUDO;
     }
 
 
@@ -362,6 +363,9 @@ class Stream extends AbstractStream impl
 
 
     final void receivedEndOfStream() {
+        synchronized (inputBuffer) {
+            inputBuffer.notifyAll();
+        }
         state.recievedEndOfStream();
     }
 

Modified: tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Oct 19 
13:31:26 2016
@@ -69,6 +69,8 @@ public abstract class Http2TestBase exte
         EMPTY_HTTP2_SETTINGS_HEADER = "HTTP2-Settings: " + 
Base64.encodeBase64String(empty) + "\r\n";
     }
 
+    private static final String TRAILER_HEADER_NAME = "X-TrailerTest";
+
     private Socket s;
     protected HpackEncoder hpackEncoder;
     protected Input input;
@@ -294,6 +296,13 @@ public abstract class Http2TestBase exte
     protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer 
headersPayload,
             boolean useExpectation, byte[] dataFrameHeader, ByteBuffer 
dataPayload, byte[] padding,
             int streamId) {
+        buildPostRequest(headersFrameHeader, headersPayload, useExpectation, 
dataFrameHeader,
+                dataPayload, padding, null, null, streamId);
+    }
+
+    protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer 
headersPayload,
+            boolean useExpectation, byte[] dataFrameHeader, ByteBuffer 
dataPayload, byte[] padding,
+            byte[] trailersFrameHeader, ByteBuffer trailersPayload, int 
streamId) {
         MimeHeaders headers = new MimeHeaders();
         headers.addValue(":method").setString("POST");
         headers.addValue(":path").setString("/simple");
@@ -332,12 +341,31 @@ public abstract class Http2TestBase exte
         ByteUtil.setThreeBytes(dataFrameHeader, 0, dataPayload.limit());
         // Data is type 0
         // Flags: End of stream 1, Padding 8
-        if (padding == null) {
+        if (trailersPayload == null) {
             dataFrameHeader[4] = 0x01;
         } else {
-            dataFrameHeader[4] = 0x09;
+            dataFrameHeader[4] = 0x00;
+        }
+        if (padding != null) {
+            dataFrameHeader[4] += 0x08;
         }
         ByteUtil.set31Bits(dataFrameHeader, 5, streamId);
+
+        // Trailers
+        if (trailersPayload != null) {
+            MimeHeaders trailerHeaders = new MimeHeaders();
+            trailerHeaders.addValue(TRAILER_HEADER_NAME).setString("xxxx");
+            hpackEncoder.encode(trailerHeaders, trailersPayload);
+
+            trailersPayload.flip();
+
+            ByteUtil.setThreeBytes(trailersFrameHeader, 0, 
trailersPayload.limit());
+            trailersFrameHeader[3] = FrameType.HEADERS.getIdByte();
+            // Flags. end of headers (0x04) and end of stream (0x01)
+            trailersFrameHeader[4] = 0x05;
+            // Stream id
+            ByteUtil.set31Bits(trailersFrameHeader, 5, streamId);
+        }
     }
 
 
@@ -1049,6 +1077,12 @@ public abstract class Http2TestBase exte
 
             ByteArrayInputStream bais = new 
ByteArrayInputStream(baos.toByteArray());
             IOTools.flow(bais, resp.getOutputStream());
+
+            // Check for trailer headers
+            String trailerValue = req.getHeader(TRAILER_HEADER_NAME);
+            if (trailerValue != null) {
+                
resp.getOutputStream().write(trailerValue.getBytes(StandardCharsets.UTF_8));
+            }
         }
     }
 

Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java?rev=1765589&r1=1765588&r2=1765589&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java 
(original)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java Wed Oct 
19 13:31:26 2016
@@ -33,6 +33,44 @@ import org.junit.Test;
 public class TestHttp2Section_8_1 extends Http2TestBase {
 
     @Test
+    public void testPostWithTrailerHeaders() throws Exception {
+        http2Connect();
+
+        byte[] headersFrameHeader = new byte[9];
+        ByteBuffer headersPayload = ByteBuffer.allocate(128);
+        byte[] dataFrameHeader = new byte[9];
+        ByteBuffer dataPayload = ByteBuffer.allocate(256);
+        byte[] trailerFrameHeader = new byte[9];
+        ByteBuffer trailerPayload = ByteBuffer.allocate(256);
+
+        buildPostRequest(headersFrameHeader, headersPayload, false, 
dataFrameHeader, dataPayload,
+                null, trailerFrameHeader, trailerPayload, 3);
+
+        // Write the headers
+        writeFrame(headersFrameHeader, headersPayload);
+        // Body
+        writeFrame(dataFrameHeader, dataPayload);
+        // Trailers
+        writeFrame(trailerFrameHeader, trailerPayload);
+
+        parser.readFrame(true);
+        parser.readFrame(true);
+        parser.readFrame(true);
+        parser.readFrame(true);
+
+        Assert.assertEquals("0-WindowSize-[256]\n" +
+                "3-WindowSize-[256]\n" +
+                "3-HeadersStart\n" +
+                "3-Header-[:status]-[200]\n" +
+                "3-Header-[date]-["+ DEFAULT_DATE + "]\n" +
+                "3-HeadersEnd\n" +
+                "3-Body-260\n" +
+                "3-EndOfStream\n",
+                output.getTrace());
+    }
+
+
+    @Test
     public void testSendAck() throws Exception {
         http2Connect();
 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to