You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/05/04 09:22:45 UTC

svn commit: r1793758 - in /tomcat/trunk/java/org/apache/coyote/http2: Http2AsyncUpgradeHandler.java Http2UpgradeHandler.java Stream.java

Author: markt
Date: Thu May  4 09:22:45 2017
New Revision: 1793758

URL: http://svn.apache.org/viewvc?rev=1793758&view=rev
Log:
Refactor to reduce duplication prior to adding trailer header support.

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/Stream.java

Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java?rev=1793758&r1=1793757&r2=1793758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java Thu May  4 09:22:45 2017
@@ -25,8 +25,8 @@ import java.util.concurrent.TimeUnit;
 import org.apache.coyote.Adapter;
 import org.apache.coyote.ProtocolException;
 import org.apache.coyote.Request;
-import org.apache.coyote.Response;
 import org.apache.coyote.http2.HpackEncoder.State;
+import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.net.SocketWrapperBase;
 import org.apache.tomcat.util.net.SocketWrapperBase.BlockingMode;
 
@@ -133,88 +133,49 @@ public class Http2AsyncUpgradeHandler ex
 
 
     @Override
-    void writeHeaders(Stream stream, Response coyoteResponse, boolean endOfStream, int payloadSize)
-            throws IOException {
+    void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders,
+            boolean endOfStream, int payloadSize) throws IOException {
+
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
-                    stream.getIdentifier()));
+                    stream.getIdentifier(), Integer.valueOf(pushedStreamId),
+                    Boolean.valueOf(endOfStream)));
         }
 
         if (!stream.canWrite()) {
             return;
         }
 
-        boolean first = true;
-        State state = null;
-        ArrayList<ByteBuffer> bufs = new ArrayList<>();
-        // This ensures the Stream processing thread has control of the socket.
-        while (state != State.COMPLETE) {
-            byte[] header = new byte[9];
-            ByteBuffer target = ByteBuffer.allocate(payloadSize);
-            state = getHpackEncoder().encode(coyoteResponse.getMimeHeaders(), target);
-            target.flip();
-            if (state == State.COMPLETE || target.limit() > 0) {
-                ByteUtil.setThreeBytes(header, 0, target.limit());
-                if (first) {
-                    first = false;
-                    header[3] = FrameType.HEADERS.getIdByte();
-                    if (endOfStream) {
-                        header[4] = FLAG_END_OF_STREAM;
-                    }
-                } else {
-                    header[3] = FrameType.CONTINUATION.getIdByte();
-                }
-                if (state == State.COMPLETE) {
-                    header[4] += FLAG_END_OF_HEADERS;
-                }
-                if (log.isDebugEnabled()) {
-                    log.debug(target.limit() + " bytes");
-                }
-                ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue());
-                bufs.add(ByteBuffer.wrap(header));
-                bufs.add(target);
-            } else if (state == State.UNDERFLOW) {
-                payloadSize = payloadSize * 2;
-            }
-        }
-        socketWrapper.write(BlockingMode.SEMI_BLOCK, getWriteTimeout(), TimeUnit.MILLISECONDS,
-                null, SocketWrapperBase.COMPLETE_WRITE, applicationErrorCompletion,
-                bufs.toArray(BYTEBUFFER_ARRAY));
-        handleAsyncException();
-    }
-
-
-    @Override
-    protected void writePushHeaders(Stream stream, int pushedStreamId, Request coyoteRequest, int payloadSize)
-            throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.writePushHeaders", connectionId,
-                    stream.getIdentifier(), Integer.toString(pushedStreamId)));
-        }
-
-        if (!stream.canWrite()) {
-            return;
+        byte[] pushedStreamIdBytes = null;
+        if (pushedStreamId > 0) {
+            pushedStreamIdBytes = new byte[4];
+            ByteUtil.set31Bits(pushedStreamIdBytes, 0, pushedStreamId);
         }
 
         boolean first = true;
         State state = null;
         ArrayList<ByteBuffer> bufs = new ArrayList<>();
-        byte[] pushedStreamIdBytes = new byte[4];
-        ByteUtil.set31Bits(pushedStreamIdBytes, 0, pushedStreamId);
-        // This ensures the Stream processing thread has control of the socket.
+
         while (state != State.COMPLETE) {
             byte[] header = new byte[9];
-            ByteBuffer target = ByteBuffer.allocate(payloadSize);
-            if (first) {
-                target.put(pushedStreamIdBytes);
+            ByteBuffer payload = ByteBuffer.allocate(payloadSize);
+            if (first && pushedStreamIdBytes != null) {
+                payload.put(pushedStreamIdBytes);
             }
-            state = getHpackEncoder().encode(coyoteRequest.getMimeHeaders(), target);
-            target.flip();
-            if (state == State.COMPLETE || target.limit() > 0) {
-                ByteUtil.setThreeBytes(header, 0, target.limit());
+            state = getHpackEncoder().encode(mimeHeaders, payload);
+            payload.flip();
+            if (state == State.COMPLETE || payload.limit() > 0) {
+                ByteUtil.setThreeBytes(header, 0, payload.limit());
                 if (first) {
                     first = false;
-                    header[3] = FrameType.PUSH_PROMISE.getIdByte();
+                    if (pushedStreamIdBytes == null) {
+                        header[3] = FrameType.HEADERS.getIdByte();
+                    } else {
+                        header[3] = FrameType.PUSH_PROMISE.getIdByte();
+                    }
+                    if (endOfStream) {
+                        header[4] = FLAG_END_OF_STREAM;
+                    }
                 } else {
                     header[3] = FrameType.CONTINUATION.getIdByte();
                 }
@@ -222,11 +183,11 @@ public class Http2AsyncUpgradeHandler ex
                     header[4] += FLAG_END_OF_HEADERS;
                 }
                 if (log.isDebugEnabled()) {
-                    log.debug(target.limit() + " bytes");
+                    log.debug(payload.limit() + " bytes");
                 }
                 ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue());
                 bufs.add(ByteBuffer.wrap(header));
-                bufs.add(target);
+                bufs.add(payload);
             } else if (state == State.UNDERFLOW) {
                 payloadSize = payloadSize * 2;
             }

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=1793758&r1=1793757&r2=1793758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Thu May  4 09:22:45 2017
@@ -40,7 +40,6 @@ import org.apache.coyote.Adapter;
 import org.apache.coyote.CloseNowException;
 import org.apache.coyote.ProtocolException;
 import org.apache.coyote.Request;
-import org.apache.coyote.Response;
 import org.apache.coyote.http11.upgrade.InternalHttpUpgradeHandler;
 import org.apache.coyote.http2.HpackDecoder.HeaderEmitter;
 import org.apache.coyote.http2.HpackEncoder.State;
@@ -49,6 +48,7 @@ import org.apache.coyote.http2.Http2Pars
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.codec.binary.Base64;
+import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
 import org.apache.tomcat.util.net.SSLSupport;
 import org.apache.tomcat.util.net.SocketEvent;
@@ -522,11 +522,13 @@ class Http2UpgradeHandler extends Abstra
         }
     }
 
-    void writeHeaders(Stream stream, Response coyoteResponse, boolean endOfStream, int payloadSize)
-            throws IOException {
+    void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders,
+            boolean endOfStream, int payloadSize) throws IOException {
+
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
-                    stream.getIdentifier()));
+                    stream.getIdentifier(), Integer.valueOf(pushedStreamId),
+                    Boolean.valueOf(endOfStream)));
         }
 
         if (!stream.canWrite()) {
@@ -534,78 +536,37 @@ class Http2UpgradeHandler extends Abstra
         }
 
         byte[] header = new byte[9];
-        ByteBuffer target = ByteBuffer.allocate(payloadSize);
-        boolean first = true;
-        State state = null;
-        // This ensures the Stream processing thread has control of the socket.
-        synchronized (socketWrapper) {
-            while (state != State.COMPLETE) {
-                state = getHpackEncoder().encode(coyoteResponse.getMimeHeaders(), target);
-                target.flip();
-                if (state == State.COMPLETE || target.limit() > 0) {
-                    ByteUtil.setThreeBytes(header, 0, target.limit());
-                    if (first) {
-                        first = false;
-                        header[3] = FrameType.HEADERS.getIdByte();
-                        if (endOfStream) {
-                            header[4] = FLAG_END_OF_STREAM;
-                        }
-                    } else {
-                        header[3] = FrameType.CONTINUATION.getIdByte();
-                    }
-                    if (state == State.COMPLETE) {
-                        header[4] += FLAG_END_OF_HEADERS;
-                    }
-                    if (log.isDebugEnabled()) {
-                        log.debug(target.limit() + " bytes");
-                    }
-                    ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue());
-                    try {
-                        socketWrapper.write(true, header, 0, header.length);
-                        socketWrapper.write(true, target);
-                        socketWrapper.flush(true);
-                    } catch (IOException ioe) {
-                        handleAppInitiatedIOException(ioe);
-                    }
-                }
-                if (state == State.UNDERFLOW && target.limit() == 0) {
-                    target = ByteBuffer.allocate(target.capacity() * 2);
-                } else {
-                    target.clear();
-                }
-            }
-        }
-    }
-
+        ByteBuffer payload = ByteBuffer.allocate(payloadSize);
 
-    protected void writePushHeaders(Stream stream, int pushedStreamId, Request coyoteRequest, int payloadSize)
-            throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.writePushHeaders", connectionId,
-                    stream.getIdentifier(), Integer.toString(pushedStreamId)));
+        byte[] pushedStreamIdBytes = null;
+        if (pushedStreamId > 0) {
+            pushedStreamIdBytes = new byte[4];
+            ByteUtil.set31Bits(pushedStreamIdBytes, 0, pushedStreamId);
         }
 
-        if (!stream.canWrite()) {
-            return;
-        }
-
-        byte[] header = new byte[9];
-        ByteBuffer target = ByteBuffer.allocate(payloadSize);
         boolean first = true;
         State state = null;
-        byte[] pushedStreamIdBytes = new byte[4];
-        ByteUtil.set31Bits(pushedStreamIdBytes, 0, pushedStreamId);
+
         // This ensures the Stream processing thread has control of the socket.
         synchronized (socketWrapper) {
-            target.put(pushedStreamIdBytes);
             while (state != State.COMPLETE) {
-                state = getHpackEncoder().encode(coyoteRequest.getMimeHeaders(), target);
-                target.flip();
-                if (state == State.COMPLETE || target.limit() > 0) {
-                    ByteUtil.setThreeBytes(header, 0, target.limit());
+                if (first && pushedStreamIdBytes != null) {
+                    payload.put(pushedStreamIdBytes);
+                }
+                state = getHpackEncoder().encode(mimeHeaders, payload);
+                payload.flip();
+                if (state == State.COMPLETE || payload.limit() > 0) {
+                    ByteUtil.setThreeBytes(header, 0, payload.limit());
                     if (first) {
                         first = false;
-                        header[3] = FrameType.PUSH_PROMISE.getIdByte();
+                        if (pushedStreamIdBytes == null) {
+                            header[3] = FrameType.HEADERS.getIdByte();
+                        } else {
+                            header[3] = FrameType.PUSH_PROMISE.getIdByte();
+                        }
+                        if (endOfStream) {
+                            header[4] = FLAG_END_OF_STREAM;
+                        }
                     } else {
                         header[3] = FrameType.CONTINUATION.getIdByte();
                     }
@@ -613,21 +574,19 @@ class Http2UpgradeHandler extends Abstra
                         header[4] += FLAG_END_OF_HEADERS;
                     }
                     if (log.isDebugEnabled()) {
-                        log.debug(target.limit() + " bytes");
+                        log.debug(payload.limit() + " bytes");
                     }
                     ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue());
                     try {
                         socketWrapper.write(true, header, 0, header.length);
-                        socketWrapper.write(true, target);
+                        socketWrapper.write(true, payload);
                         socketWrapper.flush(true);
                     } catch (IOException ioe) {
                         handleAppInitiatedIOException(ioe);
                     }
-                }
-                if (state == State.UNDERFLOW && target.limit() == 0) {
-                    target = ByteBuffer.allocate(target.capacity() * 2);
-                } else {
-                    target.clear();
+                    payload.clear();
+                } else if (state == State.UNDERFLOW) {
+                    payload = ByteBuffer.allocate(payload.capacity() * 2);
                 }
             }
         }
@@ -1133,7 +1092,8 @@ class Http2UpgradeHandler extends Abstra
         Stream pushStream  = createLocalStream(request);
 
         // TODO: Is 1k the optimal value?
-        writePushHeaders(associatedStream, pushStream.getIdentifier().intValue(), request, 1024);
+        writeHeaders(associatedStream, pushStream.getIdentifier().intValue(),
+                request.getMimeHeaders(), false, 1024);
 
         pushStream.sentPushPromise();
 

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=1793758&r1=1793757&r2=1793758&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Thu May  4 09:22:45 2017
@@ -49,11 +49,13 @@ class Stream extends AbstractStream impl
     private static final int HEADER_STATE_REGULAR = 2;
     private static final int HEADER_STATE_TRAILER = 3;
 
-    private static final Response ACK_RESPONSE = new Response();
+    private static final MimeHeaders ACK_HEADERS;
 
     static {
-        ACK_RESPONSE.setStatus(100);
-        prepareHeaders(ACK_RESPONSE);
+        Response response =  new Response();
+        response.setStatus(100);
+        prepareHeaders(response);
+        ACK_HEADERS = response.getMimeHeaders();
     }
 
     private volatile int weight = Constants.DEFAULT_WEIGHT;
@@ -391,12 +393,12 @@ class Stream extends AbstractStream impl
         prepareHeaders(coyoteResponse);
         boolean endOfStream = getOutputBuffer().hasNoBody();
         // TODO: Is 1k the optimal value?
-        handler.writeHeaders(this, coyoteResponse, endOfStream, 1024);
+        handler.writeHeaders(this, 0, coyoteResponse.getMimeHeaders(), endOfStream, 1024);
     }
 
     final void writeAck() throws IOException {
         // TODO: Is 64 too big? Just the status header with compression
-        handler.writeHeaders(this, ACK_RESPONSE, false, 64);
+        handler.writeHeaders(this, 0, ACK_HEADERS, false, 64);
     }
 
 



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