use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.
the class Http2ConnectionHandlerTest method clientShouldNeverSend431WhenHeadersAreTooLarge.
@Test
public void clientShouldNeverSend431WhenHeadersAreTooLarge() throws Exception {
int padding = 0;
handler = newHandler();
Http2Exception e = new Http2Exception.HeaderListSizeException(STREAM_ID, PROTOCOL_ERROR, "Header size exceeded max allowed size 8196", true);
when(stream.id()).thenReturn(STREAM_ID);
when(connection.isServer()).thenReturn(false);
when(stream.isHeadersSent()).thenReturn(false);
when(remote.lastStreamCreated()).thenReturn(STREAM_ID);
when(frameWriter.writeRstStream(eq(ctx), eq(STREAM_ID), eq(PROTOCOL_ERROR.code()), eq(promise))).thenReturn(future);
handler.exceptionCaught(ctx, e);
verify(encoder, never()).writeHeaders(eq(ctx), eq(STREAM_ID), any(Http2Headers.class), eq(padding), eq(true), eq(promise));
verify(frameWriter).writeRstStream(ctx, STREAM_ID, PROTOCOL_ERROR.code(), promise);
}
use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.
the class Http2ConnectionRoundtripTest method noMoreStreamIdsShouldSendGoAway.
@Test
public void noMoreStreamIdsShouldSendGoAway() throws Exception {
bootstrapEnv(1, 1, 3, 1, 1);
// Don't wait for the server to close streams
setClientGracefulShutdownTime(0);
// Create a single stream by sending a HEADERS frame to the server.
final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, true, newPromise());
http2Client.flush(ctx());
}
});
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writeHeaders(ctx(), MAX_VALUE + 1, headers, 0, (short) 16, false, 0, true, newPromise());
http2Client.flush(ctx());
}
});
assertTrue(goAwayLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
verify(serverListener).onGoAwayRead(any(ChannelHandlerContext.class), eq(0), eq(PROTOCOL_ERROR.code()), any(ByteBuf.class));
}
use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.
the class Http2ConnectionRoundtripTest method priorityUsingHigherValuedStreamIdDoesNotPreventUsingLowerStreamId.
@Test
public void priorityUsingHigherValuedStreamIdDoesNotPreventUsingLowerStreamId() throws Exception {
bootstrapEnv(1, 1, 2, 0);
final Http2Headers headers = dummyHeaders();
runInChannel(clientChannel, new Http2Runnable() {
@Override
public void run() throws Http2Exception {
http2Client.encoder().writePriority(ctx(), 5, 3, (short) 14, false, newPromise());
http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
http2Client.flush(ctx());
}
});
assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
verify(serverListener).onPriorityRead(any(ChannelHandlerContext.class), eq(5), eq(3), eq((short) 14), eq(false));
verify(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(false));
// Verify that no errors have been received.
verify(serverListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
verify(serverListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
verify(clientListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
verify(clientListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
}
use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.
the class StreamBufferingEncoderTest method receivingGoAwayFailsBufferedStreams.
@Test
public void receivingGoAwayFailsBufferedStreams() throws Http2Exception {
encoder.writeSettingsAck(ctx, newPromise());
setMaxConcurrentStreams(5);
int streamId = 3;
List<ChannelFuture> futures = new ArrayList<ChannelFuture>();
for (int i = 0; i < 9; i++) {
futures.add(encoderWriteHeaders(streamId, newPromise()));
streamId += 2;
}
assertEquals(5, connection.numActiveStreams());
assertEquals(4, encoder.numBufferedStreams());
connection.goAwayReceived(11, 8, EMPTY_BUFFER);
assertEquals(5, connection.numActiveStreams());
assertEquals(0, encoder.numBufferedStreams());
int failCount = 0;
for (ChannelFuture f : futures) {
if (f.cause() != null) {
assertTrue(f.cause() instanceof Http2GoAwayException);
failCount++;
}
}
assertEquals(4, failCount);
}
use of io.netty.handler.codec.http2.Http2Exception in project netty by netty.
the class HpackDecoder method decode.
private void decode(ByteBuf in, Sink sink) throws Http2Exception {
int index = 0;
int nameLength = 0;
int valueLength = 0;
byte state = READ_HEADER_REPRESENTATION;
boolean huffmanEncoded = false;
CharSequence name = null;
IndexType indexType = IndexType.NONE;
while (in.isReadable()) {
switch(state) {
case READ_HEADER_REPRESENTATION:
byte b = in.readByte();
if (maxDynamicTableSizeChangeRequired && (b & 0xE0) != 0x20) {
// HpackEncoder MUST signal maximum dynamic table size change
throw MAX_DYNAMIC_TABLE_SIZE_CHANGE_REQUIRED;
}
if (b < 0) {
// Indexed Header Field
index = b & 0x7F;
switch(index) {
case 0:
throw DECODE_ILLEGAL_INDEX_VALUE;
case 0x7F:
state = READ_INDEXED_HEADER;
break;
default:
HpackHeaderField indexedHeader = getIndexedHeader(index);
sink.appendToHeaderList(indexedHeader.name, indexedHeader.value);
}
} else if ((b & 0x40) == 0x40) {
// Literal Header Field with Incremental Indexing
indexType = IndexType.INCREMENTAL;
index = b & 0x3F;
switch(index) {
case 0:
state = READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
break;
case 0x3F:
state = READ_INDEXED_HEADER_NAME;
break;
default:
// Index was stored as the prefix
name = readName(index);
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
}
} else if ((b & 0x20) == 0x20) {
// Dynamic Table Size Update
index = b & 0x1F;
if (index == 0x1F) {
state = READ_MAX_DYNAMIC_TABLE_SIZE;
} else {
setDynamicTableSize(index);
state = READ_HEADER_REPRESENTATION;
}
} else {
// Literal Header Field without Indexing / never Indexed
indexType = (b & 0x10) == 0x10 ? IndexType.NEVER : IndexType.NONE;
index = b & 0x0F;
switch(index) {
case 0:
state = READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
break;
case 0x0F:
state = READ_INDEXED_HEADER_NAME;
break;
default:
// Index was stored as the prefix
name = readName(index);
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
}
}
break;
case READ_MAX_DYNAMIC_TABLE_SIZE:
setDynamicTableSize(decodeULE128(in, (long) index));
state = READ_HEADER_REPRESENTATION;
break;
case READ_INDEXED_HEADER:
HpackHeaderField indexedHeader = getIndexedHeader(decodeULE128(in, index));
sink.appendToHeaderList(indexedHeader.name, indexedHeader.value);
state = READ_HEADER_REPRESENTATION;
break;
case READ_INDEXED_HEADER_NAME:
// Header Name matches an entry in the Header Table
name = readName(decodeULE128(in, index));
nameLength = name.length();
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
break;
case READ_LITERAL_HEADER_NAME_LENGTH_PREFIX:
b = in.readByte();
huffmanEncoded = (b & 0x80) == 0x80;
index = b & 0x7F;
if (index == 0x7f) {
state = READ_LITERAL_HEADER_NAME_LENGTH;
} else {
nameLength = index;
state = READ_LITERAL_HEADER_NAME;
}
break;
case READ_LITERAL_HEADER_NAME_LENGTH:
// Header Name is a Literal String
nameLength = decodeULE128(in, index);
state = READ_LITERAL_HEADER_NAME;
break;
case READ_LITERAL_HEADER_NAME:
// Wait until entire name is readable
if (in.readableBytes() < nameLength) {
throw notEnoughDataException(in);
}
name = readStringLiteral(in, nameLength, huffmanEncoded);
state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
break;
case READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX:
b = in.readByte();
huffmanEncoded = (b & 0x80) == 0x80;
index = b & 0x7F;
switch(index) {
case 0x7f:
state = READ_LITERAL_HEADER_VALUE_LENGTH;
break;
case 0:
insertHeader(sink, name, EMPTY_STRING, indexType);
state = READ_HEADER_REPRESENTATION;
break;
default:
valueLength = index;
state = READ_LITERAL_HEADER_VALUE;
}
break;
case READ_LITERAL_HEADER_VALUE_LENGTH:
// Header Value is a Literal String
valueLength = decodeULE128(in, index);
state = READ_LITERAL_HEADER_VALUE;
break;
case READ_LITERAL_HEADER_VALUE:
// Wait until entire value is readable
if (in.readableBytes() < valueLength) {
throw notEnoughDataException(in);
}
CharSequence value = readStringLiteral(in, valueLength, huffmanEncoded);
insertHeader(sink, name, value, indexType);
state = READ_HEADER_REPRESENTATION;
break;
default:
throw new Error("should not reach here state: " + state);
}
}
if (state != READ_HEADER_REPRESENTATION) {
throw connectionError(COMPRESSION_ERROR, "Incomplete header block fragment.");
}
}
Aggregations