Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;

namespace System.Net.Http
{
Expand Down Expand Up @@ -38,12 +39,16 @@ internal static class SocketsHttpHandler
"DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP2SUPPORT",
true);

// Default to allowing HTTP/3, but enable that to be overridden by an
// Default to allowing HTTP/3 on platforms where we have QUIC, but enable that to be overridden by an
// AppContext switch, or by an environment variable being set to false/0.
[SupportedOSPlatformGuard("linux")]
[SupportedOSPlatformGuard("macOS")]
[SupportedOSPlatformGuard("windows")]
[FeatureSwitchDefinition("System.Net.SocketsHttpHandler.Http3Support")]
public static bool AllowHttp3 { get; } = RuntimeSettingParser.QueryRuntimeSettingSwitch(
"System.Net.SocketsHttpHandler.Http3Support",
"DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORT",
true);
(OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS());

// Switch to disable the HTTP/2 dynamic window scaling algorithm. Enabled by default.
public static bool DisableDynamicHttp2WindowSizing { get; } = RuntimeSettingParser.QueryRuntimeSettingSwitch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ internal sealed partial class HttpConnectionPool
/// <summary>The time, in milliseconds, that an authority should remain in <see cref="_altSvcBlocklist"/>.</summary>
private const int AltSvcBlocklistTimeoutInMilliseconds = 10 * 60 * 1000;

[SupportedOSPlatformGuard("linux")]
[SupportedOSPlatformGuard("macOS")]
[SupportedOSPlatformGuard("windows")]
internal static bool IsHttp3Supported() => (OperatingSystem.IsLinux() && !OperatingSystem.IsAndroid()) || OperatingSystem.IsWindows() || OperatingSystem.IsMacOS();

/// <summary>List of available HTTP/3 connections stored in the pool.</summary>
private List<Http3Connection>? _availableHttp3Connections;
/// <summary>The number of HTTP/3 connections associated with the pool, including in use, available, and pending.</summary>
Expand Down Expand Up @@ -67,7 +62,7 @@ internal sealed partial class HttpConnectionPool
[SupportedOSPlatform("macos")]
private async ValueTask<HttpResponseMessage?> TrySendUsingHttp3Async(HttpRequestMessage request, CancellationToken cancellationToken)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

Debug.Assert(_kind == HttpConnectionKind.Https);
Debug.Assert(_http3Enabled);
Expand Down Expand Up @@ -135,7 +130,7 @@ internal sealed partial class HttpConnectionPool
[SupportedOSPlatform("macos")]
private bool TryGetPooledHttp3Connection(HttpRequestMessage request, [NotNullWhen(true)] out Http3Connection? connection, [NotNullWhen(false)] out HttpConnectionWaiter<Http3Connection?>? waiter, out bool streamAvailable)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

// Look for a usable connection.
while (true)
Expand Down Expand Up @@ -210,7 +205,7 @@ private bool TryGetPooledHttp3Connection(HttpRequestMessage request, [NotNullWhe
[SupportedOSPlatform("macos")]
private void CheckForHttp3ConnectionInjection()
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

Debug.Assert(HasSyncObjLock);

Expand Down Expand Up @@ -249,7 +244,7 @@ private void CheckForHttp3ConnectionInjection()
[SupportedOSPlatform("macos")]
private async Task InjectNewHttp3ConnectionAsync(RequestQueue<Http3Connection?>.QueueItem queueItem)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

if (NetEventSource.Log.IsEnabled()) Trace("Creating new HTTP/3 connection for pool.");

Expand Down Expand Up @@ -332,7 +327,7 @@ private async Task InjectNewHttp3ConnectionAsync(RequestQueue<Http3Connection?>.
[SupportedOSPlatform("macos")]
private void HandleHttp3ConnectionFailure(HttpConnectionWaiter<Http3Connection?> requestWaiter, Exception? e)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

if (NetEventSource.Log.IsEnabled()) Trace($"HTTP3 connection failed: {e}");

Expand Down Expand Up @@ -363,7 +358,7 @@ private void HandleHttp3ConnectionFailure(HttpConnectionWaiter<Http3Connection?>
[SupportedOSPlatform("macos")]
private void ReturnHttp3Connection(Http3Connection connection, bool isNewConnection, HttpConnectionWaiter<Http3Connection?>? initialRequestWaiter = null)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(isNewConnection)}={isNewConnection}");

Expand Down Expand Up @@ -485,7 +480,7 @@ private void ReturnHttp3Connection(Http3Connection connection, bool isNewConnect
[SupportedOSPlatform("macos")]
private void DisableHttp3Connection(Http3Connection connection)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

if (NetEventSource.Log.IsEnabled()) connection.Trace("");

Expand Down Expand Up @@ -528,7 +523,7 @@ async Task DisableHttp3ConnectionAsync(Http3Connection connection)
[SupportedOSPlatform("macos")]
public void InvalidateHttp3Connection(Http3Connection connection, bool dispose = true)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

if (NetEventSource.Log.IsEnabled()) connection.Trace("");

Expand Down Expand Up @@ -564,7 +559,7 @@ public void InvalidateHttp3Connection(Http3Connection connection, bool dispose =
[SupportedOSPlatform("macos")]
private static int ScavengeHttp3ConnectionList(List<Http3Connection> list, ref List<HttpConnectionBase>? toDispose, long nowTicks, TimeSpan pooledConnectionLifetime, TimeSpan pooledConnectionIdleTimeout)
{
Debug.Assert(IsHttp3Supported());
Debug.Assert(GlobalHttpSettings.SocketsHttpHandler.AllowHttp3);

int freeIndex = 0;
while (freeIndex < list.Count && list[freeIndex].IsUsable(nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK

_http2Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version20;

if (IsHttp3Supported())
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3)
{
_http3Enabled = _poolManager.Settings._maxHttpVersion >= HttpVersion.Version30;
}
Expand Down Expand Up @@ -227,7 +227,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK
_http2EncodedAuthorityHostHeader = HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingToAllocatedArray(H2StaticTable.Authority, hostHeader);
}

if (IsHttp3Supported() && _http3Enabled)
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3 && _http3Enabled)
{
_http3EncodedAuthorityHostHeader = QPackEncoder.EncodeLiteralHeaderFieldWithStaticNameReferenceToArray(H3StaticTable.Authority, hostHeader);
}
Expand All @@ -244,7 +244,7 @@ public HttpConnectionPool(HttpConnectionPoolManager poolManager, HttpConnectionK
{
_http2RequestQueue = new RequestQueue<Http2Connection?>();
}
if (IsHttp3Supported() && _http3Enabled)
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3 && _http3Enabled)
{
_http3RequestQueue = new RequestQueue<Http3Connection?>();
}
Expand Down Expand Up @@ -400,7 +400,7 @@ public async ValueTask<HttpResponseMessage> SendWithVersionDetectionAndRetryAsyn
HttpResponseMessage? response = null;

// Use HTTP/3 if possible.
if (IsHttp3Supported() && // guard to enable trimming HTTP/3 support
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3 && // guard to enable trimming HTTP/3 support
_http3Enabled &&
(request.Version.Major >= 3 || (request.VersionPolicy == HttpVersionPolicy.RequestVersionOrHigher && IsSecure)) &&
!request.IsExtendedConnectRequest)
Expand Down Expand Up @@ -913,7 +913,7 @@ public void Dispose()
_availableHttp2Connections.Clear();
}

if (IsHttp3Supported() && _availableHttp3Connections is not null)
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3 && _availableHttp3Connections is not null)
{
toDispose ??= new();
toDispose.AddRange(_availableHttp3Connections);
Expand Down Expand Up @@ -989,7 +989,7 @@ public bool CleanCacheAndDisposeIfUnused()
// Note: Http11 connections will decrement the _associatedHttp11ConnectionCount when disposed.
// Http2 connections will not, hence the difference in handing _associatedHttp2ConnectionCount.
}
if (IsHttp3Supported() && _availableHttp3Connections is not null)
if (GlobalHttpSettings.SocketsHttpHandler.AllowHttp3 && _availableHttp3Connections is not null)
{
int removed = ScavengeHttp3ConnectionList(_availableHttp3Connections, ref toDispose, nowTicks, pooledConnectionLifetime, pooledConnectionIdleTimeout);
_associatedHttp3ConnectionCount -= removed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static bool QueryRuntimeSettingSwitch(string appCtxSettingName, string en
bool value;

// First check for the AppContext switch, giving it priority over the environment variable.
// This being first is important for correctness of all callers marked [FeatureSwitchDefinition].
if (AppContext.TryGetSwitch(appCtxSettingName, out value))
{
return value;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.IO;
using System.Reflection;
using System.Net;
using System.Net.Http;

try
{
_ = new HttpClient().GetStringAsync("https://bing.com").Result;
}
catch { }

try
{
var a = Assembly.Load("System.Net.Quic");
bool hasTypes = false;
foreach (var t in a.GetTypes())
{
Console.WriteLine(t);
hasTypes = true;
}

if (!hasTypes)
return 100;
}
catch (FileNotFoundException)
{
return 100;
}

return -1;
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
<TestConsoleAppSourceFiles Include="DiagnosticsHandlerTrimmedTest.cs">
<DisabledFeatureSwitches>System.Net.Http.EnableActivityPropagation</DisabledFeatureSwitches>
</TestConsoleAppSourceFiles>
<TestConsoleAppSourceFiles Include="QuicTrimmedTest.cs">
<DisabledFeatureSwitches>System.Net.SocketsHttpHandler.Http3Support</DisabledFeatureSwitches>
</TestConsoleAppSourceFiles>
</ItemGroup>

<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.targets))" />
Expand Down
Loading