Avoid multiple exceptions at startup from MsQuic support tests (#49973)
authorStephen Toub <stoub@microsoft.com>
Wed, 24 Mar 2021 21:24:43 +0000 (17:24 -0400)
committerGitHub <noreply@github.com>
Wed, 24 Mar 2021 21:24:43 +0000 (17:24 -0400)
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs
src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs [deleted file]
src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicNativeMethods.cs

index d483c76..b52b482 100644 (file)
@@ -18,23 +18,8 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
 
         private readonly IntPtr _registrationContext;
 
-        private unsafe MsQuicApi()
+        private unsafe MsQuicApi(MsQuicNativeMethods.NativeApi* registration)
         {
-            MsQuicNativeMethods.NativeApi* registration;
-
-            try
-            {
-                uint status = Interop.MsQuic.MsQuicOpen(out registration);
-                if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
-                {
-                    throw new NotSupportedException(SR.net_quic_notsupported);
-                }
-            }
-            catch (DllNotFoundException)
-            {
-                throw new NotSupportedException(SR.net_quic_notsupported);
-            }
-
             MsQuicNativeMethods.NativeApi nativeRegistration = *registration;
 
             RegistrationOpenDelegate =
@@ -138,7 +123,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
 
         internal static bool IsQuicSupported { get; }
 
-        static MsQuicApi()
+        static unsafe MsQuicApi()
         {
             // MsQuicOpen will succeed even if the platform will not support it. It will then fail with unspecified
             // platform-specific errors in subsequent callbacks. For now, check for the minimum build we've tested it on.
@@ -150,14 +135,30 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
 
             // TODO: try to initialize TLS 1.3 in SslStream.
 
-            try
-            {
-                Api = new MsQuicApi();
-                IsQuicSupported = true;
-            }
-            catch (NotSupportedException)
+            // TODO: Consider updating all of these delegates to instead use function pointers.
+
+            if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, out IntPtr msQuicHandle))
             {
-                IsQuicSupported = false;
+                try
+                {
+                    if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpen", out IntPtr msQuicOpenAddress))
+                    {
+                        MsQuicNativeMethods.MsQuicOpenDelegate msQuicOpen = Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.MsQuicOpenDelegate>(msQuicOpenAddress);
+                        uint status = msQuicOpen(out MsQuicNativeMethods.NativeApi* registration);
+                        if (MsQuicStatusHelper.SuccessfulStatusCode(status))
+                        {
+                            IsQuicSupported = true;
+                            Api = new MsQuicApi(registration);
+                        }
+                    }
+                }
+                finally
+                {
+                    if (!IsQuicSupported)
+                    {
+                        NativeLibrary.Free(msQuicHandle);
+                    }
+                }
             }
         }
 
diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs
deleted file mode 100644 (file)
index b873b78..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// 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.Net.Quic.Implementations.MsQuic.Internal;
-using System.Runtime.InteropServices;
-
-internal static partial class Interop
-{
-    internal static class MsQuic
-    {
-        [DllImport(Libraries.MsQuic, CallingConvention = CallingConvention.Cdecl)]
-        internal static unsafe extern uint MsQuicOpen(out MsQuicNativeMethods.NativeApi* registration);
-    }
-}
index c8ff6d6..3027c40 100644 (file)
@@ -55,6 +55,10 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
         }
 
         [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+        internal delegate uint MsQuicOpenDelegate(
+            out NativeApi* registration);
+
+        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         internal delegate uint SetContextDelegate(
             IntPtr handle,
             IntPtr context);