From 8471fe3ff22e19a622eb7f78b82e729104de412b Mon Sep 17 00:00:00 2001 From: Chris R Date: Fri, 27 Sep 2019 10:12:58 -0700 Subject: [PATCH 1/4] HttpSys GoAway #13356 --- .../HttpSys/samples/SelfHostServer/SelfHostServer.csproj | 7 ++++++- src/Servers/HttpSys/samples/SelfHostServer/Startup.cs | 2 ++ src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs | 8 +++++++- src/Servers/HttpSys/src/RequestProcessing/Response.cs | 5 ++++- src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Servers/HttpSys/samples/SelfHostServer/SelfHostServer.csproj b/src/Servers/HttpSys/samples/SelfHostServer/SelfHostServer.csproj index cf4b7f8a960e..35450964c9ef 100644 --- a/src/Servers/HttpSys/samples/SelfHostServer/SelfHostServer.csproj +++ b/src/Servers/HttpSys/samples/SelfHostServer/SelfHostServer.csproj @@ -1,10 +1,15 @@ - + $(DefaultNetCoreTargetFramework) Exe true + + + + 214124cd-d05b-4309-9af9-9caa44b2b74a + diff --git a/src/Servers/HttpSys/samples/SelfHostServer/Startup.cs b/src/Servers/HttpSys/samples/SelfHostServer/Startup.cs index 52b65bd248c0..42f6d11f81e5 100644 --- a/src/Servers/HttpSys/samples/SelfHostServer/Startup.cs +++ b/src/Servers/HttpSys/samples/SelfHostServer/Startup.cs @@ -37,6 +37,8 @@ public static void Main(string[] args) .UseHttpSys(options => { options.UrlPrefixes.Add("http://localhost:5000"); + // This is a pre-configured IIS express port. See the PackageTags in the csproj. + options.UrlPrefixes.Add("https://localhost:44319"); options.Authentication.Schemes = AuthenticationSchemes.None; options.Authentication.AllowAnonymous = true; }) diff --git a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs index 12d1381baeb7..27a141d1e9f2 100644 --- a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs +++ b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.Extensions.Internal; namespace Microsoft.AspNetCore.Server.HttpSys { @@ -12,11 +11,18 @@ internal static class ComNetOS // Minimum support for Windows 7 is assumed. internal static readonly bool IsWin8orLater; + public static bool SupportsGoAway { get; } + static ComNetOS() { var win8Version = new Version(6, 2); IsWin8orLater = (Environment.OSVersion.Version >= win8Version); + + var win1019H2Version = new Version(10, 0, 18363); + // Win10 1909 (19H2) or later + SupportsGoAway = (Environment.OSVersion.Version >= win1019H2Version); } + } } diff --git a/src/Servers/HttpSys/src/RequestProcessing/Response.cs b/src/Servers/HttpSys/src/RequestProcessing/Response.cs index b31dc4809ef5..f153e0901a64 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/Response.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/Response.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -417,6 +416,10 @@ internal HttpApiTypes.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfReque Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close); } flags = HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; + if (responseCloseSet && requestVersion >= Constants.V2 && ComNetOS.SupportsGoAway) + { + flags |= HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_GOAWAY; + } } Headers.IsReadOnly = true; diff --git a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs index 324426c60dbc..80a06607cbad 100644 --- a/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs +++ b/src/Shared/HttpSys/NativeInterop/HttpApiTypes.cs @@ -602,6 +602,7 @@ internal enum HTTP_FLAGS : uint HTTP_INITIALIZE_SERVER = 0x00000001, HTTP_INITIALIZE_CBT = 0x00000004, HTTP_SEND_RESPONSE_FLAG_OPAQUE = 0x00000040, + HTTP_SEND_RESPONSE_FLAG_GOAWAY = 0x00000100, } [Flags] From eefa8c24b380eaaa4652fb80b34755031dfbc2f0 Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Mon, 30 Sep 2019 14:31:39 -0700 Subject: [PATCH 2/4] Update src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs --- src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs index 27a141d1e9f2..fca3d4b75dfd 100644 --- a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs +++ b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs @@ -11,7 +11,7 @@ internal static class ComNetOS // Minimum support for Windows 7 is assumed. internal static readonly bool IsWin8orLater; - public static bool SupportsGoAway { get; } + internal static bool SupportsGoAway { get; } static ComNetOS() { From 777752eda7bbaa0ec8454bf990e2a521da2eed1c Mon Sep 17 00:00:00 2001 From: Chris R Date: Tue, 1 Oct 2019 10:20:50 -0700 Subject: [PATCH 3/4] Light up rather than version sniff --- .../HttpSys/src/NativeInterop/ComNetOS.cs | 7 ----- .../HttpSys/src/RequestProcessing/Response.cs | 29 ++++++++++++++++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs index fca3d4b75dfd..f2b693c1d150 100644 --- a/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs +++ b/src/Servers/HttpSys/src/NativeInterop/ComNetOS.cs @@ -11,18 +11,11 @@ internal static class ComNetOS // Minimum support for Windows 7 is assumed. internal static readonly bool IsWin8orLater; - internal static bool SupportsGoAway { get; } - static ComNetOS() { var win8Version = new Version(6, 2); IsWin8orLater = (Environment.OSVersion.Version >= win8Version); - - var win1019H2Version = new Version(10, 0, 18363); - // Win10 1909 (19H2) or later - SupportsGoAway = (Environment.OSVersion.Version >= win1019H2Version); } - } } diff --git a/src/Servers/HttpSys/src/RequestProcessing/Response.cs b/src/Servers/HttpSys/src/RequestProcessing/Response.cs index f153e0901a64..af0273b4e278 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/Response.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/Response.cs @@ -17,6 +17,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys { internal sealed class Response { + private static bool? SupportsGoAway; + private ResponseState _responseState; private string _reasonPhrase; private ResponseBody _nativeStream; @@ -313,6 +315,31 @@ internal unsafe uint SendHeaders(HttpApiTypes.HTTP_DATA_CHUNK[] dataChunks, asyncResult == null ? SafeNativeOverlapped.Zero : asyncResult.NativeOverlapped, IntPtr.Zero); + // GoAway is only supported on later versions. Retry. + if (statusCode == ErrorCodes.ERROR_INVALID_PARAMETER + && (flags & HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_GOAWAY) != 0) + { + flags &= ~HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_GOAWAY; + statusCode = + HttpApi.HttpSendHttpResponse( + RequestContext.Server.RequestQueue.Handle, + Request.RequestId, + (uint)flags, + pResponse, + &cachePolicy, + &bytesSent, + IntPtr.Zero, + 0, + asyncResult == null ? SafeNativeOverlapped.Zero : asyncResult.NativeOverlapped, + IntPtr.Zero); + + // Succeeded without GoAway, disable them. + if (statusCode != ErrorCodes.ERROR_INVALID_PARAMETER) + { + SupportsGoAway = false; + } + } + if (asyncResult != null && statusCode == ErrorCodes.ERROR_SUCCESS && HttpSysListener.SkipIOCPCallbackOnSuccess) @@ -416,7 +443,7 @@ internal HttpApiTypes.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfReque Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close); } flags = HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; - if (responseCloseSet && requestVersion >= Constants.V2 && ComNetOS.SupportsGoAway) + if (responseCloseSet && requestVersion >= Constants.V2 && SupportsGoAway != false) { flags |= HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_GOAWAY; } From acd518107cc8a357cb82329e59daeab44b4d3611 Mon Sep 17 00:00:00 2001 From: Chris R Date: Tue, 1 Oct 2019 12:02:42 -0700 Subject: [PATCH 4/4] Use a bool --- src/Servers/HttpSys/src/RequestProcessing/Response.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Servers/HttpSys/src/RequestProcessing/Response.cs b/src/Servers/HttpSys/src/RequestProcessing/Response.cs index af0273b4e278..5f29763d2ff5 100644 --- a/src/Servers/HttpSys/src/RequestProcessing/Response.cs +++ b/src/Servers/HttpSys/src/RequestProcessing/Response.cs @@ -17,7 +17,8 @@ namespace Microsoft.AspNetCore.Server.HttpSys { internal sealed class Response { - private static bool? SupportsGoAway; + // Support is assumed until we get an error and turn it off. + private static bool SupportsGoAway = true; private ResponseState _responseState; private string _reasonPhrase; @@ -443,7 +444,7 @@ internal HttpApiTypes.HTTP_FLAGS ComputeHeaders(long writeCount, bool endOfReque Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close); } flags = HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT; - if (responseCloseSet && requestVersion >= Constants.V2 && SupportsGoAway != false) + if (responseCloseSet && requestVersion >= Constants.V2 && SupportsGoAway) { flags |= HttpApiTypes.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_GOAWAY; }