use of io.netty.handler.codec.http2.Http2Stream in project vert.x by eclipse-vertx.
the class Http2ServerTest method testStreamPauseResume.
private void testStreamPauseResume(Function<HttpServerRequest, Future<ReadStream<Buffer>>> streamProvider) throws Exception {
Buffer expected = Buffer.buffer();
String chunk = TestUtils.randomAlphaString(1000);
AtomicBoolean done = new AtomicBoolean();
AtomicBoolean paused = new AtomicBoolean();
Buffer received = Buffer.buffer();
server.requestHandler(req -> {
Future<ReadStream<Buffer>> fut = streamProvider.apply(req);
fut.onComplete(onSuccess(stream -> {
vertx.setPeriodic(1, timerID -> {
if (paused.get()) {
vertx.cancelTimer(timerID);
done.set(true);
// Let some time to accumulate some more buffers
vertx.setTimer(100, id -> {
stream.resume();
});
}
});
stream.handler(received::appendBuffer);
stream.endHandler(v -> {
assertEquals(expected, received);
testComplete();
});
stream.pause();
}));
});
startServer();
TestClient client = new TestClient();
ChannelFuture fut = client.connect(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, request -> {
int id = request.nextStreamId();
request.encoder.writeHeaders(request.context, id, POST("/form").set("content-type", "text/plain"), 0, false, request.context.newPromise());
request.context.flush();
Http2Stream stream = request.connection.stream(id);
class Anonymous {
void send() {
boolean writable = request.encoder.flowController().isWritable(stream);
if (writable) {
Buffer buf = Buffer.buffer(chunk);
expected.appendBuffer(buf);
request.encoder.writeData(request.context, id, buf.getByteBuf(), 0, false, request.context.newPromise());
request.context.flush();
request.context.executor().execute(this::send);
} else {
request.encoder.writeData(request.context, id, Unpooled.EMPTY_BUFFER, 0, true, request.context.newPromise());
request.context.flush();
paused.set(true);
}
}
}
new Anonymous().send();
});
fut.sync();
await();
}
use of io.netty.handler.codec.http2.Http2Stream in project esa-restclient by esastack.
the class Http2FrameHandler method onHeadersRead.
@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int padding, boolean endOfStream) throws Http2Exception {
final Http2Stream stream = connection.stream(streamId);
headers.setInt(STREAM_ID.text(), streamId);
headers.addLong(HttpHeadersUtils.TTFB, System.currentTimeMillis());
onHeaders(streamId, stream, headers, stream.getProperty(messageKey) != null, endOfStream);
}
use of io.netty.handler.codec.http2.Http2Stream in project esa-restclient by esastack.
the class Http2FrameHandler method onDataRead.
@Override
public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding, boolean endOfStream) {
final ResponseHandle handle = registry.get(streamId);
if (handle == null) {
// The request has ended before.
return data.readableBytes() + padding;
}
final int readableBytes = data.readableBytes();
if (readableBytes > 0) {
ByteBuf retainedData;
boolean exceeded = false;
if (handle.remaining == -1L) {
retainedData = data;
} else {
handle.remaining -= readableBytes;
if (handle.remaining >= 0L) {
retainedData = data;
} else {
handle.remaining += readableBytes;
retainedData = data.slice(0, (int) handle.remaining);
exceeded = true;
handle.remaining = 0L;
}
}
handle.onData(new BufferImpl(retainedData.duplicate()));
if (exceeded) {
String errMsg = String.format("Content length exceeded %d bytes", maxContentLength);
onError(new ContentOverSizedException(errMsg), null, streamId, true);
return readableBytes + padding;
}
}
if (endOfStream) {
handle.onEnd();
final Http2Stream stream = connection.stream(streamId);
if (stream != null) {
stream.removeProperty(messageKey);
}
registry.remove(streamId);
}
// All bytes have been processed.
return readableBytes + padding;
}
use of io.netty.handler.codec.http2.Http2Stream in project esa-restclient by esastack.
the class Http2FrameHandler method onPushPromiseRead.
@Override
public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int promisedStreamId, Http2Headers headers, int padding) throws Http2Exception {
// A push promise should not be allowed to add headers to an existing stream
Http2Stream promisedStream = connection.stream(promisedStreamId);
if (promisedStream.getProperty(messageKey) != null) {
throw connectionError(PROTOCOL_ERROR, "Push Promise Frame received for pre-existing stream id %d", promisedStreamId);
}
if (headers.status() == null) {
headers.status(OK.codeAsText());
}
headers.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), Http2CodecUtil.DEFAULT_PRIORITY_WEIGHT);
headers.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_PROMISE_ID.text(), streamId);
onHeaders(promisedStreamId, promisedStream, headers, false, false);
}
use of io.netty.handler.codec.http2.Http2Stream in project esa-restclient by esastack.
the class Http2ConnectionHelper method setUp.
void setUp(HandleRegistry registry) throws Http2Exception {
MockitoAnnotations.initMocks(this);
when(stream.open(anyBoolean())).thenReturn(stream);
when(remote.flowController()).thenReturn(remoteFlowController);
when(local.flowController()).thenReturn(localFlowController);
when(connection.remote()).thenReturn(remote);
when(connection.local()).thenReturn(local);
when(connection.forEachActiveStream(any(Http2StreamVisitor.class))).thenAnswer((Answer<Http2Stream>) in -> {
Http2StreamVisitor visitor = in.getArgument(0);
if (!visitor.visit(stream)) {
return stream;
}
return null;
});
when(connection.numActiveStreams()).thenReturn(1);
when(connection.stream(STREAM_ID)).thenReturn(stream);
when(connection.goAwaySent(anyInt(), anyLong(), any(ByteBuf.class))).thenReturn(true);
when(encoder.connection()).thenReturn(connection);
when(encoder.frameWriter()).thenReturn(frameWriter);
when(encoder.flowController()).thenReturn(remoteFlow);
when(encoder.writeSettings(any(ChannelHandlerContext.class), any(Http2Settings.class), any(ChannelPromise.class))).thenAnswer(invocation -> {
ChannelPromise p = invocation.getArgument(2);
return p.setSuccess();
});
when(encoder.writeGoAway(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class))).thenAnswer(invocation -> {
ChannelPromise p = invocation.getArgument(4);
return p.setSuccess();
});
when(decoder.connection()).thenReturn(connection);
when(decoder.flowController()).thenReturn(localFlow);
when(frameWriter.writeGoAway(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class), any(ChannelPromise.class))).thenAnswer((Answer<ChannelFuture>) invocation -> {
ByteBuf buf = invocation.getArgument(3);
buf.release();
ChannelPromise p = invocation.getArgument(4);
return p.setSuccess();
});
channel = new EmbeddedChannel(new Http2ConnectionHandler(decoder, encoder, Http2Settings.defaultSettings(), false, registry));
Helper.mockHeaderAndDataFrameWrite(encoder);
}
Aggregations