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: [email protected]
For additional commands, e-mail: [email protected]