Skip to content

Commit f61d5c8

Browse files
authored
fix h/3 ResponseContent with large buffer (#56892)
1 parent 6f0d05b commit f61d5c8

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,11 @@ private int ReadResponseContent(HttpResponseMessage response, Span<byte> buffer)
10281028
totalBytesRead += bytesRead;
10291029
_responseDataPayloadRemaining -= bytesRead;
10301030
buffer = buffer.Slice(bytesRead);
1031+
1032+
if (_responseDataPayloadRemaining == 0)
1033+
{
1034+
break;
1035+
}
10311036
}
10321037
}
10331038

@@ -1085,6 +1090,11 @@ private async ValueTask<int> ReadResponseContentAsync(HttpResponseMessage respon
10851090
totalBytesRead += bytesRead;
10861091
_responseDataPayloadRemaining -= bytesRead;
10871092
buffer = buffer.Slice(bytesRead);
1093+
1094+
if (_responseDataPayloadRemaining == 0)
1095+
{
1096+
break;
1097+
}
10881098
}
10891099
}
10901100

src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Net.Security;
99
using System.Net.Sockets;
1010
using System.Security.Authentication;
11+
using System.Security.Cryptography;
1112
using System.Security.Cryptography.X509Certificates;
1213
using System.Text;
1314
using System.Threading;
@@ -801,5 +802,59 @@ await Task.Run(async () =>
801802
await Assert.ThrowsAsync<QuicOperationAbortedException>(() => serverStream.ReadAsync(buffer).AsTask());
802803
}).WaitAsync(TimeSpan.FromMilliseconds(PassingTestTimeoutMilliseconds));
803804
}
805+
806+
[Theory]
807+
[InlineData(true)]
808+
[InlineData(false)]
809+
public async Task BigWrite_SmallRead_Success(bool closeWithData)
810+
{
811+
const int size = 100;
812+
(QuicConnection clientConnection, QuicConnection serverConnection) = await CreateConnectedQuicConnection();
813+
using (clientConnection)
814+
using (serverConnection)
815+
{
816+
byte[] buffer = new byte[1] { 42 };
817+
818+
QuicStream clientStream = clientConnection.OpenBidirectionalStream();
819+
Task<QuicStream> t = serverConnection.AcceptStreamAsync().AsTask();
820+
await TaskTimeoutExtensions.WhenAllOrAnyFailed(clientStream.WriteAsync(buffer).AsTask(), t, PassingTestTimeoutMilliseconds);
821+
QuicStream serverStream = t.Result;
822+
Assert.Equal(1, await serverStream.ReadAsync(buffer));
823+
824+
// streams are new established and in good shape.
825+
using (clientStream)
826+
using (serverStream)
827+
{
828+
byte[] expected = RandomNumberGenerator.GetBytes(size);
829+
byte[] actual = new byte[size];
830+
831+
// should be small enough to fit.
832+
await serverStream.WriteAsync(expected, closeWithData);
833+
834+
// Add delay to have chance to receive the 100b block before ReadAsync starts.
835+
await Task.Delay(10);
836+
int remaining = size;
837+
int readLength;
838+
while (remaining > 0)
839+
{
840+
readLength = await clientStream.ReadAsync(new Memory<byte>(actual, size - remaining, 1));
841+
Assert.Equal(1, readLength);
842+
remaining--;
843+
}
844+
845+
Assert.Equal(expected, actual);
846+
847+
if (!closeWithData)
848+
{
849+
serverStream.Shutdown();
850+
}
851+
852+
readLength = await clientStream.ReadAsync(actual);
853+
Assert.Equal(0, readLength);
854+
855+
Assert.Equal(expected, actual);
856+
}
857+
}
858+
}
804859
}
805860
}

0 commit comments

Comments
 (0)