From d3be96138b98421222302d9603bd95f7dd64392e Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 00:32:07 +0000 Subject: [PATCH 1/9] Use strongly typed features --- .../Core/src/Internal/Http/Http1Connection.cs | 5 +- .../Http/HttpProtocol.FeatureCollection.cs | 19 -- .../Internal/Http/HttpProtocol.Generated.cs | 169 +++++++++--------- .../Core/src/Internal/Http2/Http2Stream.cs | 6 +- .../Core/src/Internal/Http3/Http3Stream.cs | 5 +- .../shared/TransportConnection.Generated.cs | 30 ++-- ...ransportMultiplexedConnection.Generated.cs | 32 ++-- .../FeatureCollectionGenerator.cs | 10 +- .../HttpProtocolFeatureCollection.cs | 9 +- .../TransportConnectionFeatureCollection.cs | 3 + ...tMultiplexedConnectionFeatureCollection.cs | 16 +- 11 files changed, 157 insertions(+), 147 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs index 88c35d5f670e..e5978de39b07 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/Http1Connection.cs @@ -616,7 +616,6 @@ private void ValidateNonOriginHostHeader(string hostText) protected override void OnReset() { - ResetHttp1Features(); _requestTimedOut = false; _requestTargetForm = HttpRequestTarget.Unknown; @@ -625,6 +624,10 @@ protected override void OnReset() _requestCount++; MinResponseDataRate = ServerOptions.Limits.MinResponseDataRate; + + // Reset Http1 Features + _currentIHttpMinRequestBodyDataRateFeature = this; + _currentIHttpMinResponseDataRateFeature = this; } protected override void OnRequestProcessingEnding() diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs index 71e9ed2047a6..ebc12784d6e4 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs @@ -255,25 +255,6 @@ RouteValueDictionary IRouteValuesFeature.RouteValues Stream IHttpResponseBodyFeature.Stream => ResponseBody; - protected void ResetHttp1Features() - { - _currentIHttpMinRequestBodyDataRateFeature = this; - _currentIHttpMinResponseDataRateFeature = this; - } - - protected void ResetHttp2Features() - { - _currentIHttp2StreamIdFeature = this; - _currentIHttpResponseTrailersFeature = this; - _currentIHttpResetFeature = this; - } - - protected void ResetHttp3Features() - { - _currentIHttpResponseTrailersFeature = this; - _currentIHttpResetFeature = this; - } - void IHttpResponseFeature.OnStarting(Func callback, object state) { OnStarting(callback, state); diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index f6420cc0c955..fb830859082c 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -15,34 +15,34 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { internal partial class HttpProtocol : IFeatureCollection { - private object? _currentIHttpRequestFeature; - private object? _currentIHttpRequestBodyDetectionFeature; - private object? _currentIHttpResponseFeature; - private object? _currentIHttpResponseBodyFeature; - private object? _currentIRequestBodyPipeFeature; - private object? _currentIHttpRequestIdentifierFeature; - private object? _currentIServiceProvidersFeature; - private object? _currentIHttpRequestLifetimeFeature; - private object? _currentIHttpConnectionFeature; - private object? _currentIRouteValuesFeature; - private object? _currentIEndpointFeature; - private object? _currentIHttpAuthenticationFeature; - private object? _currentIHttpRequestTrailersFeature; - private object? _currentIQueryFeature; - private object? _currentIFormFeature; - private object? _currentIHttpUpgradeFeature; - private object? _currentIHttp2StreamIdFeature; - private object? _currentIHttpResponseTrailersFeature; - private object? _currentIResponseCookiesFeature; - private object? _currentIItemsFeature; - private object? _currentITlsConnectionFeature; - private object? _currentIHttpWebSocketFeature; - private object? _currentISessionFeature; - private object? _currentIHttpMaxRequestBodySizeFeature; - private object? _currentIHttpMinRequestBodyDataRateFeature; - private object? _currentIHttpMinResponseDataRateFeature; - private object? _currentIHttpBodyControlFeature; - private object? _currentIHttpResetFeature; + internal protected IHttpRequestFeature? _currentIHttpRequestFeature; + internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; + internal protected IHttpResponseFeature? _currentIHttpResponseFeature; + internal protected IHttpResponseBodyFeature? _currentIHttpResponseBodyFeature; + internal protected IRequestBodyPipeFeature? _currentIRequestBodyPipeFeature; + internal protected IHttpRequestIdentifierFeature? _currentIHttpRequestIdentifierFeature; + internal protected IServiceProvidersFeature? _currentIServiceProvidersFeature; + internal protected IHttpRequestLifetimeFeature? _currentIHttpRequestLifetimeFeature; + internal protected IHttpConnectionFeature? _currentIHttpConnectionFeature; + internal protected IRouteValuesFeature? _currentIRouteValuesFeature; + internal protected IEndpointFeature? _currentIEndpointFeature; + internal protected IHttpAuthenticationFeature? _currentIHttpAuthenticationFeature; + internal protected IHttpRequestTrailersFeature? _currentIHttpRequestTrailersFeature; + internal protected IQueryFeature? _currentIQueryFeature; + internal protected IFormFeature? _currentIFormFeature; + internal protected IHttpUpgradeFeature? _currentIHttpUpgradeFeature; + internal protected IHttp2StreamIdFeature? _currentIHttp2StreamIdFeature; + internal protected IHttpResponseTrailersFeature? _currentIHttpResponseTrailersFeature; + internal protected IResponseCookiesFeature? _currentIResponseCookiesFeature; + internal protected IItemsFeature? _currentIItemsFeature; + internal protected ITlsConnectionFeature? _currentITlsConnectionFeature; + internal protected IHttpWebSocketFeature? _currentIHttpWebSocketFeature; + internal protected ISessionFeature? _currentISessionFeature; + internal protected IHttpMaxRequestBodySizeFeature? _currentIHttpMaxRequestBodySizeFeature; + internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; + internal protected IHttpMinResponseDataRateFeature? _currentIHttpMinResponseDataRateFeature; + internal protected IHttpBodyControlFeature? _currentIHttpBodyControlFeature; + internal protected IHttpResetFeature? _currentIHttpResetFeature; private int _featureRevision; @@ -61,7 +61,6 @@ private void FastReset() _currentIHttpRequestTrailersFeature = this; _currentIHttpConnectionFeature = this; _currentIHttpMaxRequestBodySizeFeature = this; - _currentIHttpMinRequestBodyDataRateFeature = this; _currentIHttpBodyControlFeature = this; _currentIRouteValuesFeature = this; _currentIEndpointFeature = this; @@ -276,115 +275,115 @@ private void ExtraFeatureSet(Type key, object? value) if (key == typeof(IHttpRequestFeature)) { - _currentIHttpRequestFeature = value; + _currentIHttpRequestFeature = (IHttpRequestFeature?)value; } else if (key == typeof(IHttpRequestBodyDetectionFeature)) { - _currentIHttpRequestBodyDetectionFeature = value; + _currentIHttpRequestBodyDetectionFeature = (IHttpRequestBodyDetectionFeature?)value; } else if (key == typeof(IHttpResponseFeature)) { - _currentIHttpResponseFeature = value; + _currentIHttpResponseFeature = (IHttpResponseFeature?)value; } else if (key == typeof(IHttpResponseBodyFeature)) { - _currentIHttpResponseBodyFeature = value; + _currentIHttpResponseBodyFeature = (IHttpResponseBodyFeature?)value; } else if (key == typeof(IRequestBodyPipeFeature)) { - _currentIRequestBodyPipeFeature = value; + _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)value; } else if (key == typeof(IHttpRequestIdentifierFeature)) { - _currentIHttpRequestIdentifierFeature = value; + _currentIHttpRequestIdentifierFeature = (IHttpRequestIdentifierFeature?)value; } else if (key == typeof(IServiceProvidersFeature)) { - _currentIServiceProvidersFeature = value; + _currentIServiceProvidersFeature = (IServiceProvidersFeature?)value; } else if (key == typeof(IHttpRequestLifetimeFeature)) { - _currentIHttpRequestLifetimeFeature = value; + _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)value; } else if (key == typeof(IHttpConnectionFeature)) { - _currentIHttpConnectionFeature = value; + _currentIHttpConnectionFeature = (IHttpConnectionFeature?)value; } else if (key == typeof(IRouteValuesFeature)) { - _currentIRouteValuesFeature = value; + _currentIRouteValuesFeature = (IRouteValuesFeature?)value; } else if (key == typeof(IEndpointFeature)) { - _currentIEndpointFeature = value; + _currentIEndpointFeature = (IEndpointFeature?)value; } else if (key == typeof(IHttpAuthenticationFeature)) { - _currentIHttpAuthenticationFeature = value; + _currentIHttpAuthenticationFeature = (IHttpAuthenticationFeature?)value; } else if (key == typeof(IHttpRequestTrailersFeature)) { - _currentIHttpRequestTrailersFeature = value; + _currentIHttpRequestTrailersFeature = (IHttpRequestTrailersFeature?)value; } else if (key == typeof(IQueryFeature)) { - _currentIQueryFeature = value; + _currentIQueryFeature = (IQueryFeature?)value; } else if (key == typeof(IFormFeature)) { - _currentIFormFeature = value; + _currentIFormFeature = (IFormFeature?)value; } else if (key == typeof(IHttpUpgradeFeature)) { - _currentIHttpUpgradeFeature = value; + _currentIHttpUpgradeFeature = (IHttpUpgradeFeature?)value; } else if (key == typeof(IHttp2StreamIdFeature)) { - _currentIHttp2StreamIdFeature = value; + _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)value; } else if (key == typeof(IHttpResponseTrailersFeature)) { - _currentIHttpResponseTrailersFeature = value; + _currentIHttpResponseTrailersFeature = (IHttpResponseTrailersFeature?)value; } else if (key == typeof(IResponseCookiesFeature)) { - _currentIResponseCookiesFeature = value; + _currentIResponseCookiesFeature = (IResponseCookiesFeature?)value; } else if (key == typeof(IItemsFeature)) { - _currentIItemsFeature = value; + _currentIItemsFeature = (IItemsFeature?)value; } else if (key == typeof(ITlsConnectionFeature)) { - _currentITlsConnectionFeature = value; + _currentITlsConnectionFeature = (ITlsConnectionFeature?)value; } else if (key == typeof(IHttpWebSocketFeature)) { - _currentIHttpWebSocketFeature = value; + _currentIHttpWebSocketFeature = (IHttpWebSocketFeature?)value; } else if (key == typeof(ISessionFeature)) { - _currentISessionFeature = value; + _currentISessionFeature = (ISessionFeature?)value; } else if (key == typeof(IHttpMaxRequestBodySizeFeature)) { - _currentIHttpMaxRequestBodySizeFeature = value; + _currentIHttpMaxRequestBodySizeFeature = (IHttpMaxRequestBodySizeFeature?)value; } else if (key == typeof(IHttpMinRequestBodyDataRateFeature)) { - _currentIHttpMinRequestBodyDataRateFeature = value; + _currentIHttpMinRequestBodyDataRateFeature = (IHttpMinRequestBodyDataRateFeature?)value; } else if (key == typeof(IHttpMinResponseDataRateFeature)) { - _currentIHttpMinResponseDataRateFeature = value; + _currentIHttpMinResponseDataRateFeature = (IHttpMinResponseDataRateFeature?)value; } else if (key == typeof(IHttpBodyControlFeature)) { - _currentIHttpBodyControlFeature = value; + _currentIHttpBodyControlFeature = (IHttpBodyControlFeature?)value; } else if (key == typeof(IHttpResetFeature)) { - _currentIHttpResetFeature = value; + _currentIHttpResetFeature = (IHttpResetFeature?)value; } else { @@ -526,115 +525,115 @@ private void ExtraFeatureSet(Type key, object? value) _featureRevision++; if (typeof(TFeature) == typeof(IHttpRequestFeature)) { - _currentIHttpRequestFeature = feature; + _currentIHttpRequestFeature = (IHttpRequestFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) { - _currentIHttpRequestBodyDetectionFeature = feature; + _currentIHttpRequestBodyDetectionFeature = (IHttpRequestBodyDetectionFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpResponseFeature)) { - _currentIHttpResponseFeature = feature; + _currentIHttpResponseFeature = (IHttpResponseFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpResponseBodyFeature)) { - _currentIHttpResponseBodyFeature = feature; + _currentIHttpResponseBodyFeature = (IHttpResponseBodyFeature?)feature; } else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) { - _currentIRequestBodyPipeFeature = feature; + _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) { - _currentIHttpRequestIdentifierFeature = feature; + _currentIHttpRequestIdentifierFeature = (IHttpRequestIdentifierFeature?)feature; } else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) { - _currentIServiceProvidersFeature = feature; + _currentIServiceProvidersFeature = (IServiceProvidersFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) { - _currentIHttpRequestLifetimeFeature = feature; + _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) { - _currentIHttpConnectionFeature = feature; + _currentIHttpConnectionFeature = (IHttpConnectionFeature?)feature; } else if (typeof(TFeature) == typeof(IRouteValuesFeature)) { - _currentIRouteValuesFeature = feature; + _currentIRouteValuesFeature = (IRouteValuesFeature?)feature; } else if (typeof(TFeature) == typeof(IEndpointFeature)) { - _currentIEndpointFeature = feature; + _currentIEndpointFeature = (IEndpointFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) { - _currentIHttpAuthenticationFeature = feature; + _currentIHttpAuthenticationFeature = (IHttpAuthenticationFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) { - _currentIHttpRequestTrailersFeature = feature; + _currentIHttpRequestTrailersFeature = (IHttpRequestTrailersFeature?)feature; } else if (typeof(TFeature) == typeof(IQueryFeature)) { - _currentIQueryFeature = feature; + _currentIQueryFeature = (IQueryFeature?)feature; } else if (typeof(TFeature) == typeof(IFormFeature)) { - _currentIFormFeature = feature; + _currentIFormFeature = (IFormFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) { - _currentIHttpUpgradeFeature = feature; + _currentIHttpUpgradeFeature = (IHttpUpgradeFeature?)feature; } else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) { - _currentIHttp2StreamIdFeature = feature; + _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) { - _currentIHttpResponseTrailersFeature = feature; + _currentIHttpResponseTrailersFeature = (IHttpResponseTrailersFeature?)feature; } else if (typeof(TFeature) == typeof(IResponseCookiesFeature)) { - _currentIResponseCookiesFeature = feature; + _currentIResponseCookiesFeature = (IResponseCookiesFeature?)feature; } else if (typeof(TFeature) == typeof(IItemsFeature)) { - _currentIItemsFeature = feature; + _currentIItemsFeature = (IItemsFeature?)feature; } else if (typeof(TFeature) == typeof(ITlsConnectionFeature)) { - _currentITlsConnectionFeature = feature; + _currentITlsConnectionFeature = (ITlsConnectionFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpWebSocketFeature)) { - _currentIHttpWebSocketFeature = feature; + _currentIHttpWebSocketFeature = (IHttpWebSocketFeature?)feature; } else if (typeof(TFeature) == typeof(ISessionFeature)) { - _currentISessionFeature = feature; + _currentISessionFeature = (ISessionFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature)) { - _currentIHttpMaxRequestBodySizeFeature = feature; + _currentIHttpMaxRequestBodySizeFeature = (IHttpMaxRequestBodySizeFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpMinRequestBodyDataRateFeature)) { - _currentIHttpMinRequestBodyDataRateFeature = feature; + _currentIHttpMinRequestBodyDataRateFeature = (IHttpMinRequestBodyDataRateFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpMinResponseDataRateFeature)) { - _currentIHttpMinResponseDataRateFeature = feature; + _currentIHttpMinResponseDataRateFeature = (IHttpMinResponseDataRateFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpBodyControlFeature)) { - _currentIHttpBodyControlFeature = feature; + _currentIHttpBodyControlFeature = (IHttpBodyControlFeature?)feature; } else if (typeof(TFeature) == typeof(IHttpResetFeature)) { - _currentIHttpResetFeature = feature; + _currentIHttpResetFeature = (IHttpResetFeature?)feature; } else { diff --git a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs index c8507f9e4bb7..28dc06ff310a 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Stream.cs @@ -114,7 +114,11 @@ protected override void OnReset() _keepAlive = true; _connectionAborted = false; - ResetHttp2Features(); + // Reset Http2 Features + _currentIHttpMinRequestBodyDataRateFeature = this; + _currentIHttp2StreamIdFeature = this; + _currentIHttpResponseTrailersFeature = this; + _currentIHttpResetFeature = this; } protected override void OnRequestProcessingEnded() diff --git a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs index fa269864302c..2911ef0b1d19 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http3/Http3Stream.cs @@ -577,7 +577,10 @@ public void Tick(DateTimeOffset now) protected override void OnReset() { - ResetHttp3Features(); + // Reset Http3 Features + _currentIHttpMinRequestBodyDataRateFeature = this; + _currentIHttpResponseTrailersFeature = this; + _currentIHttpResetFeature = this; } protected override void ApplicationAbort() => ApplicationAbort(new ConnectionAbortedException(CoreStrings.ConnectionAbortedByApplication), Http3ErrorCode.InternalError); diff --git a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs index b35954bb6fa2..c53e20b5184b 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs @@ -14,11 +14,11 @@ namespace Microsoft.AspNetCore.Connections { internal partial class TransportConnection : IFeatureCollection { - private object? _currentIConnectionIdFeature; - private object? _currentIConnectionTransportFeature; - private object? _currentIConnectionItemsFeature; - private object? _currentIMemoryPoolFeature; - private object? _currentIConnectionLifetimeFeature; + internal protected IConnectionIdFeature? _currentIConnectionIdFeature; + internal protected IConnectionTransportFeature? _currentIConnectionTransportFeature; + internal protected IConnectionItemsFeature? _currentIConnectionItemsFeature; + internal protected IMemoryPoolFeature? _currentIMemoryPoolFeature; + internal protected IConnectionLifetimeFeature? _currentIConnectionLifetimeFeature; private int _featureRevision; @@ -137,23 +137,23 @@ private void ExtraFeatureSet(Type key, object? value) if (key == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = value; + _currentIConnectionIdFeature = (IConnectionIdFeature?)value; } else if (key == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = value; + _currentIConnectionTransportFeature = (IConnectionTransportFeature?)value; } else if (key == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = value; + _currentIConnectionItemsFeature = (IConnectionItemsFeature?)value; } else if (key == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = value; + _currentIMemoryPoolFeature = (IMemoryPoolFeature?)value; } else if (key == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = value; + _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)value; } else { @@ -198,23 +198,23 @@ private void ExtraFeatureSet(Type key, object? value) _featureRevision++; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = feature; + _currentIConnectionIdFeature = (IConnectionIdFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = feature; + _currentIConnectionTransportFeature = (IConnectionTransportFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = feature; + _currentIConnectionItemsFeature = (IConnectionItemsFeature?)feature; } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = feature; + _currentIMemoryPoolFeature = (IMemoryPoolFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = feature; + _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)feature; } else { diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs index cdfc0bff16c3..586ec1a0b5ea 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs @@ -14,11 +14,11 @@ namespace Microsoft.AspNetCore.Connections { internal partial class TransportMultiplexedConnection : IFeatureCollection { - private object? _currentIConnectionIdFeature; - private object? _currentIConnectionTransportFeature; - private object? _currentIConnectionItemsFeature; - private object? _currentIMemoryPoolFeature; - private object? _currentIConnectionLifetimeFeature; + internal protected IConnectionIdFeature? _currentIConnectionIdFeature; + internal protected IConnectionTransportFeature? _currentIConnectionTransportFeature; + internal protected IConnectionItemsFeature? _currentIConnectionItemsFeature; + internal protected IMemoryPoolFeature? _currentIMemoryPoolFeature; + internal protected IConnectionLifetimeFeature? _currentIConnectionLifetimeFeature; private int _featureRevision; @@ -27,11 +27,11 @@ internal partial class TransportMultiplexedConnection : IFeatureCollection private void FastReset() { _currentIConnectionIdFeature = this; - _currentIConnectionTransportFeature = this; _currentIConnectionItemsFeature = this; _currentIMemoryPoolFeature = this; _currentIConnectionLifetimeFeature = this; + _currentIConnectionTransportFeature = null; } // Internal for testing @@ -137,23 +137,23 @@ private void ExtraFeatureSet(Type key, object? value) if (key == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = value; + _currentIConnectionIdFeature = (IConnectionIdFeature?)value; } else if (key == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = value; + _currentIConnectionTransportFeature = (IConnectionTransportFeature?)value; } else if (key == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = value; + _currentIConnectionItemsFeature = (IConnectionItemsFeature?)value; } else if (key == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = value; + _currentIMemoryPoolFeature = (IMemoryPoolFeature?)value; } else if (key == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = value; + _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)value; } else { @@ -198,23 +198,23 @@ private void ExtraFeatureSet(Type key, object? value) _featureRevision++; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = feature; + _currentIConnectionIdFeature = (IConnectionIdFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = feature; + _currentIConnectionTransportFeature = (IConnectionTransportFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = feature; + _currentIConnectionItemsFeature = (IConnectionItemsFeature?)feature; } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = feature; + _currentIMemoryPoolFeature = (IMemoryPoolFeature?)feature; } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = feature; + _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)feature; } else { diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index 3f75cd4e21e6..a95ff2f769e2 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -9,7 +9,7 @@ namespace CodeGenerator { public static class FeatureCollectionGenerator { - public static string GenerateFile(string namespaceName, string className, string[] allFeatures, string[] implementedFeatures, string extraUsings, string fallbackFeatures) + public static string GenerateFile(string namespaceName, string className, string[] allFeatures, string[] implementedFeatures, string[] skipResetFeatures, string extraUsings, string fallbackFeatures) { // NOTE: This list MUST always match the set of feature interfaces implemented by TransportConnection. // See also: src/Kestrel/Http/TransportConnection.FeatureCollection.cs @@ -33,14 +33,14 @@ namespace {namespaceName} {{ internal partial class {className} : IFeatureCollection {{{Each(features, feature => $@" - private object? _current{feature.Name};")} + internal protected {feature.Name}? _current{feature.Name};")} private int _featureRevision; private List>? MaybeExtra; private void FastReset() - {{{Each(implementedFeatures, feature => $@" + {{{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@" _current{feature} = this;")} {Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" _current{feature} = null;")} @@ -133,7 +133,7 @@ private void ExtraFeatureSet(Type key, object? value) {Each(features, feature => $@" {(feature.Index != 0 ? "else " : "")}if (key == typeof({feature.Name})) {{ - _current{feature.Name} = value; + _current{feature.Name} = ({feature.Name}?)value; }}")} else {{ @@ -167,7 +167,7 @@ private void ExtraFeatureSet(Type key, object? value) _featureRevision++;{Each(features, feature => $@" {(feature.Index != 0 ? "else " : "")}if (typeof(TFeature) == typeof({feature.Name})) {{ - _current{feature.Name} = feature; + _current{feature.Name} = ({feature.Name}?)feature; }}")} else {{ diff --git a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs index 7c8dc1bce725..ea312cce0688 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs @@ -74,7 +74,13 @@ public static string GenerateFile() "IRouteValuesFeature", "IEndpointFeature" }; - + + // NOTE: Each item in this list MUST always be reset by each protocol in their OnReset() method + var skipResetFeatures = new[] + { + "IHttpMinRequestBodyDataRateFeature" + }; + var usings = $@" using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features.Authentication; @@ -85,6 +91,7 @@ public static string GenerateFile() className: "HttpProtocol", allFeatures: allFeatures, implementedFeatures: implementedFeatures, + skipResetFeatures: skipResetFeatures, extraUsings: usings, fallbackFeatures: "ConnectionFeatures"); } diff --git a/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs index fdc759e7f31f..780ad7e2779a 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs @@ -1,6 +1,8 @@ // 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; + namespace CodeGenerator { public class TransportConnectionFeatureCollection @@ -27,6 +29,7 @@ public static string GenerateFile() className: "TransportConnection", allFeatures: features, implementedFeatures: features, + skipResetFeatures: Array.Empty(), extraUsings: usings, fallbackFeatures: null); } diff --git a/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs index 8c0ad9d3ff99..8ff51ad61566 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs @@ -1,6 +1,8 @@ // 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; + namespace CodeGenerator { public class TransportMultiplexedConnectionFeatureCollection @@ -9,7 +11,7 @@ public static string GenerateFile() { // NOTE: This list MUST always match the set of feature interfaces implemented by TransportConnectionBase. // See also: shared/TransportConnectionBase.FeatureCollection.cs - var features = new[] + var allFeatures = new[] { "IConnectionIdFeature", "IConnectionTransportFeature", @@ -17,6 +19,13 @@ public static string GenerateFile() "IMemoryPoolFeature", "IConnectionLifetimeFeature" }; + var implementedFeatures = new[] + { + "IConnectionIdFeature", + "IConnectionItemsFeature", + "IMemoryPoolFeature", + "IConnectionLifetimeFeature" + }; var usings = $@" using Microsoft.AspNetCore.Connections.Features; @@ -25,8 +34,9 @@ public static string GenerateFile() return FeatureCollectionGenerator.GenerateFile( namespaceName: "Microsoft.AspNetCore.Connections", className: "TransportMultiplexedConnection", - allFeatures: features, - implementedFeatures: features, + allFeatures: allFeatures, + implementedFeatures: implementedFeatures, + skipResetFeatures: Array.Empty(), extraUsings: usings, fallbackFeatures: null); } From d000e05c6a6ada622430e31ecf3296eda6a77a5b Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 05:11:17 +0100 Subject: [PATCH 2/9] Use Unsafe.As to workaround dotnet/runtime#49614 --- .../Internal/Http/HttpProtocol.Generated.cs | 61 ++++++++++--------- .../shared/TransportConnection.Generated.cs | 15 +++-- ...ransportMultiplexedConnection.Generated.cs | 15 +++-- .../FeatureCollectionGenerator.cs | 7 ++- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index fb830859082c..b691227431fc 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features.Authentication; @@ -394,118 +395,122 @@ private void ExtraFeatureSet(Type key, object? value) TFeature? IFeatureCollection.Get() where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + TFeature? feature = default; if (typeof(TFeature) == typeof(IHttpRequestFeature)) { - feature = (TFeature?)_currentIHttpRequestFeature; + feature = Unsafe.As(ref _currentIHttpRequestFeature); } else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) { - feature = (TFeature?)_currentIHttpRequestBodyDetectionFeature; + feature = Unsafe.As(ref _currentIHttpRequestBodyDetectionFeature); } else if (typeof(TFeature) == typeof(IHttpResponseFeature)) { - feature = (TFeature?)_currentIHttpResponseFeature; + feature = Unsafe.As(ref _currentIHttpResponseFeature); } else if (typeof(TFeature) == typeof(IHttpResponseBodyFeature)) { - feature = (TFeature?)_currentIHttpResponseBodyFeature; + feature = Unsafe.As(ref _currentIHttpResponseBodyFeature); } else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) { - feature = (TFeature?)_currentIRequestBodyPipeFeature; + feature = Unsafe.As(ref _currentIRequestBodyPipeFeature); } else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) { - feature = (TFeature?)_currentIHttpRequestIdentifierFeature; + feature = Unsafe.As(ref _currentIHttpRequestIdentifierFeature); } else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) { - feature = (TFeature?)_currentIServiceProvidersFeature; + feature = Unsafe.As(ref _currentIServiceProvidersFeature); } else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) { - feature = (TFeature?)_currentIHttpRequestLifetimeFeature; + feature = Unsafe.As(ref _currentIHttpRequestLifetimeFeature); } else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) { - feature = (TFeature?)_currentIHttpConnectionFeature; + feature = Unsafe.As(ref _currentIHttpConnectionFeature); } else if (typeof(TFeature) == typeof(IRouteValuesFeature)) { - feature = (TFeature?)_currentIRouteValuesFeature; + feature = Unsafe.As(ref _currentIRouteValuesFeature); } else if (typeof(TFeature) == typeof(IEndpointFeature)) { - feature = (TFeature?)_currentIEndpointFeature; + feature = Unsafe.As(ref _currentIEndpointFeature); } else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) { - feature = (TFeature?)_currentIHttpAuthenticationFeature; + feature = Unsafe.As(ref _currentIHttpAuthenticationFeature); } else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) { - feature = (TFeature?)_currentIHttpRequestTrailersFeature; + feature = Unsafe.As(ref _currentIHttpRequestTrailersFeature); } else if (typeof(TFeature) == typeof(IQueryFeature)) { - feature = (TFeature?)_currentIQueryFeature; + feature = Unsafe.As(ref _currentIQueryFeature); } else if (typeof(TFeature) == typeof(IFormFeature)) { - feature = (TFeature?)_currentIFormFeature; + feature = Unsafe.As(ref _currentIFormFeature); } else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) { - feature = (TFeature?)_currentIHttpUpgradeFeature; + feature = Unsafe.As(ref _currentIHttpUpgradeFeature); } else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) { - feature = (TFeature?)_currentIHttp2StreamIdFeature; + feature = Unsafe.As(ref _currentIHttp2StreamIdFeature); } else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) { - feature = (TFeature?)_currentIHttpResponseTrailersFeature; + feature = Unsafe.As(ref _currentIHttpResponseTrailersFeature); } else if (typeof(TFeature) == typeof(IResponseCookiesFeature)) { - feature = (TFeature?)_currentIResponseCookiesFeature; + feature = Unsafe.As(ref _currentIResponseCookiesFeature); } else if (typeof(TFeature) == typeof(IItemsFeature)) { - feature = (TFeature?)_currentIItemsFeature; + feature = Unsafe.As(ref _currentIItemsFeature); } else if (typeof(TFeature) == typeof(ITlsConnectionFeature)) { - feature = (TFeature?)_currentITlsConnectionFeature; + feature = Unsafe.As(ref _currentITlsConnectionFeature); } else if (typeof(TFeature) == typeof(IHttpWebSocketFeature)) { - feature = (TFeature?)_currentIHttpWebSocketFeature; + feature = Unsafe.As(ref _currentIHttpWebSocketFeature); } else if (typeof(TFeature) == typeof(ISessionFeature)) { - feature = (TFeature?)_currentISessionFeature; + feature = Unsafe.As(ref _currentISessionFeature); } else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature)) { - feature = (TFeature?)_currentIHttpMaxRequestBodySizeFeature; + feature = Unsafe.As(ref _currentIHttpMaxRequestBodySizeFeature); } else if (typeof(TFeature) == typeof(IHttpMinRequestBodyDataRateFeature)) { - feature = (TFeature?)_currentIHttpMinRequestBodyDataRateFeature; + feature = Unsafe.As(ref _currentIHttpMinRequestBodyDataRateFeature); } else if (typeof(TFeature) == typeof(IHttpMinResponseDataRateFeature)) { - feature = (TFeature?)_currentIHttpMinResponseDataRateFeature; + feature = Unsafe.As(ref _currentIHttpMinResponseDataRateFeature); } else if (typeof(TFeature) == typeof(IHttpBodyControlFeature)) { - feature = (TFeature?)_currentIHttpBodyControlFeature; + feature = Unsafe.As(ref _currentIHttpBodyControlFeature); } else if (typeof(TFeature) == typeof(IHttpResetFeature)) { - feature = (TFeature?)_currentIHttpResetFeature; + feature = Unsafe.As(ref _currentIHttpResetFeature); } else if (MaybeExtra != null) { diff --git a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs index c53e20b5184b..c3e852715323 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Http.Features; @@ -164,26 +165,30 @@ private void ExtraFeatureSet(Type key, object? value) TFeature? IFeatureCollection.Get() where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + TFeature? feature = default; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - feature = (TFeature?)_currentIConnectionIdFeature; + feature = Unsafe.As(ref _currentIConnectionIdFeature); } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - feature = (TFeature?)_currentIConnectionTransportFeature; + feature = Unsafe.As(ref _currentIConnectionTransportFeature); } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - feature = (TFeature?)_currentIConnectionItemsFeature; + feature = Unsafe.As(ref _currentIConnectionItemsFeature); } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - feature = (TFeature?)_currentIMemoryPoolFeature; + feature = Unsafe.As(ref _currentIMemoryPoolFeature); } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - feature = (TFeature?)_currentIConnectionLifetimeFeature; + feature = Unsafe.As(ref _currentIConnectionLifetimeFeature); } else if (MaybeExtra != null) { diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs index 586ec1a0b5ea..da9c6e064252 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using Microsoft.AspNetCore.Connections.Features; using Microsoft.AspNetCore.Http.Features; @@ -164,26 +165,30 @@ private void ExtraFeatureSet(Type key, object? value) TFeature? IFeatureCollection.Get() where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + TFeature? feature = default; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - feature = (TFeature?)_currentIConnectionIdFeature; + feature = Unsafe.As(ref _currentIConnectionIdFeature); } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - feature = (TFeature?)_currentIConnectionTransportFeature; + feature = Unsafe.As(ref _currentIConnectionTransportFeature); } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - feature = (TFeature?)_currentIConnectionItemsFeature; + feature = Unsafe.As(ref _currentIConnectionItemsFeature); } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - feature = (TFeature?)_currentIMemoryPoolFeature; + feature = Unsafe.As(ref _currentIMemoryPoolFeature); } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - feature = (TFeature?)_currentIConnectionLifetimeFeature; + feature = Unsafe.As(ref _currentIConnectionLifetimeFeature); } else if (MaybeExtra != null) { diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index a95ff2f769e2..918cf11e63b1 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -25,6 +25,7 @@ public static string GenerateFile(string namespaceName, string className, string using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; {extraUsings} #nullable enable @@ -144,10 +145,14 @@ private void ExtraFeatureSet(Type key, object? value) TFeature? IFeatureCollection.Get() where TFeature : default {{ + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + TFeature? feature = default;{Each(features, feature => $@" {(feature.Index != 0 ? "else " : "")}if (typeof(TFeature) == typeof({feature.Name})) {{ - feature = (TFeature?)_current{feature.Name}; + feature = Unsafe.As<{feature.Name}?, TFeature?>(ref _current{feature.Name}); }}")} else if (MaybeExtra != null) {{ From 675d0b6b1abb3ef8e1da8e2b63a82b7e96b60ec3 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 05:29:35 +0100 Subject: [PATCH 3/9] Do the casting it for Set as well --- .../Internal/Http/HttpProtocol.Generated.cs | 60 ++++++++++--------- .../shared/TransportConnection.Generated.cs | 14 +++-- ...ransportMultiplexedConnection.Generated.cs | 14 +++-- .../FeatureCollectionGenerator.cs | 6 +- 4 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index b691227431fc..5133ac0b4b0a 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -527,118 +527,122 @@ private void ExtraFeatureSet(Type key, object? value) void IFeatureCollection.Set(TFeature? feature) where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + _featureRevision++; if (typeof(TFeature) == typeof(IHttpRequestFeature)) { - _currentIHttpRequestFeature = (IHttpRequestFeature?)feature; + _currentIHttpRequestFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) { - _currentIHttpRequestBodyDetectionFeature = (IHttpRequestBodyDetectionFeature?)feature; + _currentIHttpRequestBodyDetectionFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpResponseFeature)) { - _currentIHttpResponseFeature = (IHttpResponseFeature?)feature; + _currentIHttpResponseFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpResponseBodyFeature)) { - _currentIHttpResponseBodyFeature = (IHttpResponseBodyFeature?)feature; + _currentIHttpResponseBodyFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) { - _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)feature; + _currentIRequestBodyPipeFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) { - _currentIHttpRequestIdentifierFeature = (IHttpRequestIdentifierFeature?)feature; + _currentIHttpRequestIdentifierFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) { - _currentIServiceProvidersFeature = (IServiceProvidersFeature?)feature; + _currentIServiceProvidersFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) { - _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)feature; + _currentIHttpRequestLifetimeFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) { - _currentIHttpConnectionFeature = (IHttpConnectionFeature?)feature; + _currentIHttpConnectionFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IRouteValuesFeature)) { - _currentIRouteValuesFeature = (IRouteValuesFeature?)feature; + _currentIRouteValuesFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IEndpointFeature)) { - _currentIEndpointFeature = (IEndpointFeature?)feature; + _currentIEndpointFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) { - _currentIHttpAuthenticationFeature = (IHttpAuthenticationFeature?)feature; + _currentIHttpAuthenticationFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) { - _currentIHttpRequestTrailersFeature = (IHttpRequestTrailersFeature?)feature; + _currentIHttpRequestTrailersFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IQueryFeature)) { - _currentIQueryFeature = (IQueryFeature?)feature; + _currentIQueryFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IFormFeature)) { - _currentIFormFeature = (IFormFeature?)feature; + _currentIFormFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) { - _currentIHttpUpgradeFeature = (IHttpUpgradeFeature?)feature; + _currentIHttpUpgradeFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) { - _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)feature; + _currentIHttp2StreamIdFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) { - _currentIHttpResponseTrailersFeature = (IHttpResponseTrailersFeature?)feature; + _currentIHttpResponseTrailersFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IResponseCookiesFeature)) { - _currentIResponseCookiesFeature = (IResponseCookiesFeature?)feature; + _currentIResponseCookiesFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IItemsFeature)) { - _currentIItemsFeature = (IItemsFeature?)feature; + _currentIItemsFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(ITlsConnectionFeature)) { - _currentITlsConnectionFeature = (ITlsConnectionFeature?)feature; + _currentITlsConnectionFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpWebSocketFeature)) { - _currentIHttpWebSocketFeature = (IHttpWebSocketFeature?)feature; + _currentIHttpWebSocketFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(ISessionFeature)) { - _currentISessionFeature = (ISessionFeature?)feature; + _currentISessionFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature)) { - _currentIHttpMaxRequestBodySizeFeature = (IHttpMaxRequestBodySizeFeature?)feature; + _currentIHttpMaxRequestBodySizeFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpMinRequestBodyDataRateFeature)) { - _currentIHttpMinRequestBodyDataRateFeature = (IHttpMinRequestBodyDataRateFeature?)feature; + _currentIHttpMinRequestBodyDataRateFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpMinResponseDataRateFeature)) { - _currentIHttpMinResponseDataRateFeature = (IHttpMinResponseDataRateFeature?)feature; + _currentIHttpMinResponseDataRateFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpBodyControlFeature)) { - _currentIHttpBodyControlFeature = (IHttpBodyControlFeature?)feature; + _currentIHttpBodyControlFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpResetFeature)) { - _currentIHttpResetFeature = (IHttpResetFeature?)feature; + _currentIHttpResetFeature = Unsafe.As(ref feature); } else { diff --git a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs index c3e852715323..2d797a462cd0 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs @@ -200,26 +200,30 @@ private void ExtraFeatureSet(Type key, object? value) void IFeatureCollection.Set(TFeature? feature) where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + _featureRevision++; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = (IConnectionIdFeature?)feature; + _currentIConnectionIdFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = (IConnectionTransportFeature?)feature; + _currentIConnectionTransportFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = (IConnectionItemsFeature?)feature; + _currentIConnectionItemsFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = (IMemoryPoolFeature?)feature; + _currentIMemoryPoolFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)feature; + _currentIConnectionLifetimeFeature = Unsafe.As(ref feature); } else { diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs index da9c6e064252..bee6c1917014 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs @@ -200,26 +200,30 @@ private void ExtraFeatureSet(Type key, object? value) void IFeatureCollection.Set(TFeature? feature) where TFeature : default { + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + _featureRevision++; if (typeof(TFeature) == typeof(IConnectionIdFeature)) { - _currentIConnectionIdFeature = (IConnectionIdFeature?)feature; + _currentIConnectionIdFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionTransportFeature)) { - _currentIConnectionTransportFeature = (IConnectionTransportFeature?)feature; + _currentIConnectionTransportFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionItemsFeature)) { - _currentIConnectionItemsFeature = (IConnectionItemsFeature?)feature; + _currentIConnectionItemsFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IMemoryPoolFeature)) { - _currentIMemoryPoolFeature = (IMemoryPoolFeature?)feature; + _currentIMemoryPoolFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IConnectionLifetimeFeature)) { - _currentIConnectionLifetimeFeature = (IConnectionLifetimeFeature?)feature; + _currentIConnectionLifetimeFeature = Unsafe.As(ref feature); } else { diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index 918cf11e63b1..b94ccffbc421 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -169,10 +169,14 @@ private void ExtraFeatureSet(Type key, object? value) void IFeatureCollection.Set(TFeature? feature) where TFeature : default {{ + // Using Unsafe.As for the cast due to https://github.com/dotnet/runtime/issues/49614 + // The type of TFeature is confirmed by the typeof() check and the As cast only accepts + // that type; however the Jit does not eliminate a regular cast in a shared generic. + _featureRevision++;{Each(features, feature => $@" {(feature.Index != 0 ? "else " : "")}if (typeof(TFeature) == typeof({feature.Name})) {{ - _current{feature.Name} = ({feature.Name}?)feature; + _current{feature.Name} = Unsafe.As(ref feature); }}")} else {{ From c064ac004d25fc01891a00cdfe86dd442744eb46 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 06:44:56 +0100 Subject: [PATCH 4/9] Add more benchmarks --- .../HttpProtocolFeatureCollection.cs | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs index 00463d9f31cf..c7e83a7709da 100644 --- a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs @@ -5,12 +5,9 @@ using System.Buffers; using System.IO.Pipelines; using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core; -using Microsoft.AspNetCore.Server.Kestrel.Core.Internal; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Testing; @@ -22,18 +19,46 @@ public class HttpProtocolFeatureCollection [Benchmark] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestFeature GetViaTypeOf_First() + public IHttpRequestFeature GetViaTypeOf_IHttpRequestFeature() { return (IHttpRequestFeature)_collection[typeof(IHttpRequestFeature)]; } [Benchmark] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestFeature GetViaGeneric_First() + public IHttpRequestFeature GetViaGeneric_IHttpRequestFeature() { return _collection.Get(); } + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public IQueryFeature GetViaTypeOf_IQueryFeature() + { + return (IQueryFeature)_collection[typeof(IQueryFeature)]; + } + + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public IQueryFeature GetViaGeneric_IQueryFeature() + { + return _collection.Get(); + } + + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResetFeature GetViaTypeOf_IHttpResetFeature() + { + return (IHttpResetFeature)_collection[typeof(IHttpResetFeature)]; + } + + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResetFeature GetViaGeneric_IHttpResetFeature() + { + return _collection.Get(); + } + [Benchmark] [MethodImpl(MethodImplOptions.NoInlining)] public object GetViaTypeOf_Custom() From d5b832dd694f944621f81d2a4497a72ac52ccf09 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 15:13:13 +0100 Subject: [PATCH 5/9] Better benchmarks --- .../HttpProtocolFeatureCollection.cs | 198 +++++++++++++++--- 1 file changed, 165 insertions(+), 33 deletions(-) diff --git a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs index c7e83a7709da..3414db8961a1 100644 --- a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs @@ -5,9 +5,13 @@ using System.Buffers; using System.IO.Pipelines; using System.Runtime.CompilerServices; + using BenchmarkDotNet.Attributes; + using Microsoft.AspNetCore.Http.Features; +using Microsoft.AspNetCore.Http.Features.Authentication; using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.AspNetCore.Server.Kestrel.Core.Features; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http; using Microsoft.AspNetCore.Testing; @@ -17,73 +21,205 @@ public class HttpProtocolFeatureCollection { private readonly IFeatureCollection _collection; - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestFeature GetViaTypeOf_IHttpRequestFeature() + public IHttpRequestFeature Get_IHttpRequestFeature() { - return (IHttpRequestFeature)_collection[typeof(IHttpRequestFeature)]; + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestFeature GetViaGeneric_IHttpRequestFeature() + public IHttpRequestBodyDetectionFeature Get_IHttpRequestBodyDetectionFeature() { - return _collection.Get(); + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResponseFeature Get_IHttpResponseFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResponseBodyFeature Get_IHttpResponseBodyFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IRequestBodyPipeFeature Get_IRequestBodyPipeFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpRequestIdentifierFeature Get_IHttpRequestIdentifierFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IServiceProvidersFeature Get_IServiceProvidersFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpRequestLifetimeFeature Get_IHttpRequestLifetimeFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpConnectionFeature Get_IHttpConnectionFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IRouteValuesFeature Get_IRouteValuesFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IEndpointFeature Get_IEndpointFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpAuthenticationFeature Get_IHttpAuthenticationFeature() + { + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IQueryFeature GetViaTypeOf_IQueryFeature() + public IHttpRequestTrailersFeature Get_IHttpRequestTrailersFeature() { - return (IQueryFeature)_collection[typeof(IQueryFeature)]; + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IQueryFeature GetViaGeneric_IQueryFeature() + public IQueryFeature Get_IQueryFeature() { return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpResetFeature GetViaTypeOf_IHttpResetFeature() + public IFormFeature Get_IFormFeature() { - return (IHttpResetFeature)_collection[typeof(IHttpResetFeature)]; + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpResetFeature GetViaGeneric_IHttpResetFeature() + public IHttpUpgradeFeature Get_IHttpUpgradeFeature() { - return _collection.Get(); + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttp2StreamIdFeature Get_IHttp2StreamIdFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResponseTrailersFeature Get_IHttpResponseTrailersFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IResponseCookiesFeature Get_IResponseCookiesFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IItemsFeature Get_IItemsFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public ITlsConnectionFeature Get_ITlsConnectionFeature() + { + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public object GetViaTypeOf_Custom() + public IHttpWebSocketFeature Get_IHttpWebSocketFeature() { - return (IHttpCustomFeature)_collection[typeof(IHttpCustomFeature)]; + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public object GetViaGeneric_Custom() + public ISessionFeature Get_ISessionFeature() { - return _collection.Get(); + return _collection.Get(); } + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpMaxRequestBodySizeFeature Get_IHttpMaxRequestBodySizeFeature() + { + return _collection.Get(); + } - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public object GetViaTypeOf_NotFound() + public IHttpMinRequestBodyDataRateFeature Get_IHttpMinRequestBodyDataRateFeature() { - return (IHttpNotFoundFeature)_collection[typeof(IHttpNotFoundFeature)]; + return _collection.Get(); } - [Benchmark] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public object GetViaGeneric_NotFound() + public IHttpMinResponseDataRateFeature Get_IHttpMinResponseDataRateFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpBodyControlFeature Get_IHttpBodyControlFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpResetFeature Get_IHttpResetFeature() + { + return _collection.Get(); + } + + [Benchmark(Description = "Get")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpNotFoundFeature Get_IHttpNotFoundFeature() { return _collection.Get(); } @@ -114,11 +250,7 @@ public HttpProtocolFeatureCollection() _collection = http1Connection; } - private interface IHttpCustomFeature - { - } - - private interface IHttpNotFoundFeature + public interface IHttpNotFoundFeature { } } From b5dadd82889bb92f63c2421943f8ceb9d603595e Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Sun, 28 Mar 2021 18:31:46 +0100 Subject: [PATCH 6/9] Rearrange features --- .../Http/HttpProtocol.FeatureCollection.cs | 14 +- .../Internal/Http/HttpProtocol.Generated.cs | 430 +++++++++--------- .../HttpProtocolFeatureCollection.cs | 118 ++--- .../HttpProtocolFeatureCollection.cs | 48 +- 4 files changed, 306 insertions(+), 304 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs index ebc12784d6e4..14311aed6754 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs @@ -2,8 +2,6 @@ // 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.Diagnostics; using System.IO; using System.IO.Pipelines; using System.Net; @@ -19,19 +17,19 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { internal partial class HttpProtocol : IHttpRequestFeature, - IHttpRequestBodyDetectionFeature, IHttpResponseFeature, IHttpResponseBodyFeature, - IRequestBodyPipeFeature, + IRouteValuesFeature, + IEndpointFeature, + IHttpRequestIdentifierFeature, + IHttpRequestTrailersFeature, IHttpUpgradeFeature, + IRequestBodyPipeFeature, IHttpConnectionFeature, IHttpRequestLifetimeFeature, - IHttpRequestIdentifierFeature, - IHttpRequestTrailersFeature, IHttpBodyControlFeature, IHttpMaxRequestBodySizeFeature, - IEndpointFeature, - IRouteValuesFeature + IHttpRequestBodyDetectionFeature { // NOTE: When feature interfaces are added to or removed from this HttpProtocol class implementation, // then the list of `implementedFeatures` in the generated code project MUST also be updated. diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index 5133ac0b4b0a..2e6136cb5d54 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -17,32 +17,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http internal partial class HttpProtocol : IFeatureCollection { internal protected IHttpRequestFeature? _currentIHttpRequestFeature; - internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; internal protected IHttpResponseFeature? _currentIHttpResponseFeature; internal protected IHttpResponseBodyFeature? _currentIHttpResponseBodyFeature; - internal protected IRequestBodyPipeFeature? _currentIRequestBodyPipeFeature; - internal protected IHttpRequestIdentifierFeature? _currentIHttpRequestIdentifierFeature; - internal protected IServiceProvidersFeature? _currentIServiceProvidersFeature; - internal protected IHttpRequestLifetimeFeature? _currentIHttpRequestLifetimeFeature; - internal protected IHttpConnectionFeature? _currentIHttpConnectionFeature; internal protected IRouteValuesFeature? _currentIRouteValuesFeature; internal protected IEndpointFeature? _currentIEndpointFeature; - internal protected IHttpAuthenticationFeature? _currentIHttpAuthenticationFeature; - internal protected IHttpRequestTrailersFeature? _currentIHttpRequestTrailersFeature; + internal protected IServiceProvidersFeature? _currentIServiceProvidersFeature; + internal protected IItemsFeature? _currentIItemsFeature; internal protected IQueryFeature? _currentIQueryFeature; internal protected IFormFeature? _currentIFormFeature; - internal protected IHttpUpgradeFeature? _currentIHttpUpgradeFeature; - internal protected IHttp2StreamIdFeature? _currentIHttp2StreamIdFeature; - internal protected IHttpResponseTrailersFeature? _currentIHttpResponseTrailersFeature; + internal protected IHttpAuthenticationFeature? _currentIHttpAuthenticationFeature; + internal protected IHttpRequestIdentifierFeature? _currentIHttpRequestIdentifierFeature; + internal protected IHttpConnectionFeature? _currentIHttpConnectionFeature; + internal protected ISessionFeature? _currentISessionFeature; internal protected IResponseCookiesFeature? _currentIResponseCookiesFeature; - internal protected IItemsFeature? _currentIItemsFeature; + internal protected IHttpRequestTrailersFeature? _currentIHttpRequestTrailersFeature; + internal protected IHttpResponseTrailersFeature? _currentIHttpResponseTrailersFeature; internal protected ITlsConnectionFeature? _currentITlsConnectionFeature; + internal protected IHttpUpgradeFeature? _currentIHttpUpgradeFeature; internal protected IHttpWebSocketFeature? _currentIHttpWebSocketFeature; - internal protected ISessionFeature? _currentISessionFeature; + internal protected IHttp2StreamIdFeature? _currentIHttp2StreamIdFeature; + internal protected IRequestBodyPipeFeature? _currentIRequestBodyPipeFeature; + internal protected IHttpRequestLifetimeFeature? _currentIHttpRequestLifetimeFeature; internal protected IHttpMaxRequestBodySizeFeature? _currentIHttpMaxRequestBodySizeFeature; internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; internal protected IHttpMinResponseDataRateFeature? _currentIHttpMinResponseDataRateFeature; internal protected IHttpBodyControlFeature? _currentIHttpBodyControlFeature; + internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; internal protected IHttpResetFeature? _currentIHttpResetFeature; private int _featureRevision; @@ -52,31 +52,31 @@ internal partial class HttpProtocol : IFeatureCollection private void FastReset() { _currentIHttpRequestFeature = this; - _currentIHttpRequestBodyDetectionFeature = this; _currentIHttpResponseFeature = this; _currentIHttpResponseBodyFeature = this; - _currentIRequestBodyPipeFeature = this; - _currentIHttpUpgradeFeature = this; + _currentIRouteValuesFeature = this; + _currentIEndpointFeature = this; _currentIHttpRequestIdentifierFeature = this; - _currentIHttpRequestLifetimeFeature = this; _currentIHttpRequestTrailersFeature = this; + _currentIHttpUpgradeFeature = this; + _currentIRequestBodyPipeFeature = this; _currentIHttpConnectionFeature = this; - _currentIHttpMaxRequestBodySizeFeature = this; + _currentIHttpRequestLifetimeFeature = this; _currentIHttpBodyControlFeature = this; - _currentIRouteValuesFeature = this; - _currentIEndpointFeature = this; + _currentIHttpMaxRequestBodySizeFeature = this; + _currentIHttpRequestBodyDetectionFeature = this; _currentIServiceProvidersFeature = null; - _currentIHttpAuthenticationFeature = null; + _currentIItemsFeature = null; _currentIQueryFeature = null; _currentIFormFeature = null; - _currentIHttp2StreamIdFeature = null; - _currentIHttpResponseTrailersFeature = null; + _currentIHttpAuthenticationFeature = null; + _currentISessionFeature = null; _currentIResponseCookiesFeature = null; - _currentIItemsFeature = null; + _currentIHttpResponseTrailersFeature = null; _currentITlsConnectionFeature = null; _currentIHttpWebSocketFeature = null; - _currentISessionFeature = null; + _currentIHttp2StreamIdFeature = null; _currentIHttpMinResponseDataRateFeature = null; _currentIHttpResetFeature = null; } @@ -154,10 +154,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIHttpRequestFeature; } - else if (key == typeof(IHttpRequestBodyDetectionFeature)) - { - feature = _currentIHttpRequestBodyDetectionFeature; - } else if (key == typeof(IHttpResponseFeature)) { feature = _currentIHttpResponseFeature; @@ -166,26 +162,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIHttpResponseBodyFeature; } - else if (key == typeof(IRequestBodyPipeFeature)) - { - feature = _currentIRequestBodyPipeFeature; - } - else if (key == typeof(IHttpRequestIdentifierFeature)) - { - feature = _currentIHttpRequestIdentifierFeature; - } - else if (key == typeof(IServiceProvidersFeature)) - { - feature = _currentIServiceProvidersFeature; - } - else if (key == typeof(IHttpRequestLifetimeFeature)) - { - feature = _currentIHttpRequestLifetimeFeature; - } - else if (key == typeof(IHttpConnectionFeature)) - { - feature = _currentIHttpConnectionFeature; - } else if (key == typeof(IRouteValuesFeature)) { feature = _currentIRouteValuesFeature; @@ -194,13 +170,13 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIEndpointFeature; } - else if (key == typeof(IHttpAuthenticationFeature)) + else if (key == typeof(IServiceProvidersFeature)) { - feature = _currentIHttpAuthenticationFeature; + feature = _currentIServiceProvidersFeature; } - else if (key == typeof(IHttpRequestTrailersFeature)) + else if (key == typeof(IItemsFeature)) { - feature = _currentIHttpRequestTrailersFeature; + feature = _currentIItemsFeature; } else if (key == typeof(IQueryFeature)) { @@ -210,37 +186,57 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIFormFeature; } - else if (key == typeof(IHttpUpgradeFeature)) + else if (key == typeof(IHttpAuthenticationFeature)) { - feature = _currentIHttpUpgradeFeature; + feature = _currentIHttpAuthenticationFeature; } - else if (key == typeof(IHttp2StreamIdFeature)) + else if (key == typeof(IHttpRequestIdentifierFeature)) { - feature = _currentIHttp2StreamIdFeature; + feature = _currentIHttpRequestIdentifierFeature; } - else if (key == typeof(IHttpResponseTrailersFeature)) + else if (key == typeof(IHttpConnectionFeature)) { - feature = _currentIHttpResponseTrailersFeature; + feature = _currentIHttpConnectionFeature; + } + else if (key == typeof(ISessionFeature)) + { + feature = _currentISessionFeature; } else if (key == typeof(IResponseCookiesFeature)) { feature = _currentIResponseCookiesFeature; } - else if (key == typeof(IItemsFeature)) + else if (key == typeof(IHttpRequestTrailersFeature)) { - feature = _currentIItemsFeature; + feature = _currentIHttpRequestTrailersFeature; + } + else if (key == typeof(IHttpResponseTrailersFeature)) + { + feature = _currentIHttpResponseTrailersFeature; } else if (key == typeof(ITlsConnectionFeature)) { feature = _currentITlsConnectionFeature; } + else if (key == typeof(IHttpUpgradeFeature)) + { + feature = _currentIHttpUpgradeFeature; + } else if (key == typeof(IHttpWebSocketFeature)) { feature = _currentIHttpWebSocketFeature; } - else if (key == typeof(ISessionFeature)) + else if (key == typeof(IHttp2StreamIdFeature)) { - feature = _currentISessionFeature; + feature = _currentIHttp2StreamIdFeature; + } + else if (key == typeof(IRequestBodyPipeFeature)) + { + feature = _currentIRequestBodyPipeFeature; + } + else if (key == typeof(IHttpRequestLifetimeFeature)) + { + feature = _currentIHttpRequestLifetimeFeature; } else if (key == typeof(IHttpMaxRequestBodySizeFeature)) { @@ -258,6 +254,10 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIHttpBodyControlFeature; } + else if (key == typeof(IHttpRequestBodyDetectionFeature)) + { + feature = _currentIHttpRequestBodyDetectionFeature; + } else if (key == typeof(IHttpResetFeature)) { feature = _currentIHttpResetFeature; @@ -278,10 +278,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpRequestFeature = (IHttpRequestFeature?)value; } - else if (key == typeof(IHttpRequestBodyDetectionFeature)) - { - _currentIHttpRequestBodyDetectionFeature = (IHttpRequestBodyDetectionFeature?)value; - } else if (key == typeof(IHttpResponseFeature)) { _currentIHttpResponseFeature = (IHttpResponseFeature?)value; @@ -290,26 +286,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpResponseBodyFeature = (IHttpResponseBodyFeature?)value; } - else if (key == typeof(IRequestBodyPipeFeature)) - { - _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)value; - } - else if (key == typeof(IHttpRequestIdentifierFeature)) - { - _currentIHttpRequestIdentifierFeature = (IHttpRequestIdentifierFeature?)value; - } - else if (key == typeof(IServiceProvidersFeature)) - { - _currentIServiceProvidersFeature = (IServiceProvidersFeature?)value; - } - else if (key == typeof(IHttpRequestLifetimeFeature)) - { - _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)value; - } - else if (key == typeof(IHttpConnectionFeature)) - { - _currentIHttpConnectionFeature = (IHttpConnectionFeature?)value; - } else if (key == typeof(IRouteValuesFeature)) { _currentIRouteValuesFeature = (IRouteValuesFeature?)value; @@ -318,13 +294,13 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIEndpointFeature = (IEndpointFeature?)value; } - else if (key == typeof(IHttpAuthenticationFeature)) + else if (key == typeof(IServiceProvidersFeature)) { - _currentIHttpAuthenticationFeature = (IHttpAuthenticationFeature?)value; + _currentIServiceProvidersFeature = (IServiceProvidersFeature?)value; } - else if (key == typeof(IHttpRequestTrailersFeature)) + else if (key == typeof(IItemsFeature)) { - _currentIHttpRequestTrailersFeature = (IHttpRequestTrailersFeature?)value; + _currentIItemsFeature = (IItemsFeature?)value; } else if (key == typeof(IQueryFeature)) { @@ -334,37 +310,57 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIFormFeature = (IFormFeature?)value; } - else if (key == typeof(IHttpUpgradeFeature)) + else if (key == typeof(IHttpAuthenticationFeature)) { - _currentIHttpUpgradeFeature = (IHttpUpgradeFeature?)value; + _currentIHttpAuthenticationFeature = (IHttpAuthenticationFeature?)value; } - else if (key == typeof(IHttp2StreamIdFeature)) + else if (key == typeof(IHttpRequestIdentifierFeature)) { - _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)value; + _currentIHttpRequestIdentifierFeature = (IHttpRequestIdentifierFeature?)value; } - else if (key == typeof(IHttpResponseTrailersFeature)) + else if (key == typeof(IHttpConnectionFeature)) { - _currentIHttpResponseTrailersFeature = (IHttpResponseTrailersFeature?)value; + _currentIHttpConnectionFeature = (IHttpConnectionFeature?)value; + } + else if (key == typeof(ISessionFeature)) + { + _currentISessionFeature = (ISessionFeature?)value; } else if (key == typeof(IResponseCookiesFeature)) { _currentIResponseCookiesFeature = (IResponseCookiesFeature?)value; } - else if (key == typeof(IItemsFeature)) + else if (key == typeof(IHttpRequestTrailersFeature)) { - _currentIItemsFeature = (IItemsFeature?)value; + _currentIHttpRequestTrailersFeature = (IHttpRequestTrailersFeature?)value; + } + else if (key == typeof(IHttpResponseTrailersFeature)) + { + _currentIHttpResponseTrailersFeature = (IHttpResponseTrailersFeature?)value; } else if (key == typeof(ITlsConnectionFeature)) { _currentITlsConnectionFeature = (ITlsConnectionFeature?)value; } + else if (key == typeof(IHttpUpgradeFeature)) + { + _currentIHttpUpgradeFeature = (IHttpUpgradeFeature?)value; + } else if (key == typeof(IHttpWebSocketFeature)) { _currentIHttpWebSocketFeature = (IHttpWebSocketFeature?)value; } - else if (key == typeof(ISessionFeature)) + else if (key == typeof(IHttp2StreamIdFeature)) { - _currentISessionFeature = (ISessionFeature?)value; + _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)value; + } + else if (key == typeof(IRequestBodyPipeFeature)) + { + _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)value; + } + else if (key == typeof(IHttpRequestLifetimeFeature)) + { + _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)value; } else if (key == typeof(IHttpMaxRequestBodySizeFeature)) { @@ -382,6 +378,10 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpBodyControlFeature = (IHttpBodyControlFeature?)value; } + else if (key == typeof(IHttpRequestBodyDetectionFeature)) + { + _currentIHttpRequestBodyDetectionFeature = (IHttpRequestBodyDetectionFeature?)value; + } else if (key == typeof(IHttpResetFeature)) { _currentIHttpResetFeature = (IHttpResetFeature?)value; @@ -404,10 +404,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIHttpRequestFeature); } - else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) - { - feature = Unsafe.As(ref _currentIHttpRequestBodyDetectionFeature); - } else if (typeof(TFeature) == typeof(IHttpResponseFeature)) { feature = Unsafe.As(ref _currentIHttpResponseFeature); @@ -416,26 +412,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIHttpResponseBodyFeature); } - else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) - { - feature = Unsafe.As(ref _currentIRequestBodyPipeFeature); - } - else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) - { - feature = Unsafe.As(ref _currentIHttpRequestIdentifierFeature); - } - else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) - { - feature = Unsafe.As(ref _currentIServiceProvidersFeature); - } - else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) - { - feature = Unsafe.As(ref _currentIHttpRequestLifetimeFeature); - } - else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) - { - feature = Unsafe.As(ref _currentIHttpConnectionFeature); - } else if (typeof(TFeature) == typeof(IRouteValuesFeature)) { feature = Unsafe.As(ref _currentIRouteValuesFeature); @@ -444,13 +420,13 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIEndpointFeature); } - else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) + else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) { - feature = Unsafe.As(ref _currentIHttpAuthenticationFeature); + feature = Unsafe.As(ref _currentIServiceProvidersFeature); } - else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) + else if (typeof(TFeature) == typeof(IItemsFeature)) { - feature = Unsafe.As(ref _currentIHttpRequestTrailersFeature); + feature = Unsafe.As(ref _currentIItemsFeature); } else if (typeof(TFeature) == typeof(IQueryFeature)) { @@ -460,37 +436,57 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIFormFeature); } - else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) + else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) { - feature = Unsafe.As(ref _currentIHttpUpgradeFeature); + feature = Unsafe.As(ref _currentIHttpAuthenticationFeature); } - else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) + else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) { - feature = Unsafe.As(ref _currentIHttp2StreamIdFeature); + feature = Unsafe.As(ref _currentIHttpRequestIdentifierFeature); } - else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) + else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) { - feature = Unsafe.As(ref _currentIHttpResponseTrailersFeature); + feature = Unsafe.As(ref _currentIHttpConnectionFeature); + } + else if (typeof(TFeature) == typeof(ISessionFeature)) + { + feature = Unsafe.As(ref _currentISessionFeature); } else if (typeof(TFeature) == typeof(IResponseCookiesFeature)) { feature = Unsafe.As(ref _currentIResponseCookiesFeature); } - else if (typeof(TFeature) == typeof(IItemsFeature)) + else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) { - feature = Unsafe.As(ref _currentIItemsFeature); + feature = Unsafe.As(ref _currentIHttpRequestTrailersFeature); + } + else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) + { + feature = Unsafe.As(ref _currentIHttpResponseTrailersFeature); } else if (typeof(TFeature) == typeof(ITlsConnectionFeature)) { feature = Unsafe.As(ref _currentITlsConnectionFeature); } + else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) + { + feature = Unsafe.As(ref _currentIHttpUpgradeFeature); + } else if (typeof(TFeature) == typeof(IHttpWebSocketFeature)) { feature = Unsafe.As(ref _currentIHttpWebSocketFeature); } - else if (typeof(TFeature) == typeof(ISessionFeature)) + else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) { - feature = Unsafe.As(ref _currentISessionFeature); + feature = Unsafe.As(ref _currentIHttp2StreamIdFeature); + } + else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) + { + feature = Unsafe.As(ref _currentIRequestBodyPipeFeature); + } + else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) + { + feature = Unsafe.As(ref _currentIHttpRequestLifetimeFeature); } else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature)) { @@ -508,6 +504,10 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIHttpBodyControlFeature); } + else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) + { + feature = Unsafe.As(ref _currentIHttpRequestBodyDetectionFeature); + } else if (typeof(TFeature) == typeof(IHttpResetFeature)) { feature = Unsafe.As(ref _currentIHttpResetFeature); @@ -536,10 +536,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpRequestFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) - { - _currentIHttpRequestBodyDetectionFeature = Unsafe.As(ref feature); - } else if (typeof(TFeature) == typeof(IHttpResponseFeature)) { _currentIHttpResponseFeature = Unsafe.As(ref feature); @@ -548,26 +544,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpResponseBodyFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) - { - _currentIRequestBodyPipeFeature = Unsafe.As(ref feature); - } - else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) - { - _currentIHttpRequestIdentifierFeature = Unsafe.As(ref feature); - } - else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) - { - _currentIServiceProvidersFeature = Unsafe.As(ref feature); - } - else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) - { - _currentIHttpRequestLifetimeFeature = Unsafe.As(ref feature); - } - else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) - { - _currentIHttpConnectionFeature = Unsafe.As(ref feature); - } else if (typeof(TFeature) == typeof(IRouteValuesFeature)) { _currentIRouteValuesFeature = Unsafe.As(ref feature); @@ -576,13 +552,13 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIEndpointFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) + else if (typeof(TFeature) == typeof(IServiceProvidersFeature)) { - _currentIHttpAuthenticationFeature = Unsafe.As(ref feature); + _currentIServiceProvidersFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) + else if (typeof(TFeature) == typeof(IItemsFeature)) { - _currentIHttpRequestTrailersFeature = Unsafe.As(ref feature); + _currentIItemsFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IQueryFeature)) { @@ -592,37 +568,57 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIFormFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) + else if (typeof(TFeature) == typeof(IHttpAuthenticationFeature)) { - _currentIHttpUpgradeFeature = Unsafe.As(ref feature); + _currentIHttpAuthenticationFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) + else if (typeof(TFeature) == typeof(IHttpRequestIdentifierFeature)) { - _currentIHttp2StreamIdFeature = Unsafe.As(ref feature); + _currentIHttpRequestIdentifierFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) + else if (typeof(TFeature) == typeof(IHttpConnectionFeature)) { - _currentIHttpResponseTrailersFeature = Unsafe.As(ref feature); + _currentIHttpConnectionFeature = Unsafe.As(ref feature); + } + else if (typeof(TFeature) == typeof(ISessionFeature)) + { + _currentISessionFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IResponseCookiesFeature)) { _currentIResponseCookiesFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IItemsFeature)) + else if (typeof(TFeature) == typeof(IHttpRequestTrailersFeature)) { - _currentIItemsFeature = Unsafe.As(ref feature); + _currentIHttpRequestTrailersFeature = Unsafe.As(ref feature); + } + else if (typeof(TFeature) == typeof(IHttpResponseTrailersFeature)) + { + _currentIHttpResponseTrailersFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(ITlsConnectionFeature)) { _currentITlsConnectionFeature = Unsafe.As(ref feature); } + else if (typeof(TFeature) == typeof(IHttpUpgradeFeature)) + { + _currentIHttpUpgradeFeature = Unsafe.As(ref feature); + } else if (typeof(TFeature) == typeof(IHttpWebSocketFeature)) { _currentIHttpWebSocketFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(ISessionFeature)) + else if (typeof(TFeature) == typeof(IHttp2StreamIdFeature)) { - _currentISessionFeature = Unsafe.As(ref feature); + _currentIHttp2StreamIdFeature = Unsafe.As(ref feature); + } + else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) + { + _currentIRequestBodyPipeFeature = Unsafe.As(ref feature); + } + else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) + { + _currentIHttpRequestLifetimeFeature = Unsafe.As(ref feature); } else if (typeof(TFeature) == typeof(IHttpMaxRequestBodySizeFeature)) { @@ -640,6 +636,10 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttpBodyControlFeature = Unsafe.As(ref feature); } + else if (typeof(TFeature) == typeof(IHttpRequestBodyDetectionFeature)) + { + _currentIHttpRequestBodyDetectionFeature = Unsafe.As(ref feature); + } else if (typeof(TFeature) == typeof(IHttpResetFeature)) { _currentIHttpResetFeature = Unsafe.As(ref feature); @@ -656,10 +656,6 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IHttpRequestFeature), _currentIHttpRequestFeature); } - if (_currentIHttpRequestBodyDetectionFeature != null) - { - yield return new KeyValuePair(typeof(IHttpRequestBodyDetectionFeature), _currentIHttpRequestBodyDetectionFeature); - } if (_currentIHttpResponseFeature != null) { yield return new KeyValuePair(typeof(IHttpResponseFeature), _currentIHttpResponseFeature); @@ -668,26 +664,6 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IHttpResponseBodyFeature), _currentIHttpResponseBodyFeature); } - if (_currentIRequestBodyPipeFeature != null) - { - yield return new KeyValuePair(typeof(IRequestBodyPipeFeature), _currentIRequestBodyPipeFeature); - } - if (_currentIHttpRequestIdentifierFeature != null) - { - yield return new KeyValuePair(typeof(IHttpRequestIdentifierFeature), _currentIHttpRequestIdentifierFeature); - } - if (_currentIServiceProvidersFeature != null) - { - yield return new KeyValuePair(typeof(IServiceProvidersFeature), _currentIServiceProvidersFeature); - } - if (_currentIHttpRequestLifetimeFeature != null) - { - yield return new KeyValuePair(typeof(IHttpRequestLifetimeFeature), _currentIHttpRequestLifetimeFeature); - } - if (_currentIHttpConnectionFeature != null) - { - yield return new KeyValuePair(typeof(IHttpConnectionFeature), _currentIHttpConnectionFeature); - } if (_currentIRouteValuesFeature != null) { yield return new KeyValuePair(typeof(IRouteValuesFeature), _currentIRouteValuesFeature); @@ -696,13 +672,13 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IEndpointFeature), _currentIEndpointFeature); } - if (_currentIHttpAuthenticationFeature != null) + if (_currentIServiceProvidersFeature != null) { - yield return new KeyValuePair(typeof(IHttpAuthenticationFeature), _currentIHttpAuthenticationFeature); + yield return new KeyValuePair(typeof(IServiceProvidersFeature), _currentIServiceProvidersFeature); } - if (_currentIHttpRequestTrailersFeature != null) + if (_currentIItemsFeature != null) { - yield return new KeyValuePair(typeof(IHttpRequestTrailersFeature), _currentIHttpRequestTrailersFeature); + yield return new KeyValuePair(typeof(IItemsFeature), _currentIItemsFeature); } if (_currentIQueryFeature != null) { @@ -712,37 +688,57 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IFormFeature), _currentIFormFeature); } - if (_currentIHttpUpgradeFeature != null) + if (_currentIHttpAuthenticationFeature != null) { - yield return new KeyValuePair(typeof(IHttpUpgradeFeature), _currentIHttpUpgradeFeature); + yield return new KeyValuePair(typeof(IHttpAuthenticationFeature), _currentIHttpAuthenticationFeature); } - if (_currentIHttp2StreamIdFeature != null) + if (_currentIHttpRequestIdentifierFeature != null) { - yield return new KeyValuePair(typeof(IHttp2StreamIdFeature), _currentIHttp2StreamIdFeature); + yield return new KeyValuePair(typeof(IHttpRequestIdentifierFeature), _currentIHttpRequestIdentifierFeature); } - if (_currentIHttpResponseTrailersFeature != null) + if (_currentIHttpConnectionFeature != null) { - yield return new KeyValuePair(typeof(IHttpResponseTrailersFeature), _currentIHttpResponseTrailersFeature); + yield return new KeyValuePair(typeof(IHttpConnectionFeature), _currentIHttpConnectionFeature); + } + if (_currentISessionFeature != null) + { + yield return new KeyValuePair(typeof(ISessionFeature), _currentISessionFeature); } if (_currentIResponseCookiesFeature != null) { yield return new KeyValuePair(typeof(IResponseCookiesFeature), _currentIResponseCookiesFeature); } - if (_currentIItemsFeature != null) + if (_currentIHttpRequestTrailersFeature != null) { - yield return new KeyValuePair(typeof(IItemsFeature), _currentIItemsFeature); + yield return new KeyValuePair(typeof(IHttpRequestTrailersFeature), _currentIHttpRequestTrailersFeature); + } + if (_currentIHttpResponseTrailersFeature != null) + { + yield return new KeyValuePair(typeof(IHttpResponseTrailersFeature), _currentIHttpResponseTrailersFeature); } if (_currentITlsConnectionFeature != null) { yield return new KeyValuePair(typeof(ITlsConnectionFeature), _currentITlsConnectionFeature); } + if (_currentIHttpUpgradeFeature != null) + { + yield return new KeyValuePair(typeof(IHttpUpgradeFeature), _currentIHttpUpgradeFeature); + } if (_currentIHttpWebSocketFeature != null) { yield return new KeyValuePair(typeof(IHttpWebSocketFeature), _currentIHttpWebSocketFeature); } - if (_currentISessionFeature != null) + if (_currentIHttp2StreamIdFeature != null) { - yield return new KeyValuePair(typeof(ISessionFeature), _currentISessionFeature); + yield return new KeyValuePair(typeof(IHttp2StreamIdFeature), _currentIHttp2StreamIdFeature); + } + if (_currentIRequestBodyPipeFeature != null) + { + yield return new KeyValuePair(typeof(IRequestBodyPipeFeature), _currentIRequestBodyPipeFeature); + } + if (_currentIHttpRequestLifetimeFeature != null) + { + yield return new KeyValuePair(typeof(IHttpRequestLifetimeFeature), _currentIHttpRequestLifetimeFeature); } if (_currentIHttpMaxRequestBodySizeFeature != null) { @@ -760,6 +756,10 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IHttpBodyControlFeature), _currentIHttpBodyControlFeature); } + if (_currentIHttpRequestBodyDetectionFeature != null) + { + yield return new KeyValuePair(typeof(IHttpRequestBodyDetectionFeature), _currentIHttpRequestBodyDetectionFeature); + } if (_currentIHttpResetFeature != null) { yield return new KeyValuePair(typeof(IHttpResetFeature), _currentIHttpResetFeature); diff --git a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs index 3414db8961a1..a50bfaf4b243 100644 --- a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs @@ -28,13 +28,6 @@ public IHttpRequestFeature Get_IHttpRequestFeature() return _collection.Get(); } - [Benchmark(Description = "Get*")] - [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestBodyDetectionFeature Get_IHttpRequestBodyDetectionFeature() - { - return _collection.Get(); - } - [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] public IHttpResponseFeature Get_IHttpResponseFeature() @@ -49,18 +42,18 @@ public IHttpResponseBodyFeature Get_IHttpResponseBodyFeature() return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IRequestBodyPipeFeature Get_IRequestBodyPipeFeature() + public IRouteValuesFeature Get_IRouteValuesFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestIdentifierFeature Get_IHttpRequestIdentifierFeature() + public IEndpointFeature Get_IEndpointFeature() { - return _collection.Get(); + return _collection.Get(); } [Benchmark(Description = "Get")] @@ -70,32 +63,25 @@ public IServiceProvidersFeature Get_IServiceProvidersFeature() return _collection.Get(); } - [Benchmark(Description = "Get*")] - [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestLifetimeFeature Get_IHttpRequestLifetimeFeature() - { - return _collection.Get(); - } - - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpConnectionFeature Get_IHttpConnectionFeature() + public IItemsFeature Get_IItemsFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IRouteValuesFeature Get_IRouteValuesFeature() + public IQueryFeature Get_IQueryFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IEndpointFeature Get_IEndpointFeature() + public IFormFeature Get_IFormFeature() { - return _collection.Get(); + return _collection.Get(); } [Benchmark(Description = "Get")] @@ -105,39 +91,39 @@ public IHttpAuthenticationFeature Get_IHttpAuthenticationFeature() return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpRequestTrailersFeature Get_IHttpRequestTrailersFeature() + public IHttpRequestIdentifierFeature Get_IHttpRequestIdentifierFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IQueryFeature Get_IQueryFeature() + public IHttpConnectionFeature Get_IHttpConnectionFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IFormFeature Get_IFormFeature() + public ISessionFeature Get_ISessionFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get*")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpUpgradeFeature Get_IHttpUpgradeFeature() + public IResponseCookiesFeature Get_IResponseCookiesFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttp2StreamIdFeature Get_IHttp2StreamIdFeature() + public IHttpRequestTrailersFeature Get_IHttpRequestTrailersFeature() { - return _collection.Get(); + return _collection.Get(); } [Benchmark(Description = "Get")] @@ -147,39 +133,46 @@ public IHttpResponseTrailersFeature Get_IHttpResponseTrailersFeature() return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IResponseCookiesFeature Get_IResponseCookiesFeature() + public ITlsConnectionFeature Get_ITlsConnectionFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public IItemsFeature Get_IItemsFeature() + public IHttpUpgradeFeature Get_IHttpUpgradeFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public ITlsConnectionFeature Get_ITlsConnectionFeature() + public IHttpWebSocketFeature Get_IHttpWebSocketFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] - public IHttpWebSocketFeature Get_IHttpWebSocketFeature() + public IHttp2StreamIdFeature Get_IHttp2StreamIdFeature() { - return _collection.Get(); + return _collection.Get(); } - [Benchmark(Description = "Get")] + [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] - public ISessionFeature Get_ISessionFeature() + public IRequestBodyPipeFeature Get_IRequestBodyPipeFeature() { - return _collection.Get(); + return _collection.Get(); + } + + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpRequestLifetimeFeature Get_IHttpRequestLifetimeFeature() + { + return _collection.Get(); } [Benchmark(Description = "Get*")] @@ -210,6 +203,13 @@ public IHttpBodyControlFeature Get_IHttpBodyControlFeature() return _collection.Get(); } + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IHttpRequestBodyDetectionFeature Get_IHttpRequestBodyDetectionFeature() + { + return _collection.Get(); + } + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] public IHttpResetFeature Get_IHttpResetFeature() diff --git a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs index ea312cce0688..70e7a667c0ec 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs @@ -12,46 +12,50 @@ public static string GenerateFile() var alwaysFeatures = new[] { "IHttpRequestFeature", - "IHttpRequestBodyDetectionFeature", "IHttpResponseFeature", "IHttpResponseBodyFeature", - "IRequestBodyPipeFeature", - "IHttpRequestIdentifierFeature", - "IServiceProvidersFeature", - "IHttpRequestLifetimeFeature", - "IHttpConnectionFeature", "IRouteValuesFeature", - "IEndpointFeature" + "IEndpointFeature", + "IServiceProvidersFeature" }; var commonFeatures = new[] { - "IHttpAuthenticationFeature", - "IHttpRequestTrailersFeature", + "IItemsFeature", "IQueryFeature", "IFormFeature", + "IHttpAuthenticationFeature", + "IHttpRequestIdentifierFeature", }; var sometimesFeatures = new[] { - "IHttpUpgradeFeature", - "IHttp2StreamIdFeature", - "IHttpResponseTrailersFeature", + "IHttpConnectionFeature", + "ISessionFeature", "IResponseCookiesFeature", - "IItemsFeature", + "IHttpRequestTrailersFeature", + "IHttpResponseTrailersFeature", "ITlsConnectionFeature", - "IHttpWebSocketFeature", - "ISessionFeature", + "IHttpUpgradeFeature", + "IHttpWebSocketFeature" + }; + var maybeFeatures = new[] + { + "IHttp2StreamIdFeature", + "IRequestBodyPipeFeature", + "IHttpRequestLifetimeFeature", "IHttpMaxRequestBodySizeFeature", "IHttpMinRequestBodyDataRateFeature", "IHttpMinResponseDataRateFeature", "IHttpBodyControlFeature", + "IHttpRequestBodyDetectionFeature", "IHttpResetFeature" }; var allFeatures = alwaysFeatures .Concat(commonFeatures) .Concat(sometimesFeatures) + .Concat(maybeFeatures) .ToArray(); // NOTE: This list MUST always match the set of feature interfaces implemented by HttpProtocol. @@ -59,20 +63,20 @@ public static string GenerateFile() var implementedFeatures = new[] { "IHttpRequestFeature", - "IHttpRequestBodyDetectionFeature", "IHttpResponseFeature", "IHttpResponseBodyFeature", - "IRequestBodyPipeFeature", - "IHttpUpgradeFeature", + "IRouteValuesFeature", + "IEndpointFeature", "IHttpRequestIdentifierFeature", - "IHttpRequestLifetimeFeature", "IHttpRequestTrailersFeature", + "IHttpUpgradeFeature", + "IRequestBodyPipeFeature", "IHttpConnectionFeature", + "IHttpRequestLifetimeFeature", + "IHttpBodyControlFeature", "IHttpMaxRequestBodySizeFeature", "IHttpMinRequestBodyDataRateFeature", - "IHttpBodyControlFeature", - "IRouteValuesFeature", - "IEndpointFeature" + "IHttpRequestBodyDetectionFeature", }; // NOTE: Each item in this list MUST always be reset by each protocol in their OnReset() method From 138f8b5a7637896a6407d480d8eac84942e7b46c Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 29 Mar 2021 03:03:55 +0100 Subject: [PATCH 7/9] Reorder features (order of reset); bump up IRequestBodyPipeFeature --- .../Internal/Http/HttpProtocol.Generated.cs | 63 ++++++++++--------- .../HttpProtocolFeatureCollection.cs | 14 ++--- .../shared/TransportConnection.Generated.cs | 3 + ...ransportMultiplexedConnection.Generated.cs | 5 +- .../FeatureCollectionGenerator.cs | 9 ++- .../HttpProtocolFeatureCollection.cs | 2 +- 6 files changed, 55 insertions(+), 41 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index 2e6136cb5d54..d85e7e418e9c 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -16,33 +16,36 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { internal partial class HttpProtocol : IFeatureCollection { + // Implemented features internal protected IHttpRequestFeature? _currentIHttpRequestFeature; internal protected IHttpResponseFeature? _currentIHttpResponseFeature; internal protected IHttpResponseBodyFeature? _currentIHttpResponseBodyFeature; internal protected IRouteValuesFeature? _currentIRouteValuesFeature; internal protected IEndpointFeature? _currentIEndpointFeature; + internal protected IHttpRequestIdentifierFeature? _currentIHttpRequestIdentifierFeature; + internal protected IHttpRequestTrailersFeature? _currentIHttpRequestTrailersFeature; + internal protected IHttpUpgradeFeature? _currentIHttpUpgradeFeature; + internal protected IRequestBodyPipeFeature? _currentIRequestBodyPipeFeature; + internal protected IHttpConnectionFeature? _currentIHttpConnectionFeature; + internal protected IHttpRequestLifetimeFeature? _currentIHttpRequestLifetimeFeature; + internal protected IHttpBodyControlFeature? _currentIHttpBodyControlFeature; + internal protected IHttpMaxRequestBodySizeFeature? _currentIHttpMaxRequestBodySizeFeature; + internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; + internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; + + // Other reserved feature slots internal protected IServiceProvidersFeature? _currentIServiceProvidersFeature; internal protected IItemsFeature? _currentIItemsFeature; internal protected IQueryFeature? _currentIQueryFeature; internal protected IFormFeature? _currentIFormFeature; internal protected IHttpAuthenticationFeature? _currentIHttpAuthenticationFeature; - internal protected IHttpRequestIdentifierFeature? _currentIHttpRequestIdentifierFeature; - internal protected IHttpConnectionFeature? _currentIHttpConnectionFeature; internal protected ISessionFeature? _currentISessionFeature; internal protected IResponseCookiesFeature? _currentIResponseCookiesFeature; - internal protected IHttpRequestTrailersFeature? _currentIHttpRequestTrailersFeature; internal protected IHttpResponseTrailersFeature? _currentIHttpResponseTrailersFeature; internal protected ITlsConnectionFeature? _currentITlsConnectionFeature; - internal protected IHttpUpgradeFeature? _currentIHttpUpgradeFeature; internal protected IHttpWebSocketFeature? _currentIHttpWebSocketFeature; internal protected IHttp2StreamIdFeature? _currentIHttp2StreamIdFeature; - internal protected IRequestBodyPipeFeature? _currentIRequestBodyPipeFeature; - internal protected IHttpRequestLifetimeFeature? _currentIHttpRequestLifetimeFeature; - internal protected IHttpMaxRequestBodySizeFeature? _currentIHttpMaxRequestBodySizeFeature; - internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; internal protected IHttpMinResponseDataRateFeature? _currentIHttpMinResponseDataRateFeature; - internal protected IHttpBodyControlFeature? _currentIHttpBodyControlFeature; - internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; internal protected IHttpResetFeature? _currentIHttpResetFeature; private int _featureRevision; @@ -182,6 +185,10 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIQueryFeature; } + else if (key == typeof(IRequestBodyPipeFeature)) + { + feature = _currentIRequestBodyPipeFeature; + } else if (key == typeof(IFormFeature)) { feature = _currentIFormFeature; @@ -230,10 +237,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = _currentIHttp2StreamIdFeature; } - else if (key == typeof(IRequestBodyPipeFeature)) - { - feature = _currentIRequestBodyPipeFeature; - } else if (key == typeof(IHttpRequestLifetimeFeature)) { feature = _currentIHttpRequestLifetimeFeature; @@ -306,6 +309,10 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIQueryFeature = (IQueryFeature?)value; } + else if (key == typeof(IRequestBodyPipeFeature)) + { + _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)value; + } else if (key == typeof(IFormFeature)) { _currentIFormFeature = (IFormFeature?)value; @@ -354,10 +361,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttp2StreamIdFeature = (IHttp2StreamIdFeature?)value; } - else if (key == typeof(IRequestBodyPipeFeature)) - { - _currentIRequestBodyPipeFeature = (IRequestBodyPipeFeature?)value; - } else if (key == typeof(IHttpRequestLifetimeFeature)) { _currentIHttpRequestLifetimeFeature = (IHttpRequestLifetimeFeature?)value; @@ -432,6 +435,10 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIQueryFeature); } + else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) + { + feature = Unsafe.As(ref _currentIRequestBodyPipeFeature); + } else if (typeof(TFeature) == typeof(IFormFeature)) { feature = Unsafe.As(ref _currentIFormFeature); @@ -480,10 +487,6 @@ private void ExtraFeatureSet(Type key, object? value) { feature = Unsafe.As(ref _currentIHttp2StreamIdFeature); } - else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) - { - feature = Unsafe.As(ref _currentIRequestBodyPipeFeature); - } else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) { feature = Unsafe.As(ref _currentIHttpRequestLifetimeFeature); @@ -564,6 +567,10 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIQueryFeature = Unsafe.As(ref feature); } + else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) + { + _currentIRequestBodyPipeFeature = Unsafe.As(ref feature); + } else if (typeof(TFeature) == typeof(IFormFeature)) { _currentIFormFeature = Unsafe.As(ref feature); @@ -612,10 +619,6 @@ private void ExtraFeatureSet(Type key, object? value) { _currentIHttp2StreamIdFeature = Unsafe.As(ref feature); } - else if (typeof(TFeature) == typeof(IRequestBodyPipeFeature)) - { - _currentIRequestBodyPipeFeature = Unsafe.As(ref feature); - } else if (typeof(TFeature) == typeof(IHttpRequestLifetimeFeature)) { _currentIHttpRequestLifetimeFeature = Unsafe.As(ref feature); @@ -684,6 +687,10 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IQueryFeature), _currentIQueryFeature); } + if (_currentIRequestBodyPipeFeature != null) + { + yield return new KeyValuePair(typeof(IRequestBodyPipeFeature), _currentIRequestBodyPipeFeature); + } if (_currentIFormFeature != null) { yield return new KeyValuePair(typeof(IFormFeature), _currentIFormFeature); @@ -732,10 +739,6 @@ private IEnumerable> FastEnumerable() { yield return new KeyValuePair(typeof(IHttp2StreamIdFeature), _currentIHttp2StreamIdFeature); } - if (_currentIRequestBodyPipeFeature != null) - { - yield return new KeyValuePair(typeof(IRequestBodyPipeFeature), _currentIRequestBodyPipeFeature); - } if (_currentIHttpRequestLifetimeFeature != null) { yield return new KeyValuePair(typeof(IHttpRequestLifetimeFeature), _currentIHttpRequestLifetimeFeature); diff --git a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs index a50bfaf4b243..ee0fc5c7f45e 100644 --- a/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/perf/Microbenchmarks/HttpProtocolFeatureCollection.cs @@ -77,6 +77,13 @@ public IQueryFeature Get_IQueryFeature() return _collection.Get(); } + [Benchmark(Description = "Get*")] + [MethodImpl(MethodImplOptions.NoInlining)] + public IRequestBodyPipeFeature Get_IRequestBodyPipeFeature() + { + return _collection.Get(); + } + [Benchmark(Description = "Get")] [MethodImpl(MethodImplOptions.NoInlining)] public IFormFeature Get_IFormFeature() @@ -161,13 +168,6 @@ public IHttp2StreamIdFeature Get_IHttp2StreamIdFeature() return _collection.Get(); } - [Benchmark(Description = "Get*")] - [MethodImpl(MethodImplOptions.NoInlining)] - public IRequestBodyPipeFeature Get_IRequestBodyPipeFeature() - { - return _collection.Get(); - } - [Benchmark(Description = "Get*")] [MethodImpl(MethodImplOptions.NoInlining)] public IHttpRequestLifetimeFeature Get_IHttpRequestLifetimeFeature() diff --git a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs index 2d797a462cd0..0110086fa2b8 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs @@ -15,12 +15,15 @@ namespace Microsoft.AspNetCore.Connections { internal partial class TransportConnection : IFeatureCollection { + // Implemented features internal protected IConnectionIdFeature? _currentIConnectionIdFeature; internal protected IConnectionTransportFeature? _currentIConnectionTransportFeature; internal protected IConnectionItemsFeature? _currentIConnectionItemsFeature; internal protected IMemoryPoolFeature? _currentIMemoryPoolFeature; internal protected IConnectionLifetimeFeature? _currentIConnectionLifetimeFeature; + // Other reserved feature slots + private int _featureRevision; private List>? MaybeExtra; diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs index bee6c1917014..61d06523f0ad 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs @@ -15,12 +15,15 @@ namespace Microsoft.AspNetCore.Connections { internal partial class TransportMultiplexedConnection : IFeatureCollection { + // Implemented features internal protected IConnectionIdFeature? _currentIConnectionIdFeature; - internal protected IConnectionTransportFeature? _currentIConnectionTransportFeature; internal protected IConnectionItemsFeature? _currentIConnectionItemsFeature; internal protected IMemoryPoolFeature? _currentIMemoryPoolFeature; internal protected IConnectionLifetimeFeature? _currentIConnectionLifetimeFeature; + // Other reserved feature slots + internal protected IConnectionTransportFeature? _currentIConnectionTransportFeature; + private int _featureRevision; private List>? MaybeExtra; diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index b94ccffbc421..6fe3c8e7ee57 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -33,8 +33,13 @@ public static string GenerateFile(string namespaceName, string className, string namespace {namespaceName} {{ internal partial class {className} : IFeatureCollection - {{{Each(features, feature => $@" - internal protected {feature.Name}? _current{feature.Name};")} + {{ + // Implemented features{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@" + internal protected {feature}? _current{feature};")}{Each(implementedFeatures.Where(f => skipResetFeatures.Contains(f)), feature => $@" + internal protected {feature}? _current{feature};")} + + // Other reserved feature slots{Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" + internal protected {feature}? _current{feature};")} private int _featureRevision; diff --git a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs index 70e7a667c0ec..35a10f9a78df 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs @@ -23,6 +23,7 @@ public static string GenerateFile() { "IItemsFeature", "IQueryFeature", + "IRequestBodyPipeFeature", "IFormFeature", "IHttpAuthenticationFeature", "IHttpRequestIdentifierFeature", @@ -42,7 +43,6 @@ public static string GenerateFile() var maybeFeatures = new[] { "IHttp2StreamIdFeature", - "IRequestBodyPipeFeature", "IHttpRequestLifetimeFeature", "IHttpMaxRequestBodySizeFeature", "IHttpMinRequestBodyDataRateFeature", From cba981fe645662d8526f33f5c0a34b383823c6ad Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 29 Mar 2021 04:05:44 +0100 Subject: [PATCH 8/9] Move interface implement on class to generated (to match order) --- .../Http/HttpProtocol.FeatureCollection.cs | 18 +++--------------- .../Internal/Http/HttpProtocol.Generated.cs | 16 +++++++++++++++- .../TransportConnection.FeatureCollection.cs | 9 +++------ .../shared/TransportConnection.Generated.cs | 9 ++++++--- ...tMultiplexedConnection.FeatureCollection.cs | 9 +++------ ...TransportMultiplexedConnection.Generated.cs | 6 +++++- .../FeatureCollectionGenerator.cs | 7 ++++--- 7 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs index 14311aed6754..7dac07e16956 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs @@ -16,23 +16,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { - internal partial class HttpProtocol : IHttpRequestFeature, - IHttpResponseFeature, - IHttpResponseBodyFeature, - IRouteValuesFeature, - IEndpointFeature, - IHttpRequestIdentifierFeature, - IHttpRequestTrailersFeature, - IHttpUpgradeFeature, - IRequestBodyPipeFeature, - IHttpConnectionFeature, - IHttpRequestLifetimeFeature, - IHttpBodyControlFeature, - IHttpMaxRequestBodySizeFeature, - IHttpRequestBodyDetectionFeature + internal partial class HttpProtocol { // NOTE: When feature interfaces are added to or removed from this HttpProtocol class implementation, - // then the list of `implementedFeatures` in the generated code project MUST also be updated. + // then the list of `implementedFeatures` in the generated code project MUST also be updated first + // and the code generator re-reun, which will change the interface list. // See also: tools/CodeGenerator/HttpProtocolFeatureCollection.cs string IHttpRequestFeature.Protocol diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index d85e7e418e9c..8436bfc306ee 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -14,7 +14,21 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http { - internal partial class HttpProtocol : IFeatureCollection + internal partial class HttpProtocol : IFeatureCollection, + IHttpRequestFeature, + IHttpResponseFeature, + IHttpResponseBodyFeature, + IRouteValuesFeature, + IEndpointFeature, + IHttpRequestIdentifierFeature, + IHttpRequestTrailersFeature, + IHttpUpgradeFeature, + IRequestBodyPipeFeature, + IHttpConnectionFeature, + IHttpRequestLifetimeFeature, + IHttpBodyControlFeature, + IHttpMaxRequestBodySizeFeature, + IHttpRequestBodyDetectionFeature { // Implemented features internal protected IHttpRequestFeature? _currentIHttpRequestFeature; diff --git a/src/Servers/Kestrel/shared/TransportConnection.FeatureCollection.cs b/src/Servers/Kestrel/shared/TransportConnection.FeatureCollection.cs index 5d94f6e3c485..757927e2f433 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.FeatureCollection.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.FeatureCollection.cs @@ -11,14 +11,11 @@ namespace Microsoft.AspNetCore.Connections { - internal partial class TransportConnection : IConnectionIdFeature, - IConnectionTransportFeature, - IConnectionItemsFeature, - IMemoryPoolFeature, - IConnectionLifetimeFeature + internal partial class TransportConnection { // NOTE: When feature interfaces are added to or removed from this TransportConnection class implementation, - // then the list of `features` in the generated code project MUST also be updated. + // then the list of `features` in the generated code project MUST also be updated first + // and the code generator re-reun, which will change the interface list. // See also: tools/CodeGenerator/TransportConnectionFeatureCollection.cs MemoryPool IMemoryPoolFeature.MemoryPool => MemoryPool; diff --git a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs index 0110086fa2b8..0f32b7d54549 100644 --- a/src/Servers/Kestrel/shared/TransportConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportConnection.Generated.cs @@ -13,7 +13,12 @@ namespace Microsoft.AspNetCore.Connections { - internal partial class TransportConnection : IFeatureCollection + internal partial class TransportConnection : IFeatureCollection, + IConnectionIdFeature, + IConnectionTransportFeature, + IConnectionItemsFeature, + IMemoryPoolFeature, + IConnectionLifetimeFeature { // Implemented features internal protected IConnectionIdFeature? _currentIConnectionIdFeature; @@ -22,8 +27,6 @@ internal partial class TransportConnection : IFeatureCollection internal protected IMemoryPoolFeature? _currentIMemoryPoolFeature; internal protected IConnectionLifetimeFeature? _currentIConnectionLifetimeFeature; - // Other reserved feature slots - private int _featureRevision; private List>? MaybeExtra; diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.FeatureCollection.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.FeatureCollection.cs index 7edfc98014b9..918903b4bbe0 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.FeatureCollection.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.FeatureCollection.cs @@ -3,19 +3,16 @@ using System.Buffers; using System.Collections.Generic; -using System.IO.Pipelines; using System.Threading; using Microsoft.AspNetCore.Connections.Features; namespace Microsoft.AspNetCore.Connections { - internal partial class TransportMultiplexedConnection : IConnectionIdFeature, - IConnectionItemsFeature, - IMemoryPoolFeature, - IConnectionLifetimeFeature + internal partial class TransportMultiplexedConnection { // NOTE: When feature interfaces are added to or removed from this TransportConnection class implementation, - // then the list of `features` in the generated code project MUST also be updated. + // then the list of `features` in the generated code project MUST also be updated first + // and the code generator re-reun, which will change the interface list. // See also: tools/CodeGenerator/TransportConnectionFeatureCollection.cs MemoryPool IMemoryPoolFeature.MemoryPool => MemoryPool; diff --git a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs index 61d06523f0ad..5be4c4c48cc8 100644 --- a/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs +++ b/src/Servers/Kestrel/shared/TransportMultiplexedConnection.Generated.cs @@ -13,7 +13,11 @@ namespace Microsoft.AspNetCore.Connections { - internal partial class TransportMultiplexedConnection : IFeatureCollection + internal partial class TransportMultiplexedConnection : IFeatureCollection, + IConnectionIdFeature, + IConnectionItemsFeature, + IMemoryPoolFeature, + IConnectionLifetimeFeature { // Implemented features internal protected IConnectionIdFeature? _currentIConnectionIdFeature; diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index 6fe3c8e7ee57..d9fd2a0596ac 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -32,13 +32,14 @@ public static string GenerateFile(string namespaceName, string className, string namespace {namespaceName} {{ - internal partial class {className} : IFeatureCollection + internal partial class {className} : IFeatureCollection{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@", + {new string(' ', className.Length)}{feature}")} {{ // Implemented features{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@" internal protected {feature}? _current{feature};")}{Each(implementedFeatures.Where(f => skipResetFeatures.Contains(f)), feature => $@" - internal protected {feature}? _current{feature};")} + internal protected {feature}? _current{feature};")}{(allFeatures.Where(f => !implementedFeatures.Contains(f)).FirstOrDefault() is not null ? @" - // Other reserved feature slots{Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" + // Other reserved feature slots" : "")}{Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" internal protected {feature}? _current{feature};")} private int _featureRevision; From 413bc5ba4812cd1beaaa570a5f27497ad71b45aa Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Mon, 29 Mar 2021 04:28:26 +0100 Subject: [PATCH 9/9] Remove skip features (always null) --- .../Core/src/Internal/Http/HttpProtocol.Generated.cs | 3 ++- .../tools/CodeGenerator/FeatureCollectionGenerator.cs | 9 ++++----- .../tools/CodeGenerator/HttpProtocolFeatureCollection.cs | 8 -------- .../TransportConnectionFeatureCollection.cs | 1 - .../TransportMultiplexedConnectionFeatureCollection.cs | 1 - 5 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs index 8436bfc306ee..1cc8eea7c01c 100644 --- a/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs +++ b/src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.Generated.cs @@ -45,7 +45,6 @@ internal partial class HttpProtocol : IFeatureCollection, internal protected IHttpBodyControlFeature? _currentIHttpBodyControlFeature; internal protected IHttpMaxRequestBodySizeFeature? _currentIHttpMaxRequestBodySizeFeature; internal protected IHttpRequestBodyDetectionFeature? _currentIHttpRequestBodyDetectionFeature; - internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; // Other reserved feature slots internal protected IServiceProvidersFeature? _currentIServiceProvidersFeature; @@ -59,6 +58,7 @@ internal partial class HttpProtocol : IFeatureCollection, internal protected ITlsConnectionFeature? _currentITlsConnectionFeature; internal protected IHttpWebSocketFeature? _currentIHttpWebSocketFeature; internal protected IHttp2StreamIdFeature? _currentIHttp2StreamIdFeature; + internal protected IHttpMinRequestBodyDataRateFeature? _currentIHttpMinRequestBodyDataRateFeature; internal protected IHttpMinResponseDataRateFeature? _currentIHttpMinResponseDataRateFeature; internal protected IHttpResetFeature? _currentIHttpResetFeature; @@ -94,6 +94,7 @@ private void FastReset() _currentITlsConnectionFeature = null; _currentIHttpWebSocketFeature = null; _currentIHttp2StreamIdFeature = null; + _currentIHttpMinRequestBodyDataRateFeature = null; _currentIHttpMinResponseDataRateFeature = null; _currentIHttpResetFeature = null; } diff --git a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs index d9fd2a0596ac..f8f4ad91b64a 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/FeatureCollectionGenerator.cs @@ -9,7 +9,7 @@ namespace CodeGenerator { public static class FeatureCollectionGenerator { - public static string GenerateFile(string namespaceName, string className, string[] allFeatures, string[] implementedFeatures, string[] skipResetFeatures, string extraUsings, string fallbackFeatures) + public static string GenerateFile(string namespaceName, string className, string[] allFeatures, string[] implementedFeatures, string extraUsings, string fallbackFeatures) { // NOTE: This list MUST always match the set of feature interfaces implemented by TransportConnection. // See also: src/Kestrel/Http/TransportConnection.FeatureCollection.cs @@ -32,11 +32,10 @@ public static string GenerateFile(string namespaceName, string className, string namespace {namespaceName} {{ - internal partial class {className} : IFeatureCollection{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@", + internal partial class {className} : IFeatureCollection{Each(implementedFeatures, feature => $@", {new string(' ', className.Length)}{feature}")} {{ - // Implemented features{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@" - internal protected {feature}? _current{feature};")}{Each(implementedFeatures.Where(f => skipResetFeatures.Contains(f)), feature => $@" + // Implemented features{Each(implementedFeatures, feature => $@" internal protected {feature}? _current{feature};")}{(allFeatures.Where(f => !implementedFeatures.Contains(f)).FirstOrDefault() is not null ? @" // Other reserved feature slots" : "")}{Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" @@ -47,7 +46,7 @@ internal partial class {className} : IFeatureCollection{Each(implementedFeatures private List>? MaybeExtra; private void FastReset() - {{{Each(implementedFeatures.Where(f => !skipResetFeatures.Contains(f)), feature => $@" + {{{Each(implementedFeatures, feature => $@" _current{feature} = this;")} {Each(allFeatures.Where(f => !implementedFeatures.Contains(f)), feature => $@" _current{feature} = null;")} diff --git a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs index 35a10f9a78df..fb793e76b8f5 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/HttpProtocolFeatureCollection.cs @@ -75,16 +75,9 @@ public static string GenerateFile() "IHttpRequestLifetimeFeature", "IHttpBodyControlFeature", "IHttpMaxRequestBodySizeFeature", - "IHttpMinRequestBodyDataRateFeature", "IHttpRequestBodyDetectionFeature", }; - // NOTE: Each item in this list MUST always be reset by each protocol in their OnReset() method - var skipResetFeatures = new[] - { - "IHttpMinRequestBodyDataRateFeature" - }; - var usings = $@" using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features.Authentication; @@ -95,7 +88,6 @@ public static string GenerateFile() className: "HttpProtocol", allFeatures: allFeatures, implementedFeatures: implementedFeatures, - skipResetFeatures: skipResetFeatures, extraUsings: usings, fallbackFeatures: "ConnectionFeatures"); } diff --git a/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs index 780ad7e2779a..60d00f404a2b 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/TransportConnectionFeatureCollection.cs @@ -29,7 +29,6 @@ public static string GenerateFile() className: "TransportConnection", allFeatures: features, implementedFeatures: features, - skipResetFeatures: Array.Empty(), extraUsings: usings, fallbackFeatures: null); } diff --git a/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs b/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs index 8ff51ad61566..b9296cac82bd 100644 --- a/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs +++ b/src/Servers/Kestrel/tools/CodeGenerator/TransportMultiplexedConnectionFeatureCollection.cs @@ -36,7 +36,6 @@ public static string GenerateFile() className: "TransportMultiplexedConnection", allFeatures: allFeatures, implementedFeatures: implementedFeatures, - skipResetFeatures: Array.Empty(), extraUsings: usings, fallbackFeatures: null); }