Fix PipeReader consumption pattern [2.1]

This commit is contained in:
Stephen Halter 2018-05-31 11:27:38 -07:00 committed by GitHub
parent 65336fe9cb
commit 9e15b2bca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 73 additions and 21 deletions

View File

@ -107,10 +107,6 @@ namespace PlatformBenchmarks
ThrowUnexpectedEndOfData();
}
}
else if (result.IsCompleted)
{
break;
}
Reader.AdvanceTo(consumed, examined);
@ -120,6 +116,10 @@ namespace PlatformBenchmarks
_state = State.StartLine;
}
else if (result.IsCompleted)
{
break;
}
}
}

View File

@ -125,7 +125,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal
readableBuffer.CopyTo(destination.Span);
return count;
}
else if (result.IsCompleted)
if (result.IsCompleted)
{
return 0;
}

View File

@ -87,7 +87,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
break;
}
}
else if (result.IsCompleted)
// Read() will have already have greedily consumed the entire request body if able.
if (result.IsCompleted)
{
// Treat any FIN from an upgraded request as expected.
// It's up to higher-level consumer (i.e. WebSocket middleware) to determine

View File

@ -57,7 +57,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
slice.CopyTo(buffer.Span);
return actual;
}
else if (result.IsCompleted)
if (result.IsCompleted)
{
return 0;
}
@ -96,7 +97,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
#endif
}
}
else if (result.IsCompleted)
if (result.IsCompleted)
{
return;
}

View File

@ -117,14 +117,12 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
try
{
if (!readableBuffer.IsEmpty)
if (!readableBuffer.IsEmpty && ParsePreface(readableBuffer, out consumed, out examined))
{
if (ParsePreface(readableBuffer, out consumed, out examined))
{
break;
}
break;
}
else if (result.IsCompleted)
if (result.IsCompleted)
{
return;
}
@ -149,13 +147,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
try
{
if (!readableBuffer.IsEmpty)
if (!readableBuffer.IsEmpty && Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, out consumed, out examined))
{
if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, out consumed, out examined))
{
Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}");
await ProcessFrameAsync<TContext>(application);
}
Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}");
await ProcessFrameAsync<TContext>(application);
}
else if (result.IsCompleted)
{

View File

@ -99,7 +99,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal
writeReq = null;
}
}
else if (result.IsCompleted)
if (result.IsCompleted)
{
break;
}

View File

@ -1,14 +1,17 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Logging.Testing;
using Xunit;
@ -634,6 +637,54 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
}
}
}
[Theory]
[MemberData(nameof(ConnectionAdapterData))]
public async Task ClosingConnectionMidChunkPrefixThrows(ListenOptions listenOptions)
{
var testContext = new TestServiceContext(LoggerFactory);
var readStartedTcs = new TaskCompletionSource<object>();
var exTcs = new TaskCompletionSource<BadHttpRequestException>();
using (var server = new TestServer(async httpContext =>
{
var readTask = httpContext.Request.Body.CopyToAsync(Stream.Null);
readStartedTcs.SetResult(null);
try
{
await readTask;
}
catch (BadHttpRequestException badRequestEx)
{
exTcs.TrySetResult(badRequestEx);
}
catch (Exception ex)
{
exTcs.SetException(ex);
}
}, testContext, listenOptions))
{
using (var connection = server.CreateConnection())
{
await connection.SendAll(
"POST / HTTP/1.1",
"Host:",
"Transfer-Encoding: chunked",
"",
"1");
await readStartedTcs.Task.TimeoutAfter(TestConstants.DefaultTimeout);
connection.Socket.Shutdown(SocketShutdown.Send);
await connection.ReceiveEnd();
var badReqEx = await exTcs.Task.TimeoutAfter(TestConstants.DefaultTimeout);
Assert.Equal(RequestRejectionReason.UnexpectedEndOfRequestContent, badReqEx.Reason);
}
}
}
}
}