From f0e572075bec9d4866ed27c8b524c62eaa9470c8 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Mon, 17 Jul 2017 14:57:26 -0700 Subject: [PATCH] Fix FlushAsync when a ConnectionAdapter is configured (#1957) * Also remove async void everywhere --- .../Adapter/Internal/RawStream.cs | 12 +++---- .../Internal/ListenerSecondary.cs | 4 +-- .../SocketConnection.cs | 2 +- .../SocketTransport.cs | 2 +- .../ConnectionAdapterTests.cs | 34 +++++++++++++++++++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Adapter/Internal/RawStream.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Adapter/Internal/RawStream.cs index cec2ba1e75..7b4ffc3340 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Core/Adapter/Internal/RawStream.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Core/Adapter/Internal/RawStream.cs @@ -75,17 +75,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken token) { - ArraySegment segment; + var output = _output.Alloc(); + if (buffer != null) { - segment = new ArraySegment(buffer, offset, count); + output.Write(new ArraySegment(buffer, offset, count)); } - else - { - segment = default(ArraySegment); - } - var output = _output.Alloc(); - output.Write(segment); + await output.FlushAsync(token); } diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/Internal/ListenerSecondary.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/Internal/ListenerSecondary.cs index 83a4c5f76c..59615c3121 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/Internal/ListenerSecondary.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/Internal/ListenerSecondary.cs @@ -81,10 +81,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Internal private static void ConnectCallback(UvConnectRequest connect, int status, UvException error, TaskCompletionSource tcs) { var listener = (ListenerSecondary)tcs.Task.AsyncState; - listener.ConnectedCallback(connect, status, error, tcs); + _ = listener.ConnectedCallback(connect, status, error, tcs); } - private async void ConnectedCallback(UvConnectRequest connect, int status, UvException error, TaskCompletionSource tcs) + private async Task ConnectedCallback(UvConnectRequest connect, int status, UvException error, TaskCompletionSource tcs) { connect.Dispose(); if (error != null) diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketConnection.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketConnection.cs index 2f5dfe96b7..5a3f64d17b 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketConnection.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketConnection.cs @@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets _remoteEndPoint = (IPEndPoint)_socket.RemoteEndPoint; } - public async void Start(IConnectionHandler connectionHandler) + public async Task StartAsync(IConnectionHandler connectionHandler) { try { diff --git a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketTransport.cs b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketTransport.cs index aed59a4def..fd6d3b57da 100644 --- a/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketTransport.cs +++ b/src/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/SocketTransport.cs @@ -105,7 +105,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets acceptSocket.NoDelay = _endPointInformation.NoDelay; var connection = new SocketConnection(acceptSocket, this); - connection.Start(_handler); + _ = connection.StartAsync(_handler); } } catch (Exception) diff --git a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ConnectionAdapterTests.cs b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ConnectionAdapterTests.cs index 7c85fe99c5..21e175d8e0 100644 --- a/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ConnectionAdapterTests.cs +++ b/test/Microsoft.AspNetCore.Server.Kestrel.FunctionalTests/ConnectionAdapterTests.cs @@ -7,6 +7,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.AspNetCore.Server.Kestrel.Core.Adapter.Internal; using Microsoft.AspNetCore.Testing; @@ -172,6 +173,39 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests } } + [Fact] + public async Task CanFlushAsyncWithConnectionAdapter() + { + var listenOptions = new ListenOptions(new IPEndPoint(IPAddress.Loopback, 0)) + { + ConnectionAdapters = { new PassThroughConnectionAdapter() } + }; + + var serviceContext = new TestServiceContext(); + + using (var server = new TestServer(async context => + { + await context.Response.WriteAsync("Hello "); + await context.Response.Body.FlushAsync(); + await context.Response.WriteAsync("World!"); + }, serviceContext, listenOptions)) + { + using (var connection = server.CreateConnection()) + { + await connection.Send( + "GET / HTTP/1.0", + "", + ""); + await connection.ReceiveEnd( + "HTTP/1.1 200 OK", + "Connection: close", + $"Date: {serviceContext.DateHeaderValue}", + "", + "Hello World!"); + } + } + } + private class RewritingConnectionAdapter : IConnectionAdapter { private RewritingStream _rewritingStream;