Process all buffers in the Http2Connection (#13921)

- Change method name to TryReadFrame instead of ReadFrame
- Make TryReadFrame slice the incoming buffer
This commit is contained in:
David Fowler 2019-09-16 18:26:45 -07:00 committed by GitHub
parent a6fb55c405
commit 2de6c732d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 16 additions and 24 deletions

View File

@ -204,27 +204,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
while (_isClosed == 0) while (_isClosed == 0)
{ {
var result = await Input.ReadAsync(); var result = await Input.ReadAsync();
var readableBuffer = result.Buffer; var buffer = result.Buffer;
var consumed = readableBuffer.Start;
var examined = readableBuffer.Start;
// Call UpdateCompletedStreams() prior to frame processing in order to remove any streams that have exceded their drain timeouts. // Call UpdateCompletedStreams() prior to frame processing in order to remove any streams that have exceded their drain timeouts.
UpdateCompletedStreams(); UpdateCompletedStreams();
try try
{ {
if (!readableBuffer.IsEmpty) while (Http2FrameReader.TryReadFrame(ref buffer, _incomingFrame, _serverSettings.MaxFrameSize, out var framePayload))
{ {
if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, _serverSettings.MaxFrameSize, out var framePayload)) Log.Http2FrameReceived(ConnectionId, _incomingFrame);
{ await ProcessFrameAsync(application, framePayload);
Log.Http2FrameReceived(ConnectionId, _incomingFrame);
consumed = examined = framePayload.End;
await ProcessFrameAsync(application, framePayload);
}
else
{
examined = readableBuffer.End;
}
} }
if (result.IsCompleted) if (result.IsCompleted)
@ -242,7 +232,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
} }
finally finally
{ {
Input.AdvanceTo(consumed, examined); Input.AdvanceTo(buffer.Start, buffer.End);
UpdateConnectionState(); UpdateConnectionState();
} }

View File

@ -31,16 +31,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
public const int SettingSize = 6; // 2 bytes for the id, 4 bytes for the value. public const int SettingSize = 6; // 2 bytes for the id, 4 bytes for the value.
public static bool ReadFrame(in ReadOnlySequence<byte> readableBuffer, Http2Frame frame, uint maxFrameSize, out ReadOnlySequence<byte> framePayload) public static bool TryReadFrame(ref ReadOnlySequence<byte> buffer, Http2Frame frame, uint maxFrameSize, out ReadOnlySequence<byte> framePayload)
{ {
framePayload = ReadOnlySequence<byte>.Empty; framePayload = ReadOnlySequence<byte>.Empty;
if (readableBuffer.Length < HeaderLength) if (buffer.Length < HeaderLength)
{ {
return false; return false;
} }
var headerSlice = readableBuffer.Slice(0, HeaderLength); var headerSlice = buffer.Slice(0, HeaderLength);
var header = headerSlice.ToSpan(); var header = headerSlice.ToSpan();
var payloadLength = (int)Bitshifter.ReadUInt24BigEndian(header); var payloadLength = (int)Bitshifter.ReadUInt24BigEndian(header);
@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// Make sure the whole frame is buffered // Make sure the whole frame is buffered
var frameLength = HeaderLength + payloadLength; var frameLength = HeaderLength + payloadLength;
if (readableBuffer.Length < frameLength) if (buffer.Length < frameLength)
{ {
return false; return false;
} }
@ -61,10 +61,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
frame.Flags = header[FlagsOffset]; frame.Flags = header[FlagsOffset];
frame.StreamId = (int)Bitshifter.ReadUInt31BigEndian(header.Slice(StreamIdOffset)); frame.StreamId = (int)Bitshifter.ReadUInt31BigEndian(header.Slice(StreamIdOffset));
var extendedHeaderLength = ReadExtendedFields(frame, readableBuffer); var extendedHeaderLength = ReadExtendedFields(frame, buffer);
// The remaining payload minus the extra fields // The remaining payload minus the extra fields
framePayload = readableBuffer.Slice(HeaderLength + extendedHeaderLength, payloadLength - extendedHeaderLength); framePayload = buffer.Slice(HeaderLength + extendedHeaderLength, payloadLength - extendedHeaderLength);
buffer = buffer.Slice(framePayload.End);
return true; return true;
} }

View File

@ -1112,12 +1112,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
var buffer = result.Buffer; var buffer = result.Buffer;
var consumed = buffer.Start; var consumed = buffer.Start;
var examined = buffer.Start; var examined = buffer.Start;
var copyBuffer = buffer;
try try
{ {
Assert.True(buffer.Length > 0); Assert.True(buffer.Length > 0);
if (Http2FrameReader.ReadFrame(buffer, frame, maxFrameSize, out var framePayload)) if (Http2FrameReader.TryReadFrame(ref buffer, frame, maxFrameSize, out var framePayload))
{ {
consumed = examined = framePayload.End; consumed = examined = framePayload.End;
frame.Payload = framePayload.ToArray(); frame.Payload = framePayload.ToArray();
@ -1135,7 +1136,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
finally finally
{ {
_bytesReceived += buffer.Slice(buffer.Start, consumed).Length; _bytesReceived += copyBuffer.Slice(copyBuffer.Start, consumed).Length;
_pair.Application.Input.AdvanceTo(consumed, examined); _pair.Application.Input.AdvanceTo(consumed, examined);
} }
} }

View File

@ -103,7 +103,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.InMemory.FunctionalTests.Http2
try try
{ {
if (Http2FrameReader.ReadFrame(buffer, frame, 16_384, out var framePayload)) if (Http2FrameReader.TryReadFrame(ref buffer, frame, 16_384, out var framePayload))
{ {
consumed = examined = framePayload.End; consumed = examined = framePayload.End;
return frame; return frame;