Skip to content

Commit

Permalink
Differentiate between retrieving an existing stream and creating a ne…
Browse files Browse the repository at this point in the history
…w one.

Start to add the 5.1.1 tests

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1684505 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
markt-asf committed Jun 9, 2015
1 parent 308ad47 commit 5bb5054
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 31 deletions.
4 changes: 2 additions & 2 deletions java/org/apache/coyote/http2/Http2Parser.java
Expand Up @@ -517,11 +517,11 @@ static interface Output {

// Data frames
ByteBuffer getInputByteBuffer(int streamId, int payloadSize) throws Http2Exception;
void receiveEndOfStream(int streamId);
void receiveEndOfStream(int streamId) throws ConnectionError;

// Header frames
HeaderEmitter headersStart(int streamId) throws Http2Exception;
void headersEnd(int streamId);
void headersEnd(int streamId) throws ConnectionError;

// Priority frames (also headers)
void reprioritise(int streamId, int parentStreamId, boolean exclusive, int weight)
Expand Down
80 changes: 51 additions & 29 deletions java/org/apache/coyote/http2/Http2UpgradeHandler.java
Expand Up @@ -168,7 +168,7 @@ public void init(WebConnection webConnection) {
socketWrapper.flush(true);

// Process the initial settings frame
stream = getStream(1);
stream = getStream(1, true);
String base64Settings = stream.getCoyoteRequest().getHeader(HTTP2_SETTINGS_HEADER);
byte[] settings = Base64.decodeBase64(base64Settings);

Expand Down Expand Up @@ -321,7 +321,8 @@ private void swallow(int len) throws IOException {
int toRead = Math.min(buffer.length, len - read);
int thisTime = socketWrapper.read(true, buffer, 0, toRead);
if (thisTime == -1) {
throw new IOException("TODO: i18n");
throw new IOException(
sm.getString("upgradeHandler.swallow.eos", Integer.valueOf(len)));
}
read += thisTime;
}
Expand All @@ -339,15 +340,17 @@ public void destroy() {
}


private void closeStream(StreamError se) throws IOException {
private void closeStream(StreamError se) throws ConnectionError, IOException {

if (log.isDebugEnabled()) {
log.debug(sm.getString("upgradeHandler.rst.debug", connectionId,
Integer.toString(se.getStreamId()), se.getError()));
}

Stream stream = getStream(se.getStreamId());
stream.sendRst();
Stream stream = getStream(se.getStreamId(), false);
if (stream != null) {
stream.sendRst();
}

// Write a RST frame
byte[] rstFrame = new byte[13];
Expand Down Expand Up @@ -624,18 +627,33 @@ private int allocate(AbstractStream stream, int allocation) {
}


private Stream getStream(int streamId) {
private Stream getStream(int streamId, boolean unknownIsError) throws ConnectionError{
Integer key = Integer.valueOf(streamId);
Stream result = streams.get(key);
if (result == null && unknownIsError) {
// Stream has been closed and removed from the map
throw new ConnectionError(sm.getString("upgradeHandler.stream.closed", key), Error.PROTOCOL_ERROR);
}
return result;
}


private Stream createRemoteStream(int streamId) throws ConnectionError {
Integer key = Integer.valueOf(streamId);

if (streamId > maxRemoteStreamId) {
// Must be a new stream
maxRemoteStreamId = streamId;
Stream stream = new Stream(key, this);
streams.put(key, stream);
return stream;
} else {
return streams.get(key);
if (streamId %2 != 1) {
throw new ConnectionError(
sm.getString("upgradeHandler.stream.even", key), Error.PROTOCOL_ERROR);
}

if (streamId <= maxRemoteStreamId) {
throw new ConnectionError(sm.getString("upgradeHandler.stream.old", key,
Integer.valueOf(maxRemoteStreamId)), Error.PROTOCOL_ERROR);
}

Stream result = new Stream(key, this);
streams.put(key, result);
return result;
}


Expand Down Expand Up @@ -741,7 +759,7 @@ public HpackDecoder getHpackDecoder() {

@Override
public ByteBuffer getInputByteBuffer(int streamId, int payloadSize) throws Http2Exception {
Stream stream = getStream(streamId);
Stream stream = getStream(streamId, true);
if (stream == null) {
return null;
}
Expand All @@ -751,8 +769,8 @@ public ByteBuffer getInputByteBuffer(int streamId, int payloadSize) throws Http2


@Override
public void receiveEndOfStream(int streamId) {
Stream stream = getStream(streamId);
public void receiveEndOfStream(int streamId) throws ConnectionError {
Stream stream = getStream(streamId, true);
if (stream != null) {
stream.receivedEndOfStream();
}
Expand All @@ -761,7 +779,10 @@ public void receiveEndOfStream(int streamId) {

@Override
public HeaderEmitter headersStart(int streamId) throws Http2Exception {
Stream stream = getStream(streamId);
Stream stream = getStream(streamId, false);
if (stream == null) {
stream = createRemoteStream(streamId);
}
stream.checkState(FrameType.HEADERS);
stream.receivedStartOfHeaders();
return stream;
Expand All @@ -771,9 +792,12 @@ public HeaderEmitter headersStart(int streamId) throws Http2Exception {
@Override
public void reprioritise(int streamId, int parentStreamId,
boolean exclusive, int weight) throws Http2Exception {
Stream stream = getStream(streamId);
Stream stream = getStream(streamId, false);
if (stream == null) {
stream = createRemoteStream(streamId);
}
stream.checkState(FrameType.PRIORITY);
AbstractStream parentStream = getStream(parentStreamId);
AbstractStream parentStream = getStream(parentStreamId, false);
if (parentStream == null) {
parentStream = this;
}
Expand All @@ -782,8 +806,8 @@ public void reprioritise(int streamId, int parentStreamId,


@Override
public void headersEnd(int streamId) {
Stream stream = getStream(streamId);
public void headersEnd(int streamId) throws ConnectionError {
Stream stream = getStream(streamId, true);
// Process this stream on a container thread
StreamProcessor streamProcessor = new StreamProcessor(stream, adapter, socketWrapper);
streamProcessor.setSslSupport(sslSupport);
Expand All @@ -794,7 +818,7 @@ public void headersEnd(int streamId) {

@Override
public void reset(int streamId, long errorCode) throws Http2Exception {
Stream stream = getStream(streamId);
Stream stream = getStream(streamId, true);
if (stream != null) {
stream.checkState(FrameType.RST);
stream.reset(errorCode);
Expand Down Expand Up @@ -852,13 +876,11 @@ public void goaway(int lastStreamId, long errorCode, String debugData) {

@Override
public void incrementWindowSize(int streamId, int increment) throws Http2Exception {
AbstractStream stream = getStream(streamId);
if (stream != null) {
if (streamId > 0) {
((Stream) stream).checkState(FrameType.WINDOW_UPDATE);
}
stream.incrementWindowSize(increment);
AbstractStream stream = getStream(streamId, true);
if (streamId > 0) {
((Stream) stream).checkState(FrameType.WINDOW_UPDATE);
}
stream.incrementWindowSize(increment);
}


Expand Down
4 changes: 4 additions & 0 deletions java/org/apache/coyote/http2/LocalStrings.properties
Expand Up @@ -69,6 +69,10 @@ upgradeHandler.init=Connection [{0}]
upgradeHandler.ioerror=Connection [{0}]
upgradeHandler.sendPrefaceFail=Failed to send preface to client
upgradeHandler.socketCloseFailed=Error closing socket
upgradeHandler.stream.closed=Stream [{0}] has been closed for some time
upgradeHandler.stream.even=A new remote stream ID of [{0}] was requested but all remote streams must use odd identifiers
upgradeHandler.stream.old=A new remote stream ID of [{0}] was requested but the most recent stream was [{1}]
upgradeHandler.swallow.eos=End of stream found while trying to swallow [{0}] bytes
upgradeHandler.unexpectedEos=Unexpected end of stream
upgradeHandler.unexpectedStatus=An unexpected value of status ([{0}]) was passed to this method
upgradeHandler.upgrade=Connection [{0}], HTTP/1.1 upgrade to stream [1]
Expand Down
27 changes: 27 additions & 0 deletions test/org/apache/coyote/http2/TestHttp2Section_5_1.java
Expand Up @@ -128,4 +128,31 @@ public void testClosedInvalidFrame02() throws Exception {


// TODO: Invalid frames for each of the remaining states

// Section 5.1.1

@Test
public void testClientSendEvenStream() throws Exception {
hpackEncoder = new HpackEncoder(ConnectionSettings.DEFAULT_HEADER_TABLE_SIZE);

// HTTP2 upgrade
http2Connect();

// Part 1
byte[] frameHeader = new byte[9];
ByteBuffer headersPayload = ByteBuffer.allocate(128);
buildSimpleRequestPart1(frameHeader, headersPayload, 4);
writeFrame(frameHeader, headersPayload);

// headers, body
parser.readFrame(true);

Assert.assertTrue(output.getTrace(),
output.getTrace().startsWith("0-Goaway-[2147483647]-[" +
Error.PROTOCOL_ERROR.getCode() + "]-["));
}

// TODO Remaining 5.1.1 tests

// TODO 5.1.2 tests
}

0 comments on commit 5bb5054

Please sign in to comment.