Author: remm
Date: Thu Feb  8 21:25:40 2018
New Revision: 1823602

URL: http://svn.apache.org/viewvc?rev=1823602&view=rev
Log:
Refactoring to reduce duplication.

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java
    tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java

Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java?rev=1823602&r1=1823601&r2=1823602&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2AsyncParser.java Thu Feb  8 
21:25:40 2018
@@ -19,10 +19,8 @@ package org.apache.coyote.http2;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.CompletionHandler;
-import java.nio.charset.StandardCharsets;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.tomcat.util.buf.ByteBufferUtils;
 import org.apache.tomcat.util.net.SocketEvent;
 import org.apache.tomcat.util.net.SocketWrapperBase;
 import org.apache.tomcat.util.net.SocketWrapperBase.BlockingMode;
@@ -80,378 +78,13 @@ class Http2AsyncParser extends Http2Pars
         }
     }
 
-    // TODO: see how to refactor to avoid duplication
-    private void readDataFrame(int streamId, int flags, int payloadSize, 
ByteBuffer buffer)
-            throws Http2Exception, IOException {
-        // Process the Stream
-        int padLength = 0;
-
-        boolean endOfStream = Flags.isEndOfStream(flags);
-
-        int dataLength;
-        if (Flags.hasPadding(flags)) {
-            padLength = buffer.get() & 0xFF;
-
-            if (padLength >= payloadSize) {
-                throw new ConnectionException(
-                        
sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId,
-                                Integer.toString(streamId), 
Integer.toString(padLength),
-                                Integer.toString(payloadSize)), 
Http2Error.PROTOCOL_ERROR);
-            }
-            // +1 is for the padding length byte we just read above
-            dataLength = payloadSize - (padLength + 1);
-        } else {
-            dataLength = payloadSize;
-        }
-
-        if (log.isDebugEnabled()) {
-            String padding;
-            if (Flags.hasPadding(flags)) {
-                padding = Integer.toString(padLength);
-            } else {
-                padding = "none";
-            }
-            log.debug(sm.getString("http2Parser.processFrameData.lengths", 
connectionId,
-                    Integer.toString(streamId), Integer.toString(dataLength), 
padding));
-        }
-
-        ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize);
-        if (dest == null) {
-            swallow(streamId, dataLength, false, buffer);
-            // Process padding before sending any notifications in case padding
-            // is invalid.
-            if (padLength > 0) {
-                swallow(streamId, padLength, true, buffer);
-            }
-            if (endOfStream) {
-                output.receivedEndOfStream(streamId);
-            }
-        } else {
-            synchronized (dest) {
-                if (dest.remaining() < dataLength) {
-                    swallow(streamId, dataLength, false, buffer);
-                    // Client has sent more data than permitted by Window size
-                    throw new StreamException("Client sent more data than 
stream window allowed", Http2Error.FLOW_CONTROL_ERROR, streamId);
-                }
-                int oldLimit = buffer.limit();
-                buffer.limit(buffer.position() + dataLength);
-                dest.put(buffer);
-                buffer.limit(oldLimit);
-                // Process padding before sending any notifications in case
-                // padding is invalid.
-                if (padLength > 0) {
-                    swallow(streamId, padLength, true, buffer);
-                }
-                if (endOfStream) {
-                    output.receivedEndOfStream(streamId);
-                }
-                output.endRequestBodyFrame(streamId);
-            }
-        }
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        if (padLength > 0) {
-            output.swallowedPadding(streamId, padLength);
-        }
-    }
-
-
-    private void readHeadersFrame(int streamId, int flags, int payloadSize, 
ByteBuffer buffer)
-            throws Http2Exception, IOException {
-
-        headersEndStream = Flags.isEndOfStream(flags);
-
-        if (hpackDecoder == null) {
-            hpackDecoder = output.getHpackDecoder();
-        }
-
-        try {
-            hpackDecoder.setHeaderEmitter(output.headersStart(streamId, 
headersEndStream));
-        } catch (StreamException se) {
-            swallow(streamId, payloadSize, false, buffer);
-            throw se;
-        }
-
-        int padLength = 0;
-        boolean padding = Flags.hasPadding(flags);
-        boolean priority = Flags.hasPriority(flags);
-        int optionalLen = 0;
-        if (padding) {
-            optionalLen = 1;
-        }
-        if (priority) {
-            optionalLen += 5;
-        }
-        if (optionalLen > 0) {
-            byte[] optional = new byte[optionalLen];
-            buffer.get(optional);
-            int optionalPos = 0;
-            if (padding) {
-                padLength = ByteUtil.getOneByte(optional, optionalPos++);
-                if (padLength >= payloadSize) {
-                    throw new ConnectionException(
-                            
sm.getString("http2Parser.processFrame.tooMuchPadding", connectionId,
-                                    Integer.toString(streamId), 
Integer.toString(padLength),
-                                    Integer.toString(payloadSize)), 
Http2Error.PROTOCOL_ERROR);
-                }
-            }
-            if (priority) {
-                boolean exclusive = ByteUtil.isBit7Set(optional[optionalPos]);
-                int parentStreamId = ByteUtil.get31Bits(optional, optionalPos);
-                int weight = ByteUtil.getOneByte(optional, optionalPos + 4) + 
1;
-                output.reprioritise(streamId, parentStreamId, exclusive, 
weight);
-            }
-
-            payloadSize -= optionalLen;
-            payloadSize -= padLength;
-        }
-
-        readHeaderPayload(streamId, payloadSize, buffer);
-
-        swallow(streamId, padLength, true, buffer);
-
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-
-        if (Flags.isEndOfHeaders(flags)) {
-            onHeadersComplete(streamId);
-        } else {
-            headersCurrentStream = streamId;
-        }
-    }
-
-
-    private void readPriorityFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception, IOException {
-        byte[] payload = new byte[5];
-        buffer.get(payload);
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-
-        boolean exclusive = ByteUtil.isBit7Set(payload[0]);
-        int parentStreamId = ByteUtil.get31Bits(payload, 0);
-        int weight = ByteUtil.getOneByte(payload, 4) + 1;
-
-        if (streamId == parentStreamId) {
-            throw new 
StreamException(sm.getString("http2Parser.processFramePriority.invalidParent",
-                    connectionId, Integer.valueOf(streamId)), 
Http2Error.PROTOCOL_ERROR, streamId);
-        }
-
-        output.reprioritise(streamId, parentStreamId, exclusive, weight);
-    }
-
-
-    private void readRstFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception, IOException {
-        byte[] payload = new byte[4];
-        buffer.get(payload);
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-
-        long errorCode = ByteUtil.getFourBytes(payload, 0);
-        output.reset(streamId, errorCode);
-        headersCurrentStream = -1;
-        headersEndStream = false;
-    }
-
-
-    private void readSettingsFrame(int flags, int payloadSize, ByteBuffer 
buffer) throws Http2Exception, IOException {
-        boolean ack = Flags.isAck(flags);
-        if (payloadSize > 0 && ack) {
-            throw new ConnectionException(sm.getString(
-                    "http2Parser.processFrameSettings.ackWithNonZeroPayload"),
-                    Http2Error.FRAME_SIZE_ERROR);
-        }
-
-        if (payloadSize != 0) {
-            // Process the settings
-            byte[] setting = new byte[6];
-            for (int i = 0; i < payloadSize / 6; i++) {
-                buffer.get(setting);
-                int id = ByteUtil.getTwoBytes(setting, 0);
-                long value = ByteUtil.getFourBytes(setting, 2);
-                output.setting(Setting.valueOf(id), value);
-            }
-        }
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        output.settingsEnd(ack);
-    }
-
-
-    private void readPingFrame(int flags, ByteBuffer buffer) throws 
IOException {
-        // Read the payload
-        byte[] payload = new byte[8];
-        buffer.get(payload);
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        output.pingReceive(payload, Flags.isAck(flags));
-    }
-
-
-    private void readGoawayFrame(int payloadSize, ByteBuffer buffer) throws 
IOException {
-        byte[] payload = new byte[payloadSize];
-        buffer.get(payload);
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        int lastStreamId = ByteUtil.get31Bits(payload, 0);
-        long errorCode = ByteUtil.getFourBytes(payload, 4);
-        String debugData = null;
-        if (payloadSize > 8) {
-            debugData = new String(payload, 8, payloadSize - 8, 
StandardCharsets.UTF_8);
-        }
-        output.goaway(lastStreamId, errorCode, debugData);
-    }
-
-
-    private void readPushPromiseFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception {
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        throw new 
ConnectionException(sm.getString("http2Parser.processFramePushPromise",
-                connectionId, Integer.valueOf(streamId)), 
Http2Error.PROTOCOL_ERROR);
-    }
-
-
-    private void readWindowUpdateFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception, IOException {
-        byte[] payload = new byte[4];
-        buffer.get(payload);
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        int windowSizeIncrement = ByteUtil.get31Bits(payload, 0);
-
-        if (log.isDebugEnabled()) {
-            
log.debug(sm.getString("http2Parser.processFrameWindowUpdate.debug", 
connectionId,
-                    Integer.toString(streamId), 
Integer.toString(windowSizeIncrement)));
-        }
-
-        // Validate the data
-        if (windowSizeIncrement == 0) {
-            if (streamId == 0) {
-                throw new ConnectionException(
-                        
sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement"),
-                        Http2Error.PROTOCOL_ERROR);
-            } else {
-                throw new StreamException(
-                        
sm.getString("http2Parser.processFrameWindowUpdate.invalidIncrement"),
-                        Http2Error.PROTOCOL_ERROR, streamId);
-            }
-        }
-
-        output.incrementWindowSize(streamId, windowSizeIncrement);
-    }
-
-
-    private void readContinuationFrame(int streamId, int flags, int 
payloadSize, ByteBuffer buffer)
-            throws Http2Exception, IOException {
-        if (headersCurrentStream == -1) {
-            // No headers to continue
-            throw new ConnectionException(sm.getString(
-                    "http2Parser.processFrameContinuation.notExpected", 
connectionId,
-                    Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
-        }
-
-        readHeaderPayload(streamId, payloadSize, buffer);
-        if (buffer.hasRemaining()) {
+    protected void unRead(ByteBuffer buffer) {
+        if (buffer != null && buffer.hasRemaining()) {
             socketWrapper.unRead(buffer);
         }
-
-        if (Flags.isEndOfHeaders(flags)) {
-            headersCurrentStream = -1;
-            onHeadersComplete(streamId);
-        }
     }
 
-
-    private void readHeaderPayload(int streamId, int payloadSize, ByteBuffer 
buffer)
-            throws Http2Exception, IOException {
-
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("http2Parser.processFrameHeaders.payload", 
connectionId,
-                    Integer.valueOf(streamId), Integer.valueOf(payloadSize)));
-        }
-
-        int remaining = payloadSize;
-
-        while (remaining > 0) {
-            if (headerReadBuffer.remaining() == 0) {
-                // Buffer needs expansion
-                int newSize;
-                if (headerReadBuffer.capacity() < payloadSize) {
-                    // First step, expand to the current payload. That should
-                    // cover most cases.
-                    newSize = payloadSize;
-                } else {
-                    // Header must be spread over multiple frames. Keep 
doubling
-                    // buffer size until the header can be read.
-                    newSize = headerReadBuffer.capacity() * 2;
-                }
-                headerReadBuffer = ByteBufferUtils.expand(headerReadBuffer, 
newSize);
-            }
-            int toRead = Math.min(headerReadBuffer.remaining(), remaining);
-            // headerReadBuffer in write mode
-            int oldLimit = buffer.limit();
-            buffer.limit(buffer.position() + toRead);
-            headerReadBuffer.put(buffer);
-            buffer.limit(oldLimit);
-            // switch to read mode
-            headerReadBuffer.flip();
-            try {
-                hpackDecoder.decode(headerReadBuffer);
-            } catch (HpackException hpe) {
-                throw new ConnectionException(
-                        
sm.getString("http2Parser.processFrameHeaders.decodingFailed"),
-                        Http2Error.COMPRESSION_ERROR, hpe);
-            }
-
-            // switches to write mode
-            headerReadBuffer.compact();
-            remaining -= toRead;
-
-            if (hpackDecoder.isHeaderCountExceeded()) {
-                StreamException headerException = new 
StreamException(sm.getString(
-                        "http2Parser.headerLimitCount", connectionId, 
Integer.valueOf(streamId)),
-                        Http2Error.ENHANCE_YOUR_CALM, streamId);
-                
hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
-            }
-
-            if 
(hpackDecoder.isHeaderSizeExceeded(headerReadBuffer.position())) {
-                StreamException headerException = new 
StreamException(sm.getString(
-                        "http2Parser.headerLimitSize", connectionId, 
Integer.valueOf(streamId)),
-                        Http2Error.ENHANCE_YOUR_CALM, streamId);
-                
hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
-            }
-
-            if 
(hpackDecoder.isHeaderSwallowSizeExceeded(headerReadBuffer.position())) {
-                throw new 
ConnectionException(sm.getString("http2Parser.headerLimitSize",
-                        connectionId, Integer.valueOf(streamId)), 
Http2Error.ENHANCE_YOUR_CALM);
-            }
-        }
-    }
-
-
-    private void readUnknownFrame(int streamId, FrameType frameType, int 
flags, int payloadSize, ByteBuffer buffer)
-            throws IOException {
-        try {
-            swallow(streamId, payloadSize, false, buffer);
-        } catch (ConnectionException e) {
-            // Will never happen because swallow() is called with mustBeZero 
set
-            // to false
-        }
-        if (buffer.hasRemaining()) {
-            socketWrapper.unRead(buffer);
-        }
-        output.swallowed(streamId, frameType, flags, payloadSize);
-    }
-
-
-    private void swallow(int streamId, int len, boolean mustBeZero, ByteBuffer 
buffer)
+    protected void swallow(int streamId, int len, boolean mustBeZero, 
ByteBuffer buffer)
             throws IOException, ConnectionException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("http2Parser.swallow.debug", connectionId,
@@ -554,6 +187,7 @@ class Http2AsyncParser extends Http2Pars
                 try {
                     if (streamException) {
                         swallow(streamId, payloadSize, false, buffers[1]);
+                        unRead(buffers[1]);
                     } else {
                         switch (frameType) {
                         case DATA:
@@ -591,8 +225,7 @@ class Http2AsyncParser extends Http2Pars
                         }
                     }
                 } catch (Exception e) {
-                    failed(e, attachment);
-                    return;
+                    error = e;
                 }
             }
             if (state == CompletionState.DONE) {
@@ -603,8 +236,8 @@ class Http2AsyncParser extends Http2Pars
         }
 
         @Override
-        public void failed(Throwable exc, Void attachment) {
-            error = exc;
+        public void failed(Throwable e, Void attachment) {
+            error = e;
             if (state == CompletionState.DONE) {
                 // The call was not completed inline, so must start reading 
new frames
                 // or process any error

Modified: tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java?rev=1823602&r1=1823601&r2=1823602&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java Thu Feb  8 
21:25:40 2018
@@ -85,50 +85,52 @@ class Http2Parser {
         try {
             validateFrame(expected, frameType, streamId, flags, payloadSize);
         } catch (StreamException se) {
-            swallow(streamId, payloadSize, false);
+            swallow(streamId, payloadSize, false, null);
             throw se;
         }
 
         switch (frameType) {
         case DATA:
-            readDataFrame(streamId, flags, payloadSize);
+            readDataFrame(streamId, flags, payloadSize, null);
             break;
         case HEADERS:
-            readHeadersFrame(streamId, flags, payloadSize);
+            readHeadersFrame(streamId, flags, payloadSize, null);
             break;
         case PRIORITY:
-            readPriorityFrame(streamId);
+            readPriorityFrame(streamId, null);
             break;
         case RST:
-            readRstFrame(streamId);
+            readRstFrame(streamId, null);
             break;
         case SETTINGS:
-            readSettingsFrame(flags, payloadSize);
+            readSettingsFrame(flags, payloadSize, null);
             break;
         case PUSH_PROMISE:
-            readPushPromiseFrame(streamId);
+            readPushPromiseFrame(streamId, null);
             break;
         case PING:
-            readPingFrame(flags);
+            readPingFrame(flags, null);
             break;
         case GOAWAY:
-            readGoawayFrame(payloadSize);
+            readGoawayFrame(payloadSize, null);
             break;
         case WINDOW_UPDATE:
-            readWindowUpdateFrame(streamId);
+            readWindowUpdateFrame(streamId, null);
             break;
         case CONTINUATION:
-            readContinuationFrame(streamId, flags, payloadSize);
+            readContinuationFrame(streamId, flags, payloadSize, null);
             break;
         case UNKNOWN:
-            readUnknownFrame(streamId, frameType, flags, payloadSize);
+            readUnknownFrame(streamId, frameType, flags, payloadSize, null);
         }
 
         return true;
     }
 
+    protected void unRead(ByteBuffer buffer) {
+    }
 
-    private void readDataFrame(int streamId, int flags, int payloadSize)
+    protected void readDataFrame(int streamId, int flags, int payloadSize, 
ByteBuffer buffer)
             throws Http2Exception, IOException {
         // Process the Stream
         int padLength = 0;
@@ -137,9 +139,13 @@ class Http2Parser {
 
         int dataLength;
         if (Flags.hasPadding(flags)) {
-            byte[] b = new byte[1];
-            input.fill(true, b);
-            padLength = b[0] & 0xFF;
+            if (buffer == null) {
+                byte[] b = new byte[1];
+                input.fill(true, b);
+                padLength = b[0] & 0xFF;
+            } else {
+                padLength = buffer.get() & 0xFF;
+            }
 
             if (padLength >= payloadSize) {
                 throw new ConnectionException(
@@ -166,11 +172,11 @@ class Http2Parser {
 
         ByteBuffer dest = output.startRequestBodyFrame(streamId, payloadSize);
         if (dest == null) {
-            swallow(streamId, dataLength, false);
+            swallow(streamId, dataLength, false, buffer);
             // Process padding before sending any notifications in case padding
             // is invalid.
             if (padLength > 0) {
-                swallow(streamId, padLength, true);
+                swallow(streamId, padLength, true, buffer);
             }
             if (endOfStream) {
                 output.receivedEndOfStream(streamId);
@@ -178,15 +184,23 @@ class Http2Parser {
         } else {
             synchronized (dest) {
                 if (dest.remaining() < dataLength) {
-                    swallow(streamId, dataLength, false);
+                    swallow(streamId, dataLength, false, buffer);
+                    unRead(buffer);
                     // Client has sent more data than permitted by Window size
                     throw new StreamException("Client sent more data than 
stream window allowed", Http2Error.FLOW_CONTROL_ERROR, streamId);
                 }
-                input.fill(true, dest, dataLength);
+                if (buffer == null) {
+                    input.fill(true, dest, dataLength);
+                } else {
+                    int oldLimit = buffer.limit();
+                    buffer.limit(buffer.position() + dataLength);
+                    dest.put(buffer);
+                    buffer.limit(oldLimit);
+                }
                 // Process padding before sending any notifications in case
                 // padding is invalid.
                 if (padLength > 0) {
-                    swallow(streamId, padLength, true);
+                    swallow(streamId, padLength, true, buffer);
                 }
                 if (endOfStream) {
                     output.receivedEndOfStream(streamId);
@@ -194,13 +208,14 @@ class Http2Parser {
                 output.endRequestBodyFrame(streamId);
             }
         }
+        unRead(buffer);
         if (padLength > 0) {
             output.swallowedPadding(streamId, padLength);
         }
     }
 
 
-    private void readHeadersFrame(int streamId, int flags, int payloadSize)
+    protected void readHeadersFrame(int streamId, int flags, int payloadSize, 
ByteBuffer buffer)
             throws Http2Exception, IOException {
 
         headersEndStream = Flags.isEndOfStream(flags);
@@ -211,7 +226,7 @@ class Http2Parser {
         try {
             hpackDecoder.setHeaderEmitter(output.headersStart(streamId, 
headersEndStream));
         } catch (StreamException se) {
-            swallow(streamId, payloadSize, false);
+            swallow(streamId, payloadSize, false, buffer);
             throw se;
         }
 
@@ -227,7 +242,11 @@ class Http2Parser {
         }
         if (optionalLen > 0) {
             byte[] optional = new byte[optionalLen];
-            input.fill(true, optional);
+            if (buffer == null) {
+                input.fill(true, optional);
+            } else {
+                buffer.get(optional);
+            }
             int optionalPos = 0;
             if (padding) {
                 padLength = ByteUtil.getOneByte(optional, optionalPos++);
@@ -249,9 +268,11 @@ class Http2Parser {
             payloadSize -= padLength;
         }
 
-        readHeaderPayload(streamId, payloadSize);
+        readHeaderPayload(streamId, payloadSize, buffer);
+
+        swallow(streamId, padLength, true, buffer);
 
-        swallow(streamId, padLength, true);
+        unRead(buffer);
 
         if (Flags.isEndOfHeaders(flags)) {
             onHeadersComplete(streamId);
@@ -261,9 +282,14 @@ class Http2Parser {
     }
 
 
-    private void readPriorityFrame(int streamId) throws Http2Exception, 
IOException {
+    protected void readPriorityFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception, IOException {
         byte[] payload = new byte[5];
-        input.fill(true, payload);
+        if (buffer == null) {
+            input.fill(true, payload);
+        } else {
+            buffer.get(payload);
+            unRead(buffer);
+        }
 
         boolean exclusive = ByteUtil.isBit7Set(payload[0]);
         int parentStreamId = ByteUtil.get31Bits(payload, 0);
@@ -278,9 +304,14 @@ class Http2Parser {
     }
 
 
-    private void readRstFrame(int streamId) throws Http2Exception, IOException 
{
+    protected void readRstFrame(int streamId, ByteBuffer buffer) throws 
Http2Exception, IOException {
         byte[] payload = new byte[4];
-        input.fill(true, payload);
+        if (buffer == null) {
+            input.fill(true, payload);
+        } else {
+            buffer.get(payload);
+            unRead(buffer);
+        }
 
         long errorCode = ByteUtil.getFourBytes(payload, 0);
         output.reset(streamId, errorCode);
@@ -289,7 +320,7 @@ class Http2Parser {
     }
 
 
-    private void readSettingsFrame(int flags, int payloadSize) throws 
Http2Exception, IOException {
+    protected void readSettingsFrame(int flags, int payloadSize, ByteBuffer 
buffer) throws Http2Exception, IOException {
         boolean ack = Flags.isAck(flags);
         if (payloadSize > 0 && ack) {
             throw new ConnectionException(sm.getString(
@@ -301,33 +332,49 @@ class Http2Parser {
             // Process the settings
             byte[] setting = new byte[6];
             for (int i = 0; i < payloadSize / 6; i++) {
-                input.fill(true, setting);
+                if (buffer == null) {
+                    input.fill(true, setting);
+                } else {
+                    buffer.get(setting);
+                }
                 int id = ByteUtil.getTwoBytes(setting, 0);
                 long value = ByteUtil.getFourBytes(setting, 2);
                 output.setting(Setting.valueOf(id), value);
             }
         }
+        unRead(buffer);
         output.settingsEnd(ack);
     }
 
 
-    private void readPushPromiseFrame(int streamId) throws Http2Exception {
+    protected void readPushPromiseFrame(int streamId, ByteBuffer buffer) 
throws Http2Exception {
+        unRead(buffer);
         throw new 
ConnectionException(sm.getString("http2Parser.processFramePushPromise",
                 connectionId, Integer.valueOf(streamId)), 
Http2Error.PROTOCOL_ERROR);
     }
 
 
-    private void readPingFrame(int flags) throws IOException {
+    protected void readPingFrame(int flags, ByteBuffer buffer) throws 
IOException {
         // Read the payload
         byte[] payload = new byte[8];
-        input.fill(true, payload);
+        if (buffer == null) {
+            input.fill(true, payload);
+        } else {
+            buffer.get(payload);
+            unRead(buffer);
+        }
         output.pingReceive(payload, Flags.isAck(flags));
     }
 
 
-    private void readGoawayFrame(int payloadSize) throws IOException {
+    protected void readGoawayFrame(int payloadSize, ByteBuffer buffer) throws 
IOException {
         byte[] payload = new byte[payloadSize];
-        input.fill(true, payload);
+        if (buffer == null) {
+            input.fill(true, payload);
+        } else {
+            buffer.get(payload);
+            unRead(buffer);
+        }
 
         int lastStreamId = ByteUtil.get31Bits(payload, 0);
         long errorCode = ByteUtil.getFourBytes(payload, 4);
@@ -339,9 +386,14 @@ class Http2Parser {
     }
 
 
-    private void readWindowUpdateFrame(int streamId) throws Http2Exception, 
IOException {
+    protected void readWindowUpdateFrame(int streamId, ByteBuffer buffer) 
throws Http2Exception, IOException {
         byte[] payload = new byte[4];
-        input.fill(true,  payload);
+        if (buffer == null) {
+            input.fill(true, payload);
+        } else {
+            buffer.get(payload);
+            unRead(buffer);
+        }
         int windowSizeIncrement = ByteUtil.get31Bits(payload, 0);
 
         if (log.isDebugEnabled()) {
@@ -366,7 +418,7 @@ class Http2Parser {
     }
 
 
-    private void readContinuationFrame(int streamId, int flags, int 
payloadSize)
+    protected void readContinuationFrame(int streamId, int flags, int 
payloadSize, ByteBuffer buffer)
             throws Http2Exception, IOException {
         if (headersCurrentStream == -1) {
             // No headers to continue
@@ -375,7 +427,8 @@ class Http2Parser {
                     Integer.toString(streamId)), Http2Error.PROTOCOL_ERROR);
         }
 
-        readHeaderPayload(streamId, payloadSize);
+        readHeaderPayload(streamId, payloadSize, buffer);
+        unRead(buffer);
 
         if (Flags.isEndOfHeaders(flags)) {
             headersCurrentStream = -1;
@@ -384,7 +437,7 @@ class Http2Parser {
     }
 
 
-    private void readHeaderPayload(int streamId, int payloadSize)
+    protected void readHeaderPayload(int streamId, int payloadSize, ByteBuffer 
buffer)
             throws Http2Exception, IOException {
 
         if (log.isDebugEnabled()) {
@@ -411,7 +464,14 @@ class Http2Parser {
             }
             int toRead = Math.min(headerReadBuffer.remaining(), remaining);
             // headerReadBuffer in write mode
-            input.fill(true, headerReadBuffer, toRead);
+            if (buffer == null) {
+                input.fill(true, headerReadBuffer, toRead);
+            } else {
+                int oldLimit = buffer.limit();
+                buffer.limit(buffer.position() + toRead);
+                headerReadBuffer.put(buffer);
+                buffer.limit(oldLimit);
+            }
             // switch to read mode
             headerReadBuffer.flip();
             try {
@@ -448,46 +508,20 @@ class Http2Parser {
     }
 
 
-    protected void onHeadersComplete(int streamId) throws Http2Exception {
-        // Any left over data is a compression error
-        if (headerReadBuffer.position() > 0) {
-            throw new ConnectionException(
-                    
sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"),
-                    Http2Error.COMPRESSION_ERROR);
-        }
-
-        // Delay validation (and triggering any exception) until this point
-        // since all the headers still have to be read if a StreamException is
-        // going to be thrown.
-        hpackDecoder.getHeaderEmitter().validateHeaders();
-
-        output.headersEnd(streamId);
-
-        if (headersEndStream) {
-            output.receivedEndOfStream(streamId);
-            headersEndStream = false;
-        }
-
-        // Reset size for new request if the buffer was previously expanded
-        if (headerReadBuffer.capacity() > 
Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) {
-            headerReadBuffer = 
ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE);
-        }
-    }
-
-
-    private void readUnknownFrame(int streamId, FrameType frameType, int 
flags, int payloadSize)
+    protected void readUnknownFrame(int streamId, FrameType frameType, int 
flags, int payloadSize, ByteBuffer buffer)
             throws IOException {
         try {
-            swallow(streamId, payloadSize, false);
+            swallow(streamId, payloadSize, false, buffer);
         } catch (ConnectionException e) {
             // Will never happen because swallow() is called with mustBeZero 
set
             // to false
         }
+        unRead(buffer);
         output.swallowed(streamId, frameType, flags, payloadSize);
     }
 
 
-    private void swallow(int streamId, int len, boolean mustBeZero)
+    protected void swallow(int streamId, int len, boolean mustBeZero, 
ByteBuffer byteBuffer)
             throws IOException, ConnectionException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("http2Parser.swallow.debug", connectionId,
@@ -516,6 +550,33 @@ class Http2Parser {
         }
     }
 
+
+    protected void onHeadersComplete(int streamId) throws Http2Exception {
+        // Any left over data is a compression error
+        if (headerReadBuffer.position() > 0) {
+            throw new ConnectionException(
+                    
sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"),
+                    Http2Error.COMPRESSION_ERROR);
+        }
+
+        // Delay validation (and triggering any exception) until this point
+        // since all the headers still have to be read if a StreamException is
+        // going to be thrown.
+        hpackDecoder.getHeaderEmitter().validateHeaders();
+
+        output.headersEnd(streamId);
+
+        if (headersEndStream) {
+            output.receivedEndOfStream(streamId);
+            headersEndStream = false;
+        }
+
+        // Reset size for new request if the buffer was previously expanded
+        if (headerReadBuffer.capacity() > 
Constants.DEFAULT_HEADER_READ_BUFFER_SIZE) {
+            headerReadBuffer = 
ByteBuffer.allocate(Constants.DEFAULT_HEADER_READ_BUFFER_SIZE);
+        }
+    }
+
 
     /*
      * Implementation note:



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

Reply via email to