Author: markt
Date: Wed Sep 30 23:33:55 2015
New Revision: 1706173

URL: http://svn.apache.org/viewvc?rev=1706173&view=rev
Log:
Add 100-continue support to HTTP/2

Added:
    tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java   (with 
props)
Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java
    tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
    tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java
    tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Wed Sep 
30 23:33:55 2015
@@ -458,7 +458,8 @@ public class Http2UpgradeHandler extends
     }
 
 
-    void writeHeaders(Stream stream, Response coyoteResponse) throws 
IOException {
+    void writeHeaders(Stream stream, Response coyoteResponse, int payloadSize)
+            throws IOException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
                     stream.getIdentifier()));
@@ -468,10 +469,8 @@ public class Http2UpgradeHandler extends
         
headers.addValue(":status").setString(Integer.toString(coyoteResponse.getStatus()));
         // This ensures the Stream processing thread has control of the socket.
         synchronized (socketWrapper) {
-            // Frame sizes are allowed to be bigger than 4k but for headers 
that
-            // should be plenty
             byte[] header = new byte[9];
-            ByteBuffer target = ByteBuffer.allocate(4 * 1024);
+            ByteBuffer target = ByteBuffer.allocate(payloadSize);
             boolean first = true;
             State state = null;
             while (state != State.COMPLETE) {

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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Sep 30 23:33:55 
2015
@@ -37,6 +37,12 @@ public class Stream extends AbstractStre
     private static final Log log = LogFactory.getLog(Stream.class);
     private static final StringManager sm = 
StringManager.getManager(Stream.class);
 
+    private static final Response ACK_RESPONSE = new Response();
+
+    static {
+        ACK_RESPONSE.setStatus(101);
+    }
+
     private volatile int weight = Constants.DEFAULT_WEIGHT;
 
     private final Http2UpgradeHandler handler;
@@ -225,6 +231,9 @@ public class Stream extends AbstractStre
             break;
         }
         default: {
+            if ("expect".equals(name) && "100-continue".equals(value)) {
+                coyoteRequest.setExpectation(true);
+            }
             // Assume other HTTP header
             coyoteRequest.getMimeHeaders().addValue(name).setString(value);
         }
@@ -233,9 +242,16 @@ public class Stream extends AbstractStre
 
 
     void writeHeaders() throws IOException {
-        handler.writeHeaders(this, coyoteResponse);
+        // TODO: Is 1k the optimal value?
+        handler.writeHeaders(this, coyoteResponse, 1024);
     }
 
+    void writeAck() throws IOException {
+        // TODO: Is 64 too big? Just the status header with compression
+        handler.writeHeaders(this, ACK_RESPONSE, 64);
+    }
+
+
 
     void flushData() throws IOException {
         if (log.isDebugEnabled()) {

Modified: tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java?rev=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/StreamProcessor.java Wed Sep 30 
23:33:55 2015
@@ -139,6 +139,16 @@ public class StreamProcessor extends Abs
             }
             break;
         }
+        case ACK: {
+            if (!response.isCommitted() && request.hasExpectation()) {
+                try {
+                    stream.writeAck();
+                } catch (IOException ioe) {
+                    // TODO
+                }
+            }
+            break;
+        }
         case CLIENT_FLUSH: {
             action(ActionCode.COMMIT, null);
             try {
@@ -330,7 +340,6 @@ public class StreamProcessor extends Abs
                     sm.getString("streamProcessor.httpupgrade.notsupported"));
 
         // Unimplemented / to review
-        case ACK:
         case CLOSE_NOW:
         case DISABLE_SWALLOW_INPUT:
         case END_REQUEST:

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=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Sep 30 
23:33:55 2015
@@ -232,12 +232,17 @@ public abstract class Http2TestBase exte
 
     protected void sendSimplePostRequest(int streamId, byte[] padding, boolean 
writeBody)
             throws IOException {
+        sendSimplePostRequest(streamId, padding, writeBody, false);
+    }
+
+    protected void sendSimplePostRequest(int streamId, byte[] padding, boolean 
writeBody,
+            boolean useExpectation) throws IOException {
         byte[] headersFrameHeader = new byte[9];
         ByteBuffer headersPayload = ByteBuffer.allocate(128);
         byte[] dataFrameHeader = new byte[9];
         ByteBuffer dataPayload = ByteBuffer.allocate(128);
 
-        buildPostRequest(headersFrameHeader, headersPayload,
+        buildPostRequest(headersFrameHeader, headersPayload, useExpectation,
                 dataFrameHeader, dataPayload, padding, streamId);
         writeFrame(headersFrameHeader, headersPayload);
         if (writeBody) {
@@ -247,11 +252,15 @@ public abstract class Http2TestBase exte
 
 
     protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer 
headersPayload,
-            byte[] dataFrameHeader, ByteBuffer dataPayload, byte[] padding, 
int streamId) {
+            boolean useExpectation, byte[] dataFrameHeader, ByteBuffer 
dataPayload, byte[] padding,
+            int streamId) {
         MimeHeaders headers = new MimeHeaders();
         headers.addValue(":method").setString("POST");
         headers.addValue(":path").setString("/simple");
         headers.addValue(":authority").setString("localhost:" + getPort());
+        if (useExpectation) {
+            headers.addValue("expect").setString("100-continue");
+        }
         hpackEncoder.encode(headers, headersPayload);
 
         headersPayload.flip();

Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java?rev=1706173&r1=1706172&r2=1706173&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java 
(original)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java Wed Sep 
30 23:33:55 2015
@@ -167,7 +167,7 @@ public class TestHttp2Section_6_9 extend
         byte[] dataFrameHeader = new byte[9];
         ByteBuffer dataPayload = ByteBuffer.allocate(8 * 1024);
 
-        buildPostRequest(headersFrameHeader, headersPayload,
+        buildPostRequest(headersFrameHeader, headersPayload, false,
                 dataFrameHeader, dataPayload, null, 3);
 
         // Write the headers

Added: 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=1706173&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java (added)
+++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java Wed Sep 
30 23:33:55 2015
@@ -0,0 +1,80 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.coyote.http2;
+
+import java.nio.ByteBuffer;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit tests for Section 8.1 of
+ * <a href="https://tools.ietf.org/html/rfc7540";>RFC 7540</a>.
+ * <br>
+ * The order of tests in this class is aligned with the order of the
+ * examples in the RFC.
+ */
+public class TestHttp2Section_8_1 extends Http2TestBase {
+
+    @Test
+    public void testPostWithContinuation() throws Exception {
+        http2Connect();
+
+    }
+
+    @Test
+    public void testSendAck() throws Exception {
+        http2Connect();
+
+        byte[] headersFrameHeader = new byte[9];
+        ByteBuffer headersPayload = ByteBuffer.allocate(128);
+        byte[] dataFrameHeader = new byte[9];
+        ByteBuffer dataPayload = ByteBuffer.allocate(256);
+
+        buildPostRequest(headersFrameHeader, headersPayload, true,
+                dataFrameHeader, dataPayload, null, 3);
+
+        // Write the headers
+        writeFrame(headersFrameHeader, headersPayload);
+
+        parser.readFrame(true);
+
+        Assert.assertEquals("3-HeadersStart\n" +
+                "3-Header-[:status]-[101]\n" +
+                "3-HeadersEnd\n",
+                output.getTrace());
+        output.clearTrace();
+
+        // Write the body
+        writeFrame(dataFrameHeader, dataPayload);
+
+        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-HeadersEnd\n" +
+                "3-Body-256\n" +
+                "3-EndOfStream\n",
+                output.getTrace());
+
+    }
+}

Propchange: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_8_1.java
------------------------------------------------------------------------------
    svn:eol-style = native



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

Reply via email to