in src/main/java/com/twitter/http2/HttpConnectionHandler.java [1001:1062]
private void updateSendWindowSize(
ChannelHandlerContext ctx, int streamId, int windowSizeIncrement) {
httpConnection.updateSendWindowSize(streamId, windowSizeIncrement);
while (true) {
// Check if we have unblocked a stalled stream
HttpConnection.PendingWrite e = httpConnection.getPendingWrite(streamId);
if (e == null) {
break;
}
HttpDataFrame httpDataFrame = e.httpDataFrame;
int dataFrameSize = httpDataFrame.content().readableBytes();
int writeStreamId = httpDataFrame.getStreamId();
int sendWindowSize = httpConnection.getSendWindowSize(writeStreamId);
int connectionSendWindowSize = httpConnection.getSendWindowSize(
HTTP_CONNECTION_STREAM_ID);
sendWindowSize = Math.min(sendWindowSize, connectionSendWindowSize);
if (sendWindowSize <= 0) {
return;
} else if (sendWindowSize < dataFrameSize) {
// We can send a partial frame
httpConnection.updateSendWindowSize(writeStreamId, -1 * sendWindowSize);
httpConnection.updateSendWindowSize(HTTP_CONNECTION_STREAM_ID, -1 * sendWindowSize);
// Create a partial data frame whose length is the current window size
ByteBuf data = httpDataFrame.content().readSlice(sendWindowSize).retain();
ByteBuf partialDataFrame = httpFrameEncoder.encodeDataFrame(writeStreamId, false, data);
ChannelPromise writeFuture = ctx.channel().newPromise();
// The transfer window size is pre-decremented when sending a data frame downstream.
// Close the connection on write failures that leaves the transfer window in a corrupt state.
writeFuture.addListener(connectionErrorListener);
ctx.writeAndFlush(partialDataFrame, writeFuture);
} else {
// Window size is large enough to send entire data frame
httpConnection.removePendingWrite(writeStreamId);
httpConnection.updateSendWindowSize(writeStreamId, -1 * dataFrameSize);
httpConnection.updateSendWindowSize(HTTP_CONNECTION_STREAM_ID, -1 * dataFrameSize);
// The transfer window size is pre-decremented when sending a data frame downstream.
// Close the connection on write failures that leaves the transfer window in a corrupt state.
e.promise.addListener(connectionErrorListener);
// Close the local side of the stream if this is the last frame
if (httpDataFrame.isLast()) {
halfCloseStream(writeStreamId, false, e.promise);
}
ByteBuf frame = httpFrameEncoder.encodeDataFrame(
writeStreamId,
httpDataFrame.isLast(),
httpDataFrame.content()
);
ctx.writeAndFlush(frame, e.promise);
}
}
}