diff --git a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs index 4f6319576..d61c0eafb 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs @@ -85,7 +85,7 @@ public override void Flush() private Task ReadAsync(ArraySegment buffer) { - return _input.ReadAsync(buffer); + return _input.ReadAsync(buffer.Array, buffer.Offset, buffer.Count); } } } diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs index c08d0eb68..e8310aab0 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -232,10 +232,8 @@ public async Task RequestProcessingAsync() await ProduceEnd(); - while (await RequestBody.ReadAsync(_nullBuffer, 0, _nullBuffer.Length) != 0) - { - // Finish reading the request body in case the app did not. - } + // Finish reading the request body in case the app did not. + await MessageBody.Consume(); } terminated = !_keepAlive; diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs index e8e438512..8edd424a1 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs @@ -38,6 +38,37 @@ protected MessageBody(FrameContext context) return result; } + public async Task Consume(CancellationToken cancellationToken = default(CancellationToken)) + { + Task result; + var send100checked = false; + do + { + result = ReadAsyncImplementation(default(ArraySegment), cancellationToken); + if (!result.IsCompleted) + { + if (!send100checked) + { + if (Interlocked.Exchange(ref _send100Continue, 0) == 1) + { + _context.FrameControl.ProduceContinue(); + } + send100checked = true; + } + } + else if (result.GetAwaiter().GetResult() == 0) + { + // Completed Task, end of stream + return; + } + else + { + // Completed Task, get next Task rather than await + continue; + } + } while (await result != 0); + } + public abstract Task ReadAsyncImplementation(ArraySegment buffer, CancellationToken cancellationToken); public static MessageBody For( @@ -108,7 +139,7 @@ public ForRemainingData(FrameContext context) public override Task ReadAsyncImplementation(ArraySegment buffer, CancellationToken cancellationToken) { - return _context.SocketInput.ReadAsync(buffer); + return _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, buffer.Array == null ? 8192 : buffer.Count); } } @@ -129,14 +160,13 @@ public override async Task ReadAsyncImplementation(ArraySegment buffe { var input = _context.SocketInput; - var limit = Math.Min(buffer.Count, _inputLength); + var limit = buffer.Array == null ? _inputLength : Math.Min(buffer.Count, _inputLength); if (limit == 0) { return 0; } - var limitedBuffer = new ArraySegment(buffer.Array, buffer.Offset, limit); - var actual = await _context.SocketInput.ReadAsync(limitedBuffer); + var actual = await _context.SocketInput.ReadAsync(buffer.Array, buffer.Offset, limit); _inputLength -= actual; if (actual == 0) @@ -189,7 +219,7 @@ public override async Task ReadAsyncImplementation(ArraySegment buffe } while (_mode == Mode.ChunkData) { - var limit = Math.Min(buffer.Count, _inputLength); + var limit = buffer.Array == null ? _inputLength : Math.Min(buffer.Count, _inputLength); if (limit != 0) { await input; diff --git a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInputExtensions.cs b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInputExtensions.cs index 9c5d69070..c36d88155 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInputExtensions.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/SocketInputExtensions.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { public static class SocketInputExtensions { - public static async Task ReadAsync(this SocketInput input, ArraySegment buffer) + public static async Task ReadAsync(this SocketInput input, byte[] buffer, int offset, int count) { while (true) { @@ -16,7 +16,7 @@ public static async Task ReadAsync(this SocketInput input, ArraySegment