Пример #1
0
 static MsQuicApi()
 {
     // TODO: Consider updating all of these delegates to instead use function pointers.
     if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, out IntPtr msQuicHandle))
     {
         try
         {
             if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpen", out IntPtr msQuicOpenAddress))
             {
                 MsQuicOpenDelegate msQuicOpen =
                     Marshal.GetDelegateForFunctionPointer <MsQuicOpenDelegate>(msQuicOpenAddress);
                 uint status = msQuicOpen(out NativeApi * vtable);
                 if (MsQuicStatusHelper.SuccessfulStatusCode(status))
                 {
                     IsQuicSupported = true;
                     Api             = new MsQuicApi(vtable);
                 }
             }
         }
         finally
         {
             if (!IsQuicSupported)
             {
                 NativeLibrary.Free(msQuicHandle);
             }
         }
     }
 }
Пример #2
0
        static 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.

            // TODO:
            // - Hopefully, MsQuicOpen will perform this check for us and give us a consistent error code.
            // - Otherwise, dial this in to reflect actual minimum requirements and add some sort of platform
            //   error code mapping when creating exceptions.

            // OperatingSystem ver = Environment.OSVersion;

            // if (ver.Platform == PlatformID.Win32NT && ver.Version < new Version(10, 0, 19041, 0))
            // {
            //     IsQuicSupported = false;
            //     return;
            // }

            // TODO: try to initialize TLS 1.3 in SslStream.

            try
            {
                Api             = new MsQuicApi();
                IsQuicSupported = true;
            }
            catch (NotSupportedException)
            {
                IsQuicSupported = false;
            }
        }
Пример #3
0
 internal static unsafe void SetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ulong value)
 {
     ThrowIfFailure(api.ApiTable->SetParam(
                        nativeObject.QuicHandle,
                        param,
                        sizeof(ulong),
                        (byte *)&value), "Could not set ulong");
 }
Пример #4
0
        internal static unsafe void SetSecurityConfig(MsQuicApi api, IntPtr nativeObject, uint level, uint param, IntPtr value)
        {
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = (uint)sizeof(void *),
                Buffer = (byte *)&value
            };

            MsQuicStatusException.ThrowIfFailed(api.UnsafeSetParam(nativeObject, level, param, buffer));
        }
Пример #5
0
        internal static unsafe void SetULongParam(MsQuicApi api, IntPtr nativeObject, uint level, uint param, ulong value)
        {
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = sizeof(ulong),
                Buffer = (byte *)&value
            };

            MsQuicStatusException.ThrowIfFailed(api.UnsafeGetParam(nativeObject, level, param, ref buffer));
        }
Пример #6
0
        internal static unsafe ulong GetULongParam(MsQuicApi api, IntPtr nativeObject, uint level, uint param)
        {
            byte *     ptr    = stackalloc byte[sizeof(ulong)];
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = sizeof(ulong),
                Buffer = ptr
            };

            MsQuicStatusException.ThrowIfFailed(api.UnsafeGetParam(nativeObject, level, param, ref buffer));
            return(*(ulong *)ptr);
        }
Пример #7
0
        internal static unsafe ulong GetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param)
        {
            ulong value;
            uint  valueLen = (uint)sizeof(ulong);

            uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte *)&value);

            QuicExceptionHelpers.ThrowIfFailed(status, "GetULongParam failed.");
            Debug.Assert(valueLen == sizeof(ulong));

            return(value);
        }
        internal static unsafe void SetSecurityConfig(MsQuicApi api, IntPtr nativeObject, uint level, uint param, IntPtr value)
        {
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = (uint)sizeof(void *),
                Buffer = (byte *)&value
            };

            QuicExceptionHelpers.ThrowIfFailed(
                api.UnsafeSetParam(nativeObject, level, param, buffer),
                "Could not set security configuration.");
        }
        internal static unsafe void SetUshortParam(MsQuicApi api, IntPtr nativeObject, uint level, uint param, ushort value)
        {
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = sizeof(ushort),
                Buffer = (byte *)&value
            };

            QuicExceptionHelpers.ThrowIfFailed(
                api.UnsafeSetParam(nativeObject, level, param, buffer),
                "Could not set ushort.");
        }
Пример #10
0
        internal static unsafe ushort GetUShortParam(MsQuicApi api, SafeHandle nativeObject, QUIC_PARAM_LEVEL level, uint param)
        {
            ushort value;
            uint   valueLen = (uint)sizeof(ushort);

            uint status = api.GetParamDelegate(nativeObject, level, param, ref valueLen, (byte *)&value);

            QuicExceptionHelpers.ThrowIfFailed(status, "GetUShortParam failed.");
            Debug.Assert(valueLen == sizeof(ushort));

            return(value);
        }
Пример #11
0
        internal static unsafe SOCKADDR_INET GetINetParam(MsQuicApi api, IntPtr nativeObject, uint level, uint param)
        {
            byte *     ptr    = stackalloc byte[sizeof(SOCKADDR_INET)];
            QuicBuffer buffer = new QuicBuffer
            {
                Length = (uint)sizeof(SOCKADDR_INET),
                Buffer = ptr
            };

            MsQuicStatusException.ThrowIfFailed(api.UnsafeGetParam(nativeObject, level, param, ref buffer));

            return(*(SOCKADDR_INET *)ptr);
        }
Пример #12
0
        internal static unsafe ulong GetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param)
        {
            ulong value;
            uint  valueLen = (uint)sizeof(ulong);

            ThrowIfFailure(api.ApiTable->GetParam(
                               nativeObject.QuicHandle,
                               param,
                               &valueLen,
                               (byte *)&value), "GetULongParam failed");
            Debug.Assert(valueLen == sizeof(ulong));

            return(value);
        }
        internal static unsafe ushort GetUShortParam(MsQuicApi api, IntPtr nativeObject, uint level, uint param)
        {
            byte *     ptr    = stackalloc byte[sizeof(ushort)];
            QuicBuffer buffer = new QuicBuffer()
            {
                Length = sizeof(ushort),
                Buffer = ptr
            };

            QuicExceptionHelpers.ThrowIfFailed(
                api.UnsafeGetParam(nativeObject, level, param, ref buffer),
                "Could not get ushort.");

            return(*(ushort *)ptr);
        }
Пример #14
0
        static MsQuicApi()
        {
            if (!IsHttp3Enabled())
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"HTTP/3 and QUIC is not enabled, see 'System.Net.SocketsHttpHandler.Http3Support' AppContext switch.");
                }

                return;
            }

            if (OperatingSystem.IsWindows() && !IsWindowsVersionSupported())
            {
                if (NetEventSource.Log.IsEnabled())
                {
                    NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}");
                }

                return;
            }

            if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out IntPtr msQuicHandle))
            {
                try
                {
                    if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
                    {
                        delegate * unmanaged[Cdecl] < uint, out NativeApi *, uint > msQuicOpenVersion =
                            (delegate * unmanaged[Cdecl] < uint, out NativeApi *, uint >)msQuicOpenVersionAddress;
                        uint status = msQuicOpenVersion(MsQuicVersion, out NativeApi * vtable);
                        if (MsQuicStatusHelper.SuccessfulStatusCode(status))
                        {
                            IsQuicSupported = true;
                            Api             = new MsQuicApi(vtable);
                        }
                    }
                }
                finally
                {
                    if (!IsQuicSupported)
                    {
                        NativeLibrary.Free(msQuicHandle);
                    }
                }
            }
        }
Пример #15
0
        static MsQuicApi()
        {
            if (OperatingSystem.IsWindows())
            {
                if (!IsWindowsVersionSupported())
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}");
                    }

                    return;
                }

                Tls13MayBeDisabled = IsTls13Disabled();
            }

            IntPtr msQuicHandle;

            if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
                NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle))
            {
                try
                {
                    if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
                    {
                        NativeApi *vtable;
                        delegate * unmanaged[Cdecl] < uint, NativeApi **, uint > msQuicOpenVersion =
                            (delegate * unmanaged[Cdecl] < uint, NativeApi **, uint >)msQuicOpenVersionAddress;
                        uint status = msQuicOpenVersion(MsQuicVersion, &vtable);
                        if (MsQuicStatusHelper.SuccessfulStatusCode(status))
                        {
                            IsQuicSupported = true;
                            Api             = new MsQuicApi(vtable);
                        }
                    }
                }
                finally
                {
                    if (!IsQuicSupported)
                    {
                        NativeLibrary.Free(msQuicHandle);
                    }
                }
            }
        }
Пример #16
0
        internal static unsafe void SetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param, IPEndPoint value)
        {
            Internals.SocketAddress socketAddress = IPEndPointExtensions.Serialize(value);

            // MsQuic always reads same amount of memory as if IPv6 was used, so we can't pass pointer to socketAddress.Buffer directly
            Span <byte> address = stackalloc byte[Internals.SocketAddress.IPv6AddressSize];

            socketAddress.Buffer.AsSpan(0, socketAddress.Size).CopyTo(address);
            address.Slice(socketAddress.Size).Clear();

            fixed(byte *paddress = &MemoryMarshal.GetReference(address))
            {
                QuicExceptionHelpers.ThrowIfFailed(
                    api.SetParamDelegate(nativeObject, param, (uint)address.Length, paddress),
                    "Could not set IPEndPoint");
            }
        }
Пример #17
0
        internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param)
        {
            // MsQuic always uses storage size as if IPv6 was used
            uint        valueLen = (uint)Internals.SocketAddress.IPv6AddressSize;
            Span <byte> address  = stackalloc byte[Internals.SocketAddress.IPv6AddressSize];

            fixed(byte *paddress = &MemoryMarshal.GetReference(address))
            {
                uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, paddress);

                QuicExceptionHelpers.ThrowIfFailed(status, "GetIPEndPointParam failed.");
            }

            address = address.Slice(0, (int)valueLen);

            return(new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address)
                   .GetIPEndPoint());
        }
Пример #18
0
        internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param)
        {
            // MsQuic always uses storage size as if IPv6 was used
            uint        valueLen = (uint)Internals.SocketAddress.IPv6AddressSize;
            Span <byte> address  = stackalloc byte[Internals.SocketAddress.IPv6AddressSize];

            fixed(byte *paddress = &MemoryMarshal.GetReference(address))
            {
                ThrowIfFailure(api.ApiTable->GetParam(
                                   nativeObject.QuicHandle,
                                   param,
                                   &valueLen,
                                   paddress), "GetIPEndPointParam failed.");
            }

            address = address.Slice(0, (int)valueLen);

            return(new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address).GetIPEndPoint());
        }
Пример #19
0
        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.

            // TODO:
            // - Hopefully, MsQuicOpen will perform this check for us and give us a consistent error code.
            // - Otherwise, dial this in to reflect actual minimum requirements and add some sort of platform
            //   error code mapping when creating exceptions.

            // TODO: try to initialize TLS 1.3 in SslStream.

            // TODO: Consider updating all of these delegates to instead use function pointers.

            if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, out IntPtr msQuicHandle))
            {
                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);
                    }
                }
            }
        }
Пример #20
0
 internal static unsafe void SetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param, ulong value)
 {
     QuicExceptionHelpers.ThrowIfFailed(
         api.SetParamDelegate(nativeObject, param, sizeof(ulong), (byte *)&value),
         "Could not set ulong.");
 }
Пример #21
0
        static MsQuicApi()
        {
            if (OperatingSystem.IsWindows())
            {
                if (!IsWindowsVersionSupported())
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}");
                    }

                    return;
                }

                Tls13MayBeDisabled = IsTls13Disabled();
            }

            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))
            {
                try
                {
                    if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
                    {
                        QUIC_API_TABLE *apiTable;
                        delegate * unmanaged[Cdecl] < uint, QUIC_API_TABLE **, int > msQuicOpenVersion = (delegate * unmanaged[Cdecl] < uint, QUIC_API_TABLE **, int >)msQuicOpenVersionAddress;
                        if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable)))
                        {
                            int   arraySize  = 4;
                            uint *libVersion = stackalloc uint[arraySize];
                            uint  size       = (uint)arraySize * sizeof(uint);
                            if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion)))
                            {
                                var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]);
                                if (version >= MsQuicVersion)
                                {
                                    Api             = new MsQuicApi(apiTable);
                                    IsQuicSupported = true;
                                }
                                else
                                {
                                    if (NetEventSource.Log.IsEnabled())
                                    {
                                        NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'");
                                    }
                                }
                            }
                        }
                    }
                }
                finally
                {
                    if (!IsQuicSupported)
                    {
                        NativeLibrary.Free(msQuicHandle);
                    }
                }
            }
        }
Пример #22
0
 internal static unsafe void SetUShortParam(MsQuicApi api, SafeHandle nativeObject, QUIC_PARAM_LEVEL level, uint param, ushort value)
 {
     QuicExceptionHelpers.ThrowIfFailed(
         api.SetParamDelegate(nativeObject, level, param, sizeof(ushort), (byte *)&value),
         "Could not set ushort.");
 }