Skip to content

Commit

Permalink
[Http/2] Fix handling of effectively empty DATA frame (#99502)
Browse files Browse the repository at this point in the history
* Fix handling effectively empty DATA frame

* Added test
  • Loading branch information
ManickaP authored Mar 11, 2024
1 parent 2909fe8 commit bbecf54
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -765,9 +765,12 @@ private void ProcessDataFrame(FrameHeader frameHeader)
// Just ignore the frame in this case.

ReadOnlySpan<byte> frameData = GetFrameData(_incomingBuffer.ActiveSpan.Slice(0, frameHeader.PayloadLength), hasPad: frameHeader.PaddedFlag, hasPriority: false);

bool endStream = frameHeader.EndStreamFlag;
http2Stream?.OnResponseData(frameData, endStream);

if (frameData.Length > 0 || endStream)
{
http2Stream?.OnResponseData(frameData, endStream);
}

if (frameData.Length > 0)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,50 @@ public async Task Http2_ZeroLengthResponseBody_Success()
}
}

[Fact]
public async Task Http2_DataFrameOnlyPadding_Success()
{
using (Http2LoopbackServer server = Http2LoopbackServer.CreateServer())
using (HttpClient client = CreateHttpClient())
{
Task<HttpResponseMessage> sendTask = client.GetAsync(server.Address, HttpCompletionOption.ResponseHeadersRead);

Http2LoopbackConnection connection = await server.EstablishConnectionAsync();

int streamId = await connection.ReadRequestHeaderAsync();

await connection.SendDefaultResponseHeadersAsync(streamId);

// Send zero-length DATA frame with padding
byte paddingLength = byte.MaxValue;
int dataLength = 1024;
DataFrame frame = new DataFrame(new byte[0], FrameFlags.Padded, paddingLength, streamId);
await connection.WriteFrameAsync(frame);

HttpResponseMessage response = await sendTask;
Assert.Equal(HttpStatusCode.OK, response.StatusCode);

using var responseStream = response.Content.ReadAsStream();

// The read must pend because we havent received any data yet.
var buffer = new byte[dataLength];
var readTask = responseStream.ReadAtLeastAsync(buffer, dataLength);
Assert.False(readTask.IsCompleted);

// Send DATA frame with padding
frame = new DataFrame(new byte[dataLength], FrameFlags.Padded, paddingLength, streamId);
await connection.WriteFrameAsync(frame);

Assert.Equal(dataLength, await readTask);

// Send zero-length, end-stream DATA frame with padding
frame = new DataFrame(new byte[0], FrameFlags.Padded | FrameFlags.EndStream, paddingLength, streamId);
await connection.WriteFrameAsync(frame);

Assert.Equal(0, await responseStream.ReadAsync(buffer));
}
}

[Theory]
[InlineData("Client content", null)]
[InlineData("Client content", "Server content")]
Expand Down

0 comments on commit bbecf54

Please sign in to comment.