use of io.netty.handler.codec.http2.Http2DataFrame in project netty by netty.
the class Http2MultiplexTest method endOfStreamDoesNotDiscardData.
@Test
public void endOfStreamDoesNotDiscardData() {
AtomicInteger numReads = new AtomicInteger(1);
final AtomicBoolean shouldDisableAutoRead = new AtomicBoolean();
Consumer<ChannelHandlerContext> ctxConsumer = new Consumer<ChannelHandlerContext>() {
@Override
public void accept(ChannelHandlerContext obj) {
if (shouldDisableAutoRead.get()) {
obj.channel().config().setAutoRead(false);
}
}
};
LastInboundHandler inboundHandler = new LastInboundHandler(ctxConsumer);
Http2StreamChannel childChannel = newInboundStream(3, false, numReads, inboundHandler);
childChannel.config().setAutoRead(false);
Http2DataFrame dataFrame1 = new DefaultHttp2DataFrame(bb("1")).stream(childChannel.stream());
Http2DataFrame dataFrame2 = new DefaultHttp2DataFrame(bb("2")).stream(childChannel.stream());
Http2DataFrame dataFrame3 = new DefaultHttp2DataFrame(bb("3")).stream(childChannel.stream());
Http2DataFrame dataFrame4 = new DefaultHttp2DataFrame(bb("4")).stream(childChannel.stream());
assertEquals(new DefaultHttp2HeadersFrame(request).stream(childChannel.stream()), inboundHandler.readInbound());
ChannelHandler readCompleteSupressHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
// We want to simulate the parent channel calling channelRead and delay calling channelReadComplete.
}
};
parentChannel.pipeline().addFirst(readCompleteSupressHandler);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("1"), 0, false);
assertEqualsAndRelease(dataFrame1, inboundHandler.<Http2DataFrame>readInbound());
// Deliver frames, and then a stream closed while read is inactive.
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("2"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("3"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("4"), 0, false);
shouldDisableAutoRead.set(true);
childChannel.config().setAutoRead(true);
numReads.set(1);
frameInboundWriter.writeInboundRstStream(childChannel.stream().id(), Http2Error.NO_ERROR.code());
// Detecting EOS should flush all pending data regardless of read calls.
assertEqualsAndRelease(dataFrame2, inboundHandler.<Http2DataFrame>readInbound());
assertNull(inboundHandler.readInbound());
// As we limited the number to 1 we also need to call read() again.
childChannel.read();
assertEqualsAndRelease(dataFrame3, inboundHandler.<Http2DataFrame>readInbound());
assertEqualsAndRelease(dataFrame4, inboundHandler.<Http2DataFrame>readInbound());
Http2ResetFrame resetFrame = useUserEventForResetFrame() ? inboundHandler.<Http2ResetFrame>readUserEvent() : inboundHandler.<Http2ResetFrame>readInbound();
assertEquals(childChannel.stream(), resetFrame.stream());
assertEquals(Http2Error.NO_ERROR.code(), resetFrame.errorCode());
assertNull(inboundHandler.readInbound());
// Now we want to call channelReadComplete and simulate the end of the read loop.
parentChannel.pipeline().remove(readCompleteSupressHandler);
parentChannel.flushInbound();
childChannel.closeFuture().syncUninterruptibly();
}
use of io.netty.handler.codec.http2.Http2DataFrame in project netty by netty.
the class Http2FrameCodecTest method upgradeWithoutFlowControlling.
@Test
public void upgradeWithoutFlowControlling() throws Exception {
channel.pipeline().addAfter(frameCodec.ctx.name(), null, new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Http2DataFrame) {
// Simulate consuming the frame and update the flow-controller.
Http2DataFrame data = (Http2DataFrame) msg;
ctx.writeAndFlush(new DefaultHttp2WindowUpdateFrame(data.initialFlowControlledBytes()).stream(data.stream())).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
ctx.fireExceptionCaught(cause);
}
}
});
}
ReferenceCountUtil.release(msg);
}
});
frameInboundWriter.writeInboundHeaders(Http2CodecUtil.HTTP_UPGRADE_STREAM_ID, request, 31, false);
// Using reflect as the constructor is package-private and the class is final.
Constructor<UpgradeEvent> constructor = UpgradeEvent.class.getDeclaredConstructor(CharSequence.class, FullHttpRequest.class);
// Check if we could make it accessible which may fail on java9.
Assumptions.assumeTrue(ReflectionUtil.trySetAccessible(constructor, true) == null);
String longString = new String(new char[70000]).replace("\0", "*");
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/", bb(longString));
HttpServerUpgradeHandler.UpgradeEvent upgradeEvent = constructor.newInstance("HTTP/2", request);
channel.pipeline().fireUserEventTriggered(upgradeEvent);
}
use of io.netty.handler.codec.http2.Http2DataFrame in project netty by netty.
the class Http2MultiplexTest method channelReadShouldRespectAutoReadAndNotProduceNPE.
@Test
public void channelReadShouldRespectAutoReadAndNotProduceNPE() throws Exception {
LastInboundHandler inboundHandler = new LastInboundHandler();
Http2StreamChannel childChannel = newInboundStream(3, false, inboundHandler);
assertTrue(childChannel.config().isAutoRead());
Http2HeadersFrame headersFrame = inboundHandler.readInbound();
assertNotNull(headersFrame);
childChannel.config().setAutoRead(false);
childChannel.pipeline().addFirst(new ChannelInboundHandlerAdapter() {
private int count;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
// Close channel after 2 reads so there is still something in the inboundBuffer when the close happens.
if (++count == 2) {
ctx.close();
}
}
});
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("hello world"), 0, false);
Http2DataFrame dataFrame0 = inboundHandler.readInbound();
assertNotNull(dataFrame0);
release(dataFrame0);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("foo"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("bar"), 0, false);
frameInboundWriter.writeInboundData(childChannel.stream().id(), bb("bar"), 0, false);
assertNull(inboundHandler.readInbound());
childChannel.config().setAutoRead(true);
verifyFramesMultiplexedToCorrectChannel(childChannel, inboundHandler, 3);
inboundHandler.checkException();
}
use of io.netty.handler.codec.http2.Http2DataFrame in project netty by netty.
the class Http2StaticFileServerHandler method sendError.
private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
Http2Headers headers = new DefaultHttp2Headers();
headers.status(status.toString());
headers.add(HttpHeaderNames.CONTENT_TYPE, "text/plain; charset=UTF-8");
Http2HeadersFrame headersFrame = new DefaultHttp2HeadersFrame(headers);
headersFrame.stream(stream);
Http2DataFrame dataFrame = new DefaultHttp2DataFrame(Unpooled.copiedBuffer("Failure: " + status + "\r\n", CharsetUtil.UTF_8), true);
dataFrame.stream(stream);
ctx.write(headersFrame);
ctx.writeAndFlush(dataFrame);
}
use of io.netty.handler.codec.http2.Http2DataFrame in project ambry by linkedin.
the class Http2ClientStreamStatsHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, Http2Frame frame) throws Exception {
ReferenceCountUtil.retain(frame);
RequestInfo requestInfo = ctx.channel().attr(Http2NetworkClient.REQUEST_INFO).get();
requestInfo.responseFramesCount++;
long time = System.currentTimeMillis() - requestInfo.getStreamSendTime();
if (frame instanceof Http2HeadersFrame) {
http2ClientMetrics.http2StreamRoundTripTime.update(time);
requestInfo.setStreamHeaderFrameReceiveTime(System.currentTimeMillis());
logger.debug("Header Frame received. Time from send: {}ms. Request: {}", time, requestInfo);
} else if (frame instanceof Http2DataFrame) {
logger.debug("Data Frame size: {}. Time from send: {}ms. Request: {}", ((Http2DataFrame) frame).content().readableBytes(), time, requestInfo);
}
if (frame instanceof Http2DataFrame && ((Http2DataFrame) frame).isEndStream()) {
http2ClientMetrics.http2StreamFirstToLastFrameTime.update(time);
http2ClientMetrics.http2ResponseFrameCount.update(requestInfo.responseFramesCount);
logger.debug("All Frame received. Time from send: {}ms. Request: {}", time, requestInfo);
}
ctx.fireChannelRead(frame);
}
Aggregations