diff --git a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs index 4f63195760..d61c0eafbc 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Filter/LibuvStream.cs @@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Filter 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 c13826964b..bf6b821d3e 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs @@ -234,10 +234,8 @@ namespace Microsoft.AspNet.Server.Kestrel.Http 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 e8e438512b..8edd424a10 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Http/MessageBody.cs @@ -38,6 +38,37 @@ namespace Microsoft.AspNet.Server.Kestrel.Http 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 @@ namespace Microsoft.AspNet.Server.Kestrel.Http 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 @@ namespace Microsoft.AspNet.Server.Kestrel.Http { 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 @@ namespace Microsoft.AspNet.Server.Kestrel.Http } 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 9c5d690707..c36d88155d 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 @@ namespace Microsoft.AspNet.Server.Kestrel.Http var begin = input.ConsumingStart(); int actual; - var end = begin.CopyTo(buffer.Array, buffer.Offset, buffer.Count, out actual); + var end = begin.CopyTo(buffer, offset, count, out actual); input.ConsumingComplete(end, end); if (actual != 0) diff --git a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs index 7de5c7fb10..ddb12bff7f 100644 --- a/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs +++ b/src/Microsoft.AspNet.Server.Kestrel/Infrastructure/MemoryPoolIterator2.cs @@ -600,18 +600,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Infrastructure if (remaining <= following) { actual = count; - Buffer.BlockCopy(block.Array, index, array, offset, remaining); + if (array != null) + { + Buffer.BlockCopy(block.Array, index, array, offset, remaining); + } return new MemoryPoolIterator2(block, index + remaining); } else if (block.Next == null) { actual = count - remaining + following; - Buffer.BlockCopy(block.Array, index, array, offset, following); + if (array != null) + { + Buffer.BlockCopy(block.Array, index, array, offset, following); + } return new MemoryPoolIterator2(block, index + following); } else { - Buffer.BlockCopy(block.Array, index, array, offset, following); + if (array != null) + { + Buffer.BlockCopy(block.Array, index, array, offset, following); + } offset += following; remaining -= following; block = block.Next;