Author: markt
Date: Tue Jun  2 11:13:24 2015
New Revision: 1683080

URL: http://svn.apache.org/r1683080
Log:
Switch to using the Http2Parser for frame processing
 - remove original frame parsing code from Http2UpgradeHandler

Modified:
    tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java
    tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java
    tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties
    tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java

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=1683080&r1=1683079&r2=1683080&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2Parser.java Tue Jun  2 
11:13:24 2015
@@ -25,7 +25,7 @@ import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 
-class Http2Parser implements HeaderEmitter {
+class Http2Parser {
 
     private static final Log log = LogFactory.getLog(Http2Parser.class);
     private static final StringManager sm = 
StringManager.getManager(Http2Parser.class);
@@ -175,9 +175,12 @@ class Http2Parser implements HeaderEmitt
 
         // TODO Handle end of headers flag
         // TODO Handle end of stream flag
-        // TODO Handle continutation frames
+        // TODO Handle continuation frames
 
-        output.headersStart(streamId);
+        if (hpackDecoder == null) {
+            hpackDecoder = output.getHpackDecoder();
+        }
+        hpackDecoder.setHeaderEmitter(output.headersStart(streamId));
 
         int padLength = 0;
         boolean padding = (flags & 0x08) > 0;
@@ -206,11 +209,6 @@ class Http2Parser implements HeaderEmitt
             payloadSize -= optionalLen;
         }
 
-        if (hpackDecoder == null) {
-            hpackDecoder = output.getHpackDecoder();
-            hpackDecoder.setHeaderEmitter(this);
-        }
-
         while (payloadSize > 0) {
             int toRead = Math.min(headerReadBuffer.remaining(), payloadSize);
             // headerReadBuffer in write mode
@@ -236,10 +234,12 @@ class Http2Parser implements HeaderEmitt
         }
 
         swallow(padLength);
+
+        output.headersEnd(streamId);
     }
 
 
-    private void readPriorityFrame(int flags, int streamId, int payloadSize) 
throws IOException {
+    private void readPriorityFrame(int streamId, int flags, int payloadSize) 
throws IOException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("http2Parser.processFrame", connectionId,
                     Integer.toString(streamId), Integer.toString(flags),
@@ -305,7 +305,7 @@ class Http2Parser implements HeaderEmitt
     }
 
 
-    private void readPingFrame(int flags, int streamId, int payloadSize)
+    private void readPingFrame(int streamId, int flags, int payloadSize)
             throws IOException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("http2Parser.processFrame", connectionId,
@@ -332,7 +332,7 @@ class Http2Parser implements HeaderEmitt
     }
 
 
-    private void readWindowUpdateFrame(int flags, int streamId, int 
payloadSize)
+    private void readWindowUpdateFrame(int streamId, int flags, int 
payloadSize)
             throws IOException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("http2Parser.processFrame", connectionId,
@@ -423,13 +423,6 @@ class Http2Parser implements HeaderEmitt
 
     void setHpackDecoder(HpackDecoder hpackDecoder) {
         this.hpackDecoder = hpackDecoder;
-        hpackDecoder.setHeaderEmitter(this);
-    }
-
-
-    @Override
-    public void emitHeader(String name, String value, boolean neverIndex) {
-        output.header(name, value);
     }
 
 
@@ -441,7 +434,7 @@ class Http2Parser implements HeaderEmitt
         /**
          * Fill the given array with data unless non-blocking is requested and
          * no data is available. If any data is available then the buffer will
-         * be filled with blocking I/O.
+         * be filled using blocking I/O.
          *
          * @param block Should the first read into the provided buffer be a
          *              blocking read or not.
@@ -472,7 +465,8 @@ class Http2Parser implements HeaderEmitt
 
 
     /**
-     *
+     * Interface that must be implemented to receive notifications from the
+     * parser as it processes incoming frames.
      */
     static interface Output {
 
@@ -483,17 +477,16 @@ class Http2Parser implements HeaderEmitt
         void endOfStream(int streamId);
 
         // Header frames
-        void headersStart(int streamId);
+        HeaderEmitter headersStart(int streamId);
         void reprioritise(int streamId, int parentStreamId, boolean exclusive, 
int weight);
-        void header(String name, String value);
-        void headersEnd();
+        void headersEnd(int streamId);
 
         // Settings frames
         void settingsAck();
         void setting(int identifier, long value) throws IOException;
 
         // Ping frames
-        void pingReceive(byte[] payload);
+        void pingReceive(byte[] payload) throws IOException;
         void pingAck();
 
         // Window size

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=1683080&r1=1683079&r2=1683080&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java 
(original)
+++ tomcat/trunk/java/org/apache/coyote/http2/Http2UpgradeHandler.java Tue Jun  
2 11:13:24 2015
@@ -36,6 +36,7 @@ import org.apache.coyote.ProtocolExcepti
 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;
 import org.apache.coyote.http2.Http2Parser.Input;
 import org.apache.coyote.http2.Http2Parser.Output;
@@ -85,15 +86,10 @@ public class Http2UpgradeHandler extends
 
     private static final int FRAME_TYPE_DATA = 0;
     private static final int FRAME_TYPE_HEADERS = 1;
-    private static final int FRAME_TYPE_PRIORITY = 2;
-    private static final int FRAME_TYPE_SETTINGS = 4;
-    private static final int FRAME_TYPE_PING = 6;
-    private static final int FRAME_TYPE_WINDOW_UPDATE = 8;
     private static final int FRAME_TYPE_CONTINUATION = 9;
 
     private static final byte[] PING_ACK = { 0x00, 0x00, 0x08, 0x06, 0x01, 
0x00, 0x00, 0x00, 0x00 };
 
-    private static final byte[] SETTINGS_ACK = { 0x00, 0x00, 0x00, 0x04, 0x01, 
0x00, 0x00, 0x00, 0x00 };
     private static final byte[] SETTINGS_EMPTY = { 0x00, 0x00, 0x00, 0x04, 
0x00, 0x00, 0x00, 0x00, 0x00 };
 
     private static final byte[] GOAWAY = { 0x07, 0x00, 0x00, 0x00, 0x00 };
@@ -111,14 +107,12 @@ public class Http2UpgradeHandler extends
     private volatile Http2Parser parser;
 
     private volatile boolean initialized = false;
-    private volatile boolean firstFrame = true;
 
     private final ConnectionSettings remoteSettings = new ConnectionSettings();
     private final ConnectionSettings localSettings = new ConnectionSettings();
     private volatile int maxRemoteStreamId = 0;
 
     private HpackDecoder hpackDecoder;
-    private ByteBuffer headerReadBuffer = ByteBuffer.allocate(1024);
     private HpackEncoder hpackEncoder;
 
     // All timeouts in milliseconds
@@ -155,7 +149,7 @@ public class Http2UpgradeHandler extends
             log.debug(sm.getString("upgradeHandler.init", connectionId));
         }
 
-        parser = new Http2Parser(connectionId, this, null);
+        parser = new Http2Parser(connectionId, this, this);
 
         initialized = true;
         Stream stream = null;
@@ -189,10 +183,6 @@ public class Http2UpgradeHandler extends
                     remoteSettings.set(id, value);
                 }
 
-                firstFrame = false;
-                hpackDecoder = new 
HpackDecoder(remoteSettings.getHeaderTableSize());
-                hpackEncoder = new 
HpackEncoder(localSettings.getHeaderTableSize());
-
                 if (!parser.readConnectionPreface()) {
                     throw new 
ProtocolException(sm.getString("upgradeHandler.invalidPreface"));
                 }
@@ -255,7 +245,7 @@ public class Http2UpgradeHandler extends
 
             // Process all the incoming data
             try {
-                while (processFrame()) {
+                while (parser.readFrame(false)) {
                 }
             } catch (Http2Exception h2e) {
                 if (h2e.getStreamId() == 0) {
@@ -330,342 +320,6 @@ public class Http2UpgradeHandler extends
     }
 
 
-    private boolean processFrame() throws IOException {
-        // TODO: Consider refactoring and making this a field to reduce GC.
-        byte[] frameHeader = new byte[9];
-        if (!getFrameHeader(frameHeader)) {
-            // Switch to keep-alive timeout between frames
-            socketWrapper.setReadTimeout(getKeepAliveTimeout());
-            return false;
-        }
-
-        int frameType = getFrameType(frameHeader);
-        int flags = ByteUtil.getOneByte(frameHeader, 4);
-        int streamId = ByteUtil.get31Bits(frameHeader, 5);
-        int payloadSize = getPayloadSize(streamId, frameHeader);
-
-        switch (frameType) {
-        case FRAME_TYPE_DATA:
-            processFrameData(flags, streamId, payloadSize);
-            break;
-        case FRAME_TYPE_HEADERS:
-            processFrameHeaders(flags, streamId, payloadSize);
-            break;
-        case FRAME_TYPE_PRIORITY:
-            processFramePriority(flags, streamId, payloadSize);
-            break;
-        case FRAME_TYPE_SETTINGS:
-            processFrameSettings(flags, streamId, payloadSize);
-            break;
-        case FRAME_TYPE_PING:
-            processFramePing(flags, streamId, payloadSize);
-            break;
-        case FRAME_TYPE_WINDOW_UPDATE:
-            processFrameWindowUpdate(flags, streamId, payloadSize);
-            break;
-        default:
-            // Unknown frame type.
-            processFrameUnknown(streamId, frameType, payloadSize);
-        }
-        return true;
-    }
-
-
-    private void processFrameData(int flags, int streamId, int payloadSize) 
throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-
-        // Validate the stream
-        if (streamId == 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameData.invalidStream"),
-                    0, Http2Exception.PROTOCOL_ERROR);
-        }
-
-        // Process the Stream
-        int padLength = 0;
-
-        boolean endOfStream = (flags & 0x01) > 0;
-        boolean padding = (flags & 0x08) > 0;
-
-        if (padding) {
-            byte[] b = new byte[1];
-            readFully(b);
-            padLength = b[0] & 0xFF;
-        }
-
-        // TODO Flow control
-        Stream stream = getStream(streamId);
-        ByteBuffer dest = stream.getInputByteBuffer();
-        synchronized (dest) {
-            readFully(dest, payloadSize);
-            if (endOfStream) {
-                stream.setEndOfStream();
-            }
-            dest.notifyAll();
-        }
-
-        swallow(padLength);
-    }
-
-
-    private void processFrameHeaders(int flags, int streamId, int payloadSize) 
throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-
-        // Validate the stream
-        if (streamId == 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameHeaders.invalidStream"),
-                    0, Http2Exception.PROTOCOL_ERROR);
-        }
-
-        // Process the stream
-        // TODO Handle end of headers flag
-        // TODO Handle end of stream flag
-        // TODO Handle continutation frames
-        Stream stream = getStream(streamId);
-        int padLength = 0;
-
-        boolean padding = (flags & 0x08) > 0;
-        boolean priority = (flags & 0x20) > 0;
-        int optionalLen = 0;
-        if (padding) {
-            optionalLen = 1;
-        }
-        if (priority) {
-            optionalLen += 5;
-        }
-        if (optionalLen > 0) {
-            byte[] optional = new byte[optionalLen];
-            readFully(optional);
-            int optionalPos = 0;
-            if (padding) {
-                padLength = ByteUtil.getOneByte(optional, optionalPos++);
-            }
-            if (priority) {
-                boolean exclusive = ByteUtil.isBit7Set(optional[optionalPos]);
-                int parentStreamId = ByteUtil.get31Bits(optional, optionalPos);
-                int weight = ByteUtil.getOneByte(optional, optionalPos + 4) + 
1;
-                AbstractStream parentStream = getStream(parentStreamId);
-                if (parentStream == null) {
-                    parentStream = this;
-                }
-                stream.rePrioritise(parentStream, exclusive, weight);
-            }
-
-            payloadSize -= optionalLen;
-        }
-
-        hpackDecoder.setHeaderEmitter(stream);
-        while (payloadSize > 0) {
-            int toRead = Math.min(headerReadBuffer.remaining(), payloadSize);
-            // headerReadBuffer in write mode
-            readFully(headerReadBuffer, toRead);
-            // switch to read mode
-            headerReadBuffer.flip();
-            try {
-                hpackDecoder.decode(headerReadBuffer);
-            } catch (HpackException hpe) {
-                throw new Http2Exception(
-                        
sm.getString("upgradeHandler.processFrameHeaders.decodingFailed"),
-                        0, Http2Exception.PROTOCOL_ERROR);
-            }
-            // switches to write mode
-            headerReadBuffer.compact();
-            payloadSize -= toRead;
-        }
-        // Should be empty at this point
-        if (headerReadBuffer.position() > 0) {
-            throw new Http2Exception(
-                    
sm.getString("upgradeHandler.processFrameHeaders.decodingDataLeft"),
-                    0, Http2Exception.PROTOCOL_ERROR);
-        }
-
-        swallow(padLength);
-
-        // Process this stream on a container thread
-        StreamProcessor streamProcessor = new StreamProcessor(stream, adapter, 
socketWrapper);
-        streamProcessor.setSslSupport(sslSupport);
-        socketWrapper.getEndpoint().getExecutor().execute(streamProcessor);
-    }
-
-
-    private void processFramePriority(int flags, int streamId, int 
payloadSize) throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-        // Validate the frame
-        if (streamId == 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFramePriority.invalidStream"),
-                    0, Http2Exception.PROTOCOL_ERROR);
-        }
-        if (payloadSize != 5) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFramePriority.invalidPayloadSize",
-                    Integer.toString(payloadSize)), streamId, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-
-        byte[] payload = new byte[5];
-        readFully(payload);
-
-        boolean exclusive = ByteUtil.isBit7Set(payload[0]);
-        int parentStreamId = ByteUtil.get31Bits(payload, 0);
-        int weight = ByteUtil.getOneByte(payload, 4) + 1;
-
-        Stream stream = getStream(streamId);
-        if (stream != null) {
-            // stream == null => an old stream already dropped from the map
-            AbstractStream parentStream;
-            if (parentStreamId == 0) {
-                parentStream = this;
-            } else {
-                parentStream = getStream(parentStreamId);
-                if (parentStream == null) {
-                    parentStream = this;
-                    weight = Constants.DEFAULT_WEIGHT;
-                    exclusive = false;
-                }
-            }
-            stream.rePrioritise(parentStream, exclusive, weight);
-        }
-    }
-
-
-    private void processFrameSettings(int flags, int streamId, int 
payloadSize) throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-        // Validate the frame
-        if (streamId != 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameSettings.invalidStream",
-                    Integer.toString(streamId)), 0, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-        if (payloadSize % 6 != 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameSettings.invalidPayloadSize",
-                    Integer.toString(payloadSize)), 0, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-        if (payloadSize > 0 && (flags & 0x1) != 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameSettings.ackWithNonZeroPayload"),
-                    0, Http2Exception.FRAME_SIZE_ERROR);
-        }
-
-        if (payloadSize == 0) {
-            // Either an ACK or an empty settings frame
-            if ((flags & 0x1) != 0) {
-                // TODO process ACK
-            }
-        } else {
-            // Process the settings
-            byte[] setting = new byte[6];
-            for (int i = 0; i < payloadSize / 6; i++) {
-                readFully(setting);
-                int id = ByteUtil.getTwoBytes(setting, 0);
-                long value = ByteUtil.getFourBytes(setting, 2);
-                remoteSettings.set(id, value);
-            }
-        }
-        if (firstFrame) {
-            firstFrame = false;
-            hpackDecoder = new 
HpackDecoder(remoteSettings.getHeaderTableSize());
-            hpackEncoder = new 
HpackEncoder(localSettings.getHeaderTableSize());
-        }
-
-        // Acknowledge the settings
-        socketWrapper.write(true, SETTINGS_ACK, 0, SETTINGS_ACK.length);
-        socketWrapper.flush(true);
-    }
-
-
-    private void processFramePing(int flags, int streamId, int payloadSize)
-            throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-        // Validate the frame
-        if (streamId != 0) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFramePing.invalidStream",
-                    Integer.toString(streamId)), 0, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-        if (payloadSize != 8) {
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFramePing.invalidPayloadSize",
-                    Integer.toString(payloadSize)), 0, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-        if ((flags & 0x1) == 0) {
-            // Read the payload
-            byte[] payload = new byte[8];
-            readFully(payload);
-            // Echo it back
-            socketWrapper.write(true, PING_ACK, 0, PING_ACK.length);
-            socketWrapper.write(true, payload, 0, payload.length);
-            socketWrapper.flush(true);
-        } else {
-            // This is an ACK.
-            // NO-OP (until such time this implementation decides to initiate
-            // pings)
-        }
-    }
-
-
-    private void processFrameWindowUpdate(int flags, int streamId, int 
payloadSize)
-            throws IOException {
-        if (log.isDebugEnabled()) {
-            log.debug(sm.getString("upgradeHandler.processFrame", connectionId,
-                    Integer.toString(streamId), Integer.toString(flags),
-                    Integer.toString(payloadSize)));
-        }
-        // Validate the frame
-        if (payloadSize != 4) {
-            // Use stream 0 since this is always a connection error
-            throw new 
Http2Exception(sm.getString("upgradeHandler.processFrameWindowUpdate.invalidPayloadSize",
-                    Integer.toString(payloadSize)), 0, 
Http2Exception.FRAME_SIZE_ERROR);
-        }
-
-        byte[] payload = new byte[4];
-        readFully(payload);
-        int windowSizeIncrement = ByteUtil.get31Bits(payload, 0);
-
-        if (log.isDebugEnabled()) {
-            
log.debug(sm.getString("upgradeHandler.processFrameWindowUpdate.debug", 
connectionId,
-                    Integer.toString(streamId), 
Integer.toString(windowSizeIncrement)));
-        }
-
-        // Validate the data
-        if (windowSizeIncrement == 0) {
-            throw new 
Http2Exception("upgradeHandler.processFrameWindowUpdate.invalidIncrement",
-                    streamId, Http2Exception.PROTOCOL_ERROR);
-        }
-        if (streamId == 0) {
-            incrementWindowSize(windowSizeIncrement);
-        } else {
-            Stream stream = getStream(streamId);
-            if (stream == null) {
-                // Old stream already closed.
-                // Ignore
-            } else {
-                stream.incrementWindowSize(windowSizeIncrement);
-            }
-        }
-    }
-
-
-    private void processFrameUnknown(int streamId, int type, int payloadSize) 
throws IOException {
-        // Swallow the payload
-        log.info("Swallowing [" + payloadSize + "] bytes of unknown frame type 
[" + type +
-                "] from stream [" + streamId + "]");
-        swallow(payloadSize);
-    }
-
-
     private void swallow(int len) throws IOException {
         if (len == 0) {
             return;
@@ -683,60 +337,6 @@ public class Http2UpgradeHandler extends
     }
 
 
-    private boolean getFrameHeader(byte[] frameHeader) throws IOException {
-        // All frames start with a fixed size header.
-        int headerBytesRead = socketWrapper.read(false, frameHeader, 0, 
frameHeader.length);
-
-        // No frame header read. Non-blocking between frames, so return.
-        if (headerBytesRead == 0) {
-            return false;
-        }
-
-        // Switch to read timeout
-        socketWrapper.setReadTimeout(getReadTimeout());
-
-        // Partial header read. Blocking within a frame to block while the
-        // remainder is read.
-        while (headerBytesRead < frameHeader.length) {
-            int read = socketWrapper.read(true, frameHeader, headerBytesRead,
-                    frameHeader.length - headerBytesRead);
-            if (read == -1) {
-                throw new 
EOFException(sm.getString("upgradeHandler.unexpectedEos"));
-            }
-        }
-
-        return true;
-    }
-
-
-    private int getFrameType(byte[] frameHeader) throws IOException {
-        int frameType = ByteUtil.getOneByte(frameHeader, 3);
-        // Make sure the first frame is a settings frame
-        if (firstFrame) {
-            if (frameType != FRAME_TYPE_SETTINGS) {
-                throw new 
Http2Exception(sm.getString("upgradeHandler.receivePrefaceNotSettings"),
-                        0, Http2Exception.PROTOCOL_ERROR);
-            }
-        }
-        return frameType;
-    }
-
-
-    private int getPayloadSize(int streamId, byte[] frameHeader) throws 
IOException {
-        // Make sure the payload size is valid
-        int payloadSize = ByteUtil.getThreeBytes(frameHeader, 0);
-
-        if (payloadSize > remoteSettings.getMaxFrameSize()) {
-            swallow(payloadSize);
-            throw new 
Http2Exception(sm.getString("upgradeHandler.payloadTooBig",
-                    Integer.toString(payloadSize), 
Long.toString(remoteSettings.getMaxFrameSize())),
-                    streamId, Http2Exception.FRAME_SIZE_ERROR);
-        }
-
-        return payloadSize;
-    }
-
-
     ConnectionSettings getRemoteSettings() {
         return remoteSettings;
     }
@@ -767,31 +367,6 @@ public class Http2UpgradeHandler extends
     }
 
 
-    private void readFully(byte[] dest) throws IOException {
-        int read = 0;
-        while (read < dest.length) {
-            int thisTime = socketWrapper.read(true, dest, read, dest.length - 
read);
-            if (thisTime == -1) {
-                throw new 
EOFException(sm.getString("upgradeHandler.unexpectedEos"));
-            }
-            read += thisTime;
-        }
-    }
-
-
-    private void readFully(ByteBuffer dest, int len) throws IOException {
-        int read = 0;
-        while (read < len) {
-            int thisTime = socketWrapper.read(true, dest.array(), 
dest.arrayOffset(), len -read);
-            if (thisTime == -1) {
-                throw new 
EOFException(sm.getString("upgradeHandler.unexpectedEos"));
-            }
-            read += thisTime;
-        }
-        dest.position(dest.position() + read);
-    }
-
-
     void writeHeaders(Stream stream, Response coyoteResponse) throws 
IOException {
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("upgradeHandler.writeHeaders", connectionId,
@@ -809,7 +384,7 @@ public class Http2UpgradeHandler extends
             boolean first = true;
             State state = null;
             while (state != State.COMPLETE) {
-                state = hpackEncoder.encode(coyoteResponse.getMimeHeaders(), 
target);
+                state = 
getHpackEncoder().encode(coyoteResponse.getMimeHeaders(), target);
                 target.flip();
                 ByteUtil.setThreeBytes(header, 0, target.limit());
                 if (first) {
@@ -835,6 +410,14 @@ public class Http2UpgradeHandler extends
     }
 
 
+    private HpackEncoder getHpackEncoder() {
+        if (hpackEncoder == null) {
+            hpackEncoder = new 
HpackEncoder(localSettings.getHeaderTableSize());
+        }
+        return hpackEncoder;
+    }
+
+
     void writeBody(Stream stream, ByteBuffer data, int len) throws IOException 
{
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("upgradeHandler.writeBody", connectionId, 
stream.getIdentifier(),
@@ -1109,51 +692,57 @@ public class Http2UpgradeHandler extends
 
     @Override
     public HpackDecoder getHpackDecoder() {
-        // TODO Auto-generated method stub
-        return null;
+        if (hpackDecoder == null) {
+            hpackDecoder = new 
HpackDecoder(remoteSettings.getHeaderTableSize());
+        }
+        return hpackDecoder;
     }
 
 
     @Override
     public ByteBuffer getInputByteBuffer(int streamId, int payloadSize) {
-        // TODO Auto-generated method stub
-        return null;
+        Stream stream = getStream(streamId);
+        if (stream == null) {
+            return null;
+        }
+        return stream.getInputByteBuffer();
     }
 
 
     @Override
     public void endOfStream(int streamId) {
-        // TODO Auto-generated method stub
-
+        Stream stream = getStream(streamId);
+        if (stream != null) {
+            stream.setEndOfStream();
+        }
     }
 
 
     @Override
-    public void headersStart(int streamId) {
-        // TODO Auto-generated method stub
-
+    public HeaderEmitter headersStart(int streamId) {
+        return getStream(streamId);
     }
 
 
     @Override
     public void reprioritise(int streamId, int parentStreamId,
             boolean exclusive, int weight) {
-        // TODO Auto-generated method stub
-
-    }
-
-
-    @Override
-    public void header(String name, String value) {
-        // TODO Auto-generated method stub
-
+        Stream stream = getStream(streamId);
+        AbstractStream parentStream = getStream(parentStreamId);
+        if (parentStream == null) {
+            parentStream = this;
+        }
+        stream.rePrioritise(parentStream, exclusive, weight);
     }
 
 
     @Override
-    public void headersEnd() {
-        // TODO Auto-generated method stub
-
+    public void headersEnd(int streamId) {
+        // Process this stream on a container thread
+        StreamProcessor streamProcessor = new StreamProcessor(
+                getStream(streamId), adapter, socketWrapper);
+        streamProcessor.setSslSupport(sslSupport);
+        socketWrapper.getEndpoint().getExecutor().execute(streamProcessor);
     }
 
 
@@ -1170,8 +759,11 @@ public class Http2UpgradeHandler extends
 
 
     @Override
-    public void pingReceive(byte[] payload) {
-        // TODO Auto-generated method stub
+    public void pingReceive(byte[] payload) throws IOException {
+        // Echo it back
+        socketWrapper.write(true, PING_ACK, 0, PING_ACK.length);
+        socketWrapper.write(true, payload, 0, payload.length);
+        socketWrapper.flush(true);
     }
 
 
@@ -1183,7 +775,10 @@ public class Http2UpgradeHandler extends
 
     @Override
     public void incrementWindowSize(int streamId, int increment) {
-        // TODO Auto-generated method stub
+        AbstractStream stream = getStream(streamId);
+        if (stream != null) {
+            stream.incrementWindowSize(increment);
+        }
     }
 
 

Modified: tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties?rev=1683080&r1=1683079&r2=1683080&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties (original)
+++ tomcat/trunk/java/org/apache/coyote/http2/LocalStrings.properties Tue Jun  
2 11:13:24 2015
@@ -60,15 +60,6 @@ upgradeHandler.connectionError=An error
 upgradeHandler.init=Connection [{0}]
 upgradeHandler.ioerror=Connection [{0}]
 upgradeHandler.invalidPreface=And invalid connection preface was received from 
the client
-upgradeHandler.processFrame=Connection [{0}], Stream [{1}], Flags [{2}], 
Payload size [{3}]
-upgradeHandler.processFrameHeaders.invalidStream=Headers frame received for 
stream [0]
-upgradeHandler.processFrameHeaders.decodingFailed=There was an error during 
the HPACK decoding of HTTP headers
-upgradeHandler.processFrameHeaders.decodingDataLeft=Data left over after HPACK 
decoding - it should have been consumed
-upgradeHandler.processFramePriority.invalidPayloadSize=Priority frame received 
with an invalid payload size of [{0}] (should be 5)
-upgradeHandler.processFramePriority.invalidStream=Priority frame received for 
stream [0]
-upgradeHandler.processFrameSettings.ackWithNonZeroPayload=Settings frame 
received with the ACK flag set and payload present
-upgradeHandler.processFrameSettings.invalidPayloadSize=Settings frame received 
with a payload size of [{0}] which is not a multiple of 6
-upgradeHandler.processFrameSettings.invalidStream=Settings frame received for 
stream [{0}]
 upgradeHandler.receivePrefaceNotSettings=The first frame received from the 
client was not a settings frame
 upgradeHandler.sendPrefaceFail=Failed to send preface to client
 upgradeHandler.socketCloseFailed=Error closing socket

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=1683080&r1=1683079&r2=1683080&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original)
+++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Tue Jun  2 
11:13:24 2015
@@ -36,7 +36,9 @@ import org.apache.catalina.LifecycleExce
 import org.apache.catalina.connector.Connector;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.catalina.startup.TomcatBaseTest;
+import org.apache.coyote.http2.HpackDecoder.HeaderEmitter;
 import org.apache.coyote.http2.Http2Parser.Input;
+import org.apache.coyote.http2.Http2Parser.Output;
 import org.apache.tomcat.util.codec.binary.Base64;
 
 
@@ -75,10 +77,11 @@ public abstract class Http2TestBase exte
         parser.readFrame(true);
         parser.readFrame(true);
 
-        Assert.assertEquals("1-HeadersStart\n"
-                + "1-Header-[:status]-[200]\n"
-                + "1-Body-8192\n"
-                + "1-EndOfStream", output.getTrace());
+        Assert.assertEquals("1-HeadersStart\n" +
+                "1-Header-[:status]-[200]\n" +
+                "1-HeadersEnd\n" +
+                "1-Body-8192\n" +
+                "1-EndOfStream", output.getTrace());
         output.clearTrace();
     }
 
@@ -234,7 +237,7 @@ public abstract class Http2TestBase exte
     }
 
 
-    private static class TestOutput implements Http2Parser.Output {
+    private static class TestOutput implements Output, HeaderEmitter {
 
         private StringBuffer trace = new StringBuffer();
         private String lastStreamId = "0";
@@ -263,9 +266,10 @@ public abstract class Http2TestBase exte
 
 
         @Override
-        public void headersStart(int streamId) {
+        public HeaderEmitter headersStart(int streamId) {
             lastStreamId = Integer.toString(streamId);
             trace.append(lastStreamId + "-HeadersStart\n");
+            return this;
         }
 
         @Override
@@ -275,16 +279,19 @@ public abstract class Http2TestBase exte
                     "]-[" + weight + "]\n");
         }
 
+
         @Override
-        public void header(String name, String value) {
+        public void emitHeader(String name, String value, boolean neverIndex) {
             trace.append(lastStreamId + "-Header-[" + name + "]-[" + value + 
"]\n");
         }
 
+
         @Override
-        public void headersEnd() {
-            trace.append(lastStreamId + "-HeadersEnd\n");
+        public void headersEnd(int streamId) {
+            trace.append(streamId + "-HeadersEnd\n");
         }
 
+
         @Override
         public void settingsAck() {
             trace.append("0-Settings-Ack\n");



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

Reply via email to