From 1147c86d34c06b12ab419f4a37f663c90aa07ead Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Fri, 9 Sep 2022 10:02:54 +0200 Subject: [PATCH 1/4] Unload MsQuic after checking for QUIC support to free resources (#75163) * Revert "Revert "Unload MsQuic after checking for QUIC support to free resources. (#74749)" (#74984)" This reverts commit 953f52482ac2460e4b3faff33e4f73c9b30cd7b4. * update helix images * update helix images * Improve diagnostics when opening MsQuic Co-authored-by: Radek Zikmund --- .../libraries/helix-queues-setup.yml | 8 +- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 96 ++++++++++++++----- 2 files changed, 80 insertions(+), 24 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index cac632e79177b..875fd96f4c75f 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -39,9 +39,13 @@ jobs: # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220504035342-1b9461f + - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220906173536-06f234f - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220427172132-97d8652 + - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220906173506-06f234f + - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20220906200500-06f234f + - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: + - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20220906200540-06f234f # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index e28134ea4b6f5..e3e4728610b14 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using Microsoft.Quic; @@ -47,7 +48,8 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) } } - internal static MsQuicApi Api { get; } = null!; + private static readonly Lazy _api = new Lazy(AllocateMsQuicApi); + internal static MsQuicApi Api => _api.Value; internal static bool IsQuicSupported { get; } @@ -58,29 +60,21 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) static MsQuicApi() { - IntPtr msQuicHandle; - if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) && - !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) + if (!TryLoadMsQuic(out IntPtr msQuicHandle)) { return; } try { - if (!NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) - { - return; - } - - QUIC_API_TABLE* apiTable = null; - delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; - if (StatusFailed(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable))) + if (!TryOpenMsQuic(msQuicHandle, out QUIC_API_TABLE* apiTable, out _)) { return; } try { + // Check version int arraySize = 4; uint* libVersion = stackalloc uint[arraySize]; uint size = (uint)arraySize * sizeof(uint); @@ -99,7 +93,7 @@ static MsQuicApi() return; } - // Assume SChannel is being used on windows and query for the actual provider from the library + // Assume SChannel is being used on windows and query for the actual provider from the library if querying is supported QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; size = sizeof(QUIC_TLS_PROVIDER); apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); @@ -122,26 +116,84 @@ static MsQuicApi() Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); } - Api = new MsQuicApi(apiTable); IsQuicSupported = true; } finally { - if (!IsQuicSupported && NativeLibrary.TryGetExport(msQuicHandle, "MsQuicClose", out IntPtr msQuicClose)) - { - // Gracefully close the API table - ((delegate* unmanaged[Cdecl])msQuicClose)(apiTable); - } + // Gracefully close the API table to free resources. The API table will be allocated lazily again if needed + bool closed = TryCloseMsQuic(msQuicHandle, apiTable); + Debug.Assert(closed, "Failed to close MsQuic"); } - } finally { - if (!IsQuicSupported) + // Unload the library, we will load it again when we actually use QUIC + NativeLibrary.Free(msQuicHandle); + } + } + + private static MsQuicApi AllocateMsQuicApi() + { + Debug.Assert(IsQuicSupported); + + int openStatus = MsQuic.QUIC_STATUS_INTERNAL_ERROR; + + if (TryLoadMsQuic(out IntPtr msQuicHandle) && + TryOpenMsQuic(msQuicHandle, out QUIC_API_TABLE* apiTable, out openStatus)) + { + return new MsQuicApi(apiTable); + } + + ThrowHelper.ThrowIfMsQuicError(openStatus); + + // this should unreachable as TryOpenMsQuic returns non-success status on failure + throw new Exception("Failed to create MsQuicApi instance"); + } + + private static bool TryLoadMsQuic(out IntPtr msQuicHandle) => + NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || + NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle); + + private static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTable, out int openStatus) + { + apiTable = null; + if (!NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(null, "Failed to get MsQuicOpenVersion export in msquic library."); + } + + openStatus = MsQuic.QUIC_STATUS_NOT_FOUND; + return false; + } + + QUIC_API_TABLE* table = null; + delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; + openStatus = msQuicOpenVersion((uint)MsQuicVersion.Major, &table); + if (StatusFailed(openStatus)) + { + if (NetEventSource.Log.IsEnabled()) { - NativeLibrary.Free(msQuicHandle); + NetEventSource.Info(null, $"MsQuicOpenVersion returned {openStatus} status code."); } + + return false; + } + + apiTable = table; + return true; + } + + private static bool TryCloseMsQuic(IntPtr msQuicHandle, QUIC_API_TABLE* apiTable) + { + if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicClose", out IntPtr msQuicClose)) + { + ((delegate* unmanaged[Cdecl])msQuicClose)(apiTable); + return true; } + + return false; } private static bool IsWindowsVersionSupported() => OperatingSystem.IsWindowsVersionAtLeast(MinWindowsVersion.Major, From 67b137f2a8275ca03b63b454c158c69278b132cb Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Mon, 12 Sep 2022 21:57:27 -0700 Subject: [PATCH 2/4] Don't unload MsQuic from the process (#75441) --- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 135 +++++++----------- 1 file changed, 53 insertions(+), 82 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index e3e4728610b14..8e476eb91b146 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -20,6 +20,9 @@ internal sealed unsafe partial class MsQuicApi private static readonly Version MsQuicVersion = new Version(2, 1); + private static readonly delegate* unmanaged[Cdecl] MsQuicOpenVersion; + private static readonly delegate* unmanaged[Cdecl] MsQuicClose; + public MsQuicSafeHandle Registration { get; } public QUIC_API_TABLE* ApiTable { get; } @@ -58,119 +61,97 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) internal static bool Tls13ServerMayBeDisabled { get; } internal static bool Tls13ClientMayBeDisabled { get; } +#pragma warning disable CA1810 // Initialize all static fields in 'MsQuicApi' when those fields are declared and remove the explicit static constructor static MsQuicApi() { - if (!TryLoadMsQuic(out IntPtr msQuicHandle)) + if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) && + !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) + { + // MsQuic library not loaded + return; + } + + MsQuicOpenVersion = (delegate* unmanaged[Cdecl])NativeLibrary.GetExport(msQuicHandle, nameof(MsQuicOpenVersion)); + MsQuicClose = (delegate* unmanaged[Cdecl])NativeLibrary.GetExport(msQuicHandle, nameof(MsQuicClose)); + + if (!TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out _)) { + // Too low version of the library (likely pre-2.0) return; } try { - if (!TryOpenMsQuic(msQuicHandle, out QUIC_API_TABLE* apiTable, out _)) + // Check version + int arraySize = 4; + uint* libVersion = stackalloc uint[arraySize]; + uint size = (uint)arraySize * sizeof(uint); + if (StatusFailed(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) { return; } - try + var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); + if (version < MsQuicVersion) { - // Check version - int arraySize = 4; - uint* libVersion = stackalloc uint[arraySize]; - uint size = (uint)arraySize * sizeof(uint); - if (StatusFailed(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) + if (NetEventSource.Log.IsEnabled()) { - return; - } - - var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); - if (version < MsQuicVersion) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); - } - return; + NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); } + return; + } - // Assume SChannel is being used on windows and query for the actual provider from the library if querying is supported - QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; - size = sizeof(QUIC_TLS_PROVIDER); - apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); - UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL; + // Assume SChannel is being used on windows and query for the actual provider from the library if querying is supported + QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; + size = sizeof(QUIC_TLS_PROVIDER); + apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); + UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL; - if (UsesSChannelBackend) + if (UsesSChannelBackend) + { + // Implies windows platform, check TLS1.3 availability + if (!IsWindowsVersionSupported()) { - // Implies windows platform, check TLS1.3 availability - if (!IsWindowsVersionSupported()) + if (NetEventSource.Log.IsEnabled()) { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); - } - - return; + NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); } - Tls13ServerMayBeDisabled = IsTls13Disabled(isServer: true); - Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); + return; } - IsQuicSupported = true; - } - finally - { - // Gracefully close the API table to free resources. The API table will be allocated lazily again if needed - bool closed = TryCloseMsQuic(msQuicHandle, apiTable); - Debug.Assert(closed, "Failed to close MsQuic"); + Tls13ServerMayBeDisabled = IsTls13Disabled(isServer: true); + Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); } + + IsQuicSupported = true; } finally { - // Unload the library, we will load it again when we actually use QUIC - NativeLibrary.Free(msQuicHandle); + // Gracefully close the API table to free resources. The API table will be allocated lazily again if needed + MsQuicClose(apiTable); } } +#pragma warning restore CA1810 private static MsQuicApi AllocateMsQuicApi() { Debug.Assert(IsQuicSupported); - int openStatus = MsQuic.QUIC_STATUS_INTERNAL_ERROR; - - if (TryLoadMsQuic(out IntPtr msQuicHandle) && - TryOpenMsQuic(msQuicHandle, out QUIC_API_TABLE* apiTable, out openStatus)) + if (!TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out int openStatus)) { - return new MsQuicApi(apiTable); + throw ThrowHelper.GetExceptionForMsQuicStatus(openStatus); } - ThrowHelper.ThrowIfMsQuicError(openStatus); - - // this should unreachable as TryOpenMsQuic returns non-success status on failure - throw new Exception("Failed to create MsQuicApi instance"); + return new MsQuicApi(apiTable); } - private static bool TryLoadMsQuic(out IntPtr msQuicHandle) => - NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || - NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle); - - private static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTable, out int openStatus) + private static bool TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out int openStatus) { - apiTable = null; - if (!NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(null, "Failed to get MsQuicOpenVersion export in msquic library."); - } - - openStatus = MsQuic.QUIC_STATUS_NOT_FOUND; - return false; - } + Debug.Assert(MsQuicOpenVersion != null); QUIC_API_TABLE* table = null; - delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; - openStatus = msQuicOpenVersion((uint)MsQuicVersion.Major, &table); + openStatus = MsQuicOpenVersion((uint)MsQuicVersion.Major, &table); if (StatusFailed(openStatus)) { if (NetEventSource.Log.IsEnabled()) @@ -178,6 +159,7 @@ private static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTa NetEventSource.Info(null, $"MsQuicOpenVersion returned {openStatus} status code."); } + apiTable = null; return false; } @@ -185,17 +167,6 @@ private static bool TryOpenMsQuic(IntPtr msQuicHandle, out QUIC_API_TABLE* apiTa return true; } - private static bool TryCloseMsQuic(IntPtr msQuicHandle, QUIC_API_TABLE* apiTable) - { - if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicClose", out IntPtr msQuicClose)) - { - ((delegate* unmanaged[Cdecl])msQuicClose)(apiTable); - return true; - } - - return false; - } - private static bool IsWindowsVersionSupported() => OperatingSystem.IsWindowsVersionAtLeast(MinWindowsVersion.Major, MinWindowsVersion.Minor, MinWindowsVersion.Build, MinWindowsVersion.Revision); From d3b40840864ae0d6b16fddcdf5df0450fe7ed253 Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Tue, 13 Sep 2022 14:15:24 +0200 Subject: [PATCH 3/4] Revert helix queues change (to be done in another PR) --- eng/pipelines/libraries/helix-queues-setup.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/libraries/helix-queues-setup.yml b/eng/pipelines/libraries/helix-queues-setup.yml index 875fd96f4c75f..cac632e79177b 100644 --- a/eng/pipelines/libraries/helix-queues-setup.yml +++ b/eng/pipelines/libraries/helix-queues-setup.yml @@ -39,13 +39,9 @@ jobs: # Linux arm64 - ${{ if eq(parameters.platform, 'Linux_arm64') }}: - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220906173536-06f234f + - (Ubuntu.2204.Arm64.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-arm64v8-20220504035342-1b9461f - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220906173506-06f234f - - ${{ if or(eq(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Debian.10.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-10-helix-arm64v8-20220906200500-06f234f - - ${{ if or(ne(parameters.jobParameters.isExtraPlatforms, true), eq(parameters.jobParameters.includeAllPlatforms, true)) }}: - - (Debian.11.Arm64.Open)Ubuntu.1804.Armarch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:debian-11-helix-arm64v8-20220906200540-06f234f + - (Ubuntu.1804.ArmArch.Open)Ubuntu.1804.ArmArch.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-arm64v8-20220427172132-97d8652 # Linux musl x64 - ${{ if eq(parameters.platform, 'Linux_musl_x64') }}: From 454ce6b771bf1297e781a8a81bdd9792d702d6e2 Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Fri, 23 Sep 2022 09:53:18 +0200 Subject: [PATCH 4/4] Code review feedback --- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index 8e476eb91b146..95b3f870db5d0 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -18,7 +18,7 @@ internal sealed unsafe partial class MsQuicApi { private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000); - private static readonly Version MsQuicVersion = new Version(2, 1); + private static readonly Version MinMsQuicVersion = new Version(2, 1); private static readonly delegate* unmanaged[Cdecl] MsQuicOpenVersion; private static readonly delegate* unmanaged[Cdecl] MsQuicClose; @@ -51,8 +51,8 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) } } - private static readonly Lazy _api = new Lazy(AllocateMsQuicApi); - internal static MsQuicApi Api => _api.Value; + private static readonly Lazy s_api = new Lazy(AllocateMsQuicApi); + internal static MsQuicApi Api => s_api.Value; internal static bool IsQuicSupported { get; } @@ -64,7 +64,7 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) #pragma warning disable CA1810 // Initialize all static fields in 'MsQuicApi' when those fields are declared and remove the explicit static constructor static MsQuicApi() { - if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) && + if (!NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MinMsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle) && !NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) { // MsQuic library not loaded @@ -83,20 +83,20 @@ static MsQuicApi() try { // Check version - int arraySize = 4; - uint* libVersion = stackalloc uint[arraySize]; - uint size = (uint)arraySize * sizeof(uint); + const int ArraySize = 4; + uint* libVersion = stackalloc uint[ArraySize]; + uint size = (uint)ArraySize * sizeof(uint); if (StatusFailed(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) { return; } var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); - if (version < MsQuicVersion) + if (version < MinMsQuicVersion) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); + NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting at least '{MinMsQuicVersion}'"); } return; } @@ -151,7 +151,7 @@ private static bool TryOpenMsQuic(out QUIC_API_TABLE* apiTable, out int openStat Debug.Assert(MsQuicOpenVersion != null); QUIC_API_TABLE* table = null; - openStatus = MsQuicOpenVersion((uint)MsQuicVersion.Major, &table); + openStatus = MsQuicOpenVersion((uint)MinMsQuicVersion.Major, &table); if (StatusFailed(openStatus)) { if (NetEventSource.Log.IsEnabled())