diff --git a/src/libraries/Common/tests/TestUtilities/TestEventListener.cs b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs new file mode 100644 index 00000000000000..7b29189350ad08 --- /dev/null +++ b/src/libraries/Common/tests/TestUtilities/TestEventListener.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.Tracing; +using System.Text; +using Xunit.Abstractions; + +namespace TestUtilities; + +/// +/// Logging helper for tests. +/// Logs event source events into test output. +/// +public sealed class TestEventListener : EventListener +{ + private readonly ITestOutputHelper _output; + private readonly HashSet _sourceNames; + + // Until https://github.com/dotnet/runtime/issues/63979 is solved. + private List _eventSources = new List(); + + public TestEventListener(ITestOutputHelper output, params string[] sourceNames) + { + _output = output; + _sourceNames = new HashSet(sourceNames); + foreach (var eventSource in _eventSources) + { + OnEventSourceCreated(eventSource); + } + _eventSources = null; + } + + protected override void OnEventSourceCreated(EventSource eventSource) + { + // We're called from base ctor, just save the event source for later initialization. + if (_sourceNames is null) + { + _eventSources.Add(eventSource); + return; + } + + // Second pass called from our ctor, allow logging for specified source names. + if (_sourceNames.Contains(eventSource.Name)) + { + EnableEvents(eventSource, EventLevel.LogAlways); + } + } + + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + var sb = new StringBuilder().Append($"{eventData.TimeStamp:HH:mm:ss.fffffff}[{eventData.EventName}] "); + for (int i = 0; i < eventData.Payload?.Count; i++) + { + if (i > 0) + sb.Append(", "); + sb.Append(eventData.PayloadNames?[i]).Append(": ").Append(eventData.Payload[i]); + } + try + { + _output.WriteLine(sb.ToString()); + } + catch { } + } +} diff --git a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj index 657ccf8f5ef224..ad1ab67e89c947 100644 --- a/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj +++ b/src/libraries/Common/tests/TestUtilities/TestUtilities.csproj @@ -47,6 +47,8 @@ + + diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index c1f0c1ac6447ff..967482b5ff848a 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -30,21 +30,9 @@ - - - - - - - - - - - - - Common\DisableRuntimeMarshalling.cs - + + @@ -52,7 +40,6 @@ - @@ -75,7 +62,6 @@ - @@ -108,26 +94,21 @@ - - + - - - - alpnProtocols, [NotNull] out MemoryHandle[]? handles, [NotNull] out QuicBuffer[]? buffers) + public static unsafe void Prepare(List alpnProtocols, [NotNull] out MemoryHandle[]? handles, [NotNull] out QUIC_BUFFER[]? buffers) { handles = ArrayPool.Shared.Rent(alpnProtocols.Count); - buffers = ArrayPool.Shared.Rent(alpnProtocols.Count); + buffers = ArrayPool.Shared.Rent(alpnProtocols.Count); try { @@ -35,7 +35,7 @@ public static unsafe void Prepare(List alpnProtocols, [N } } - public static void Return(ref MemoryHandle[]? handles, ref QuicBuffer[]? buffers) + public static void Return(ref MemoryHandle[]? handles, ref QUIC_BUFFER[]? buffers) { if (handles is MemoryHandle[] notNullHandles) { @@ -48,10 +48,10 @@ public static void Return(ref MemoryHandle[]? handles, ref QuicBuffer[]? buffers ArrayPool.Shared.Return(notNullHandles); } - if (buffers is QuicBuffer[] notNullBuffers) + if (buffers is QUIC_BUFFER[] notNullBuffers) { buffers = null; - ArrayPool.Shared.Return(notNullBuffers); + ArrayPool.Shared.Return(notNullBuffers); } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs index d606651d6adeb9..2abe7e236108a5 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs @@ -3,21 +3,27 @@ using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; +using System.Text; +using Microsoft.Quic; + +using static Microsoft.Quic.MsQuic; #if TARGET_WINDOWS using Microsoft.Win32; #endif -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; - namespace System.Net.Quic.Implementations.MsQuic.Internal { internal unsafe sealed class MsQuicApi { + private static readonly byte[] s_appName = Encoding.ASCII.GetBytes("System.Net.Quic"); + private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000); public SafeMsQuicRegistrationHandle Registration { get; } + public QUIC_API_TABLE* ApiTable { get; } + // This is workaround for a bug in ILTrimmer. // Without these DynamicDependency attributes, .ctor() will be removed from the safe handles. // Remove once fixed: https://github.com/mono/linker/issues/1660 @@ -26,81 +32,22 @@ internal unsafe sealed class MsQuicApi [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicListenerHandle))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicConnectionHandle))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicStreamHandle))] - private MsQuicApi(NativeApi* vtable) + private MsQuicApi(QUIC_API_TABLE* apiTable) { - uint status; - - SetParamDelegate = - new SetParamDelegate(new DelegateHelper(vtable->SetParam).SetParam); - - GetParamDelegate = - new GetParamDelegate(new DelegateHelper(vtable->GetParam).GetParam); - - SetCallbackHandlerDelegate = - new SetCallbackHandlerDelegate(new DelegateHelper(vtable->SetCallbackHandler).SetCallbackHandler); - - RegistrationOpenDelegate = - new RegistrationOpenDelegate(new DelegateHelper(vtable->RegistrationOpen).RegistrationOpen); - RegistrationCloseDelegate = - Marshal.GetDelegateForFunctionPointer( - vtable->RegistrationClose); - - ConfigurationOpenDelegate = - new ConfigurationOpenDelegate(new DelegateHelper(vtable->ConfigurationOpen).ConfigurationOpen); - ConfigurationCloseDelegate = - Marshal.GetDelegateForFunctionPointer( - vtable->ConfigurationClose); - ConfigurationLoadCredentialDelegate = - new ConfigurationLoadCredentialDelegate(new DelegateHelper(vtable->ConfigurationLoadCredential).ConfigurationLoadCredential); - - ListenerOpenDelegate = - new ListenerOpenDelegate(new DelegateHelper(vtable->ListenerOpen).ListenerOpen); - ListenerCloseDelegate = - Marshal.GetDelegateForFunctionPointer( - vtable->ListenerClose); - ListenerStartDelegate = - new ListenerStartDelegate(new DelegateHelper(vtable->ListenerStart).ListenerStart); - ListenerStopDelegate = - new ListenerStopDelegate(new DelegateHelper(vtable->ListenerStop).ListenerStop); - - ConnectionOpenDelegate = - new ConnectionOpenDelegate(new DelegateHelper(vtable->ConnectionOpen).ConnectionOpen); - ConnectionCloseDelegate = - Marshal.GetDelegateForFunctionPointer( - vtable->ConnectionClose); - ConnectionSetConfigurationDelegate = - new ConnectionSetConfigurationDelegate(new DelegateHelper(vtable->ConnectionSetConfiguration).ConnectionSetConfiguration); - ConnectionShutdownDelegate = - new ConnectionShutdownDelegate(new DelegateHelper(vtable->ConnectionShutdown).ConnectionShutdown); - ConnectionStartDelegate = - new ConnectionStartDelegate(new DelegateHelper(vtable->ConnectionStart).ConnectionStart); - - StreamOpenDelegate = - new StreamOpenDelegate(new DelegateHelper(vtable->StreamOpen).StreamOpen); - StreamCloseDelegate = - Marshal.GetDelegateForFunctionPointer( - vtable->StreamClose); - StreamStartDelegate = - new StreamStartDelegate(new DelegateHelper(vtable->StreamStart).StreamStart); - StreamShutdownDelegate = - new StreamShutdownDelegate(new DelegateHelper(vtable->StreamShutdown).StreamShutdown); - StreamSendDelegate = - new StreamSendDelegate(new DelegateHelper(vtable->StreamSend).StreamSend); - StreamReceiveCompleteDelegate = - new StreamReceiveCompleteDelegate(new DelegateHelper(vtable->StreamReceiveComplete).StreamReceiveComplete); - StreamReceiveSetEnabledDelegate = - new StreamReceiveSetEnabledDelegate(new DelegateHelper(vtable->StreamReceiveSetEnabled).StreamReceiveSetEnabled); - - var cfg = new RegistrationConfig + ApiTable = apiTable; + + fixed (byte* pAppName = s_appName) { - AppName = ".NET", - ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY - }; + var cfg = new QUIC_REGISTRATION_CONFIG { + AppName = (sbyte*)pAppName, + ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY + }; - status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle); - QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed."); + QUIC_HANDLE* handle; + ThrowIfFailure(ApiTable->RegistrationOpen(&cfg, &handle), "RegistrationOpen failed"); - Registration = handle; + Registration = new SafeMsQuicRegistrationHandle(handle); + } } internal static MsQuicApi Api { get; } = null!; @@ -136,14 +83,13 @@ static MsQuicApi() { if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) { - NativeApi* vtable; - delegate* unmanaged[Cdecl] msQuicOpenVersion = - (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; - uint status = msQuicOpenVersion(MsQuicVersion, &vtable); - if (MsQuicStatusHelper.SuccessfulStatusCode(status)) + QUIC_API_TABLE* apiTable; + delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; + int status = msQuicOpenVersion(MsQuicVersion, &apiTable); + if (StatusSucceeded(status)) { IsQuicSupported = true; - Api = new MsQuicApi(vtable); + Api = new MsQuicApi(apiTable); } } } @@ -182,38 +128,5 @@ private static bool IsTls13Disabled() #endif return false; } - - // TODO: Consider updating all of these delegates to instead use function pointers. - internal RegistrationOpenDelegate RegistrationOpenDelegate { get; } - internal RegistrationCloseDelegate RegistrationCloseDelegate { get; } - - internal ConfigurationOpenDelegate ConfigurationOpenDelegate { get; } - internal ConfigurationCloseDelegate ConfigurationCloseDelegate { get; } - internal ConfigurationLoadCredentialDelegate ConfigurationLoadCredentialDelegate { get; } - - internal ListenerOpenDelegate ListenerOpenDelegate { get; } - internal ListenerCloseDelegate ListenerCloseDelegate { get; } - internal ListenerStartDelegate ListenerStartDelegate { get; } - internal ListenerStopDelegate ListenerStopDelegate { get; } - - // TODO: missing SendResumptionTicket - internal ConnectionOpenDelegate ConnectionOpenDelegate { get; } - internal ConnectionCloseDelegate ConnectionCloseDelegate { get; } - internal ConnectionShutdownDelegate ConnectionShutdownDelegate { get; } - internal ConnectionStartDelegate ConnectionStartDelegate { get; } - internal ConnectionSetConfigurationDelegate ConnectionSetConfigurationDelegate { get; } - - internal StreamOpenDelegate StreamOpenDelegate { get; } - internal StreamCloseDelegate StreamCloseDelegate { get; } - internal StreamStartDelegate StreamStartDelegate { get; } - internal StreamShutdownDelegate StreamShutdownDelegate { get; } - internal StreamSendDelegate StreamSendDelegate { get; } - internal StreamReceiveCompleteDelegate StreamReceiveCompleteDelegate { get; } - internal StreamReceiveSetEnabledDelegate StreamReceiveSetEnabledDelegate { get; } - - internal SetCallbackHandlerDelegate SetCallbackHandlerDelegate { get; } - - internal SetParamDelegate SetParamDelegate { get; } - internal GetParamDelegate GetParamDelegate { get; } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicParameterHelpers.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicParameterHelpers.cs index 7fef8a88e6899a..784d89566b3517 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicParameterHelpers.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicParameterHelpers.cs @@ -4,13 +4,13 @@ using System.Diagnostics; using System.Runtime.InteropServices; using System.Net.Sockets; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; +using static Microsoft.Quic.MsQuic; namespace System.Net.Quic.Implementations.MsQuic.Internal { internal static class MsQuicParameterHelpers { - internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param) + 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; @@ -18,17 +18,19 @@ internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, SafeHandle n fixed (byte* paddress = &MemoryMarshal.GetReference(address)) { - uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, paddress); - QuicExceptionHelpers.ThrowIfFailed(status, "GetIPEndPointParam failed."); + 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(); + return new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address).GetIPEndPoint(); } - internal static unsafe void SetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param, IPEndPoint value) + internal static unsafe void SetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, IPEndPoint value) { Internals.SocketAddress socketAddress = IPEndPointExtensions.Serialize(value); @@ -39,48 +41,60 @@ internal static unsafe void SetIPEndPointParam(MsQuicApi api, SafeHandle nativeO fixed (byte* paddress = &MemoryMarshal.GetReference(address)) { - QuicExceptionHelpers.ThrowIfFailed( - api.SetParamDelegate(nativeObject, param, (uint)address.Length, paddress), - "Could not set IPEndPoint"); + ThrowIfFailure(api.ApiTable->SetParam( + nativeObject.QuicHandle, + param, + (uint)address.Length, + paddress), "Could not set IPEndPoint"); } } - internal static unsafe ushort GetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param) + internal static unsafe ushort GetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param) { ushort value; uint valueLen = (uint)sizeof(ushort); - uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte*)&value); - QuicExceptionHelpers.ThrowIfFailed(status, "GetUShortParam failed."); + ThrowIfFailure(api.ApiTable->GetParam( + nativeObject.QuicHandle, + param, + &valueLen, + (byte*)&value), "GetUShortParam failed"); Debug.Assert(valueLen == sizeof(ushort)); return value; } - internal static unsafe void SetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param, ushort value) + internal static unsafe void SetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ushort value) { - QuicExceptionHelpers.ThrowIfFailed( - api.SetParamDelegate(nativeObject, param, sizeof(ushort), (byte*)&value), - "Could not set ushort."); + ThrowIfFailure(api.ApiTable->SetParam( + nativeObject.QuicHandle, + param, + sizeof(ushort), + (byte*)&value), "Could not set ushort"); } - internal static unsafe ulong GetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param) + internal static unsafe ulong GetULongParam(MsQuicApi api, MsQuicSafeHandle 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."); + ThrowIfFailure(api.ApiTable->GetParam( + nativeObject.QuicHandle, + param, + &valueLen, + (byte*)&value), "GetULongParam failed"); Debug.Assert(valueLen == sizeof(ulong)); return value; } - internal static unsafe void SetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param, ulong value) + internal static unsafe void SetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ulong value) { - QuicExceptionHelpers.ThrowIfFailed( - api.SetParamDelegate(nativeObject, param, sizeof(ulong), (byte*)&value), - "Could not set ulong."); + ThrowIfFailure(api.ApiTable->SetParam( + nativeObject.QuicHandle, + param, + sizeof(ulong), + (byte*)&value), "Could not set ulong"); } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/QuicExceptionHelpers.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/QuicExceptionHelpers.cs deleted file mode 100644 index 680069bf7b815c..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/QuicExceptionHelpers.cs +++ /dev/null @@ -1,38 +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.Net.Sockets; - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static class QuicExceptionHelpers - { - internal static void ThrowIfFailed(uint status, string? message = null, Exception? innerException = null) - { - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) - { - throw CreateExceptionForHResult(status, message, innerException); - } - } - - internal static Exception CreateExceptionForHResult(uint status, string? message = null, Exception? innerException = null) - { - return new QuicException($"{message} Error Code: {MsQuicStatusCodes.GetError(status)}", innerException, MapMsQuicStatusToHResult(status)); - } - - internal static int MapMsQuicStatusToHResult(uint status) - { - switch (status) - { - case MsQuicStatusCodes.ConnectionRefused: - return (int)SocketError.ConnectionRefused; // 0x8007274D - WSAECONNREFUSED - case MsQuicStatusCodes.ConnectionTimeout: - return (int)SocketError.TimedOut; // 0x8007274C - WSAETIMEDOUT - case MsQuicStatusCodes.HostUnreachable: - return (int)SocketError.HostUnreachable; - default: - return 0; - } - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicEnums.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicEnums.cs deleted file mode 100644 index 956c425828c46c..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicEnums.cs +++ /dev/null @@ -1,228 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal enum QUIC_EXECUTION_PROFILE : uint - { - QUIC_EXECUTION_PROFILE_LOW_LATENCY, // Default - QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT, - QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER, - QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME, - } - - internal enum QUIC_CREDENTIAL_TYPE : uint - { - NONE, - HASH, - HASH_STORE, - CONTEXT, - FILE, - FILE_PROTECTED, - PKCS12, - } - - [Flags] - internal enum QUIC_CREDENTIAL_FLAGS : uint - { - NONE = 0x00000000, - CLIENT = 0x00000001, // Lack of client flag indicates server. - LOAD_ASYNCHRONOUS = 0x00000002, - NO_CERTIFICATE_VALIDATION = 0x00000004, - ENABLE_OCSP = 0x00000008, // Schannel only currently. - INDICATE_CERTIFICATE_RECEIVED = 0x00000010, - DEFER_CERTIFICATE_VALIDATION = 0x00000020, // Schannel only currently. - REQUIRE_CLIENT_AUTHENTICATION = 0x00000040, // Schannel only currently. - USE_TLS_BUILTIN_CERTIFICATE_VALIDATION = 0x00000080, - SET_ALLOWED_CIPHER_SUITES = 0x00002000, - USE_PORTABLE_CERTIFICATES = 0x00004000, - } - - [Flags] - internal enum QUIC_ALLOWED_CIPHER_SUITE_FLAGS : uint - { - NONE = 0x0, - AES_128_GCM_SHA256 = 0x1, - AES_256_GCM_SHA384 = 0x2, - CHACHA20_POLY1305_SHA256 = 0x4, - } - - internal enum QUIC_CERTIFICATE_HASH_STORE_FLAGS - { - QUIC_CERTIFICATE_HASH_STORE_FLAG_NONE = 0x0000, - QUIC_CERTIFICATE_HASH_STORE_FLAG_MACHINE_STORE = 0x0001, - } - - [Flags] - internal enum QUIC_CONNECTION_SHUTDOWN_FLAGS : uint - { - NONE = 0x0000, - SILENT = 0x0001, // Don't send the close frame over the network. - } - - internal enum QUIC_SERVER_RESUMPTION_LEVEL : uint - { - NO_RESUME, - RESUME_ONLY, - RESUME_AND_ZERORTT, - } - - [Flags] - internal enum QUIC_STREAM_OPEN_FLAGS : uint - { - NONE = 0x0000, - UNIDIRECTIONAL = 0x0001, // Indicates the stream is unidirectional. - ZERO_RTT = 0x0002, // The stream was opened via a 0-RTT packet. - } - - [Flags] - internal enum QUIC_STREAM_START_FLAGS : uint - { - NONE = 0x0000, - IMMEDIATE = 0x0001, // Immediately informs peer that stream is open. - FAIL_BLOCKED = 0x0002, // Only opens the stream if flow control allows. - SHUTDOWN_ON_FAIL = 0x0004, // Shutdown the stream immediately after start failure. - INDICATE_PEER_ACCEPT = 0x0008, // PEER_ACCEPTED event to be delivered if the stream isn't initially accepted. - } - - [Flags] - internal enum QUIC_STREAM_SHUTDOWN_FLAGS : uint - { - NONE = 0x0000, - GRACEFUL = 0x0001, // Cleanly closes the send path. - ABORT_SEND = 0x0002, // Abruptly closes the send path. - ABORT_RECEIVE = 0x0004, // Abruptly closes the receive path. - ABORT = 0x0006, // Abruptly closes both send and receive paths. - IMMEDIATE = 0x0008, // Immediately sends completion events to app. - } - - [Flags] - internal enum QUIC_RECEIVE_FLAGS : uint - { - NONE = 0x0000, - ZERO_RTT = 0x0001, // Data was encrypted with 0-RTT key. - FIN = 0x0002, // FIN was included with this data. - } - - [Flags] - internal enum QUIC_SEND_FLAGS : uint - { - NONE = 0x0000, - ALLOW_0_RTT = 0x0001, // Allows the use of encrypting with 0-RTT key. - START = 0x0002, // Asynchronously starts the stream with the sent data. - FIN = 0x0004, // Indicates the request is the one last sent on the stream. - DGRAM_PRIORITY = 0x0008, // Indicates the datagram is higher priority than others. - DELAY_SEND = 0x0010, // Indicates the send should be delayed because more will be queued soon. - } - - internal enum QUIC_PARAM_PREFIX : uint - { - GLOBAL = 0x01000000, - REGISTRATION = 0x02000000, - CONFIGURATION = 0x03000000, - LISTENER = 0x04000000, - CONNECTION = 0x05000000, - TLS = 0x06000000, - TLS_SCHANNEL = 0x07000000, - STREAM = 0x08000000, - } - - internal enum QUIC_PARAM_GLOBAL : uint - { - RETRY_MEMORY_PERCENT = 0 | QUIC_PARAM_PREFIX.GLOBAL, // uint16_t - SUPPORTED_VERSIONS = 1 | QUIC_PARAM_PREFIX.GLOBAL, // uint32_t[] - network byte order - LOAD_BALANCING_MODE = 2 | QUIC_PARAM_PREFIX.GLOBAL, // uint16_t - QUIC_LOAD_BALANCING_MODE - PERF_COUNTERS = 3 | QUIC_PARAM_PREFIX.GLOBAL, // uint64_t[] - Array size is QUIC_PERF_COUNTER_MAX - SETTINGS = 4 | QUIC_PARAM_PREFIX.GLOBAL, // QUIC_SETTINGS - } - - internal enum QUIC_PARAM_REGISTRATION : uint - { - CID_PREFIX = 0 | QUIC_PARAM_PREFIX.REGISTRATION, // uint8_t[] - } - - internal enum QUIC_PARAM_LISTENER : uint - { - LOCAL_ADDRESS = 0 | QUIC_PARAM_PREFIX.LISTENER, // QUIC_ADDR - STATS = 1 | QUIC_PARAM_PREFIX.LISTENER, // QUIC_LISTENER_STATISTICS - } - - internal enum QUIC_PARAM_CONN : uint - { - QUIC_VERSION = 0 | QUIC_PARAM_PREFIX.CONNECTION, // uint32_t - LOCAL_ADDRESS = 1 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_ADDR - REMOTE_ADDRESS = 2 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_ADDR - IDEAL_PROCESSOR = 3 | QUIC_PARAM_PREFIX.CONNECTION, // uint16_t - SETTINGS = 4 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_SETTINGS - STATISTICS = 5 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_STATISTICS - STATISTICS_PLAT = 6 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_STATISTICS - SHARE_UDP_BINDING = 7 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t (BOOLEAN) - LOCAL_BIDI_STREAM_COUNT = 8 | QUIC_PARAM_PREFIX.CONNECTION, // uint16_t - LOCAL_UNIDI_STREAM_COUNT = 9 | QUIC_PARAM_PREFIX.CONNECTION, // uint16_t - MAX_STREAM_IDS = 10 | QUIC_PARAM_PREFIX.CONNECTION, // uint64_t[4] - CLOSE_REASON_PHRASE = 11 | QUIC_PARAM_PREFIX.CONNECTION, // char[] - STREAM_SCHEDULING_SCHEME = 12 | QUIC_PARAM_PREFIX.CONNECTION, // QUIC_STREAM_SCHEDULING_SCHEME - DATAGRAM_RECEIVE_ENABLED = 13 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t (BOOLEAN) - DATAGRAM_SEND_ENABLED = 14 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t (BOOLEAN) - DISABLE_1RTT_ENCRYPTION = 15 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t (BOOLEAN) - RESUMPTION_TICKET = 16 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t[] - PEER_CERTIFICATE_VALID = 17 | QUIC_PARAM_PREFIX.CONNECTION, // uint8_t (BOOLEAN) - } - - internal enum QUIC_PARAM_STREAM : uint - { - ID = 0 | QUIC_PARAM_PREFIX.STREAM, // QUIC_UINT62 - ZERRTT_LENGTH = 1 | QUIC_PARAM_PREFIX.STREAM, // uint64_t - IDEAL_SEND_BUFFER_SIZE = 2 | QUIC_PARAM_PREFIX.STREAM, // uint64_t - bytes - } - - internal enum QUIC_LISTENER_EVENT : uint - { - NEW_CONNECTION = 0, - STOP_COMPLETE = 1, - } - - internal enum QUIC_CONNECTION_EVENT_TYPE : uint - { - CONNECTED = 0, - SHUTDOWN_INITIATED_BY_TRANSPORT = 1, // The transport started the shutdown process. - SHUTDOWN_INITIATED_BY_PEER = 2, // The peer application started the shutdown process. - SHUTDOWN_COMPLETE = 3, // Ready for the handle to be closed. - LOCAL_ADDRESS_CHANGED = 4, - PEER_ADDRESS_CHANGED = 5, - PEER_STREAM_STARTED = 6, - STREAMS_AVAILABLE = 7, - PEER_NEEDS_STREAMS = 8, - IDEAL_PROCESSOR_CHANGED = 9, - DATAGRAM_STATE_CHANGED = 10, - DATAGRAM_RECEIVED = 11, - DATAGRAM_SEND_STATE_CHANGED = 12, - RESUMED = 13, // Server-only; provides resumption data, if any. - RESUMPTION_TICKET_RECEIVED = 14, // Client-only; provides ticket to persist, if any. - PEER_CERTIFICATE_RECEIVED = 15, // Only with QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED set. - } - - internal enum QUIC_STREAM_EVENT_TYPE : uint - { - START_COMPLETE = 0, - RECEIVE = 1, - SEND_COMPLETE = 2, - PEER_SEND_SHUTDOWN = 3, - PEER_SEND_ABORTED = 4, - PEER_RECEIVE_ABORTED = 5, - SEND_SHUTDOWN_COMPLETE = 6, - SHUTDOWN_COMPLETE = 7, - IDEAL_SEND_BUFFER_SIZE = 8, - } - -#if SOCKADDR_HAS_LENGTH - internal enum QUIC_ADDRESS_FAMILY : byte -#else - internal enum QUIC_ADDRESS_FAMILY : ushort -#endif - { - UNSPEC = 0, - INET = 2, - INET6 = 23, - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicException.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicException.cs new file mode 100644 index 00000000000000..967411b4d2be20 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicException.cs @@ -0,0 +1,65 @@ +// 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; +using System.Net.Sockets; +using static Microsoft.Quic.MsQuic; + +namespace Microsoft.Quic +{ + internal class MsQuicException : QuicException + { + public int Status { get; } + + public MsQuicException(int status, string? message = null, Exception? innerException = null) + : base($"{(message ?? nameof(MsQuicException))}: {GetErrorCodeForStatus(status)}", innerException, MapMsQuicStatusToHResult(status)) + { + Status = status; + } + + public static string GetErrorCodeForStatus(int status) + { + if (status == MsQuic.QUIC_STATUS_SUCCESS) return "QUIC_STATUS_SUCCESS"; + else if (status == MsQuic.QUIC_STATUS_PENDING) return "QUIC_STATUS_PENDING"; + else if (status == MsQuic.QUIC_STATUS_CONTINUE) return "QUIC_STATUS_CONTINUE"; + else if (status == MsQuic.QUIC_STATUS_OUT_OF_MEMORY) return "QUIC_STATUS_OUT_OF_MEMORY"; + else if (status == MsQuic.QUIC_STATUS_INVALID_PARAMETER) return "QUIC_STATUS_INVALID_PARAMETER"; + else if (status == MsQuic.QUIC_STATUS_INVALID_STATE) return "QUIC_STATUS_INVALID_STATE"; + else if (status == MsQuic.QUIC_STATUS_NOT_SUPPORTED) return "QUIC_STATUS_NOT_SUPPORTED"; + else if (status == MsQuic.QUIC_STATUS_NOT_FOUND) return "QUIC_STATUS_NOT_FOUND"; + else if (status == MsQuic.QUIC_STATUS_BUFFER_TOO_SMALL) return "QUIC_STATUS_BUFFER_TOO_SMALL"; + else if (status == MsQuic.QUIC_STATUS_HANDSHAKE_FAILURE) return "QUIC_STATUS_HANDSHAKE_FAILURE"; + else if (status == MsQuic.QUIC_STATUS_ABORTED) return "QUIC_STATUS_ABORTED"; + else if (status == MsQuic.QUIC_STATUS_ADDRESS_IN_USE) return "QUIC_STATUS_ADDRESS_IN_USE"; + else if (status == MsQuic.QUIC_STATUS_CONNECTION_TIMEOUT) return "QUIC_STATUS_CONNECTION_TIMEOUT"; + else if (status == MsQuic.QUIC_STATUS_CONNECTION_IDLE) return "QUIC_STATUS_CONNECTION_IDLE"; + else if (status == MsQuic.QUIC_STATUS_UNREACHABLE) return "QUIC_STATUS_UNREACHABLE"; + else if (status == MsQuic.QUIC_STATUS_INTERNAL_ERROR) return "QUIC_STATUS_INTERNAL_ERROR"; + else if (status == MsQuic.QUIC_STATUS_CONNECTION_REFUSED) return "QUIC_STATUS_CONNECTION_REFUSED"; + else if (status == MsQuic.QUIC_STATUS_PROTOCOL_ERROR) return "QUIC_STATUS_PROTOCOL_ERROR"; + else if (status == MsQuic.QUIC_STATUS_VER_NEG_ERROR) return "QUIC_STATUS_VER_NEG_ERROR"; + else if (status == MsQuic.QUIC_STATUS_TLS_ERROR) return "QUIC_STATUS_TLS_ERROR"; + else if (status == MsQuic.QUIC_STATUS_USER_CANCELED) return "QUIC_STATUS_USER_CANCELED"; + else if (status == MsQuic.QUIC_STATUS_ALPN_NEG_FAILURE) return "QUIC_STATUS_ALPN_NEG_FAILURE"; + else if (status == MsQuic.QUIC_STATUS_STREAM_LIMIT_REACHED) return "QUIC_STATUS_STREAM_LIMIT_REACHED"; + else if (status == MsQuic.QUIC_STATUS_CLOSE_NOTIFY) return "QUIC_STATUS_CLOSE_NOTIFY"; + else if (status == MsQuic.QUIC_STATUS_BAD_CERTIFICATE) return "QUIC_STATUS_BAD_CERTIFICATE"; + else if (status == MsQuic.QUIC_STATUS_UNSUPPORTED_CERTIFICATE) return "QUIC_STATUS_UNSUPPORTED_CERTIFICATE"; + else if (status == MsQuic.QUIC_STATUS_REVOKED_CERTIFICATE) return "QUIC_STATUS_REVOKED_CERTIFICATE"; + else if (status == MsQuic.QUIC_STATUS_EXPIRED_CERTIFICATE) return "QUIC_STATUS_EXPIRED_CERTIFICATE"; + else if (status == MsQuic.QUIC_STATUS_UNKNOWN_CERTIFICATE) return "QUIC_STATUS_UNKNOWN_CERTIFICATE"; + else if (status == MsQuic.QUIC_STATUS_CERT_EXPIRED) return "QUIC_STATUS_CERT_EXPIRED"; + else if (status == MsQuic.QUIC_STATUS_CERT_UNTRUSTED_ROOT) return "QUIC_STATUS_CERT_UNTRUSTED_ROOT"; + else return $"Unknown status '{status}'"; + } + + public static int MapMsQuicStatusToHResult(int status) + { + if (status == QUIC_STATUS_CONNECTION_REFUSED) return (int)SocketError.ConnectionRefused; // 0x8007274D - WSAECONNREFUSED + else if (status == QUIC_STATUS_CONNECTION_TIMEOUT) return (int)SocketError.TimedOut; // 0x8007274C - WSAETIMEDOUT + else if (status == QUIC_STATUS_UNREACHABLE) return (int)SocketError.HostUnreachable; + else return 0; + } + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs deleted file mode 100644 index 6a7e35ca14e720..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs +++ /dev/null @@ -1,1437 +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.Runtime.InteropServices; - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - /// - /// Contains all native delegates and structs that are used with MsQuic. - /// - internal static unsafe partial class MsQuicNativeMethods - { - [StructLayout(LayoutKind.Sequential)] - internal struct NativeApi - { - internal IntPtr SetContext; - internal IntPtr GetContext; - internal IntPtr SetCallbackHandler; - - internal IntPtr SetParam; - internal IntPtr GetParam; - - internal IntPtr RegistrationOpen; - internal IntPtr RegistrationClose; - internal IntPtr RegistrationShutdown; - - internal IntPtr ConfigurationOpen; - internal IntPtr ConfigurationClose; - internal IntPtr ConfigurationLoadCredential; - - internal IntPtr ListenerOpen; - internal IntPtr ListenerClose; - internal IntPtr ListenerStart; - internal IntPtr ListenerStop; - - internal IntPtr ConnectionOpen; - internal IntPtr ConnectionClose; - internal IntPtr ConnectionShutdown; - internal IntPtr ConnectionStart; - internal IntPtr ConnectionSetConfiguration; - internal IntPtr ConnectionSendResumptionTicket; - - internal IntPtr StreamOpen; - internal IntPtr StreamClose; - internal IntPtr StreamStart; - internal IntPtr StreamShutdown; - internal IntPtr StreamSend; - internal IntPtr StreamReceiveComplete; - internal IntPtr StreamReceiveSetEnabled; - - internal IntPtr DatagramSend; - } - - internal delegate uint SetContextDelegate( - SafeHandle handle, - IntPtr context); - - internal delegate IntPtr GetContextDelegate( - SafeHandle handle); - - internal delegate void SetCallbackHandlerDelegate( - SafeHandle handle, - Delegate del, - IntPtr context); - - internal delegate uint SetParamDelegate( - SafeHandle handle, - uint param, - uint bufferLength, - byte* buffer); - - internal delegate uint GetParamDelegate( - SafeHandle handle, - uint param, - ref uint bufferLength, - byte* buffer); - - internal delegate uint RegistrationOpenDelegate( - ref RegistrationConfig config, - out SafeMsQuicRegistrationHandle registrationContext); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void RegistrationCloseDelegate( - IntPtr registrationContext); - - [NativeMarshalling(typeof(Native))] - internal struct RegistrationConfig - { - internal string AppName; - internal QUIC_EXECUTION_PROFILE ExecutionProfile; - - [CustomTypeMarshaller(typeof(RegistrationConfig), Features = CustomTypeMarshallerFeatures.UnmanagedResources)] - [StructLayout(LayoutKind.Sequential)] - public struct Native - { - private IntPtr AppName; - private QUIC_EXECUTION_PROFILE ExecutionProfile; - - public Native(RegistrationConfig managed) - { - AppName = Marshal.StringToCoTaskMemUTF8(managed.AppName); - ExecutionProfile = managed.ExecutionProfile; - } - - public RegistrationConfig ToManaged() - { - return new RegistrationConfig() - { - AppName = Marshal.PtrToStringUTF8(AppName)!, - ExecutionProfile = ExecutionProfile - }; - } - - public void FreeNative() - { - Marshal.FreeCoTaskMem(AppName); - } - } - } - - internal delegate uint ConfigurationOpenDelegate( - SafeMsQuicRegistrationHandle registrationContext, - QuicBuffer* alpnBuffers, - uint alpnBufferCount, - ref QuicSettings settings, - uint settingsSize, - IntPtr context, - out SafeMsQuicConfigurationHandle configuration); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ConfigurationCloseDelegate( - IntPtr configuration); - - internal delegate uint ConfigurationLoadCredentialDelegate( - SafeMsQuicConfigurationHandle configuration, - ref CredentialConfig credConfig); - - internal struct AnyDelegateMarshaller - { - private readonly Delegate _managed; - - public AnyDelegateMarshaller(Delegate managed) - { - _managed = managed; - Value = Marshal.GetFunctionPointerForDelegate(_managed); - } - - public IntPtr Value { get; } - - public void FreeNative() - { - GC.KeepAlive(_managed); - } - } - - [StructLayout(LayoutKind.Sequential)] - internal struct QuicSettings - { - internal QuicSettingsIsSetFlags IsSetFlags; - internal ulong MaxBytesPerKey; - internal ulong HandshakeIdleTimeoutMs; - internal ulong IdleTimeoutMs; - internal ulong MtuDiscoverySearchCompleteTimeoutUs; - internal uint TlsClientMaxSendBuffer; - internal uint TlsServerMaxSendBuffer; - internal uint StreamRecvWindowDefault; - internal uint StreamRecvBufferDefault; - internal uint ConnFlowControlWindow; - internal uint MaxWorkerQueueDelayUs; - internal uint MaxStatelessOperations; - internal uint InitialWindowPackets; - internal uint SendIdleTimeoutMs; - internal uint InitialRttMs; - internal uint MaxAckDelayMs; - internal uint DisconnectTimeoutMs; - internal uint KeepAliveIntervalMs; - internal ushort CongestionControlAlgorithm; // QUIC_CONGESTION_CONTROL_ALGORITHM - internal ushort PeerBidiStreamCount; - internal ushort PeerUnidiStreamCount; - internal ushort MaxBindingStatelessOperations; - internal ushort StatelessOperationExpirationMs; - internal ushort MinimumMtu; - internal ushort MaximumMtu; - internal QuicSettingsEnabledFlagsFlags EnabledFlags; - internal byte MaxOperationsPerDrain; - internal byte MtuDiscoveryMissingProbeCount; - } - - [Flags] - internal enum QuicSettingsIsSetFlags : ulong - { - MaxBytesPerKey = 1UL << 0, - HandshakeIdleTimeoutMs = 1UL << 1, - IdleTimeoutMs = 1UL << 2, - MtuDiscoverySearchCompleteTimeoutUs = 1UL << 3, - TlsClientMaxSendBuffer = 1UL << 4, - TlsServerMaxSendBuffer = 1UL << 5, - StreamRecvWindowDefault = 1UL << 6, - StreamRecvBufferDefault = 1UL << 7, - ConnFlowControlWindow = 1UL << 8, - MaxWorkerQueueDelayUs = 1UL << 9, - MaxStatelessOperations = 1UL << 10, - InitialWindowPackets = 1UL << 11, - SendIdleTimeoutMs = 1UL << 12, - InitialRttMs = 1UL << 13, - MaxAckDelayMs = 1UL << 14, - DisconnectTimeoutMs = 1UL << 15, - KeepAliveIntervalMs = 1UL << 16, - CongestionControlAlgorithm = 1UL << 17, - PeerBidiStreamCount = 1UL << 18, - PeerUnidiStreamCount = 1UL << 19, - MaxBindingStatelessOperations = 1UL << 20, - StatelessOperationExpirationMs = 1UL << 21, - MinimumMtu = 1UL << 22, - MaximumMtu = 1UL << 23, - SendBufferingEnabled = 1UL << 24, - PacingEnabled = 1UL << 25, - MigrationEnabled = 1UL << 26, - DatagramReceiveEnabled = 1UL << 27, - ServerResumptionLevel = 1UL << 28, - MaxOperationsPerDrain = 1UL << 29, - MtuDiscoveryMissingProbeCount = 1UL << 31, - } - - [Flags] - internal enum QuicSettingsEnabledFlagsFlags : byte - { - SendBufferingEnabled = 1 << 0, - PacingEnabled = 1 << 1, - MigrationEnabled = 1 << 2, - DatagramReceiveEnabled = 1 << 3, - // Contains values of QUIC_SERVER_RESUMPTION_LEVEL - ServerResumptionLevel = 1 << 4 | 1 << 5, - VersionNegotiationExtEnabled = 1 << 6, - } - - [NativeMarshalling(typeof(Native))] - internal struct CredentialConfig - { - internal QUIC_CREDENTIAL_TYPE Type; - internal QUIC_CREDENTIAL_FLAGS Flags; - // CredentialConfigCertificateUnion* - internal IntPtr Certificate; - - internal string Principal; - internal IntPtr Reserved; // Currently unused - // TODO: define delegate for AsyncHandler and make proper use of it. - internal IntPtr AsyncHandler; - internal QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites; - - [CustomTypeMarshaller(typeof(CredentialConfig), Features = CustomTypeMarshallerFeatures.UnmanagedResources)] - [StructLayout(LayoutKind.Sequential)] - public struct Native - { - internal QUIC_CREDENTIAL_TYPE Type; - internal QUIC_CREDENTIAL_FLAGS Flags; - // CredentialConfigCertificateUnion* - internal IntPtr Certificate; - internal IntPtr Principal; - internal IntPtr Reserved; - internal IntPtr AsyncHandler; - internal QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites; - - public Native(CredentialConfig managed) - { - Type = managed.Type; - Flags = managed.Flags; - Certificate = managed.Certificate; - Principal = Marshal.StringToCoTaskMemUTF8(managed.Principal); - Reserved = managed.Reserved; - AsyncHandler = managed.AsyncHandler; - AllowedCipherSuites = managed.AllowedCipherSuites; - } - - public CredentialConfig ToManaged() - { - return new CredentialConfig - { - Type = Type, - Flags = Flags, - Certificate = Certificate, - Principal = Marshal.PtrToStringUTF8(Principal)!, - Reserved = Reserved, - AsyncHandler = AsyncHandler, - AllowedCipherSuites = AllowedCipherSuites - }; - } - - public void FreeNative() - { - Marshal.FreeCoTaskMem(Principal); - } - } - } - - [StructLayout(LayoutKind.Explicit)] - internal struct CredentialConfigCertificateUnion - { - [FieldOffset(0)] - internal CredentialConfigCertificateHash CertificateHash; - - [FieldOffset(0)] - internal CredentialConfigCertificateHashStore CertificateHashStore; - - [FieldOffset(0)] - internal IntPtr CertificateContext; - - [FieldOffset(0)] - internal CredentialConfigCertificateFile CertificateFile; - - [FieldOffset(0)] - internal CredentialConfigCertificateFileProtected CertificateFileProtected; - - [FieldOffset(0)] - internal CredentialConfigCertificatePkcs12 CertificatePkcs12; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct CredentialConfigCertificateHash - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] - internal byte[] ShaHash; - } - - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] - internal struct CredentialConfigCertificateHashStore - { - internal QUIC_CERTIFICATE_HASH_STORE_FLAGS Flags; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] - internal byte[] ShaHash; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] - internal char[] StoreName; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct CredentialConfigCertificateFile - { - [MarshalAs(UnmanagedType.LPUTF8Str)] - internal string PrivateKeyFile; - - [MarshalAs(UnmanagedType.LPUTF8Str)] - internal string CertificateFile; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct CredentialConfigCertificateFileProtected - { - [MarshalAs(UnmanagedType.LPUTF8Str)] - internal string PrivateKeyFile; - - [MarshalAs(UnmanagedType.LPUTF8Str)] - internal string CertificateFile; - - [MarshalAs(UnmanagedType.LPUTF8Str)] - internal string PrivateKeyPassword; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct CredentialConfigCertificatePkcs12 - { - internal IntPtr Asn1Blob; - - internal uint Asn1BlobLength; - - internal IntPtr PrivateKeyPassword; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ListenerEvent - { - internal QUIC_LISTENER_EVENT Type; - internal ListenerEventDataUnion Data; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct ListenerEventDataUnion - { - [FieldOffset(0)] - internal ListenerEventDataNewConnection NewConnection; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ListenerEventDataNewConnection - { - internal NewConnectionInfo* Info; - internal IntPtr Connection; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct NewConnectionInfo - { - internal uint QuicVersion; - // QUIC_ADDR - internal IntPtr LocalAddress; - // QUIC_ADDR - internal IntPtr RemoteAddress; - internal uint CryptoBufferLength; - internal ushort ClientAlpnListLength; - internal ushort ServerNameLength; - internal byte NegotiatedAlpnLength; - // byte[] - internal IntPtr CryptoBuffer; - // byte[] - internal IntPtr ClientAlpnList; - // byte[] - internal IntPtr NegotiatedAlpn; - // string - internal IntPtr ServerName; - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate uint ListenerCallbackDelegate( - IntPtr listener, - IntPtr context, - ListenerEvent* evt); - - internal delegate uint ListenerOpenDelegate( - SafeMsQuicRegistrationHandle registration, - ListenerCallbackDelegate handler, - IntPtr context, - out SafeMsQuicListenerHandle listener); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ListenerCloseDelegate( - IntPtr listener); - - internal delegate uint ListenerStartDelegate( - SafeMsQuicListenerHandle listener, - QuicBuffer* alpnBuffers, - uint alpnBufferCount, - byte* localAddress); - - internal delegate void ListenerStopDelegate( - SafeMsQuicListenerHandle listener); - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataConnected - { - internal byte SessionResumed; - internal byte NegotiatedAlpnLength; - // byte[] - internal IntPtr NegotiatedAlpn; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataShutdownInitiatedByTransport - { - internal uint Status; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataShutdownInitiatedByPeer - { - internal long ErrorCode; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataShutdownComplete - { - // The flags have fixed sized exactly 3 bits - internal ConnectionEventDataShutdownCompleteFlags Flags; - } - - [Flags] - internal enum ConnectionEventDataShutdownCompleteFlags : byte - { - HandshakeCompleted = 1 << 0, - PeerAcknowledgedShutdown = 1 << 1, - AppCloseInProgress = 1 << 2, - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataLocalAddressChanged - { - // QUIC_ADDR - internal IntPtr Address; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataPeerAddressChanged - { - // QUIC_ADDR - internal IntPtr Address; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataPeerStreamStarted - { - internal IntPtr Stream; - internal QUIC_STREAM_OPEN_FLAGS Flags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventDataStreamsAvailable - { - internal ushort BiDirectionalCount; - internal ushort UniDirectionalCount; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEventPeerCertificateReceived - { - internal IntPtr PlatformCertificateHandle; - internal uint DeferredErrorFlags; - internal uint DeferredStatus; - internal IntPtr PlatformCertificateChainHandle; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct ConnectionEventDataUnion - { - [FieldOffset(0)] - internal ConnectionEventDataConnected Connected; - - [FieldOffset(0)] - internal ConnectionEventDataShutdownInitiatedByTransport ShutdownInitiatedByTransport; - - [FieldOffset(0)] - internal ConnectionEventDataShutdownInitiatedByPeer ShutdownInitiatedByPeer; - - [FieldOffset(0)] - internal ConnectionEventDataShutdownComplete ShutdownComplete; - - [FieldOffset(0)] - internal ConnectionEventDataLocalAddressChanged LocalAddressChanged; - - [FieldOffset(0)] - internal ConnectionEventDataPeerAddressChanged PeerAddressChanged; - - [FieldOffset(0)] - internal ConnectionEventDataPeerStreamStarted PeerStreamStarted; - - [FieldOffset(0)] - internal ConnectionEventDataStreamsAvailable StreamsAvailable; - - [FieldOffset(0)] - internal ConnectionEventPeerCertificateReceived PeerCertificateReceived; - - // TODO: missing IDEAL_PROCESSOR_CHANGED, ..., (6 total) - } - - [StructLayout(LayoutKind.Sequential)] - internal struct ConnectionEvent - { - internal QUIC_CONNECTION_EVENT_TYPE Type; - internal ConnectionEventDataUnion Data; - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate uint ConnectionCallbackDelegate( - IntPtr connection, - IntPtr context, - ConnectionEvent* connectionEvent); - - // TODO: order is Open, Close, Shutdown, Start, SetConfiguration, SendResumptionTicket - internal delegate uint ConnectionOpenDelegate( - SafeMsQuicRegistrationHandle registration, - ConnectionCallbackDelegate handler, - IntPtr context, - out SafeMsQuicConnectionHandle connection); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void ConnectionCloseDelegate( - IntPtr connection); - - internal delegate uint ConnectionSetConfigurationDelegate( - SafeMsQuicConnectionHandle connection, - SafeMsQuicConfigurationHandle configuration); - - internal delegate uint ConnectionStartDelegate( - SafeMsQuicConnectionHandle connection, - SafeMsQuicConfigurationHandle configuration, - QUIC_ADDRESS_FAMILY family, - [MarshalAs(UnmanagedType.LPUTF8Str)] - string serverName, - ushort serverPort); - - internal delegate void ConnectionShutdownDelegate( - SafeMsQuicConnectionHandle connection, - QUIC_CONNECTION_SHUTDOWN_FLAGS flags, - long errorCode); - - // TODO: missing SendResumptionTicket - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataStartComplete - { - internal uint Status; - internal ulong Id; - internal byte PeerAccepted; - }; - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataReceive - { - internal ulong AbsoluteOffset; - internal ulong TotalBufferLength; - internal QuicBuffer* Buffers; - internal uint BufferCount; - internal QUIC_RECEIVE_FLAGS Flags; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataSendComplete - { - internal byte Canceled; - internal IntPtr ClientContext; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataPeerSendAborted - { - internal long ErrorCode; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataPeerReceiveAborted - { - internal long ErrorCode; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataSendShutdownComplete - { - internal byte Graceful; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEventDataShutdownComplete - { - internal byte ConnectionShutdown; - } - - [StructLayout(LayoutKind.Explicit)] - internal struct StreamEventDataUnion - { - [FieldOffset(0)] - internal StreamEventDataStartComplete StartComplete; - - [FieldOffset(0)] - internal StreamEventDataReceive Receive; - - [FieldOffset(0)] - internal StreamEventDataSendComplete SendComplete; - - [FieldOffset(0)] - internal StreamEventDataPeerSendAborted PeerSendAborted; - - [FieldOffset(0)] - internal StreamEventDataPeerReceiveAborted PeerReceiveAborted; - - [FieldOffset(0)] - internal StreamEventDataSendShutdownComplete SendShutdownComplete; - - [FieldOffset(0)] - internal StreamEventDataShutdownComplete ShutdownComplete; - - // TODO: missing IDEAL_SEND_BUFFER_SIZE - } - - [StructLayout(LayoutKind.Sequential)] - internal struct StreamEvent - { - internal QUIC_STREAM_EVENT_TYPE Type; - internal StreamEventDataUnion Data; - } - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate uint StreamCallbackDelegate( - IntPtr stream, - IntPtr context, - StreamEvent* streamEvent); - - internal delegate uint StreamOpenDelegate( - SafeMsQuicConnectionHandle connection, - QUIC_STREAM_OPEN_FLAGS flags, - StreamCallbackDelegate handler, - IntPtr context, - out SafeMsQuicStreamHandle stream); - - internal delegate uint StreamStartDelegate( - SafeMsQuicStreamHandle stream, - QUIC_STREAM_START_FLAGS flags); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - internal delegate void StreamCloseDelegate( - IntPtr stream); - - internal delegate uint StreamShutdownDelegate( - SafeMsQuicStreamHandle stream, - QUIC_STREAM_SHUTDOWN_FLAGS flags, - long errorCode); - - internal delegate uint StreamSendDelegate( - SafeMsQuicStreamHandle stream, - QuicBuffer* buffers, - uint bufferCount, - QUIC_SEND_FLAGS flags, - IntPtr clientSendContext); - - internal delegate void StreamReceiveCompleteDelegate( - SafeMsQuicStreamHandle stream, - ulong bufferLength); - - internal delegate uint StreamReceiveSetEnabledDelegate( - SafeMsQuicStreamHandle stream, - bool enabled); - - [StructLayout(LayoutKind.Sequential)] - internal struct QuicBuffer - { - internal uint Length; - internal byte* Buffer; - } - - // TODO: DatagramSend missing - - internal struct DelegateHelper - { - private IntPtr _functionPointer; - - public DelegateHelper(IntPtr functionPointer) - { - _functionPointer = functionPointer; - } - internal uint SetContext(SafeHandle handle, IntPtr context) - { - IntPtr __handle_gen_native; - uint __retVal; - // - // Setup - // - bool handle__addRefd = false; - try - { - // - // Marshal - // - handle.DangerousAddRef(ref handle__addRefd); - __handle_gen_native = handle.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__handle_gen_native, context); - } - finally - { - // - // Cleanup - // - if (handle__addRefd) - handle.DangerousRelease(); - } - - return __retVal; - } - internal IntPtr GetContext(SafeHandle handle) - { - IntPtr __handle_gen_native; - IntPtr __retVal; - // - // Setup - // - bool handle__addRefd = false; - try - { - // - // Marshal - // - handle.DangerousAddRef(ref handle__addRefd); - __handle_gen_native = handle.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__handle_gen_native); - } - finally - { - // - // Cleanup - // - if (handle__addRefd) - handle.DangerousRelease(); - } - - return __retVal; - } - internal void SetCallbackHandler(SafeHandle handle, Delegate del, IntPtr context) - { - // - // Setup - // - bool handle__addRefd = false; - AnyDelegateMarshaller __del_gen_native__marshaller = default; - try - { - // - // Marshal - // - handle.DangerousAddRef(ref handle__addRefd); - IntPtr __handle_gen_native = handle.DangerousGetHandle(); - __del_gen_native__marshaller = new AnyDelegateMarshaller(del); - IntPtr __del_gen_native = __del_gen_native__marshaller.Value; - ((delegate* unmanaged[Cdecl])_functionPointer)(__handle_gen_native, __del_gen_native, context); - } - finally - { - // - // Cleanup - // - if (handle__addRefd) - handle.DangerousRelease(); - __del_gen_native__marshaller.FreeNative(); - } - } - internal uint SetParam(SafeHandle handle, uint param, uint bufferLength, byte* buffer) - { - uint __retVal; - // - // Setup - // - bool handle__addRefd = false; - try - { - // - // Marshal - // - handle.DangerousAddRef(ref handle__addRefd); - IntPtr __handle_gen_native = handle.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__handle_gen_native, param, bufferLength, buffer); - } - finally - { - // - // Cleanup - // - if (handle__addRefd) - handle.DangerousRelease(); - } - - return __retVal; - } - internal uint GetParam(SafeHandle handle, uint param, ref uint bufferLength, byte* buffer) - { - IntPtr __handle_gen_native = default; - uint __retVal; - // - // Setup - // - bool handle__addRefd = false; - try - { - // - // Marshal - // - handle.DangerousAddRef(ref handle__addRefd); - __handle_gen_native = handle.DangerousGetHandle(); - fixed (uint* __bufferLength_gen_native = &bufferLength) - { - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__handle_gen_native, param, __bufferLength_gen_native, buffer); - } - } - finally - { - // - // Cleanup - // - if (handle__addRefd) - handle.DangerousRelease(); - } - - return __retVal; - } - internal uint RegistrationOpen(ref RegistrationConfig config, out SafeMsQuicRegistrationHandle registrationContext) - { - RegistrationConfig.Native __config_gen_native = default; - registrationContext = default!; - IntPtr __registrationContext_gen_native = default; - uint __retVal; - bool __invokeSucceeded = default; - // - // Setup - // - SafeMsQuicRegistrationHandle registrationContext__newHandle = new SafeMsQuicRegistrationHandle(); - try - { - // - // Marshal - // - __config_gen_native = new RegistrationConfig.Native(config); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(&__config_gen_native, &__registrationContext_gen_native); - __invokeSucceeded = true; - // - // Unmarshal - // - config = __config_gen_native.ToManaged(); - } - finally - { - if (__invokeSucceeded) - { - // - // GuaranteedUnmarshal - // - Marshal.InitHandle(registrationContext__newHandle, __registrationContext_gen_native); - registrationContext = registrationContext__newHandle; - } - - // - // Cleanup - // - __config_gen_native.FreeNative(); - } - - return __retVal; - } - internal uint ConfigurationOpen(SafeMsQuicRegistrationHandle registrationContext, QuicBuffer* alpnBuffers, uint alpnBufferCount, ref QuicSettings settings, uint settingsSize, IntPtr context, out SafeMsQuicConfigurationHandle configuration) - { - IntPtr __registrationContext_gen_native = default; - configuration = default!; - IntPtr __configuration_gen_native = default; - uint __retVal; - bool __invokeSucceeded = default; - // - // Setup - // - bool registrationContext__addRefd = false; - SafeMsQuicConfigurationHandle configuration__newHandle = new SafeMsQuicConfigurationHandle(); - try - { - // - // Marshal - // - registrationContext.DangerousAddRef(ref registrationContext__addRefd); - __registrationContext_gen_native = registrationContext.DangerousGetHandle(); - fixed (QuicSettings* __settings_gen_native = &settings) - { - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__registrationContext_gen_native, alpnBuffers, alpnBufferCount, __settings_gen_native, settingsSize, context, &__configuration_gen_native); - } - - __invokeSucceeded = true; - } - finally - { - if (__invokeSucceeded) - { - // - // GuaranteedUnmarshal - // - Marshal.InitHandle(configuration__newHandle, __configuration_gen_native); - configuration = configuration__newHandle; - } - - // - // Cleanup - // - if (registrationContext__addRefd) - registrationContext.DangerousRelease(); - } - - return __retVal; - } - internal uint ConfigurationLoadCredential(SafeMsQuicConfigurationHandle configuration, ref CredentialConfig credConfig) - { - CredentialConfig.Native __credConfig_gen_native = default; - uint __retVal; - // - // Setup - // - bool configuration__addRefd = false; - try - { - // - // Marshal - // - configuration.DangerousAddRef(ref configuration__addRefd); - IntPtr __configuration_gen_native = configuration.DangerousGetHandle(); - __credConfig_gen_native = new CredentialConfig.Native(credConfig); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__configuration_gen_native, &__credConfig_gen_native); - // - // Unmarshal - // - credConfig = __credConfig_gen_native.ToManaged(); - } - finally - { - // - // Cleanup - // - if (configuration__addRefd) - configuration.DangerousRelease(); - __credConfig_gen_native.FreeNative(); - } - - return __retVal; - } - internal uint ListenerOpen(SafeMsQuicRegistrationHandle registration, ListenerCallbackDelegate handler, IntPtr context, out SafeMsQuicListenerHandle listener) - { - IntPtr __handler_gen_native = default; - listener = default!; - IntPtr __listener_gen_native = default; - uint __retVal; - bool __invokeSucceeded = default; - // - // Setup - // - bool registration__addRefd = false; - SafeMsQuicListenerHandle listener__newHandle = new SafeMsQuicListenerHandle(); - try - { - // - // Marshal - // - registration.DangerousAddRef(ref registration__addRefd); - IntPtr __registration_gen_native = registration.DangerousGetHandle(); - __handler_gen_native = handler != null ? Marshal.GetFunctionPointerForDelegate(handler) : default; - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__registration_gen_native, __handler_gen_native, context, &__listener_gen_native); - __invokeSucceeded = true; - // - // KeepAlive - // - GC.KeepAlive(handler); - } - finally - { - if (__invokeSucceeded) - { - // - // GuaranteedUnmarshal - // - Marshal.InitHandle(listener__newHandle, __listener_gen_native); - listener = listener__newHandle; - } - - // - // Cleanup - // - if (registration__addRefd) - registration.DangerousRelease(); - } - - return __retVal; - } - internal uint ListenerStart(SafeMsQuicListenerHandle listener, QuicBuffer* alpnBuffers, uint alpnBufferCount, byte* localAddress) - { - IntPtr __listener_gen_native; - uint __retVal; - // - // Setup - // - bool listener__addRefd = false; - try - { - // - // Marshal - // - listener.DangerousAddRef(ref listener__addRefd); - __listener_gen_native = listener.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__listener_gen_native, alpnBuffers, alpnBufferCount, localAddress); - } - finally - { - // - // Cleanup - // - if (listener__addRefd) - listener.DangerousRelease(); - } - - return __retVal; - } - internal void ListenerStop(SafeMsQuicListenerHandle listener) - { - // - // Setup - // - bool listener__addRefd = false; - try - { - // - // Marshal - // - listener.DangerousAddRef(ref listener__addRefd); - IntPtr __listener_gen_native = listener.DangerousGetHandle(); - ((delegate* unmanaged[Cdecl])_functionPointer)(__listener_gen_native); - } - finally - { - // - // Cleanup - // - if (listener__addRefd) - listener.DangerousRelease(); - } - } - internal uint ConnectionOpen(SafeMsQuicRegistrationHandle registration, ConnectionCallbackDelegate handler, IntPtr context, out SafeMsQuicConnectionHandle connection) - { - IntPtr __handler_gen_native = default; - connection = default!; - IntPtr __connection_gen_native = default; - uint __retVal; - bool __invokeSucceeded = default; - // - // Setup - // - bool registration__addRefd = false; - SafeMsQuicConnectionHandle connection__newHandle = new SafeMsQuicConnectionHandle(); - try - { - // - // Marshal - // - registration.DangerousAddRef(ref registration__addRefd); - IntPtr __registration_gen_native = registration.DangerousGetHandle(); - __handler_gen_native = handler != null ? Marshal.GetFunctionPointerForDelegate(handler) : default; - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__registration_gen_native, __handler_gen_native, context, &__connection_gen_native); - __invokeSucceeded = true; - // - // KeepAlive - // - GC.KeepAlive(handler); - } - finally - { - if (__invokeSucceeded) - { - // - // GuaranteedUnmarshal - // - Marshal.InitHandle(connection__newHandle, __connection_gen_native); - connection = connection__newHandle; - } - - // - // Cleanup - // - if (registration__addRefd) - registration.DangerousRelease(); - } - - return __retVal; - } - internal uint ConnectionSetConfiguration(SafeMsQuicConnectionHandle connection, SafeMsQuicConfigurationHandle configuration) - { - uint __retVal; - // - // Setup - // - bool connection__addRefd = false; - bool configuration__addRefd = false; - try - { - // - // Marshal - // - connection.DangerousAddRef(ref connection__addRefd); - IntPtr __connection_gen_native = connection.DangerousGetHandle(); - configuration.DangerousAddRef(ref configuration__addRefd); - IntPtr __configuration_gen_native = configuration.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__connection_gen_native, __configuration_gen_native); - } - finally - { - // - // Cleanup - // - if (connection__addRefd) - connection.DangerousRelease(); - if (configuration__addRefd) - configuration.DangerousRelease(); - } - - return __retVal; - } - internal uint ConnectionStart(SafeMsQuicConnectionHandle connection, SafeMsQuicConfigurationHandle configuration, QUIC_ADDRESS_FAMILY family, string serverName, ushort serverPort) - { - IntPtr __connection_gen_native = default; - IntPtr __configuration_gen_native = default; - byte* __serverName_gen_native = default; - uint __retVal; - // - // Setup - // - bool connection__addRefd = false; - bool configuration__addRefd = false; - bool __serverName_gen_native__allocated = false; - try - { - // - // Marshal - // - connection.DangerousAddRef(ref connection__addRefd); - __connection_gen_native = connection.DangerousGetHandle(); - configuration.DangerousAddRef(ref configuration__addRefd); - __configuration_gen_native = configuration.DangerousGetHandle(); - if (serverName != null) - { - int __serverName_gen_native__bytelen = (serverName.Length + 1) * 3 + 1; - if (__serverName_gen_native__bytelen > 260) - { - __serverName_gen_native = (byte*)Marshal.StringToCoTaskMemUTF8(serverName); - __serverName_gen_native__allocated = true; - } - else - { - byte* __serverName_gen_native__stackptr = stackalloc byte[__serverName_gen_native__bytelen]; - { - __serverName_gen_native__bytelen = Text.Encoding.UTF8.GetBytes(serverName, new Span(__serverName_gen_native__stackptr, __serverName_gen_native__bytelen)); - __serverName_gen_native__stackptr[__serverName_gen_native__bytelen] = 0; - } - - __serverName_gen_native = (byte*)__serverName_gen_native__stackptr; - } - } - - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__connection_gen_native, __configuration_gen_native, family, __serverName_gen_native, serverPort); - } - finally - { - // - // Cleanup - // - if (connection__addRefd) - connection.DangerousRelease(); - if (configuration__addRefd) - configuration.DangerousRelease(); - if (__serverName_gen_native__allocated) - { - Marshal.FreeCoTaskMem((IntPtr)__serverName_gen_native); - } - } - - return __retVal; - } - internal void ConnectionShutdown(SafeMsQuicConnectionHandle connection, QUIC_CONNECTION_SHUTDOWN_FLAGS flags, long errorCode) - { - // - // Setup - // - bool connection__addRefd = false; - try - { - // - // Marshal - // - connection.DangerousAddRef(ref connection__addRefd); - IntPtr __connection_gen_native = connection.DangerousGetHandle(); - ((delegate* unmanaged[Cdecl])_functionPointer)(__connection_gen_native, flags, errorCode); - } - finally - { - // - // Cleanup - // - if (connection__addRefd) - connection.DangerousRelease(); - } - } - internal uint StreamOpen(SafeMsQuicConnectionHandle connection, QUIC_STREAM_OPEN_FLAGS flags, StreamCallbackDelegate handler, IntPtr context, out SafeMsQuicStreamHandle stream) - { - IntPtr __handler_gen_native = default; - stream = default!; - IntPtr __stream_gen_native = default; - uint __retVal; - bool __invokeSucceeded = default; - // - // Setup - // - bool connection__addRefd = false; - SafeMsQuicStreamHandle stream__newHandle = new SafeMsQuicStreamHandle(); - try - { - // - // Marshal - // - connection.DangerousAddRef(ref connection__addRefd); - IntPtr __connection_gen_native = connection.DangerousGetHandle(); - __handler_gen_native = handler != null ? Marshal.GetFunctionPointerForDelegate(handler) : default; - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__connection_gen_native, flags, __handler_gen_native, context, &__stream_gen_native); - __invokeSucceeded = true; - // - // KeepAlive - // - GC.KeepAlive(handler); - } - finally - { - if (__invokeSucceeded) - { - // - // GuaranteedUnmarshal - // - Marshal.InitHandle(stream__newHandle, __stream_gen_native); - stream = stream__newHandle; - } - - // - // Cleanup - // - if (connection__addRefd) - connection.DangerousRelease(); - } - - return __retVal; - } - internal uint StreamStart(SafeMsQuicStreamHandle stream, QUIC_STREAM_START_FLAGS flags) - { - uint __retVal; - // - // Setup - // - bool stream__addRefd = false; - try - { - // - // Marshal - // - stream.DangerousAddRef(ref stream__addRefd); - IntPtr __stream_gen_native = stream.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__stream_gen_native, flags); - } - finally - { - // - // Cleanup - // - if (stream__addRefd) - stream.DangerousRelease(); - } - - return __retVal; - } - internal uint StreamShutdown(SafeMsQuicStreamHandle stream, QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) - { - uint __retVal; - // - // Setup - // - bool stream__addRefd = false; - try - { - // - // Marshal - // - stream.DangerousAddRef(ref stream__addRefd); - IntPtr __stream_gen_native = stream.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__stream_gen_native, flags, errorCode); - } - finally - { - // - // Cleanup - // - if (stream__addRefd) - stream.DangerousRelease(); - } - - return __retVal; - } - internal uint StreamSend(SafeMsQuicStreamHandle stream, QuicBuffer* buffers, uint bufferCount, QUIC_SEND_FLAGS flags, IntPtr clientSendContext) - { - uint __retVal; - // - // Setup - // - bool stream__addRefd = false; - try - { - // - // Marshal - // - stream.DangerousAddRef(ref stream__addRefd); - IntPtr __stream_gen_native = stream.DangerousGetHandle(); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__stream_gen_native, buffers, bufferCount, flags, clientSendContext); - } - finally - { - // - // Cleanup - // - if (stream__addRefd) - stream.DangerousRelease(); - } - - return __retVal; - } - internal void StreamReceiveComplete(SafeMsQuicStreamHandle stream, ulong bufferLength) - { - // - // Setup - // - bool stream__addRefd = false; - try - { - // - // Marshal - // - stream.DangerousAddRef(ref stream__addRefd); - IntPtr __stream_gen_native = stream.DangerousGetHandle(); - ((delegate* unmanaged[Cdecl])_functionPointer)(__stream_gen_native, bufferLength); - } - finally - { - // - // Cleanup - // - if (stream__addRefd) - stream.DangerousRelease(); - } - } - internal uint StreamReceiveSetEnabled(SafeMsQuicStreamHandle stream, bool enabled) - { - uint __retVal; - // - // Setup - // - bool stream__addRefd = false; - try - { - // - // Marshal - // - stream.DangerousAddRef(ref stream__addRefd); - IntPtr __stream_gen_native = stream.DangerousGetHandle(); - byte __enabled_gen_native = (byte)(enabled ? 1 : 0); - __retVal = ((delegate* unmanaged[Cdecl])_functionPointer)(__stream_gen_native, __enabled_gen_native); - } - finally - { - // - // Cleanup - // - if (stream__addRefd) - stream.DangerousRelease(); - } - - return __retVal; - } - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicSafeHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicSafeHandle.cs new file mode 100644 index 00000000000000..5ac710f972e090 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicSafeHandle.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Microsoft.Quic; + +namespace System.Net.Quic.Implementations.MsQuic.Internal +{ + internal abstract class MsQuicSafeHandle : SafeHandle + { + private readonly Action _releaseAction; + private readonly string _traceId; + + public override bool IsInvalid => handle == IntPtr.Zero; + + public unsafe QUIC_HANDLE* QuicHandle => (QUIC_HANDLE*)DangerousGetHandle(); + + protected unsafe MsQuicSafeHandle(QUIC_HANDLE* handle, Action releaseAction, string prefix) + : base((IntPtr)handle, ownsHandle: true) + { + _releaseAction = releaseAction; + _traceId = $"[{prefix}][0x{DangerousGetHandle():X11}]"; + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "MsQuicSafeHandle created"); + } + } + + protected override bool ReleaseHandle() + { + _releaseAction(handle); + SetHandle(IntPtr.Zero); + + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(this, "MsQuicSafeHandle released"); + } + + return true; + } + + public override string ToString() => _traceId; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Linux.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Linux.cs deleted file mode 100644 index d99df7976d7951..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Linux.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static partial class MsQuicStatusCodes - { - internal const uint Success = 0; - internal const uint Pending = unchecked((uint)-2); - internal const uint Continue = unchecked((uint)-1); - internal const uint OutOfMemory = 12; // ENOMEM - internal const uint InvalidParameter = 22; // EINVAL - internal const uint InvalidState = 1; // EPERM - internal const uint NotSupported = 95; // EOPNOTSUPP - internal const uint NotFound = 2; // ENOENT - internal const uint BufferTooSmall = 75; // EOVERFLOW - internal const uint HandshakeFailure = 103; // ECONNABORTED - internal const uint Aborted = 125; // ECANCELED - internal const uint AddressInUse = 98; // EADDRINUSE - internal const uint ConnectionTimeout = 110; // ETIMEDOUT - internal const uint ConnectionIdle = 62; // ETIME - internal const uint HostUnreachable = 113; // EHOSTUNREACH - internal const uint InternalError = 5; // EIO - internal const uint ConnectionRefused = 111; // ECONNREFUSED - internal const uint ProtocolError = 71; // EPROTO - internal const uint VerNegError = 93; // EPROTONOSUPPORT - internal const uint TlsError = 126; // ENOKEY - internal const uint UserCanceled = 130; // EOWNERDEAD - internal const uint AlpnNegotiationFailure = 92;// ENOPROTOOPT - internal const uint StreamLimit = 86; // ESTRPIPE - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.OSX.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.OSX.cs deleted file mode 100644 index 03fc254f24781b..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.OSX.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static partial class MsQuicStatusCodes - { - internal const uint Success = 0; - internal const uint Pending = unchecked((uint)-2); - internal const uint Continue = unchecked((uint)-1); - internal const uint OutOfMemory = 12; // ENOMEM - internal const uint InvalidParameter = 22; // EINVAL - internal const uint InvalidState = 1; // EPERM - internal const uint NotSupported = 102; // EOPNOTSUPP - internal const uint NotFound = 2; // ENOENT - internal const uint BufferTooSmall = 84; // EOVERFLOW - internal const uint HandshakeFailure = 53; // ECONNABORTED - internal const uint Aborted = 89; // ECANCELED - internal const uint AddressInUse = 48; // EADDRINUSE - internal const uint ConnectionTimeout = 60; // ETIMEDOUT - internal const uint ConnectionIdle = 101; // ETIME - internal const uint HostUnreachable = 65; // EHOSTUNREACH - internal const uint InternalError = 5; // EIO - internal const uint ConnectionRefused = 61; // ECONNREFUSED - internal const uint ProtocolError = 100; // EPROTO - internal const uint VerNegError = 43; // EPROTONOSUPPORT - internal const uint TlsError = 126; // ENOKEY Linux value - internal const uint UserCanceled = 105; // EOWNERDEAD - internal const uint AlpnNegotiationFailure = 42;// ENOPROTOOPT - internal const uint StreamLimit = 86; // ESTRPIPE Linux value - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Windows.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Windows.cs deleted file mode 100644 index 003aaa84ec6573..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Windows.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static partial class MsQuicStatusCodes - { - internal const uint Success = 0; - internal const uint Pending = 0x703E5; - internal const uint Continue = 0x704DE; - internal const uint OutOfMemory = 0x8007000E; - internal const uint InvalidParameter = 0x80070057; - internal const uint InvalidState = 0x8007139F; - internal const uint NotSupported = 0x80004002; - internal const uint NotFound = 0x80070490; - internal const uint BufferTooSmall = 0x8007007A; - internal const uint HandshakeFailure = 0x80410000; - internal const uint Aborted = 0x80004004; - internal const uint AddressInUse = 0x80072740; - internal const uint ConnectionTimeout = 0x80410006; - internal const uint ConnectionIdle = 0x80410005; - internal const uint HostUnreachable = 0x800704D0; - internal const uint InternalError = 0x80410003; - internal const uint ConnectionRefused = 0x800704C9; - internal const uint ProtocolError = 0x80410004; - internal const uint VerNegError = 0x80410001; - internal const uint TlsError = 0x80072B18; - internal const uint UserCanceled = 0x80410002; - internal const uint AlpnNegotiationFailure = 0x80410007; - internal const uint StreamLimit = 0x80410008; - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.cs deleted file mode 100644 index 50bc0612ae3c7e..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static partial class MsQuicStatusCodes - { - // TODO return better error messages here. - public static string GetError(uint status) - { - return status switch - { - Success => "SUCCESS", - Pending => "PENDING", - Continue => "CONTINUE", - OutOfMemory => "OUT_OF_MEMORY", - InvalidParameter => "INVALID_PARAMETER", - InvalidState => "INVALID_STATE", - NotSupported => "NOT_SUPPORTED", - NotFound => "NOT_FOUND", - BufferTooSmall => "BUFFER_TOO_SMALL", - HandshakeFailure => "HANDSHAKE_FAILURE", - Aborted => "ABORTED", - AddressInUse => "ADDRESS_IN_USE", - ConnectionTimeout => "CONNECTION_TIMEOUT", - ConnectionIdle => "CONNECTION_IDLE", - HostUnreachable => "UNREACHABLE", - InternalError => "INTERNAL_ERROR", - ConnectionRefused => "CONNECTION_REFUSED", - ProtocolError => "PROTOCOL_ERROR", - VerNegError => "VER_NEG_ERROR", - TlsError => "TLS_ERROR", - UserCanceled => "USER_CANCELED", - AlpnNegotiationFailure => "ALPN_NEG_FAILURE", - StreamLimit => "STREAM_LIMIT_REACHED", - _ => $"0x{status:X8}" - }; - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusHelper.cs deleted file mode 100644 index 4f2bedb1410364..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusHelper.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static class MsQuicStatusHelper - { - internal static bool SuccessfulStatusCode(uint status) - { - if (OperatingSystem.IsWindows()) - { - return status < 0x80000000; - } - - if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) - { - return (int)status <= 0; - } - - return false; - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicTraceHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicTraceHelper.cs deleted file mode 100644 index cd7b4ba9a64f07..00000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicTraceHelper.cs +++ /dev/null @@ -1,30 +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.Runtime.InteropServices; - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static class MsQuicTraceHelper - { - internal static string GetTraceId(SafeMsQuicStreamHandle handle) - { - return $"[strm][0x{GetIntPtrHex(handle)}]"; - } - - internal static string GetTraceId(SafeMsQuicConnectionHandle handle) - { - return $"[conn][0x{GetIntPtrHex(handle)}]"; - } - - internal static string GetTraceId(SafeMsQuicListenerHandle handle) - { - return $"[list][0x{GetIntPtrHex(handle)}]"; - } - - private static string GetIntPtrHex(SafeHandle handle) - { - return handle.DangerousGetHandle().ToString("X11"); - } - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs index dba6e6cfb5301f..75483157fee247 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs @@ -9,28 +9,20 @@ using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Threading; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; +using Microsoft.Quic; +using static Microsoft.Quic.MsQuic; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicConfigurationHandle : SafeHandle + internal sealed class SafeMsQuicConfigurationHandle : MsQuicSafeHandle { private static readonly FieldInfo _contextCertificate = typeof(SslStreamCertificateContext).GetField("Certificate", BindingFlags.NonPublic | BindingFlags.Instance)!; private static readonly FieldInfo _contextChain = typeof(SslStreamCertificateContext).GetField("IntermediateCertificates", BindingFlags.NonPublic | BindingFlags.Instance)!; - public override bool IsInvalid => handle == IntPtr.Zero; - - public SafeMsQuicConfigurationHandle() - : base(IntPtr.Zero, ownsHandle: true) + public unsafe SafeMsQuicConfigurationHandle(QUIC_HANDLE* handle) + : base(handle, ptr => MsQuicApi.Api.ApiTable->ConfigurationClose((QUIC_HANDLE*)ptr), "cnfg") { } - protected override bool ReleaseHandle() - { - MsQuicApi.Api.ConfigurationCloseDelegate(handle); - SetHandle(IntPtr.Zero); - return true; - } - // TODO: consider moving the static code from here to keep all the handle classes small and simple. public static SafeMsQuicConfigurationHandle Create(QuicClientConnectionOptions options) { @@ -63,12 +55,12 @@ public static SafeMsQuicConfigurationHandle Create(QuicClientConnectionOptions o } } - return Create(options, QUIC_CREDENTIAL_FLAGS.CLIENT, certificate: certificate, certificateContext: null, options.ClientAuthenticationOptions?.ApplicationProtocols, options.ClientAuthenticationOptions?.CipherSuitesPolicy); + return Create(options, QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_CLIENT, certificate: certificate, certificateContext: null, options.ClientAuthenticationOptions?.ApplicationProtocols, options.ClientAuthenticationOptions?.CipherSuitesPolicy); } public static SafeMsQuicConfigurationHandle Create(QuicOptions options, SslServerAuthenticationOptions? serverAuthenticationOptions, string? targetHost = null) { - QUIC_CREDENTIAL_FLAGS flags = QUIC_CREDENTIAL_FLAGS.NONE; + QUIC_CREDENTIAL_FLAGS flags = QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_NONE; X509Certificate? certificate = serverAuthenticationOptions?.ServerCertificate; if (serverAuthenticationOptions != null) @@ -82,7 +74,7 @@ public static SafeMsQuicConfigurationHandle Create(QuicOptions options, SslServe if (serverAuthenticationOptions.ClientCertificateRequired) { - flags |= QUIC_CREDENTIAL_FLAGS.REQUIRE_CLIENT_AUTHENTICATION | QUIC_CREDENTIAL_FLAGS.INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.NO_CERTIFICATE_VALIDATION; + flags |= QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION | QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION; } if (certificate == null && serverAuthenticationOptions?.ServerCertificateSelectionCallback != null && targetHost != null) @@ -114,7 +106,7 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, throw new Exception("MaxBidirectionalStreams overflow."); } - if ((flags & QUIC_CREDENTIAL_FLAGS.CLIENT) == 0) + if ((flags & QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_CLIENT) == 0) { if (certificate == null && certificateContext == null) { @@ -123,66 +115,67 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, } else { - flags |= QUIC_CREDENTIAL_FLAGS.INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.NO_CERTIFICATE_VALIDATION; + flags |= QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION; } if (!OperatingSystem.IsWindows()) { // Use certificate handles on Windows, fall-back to ASN1 otherwise. - flags |= QUIC_CREDENTIAL_FLAGS.USE_PORTABLE_CERTIFICATES; + flags |= QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_USE_PORTABLE_CERTIFICATES; } Debug.Assert(!MsQuicApi.Api.Registration.IsInvalid); - var settings = new QuicSettings - { - IsSetFlags = QuicSettingsIsSetFlags.PeerBidiStreamCount | - QuicSettingsIsSetFlags.PeerUnidiStreamCount, - PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams, - PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams - }; + QUIC_SETTINGS settings = default(QUIC_SETTINGS); + settings.IsSet.PeerUnidiStreamCount = 1; + settings.PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams; + settings.IsSet.PeerBidiStreamCount = 1; + settings.PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams; + settings.IsSet.IdleTimeoutMs = 1; if (options.IdleTimeout != Timeout.InfiniteTimeSpan) { if (options.IdleTimeout <= TimeSpan.Zero) throw new Exception("IdleTimeout must not be negative."); - - ulong ms = (ulong)options.IdleTimeout.Ticks / TimeSpan.TicksPerMillisecond; - if (ms > (1ul << 62) - 1) throw new Exception("IdleTimeout is too large (max 2^62-1 milliseconds)"); - settings.IdleTimeoutMs = (ulong)options.IdleTimeout.TotalMilliseconds; } else { settings.IdleTimeoutMs = 0; } - settings.IsSetFlags |= QuicSettingsIsSetFlags.IdleTimeoutMs; - uint status; - SafeMsQuicConfigurationHandle? configurationHandle; + SafeMsQuicConfigurationHandle configurationHandle; X509Certificate2[]? intermediates = null; MemoryHandle[]? handles = null; - QuicBuffer[]? buffers = null; + // TODO: should they be pinned? The content is pinned, but the array holding the individual buffers isn't. + QUIC_BUFFER[]? buffers = null; try { + QUIC_HANDLE* handle; MsQuicAlpnHelper.Prepare(alpnProtocols, out handles, out buffers); - status = MsQuicApi.Api.ConfigurationOpenDelegate(MsQuicApi.Api.Registration, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)alpnProtocols.Count, ref settings, (uint)sizeof(QuicSettings), context: IntPtr.Zero, out configurationHandle); + ThrowIfFailure(MsQuicApi.Api.ApiTable->ConfigurationOpen( + MsQuicApi.Api.Registration.QuicHandle, + (QUIC_BUFFER*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), + (uint)alpnProtocols.Count, + &settings, + (uint)sizeof(QUIC_SETTINGS), + (void*)IntPtr.Zero, + &handle), "ConfigurationOpen failed"); + configurationHandle = new SafeMsQuicConfigurationHandle(handle); } finally { MsQuicAlpnHelper.Return(ref handles, ref buffers); } - QuicExceptionHelpers.ThrowIfFailed(status, "ConfigurationOpen failed."); - try { - CredentialConfig config = default; + QUIC_CREDENTIAL_CONFIG config = default; config.Flags = flags; // TODO: consider using LOAD_ASYNCHRONOUS with a callback. if (cipherSuitesPolicy != null) { - config.Flags |= QUIC_CREDENTIAL_FLAGS.SET_ALLOWED_CIPHER_SUITES; + config.Flags |= QUIC_CREDENTIAL_FLAGS.QUIC_CREDENTIAL_FLAG_SET_ALLOWED_CIPHER_SUITES; config.AllowedCipherSuites = CipherSuitePolicyToFlags(cipherSuitesPolicy); } @@ -197,17 +190,17 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, } } + int status; if (certificate != null) { if (OperatingSystem.IsWindows()) { - config.Type = QUIC_CREDENTIAL_TYPE.CONTEXT; - config.Certificate = certificate.Handle; - status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config); + config.Type = QUIC_CREDENTIAL_TYPE.QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT; + config.CertificateContext = (void*)certificate.Handle; + status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); } else { - CredentialConfigCertificatePkcs12 pkcs12Config; byte[] asn1; if (intermediates?.Length > 0) @@ -226,32 +219,35 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, asn1 = certificate.Export(X509ContentType.Pkcs12); } - fixed (void* ptr = asn1) + fixed (byte* ptr = asn1) { - pkcs12Config.Asn1Blob = (IntPtr)ptr; - pkcs12Config.Asn1BlobLength = (uint)asn1.Length; - pkcs12Config.PrivateKeyPassword = IntPtr.Zero; - - config.Type = QUIC_CREDENTIAL_TYPE.PKCS12; - config.Certificate = (IntPtr)(&pkcs12Config); - status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config); + QUIC_CERTIFICATE_PKCS12 pkcs12Config = new QUIC_CERTIFICATE_PKCS12 + { + Asn1Blob = ptr, + Asn1BlobLength = (uint)asn1.Length, + PrivateKeyPassword = (sbyte*)IntPtr.Zero + }; + + config.Type = QUIC_CREDENTIAL_TYPE.QUIC_CREDENTIAL_TYPE_CERTIFICATE_PKCS12; + config.CertificatePkcs12 = &pkcs12Config; + status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); } } } else { - config.Type = QUIC_CREDENTIAL_TYPE.NONE; - status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config); + config.Type = QUIC_CREDENTIAL_TYPE.QUIC_CREDENTIAL_TYPE_NONE; + status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); } #if TARGET_WINDOWS if ((Interop.SECURITY_STATUS)status == Interop.SECURITY_STATUS.AlgorithmMismatch && MsQuicApi.Tls13MayBeDisabled) { - throw new QuicException(SR.net_ssl_app_protocols_invalid, null, (int)status); + throw new MsQuicException(status, SR.net_ssl_app_protocols_invalid); } #endif - QuicExceptionHelpers.ThrowIfFailed(status, "ConfigurationLoadCredential failed."); + ThrowIfFailure(status, "ConfigurationLoadCredential failed"); } catch { @@ -264,20 +260,20 @@ private static unsafe SafeMsQuicConfigurationHandle Create(QuicOptions options, private static QUIC_ALLOWED_CIPHER_SUITE_FLAGS CipherSuitePolicyToFlags(CipherSuitesPolicy cipherSuitesPolicy) { - QUIC_ALLOWED_CIPHER_SUITE_FLAGS flags = QUIC_ALLOWED_CIPHER_SUITE_FLAGS.NONE; + QUIC_ALLOWED_CIPHER_SUITE_FLAGS flags = QUIC_ALLOWED_CIPHER_SUITE_FLAGS.QUIC_ALLOWED_CIPHER_SUITE_NONE; foreach (TlsCipherSuite cipher in cipherSuitesPolicy.AllowedCipherSuites) { switch (cipher) { case TlsCipherSuite.TLS_AES_128_GCM_SHA256: - flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.AES_128_GCM_SHA256; + flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.QUIC_ALLOWED_CIPHER_SUITE_AES_128_GCM_SHA256; break; case TlsCipherSuite.TLS_AES_256_GCM_SHA384: - flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.AES_256_GCM_SHA384; + flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.QUIC_ALLOWED_CIPHER_SUITE_AES_256_GCM_SHA384; break; case TlsCipherSuite.TLS_CHACHA20_POLY1305_SHA256: - flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.CHACHA20_POLY1305_SHA256; + flags |= QUIC_ALLOWED_CIPHER_SUITE_FLAGS.QUIC_ALLOWED_CIPHER_SUITE_CHACHA20_POLY1305_SHA256; break; case TlsCipherSuite.TLS_AES_128_CCM_SHA256: // not supported by MsQuic (yet?), but QUIC RFC allows it so we ignore it. default: @@ -286,7 +282,7 @@ private static QUIC_ALLOWED_CIPHER_SUITE_FLAGS CipherSuitePolicyToFlags(CipherSu } } - if (flags == QUIC_ALLOWED_CIPHER_SUITE_FLAGS.NONE) + if (flags == QUIC_ALLOWED_CIPHER_SUITE_FLAGS.QUIC_ALLOWED_CIPHER_SUITE_NONE) { throw new ArgumentException(SR.net_quic_empty_cipher_suite, nameof(SslClientAuthenticationOptions.CipherSuitesPolicy)); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConnectionHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConnectionHandle.cs index 9354ce04a18e94..10fe176f94b17c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConnectionHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConnectionHandle.cs @@ -1,29 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; +using Microsoft.Quic; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicConnectionHandle : SafeHandle + internal sealed class SafeMsQuicConnectionHandle : MsQuicSafeHandle { - public override bool IsInvalid => handle == IntPtr.Zero; - - public SafeMsQuicConnectionHandle() - : base(IntPtr.Zero, ownsHandle: true) + public unsafe SafeMsQuicConnectionHandle(QUIC_HANDLE* handle) + : base(handle, ptr => MsQuicApi.Api.ApiTable->ConnectionClose((QUIC_HANDLE*)ptr), "conn") { } - - public SafeMsQuicConnectionHandle(IntPtr connectionHandle) - : this() - { - SetHandle(connectionHandle); - } - - protected override bool ReleaseHandle() - { - MsQuicApi.Api.ConnectionCloseDelegate(handle); - SetHandle(IntPtr.Zero); - return true; - } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicListenerHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicListenerHandle.cs index f0f75556921c3c..04387c049ab6a6 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicListenerHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicListenerHandle.cs @@ -1,23 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; +using Microsoft.Quic; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicListenerHandle : SafeHandle + internal sealed class SafeMsQuicListenerHandle : MsQuicSafeHandle { - public override bool IsInvalid => handle == IntPtr.Zero; - - public SafeMsQuicListenerHandle() - : base(IntPtr.Zero, ownsHandle: true) + public unsafe SafeMsQuicListenerHandle(QUIC_HANDLE* handle) + : base(handle, ptr => MsQuicApi.Api.ApiTable->ListenerClose((QUIC_HANDLE*)ptr), "list") { } - - protected override bool ReleaseHandle() - { - MsQuicApi.Api.ListenerCloseDelegate(handle); - SetHandle(IntPtr.Zero); - return true; - } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicRegistrationHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicRegistrationHandle.cs index 798636bd7e4313..0595f10dbe3479 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicRegistrationHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicRegistrationHandle.cs @@ -1,23 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; +using Microsoft.Quic; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicRegistrationHandle : SafeHandle + internal sealed class SafeMsQuicRegistrationHandle : MsQuicSafeHandle { - public override bool IsInvalid => handle == IntPtr.Zero; - - public SafeMsQuicRegistrationHandle() - : base(IntPtr.Zero, ownsHandle: true) + public unsafe SafeMsQuicRegistrationHandle(QUIC_HANDLE* handle) + : base(handle, ptr => MsQuicApi.Api.ApiTable->RegistrationClose((QUIC_HANDLE*)ptr), " reg") { } - - protected override bool ReleaseHandle() - { - MsQuicApi.Api.RegistrationCloseDelegate(handle); - SetHandle(IntPtr.Zero); - return true; - } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicStreamHandle.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicStreamHandle.cs index 179bdd3d15e1c5..4b1bd48a92eb96 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicStreamHandle.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicStreamHandle.cs @@ -1,29 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Runtime.InteropServices; +using Microsoft.Quic; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicStreamHandle : SafeHandle + internal sealed class SafeMsQuicStreamHandle : MsQuicSafeHandle { - public override bool IsInvalid => handle == IntPtr.Zero; - - public SafeMsQuicStreamHandle() - : base(IntPtr.Zero, ownsHandle: true) + public unsafe SafeMsQuicStreamHandle(QUIC_HANDLE* handle) + : base(handle, ptr => MsQuicApi.Api.ApiTable->StreamClose((QUIC_HANDLE*)ptr), "strm") { } - - public SafeMsQuicStreamHandle(IntPtr streamHandle) - : this() - { - SetHandle(streamHandle); - } - - protected override bool ReleaseHandle() - { - MsQuicApi.Api.StreamCloseDelegate(handle); - SetHandle(IntPtr.Zero); - return true; - } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic.cs new file mode 100644 index 00000000000000..c1912d00a8a296 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic.cs @@ -0,0 +1,191 @@ +#pragma warning disable IDE0073 +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +#pragma warning restore IDE0073 + +using System; +using System.Diagnostics; +using System.Net.Quic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Microsoft.Quic +{ + internal unsafe partial struct QUIC_BUFFER + { + public Span Span => new(Buffer, (int)Length); + } + + internal partial class MsQuic + { + public static unsafe QUIC_API_TABLE* Open() + { + QUIC_API_TABLE* ApiTable; + int Status = MsQuicOpenVersion(2, (void**)&ApiTable); + ThrowIfFailure(Status); + return ApiTable; + } + + public static unsafe void Close(QUIC_API_TABLE* ApiTable) + { + MsQuicClose(ApiTable); + } + + public static void ThrowIfFailure(int status, string? message = null) + { + if (StatusFailed(status)) + { + // TODO make custom exception, and maybe throw helpers + throw new MsQuicException(status, message); + } + } + + public static bool StatusSucceeded(int status) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return status >= 0; + } + else + { + return status <= 0; + } + } + + public static bool StatusFailed(int status) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return status < 0; + } + else + { + return status > 0; + } + } + + public static readonly int QUIC_STATUS_SUCCESS = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_SUCCESS : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_SUCCESS : MsQuic_Linux.QUIC_STATUS_SUCCESS; + public static readonly int QUIC_STATUS_PENDING = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_PENDING : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_PENDING : MsQuic_Linux.QUIC_STATUS_PENDING; + public static readonly int QUIC_STATUS_CONTINUE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CONTINUE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CONTINUE : MsQuic_Linux.QUIC_STATUS_CONTINUE; + public static readonly int QUIC_STATUS_OUT_OF_MEMORY = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_OUT_OF_MEMORY : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_OUT_OF_MEMORY : MsQuic_Linux.QUIC_STATUS_OUT_OF_MEMORY; + public static readonly int QUIC_STATUS_INVALID_PARAMETER = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_INVALID_PARAMETER : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_INVALID_PARAMETER : MsQuic_Linux.QUIC_STATUS_INVALID_PARAMETER; + public static readonly int QUIC_STATUS_INVALID_STATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_INVALID_STATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_INVALID_STATE : MsQuic_Linux.QUIC_STATUS_INVALID_STATE; + public static readonly int QUIC_STATUS_NOT_SUPPORTED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_NOT_SUPPORTED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_NOT_SUPPORTED : MsQuic_Linux.QUIC_STATUS_NOT_SUPPORTED; + public static readonly int QUIC_STATUS_NOT_FOUND = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_NOT_FOUND : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_NOT_FOUND : MsQuic_Linux.QUIC_STATUS_NOT_FOUND; + public static readonly int QUIC_STATUS_BUFFER_TOO_SMALL = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_BUFFER_TOO_SMALL : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_BUFFER_TOO_SMALL : MsQuic_Linux.QUIC_STATUS_BUFFER_TOO_SMALL; + public static readonly int QUIC_STATUS_HANDSHAKE_FAILURE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_HANDSHAKE_FAILURE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_HANDSHAKE_FAILURE : MsQuic_Linux.QUIC_STATUS_HANDSHAKE_FAILURE; + public static readonly int QUIC_STATUS_ABORTED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_ABORTED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_ABORTED : MsQuic_Linux.QUIC_STATUS_ABORTED; + public static readonly int QUIC_STATUS_ADDRESS_IN_USE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_ADDRESS_IN_USE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_ADDRESS_IN_USE : MsQuic_Linux.QUIC_STATUS_ADDRESS_IN_USE; + public static readonly int QUIC_STATUS_CONNECTION_TIMEOUT = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CONNECTION_TIMEOUT : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CONNECTION_TIMEOUT : MsQuic_Linux.QUIC_STATUS_CONNECTION_TIMEOUT; + public static readonly int QUIC_STATUS_CONNECTION_IDLE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CONNECTION_IDLE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CONNECTION_IDLE : MsQuic_Linux.QUIC_STATUS_CONNECTION_IDLE; + public static readonly int QUIC_STATUS_UNREACHABLE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_UNREACHABLE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_UNREACHABLE : MsQuic_Linux.QUIC_STATUS_UNREACHABLE; + public static readonly int QUIC_STATUS_INTERNAL_ERROR = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_INTERNAL_ERROR : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_INTERNAL_ERROR : MsQuic_Linux.QUIC_STATUS_INTERNAL_ERROR; + public static readonly int QUIC_STATUS_CONNECTION_REFUSED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CONNECTION_REFUSED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CONNECTION_REFUSED : MsQuic_Linux.QUIC_STATUS_CONNECTION_REFUSED; + public static readonly int QUIC_STATUS_PROTOCOL_ERROR = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_PROTOCOL_ERROR : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_PROTOCOL_ERROR : MsQuic_Linux.QUIC_STATUS_PROTOCOL_ERROR; + public static readonly int QUIC_STATUS_VER_NEG_ERROR = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_VER_NEG_ERROR : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_VER_NEG_ERROR : MsQuic_Linux.QUIC_STATUS_VER_NEG_ERROR; + public static readonly int QUIC_STATUS_TLS_ERROR = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_TLS_ERROR : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_TLS_ERROR : MsQuic_Linux.QUIC_STATUS_TLS_ERROR; + public static readonly int QUIC_STATUS_USER_CANCELED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_USER_CANCELED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_USER_CANCELED : MsQuic_Linux.QUIC_STATUS_USER_CANCELED; + public static readonly int QUIC_STATUS_ALPN_NEG_FAILURE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_ALPN_NEG_FAILURE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_ALPN_NEG_FAILURE : MsQuic_Linux.QUIC_STATUS_ALPN_NEG_FAILURE; + public static readonly int QUIC_STATUS_STREAM_LIMIT_REACHED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_STREAM_LIMIT_REACHED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_STREAM_LIMIT_REACHED : MsQuic_Linux.QUIC_STATUS_STREAM_LIMIT_REACHED; + public static readonly int QUIC_STATUS_CLOSE_NOTIFY = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CLOSE_NOTIFY : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CLOSE_NOTIFY : MsQuic_Linux.QUIC_STATUS_CLOSE_NOTIFY; + public static readonly int QUIC_STATUS_BAD_CERTIFICATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_BAD_CERTIFICATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_BAD_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_BAD_CERTIFICATE; + public static readonly int QUIC_STATUS_UNSUPPORTED_CERTIFICATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_UNSUPPORTED_CERTIFICATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_UNSUPPORTED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_UNSUPPORTED_CERTIFICATE; + public static readonly int QUIC_STATUS_REVOKED_CERTIFICATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_REVOKED_CERTIFICATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_REVOKED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_REVOKED_CERTIFICATE; + public static readonly int QUIC_STATUS_EXPIRED_CERTIFICATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_EXPIRED_CERTIFICATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_EXPIRED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_EXPIRED_CERTIFICATE; + public static readonly int QUIC_STATUS_UNKNOWN_CERTIFICATE = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_UNKNOWN_CERTIFICATE : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_UNKNOWN_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_UNKNOWN_CERTIFICATE; + public static readonly int QUIC_STATUS_CERT_EXPIRED = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CERT_EXPIRED : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CERT_EXPIRED : MsQuic_Linux.QUIC_STATUS_CERT_EXPIRED; + public static readonly int QUIC_STATUS_CERT_UNTRUSTED_ROOT = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_STATUS_CERT_UNTRUSTED_ROOT : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_STATUS_CERT_UNTRUSTED_ROOT : MsQuic_Linux.QUIC_STATUS_CERT_UNTRUSTED_ROOT; + + public static readonly int QUIC_ADDRESS_FAMILY_UNSPEC = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_UNSPEC : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_ADDRESS_FAMILY_UNSPEC : MsQuic_Linux.QUIC_ADDRESS_FAMILY_UNSPEC; + public static readonly int QUIC_ADDRESS_FAMILY_INET = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_INET : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_ADDRESS_FAMILY_INET : MsQuic_Linux.QUIC_ADDRESS_FAMILY_INET; + public static readonly int QUIC_ADDRESS_FAMILY_INET6 = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_INET6 : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? MsQuic_MacOS.QUIC_ADDRESS_FAMILY_INET6 : MsQuic_Linux.QUIC_ADDRESS_FAMILY_INET6; + } + + /// Defines the type of a member as it was used in the native signature. + [AttributeUsage(AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)] + [Conditional("DEBUG")] + internal sealed class NativeTypeNameAttribute : Attribute + { + private readonly string _name; + + /// Initializes a new instance of the class. + /// The name of the type that was used in the native signature. + public NativeTypeNameAttribute(string name) + { + _name = name; + } + + /// Gets the name of the type that was used in the native signature. + public string Name => _name; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct QuicAddrFamilyAndLen + { + [FieldOffset(0)] + public ushort sin_family; + [FieldOffset(0)] + public byte sin_len; + [FieldOffset(1)] + public byte sin_family_bsd; + } + + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct QuicAddrIn + { + public QuicAddrFamilyAndLen sin_family; + public ushort sin_port; + public fixed byte sin_addr[4]; + } + + // TODO: rename to C#-like + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct QuicAddrIn6 + { + public QuicAddrFamilyAndLen sin6_family; + public ushort sin6_port; + public uint sin6_flowinfo; + public fixed byte sin6_addr[16]; + public uint sin6_scope_id; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct QuicAddr + { + [FieldOffset(0)] + public QuicAddrIn Ipv4; + [FieldOffset(0)] + public QuicAddrIn6 Ipv6; + [FieldOffset(0)] + public QuicAddrFamilyAndLen FamilyLen; + + public int Family + { + get + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return FamilyLen.sin_family_bsd; + } + else + { + return FamilyLen.sin_family; + } + } + set + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + FamilyLen.sin_family_bsd = (byte)value; + } + else + { + FamilyLen.sin_family = (ushort)value; + } + } + } + } + +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated.cs new file mode 100644 index 00000000000000..ab8608bc9d274a --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated.cs @@ -0,0 +1,2677 @@ +#pragma warning disable IDE0073 +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +#pragma warning restore IDE0073 + +using System.Runtime.InteropServices; + +#pragma warning disable CS0649 +namespace Microsoft.Quic +{ + internal partial struct QUIC_HANDLE + { + } + + internal enum QUIC_EXECUTION_PROFILE + { + QUIC_EXECUTION_PROFILE_LOW_LATENCY, + QUIC_EXECUTION_PROFILE_TYPE_MAX_THROUGHPUT, + QUIC_EXECUTION_PROFILE_TYPE_SCAVENGER, + QUIC_EXECUTION_PROFILE_TYPE_REAL_TIME, + } + + internal enum QUIC_LOAD_BALANCING_MODE + { + QUIC_LOAD_BALANCING_DISABLED, + QUIC_LOAD_BALANCING_SERVER_ID_IP, + } + + internal enum QUIC_CREDENTIAL_TYPE + { + QUIC_CREDENTIAL_TYPE_NONE, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_HASH_STORE, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_CONTEXT, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_FILE_PROTECTED, + QUIC_CREDENTIAL_TYPE_CERTIFICATE_PKCS12, + } + + [System.Flags] + internal enum QUIC_CREDENTIAL_FLAGS + { + QUIC_CREDENTIAL_FLAG_NONE = 0x00000000, + QUIC_CREDENTIAL_FLAG_CLIENT = 0x00000001, + QUIC_CREDENTIAL_FLAG_LOAD_ASYNCHRONOUS = 0x00000002, + QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION = 0x00000004, + QUIC_CREDENTIAL_FLAG_ENABLE_OCSP = 0x00000008, + QUIC_CREDENTIAL_FLAG_INDICATE_CERTIFICATE_RECEIVED = 0x00000010, + QUIC_CREDENTIAL_FLAG_DEFER_CERTIFICATE_VALIDATION = 0x00000020, + QUIC_CREDENTIAL_FLAG_REQUIRE_CLIENT_AUTHENTICATION = 0x00000040, + QUIC_CREDENTIAL_FLAG_USE_TLS_BUILTIN_CERTIFICATE_VALIDATION = 0x00000080, + QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_END_CERT = 0x00000100, + QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN = 0x00000200, + QUIC_CREDENTIAL_FLAG_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x00000400, + QUIC_CREDENTIAL_FLAG_IGNORE_NO_REVOCATION_CHECK = 0x00000800, + QUIC_CREDENTIAL_FLAG_IGNORE_REVOCATION_OFFLINE = 0x00001000, + QUIC_CREDENTIAL_FLAG_SET_ALLOWED_CIPHER_SUITES = 0x00002000, + QUIC_CREDENTIAL_FLAG_USE_PORTABLE_CERTIFICATES = 0x00004000, + QUIC_CREDENTIAL_FLAG_USE_SUPPLIED_CREDENTIALS = 0x00008000, + } + + [System.Flags] + internal enum QUIC_ALLOWED_CIPHER_SUITE_FLAGS + { + QUIC_ALLOWED_CIPHER_SUITE_NONE = 0x0, + QUIC_ALLOWED_CIPHER_SUITE_AES_128_GCM_SHA256 = 0x1, + QUIC_ALLOWED_CIPHER_SUITE_AES_256_GCM_SHA384 = 0x2, + QUIC_ALLOWED_CIPHER_SUITE_CHACHA20_POLY1305_SHA256 = 0x4, + } + + [System.Flags] + internal enum QUIC_CERTIFICATE_HASH_STORE_FLAGS + { + QUIC_CERTIFICATE_HASH_STORE_FLAG_NONE = 0x0000, + QUIC_CERTIFICATE_HASH_STORE_FLAG_MACHINE_STORE = 0x0001, + } + + [System.Flags] + internal enum QUIC_CONNECTION_SHUTDOWN_FLAGS + { + QUIC_CONNECTION_SHUTDOWN_FLAG_NONE = 0x0000, + QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT = 0x0001, + } + + internal enum QUIC_SERVER_RESUMPTION_LEVEL + { + QUIC_SERVER_NO_RESUME, + QUIC_SERVER_RESUME_ONLY, + QUIC_SERVER_RESUME_AND_ZERORTT, + } + + [System.Flags] + internal enum QUIC_SEND_RESUMPTION_FLAGS + { + QUIC_SEND_RESUMPTION_FLAG_NONE = 0x0000, + QUIC_SEND_RESUMPTION_FLAG_FINAL = 0x0001, + } + + internal enum QUIC_STREAM_SCHEDULING_SCHEME + { + QUIC_STREAM_SCHEDULING_SCHEME_FIFO = 0x0000, + QUIC_STREAM_SCHEDULING_SCHEME_ROUND_ROBIN = 0x0001, + QUIC_STREAM_SCHEDULING_SCHEME_COUNT, + } + + [System.Flags] + internal enum QUIC_STREAM_OPEN_FLAGS + { + QUIC_STREAM_OPEN_FLAG_NONE = 0x0000, + QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL = 0x0001, + QUIC_STREAM_OPEN_FLAG_0_RTT = 0x0002, + } + + [System.Flags] + internal enum QUIC_STREAM_START_FLAGS + { + QUIC_STREAM_START_FLAG_NONE = 0x0000, + QUIC_STREAM_START_FLAG_IMMEDIATE = 0x0001, + QUIC_STREAM_START_FLAG_FAIL_BLOCKED = 0x0002, + QUIC_STREAM_START_FLAG_SHUTDOWN_ON_FAIL = 0x0004, + QUIC_STREAM_START_FLAG_INDICATE_PEER_ACCEPT = 0x0008, + } + + [System.Flags] + internal enum QUIC_STREAM_SHUTDOWN_FLAGS + { + QUIC_STREAM_SHUTDOWN_FLAG_NONE = 0x0000, + QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL = 0x0001, + QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND = 0x0002, + QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE = 0x0004, + QUIC_STREAM_SHUTDOWN_FLAG_ABORT = 0x0006, + QUIC_STREAM_SHUTDOWN_FLAG_IMMEDIATE = 0x0008, + QUIC_STREAM_SHUTDOWN_FLAG_INLINE = 0x0010, + } + + [System.Flags] + internal enum QUIC_RECEIVE_FLAGS + { + QUIC_RECEIVE_FLAG_NONE = 0x0000, + QUIC_RECEIVE_FLAG_0_RTT = 0x0001, + QUIC_RECEIVE_FLAG_FIN = 0x0002, + } + + [System.Flags] + internal enum QUIC_SEND_FLAGS + { + QUIC_SEND_FLAG_NONE = 0x0000, + QUIC_SEND_FLAG_ALLOW_0_RTT = 0x0001, + QUIC_SEND_FLAG_START = 0x0002, + QUIC_SEND_FLAG_FIN = 0x0004, + QUIC_SEND_FLAG_DGRAM_PRIORITY = 0x0008, + QUIC_SEND_FLAG_DELAY_SEND = 0x0010, + } + + internal enum QUIC_DATAGRAM_SEND_STATE + { + QUIC_DATAGRAM_SEND_UNKNOWN, + QUIC_DATAGRAM_SEND_SENT, + QUIC_DATAGRAM_SEND_LOST_SUSPECT, + QUIC_DATAGRAM_SEND_LOST_DISCARDED, + QUIC_DATAGRAM_SEND_ACKNOWLEDGED, + QUIC_DATAGRAM_SEND_ACKNOWLEDGED_SPURIOUS, + QUIC_DATAGRAM_SEND_CANCELED, + } + + internal unsafe partial struct QUIC_REGISTRATION_CONFIG + { + [NativeTypeName("const char *")] + public sbyte* AppName; + + public QUIC_EXECUTION_PROFILE ExecutionProfile; + } + + internal unsafe partial struct QUIC_CERTIFICATE_HASH + { + [NativeTypeName("uint8_t [20]")] + public fixed byte ShaHash[20]; + } + + internal unsafe partial struct QUIC_CERTIFICATE_HASH_STORE + { + public QUIC_CERTIFICATE_HASH_STORE_FLAGS Flags; + + [NativeTypeName("uint8_t [20]")] + public fixed byte ShaHash[20]; + + [NativeTypeName("char [128]")] + public fixed sbyte StoreName[128]; + } + + internal unsafe partial struct QUIC_CERTIFICATE_FILE + { + [NativeTypeName("const char *")] + public sbyte* PrivateKeyFile; + + [NativeTypeName("const char *")] + public sbyte* CertificateFile; + } + + internal unsafe partial struct QUIC_CERTIFICATE_FILE_PROTECTED + { + [NativeTypeName("const char *")] + public sbyte* PrivateKeyFile; + + [NativeTypeName("const char *")] + public sbyte* CertificateFile; + + [NativeTypeName("const char *")] + public sbyte* PrivateKeyPassword; + } + + internal unsafe partial struct QUIC_CERTIFICATE_PKCS12 + { + [NativeTypeName("const uint8_t *")] + public byte* Asn1Blob; + + [NativeTypeName("uint32_t")] + public uint Asn1BlobLength; + + [NativeTypeName("const char *")] + public sbyte* PrivateKeyPassword; + } + + internal unsafe partial struct QUIC_CREDENTIAL_CONFIG + { + public QUIC_CREDENTIAL_TYPE Type; + + public QUIC_CREDENTIAL_FLAGS Flags; + + [NativeTypeName("QUIC_CREDENTIAL_CONFIG::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + [NativeTypeName("const char *")] + public sbyte* Principal; + + public void* Reserved; + + [NativeTypeName("QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER")] + public delegate* unmanaged[Cdecl] AsyncHandler; + + public QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites; + + public ref QUIC_CERTIFICATE_HASH* CertificateHash + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateHash; + } + } + + public ref QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateHashStore; + } + } + + public ref void* CertificateContext + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateContext; + } + } + + public ref QUIC_CERTIFICATE_FILE* CertificateFile + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateFile; + } + } + + public ref QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateFileProtected; + } + } + + public ref QUIC_CERTIFICATE_PKCS12* CertificatePkcs12 + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificatePkcs12; + } + } + + [StructLayout(LayoutKind.Explicit)] + internal unsafe partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + public QUIC_CERTIFICATE_HASH* CertificateHash; + + [FieldOffset(0)] + public QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore; + + [FieldOffset(0)] + [NativeTypeName("QUIC_CERTIFICATE *")] + public void* CertificateContext; + + [FieldOffset(0)] + public QUIC_CERTIFICATE_FILE* CertificateFile; + + [FieldOffset(0)] + public QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected; + + [FieldOffset(0)] + public QUIC_CERTIFICATE_PKCS12* CertificatePkcs12; + } + } + + internal unsafe partial struct QUIC_TICKET_KEY_CONFIG + { + [NativeTypeName("uint8_t [16]")] + public fixed byte Id[16]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte Material[64]; + + [NativeTypeName("uint8_t")] + public byte MaterialLength; + } + + internal unsafe partial struct QUIC_BUFFER + { + [NativeTypeName("uint32_t")] + public uint Length; + + [NativeTypeName("uint8_t *")] + public byte* Buffer; + } + + internal unsafe partial struct QUIC_NEW_CONNECTION_INFO + { + [NativeTypeName("uint32_t")] + public uint QuicVersion; + + [NativeTypeName("const QUIC_ADDR *")] + public QuicAddr* LocalAddress; + + [NativeTypeName("const QUIC_ADDR *")] + public QuicAddr* RemoteAddress; + + [NativeTypeName("uint32_t")] + public uint CryptoBufferLength; + + [NativeTypeName("uint16_t")] + public ushort ClientAlpnListLength; + + [NativeTypeName("uint16_t")] + public ushort ServerNameLength; + + [NativeTypeName("uint8_t")] + public byte NegotiatedAlpnLength; + + [NativeTypeName("const uint8_t *")] + public byte* CryptoBuffer; + + [NativeTypeName("const uint8_t *")] + public byte* ClientAlpnList; + + [NativeTypeName("const uint8_t *")] + public byte* NegotiatedAlpn; + + [NativeTypeName("const char *")] + public sbyte* ServerName; + } + + internal enum QUIC_TLS_PROTOCOL_VERSION + { + QUIC_TLS_PROTOCOL_UNKNOWN = 0, + QUIC_TLS_PROTOCOL_1_3 = 0x3000, + } + + internal enum QUIC_CIPHER_ALGORITHM + { + QUIC_CIPHER_ALGORITHM_NONE = 0, + QUIC_CIPHER_ALGORITHM_AES_128 = 0x660E, + QUIC_CIPHER_ALGORITHM_AES_256 = 0x6610, + QUIC_CIPHER_ALGORITHM_CHACHA20 = 0x6612, + } + + internal enum QUIC_HASH_ALGORITHM + { + QUIC_HASH_ALGORITHM_NONE = 0, + QUIC_HASH_ALGORITHM_SHA_256 = 0x800C, + QUIC_HASH_ALGORITHM_SHA_384 = 0x800D, + } + + internal enum QUIC_KEY_EXCHANGE_ALGORITHM + { + QUIC_KEY_EXCHANGE_ALGORITHM_NONE = 0, + } + + internal enum QUIC_CIPHER_SUITE + { + QUIC_CIPHER_SUITE_TLS_AES_128_GCM_SHA256 = 0x1301, + QUIC_CIPHER_SUITE_TLS_AES_256_GCM_SHA384 = 0x1302, + QUIC_CIPHER_SUITE_TLS_CHACHA20_POLY1305_SHA256 = 0x1303, + } + + internal enum QUIC_CONGESTION_CONTROL_ALGORITHM + { + QUIC_CONGESTION_CONTROL_ALGORITHM_CUBIC, + QUIC_CONGESTION_CONTROL_ALGORITHM_MAX, + } + + internal partial struct QUIC_HANDSHAKE_INFO + { + public QUIC_TLS_PROTOCOL_VERSION TlsProtocolVersion; + + public QUIC_CIPHER_ALGORITHM CipherAlgorithm; + + [NativeTypeName("int32_t")] + public int CipherStrength; + + public QUIC_HASH_ALGORITHM Hash; + + [NativeTypeName("int32_t")] + public int HashStrength; + + public QUIC_KEY_EXCHANGE_ALGORITHM KeyExchangeAlgorithm; + + [NativeTypeName("int32_t")] + public int KeyExchangeStrength; + + public QUIC_CIPHER_SUITE CipherSuite; + } + + internal partial struct QUIC_STATISTICS + { + [NativeTypeName("uint64_t")] + public ulong CorrelationId; + + public uint _bitfield; + + [NativeTypeName("uint32_t : 1")] + public uint VersionNegotiation + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint StatelessRetry + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint ResumptionAttempted + { + get + { + return (_bitfield >> 2) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint ResumptionSucceeded + { + get + { + return (_bitfield >> 3) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3); + } + } + + [NativeTypeName("uint32_t")] + public uint Rtt; + + [NativeTypeName("uint32_t")] + public uint MinRtt; + + [NativeTypeName("uint32_t")] + public uint MaxRtt; + + [NativeTypeName("struct (anonymous struct)")] + public _Timing_e__Struct Timing; + + [NativeTypeName("struct (anonymous struct)")] + public _Handshake_e__Struct Handshake; + + [NativeTypeName("struct (anonymous struct)")] + public _Send_e__Struct Send; + + [NativeTypeName("struct (anonymous struct)")] + public _Recv_e__Struct Recv; + + [NativeTypeName("struct (anonymous struct)")] + public _Misc_e__Struct Misc; + + internal partial struct _Timing_e__Struct + { + [NativeTypeName("uint64_t")] + public ulong Start; + + [NativeTypeName("uint64_t")] + public ulong InitialFlightEnd; + + [NativeTypeName("uint64_t")] + public ulong HandshakeFlightEnd; + } + + internal partial struct _Handshake_e__Struct + { + [NativeTypeName("uint32_t")] + public uint ClientFlight1Bytes; + + [NativeTypeName("uint32_t")] + public uint ServerFlight1Bytes; + + [NativeTypeName("uint32_t")] + public uint ClientFlight2Bytes; + } + + internal partial struct _Send_e__Struct + { + [NativeTypeName("uint16_t")] + public ushort PathMtu; + + [NativeTypeName("uint64_t")] + public ulong TotalPackets; + + [NativeTypeName("uint64_t")] + public ulong RetransmittablePackets; + + [NativeTypeName("uint64_t")] + public ulong SuspectedLostPackets; + + [NativeTypeName("uint64_t")] + public ulong SpuriousLostPackets; + + [NativeTypeName("uint64_t")] + public ulong TotalBytes; + + [NativeTypeName("uint64_t")] + public ulong TotalStreamBytes; + + [NativeTypeName("uint32_t")] + public uint CongestionCount; + + [NativeTypeName("uint32_t")] + public uint PersistentCongestionCount; + } + + internal partial struct _Recv_e__Struct + { + [NativeTypeName("uint64_t")] + public ulong TotalPackets; + + [NativeTypeName("uint64_t")] + public ulong ReorderedPackets; + + [NativeTypeName("uint64_t")] + public ulong DroppedPackets; + + [NativeTypeName("uint64_t")] + public ulong DuplicatePackets; + + [NativeTypeName("uint64_t")] + public ulong TotalBytes; + + [NativeTypeName("uint64_t")] + public ulong TotalStreamBytes; + + [NativeTypeName("uint64_t")] + public ulong DecryptionFailures; + + [NativeTypeName("uint64_t")] + public ulong ValidAckFrames; + } + + internal partial struct _Misc_e__Struct + { + [NativeTypeName("uint32_t")] + public uint KeyUpdateCount; + } + } + + internal partial struct QUIC_STATISTICS_V2 + { + [NativeTypeName("uint64_t")] + public ulong CorrelationId; + + public uint _bitfield; + + [NativeTypeName("uint32_t : 1")] + public uint VersionNegotiation + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint StatelessRetry + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint ResumptionAttempted + { + get + { + return (_bitfield >> 2) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2); + } + } + + [NativeTypeName("uint32_t : 1")] + public uint ResumptionSucceeded + { + get + { + return (_bitfield >> 3) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3); + } + } + + [NativeTypeName("uint32_t")] + public uint Rtt; + + [NativeTypeName("uint32_t")] + public uint MinRtt; + + [NativeTypeName("uint32_t")] + public uint MaxRtt; + + [NativeTypeName("uint64_t")] + public ulong TimingStart; + + [NativeTypeName("uint64_t")] + public ulong TimingInitialFlightEnd; + + [NativeTypeName("uint64_t")] + public ulong TimingHandshakeFlightEnd; + + [NativeTypeName("uint32_t")] + public uint HandshakeClientFlight1Bytes; + + [NativeTypeName("uint32_t")] + public uint HandshakeServerFlight1Bytes; + + [NativeTypeName("uint32_t")] + public uint HandshakeClientFlight2Bytes; + + [NativeTypeName("uint16_t")] + public ushort SendPathMtu; + + [NativeTypeName("uint64_t")] + public ulong SendTotalPackets; + + [NativeTypeName("uint64_t")] + public ulong SendRetransmittablePackets; + + [NativeTypeName("uint64_t")] + public ulong SendSuspectedLostPackets; + + [NativeTypeName("uint64_t")] + public ulong SendSpuriousLostPackets; + + [NativeTypeName("uint64_t")] + public ulong SendTotalBytes; + + [NativeTypeName("uint64_t")] + public ulong SendTotalStreamBytes; + + [NativeTypeName("uint32_t")] + public uint SendCongestionCount; + + [NativeTypeName("uint32_t")] + public uint SendPersistentCongestionCount; + + [NativeTypeName("uint64_t")] + public ulong RecvTotalPackets; + + [NativeTypeName("uint64_t")] + public ulong RecvReorderedPackets; + + [NativeTypeName("uint64_t")] + public ulong RecvDroppedPackets; + + [NativeTypeName("uint64_t")] + public ulong RecvDuplicatePackets; + + [NativeTypeName("uint64_t")] + public ulong RecvTotalBytes; + + [NativeTypeName("uint64_t")] + public ulong RecvTotalStreamBytes; + + [NativeTypeName("uint64_t")] + public ulong RecvDecryptionFailures; + + [NativeTypeName("uint64_t")] + public ulong RecvValidAckFrames; + + [NativeTypeName("uint32_t")] + public uint KeyUpdateCount; + + [NativeTypeName("uint32_t")] + public uint SendCongestionWindow; + } + + internal partial struct QUIC_LISTENER_STATISTICS + { + [NativeTypeName("uint64_t")] + public ulong TotalAcceptedConnections; + + [NativeTypeName("uint64_t")] + public ulong TotalRejectedConnections; + + [NativeTypeName("uint64_t")] + public ulong BindingRecvDroppedPackets; + } + + internal enum QUIC_PERFORMANCE_COUNTERS + { + QUIC_PERF_COUNTER_CONN_CREATED, + QUIC_PERF_COUNTER_CONN_HANDSHAKE_FAIL, + QUIC_PERF_COUNTER_CONN_APP_REJECT, + QUIC_PERF_COUNTER_CONN_RESUMED, + QUIC_PERF_COUNTER_CONN_ACTIVE, + QUIC_PERF_COUNTER_CONN_CONNECTED, + QUIC_PERF_COUNTER_CONN_PROTOCOL_ERRORS, + QUIC_PERF_COUNTER_CONN_NO_ALPN, + QUIC_PERF_COUNTER_STRM_ACTIVE, + QUIC_PERF_COUNTER_PKTS_SUSPECTED_LOST, + QUIC_PERF_COUNTER_PKTS_DROPPED, + QUIC_PERF_COUNTER_PKTS_DECRYPTION_FAIL, + QUIC_PERF_COUNTER_UDP_RECV, + QUIC_PERF_COUNTER_UDP_SEND, + QUIC_PERF_COUNTER_UDP_RECV_BYTES, + QUIC_PERF_COUNTER_UDP_SEND_BYTES, + QUIC_PERF_COUNTER_UDP_RECV_EVENTS, + QUIC_PERF_COUNTER_UDP_SEND_CALLS, + QUIC_PERF_COUNTER_APP_SEND_BYTES, + QUIC_PERF_COUNTER_APP_RECV_BYTES, + QUIC_PERF_COUNTER_CONN_QUEUE_DEPTH, + QUIC_PERF_COUNTER_CONN_OPER_QUEUE_DEPTH, + QUIC_PERF_COUNTER_CONN_OPER_QUEUED, + QUIC_PERF_COUNTER_CONN_OPER_COMPLETED, + QUIC_PERF_COUNTER_WORK_OPER_QUEUE_DEPTH, + QUIC_PERF_COUNTER_WORK_OPER_QUEUED, + QUIC_PERF_COUNTER_WORK_OPER_COMPLETED, + QUIC_PERF_COUNTER_PATH_VALIDATED, + QUIC_PERF_COUNTER_PATH_FAILURE, + QUIC_PERF_COUNTER_SEND_STATELESS_RESET, + QUIC_PERF_COUNTER_SEND_STATELESS_RETRY, + QUIC_PERF_COUNTER_MAX, + } + + internal unsafe partial struct QUIC_VERSION_SETTINGS + { + [NativeTypeName("uint32_t *")] + public uint* AcceptableVersions; + + [NativeTypeName("uint32_t *")] + public uint* OfferedVersions; + + [NativeTypeName("uint32_t *")] + public uint* FullyDeployedVersions; + + [NativeTypeName("uint32_t")] + public uint AcceptableVersionsLength; + + [NativeTypeName("uint32_t")] + public uint OfferedVersionsLength; + + [NativeTypeName("uint32_t")] + public uint FullyDeployedVersionsLength; + } + + internal partial struct QUIC_GLOBAL_SETTINGS + { + [NativeTypeName("QUIC_GLOBAL_SETTINGS::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + [NativeTypeName("uint16_t")] + public ushort RetryMemoryLimit; + + [NativeTypeName("uint16_t")] + public ushort LoadBalancingMode; + + public ref ulong IsSetFlags + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSetFlags, 1)); + } + } + + public ref _Anonymous_e__Union._IsSet_e__Struct IsSet + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSet, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + internal partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("uint64_t")] + public ulong IsSetFlags; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _IsSet_e__Struct IsSet; + + internal partial struct _IsSet_e__Struct + { + public ulong _bitfield; + + [NativeTypeName("uint64_t : 1")] + public ulong RetryMemoryLimit + { + get + { + return _bitfield & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~0x1UL) | (value & 0x1UL); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong LoadBalancingMode + { + get + { + return (_bitfield >> 1) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 1)) | ((value & 0x1UL) << 1); + } + } + + [NativeTypeName("uint64_t : 62")] + public ulong RESERVED + { + get + { + return (_bitfield >> 2) & 0x3FFFFFFFUL; + } + + set + { + _bitfield = (_bitfield & ~(0x3FFFFFFFUL << 2)) | ((value & 0x3FFFFFFFUL) << 2); + } + } + } + } + } + + internal partial struct QUIC_SETTINGS + { + [NativeTypeName("QUIC_SETTINGS::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + [NativeTypeName("uint64_t")] + public ulong MaxBytesPerKey; + + [NativeTypeName("uint64_t")] + public ulong HandshakeIdleTimeoutMs; + + [NativeTypeName("uint64_t")] + public ulong IdleTimeoutMs; + + [NativeTypeName("uint64_t")] + public ulong MtuDiscoverySearchCompleteTimeoutUs; + + [NativeTypeName("uint32_t")] + public uint TlsClientMaxSendBuffer; + + [NativeTypeName("uint32_t")] + public uint TlsServerMaxSendBuffer; + + [NativeTypeName("uint32_t")] + public uint StreamRecvWindowDefault; + + [NativeTypeName("uint32_t")] + public uint StreamRecvBufferDefault; + + [NativeTypeName("uint32_t")] + public uint ConnFlowControlWindow; + + [NativeTypeName("uint32_t")] + public uint MaxWorkerQueueDelayUs; + + [NativeTypeName("uint32_t")] + public uint MaxStatelessOperations; + + [NativeTypeName("uint32_t")] + public uint InitialWindowPackets; + + [NativeTypeName("uint32_t")] + public uint SendIdleTimeoutMs; + + [NativeTypeName("uint32_t")] + public uint InitialRttMs; + + [NativeTypeName("uint32_t")] + public uint MaxAckDelayMs; + + [NativeTypeName("uint32_t")] + public uint DisconnectTimeoutMs; + + [NativeTypeName("uint32_t")] + public uint KeepAliveIntervalMs; + + [NativeTypeName("uint16_t")] + public ushort CongestionControlAlgorithm; + + [NativeTypeName("uint16_t")] + public ushort PeerBidiStreamCount; + + [NativeTypeName("uint16_t")] + public ushort PeerUnidiStreamCount; + + [NativeTypeName("uint16_t")] + public ushort MaxBindingStatelessOperations; + + [NativeTypeName("uint16_t")] + public ushort StatelessOperationExpirationMs; + + [NativeTypeName("uint16_t")] + public ushort MinimumMtu; + + [NativeTypeName("uint16_t")] + public ushort MaximumMtu; + + public byte _bitfield; + + [NativeTypeName("uint8_t : 1")] + public byte SendBufferingEnabled + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte PacingEnabled + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte MigrationEnabled + { + get + { + return (byte)((_bitfield >> 2) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte DatagramReceiveEnabled + { + get + { + return (byte)((_bitfield >> 3) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3)); + } + } + + [NativeTypeName("uint8_t : 2")] + public byte ServerResumptionLevel + { + get + { + return (byte)((_bitfield >> 4) & 0x3u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x3u << 4)) | ((value & 0x3u) << 4)); + } + } + + [NativeTypeName("uint8_t : 2")] + public byte RESERVED + { + get + { + return (byte)((_bitfield >> 6) & 0x3u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x3u << 6)) | ((value & 0x3u) << 6)); + } + } + + [NativeTypeName("uint8_t")] + public byte MaxOperationsPerDrain; + + [NativeTypeName("uint8_t")] + public byte MtuDiscoveryMissingProbeCount; + + public ref ulong IsSetFlags + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSetFlags, 1)); + } + } + + public ref _Anonymous_e__Union._IsSet_e__Struct IsSet + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSet, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + internal partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("uint64_t")] + public ulong IsSetFlags; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _IsSet_e__Struct IsSet; + + internal partial struct _IsSet_e__Struct + { + public ulong _bitfield; + + [NativeTypeName("uint64_t : 1")] + public ulong MaxBytesPerKey + { + get + { + return _bitfield & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~0x1UL) | (value & 0x1UL); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong HandshakeIdleTimeoutMs + { + get + { + return (_bitfield >> 1) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 1)) | ((value & 0x1UL) << 1); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong IdleTimeoutMs + { + get + { + return (_bitfield >> 2) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 2)) | ((value & 0x1UL) << 2); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MtuDiscoverySearchCompleteTimeoutUs + { + get + { + return (_bitfield >> 3) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 3)) | ((value & 0x1UL) << 3); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong TlsClientMaxSendBuffer + { + get + { + return (_bitfield >> 4) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 4)) | ((value & 0x1UL) << 4); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong TlsServerMaxSendBuffer + { + get + { + return (_bitfield >> 5) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 5)) | ((value & 0x1UL) << 5); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong StreamRecvWindowDefault + { + get + { + return (_bitfield >> 6) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 6)) | ((value & 0x1UL) << 6); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong StreamRecvBufferDefault + { + get + { + return (_bitfield >> 7) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 7)) | ((value & 0x1UL) << 7); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong ConnFlowControlWindow + { + get + { + return (_bitfield >> 8) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 8)) | ((value & 0x1UL) << 8); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaxWorkerQueueDelayUs + { + get + { + return (_bitfield >> 9) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 9)) | ((value & 0x1UL) << 9); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaxStatelessOperations + { + get + { + return (_bitfield >> 10) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 10)) | ((value & 0x1UL) << 10); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong InitialWindowPackets + { + get + { + return (_bitfield >> 11) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 11)) | ((value & 0x1UL) << 11); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong SendIdleTimeoutMs + { + get + { + return (_bitfield >> 12) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 12)) | ((value & 0x1UL) << 12); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong InitialRttMs + { + get + { + return (_bitfield >> 13) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 13)) | ((value & 0x1UL) << 13); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaxAckDelayMs + { + get + { + return (_bitfield >> 14) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 14)) | ((value & 0x1UL) << 14); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong DisconnectTimeoutMs + { + get + { + return (_bitfield >> 15) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 15)) | ((value & 0x1UL) << 15); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong KeepAliveIntervalMs + { + get + { + return (_bitfield >> 16) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 16)) | ((value & 0x1UL) << 16); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong CongestionControlAlgorithm + { + get + { + return (_bitfield >> 17) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 17)) | ((value & 0x1UL) << 17); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong PeerBidiStreamCount + { + get + { + return (_bitfield >> 18) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 18)) | ((value & 0x1UL) << 18); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong PeerUnidiStreamCount + { + get + { + return (_bitfield >> 19) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 19)) | ((value & 0x1UL) << 19); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaxBindingStatelessOperations + { + get + { + return (_bitfield >> 20) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 20)) | ((value & 0x1UL) << 20); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong StatelessOperationExpirationMs + { + get + { + return (_bitfield >> 21) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 21)) | ((value & 0x1UL) << 21); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MinimumMtu + { + get + { + return (_bitfield >> 22) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 22)) | ((value & 0x1UL) << 22); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaximumMtu + { + get + { + return (_bitfield >> 23) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 23)) | ((value & 0x1UL) << 23); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong SendBufferingEnabled + { + get + { + return (_bitfield >> 24) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 24)) | ((value & 0x1UL) << 24); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong PacingEnabled + { + get + { + return (_bitfield >> 25) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 25)) | ((value & 0x1UL) << 25); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MigrationEnabled + { + get + { + return (_bitfield >> 26) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 26)) | ((value & 0x1UL) << 26); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong DatagramReceiveEnabled + { + get + { + return (_bitfield >> 27) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 27)) | ((value & 0x1UL) << 27); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong ServerResumptionLevel + { + get + { + return (_bitfield >> 28) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 28)) | ((value & 0x1UL) << 28); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MaxOperationsPerDrain + { + get + { + return (_bitfield >> 29) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 29)) | ((value & 0x1UL) << 29); + } + } + + [NativeTypeName("uint64_t : 1")] + public ulong MtuDiscoveryMissingProbeCount + { + get + { + return (_bitfield >> 30) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 30)) | ((value & 0x1UL) << 30); + } + } + + [NativeTypeName("uint64_t : 33")] + public ulong RESERVED + { + get + { + return (_bitfield >> 31) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 31)) | ((value & 0x1UL) << 31); + } + } + } + } + } + + internal unsafe partial struct QUIC_TLS_SECRETS + { + [NativeTypeName("uint8_t")] + public byte SecretLength; + + [NativeTypeName("struct (anonymous struct)")] + public _IsSet_e__Struct IsSet; + + [NativeTypeName("uint8_t [32]")] + public fixed byte ClientRandom[32]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte ClientEarlyTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte ClientHandshakeTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte ServerHandshakeTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte ClientTrafficSecret0[64]; + + [NativeTypeName("uint8_t [64]")] + public fixed byte ServerTrafficSecret0[64]; + + internal partial struct _IsSet_e__Struct + { + public byte _bitfield; + + [NativeTypeName("uint8_t : 1")] + public byte ClientRandom + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte ClientEarlyTrafficSecret + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte ClientHandshakeTrafficSecret + { + get + { + return (byte)((_bitfield >> 2) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte ServerHandshakeTrafficSecret + { + get + { + return (byte)((_bitfield >> 3) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte ClientTrafficSecret0 + { + get + { + return (byte)((_bitfield >> 4) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 4)) | ((value & 0x1u) << 4)); + } + } + + [NativeTypeName("uint8_t : 1")] + public byte ServerTrafficSecret0 + { + get + { + return (byte)((_bitfield >> 5) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 5)) | ((value & 0x1u) << 5)); + } + } + } + } + + internal unsafe partial struct QUIC_SCHANNEL_CONTEXT_ATTRIBUTE_W + { + [NativeTypeName("unsigned long")] + public uint Attribute; + + public void* Buffer; + } + + internal enum QUIC_LISTENER_EVENT_TYPE + { + QUIC_LISTENER_EVENT_NEW_CONNECTION = 0, + QUIC_LISTENER_EVENT_STOP_COMPLETE = 1, + } + + internal partial struct QUIC_LISTENER_EVENT + { + public QUIC_LISTENER_EVENT_TYPE Type; + + [NativeTypeName("QUIC_LISTENER_EVENT::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + public ref _Anonymous_e__Union._NEW_CONNECTION_e__Struct NEW_CONNECTION + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.NEW_CONNECTION, 1)); + } + } + + public ref _Anonymous_e__Union._STOP_COMPLETE_e__Struct STOP_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.STOP_COMPLETE, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + internal partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _NEW_CONNECTION_e__Struct NEW_CONNECTION; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _STOP_COMPLETE_e__Struct STOP_COMPLETE; + + internal unsafe partial struct _NEW_CONNECTION_e__Struct + { + [NativeTypeName("const QUIC_NEW_CONNECTION_INFO *")] + public QUIC_NEW_CONNECTION_INFO* Info; + + [NativeTypeName("HQUIC")] + public QUIC_HANDLE* Connection; + } + + internal partial struct _STOP_COMPLETE_e__Struct + { + public byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + public byte AppCloseInProgress + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + public byte RESERVED + { + get + { + return (byte)((_bitfield >> 1) & 0x7Fu); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x7Fu << 1)) | ((value & 0x7Fu) << 1)); + } + } + } + } + } + + internal enum QUIC_CONNECTION_EVENT_TYPE + { + QUIC_CONNECTION_EVENT_CONNECTED = 0, + QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT = 1, + QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER = 2, + QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE = 3, + QUIC_CONNECTION_EVENT_LOCAL_ADDRESS_CHANGED = 4, + QUIC_CONNECTION_EVENT_PEER_ADDRESS_CHANGED = 5, + QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED = 6, + QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE = 7, + QUIC_CONNECTION_EVENT_PEER_NEEDS_STREAMS = 8, + QUIC_CONNECTION_EVENT_IDEAL_PROCESSOR_CHANGED = 9, + QUIC_CONNECTION_EVENT_DATAGRAM_STATE_CHANGED = 10, + QUIC_CONNECTION_EVENT_DATAGRAM_RECEIVED = 11, + QUIC_CONNECTION_EVENT_DATAGRAM_SEND_STATE_CHANGED = 12, + QUIC_CONNECTION_EVENT_RESUMED = 13, + QUIC_CONNECTION_EVENT_RESUMPTION_TICKET_RECEIVED = 14, + QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED = 15, + } + + internal partial struct QUIC_CONNECTION_EVENT + { + public QUIC_CONNECTION_EVENT_TYPE Type; + + [NativeTypeName("QUIC_CONNECTION_EVENT::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + public ref _Anonymous_e__Union._CONNECTED_e__Struct CONNECTED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.CONNECTED, 1)); + } + } + + public ref _Anonymous_e__Union._SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct SHUTDOWN_INITIATED_BY_TRANSPORT + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_INITIATED_BY_TRANSPORT, 1)); + } + } + + public ref _Anonymous_e__Union._SHUTDOWN_INITIATED_BY_PEER_e__Struct SHUTDOWN_INITIATED_BY_PEER + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_INITIATED_BY_PEER, 1)); + } + } + + public ref _Anonymous_e__Union._SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_COMPLETE, 1)); + } + } + + public ref _Anonymous_e__Union._LOCAL_ADDRESS_CHANGED_e__Struct LOCAL_ADDRESS_CHANGED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.LOCAL_ADDRESS_CHANGED, 1)); + } + } + + public ref _Anonymous_e__Union._PEER_ADDRESS_CHANGED_e__Struct PEER_ADDRESS_CHANGED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.PEER_ADDRESS_CHANGED, 1)); + } + } + + public ref _Anonymous_e__Union._PEER_STREAM_STARTED_e__Struct PEER_STREAM_STARTED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.PEER_STREAM_STARTED, 1)); + } + } + + public ref _Anonymous_e__Union._STREAMS_AVAILABLE_e__Struct STREAMS_AVAILABLE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.STREAMS_AVAILABLE, 1)); + } + } + + public ref _Anonymous_e__Union._IDEAL_PROCESSOR_CHANGED_e__Struct IDEAL_PROCESSOR_CHANGED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IDEAL_PROCESSOR_CHANGED, 1)); + } + } + + public ref _Anonymous_e__Union._DATAGRAM_STATE_CHANGED_e__Struct DATAGRAM_STATE_CHANGED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.DATAGRAM_STATE_CHANGED, 1)); + } + } + + public ref _Anonymous_e__Union._DATAGRAM_RECEIVED_e__Struct DATAGRAM_RECEIVED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.DATAGRAM_RECEIVED, 1)); + } + } + + public ref _Anonymous_e__Union._DATAGRAM_SEND_STATE_CHANGED_e__Struct DATAGRAM_SEND_STATE_CHANGED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.DATAGRAM_SEND_STATE_CHANGED, 1)); + } + } + + public ref _Anonymous_e__Union._RESUMED_e__Struct RESUMED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.RESUMED, 1)); + } + } + + public ref _Anonymous_e__Union._RESUMPTION_TICKET_RECEIVED_e__Struct RESUMPTION_TICKET_RECEIVED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.RESUMPTION_TICKET_RECEIVED, 1)); + } + } + + public ref _Anonymous_e__Union._PEER_CERTIFICATE_RECEIVED_e__Struct PEER_CERTIFICATE_RECEIVED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.PEER_CERTIFICATE_RECEIVED, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + internal partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _CONNECTED_e__Struct CONNECTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct SHUTDOWN_INITIATED_BY_TRANSPORT; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SHUTDOWN_INITIATED_BY_PEER_e__Struct SHUTDOWN_INITIATED_BY_PEER; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _LOCAL_ADDRESS_CHANGED_e__Struct LOCAL_ADDRESS_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _PEER_ADDRESS_CHANGED_e__Struct PEER_ADDRESS_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _PEER_STREAM_STARTED_e__Struct PEER_STREAM_STARTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _STREAMS_AVAILABLE_e__Struct STREAMS_AVAILABLE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _IDEAL_PROCESSOR_CHANGED_e__Struct IDEAL_PROCESSOR_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _DATAGRAM_STATE_CHANGED_e__Struct DATAGRAM_STATE_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _DATAGRAM_RECEIVED_e__Struct DATAGRAM_RECEIVED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _DATAGRAM_SEND_STATE_CHANGED_e__Struct DATAGRAM_SEND_STATE_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _RESUMED_e__Struct RESUMED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _RESUMPTION_TICKET_RECEIVED_e__Struct RESUMPTION_TICKET_RECEIVED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _PEER_CERTIFICATE_RECEIVED_e__Struct PEER_CERTIFICATE_RECEIVED; + + internal unsafe partial struct _CONNECTED_e__Struct + { + [NativeTypeName("BOOLEAN")] + public byte SessionResumed; + + [NativeTypeName("uint8_t")] + public byte NegotiatedAlpnLength; + + [NativeTypeName("const uint8_t *")] + public byte* NegotiatedAlpn; + } + + internal partial struct _SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct + { + [NativeTypeName("HRESULT")] + public int Status; + } + + internal partial struct _SHUTDOWN_INITIATED_BY_PEER_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + public ulong ErrorCode; + } + + internal partial struct _SHUTDOWN_COMPLETE_e__Struct + { + public byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + public byte HandshakeCompleted + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 1")] + public byte PeerAcknowledgedShutdown + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("BOOLEAN : 1")] + public byte AppCloseInProgress + { + get + { + return (byte)((_bitfield >> 2) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2)); + } + } + } + + internal unsafe partial struct _LOCAL_ADDRESS_CHANGED_e__Struct + { + [NativeTypeName("const QUIC_ADDR *")] + public QuicAddr* Address; + } + + internal unsafe partial struct _PEER_ADDRESS_CHANGED_e__Struct + { + [NativeTypeName("const QUIC_ADDR *")] + public QuicAddr* Address; + } + + internal unsafe partial struct _PEER_STREAM_STARTED_e__Struct + { + [NativeTypeName("HQUIC")] + public QUIC_HANDLE* Stream; + + public QUIC_STREAM_OPEN_FLAGS Flags; + } + + internal partial struct _STREAMS_AVAILABLE_e__Struct + { + [NativeTypeName("uint16_t")] + public ushort BidirectionalCount; + + [NativeTypeName("uint16_t")] + public ushort UnidirectionalCount; + } + + internal partial struct _IDEAL_PROCESSOR_CHANGED_e__Struct + { + [NativeTypeName("uint16_t")] + public ushort IdealProcessor; + } + + internal partial struct _DATAGRAM_STATE_CHANGED_e__Struct + { + [NativeTypeName("BOOLEAN")] + public byte SendEnabled; + + [NativeTypeName("uint16_t")] + public ushort MaxSendLength; + } + + internal unsafe partial struct _DATAGRAM_RECEIVED_e__Struct + { + [NativeTypeName("const QUIC_BUFFER *")] + public QUIC_BUFFER* Buffer; + + public QUIC_RECEIVE_FLAGS Flags; + } + + internal unsafe partial struct _DATAGRAM_SEND_STATE_CHANGED_e__Struct + { + public void* ClientContext; + + public QUIC_DATAGRAM_SEND_STATE State; + } + + internal unsafe partial struct _RESUMED_e__Struct + { + [NativeTypeName("uint16_t")] + public ushort ResumptionStateLength; + + [NativeTypeName("const uint8_t *")] + public byte* ResumptionState; + } + + internal unsafe partial struct _RESUMPTION_TICKET_RECEIVED_e__Struct + { + [NativeTypeName("uint32_t")] + public uint ResumptionTicketLength; + + [NativeTypeName("const uint8_t *")] + public byte* ResumptionTicket; + } + + internal unsafe partial struct _PEER_CERTIFICATE_RECEIVED_e__Struct + { + [NativeTypeName("QUIC_CERTIFICATE *")] + public void* Certificate; + + [NativeTypeName("uint32_t")] + public uint DeferredErrorFlags; + + [NativeTypeName("HRESULT")] + public int DeferredStatus; + + [NativeTypeName("QUIC_CERTIFICATE_CHAIN *")] + public void* Chain; + } + } + } + + internal enum QUIC_STREAM_EVENT_TYPE + { + QUIC_STREAM_EVENT_START_COMPLETE = 0, + QUIC_STREAM_EVENT_RECEIVE = 1, + QUIC_STREAM_EVENT_SEND_COMPLETE = 2, + QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN = 3, + QUIC_STREAM_EVENT_PEER_SEND_ABORTED = 4, + QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED = 5, + QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE = 6, + QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE = 7, + QUIC_STREAM_EVENT_IDEAL_SEND_BUFFER_SIZE = 8, + QUIC_STREAM_EVENT_PEER_ACCEPTED = 9, + } + + internal partial struct QUIC_STREAM_EVENT + { + public QUIC_STREAM_EVENT_TYPE Type; + + [NativeTypeName("QUIC_STREAM_EVENT::(anonymous union)")] + public _Anonymous_e__Union Anonymous; + + public ref _Anonymous_e__Union._START_COMPLETE_e__Struct START_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.START_COMPLETE, 1)); + } + } + + public ref _Anonymous_e__Union._RECEIVE_e__Struct RECEIVE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.RECEIVE, 1)); + } + } + + public ref _Anonymous_e__Union._SEND_COMPLETE_e__Struct SEND_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SEND_COMPLETE, 1)); + } + } + + public ref _Anonymous_e__Union._PEER_SEND_ABORTED_e__Struct PEER_SEND_ABORTED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.PEER_SEND_ABORTED, 1)); + } + } + + public ref _Anonymous_e__Union._PEER_RECEIVE_ABORTED_e__Struct PEER_RECEIVE_ABORTED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.PEER_RECEIVE_ABORTED, 1)); + } + } + + public ref _Anonymous_e__Union._SEND_SHUTDOWN_COMPLETE_e__Struct SEND_SHUTDOWN_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SEND_SHUTDOWN_COMPLETE, 1)); + } + } + + public ref _Anonymous_e__Union._SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_COMPLETE, 1)); + } + } + + public ref _Anonymous_e__Union._IDEAL_SEND_BUFFER_SIZE_e__Struct IDEAL_SEND_BUFFER_SIZE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IDEAL_SEND_BUFFER_SIZE, 1)); + } + } + + [StructLayout(LayoutKind.Explicit)] + internal partial struct _Anonymous_e__Union + { + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _START_COMPLETE_e__Struct START_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _RECEIVE_e__Struct RECEIVE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SEND_COMPLETE_e__Struct SEND_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _PEER_SEND_ABORTED_e__Struct PEER_SEND_ABORTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _PEER_RECEIVE_ABORTED_e__Struct PEER_RECEIVE_ABORTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SEND_SHUTDOWN_COMPLETE_e__Struct SEND_SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + public _IDEAL_SEND_BUFFER_SIZE_e__Struct IDEAL_SEND_BUFFER_SIZE; + + internal partial struct _START_COMPLETE_e__Struct + { + [NativeTypeName("HRESULT")] + public int Status; + + [NativeTypeName("QUIC_UINT62")] + public ulong ID; + + public byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + public byte PeerAccepted + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + public byte RESERVED + { + get + { + return (byte)((_bitfield >> 1) & 0x7Fu); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x7Fu << 1)) | ((value & 0x7Fu) << 1)); + } + } + } + + internal unsafe partial struct _RECEIVE_e__Struct + { + [NativeTypeName("uint64_t")] + public ulong AbsoluteOffset; + + [NativeTypeName("uint64_t")] + public ulong TotalBufferLength; + + [NativeTypeName("const QUIC_BUFFER *")] + public QUIC_BUFFER* Buffers; + + [NativeTypeName("uint32_t")] + public uint BufferCount; + + public QUIC_RECEIVE_FLAGS Flags; + } + + internal unsafe partial struct _SEND_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + public byte Canceled; + + public void* ClientContext; + } + + internal partial struct _PEER_SEND_ABORTED_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + public ulong ErrorCode; + } + + internal partial struct _PEER_RECEIVE_ABORTED_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + public ulong ErrorCode; + } + + internal partial struct _SEND_SHUTDOWN_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + public byte Graceful; + } + + internal partial struct _SHUTDOWN_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + public byte ConnectionShutdown; + + public byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + public byte AppCloseInProgress + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + public byte RESERVED + { + get + { + return (byte)((_bitfield >> 1) & 0x7Fu); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x7Fu << 1)) | ((value & 0x7Fu) << 1)); + } + } + } + + internal partial struct _IDEAL_SEND_BUFFER_SIZE_e__Struct + { + [NativeTypeName("uint64_t")] + public ulong ByteCount; + } + } + } + + internal unsafe partial struct QUIC_API_TABLE + { + [NativeTypeName("QUIC_SET_CONTEXT_FN")] + public delegate* unmanaged[Cdecl] SetContext; + + [NativeTypeName("QUIC_GET_CONTEXT_FN")] + public delegate* unmanaged[Cdecl] GetContext; + + [NativeTypeName("QUIC_SET_CALLBACK_HANDLER_FN")] + public delegate* unmanaged[Cdecl] SetCallbackHandler; + + [NativeTypeName("QUIC_SET_PARAM_FN")] + public delegate* unmanaged[Cdecl] SetParam; + + [NativeTypeName("QUIC_GET_PARAM_FN")] + public delegate* unmanaged[Cdecl] GetParam; + + [NativeTypeName("QUIC_REGISTRATION_OPEN_FN")] + public delegate* unmanaged[Cdecl] RegistrationOpen; + + [NativeTypeName("QUIC_REGISTRATION_CLOSE_FN")] + public delegate* unmanaged[Cdecl] RegistrationClose; + + [NativeTypeName("QUIC_REGISTRATION_SHUTDOWN_FN")] + public delegate* unmanaged[Cdecl] RegistrationShutdown; + + [NativeTypeName("QUIC_CONFIGURATION_OPEN_FN")] + public delegate* unmanaged[Cdecl] ConfigurationOpen; + + [NativeTypeName("QUIC_CONFIGURATION_CLOSE_FN")] + public delegate* unmanaged[Cdecl] ConfigurationClose; + + [NativeTypeName("QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN")] + public delegate* unmanaged[Cdecl] ConfigurationLoadCredential; + + [NativeTypeName("QUIC_LISTENER_OPEN_FN")] + public delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> ListenerOpen; + + [NativeTypeName("QUIC_LISTENER_CLOSE_FN")] + public delegate* unmanaged[Cdecl] ListenerClose; + + [NativeTypeName("QUIC_LISTENER_START_FN")] + public delegate* unmanaged[Cdecl] ListenerStart; + + [NativeTypeName("QUIC_LISTENER_STOP_FN")] + public delegate* unmanaged[Cdecl] ListenerStop; + + [NativeTypeName("QUIC_CONNECTION_OPEN_FN")] + public delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> ConnectionOpen; + + [NativeTypeName("QUIC_CONNECTION_CLOSE_FN")] + public delegate* unmanaged[Cdecl] ConnectionClose; + + [NativeTypeName("QUIC_CONNECTION_SHUTDOWN_FN")] + public delegate* unmanaged[Cdecl] ConnectionShutdown; + + [NativeTypeName("QUIC_CONNECTION_START_FN")] + public delegate* unmanaged[Cdecl] ConnectionStart; + + [NativeTypeName("QUIC_CONNECTION_SET_CONFIGURATION_FN")] + public delegate* unmanaged[Cdecl] ConnectionSetConfiguration; + + [NativeTypeName("QUIC_CONNECTION_SEND_RESUMPTION_FN")] + public delegate* unmanaged[Cdecl] ConnectionSendResumptionTicket; + + [NativeTypeName("QUIC_STREAM_OPEN_FN")] + public delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> StreamOpen; + + [NativeTypeName("QUIC_STREAM_CLOSE_FN")] + public delegate* unmanaged[Cdecl] StreamClose; + + [NativeTypeName("QUIC_STREAM_START_FN")] + public delegate* unmanaged[Cdecl] StreamStart; + + [NativeTypeName("QUIC_STREAM_SHUTDOWN_FN")] + public delegate* unmanaged[Cdecl] StreamShutdown; + + [NativeTypeName("QUIC_STREAM_SEND_FN")] + public delegate* unmanaged[Cdecl] StreamSend; + + [NativeTypeName("QUIC_STREAM_RECEIVE_COMPLETE_FN")] + public delegate* unmanaged[Cdecl] StreamReceiveComplete; + + [NativeTypeName("QUIC_STREAM_RECEIVE_SET_ENABLED_FN")] + public delegate* unmanaged[Cdecl] StreamReceiveSetEnabled; + + [NativeTypeName("QUIC_DATAGRAM_SEND_FN")] + public delegate* unmanaged[Cdecl] DatagramSend; + } + + internal static unsafe partial class MsQuic + { + [DllImport("msquic", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: NativeTypeName("HRESULT")] + public static extern int MsQuicOpenVersion([NativeTypeName("uint32_t")] uint Version, [NativeTypeName("const void **")] void** QuicApi); + + [DllImport("msquic", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public static extern void MsQuicClose([NativeTypeName("const void *")] void* QuicApi); + + [NativeTypeName("#define QUIC_MAX_ALPN_LENGTH 255")] + public const uint QUIC_MAX_ALPN_LENGTH = 255; + + [NativeTypeName("#define QUIC_MAX_SNI_LENGTH 65535")] + public const uint QUIC_MAX_SNI_LENGTH = 65535; + + [NativeTypeName("#define QUIC_MAX_RESUMPTION_APP_DATA_LENGTH 1000")] + public const uint QUIC_MAX_RESUMPTION_APP_DATA_LENGTH = 1000; + + [NativeTypeName("#define QUIC_MAX_TICKET_KEY_COUNT 16")] + public const uint QUIC_MAX_TICKET_KEY_COUNT = 16; + + [NativeTypeName("#define QUIC_TLS_SECRETS_MAX_SECRET_LEN 64")] + public const uint QUIC_TLS_SECRETS_MAX_SECRET_LEN = 64; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_GLOBAL 0x01000000")] + public const uint QUIC_PARAM_PREFIX_GLOBAL = 0x01000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_REGISTRATION 0x02000000")] + public const uint QUIC_PARAM_PREFIX_REGISTRATION = 0x02000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_CONFIGURATION 0x03000000")] + public const uint QUIC_PARAM_PREFIX_CONFIGURATION = 0x03000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_LISTENER 0x04000000")] + public const uint QUIC_PARAM_PREFIX_LISTENER = 0x04000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_CONNECTION 0x05000000")] + public const uint QUIC_PARAM_PREFIX_CONNECTION = 0x05000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_TLS 0x06000000")] + public const uint QUIC_PARAM_PREFIX_TLS = 0x06000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_TLS_SCHANNEL 0x07000000")] + public const uint QUIC_PARAM_PREFIX_TLS_SCHANNEL = 0x07000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_STREAM 0x08000000")] + public const uint QUIC_PARAM_PREFIX_STREAM = 0x08000000; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT 0x01000000")] + public const uint QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT = 0x01000000; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS 0x01000001")] + public const uint QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS = 0x01000001; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE 0x01000002")] + public const uint QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE = 0x01000002; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_PERF_COUNTERS 0x01000003")] + public const uint QUIC_PARAM_GLOBAL_PERF_COUNTERS = 0x01000003; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LIBRARY_VERSION 0x01000004")] + public const uint QUIC_PARAM_GLOBAL_LIBRARY_VERSION = 0x01000004; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_SETTINGS 0x01000005")] + public const uint QUIC_PARAM_GLOBAL_SETTINGS = 0x01000005; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS 0x01000006")] + public const uint QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS = 0x01000006; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_VERSION_SETTINGS 0x01000007")] + public const uint QUIC_PARAM_GLOBAL_VERSION_SETTINGS = 0x01000007; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH 0x01000008")] + public const uint QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH = 0x01000008; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_DATAPATH_PROCESSORS 0x01000009")] + public const uint QUIC_PARAM_GLOBAL_DATAPATH_PROCESSORS = 0x01000009; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_SETTINGS 0x03000000")] + public const uint QUIC_PARAM_CONFIGURATION_SETTINGS = 0x03000000; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_TICKET_KEYS 0x03000001")] + public const uint QUIC_PARAM_CONFIGURATION_TICKET_KEYS = 0x03000001; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS 0x03000002")] + public const uint QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS = 0x03000002; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_LOCAL_ADDRESS 0x04000000")] + public const uint QUIC_PARAM_LISTENER_LOCAL_ADDRESS = 0x04000000; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_STATS 0x04000001")] + public const uint QUIC_PARAM_LISTENER_STATS = 0x04000001; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_CIBIR_ID 0x04000002")] + public const uint QUIC_PARAM_LISTENER_CIBIR_ID = 0x04000002; + + [NativeTypeName("#define QUIC_PARAM_CONN_QUIC_VERSION 0x05000000")] + public const uint QUIC_PARAM_CONN_QUIC_VERSION = 0x05000000; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_ADDRESS 0x05000001")] + public const uint QUIC_PARAM_CONN_LOCAL_ADDRESS = 0x05000001; + + [NativeTypeName("#define QUIC_PARAM_CONN_REMOTE_ADDRESS 0x05000002")] + public const uint QUIC_PARAM_CONN_REMOTE_ADDRESS = 0x05000002; + + [NativeTypeName("#define QUIC_PARAM_CONN_IDEAL_PROCESSOR 0x05000003")] + public const uint QUIC_PARAM_CONN_IDEAL_PROCESSOR = 0x05000003; + + [NativeTypeName("#define QUIC_PARAM_CONN_SETTINGS 0x05000004")] + public const uint QUIC_PARAM_CONN_SETTINGS = 0x05000004; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS 0x05000005")] + public const uint QUIC_PARAM_CONN_STATISTICS = 0x05000005; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_PLAT 0x05000006")] + public const uint QUIC_PARAM_CONN_STATISTICS_PLAT = 0x05000006; + + [NativeTypeName("#define QUIC_PARAM_CONN_SHARE_UDP_BINDING 0x05000007")] + public const uint QUIC_PARAM_CONN_SHARE_UDP_BINDING = 0x05000007; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT 0x05000008")] + public const uint QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT = 0x05000008; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT 0x05000009")] + public const uint QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT = 0x05000009; + + [NativeTypeName("#define QUIC_PARAM_CONN_MAX_STREAM_IDS 0x0500000A")] + public const uint QUIC_PARAM_CONN_MAX_STREAM_IDS = 0x0500000A; + + [NativeTypeName("#define QUIC_PARAM_CONN_CLOSE_REASON_PHRASE 0x0500000B")] + public const uint QUIC_PARAM_CONN_CLOSE_REASON_PHRASE = 0x0500000B; + + [NativeTypeName("#define QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME 0x0500000C")] + public const uint QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME = 0x0500000C; + + [NativeTypeName("#define QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED 0x0500000D")] + public const uint QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED = 0x0500000D; + + [NativeTypeName("#define QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED 0x0500000E")] + public const uint QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED = 0x0500000E; + + [NativeTypeName("#define QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION 0x0500000F")] + public const uint QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION = 0x0500000F; + + [NativeTypeName("#define QUIC_PARAM_CONN_RESUMPTION_TICKET 0x05000010")] + public const uint QUIC_PARAM_CONN_RESUMPTION_TICKET = 0x05000010; + + [NativeTypeName("#define QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID 0x05000011")] + public const uint QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID = 0x05000011; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_INTERFACE 0x05000012")] + public const uint QUIC_PARAM_CONN_LOCAL_INTERFACE = 0x05000012; + + [NativeTypeName("#define QUIC_PARAM_CONN_TLS_SECRETS 0x05000013")] + public const uint QUIC_PARAM_CONN_TLS_SECRETS = 0x05000013; + + [NativeTypeName("#define QUIC_PARAM_CONN_VERSION_SETTINGS 0x05000014")] + public const uint QUIC_PARAM_CONN_VERSION_SETTINGS = 0x05000014; + + [NativeTypeName("#define QUIC_PARAM_CONN_CIBIR_ID 0x05000015")] + public const uint QUIC_PARAM_CONN_CIBIR_ID = 0x05000015; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_V2 0x05000016")] + public const uint QUIC_PARAM_CONN_STATISTICS_V2 = 0x05000016; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_V2_PLAT 0x05000017")] + public const uint QUIC_PARAM_CONN_STATISTICS_V2_PLAT = 0x05000017; + + [NativeTypeName("#define QUIC_PARAM_TLS_HANDSHAKE_INFO 0x06000000")] + public const uint QUIC_PARAM_TLS_HANDSHAKE_INFO = 0x06000000; + + [NativeTypeName("#define QUIC_PARAM_TLS_NEGOTIATED_ALPN 0x06000001")] + public const uint QUIC_PARAM_TLS_NEGOTIATED_ALPN = 0x06000001; + + [NativeTypeName("#define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W 0x07000000")] + public const uint QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W = 0x07000000; + + [NativeTypeName("#define QUIC_PARAM_STREAM_ID 0x08000000")] + public const uint QUIC_PARAM_STREAM_ID = 0x08000000; + + [NativeTypeName("#define QUIC_PARAM_STREAM_0RTT_LENGTH 0x08000001")] + public const uint QUIC_PARAM_STREAM_0RTT_LENGTH = 0x08000001; + + [NativeTypeName("#define QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE 0x08000002")] + public const uint QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE = 0x08000002; + + [NativeTypeName("#define QUIC_PARAM_STREAM_PRIORITY 0x08000003")] + public const uint QUIC_PARAM_STREAM_PRIORITY = 0x08000003; + + [NativeTypeName("#define QUIC_API_VERSION_2 2")] + public const uint QUIC_API_VERSION_2 = 2; + } +} +#pragma warning restore CS0649 diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_linux.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_linux.cs new file mode 100644 index 00000000000000..d9dfdb6134ab4a --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_linux.cs @@ -0,0 +1,112 @@ +#pragma warning disable IDE0073 +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +#pragma warning restore IDE0073 + + +using System.Runtime.InteropServices; + +namespace Microsoft.Quic +{ + internal static unsafe partial class MsQuic_Linux + { + [NativeTypeName("#define QUIC_STATUS_SUCCESS ((QUIC_STATUS)0)")] + public const int QUIC_STATUS_SUCCESS = ((int)(0)); + + [NativeTypeName("#define QUIC_STATUS_PENDING ((QUIC_STATUS)-2)")] + public const int QUIC_STATUS_PENDING = unchecked((int)(-2)); + + [NativeTypeName("#define QUIC_STATUS_CONTINUE ((QUIC_STATUS)-1)")] + public const int QUIC_STATUS_CONTINUE = unchecked((int)(-1)); + + [NativeTypeName("#define QUIC_STATUS_OUT_OF_MEMORY ((QUIC_STATUS)ENOMEM)")] + public const int QUIC_STATUS_OUT_OF_MEMORY = ((int)(12)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_PARAMETER ((QUIC_STATUS)EINVAL)")] + public const int QUIC_STATUS_INVALID_PARAMETER = ((int)(22)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_STATE ((QUIC_STATUS)EPERM)")] + public const int QUIC_STATUS_INVALID_STATE = ((int)(1)); + + [NativeTypeName("#define QUIC_STATUS_NOT_SUPPORTED ((QUIC_STATUS)EOPNOTSUPP)")] + public const int QUIC_STATUS_NOT_SUPPORTED = ((int)(95)); + + [NativeTypeName("#define QUIC_STATUS_NOT_FOUND ((QUIC_STATUS)ENOENT)")] + public const int QUIC_STATUS_NOT_FOUND = ((int)(2)); + + [NativeTypeName("#define QUIC_STATUS_BUFFER_TOO_SMALL ((QUIC_STATUS)EOVERFLOW)")] + public const int QUIC_STATUS_BUFFER_TOO_SMALL = ((int)(75)); + + [NativeTypeName("#define QUIC_STATUS_HANDSHAKE_FAILURE ((QUIC_STATUS)ECONNABORTED)")] + public const int QUIC_STATUS_HANDSHAKE_FAILURE = ((int)(103)); + + [NativeTypeName("#define QUIC_STATUS_ABORTED ((QUIC_STATUS)ECANCELED)")] + public const int QUIC_STATUS_ABORTED = ((int)(125)); + + [NativeTypeName("#define QUIC_STATUS_ADDRESS_IN_USE ((QUIC_STATUS)EADDRINUSE)")] + public const int QUIC_STATUS_ADDRESS_IN_USE = ((int)(98)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_TIMEOUT ((QUIC_STATUS)ETIMEDOUT)")] + public const int QUIC_STATUS_CONNECTION_TIMEOUT = ((int)(110)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_IDLE ((QUIC_STATUS)ETIME)")] + public const int QUIC_STATUS_CONNECTION_IDLE = ((int)(62)); + + [NativeTypeName("#define QUIC_STATUS_INTERNAL_ERROR ((QUIC_STATUS)EIO)")] + public const int QUIC_STATUS_INTERNAL_ERROR = ((int)(5)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_REFUSED ((QUIC_STATUS)ECONNREFUSED)")] + public const int QUIC_STATUS_CONNECTION_REFUSED = ((int)(111)); + + [NativeTypeName("#define QUIC_STATUS_PROTOCOL_ERROR ((QUIC_STATUS)EPROTO)")] + public const int QUIC_STATUS_PROTOCOL_ERROR = ((int)(71)); + + [NativeTypeName("#define QUIC_STATUS_VER_NEG_ERROR ((QUIC_STATUS)EPROTONOSUPPORT)")] + public const int QUIC_STATUS_VER_NEG_ERROR = ((int)(93)); + + [NativeTypeName("#define QUIC_STATUS_UNREACHABLE ((QUIC_STATUS)EHOSTUNREACH)")] + public const int QUIC_STATUS_UNREACHABLE = ((int)(113)); + + [NativeTypeName("#define QUIC_STATUS_TLS_ERROR ((QUIC_STATUS)ENOKEY)")] + public const int QUIC_STATUS_TLS_ERROR = ((int)(126)); + + [NativeTypeName("#define QUIC_STATUS_USER_CANCELED ((QUIC_STATUS)EOWNERDEAD)")] + public const int QUIC_STATUS_USER_CANCELED = ((int)(130)); + + [NativeTypeName("#define QUIC_STATUS_ALPN_NEG_FAILURE ((QUIC_STATUS)ENOPROTOOPT)")] + public const int QUIC_STATUS_ALPN_NEG_FAILURE = ((int)(92)); + + [NativeTypeName("#define QUIC_STATUS_STREAM_LIMIT_REACHED ((QUIC_STATUS)ESTRPIPE)")] + public const int QUIC_STATUS_STREAM_LIMIT_REACHED = ((int)(86)); + + [NativeTypeName("#define QUIC_STATUS_CLOSE_NOTIFY QUIC_STATUS_TLS_ALERT(0)")] + public const int QUIC_STATUS_CLOSE_NOTIFY = ((int)(0xff & 0) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_BAD_CERTIFICATE QUIC_STATUS_TLS_ALERT(42)")] + public const int QUIC_STATUS_BAD_CERTIFICATE = ((int)(0xff & 42) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_UNSUPPORTED_CERTIFICATE QUIC_STATUS_TLS_ALERT(43)")] + public const int QUIC_STATUS_UNSUPPORTED_CERTIFICATE = ((int)(0xff & 43) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_REVOKED_CERTIFICATE QUIC_STATUS_TLS_ALERT(44)")] + public const int QUIC_STATUS_REVOKED_CERTIFICATE = ((int)(0xff & 44) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_EXPIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(45)")] + public const int QUIC_STATUS_EXPIRED_CERTIFICATE = ((int)(0xff & 45) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_UNKNOWN_CERTIFICATE QUIC_STATUS_TLS_ALERT(46)")] + public const int QUIC_STATUS_UNKNOWN_CERTIFICATE = ((int)(0xff & 46) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_CERT_EXPIRED QUIC_STATUS_CERT_ERROR(1)")] + public const int QUIC_STATUS_CERT_EXPIRED = ((int)(1) + 512 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_CERT_UNTRUSTED_ROOT QUIC_STATUS_CERT_ERROR(2)")] + public const int QUIC_STATUS_CERT_UNTRUSTED_ROOT = ((int)(2) + 512 + 200000000); + + public const int QUIC_ADDRESS_FAMILY_UNSPEC = 0; + public const int QUIC_ADDRESS_FAMILY_INET = 2; + public const int QUIC_ADDRESS_FAMILY_INET6 = 10; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_macos.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_macos.cs new file mode 100644 index 00000000000000..a0a8d3d8d1f2d7 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_macos.cs @@ -0,0 +1,112 @@ +#pragma warning disable IDE0073 +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +#pragma warning restore IDE0073 + + +using System.Runtime.InteropServices; + +namespace Microsoft.Quic +{ + internal static unsafe partial class MsQuic_MacOS + { + [NativeTypeName("#define QUIC_STATUS_SUCCESS ((QUIC_STATUS)0)")] + public const int QUIC_STATUS_SUCCESS = ((int)(0)); + + [NativeTypeName("#define QUIC_STATUS_PENDING ((QUIC_STATUS)-2)")] + public const int QUIC_STATUS_PENDING = unchecked((int)(-2)); + + [NativeTypeName("#define QUIC_STATUS_CONTINUE ((QUIC_STATUS)-1)")] + public const int QUIC_STATUS_CONTINUE = unchecked((int)(-1)); + + [NativeTypeName("#define QUIC_STATUS_OUT_OF_MEMORY ((QUIC_STATUS)ENOMEM)")] + public const int QUIC_STATUS_OUT_OF_MEMORY = ((int)(12)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_PARAMETER ((QUIC_STATUS)EINVAL)")] + public const int QUIC_STATUS_INVALID_PARAMETER = ((int)(22)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_STATE ((QUIC_STATUS)EPERM)")] + public const int QUIC_STATUS_INVALID_STATE = ((int)(1)); + + [NativeTypeName("#define QUIC_STATUS_NOT_SUPPORTED ((QUIC_STATUS)EOPNOTSUPP)")] + public const int QUIC_STATUS_NOT_SUPPORTED = ((int)(102)); + + [NativeTypeName("#define QUIC_STATUS_NOT_FOUND ((QUIC_STATUS)ENOENT)")] + public const int QUIC_STATUS_NOT_FOUND = ((int)(2)); + + [NativeTypeName("#define QUIC_STATUS_BUFFER_TOO_SMALL ((QUIC_STATUS)EOVERFLOW)")] + public const int QUIC_STATUS_BUFFER_TOO_SMALL = ((int)(84)); + + [NativeTypeName("#define QUIC_STATUS_HANDSHAKE_FAILURE ((QUIC_STATUS)ECONNABORTED)")] + public const int QUIC_STATUS_HANDSHAKE_FAILURE = ((int)(53)); + + [NativeTypeName("#define QUIC_STATUS_ABORTED ((QUIC_STATUS)ECANCELED)")] + public const int QUIC_STATUS_ABORTED = ((int)(89)); + + [NativeTypeName("#define QUIC_STATUS_ADDRESS_IN_USE ((QUIC_STATUS)EADDRINUSE)")] + public const int QUIC_STATUS_ADDRESS_IN_USE = ((int)(48)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_TIMEOUT ((QUIC_STATUS)ETIMEDOUT)")] + public const int QUIC_STATUS_CONNECTION_TIMEOUT = ((int)(60)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_IDLE ((QUIC_STATUS)ETIME)")] + public const int QUIC_STATUS_CONNECTION_IDLE = ((int)(101)); + + [NativeTypeName("#define QUIC_STATUS_INTERNAL_ERROR ((QUIC_STATUS)EIO)")] + public const int QUIC_STATUS_INTERNAL_ERROR = ((int)(5)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_REFUSED ((QUIC_STATUS)ECONNREFUSED)")] + public const int QUIC_STATUS_CONNECTION_REFUSED = ((int)(61)); + + [NativeTypeName("#define QUIC_STATUS_PROTOCOL_ERROR ((QUIC_STATUS)EPROTO)")] + public const int QUIC_STATUS_PROTOCOL_ERROR = ((int)(100)); + + [NativeTypeName("#define QUIC_STATUS_VER_NEG_ERROR ((QUIC_STATUS)EPROTONOSUPPORT)")] + public const int QUIC_STATUS_VER_NEG_ERROR = ((int)(43)); + + [NativeTypeName("#define QUIC_STATUS_UNREACHABLE ((QUIC_STATUS)EHOSTUNREACH)")] + public const int QUIC_STATUS_UNREACHABLE = ((int)(65)); + + [NativeTypeName("#define QUIC_STATUS_TLS_ERROR ((QUIC_STATUS)ENOKEY)")] + public const int QUIC_STATUS_TLS_ERROR = ((int)(126)); + + [NativeTypeName("#define QUIC_STATUS_USER_CANCELED ((QUIC_STATUS)EOWNERDEAD)")] + public const int QUIC_STATUS_USER_CANCELED = ((int)(105)); + + [NativeTypeName("#define QUIC_STATUS_ALPN_NEG_FAILURE ((QUIC_STATUS)ENOPROTOOPT)")] + public const int QUIC_STATUS_ALPN_NEG_FAILURE = ((int)(42)); + + [NativeTypeName("#define QUIC_STATUS_STREAM_LIMIT_REACHED ((QUIC_STATUS)ESTRPIPE)")] + public const int QUIC_STATUS_STREAM_LIMIT_REACHED = ((int)(86)); + + [NativeTypeName("#define QUIC_STATUS_CLOSE_NOTIFY QUIC_STATUS_TLS_ALERT(0)")] + public const int QUIC_STATUS_CLOSE_NOTIFY = ((int)(0xff & 0) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_BAD_CERTIFICATE QUIC_STATUS_TLS_ALERT(42)")] + public const int QUIC_STATUS_BAD_CERTIFICATE = ((int)(0xff & 42) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_UNSUPPORTED_CERTIFICATE QUIC_STATUS_TLS_ALERT(43)")] + public const int QUIC_STATUS_UNSUPPORTED_CERTIFICATE = ((int)(0xff & 43) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_REVOKED_CERTIFICATE QUIC_STATUS_TLS_ALERT(44)")] + public const int QUIC_STATUS_REVOKED_CERTIFICATE = ((int)(0xff & 44) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_EXPIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(45)")] + public const int QUIC_STATUS_EXPIRED_CERTIFICATE = ((int)(0xff & 45) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_UNKNOWN_CERTIFICATE QUIC_STATUS_TLS_ALERT(46)")] + public const int QUIC_STATUS_UNKNOWN_CERTIFICATE = ((int)(0xff & 46) + 256 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_CERT_EXPIRED QUIC_STATUS_CERT_ERROR(1)")] + public const int QUIC_STATUS_CERT_EXPIRED = ((int)(1) + 512 + 200000000); + + [NativeTypeName("#define QUIC_STATUS_CERT_UNTRUSTED_ROOT QUIC_STATUS_CERT_ERROR(2)")] + public const int QUIC_STATUS_CERT_UNTRUSTED_ROOT = ((int)(2) + 512 + 200000000); + + public const int QUIC_ADDRESS_FAMILY_UNSPEC = 0; + public const int QUIC_ADDRESS_FAMILY_INET = 2; + public const int QUIC_ADDRESS_FAMILY_INET6 = 30; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_windows.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_windows.cs new file mode 100644 index 00000000000000..ee8cf6bf74ccba --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_windows.cs @@ -0,0 +1,109 @@ +#pragma warning disable IDE0073 +// +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// +#pragma warning restore IDE0073 + +namespace Microsoft.Quic +{ + internal static partial class MsQuic_Windows + { + [NativeTypeName("#define QUIC_STATUS_SUCCESS S_OK")] + public const int QUIC_STATUS_SUCCESS = ((int)(0)); + + [NativeTypeName("#define QUIC_STATUS_PENDING SUCCESS_HRESULT_FROM_WIN32(ERROR_IO_PENDING)")] + public const int QUIC_STATUS_PENDING = ((int)(((997) & 0x0000FFFF) | (7 << 16))); + + [NativeTypeName("#define QUIC_STATUS_CONTINUE SUCCESS_HRESULT_FROM_WIN32(ERROR_CONTINUE)")] + public const int QUIC_STATUS_CONTINUE = ((int)(((1246) & 0x0000FFFF) | (7 << 16))); + + [NativeTypeName("#define QUIC_STATUS_OUT_OF_MEMORY E_OUTOFMEMORY")] + public const int QUIC_STATUS_OUT_OF_MEMORY = unchecked((int)(0x8007000E)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_PARAMETER E_INVALIDARG")] + public const int QUIC_STATUS_INVALID_PARAMETER = unchecked((int)(0x80070057)); + + [NativeTypeName("#define QUIC_STATUS_INVALID_STATE QUIC_STATUS_HRESULT_FROM_WIN32(ERROR_INVALID_STATE)")] + public const int QUIC_STATUS_INVALID_STATE = unchecked((int)(5023) <= 0 ? ((int)(5023)) : ((int)(((5023) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_NOT_SUPPORTED E_NOINTERFACE")] + public const int QUIC_STATUS_NOT_SUPPORTED = unchecked((int)(0x80004002)); + + [NativeTypeName("#define QUIC_STATUS_NOT_FOUND QUIC_STATUS_HRESULT_FROM_WIN32(ERROR_NOT_FOUND)")] + public const int QUIC_STATUS_NOT_FOUND = unchecked((int)(1168) <= 0 ? ((int)(1168)) : ((int)(((1168) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_BUFFER_TOO_SMALL QUIC_STATUS_HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER)")] + public const int QUIC_STATUS_BUFFER_TOO_SMALL = unchecked((int)(122) <= 0 ? ((int)(122)) : ((int)(((122) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_HANDSHAKE_FAILURE ERROR_QUIC_HANDSHAKE_FAILURE")] + public const int QUIC_STATUS_HANDSHAKE_FAILURE = unchecked((int)(0x80410000)); + + [NativeTypeName("#define QUIC_STATUS_ABORTED E_ABORT")] + public const int QUIC_STATUS_ABORTED = unchecked((int)(0x80004004)); + + [NativeTypeName("#define QUIC_STATUS_ADDRESS_IN_USE QUIC_STATUS_HRESULT_FROM_WIN32(WSAEADDRINUSE)")] + public const int QUIC_STATUS_ADDRESS_IN_USE = unchecked((int)(10048) <= 0 ? ((int)(10048)) : ((int)(((10048) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_TIMEOUT ERROR_QUIC_CONNECTION_TIMEOUT")] + public const int QUIC_STATUS_CONNECTION_TIMEOUT = unchecked((int)(0x80410006)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_IDLE ERROR_QUIC_CONNECTION_IDLE")] + public const int QUIC_STATUS_CONNECTION_IDLE = unchecked((int)(0x80410005)); + + [NativeTypeName("#define QUIC_STATUS_UNREACHABLE QUIC_STATUS_HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE)")] + public const int QUIC_STATUS_UNREACHABLE = unchecked((int)(1232) <= 0 ? ((int)(1232)) : ((int)(((1232) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_INTERNAL_ERROR ERROR_QUIC_INTERNAL_ERROR")] + public const int QUIC_STATUS_INTERNAL_ERROR = unchecked((int)(0x80410003)); + + [NativeTypeName("#define QUIC_STATUS_CONNECTION_REFUSED QUIC_STATUS_HRESULT_FROM_WIN32(ERROR_CONNECTION_REFUSED)")] + public const int QUIC_STATUS_CONNECTION_REFUSED = unchecked((int)(1225) <= 0 ? ((int)(1225)) : ((int)(((1225) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_PROTOCOL_ERROR ERROR_QUIC_PROTOCOL_VIOLATION")] + public const int QUIC_STATUS_PROTOCOL_ERROR = unchecked((int)(0x80410004)); + + [NativeTypeName("#define QUIC_STATUS_VER_NEG_ERROR ERROR_QUIC_VER_NEG_FAILURE")] + public const int QUIC_STATUS_VER_NEG_ERROR = unchecked((int)(0x80410001)); + + [NativeTypeName("#define QUIC_STATUS_TLS_ERROR QUIC_STATUS_HRESULT_FROM_WIN32(WSA_SECURE_HOST_NOT_FOUND)")] + public const int QUIC_STATUS_TLS_ERROR = unchecked((int)(11032) <= 0 ? ((int)(11032)) : ((int)(((11032) & 0x0000FFFF) | (7 << 16) | 0x80000000))); + + [NativeTypeName("#define QUIC_STATUS_USER_CANCELED ERROR_QUIC_USER_CANCELED")] + public const int QUIC_STATUS_USER_CANCELED = unchecked((int)(0x80410002)); + + [NativeTypeName("#define QUIC_STATUS_ALPN_NEG_FAILURE ERROR_QUIC_ALPN_NEG_FAILURE")] + public const int QUIC_STATUS_ALPN_NEG_FAILURE = unchecked((int)(0x80410007)); + + [NativeTypeName("#define QUIC_STATUS_STREAM_LIMIT_REACHED ERROR_QUIC_STREAM_LIMIT_REACHED")] + public const int QUIC_STATUS_STREAM_LIMIT_REACHED = unchecked((int)(0x80410008)); + + [NativeTypeName("#define QUIC_STATUS_CLOSE_NOTIFY QUIC_STATUS_TLS_ALERT(0)")] + public const int QUIC_STATUS_CLOSE_NOTIFY = unchecked(((int)(0x80410100)) | (0xff & 0)); + + [NativeTypeName("#define QUIC_STATUS_BAD_CERTIFICATE QUIC_STATUS_TLS_ALERT(42)")] + public const int QUIC_STATUS_BAD_CERTIFICATE = unchecked(((int)(0x80410100)) | (0xff & 42)); + + [NativeTypeName("#define QUIC_STATUS_UNSUPPORTED_CERTIFICATE QUIC_STATUS_TLS_ALERT(43)")] + public const int QUIC_STATUS_UNSUPPORTED_CERTIFICATE = unchecked(((int)(0x80410100)) | (0xff & 43)); + + [NativeTypeName("#define QUIC_STATUS_REVOKED_CERTIFICATE QUIC_STATUS_TLS_ALERT(44)")] + public const int QUIC_STATUS_REVOKED_CERTIFICATE = unchecked(((int)(0x80410100)) | (0xff & 44)); + + [NativeTypeName("#define QUIC_STATUS_EXPIRED_CERTIFICATE QUIC_STATUS_TLS_ALERT(45)")] + public const int QUIC_STATUS_EXPIRED_CERTIFICATE = unchecked(((int)(0x80410100)) | (0xff & 45)); + + [NativeTypeName("#define QUIC_STATUS_UNKNOWN_CERTIFICATE QUIC_STATUS_TLS_ALERT(46)")] + public const int QUIC_STATUS_UNKNOWN_CERTIFICATE = unchecked(((int)(0x80410100)) | (0xff & 46)); + + [NativeTypeName("#define QUIC_STATUS_CERT_EXPIRED CERT_E_EXPIRED")] + public const int QUIC_STATUS_CERT_EXPIRED = unchecked((int)(0x800B0101)); + + [NativeTypeName("#define QUIC_STATUS_CERT_UNTRUSTED_ROOT CERT_E_UNTRUSTEDROOT")] + public const int QUIC_STATUS_CERT_UNTRUSTED_ROOT = unchecked((int)(0x800B0109)); + + public const int QUIC_ADDRESS_FAMILY_UNSPEC = 0; + public const int QUIC_ADDRESS_FAMILY_INET = 2; + public const int QUIC_ADDRESS_FAMILY_INET6 = 23; + } +} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index 99dc15398e9f04..6a03a4df4a4649 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -5,6 +5,7 @@ using System.Net.Quic.Implementations.MsQuic.Internal; using System.Net.Security; using System.Net.Sockets; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Security.Authentication; @@ -13,7 +14,8 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; +using Microsoft.Quic; +using static Microsoft.Quic.MsQuic; namespace System.Net.Quic.Implementations.MsQuic { @@ -23,9 +25,6 @@ internal sealed class MsQuicConnection : QuicConnectionProvider private static readonly Oid s_serverAuthOid = new Oid("1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.1"); private const uint DefaultResetValue = 0xffffffff; // Arbitrary value unlikely to conflict with application protocols. - // Delegate that wraps the static function that will be called when receiving an event. - private static unsafe readonly ConnectionCallbackDelegate s_connectionDelegate = new ConnectionCallbackDelegate(NativeCallbackHandler); - // TODO: remove this. // This is only used for client-initiated connections, and isn't needed even then once Connect() has been called. private SafeMsQuicConfigurationHandle? _configuration; @@ -40,7 +39,6 @@ internal sealed class MsQuicConnection : QuicConnectionProvider internal sealed class State { public SafeMsQuicConnectionHandle Handle = null!; // set inside of MsQuicConnection ctor. - public string TraceId = null!; // set inside of MsQuicConnection ctor. public GCHandle StateGCHandle; @@ -48,9 +46,9 @@ internal sealed class State public MsQuicConnection? Connection; public MsQuicListener.State? ListenerState; - public TaskCompletionSource? ConnectTcs; + public TaskCompletionSource? ConnectTcs; // TODO: only allocate these when there is an outstanding shutdown. - public readonly TaskCompletionSource ShutdownTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + public readonly TaskCompletionSource ShutdownTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); // Note that there's no such thing as resetable TCS, so we cannot reuse the same instance after we've set the result. // We also cannot use solutions like ManualResetValueTaskSourceCore, since we can have multiple waiters on the same TCS. @@ -90,7 +88,7 @@ public void RemoveStream(MsQuicStream? stream) if (releaseHandles) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handle after last stream."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handle after last stream."); Handle?.Dispose(); } } @@ -133,10 +131,8 @@ public void SetClosing() } } - internal string TraceId() => _state.TraceId; - // constructor for inbound connections - public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQuicListener.State listenerState, SafeMsQuicConnectionHandle handle, bool remoteCertificateRequired = false, X509RevocationMode revocationMode = X509RevocationMode.Offline, RemoteCertificateValidationCallback? remoteCertificateValidationCallback = null, ServerCertificateSelectionCallback? serverCertificateSelectionCallback = null) + public unsafe MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQuicListener.State listenerState, SafeMsQuicConnectionHandle handle, bool remoteCertificateRequired = false, X509RevocationMode revocationMode = X509RevocationMode.Offline, RemoteCertificateValidationCallback? remoteCertificateValidationCallback = null, ServerCertificateSelectionCallback? serverCertificateSelectionCallback = null) { _state.Handle = handle; _state.StateGCHandle = GCHandle.Alloc(_state); @@ -150,10 +146,11 @@ public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQ try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.SetCallbackHandlerDelegate( - _state.Handle, - s_connectionDelegate, - GCHandle.ToIntPtr(_state.StateGCHandle)); + delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; + MsQuicApi.Api.ApiTable->SetCallbackHandler( + _state.Handle.QuicHandle, + nativeCallback, + (void*)GCHandle.ToIntPtr(_state.StateGCHandle)); } catch { @@ -162,15 +159,14 @@ public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQ } _state.ListenerState = listenerState; - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{TraceId()} Inbound connection created"); + NetEventSource.Info(_state, $"{handle} Inbound connection created"); } } // constructor for outbound connections - public MsQuicConnection(QuicClientConnectionOptions options) + public unsafe MsQuicConnection(QuicClientConnectionOptions options) { ArgumentNullException.ThrowIfNull(options.RemoteEndPoint, nameof(options.RemoteEndPoint)); @@ -187,14 +183,14 @@ public MsQuicConnection(QuicClientConnectionOptions options) _state.StateGCHandle = GCHandle.Alloc(_state); try { + QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.ConnectionOpenDelegate( - MsQuicApi.Api.Registration, - s_connectionDelegate, - GCHandle.ToIntPtr(_state.StateGCHandle), - out _state.Handle); - - QuicExceptionHelpers.ThrowIfFailed(status, "Could not open the connection."); + ThrowIfFailure(MsQuicApi.Api.ApiTable->ConnectionOpen( + MsQuicApi.Api.Registration.QuicHandle, + &NativeCallback, + (void*)GCHandle.ToIntPtr(_state.StateGCHandle), + &handle), "Could not open the connection"); + _state.Handle = new SafeMsQuicConnectionHandle(handle); } catch { @@ -202,10 +198,9 @@ public MsQuicConnection(QuicClientConnectionOptions options) throw; } - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{TraceId()} Outbound connection created"); + NetEventSource.Info(_state, $"{_state.Handle} Outbound connection created"); } } @@ -219,11 +214,11 @@ public MsQuicConnection(QuicClientConnectionOptions options) internal override bool Connected => _state.Connected; - private static uint HandleEventConnected(State state, ref ConnectionEvent connectionEvent) + private static unsafe int HandleEventConnected(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { if (state.Connected) { - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } if (state.IsServer) @@ -239,14 +234,14 @@ private static uint HandleEventConnected(State state, ref ConnectionEvent connec // Move connection from pending to Accept queue and hand it out. if (listenerState.AcceptConnectionQueue.Writer.TryWrite(connection)) { - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } // Listener is closed connection.Dispose(); } } - return MsQuicStatusCodes.UserCanceled; + return QUIC_STATUS_USER_CANCELED; } else { @@ -255,27 +250,26 @@ private static uint HandleEventConnected(State state, ref ConnectionEvent connec Debug.Assert(state.Connection != null); - state.Connection._localEndPoint = MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS); - state.Connection.SetNegotiatedAlpn(connectionEvent.Data.Connected.NegotiatedAlpn, connectionEvent.Data.Connected.NegotiatedAlpnLength); + state.Connection._localEndPoint = MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, state.Handle, QUIC_PARAM_CONN_LOCAL_ADDRESS); + state.Connection.SetNegotiatedAlpn((IntPtr)connectionEvent.CONNECTED.NegotiatedAlpn, connectionEvent.CONNECTED.NegotiatedAlpnLength); state.Connection = null; state.Connected = true; - state.ConnectTcs!.SetResult(MsQuicStatusCodes.Success); + state.ConnectTcs!.SetResult(QUIC_STATUS_SUCCESS); state.ConnectTcs = null; } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventShutdownInitiatedByTransport(State state, ref ConnectionEvent connectionEvent) + private static int HandleEventShutdownInitiatedByTransport(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { if (!state.Connected && state.ConnectTcs != null) { Debug.Assert(state.Connection != null); state.Connection = null; - uint hresult = connectionEvent.Data.ShutdownInitiatedByTransport.Status; - Exception ex = QuicExceptionHelpers.CreateExceptionForHResult(hresult, "Connection has been shutdown by transport."); + Exception ex = new MsQuicException(connectionEvent.SHUTDOWN_INITIATED_BY_TRANSPORT.Status, "Connection has been shutdown by transport"); state.ConnectTcs!.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex)); state.ConnectTcs = null; } @@ -286,24 +280,24 @@ private static uint HandleEventShutdownInitiatedByTransport(State state, ref Con // See: https://github.com/dotnet/runtime/issues/60133 state.AbortErrorCode = 0; state.AcceptQueue.Writer.TryComplete(); - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventShutdownInitiatedByPeer(State state, ref ConnectionEvent connectionEvent) + private static int HandleEventShutdownInitiatedByPeer(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { - state.AbortErrorCode = (long)connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode; + state.AbortErrorCode = (long)connectionEvent.SHUTDOWN_INITIATED_BY_PEER.ErrorCode; state.AcceptQueue.Writer.TryComplete(); - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent connectionEvent) + private static int HandleEventShutdownComplete(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { // This is the final event on the connection, so free the GCHandle used by the event callback. state.StateGCHandle.Free(); if (state.ListenerState != null) { - // This is inbound connection that never got connected - becasue of TLS validation or some other reason. + // This is inbound connection that never got connected - because of TLS validation or some other reason. // Remove connection from pending queue and dispose it. if (state.ListenerState.PendingConnections.TryRemove(state.Handle.DangerousGetHandle(), out MsQuicConnection? connection)) { @@ -315,7 +309,7 @@ private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent state.Connection = null; - state.ShutdownTcs.SetResult(MsQuicStatusCodes.Success); + state.ShutdownTcs.SetResult(QUIC_STATUS_SUCCESS); // Stop accepting new streams. state.AcceptQueue.Writer.TryComplete(); @@ -340,35 +334,35 @@ private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent bidirectionalTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException())); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventNewStream(State state, ref ConnectionEvent connectionEvent) + private static unsafe int HandleEventNewStream(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { - var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.Data.PeerStreamStarted.Stream); - if (!state.TryQueueNewStream(streamHandle, connectionEvent.Data.PeerStreamStarted.Flags)) + var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.PEER_STREAM_STARTED.Stream); + if (!state.TryQueueNewStream(streamHandle, connectionEvent.PEER_STREAM_STARTED.Flags)) { // This will call StreamCloseDelegate and free the stream. // We will return Success to the MsQuic to prevent double free. streamHandle.Dispose(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventStreamsAvailable(State state, ref ConnectionEvent connectionEvent) + private static int HandleEventStreamsAvailable(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { TaskCompletionSource? unidirectionalTcs = null; TaskCompletionSource? bidirectionalTcs = null; lock (state) { - if (connectionEvent.Data.StreamsAvailable.UniDirectionalCount > 0) + if (connectionEvent.STREAMS_AVAILABLE.UnidirectionalCount > 0) { unidirectionalTcs = state.NewUnidirectionalStreamsAvailable; state.NewUnidirectionalStreamsAvailable = null; } - if (connectionEvent.Data.StreamsAvailable.BiDirectionalCount > 0) + if (connectionEvent.STREAMS_AVAILABLE.BidirectionalCount > 0) { bidirectionalTcs = state.NewBidirectionalStreamsAvailable; state.NewBidirectionalStreamsAvailable = null; @@ -384,10 +378,10 @@ private static uint HandleEventStreamsAvailable(State state, ref ConnectionEvent bidirectionalTcs.SetResult(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventPeerCertificateReceived(State state, ref ConnectionEvent connectionEvent) + private static unsafe int HandleEventPeerCertificateReceived(State state, ref QUIC_CONNECTION_EVENT connectionEvent) { SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None; X509Chain? chain = null; @@ -398,24 +392,26 @@ private static uint HandleEventPeerCertificateReceived(State state, ref Connecti try { - if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle != IntPtr.Zero) + IntPtr certificateHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Certificate; + if (certificateHandle != IntPtr.Zero) { if (OperatingSystem.IsWindows()) { - certificate = new X509Certificate2(connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle); + certificate = new X509Certificate2(certificateHandle); } else { unsafe { - ReadOnlySpan quicBuffer = new ReadOnlySpan((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle, sizeof(QuicBuffer)); + ReadOnlySpan quicBuffer = new ReadOnlySpan((void*)certificateHandle, sizeof(QUIC_BUFFER)); certificate = new X509Certificate2(new ReadOnlySpan(quicBuffer[0].Buffer, (int)quicBuffer[0].Length)); certificateBuffer = (IntPtr)quicBuffer[0].Buffer; certificateLength = (int)quicBuffer[0].Length; - if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle != IntPtr.Zero) + IntPtr chainHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Chain; + if (chainHandle != IntPtr.Zero) { - quicBuffer = new ReadOnlySpan((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle, sizeof(QuicBuffer)); + quicBuffer = new ReadOnlySpan((void*)chainHandle, sizeof(QUIC_BUFFER)); if (quicBuffer[0].Length != 0 && quicBuffer[0].Buffer != null) { additionalCertificates = new X509Certificate2Collection(); @@ -428,7 +424,7 @@ private static uint HandleEventPeerCertificateReceived(State state, ref Connecti if (certificate == null) { - if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.TraceId} Remote certificate required, but no remote certificate received"); + if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.Handle} Remote certificate required, but no remote certificate received"); sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable; } else @@ -461,40 +457,40 @@ private static uint HandleEventPeerCertificateReceived(State state, ref Connecti state.RemoteCertificateValidationCallback = (_, _, _, _) => success; if (!success && NetEventSource.Log.IsEnabled()) - NetEventSource.Error(state, $"{state.TraceId} Remote certificate rejected by verification callback"); + NetEventSource.Error(state, $"{state.Handle} Remote certificate rejected by verification callback"); if (!success) { if (state.IsServer) { - return MsQuicStatusCodes.UserCanceled; + return QUIC_STATUS_USER_CANCELED; } throw new AuthenticationException(SR.net_quic_cert_custom_validation); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } if (NetEventSource.Log.IsEnabled()) - NetEventSource.Info(state, $"{state.TraceId} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}"); + NetEventSource.Info(state, $"{state.Handle} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}"); if (sslPolicyErrors != SslPolicyErrors.None) { if (state.IsServer) { - return MsQuicStatusCodes.HandshakeFailure; + return QUIC_STATUS_HANDSHAKE_FAILURE; } throw new AuthenticationException(SR.Format(SR.net_quic_cert_chain_validation, sslPolicyErrors)); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } catch (Exception ex) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.TraceId} Certificate validation failed ${ex.Message}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.Handle} Certificate validation failed ${ex.Message}"); throw; } } @@ -590,7 +586,7 @@ internal override QuicStreamProvider OpenUnidirectionalStream() throw new InvalidOperationException(SR.net_quic_not_connected); } - return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); + return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL); } internal override QuicStreamProvider OpenBidirectionalStream() @@ -601,22 +597,22 @@ internal override QuicStreamProvider OpenBidirectionalStream() throw new InvalidOperationException(SR.net_quic_not_connected); } - return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.NONE); + return new MsQuicStream(_state, QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_NONE); } internal override int GetRemoteAvailableUnidirectionalStreamCount() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_UNIDI_STREAM_COUNT); + return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT); } internal override int GetRemoteAvailableBidirectionalStreamCount() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT); + return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT); } - internal override ValueTask ConnectAsync(CancellationToken cancellationToken = default) + internal unsafe override ValueTask ConnectAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -625,25 +621,24 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d throw new InvalidOperationException($"{nameof(ConnectAsync)} must not be called on a connection obtained from a listener."); } - QUIC_ADDRESS_FAMILY af = _remoteEndPoint.AddressFamily switch + ushort af = _remoteEndPoint.AddressFamily switch { - AddressFamily.Unspecified => QUIC_ADDRESS_FAMILY.UNSPEC, - AddressFamily.InterNetwork => QUIC_ADDRESS_FAMILY.INET, - AddressFamily.InterNetworkV6 => QUIC_ADDRESS_FAMILY.INET6, + AddressFamily.Unspecified => (ushort)QUIC_ADDRESS_FAMILY_UNSPEC, + AddressFamily.InterNetwork => (ushort)QUIC_ADDRESS_FAMILY_INET, + AddressFamily.InterNetworkV6 => (ushort)QUIC_ADDRESS_FAMILY_INET6, _ => throw new ArgumentException(SR.Format(SR.net_quic_unsupported_address_family, _remoteEndPoint.AddressFamily)) }; Debug.Assert(_state.StateGCHandle.IsAllocated); _state.Connection = this; - uint status; string targetHost; int port; if (_remoteEndPoint is IPEndPoint ipEndPoint) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, ipEndPoint); + MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_REMOTE_ADDRESS, ipEndPoint); targetHost = _state.TargetHost ?? ((IPEndPoint)_remoteEndPoint).Address.ToString(); port = ((IPEndPoint)_remoteEndPoint).Port; @@ -660,7 +655,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d { // This is form of IPAddress and _state.TargetHost is set to different string Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, new IPEndPoint(address, port)); + MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_REMOTE_ADDRESS, new IPEndPoint(address, port)); targetHost = _state.TargetHost!; } else @@ -674,19 +669,18 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d } // We store TCS to local variable to avoid NRE if callbacks finish fast and set _state.ConnectTcs to null. - var tcs = _state.ConnectTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var tcs = _state.ConnectTcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + IntPtr pTargetHost = Marshal.StringToCoTaskMemAnsi(targetHost); try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - status = MsQuicApi.Api.ConnectionStartDelegate( - _state.Handle, - _configuration, + ThrowIfFailure(MsQuicApi.Api.ApiTable->ConnectionStart( + _state.Handle.QuicHandle, + _configuration.QuicHandle, af, - targetHost, - (ushort)port); - - QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer."); + (sbyte*)pTargetHost, + (ushort)port), "Failed to connect to peer"); // this handle is ref counted by MsQuic, so safe to dispose here. _configuration.Dispose(); @@ -697,11 +691,15 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d _state.Connection = null; throw; } + finally + { + Marshal.FreeCoTaskMem(pTargetHost); + } return new ValueTask(tcs.Task); } - private ValueTask ShutdownAsync( + private unsafe ValueTask ShutdownAsync( QUIC_CONNECTION_SHUTDOWN_FLAGS Flags, long ErrorCode) { @@ -712,10 +710,10 @@ private ValueTask ShutdownAsync( try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.ConnectionShutdownDelegate( - _state.Handle, + MsQuicApi.Api.ApiTable->ConnectionShutdown( + _state.Handle.QuicHandle, Flags, - ErrorCode); + (ulong)ErrorCode); } catch { @@ -736,48 +734,48 @@ internal void SetNegotiatedAlpn(IntPtr alpn, int alpnLength) } } - private static unsafe uint NativeCallbackHandler( - IntPtr connection, - IntPtr context, - ConnectionEvent* connectionEvent) +#pragma warning disable CS3016 + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })] +#pragma warning restore CS3016 + private static unsafe int NativeCallback(QUIC_HANDLE* connection, void* context, QUIC_CONNECTION_EVENT* connectionEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr(context); + GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.TraceId} Connection received event {connectionEvent->Type}"); + NetEventSource.Info(state, $"{state.Handle} Connection received event {connectionEvent->Type}"); } try { switch (connectionEvent->Type) { - case QUIC_CONNECTION_EVENT_TYPE.CONNECTED: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_CONNECTED: return HandleEventConnected(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.SHUTDOWN_INITIATED_BY_TRANSPORT: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_TRANSPORT: return HandleEventShutdownInitiatedByTransport(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.SHUTDOWN_INITIATED_BY_PEER: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_SHUTDOWN_INITIATED_BY_PEER: return HandleEventShutdownInitiatedByPeer(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.SHUTDOWN_COMPLETE: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_SHUTDOWN_COMPLETE: return HandleEventShutdownComplete(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.PEER_STREAM_STARTED: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_PEER_STREAM_STARTED: return HandleEventNewStream(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.STREAMS_AVAILABLE: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_STREAMS_AVAILABLE: return HandleEventStreamsAvailable(state, ref *connectionEvent); - case QUIC_CONNECTION_EVENT_TYPE.PEER_CERTIFICATE_RECEIVED: + case QUIC_CONNECTION_EVENT_TYPE.QUIC_CONNECTION_EVENT_PEER_CERTIFICATE_RECEIVED: return HandleEventPeerCertificateReceived(state, ref *connectionEvent); default: - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"{state.TraceId} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); + NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); } if (state.ConnectTcs != null) @@ -789,11 +787,11 @@ private static unsafe uint NativeCallbackHandler( } else { - Debug.Fail($"{state.TraceId} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); + Debug.Fail($"{state.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); } // TODO: trigger an exception on any outstanding async calls. - return MsQuicStatusCodes.InternalError; + return QUIC_STATUS_INTERNAL_ERROR; } } @@ -825,7 +823,7 @@ private async Task FlushAcceptQueue() } } - private void Dispose(bool disposing) + private unsafe void Dispose(bool disposing) { int disposed = Interlocked.Exchange(ref _disposed, 1); if (disposed != 0) @@ -833,16 +831,16 @@ private void Dispose(bool disposing) return; } - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Connection disposing {disposing}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Connection disposing {disposing}"); // If we haven't already shutdown gracefully (via a successful CloseAsync call), then force an abortive shutdown. if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed) { // Handle can be null if outbound constructor failed and we are called from finalizer. Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.ConnectionShutdownDelegate( - _state.Handle, - QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT, + MsQuicApi.Api.ApiTable->ConnectionShutdown( + _state.Handle.QuicHandle, + QUIC_CONNECTION_SHUTDOWN_FLAGS.QUIC_CONNECTION_SHUTDOWN_FLAG_SILENT, 0); } @@ -865,7 +863,7 @@ private void Dispose(bool disposing) _configuration?.Dispose(); if (releaseHandles) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Connection releasing handle"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Connection releasing handle"); // We may not be fully initialized if constructor fails. _state.Handle?.Dispose(); @@ -881,7 +879,7 @@ internal override ValueTask CloseAsync(long errorCode, CancellationToken cancell return default; } - return ShutdownAsync(QUIC_CONNECTION_SHUTDOWN_FLAGS.NONE, errorCode); + return ShutdownAsync(QUIC_CONNECTION_SHUTDOWN_FLAGS.QUIC_CONNECTION_SHUTDOWN_FLAG_NONE, errorCode); } private void ThrowIfDisposed() diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs index 7c6831349062f1..95cc82471363fc 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs @@ -12,15 +12,15 @@ using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; using System.Net.Sockets; +using Microsoft.Quic; +using System.Runtime.CompilerServices; +using static Microsoft.Quic.MsQuic; namespace System.Net.Quic.Implementations.MsQuic { internal sealed class MsQuicListener : QuicListenerProvider, IDisposable { - private static unsafe readonly ListenerCallbackDelegate s_listenerDelegate = new ListenerCallbackDelegate(NativeCallbackHandler); - private readonly State _state; private GCHandle _stateHandle; private volatile bool _disposed; @@ -31,7 +31,6 @@ internal sealed class State { // set immediately in ctor, but we need a GCHandle to State in order to create the handle. public SafeMsQuicListenerHandle Handle = null!; - public string TraceId = null!; // set in ctor. public TaskCompletionSource StopCompletion = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -83,7 +82,7 @@ public State(QuicListenerOptions options) } } - internal MsQuicListener(QuicListenerOptions options) + internal unsafe MsQuicListener(QuicListenerOptions options) { ArgumentNullException.ThrowIfNull(options.ListenEndPoint, nameof(options.ListenEndPoint)); @@ -91,14 +90,14 @@ internal MsQuicListener(QuicListenerOptions options) _stateHandle = GCHandle.Alloc(_state); try { + QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.ListenerOpenDelegate( - MsQuicApi.Api.Registration, - s_listenerDelegate, - GCHandle.ToIntPtr(_stateHandle), - out _state.Handle); - - QuicExceptionHelpers.ThrowIfFailed(status, "ListenerOpen failed."); + ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerOpen( + MsQuicApi.Api.Registration.QuicHandle, + &NativeCallback, + (void*)GCHandle.ToIntPtr(_stateHandle), + &handle), "ListenerOpen failed"); + _state.Handle = new SafeMsQuicListenerHandle(handle); } catch { @@ -106,17 +105,16 @@ internal MsQuicListener(QuicListenerOptions options) throw; } - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.TraceId} Listener created"); + NetEventSource.Info(_state, $"{_state.Handle} Listener created"); } _listenEndPoint = Start(options); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.TraceId} Listener started"); + NetEventSource.Info(_state, $"{_state.Handle} Listener started"); } } @@ -183,19 +181,26 @@ private unsafe IPEndPoint Start(QuicListenerOptions options) Internals.SocketAddress address = IPEndPointExtensions.Serialize(listenEndPoint); - uint status; - Debug.Assert(_stateHandle.IsAllocated); MemoryHandle[]? handles = null; - QuicBuffer[]? buffers = null; + // TODO: should they be pinned? The content is pinned, but the array holding the individual buffers isn't. + QUIC_BUFFER[]? buffers = null; try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers); + // TODO: is the layout same for SocketAddress.Buffer and QuicAddr? + // TODO: maybe add simple extensions/helpers: + // - QuicAddr ToQuicAddr(this IPEndPoint ipEndPoint) + // - IPEndPoint ToIPEndPoint(this ref QuicAddr quicAddress) fixed (byte* paddress = address.Buffer) { - status = MsQuicApi.Api.ListenerStartDelegate(_state.Handle, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)applicationProtocols.Count, paddress); + ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerStart( + _state.Handle.QuicHandle, + (QUIC_BUFFER*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), + (uint)applicationProtocols.Count, + (QuicAddr*)paddress), "ListenerStart failed"); } } catch @@ -208,13 +213,11 @@ private unsafe IPEndPoint Start(QuicListenerOptions options) MsQuicAlpnHelper.Return(ref handles, ref buffers); } - QuicExceptionHelpers.ThrowIfFailed(status, "ListenerStart failed."); - Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - return MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_LISTENER.LOCAL_ADDRESS); + return MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LISTENER_LOCAL_ADDRESS); } - private Task StopAsync() + private unsafe Task StopAsync() { // TODO finalizers are called even if the object construction fails. if (_state == null) @@ -227,47 +230,47 @@ private Task StopAsync() if (_state.Handle != null) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.ListenerStopDelegate(_state.Handle); + MsQuicApi.Api.ApiTable->ListenerStop(_state.Handle.QuicHandle); } return _state.StopCompletion.Task; } - private static unsafe uint NativeCallbackHandler( - IntPtr listener, - IntPtr context, - ListenerEvent* listenerEvent) +#pragma warning disable CS3016 + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })] +#pragma warning restore CS3016 + private static unsafe int NativeCallback(QUIC_HANDLE* listener, void* context, QUIC_LISTENER_EVENT* listenerEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr(context); + GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; - if (listenerEvent->Type == QUIC_LISTENER_EVENT.STOP_COMPLETE) + if (listenerEvent->Type == QUIC_LISTENER_EVENT_TYPE.QUIC_LISTENER_EVENT_STOP_COMPLETE) { state.StopCompletion.TrySetResult(); - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - if (listenerEvent->Type != QUIC_LISTENER_EVENT.NEW_CONNECTION) + if (listenerEvent->Type != QUIC_LISTENER_EVENT_TYPE.QUIC_LISTENER_EVENT_NEW_CONNECTION) { - return MsQuicStatusCodes.InternalError; + return QUIC_STATUS_INTERNAL_ERROR; } SafeMsQuicConnectionHandle? connectionHandle = null; MsQuicConnection? msQuicConnection = null; try { - ref NewConnectionInfo connectionInfo = ref *listenerEvent->Data.NewConnection.Info; + ref QUIC_NEW_CONNECTION_INFO connectionInfo = ref *listenerEvent->NEW_CONNECTION.Info; - IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.LocalAddress); - IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.RemoteAddress); + IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.LocalAddress); + IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.RemoteAddress); string targetHost = string.Empty; // compat with SslStream - if (connectionInfo.ServerNameLength > 0 && connectionInfo.ServerName != IntPtr.Zero) + if (connectionInfo.ServerNameLength > 0 && (IntPtr)connectionInfo.ServerName != IntPtr.Zero) { // TBD We should figure out what to do with international names. - targetHost = Marshal.PtrToStringAnsi(connectionInfo.ServerName, connectionInfo.ServerNameLength); + targetHost = Marshal.PtrToStringAnsi((IntPtr)connectionInfo.ServerName, connectionInfo.ServerNameLength); } SafeMsQuicConfigurationHandle? connectionConfiguration = state.ConnectionConfiguration; @@ -291,25 +294,25 @@ private static unsafe uint NativeCallbackHandler( if (connectionConfiguration == null) { // We don't have safe handle yet so MsQuic will cleanup new connection. - return MsQuicStatusCodes.InternalError; + return QUIC_STATUS_INTERNAL_ERROR; } } - connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->Data.NewConnection.Connection); + connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->NEW_CONNECTION.Connection); Debug.Assert(!Monitor.IsEntered(state), "!Monitor.IsEntered(state)"); - uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, connectionConfiguration); - if (MsQuicStatusHelper.SuccessfulStatusCode(status)) + int status = MsQuicApi.Api.ApiTable->ConnectionSetConfiguration(connectionHandle.QuicHandle, connectionConfiguration.QuicHandle); + if (StatusSucceeded(status)) { msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, state, connectionHandle, state.AuthenticationOptions.ClientCertificateRequired, state.AuthenticationOptions.CertificateRevocationCheckMode, state.AuthenticationOptions.RemoteCertificateValidationCallback); - msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); + msQuicConnection.SetNegotiatedAlpn((IntPtr)connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); if (!state.PendingConnections.TryAdd(connectionHandle.DangerousGetHandle(), msQuicConnection)) { msQuicConnection.Dispose(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } // If we fall-through here something wrong happened. @@ -318,14 +321,14 @@ private static unsafe uint NativeCallbackHandler( { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {(QUIC_LISTENER_EVENT)listenerEvent->Type} connection callback: {ex}"); + NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {listenerEvent->Type} connection callback: {ex}"); } } // This handle will be cleaned up by MsQuic by returning InternalError. connectionHandle?.SetHandleAsInvalid(); msQuicConnection?.Dispose(); - return MsQuicStatusCodes.InternalError; + return QUIC_STATUS_INTERNAL_ERROR; } private void ThrowIfDisposed() diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs index e9a099b5ba5625..83bc624a018473 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs @@ -5,19 +5,18 @@ using System.Diagnostics; using System.IO; using System.Net.Quic.Implementations.MsQuic.Internal; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; +using Microsoft.Quic; +using static Microsoft.Quic.MsQuic; namespace System.Net.Quic.Implementations.MsQuic { internal sealed class MsQuicStream : QuicStreamProvider { - // Delegate that wraps the static function that will be called when receiving an event. - internal static unsafe readonly StreamCallbackDelegate s_streamDelegate = new StreamCallbackDelegate(NativeCallbackHandler); - // The state is passed to msquic and then it's passed back by msquic to the callback handler. private readonly State _state = new State(); @@ -38,9 +37,8 @@ private sealed class State public MsQuicStream? Stream; // roots the stream in the pinned state to prevent GC during an async read I/O. public MsQuicConnection.State ConnectionState = null!; // set in ctor. - public string TraceId = null!; // set in ctor. - public uint StartStatus = MsQuicStatusCodes.Success; + public int StartStatus = QUIC_STATUS_SUCCESS; public ReadState ReadState; @@ -48,7 +46,7 @@ private sealed class State public long ReadErrorCode = -1; // filled when ReadState.BuffersAvailable: - public QuicBuffer[] ReceiveQuicBuffers = Array.Empty(); + public QUIC_BUFFER[] ReceiveQuicBuffers = Array.Empty(); public int ReceiveQuicBuffersCount; public int ReceiveQuicBuffersTotalBytes; public bool ReceiveIsFinal; @@ -69,7 +67,7 @@ private sealed class State public int SendBufferCount; // Resettable completions to be used for multiple calls to send. - public readonly ResettableCompletionSource SendResettableCompletionSource = new ResettableCompletionSource(); + public readonly ResettableCompletionSource SendResettableCompletionSource = new ResettableCompletionSource(); public ShutdownWriteState ShutdownWriteState; @@ -88,7 +86,7 @@ private sealed class State public void Cleanup() { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handles."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handles."); ShutdownState = ShutdownState.Finished; CleanupSendState(this); @@ -100,10 +98,8 @@ public void Cleanup() } } - internal string TraceId() => _state.TraceId; - // inbound. - internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) + internal unsafe MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { if (!connectionState.TryAddStream(this)) { @@ -115,7 +111,7 @@ internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHa _state.Handle = streamHandle; _canRead = true; - _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); + _canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL); if (!_canWrite) { _state.SendState = SendState.Closed; @@ -125,10 +121,11 @@ internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHa try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.SetCallbackHandlerDelegate( - _state.Handle, - s_streamDelegate, - GCHandle.ToIntPtr(_state.StateGCHandle)); + delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; + MsQuicApi.Api.ApiTable->SetCallbackHandler( + _state.Handle.QuicHandle, + nativeCallback, + (void*)GCHandle.ToIntPtr(_state.StateGCHandle)); } catch { @@ -136,18 +133,17 @@ internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHa throw; } - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, - $"{TraceId()} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + - $"in connection {_state.ConnectionState.TraceId}."); + $"{_state.Handle} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + + $"in connection {_state.ConnectionState.Handle}."); } } // outbound. - internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags) + internal unsafe MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags) { Debug.Assert(connectionState.Handle != null); @@ -159,7 +155,7 @@ internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_F // but after TryAddStream to prevent unnecessary RemoveStream in finalizer _state.ConnectionState = connectionState; - _canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL); + _canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL); _canWrite = true; _state.StateGCHandle = GCHandle.Alloc(_state); @@ -170,25 +166,29 @@ internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_F try { + QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamOpenDelegate( - connectionState.Handle, + int status = MsQuicApi.Api.ApiTable->StreamOpen( + connectionState.Handle.QuicHandle, flags, - s_streamDelegate, - GCHandle.ToIntPtr(_state.StateGCHandle), - out _state.Handle); + &NativeCallback, + (void*)GCHandle.ToIntPtr(_state.StateGCHandle), + &handle); - if (status == MsQuicStatusCodes.Aborted) + if (status == QUIC_STATUS_ABORTED) { // connection already aborted by peer, throw relevant exception throw ThrowHelper.GetConnectionAbortedException(connectionState.AbortErrorCode); } - QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer."); + ThrowIfFailure(status, "Failed to open stream to peer"); + + _state.Handle = new SafeMsQuicStreamHandle(handle); Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.FAIL_BLOCKED | QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL); - QuicExceptionHelpers.ThrowIfFailed(status, "Could not start stream."); + ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamStart( + _state.Handle.QuicHandle, + QUIC_STREAM_START_FLAGS.QUIC_STREAM_START_FLAG_FAIL_BLOCKED | QUIC_STREAM_START_FLAGS.QUIC_STREAM_START_FLAG_SHUTDOWN_ON_FAIL), "Could not start stream"); } catch { @@ -197,13 +197,12 @@ internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_F throw; } - _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, - $"{_state.TraceId} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + - $"in connection {_state.ConnectionState.TraceId}."); + $"{_state.Handle} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.QUIC_STREAM_OPEN_FLAG_UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + + $"in connection {_state.ConnectionState.Handle}."); } } @@ -285,7 +284,7 @@ internal override async ValueTask WriteAsync(ReadOnlySequence buffers, boo using CancellationTokenRegistration registration = SetupWriteStartState(buffers.IsEmpty, cancellationToken); - await SendReadOnlySequenceAsync(buffers, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); + await SendReadOnlySequenceAsync(buffers, endStream ? QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN : QUIC_SEND_FLAGS.QUIC_SEND_FLAG_NONE).ConfigureAwait(false); CleanupWriteCompletedState(); } @@ -301,7 +300,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory using CancellationTokenRegistration registration = SetupWriteStartState(buffers.IsEmpty, cancellationToken); - await SendReadOnlyMemoryListAsync(buffers, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); + await SendReadOnlyMemoryListAsync(buffers, endStream ? QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN : QUIC_SEND_FLAGS.QUIC_SEND_FLAG_NONE).ConfigureAwait(false); CleanupWriteCompletedState(); } @@ -312,7 +311,7 @@ internal override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool e using CancellationTokenRegistration registration = SetupWriteStartState(buffer.IsEmpty, cancellationToken); - await SendReadOnlyMemoryAsync(buffer, endStream ? QUIC_SEND_FLAGS.FIN : QUIC_SEND_FLAGS.NONE).ConfigureAwait(false); + await SendReadOnlyMemoryAsync(buffer, endStream ? QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN : QUIC_SEND_FLAGS.QUIC_SEND_FLAG_NONE).ConfigureAwait(false); CleanupWriteCompletedState(); } @@ -431,7 +430,7 @@ internal override ValueTask ReadAsync(Memory destination, Cancellatio if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{TraceId()} Stream reading into Memory of '{destination.Length}' bytes."); + NetEventSource.Info(_state, $"{_state.Handle} Stream reading into Memory of '{destination.Length}' bytes."); } ReadState initialReadState; // value before transitions @@ -554,7 +553,7 @@ internal override ValueTask ReadAsync(Memory destination, Cancellatio } /// The number of bytes copied. - private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan sourceBuffers, Span destinationBuffer) + private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan sourceBuffers, Span destinationBuffer) { if (sourceBuffers.Length == 0) { @@ -562,7 +561,7 @@ private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan } int originalDestinationLength = destinationBuffer.Length; - QuicBuffer nativeBuffer; + QUIC_BUFFER nativeBuffer; int takeLength; int i = 0; @@ -599,7 +598,7 @@ internal override void AbortRead(long errorCode) ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException("Read was aborted"))); } - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, errorCode); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE, errorCode); } internal override void AbortWrite(long errorCode) @@ -646,14 +645,16 @@ internal override void AbortWrite(long errorCode) ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException("Write was aborted."))); } - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_SEND, errorCode); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_ABORT_SEND, errorCode); } - private void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) + private unsafe void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamShutdownDelegate(_state.Handle, flags, errorCode); - QuicExceptionHelpers.ThrowIfFailed(status, "StreamShutdown failed."); + ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamShutdown( + _state.Handle.QuicHandle, + flags, + (uint)errorCode), "StreamShutdown failed"); } internal override async ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) @@ -721,7 +722,7 @@ internal override void Shutdown() } // it is ok to send shutdown several times, MsQuic will ignore it - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, errorCode: 0); } // TODO consider removing sync-over-async with blocking calls. @@ -821,7 +822,7 @@ private void Dispose(bool disposing) } - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposing {disposing}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposing {disposing}"); bool callShutdown = false; bool abortRead = false; @@ -855,24 +856,27 @@ private void Dispose(bool disposing) } } - if (callShutdown) + if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed) { - try + if (callShutdown) { - // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE. - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); + try + { + // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE. + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, errorCode: 0); + } + catch (ObjectDisposedException) { }; } - catch (ObjectDisposedException) { }; - } - if (abortRead) - { - try + if (abortRead) { + try + { // TODO: error code used here MUST be specified by the application layer - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_ABORT_RECEIVE, 0xffffffff); + } + catch (ObjectDisposedException) { }; } - catch (ObjectDisposedException) { }; } if (completeRead) @@ -886,33 +890,32 @@ private void Dispose(bool disposing) _state.Cleanup(); } - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposed"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposed"); } - private void EnableReceive() + private unsafe void EnableReceive() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamReceiveSetEnabledDelegate(_state.Handle, enabled: true); - QuicExceptionHelpers.ThrowIfFailed(status, "StreamReceiveSetEnabled failed."); + ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamReceiveSetEnabled(_state.Handle.QuicHandle, 1), "StreamReceiveSetEnabled failed"); } /// /// Callback calls for a single instance of a stream are serialized by msquic. /// They happen on a msquic thread and shouldn't take too long to not to block msquic. /// - private static unsafe uint NativeCallbackHandler( - IntPtr stream, - IntPtr context, - StreamEvent* streamEvent) +#pragma warning disable CS3016 + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })] +#pragma warning restore CS3016 + private static unsafe int NativeCallback(QUIC_HANDLE* stream, void* context, QUIC_STREAM_EVENT* streamEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr(context); + GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.TraceId} Stream received event {streamEvent->Type}"); + NetEventSource.Info(state, $"{state.Handle} Stream received event {streamEvent->Type}"); } try @@ -921,56 +924,56 @@ private static unsafe uint NativeCallbackHandler( { // Stream has started. // Will only be done for outbound streams (inbound streams have already started) - case QUIC_STREAM_EVENT_TYPE.START_COMPLETE: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_START_COMPLETE: return HandleEventStartComplete(state, ref *streamEvent); // Received data on the stream - case QUIC_STREAM_EVENT_TYPE.RECEIVE: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_RECEIVE: return HandleEventRecv(state, ref *streamEvent); // Send has completed. // Contains a canceled bool to indicate if the send was canceled. - case QUIC_STREAM_EVENT_TYPE.SEND_COMPLETE: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_SEND_COMPLETE: return HandleEventSendComplete(state, ref *streamEvent); // Peer has told us to shutdown the reading side of the stream. - case QUIC_STREAM_EVENT_TYPE.PEER_SEND_SHUTDOWN: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_PEER_SEND_SHUTDOWN: return HandleEventPeerSendShutdown(state); // Peer has told us to abort the reading side of the stream. - case QUIC_STREAM_EVENT_TYPE.PEER_SEND_ABORTED: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_PEER_SEND_ABORTED: return HandleEventPeerSendAborted(state, ref *streamEvent); // Peer has stopped receiving data, don't send anymore. - case QUIC_STREAM_EVENT_TYPE.PEER_RECEIVE_ABORTED: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_PEER_RECEIVE_ABORTED: return HandleEventPeerRecvAborted(state, ref *streamEvent); // Occurs when shutdown is completed for the send side. // This only happens for shutdown on sending, not receiving // Receive shutdown can only be abortive. - case QUIC_STREAM_EVENT_TYPE.SEND_SHUTDOWN_COMPLETE: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_SEND_SHUTDOWN_COMPLETE: return HandleEventSendShutdownComplete(state, ref *streamEvent); // Shutdown for both sending and receiving is completed. - case QUIC_STREAM_EVENT_TYPE.SHUTDOWN_COMPLETE: + case QUIC_STREAM_EVENT_TYPE.QUIC_STREAM_EVENT_SHUTDOWN_COMPLETE: return HandleEventShutdownComplete(state, ref *streamEvent); default: - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); + NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); } - Debug.Fail($"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); + Debug.Fail($"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); - return MsQuicStatusCodes.InternalError; + return QUIC_STATUS_INTERNAL_ERROR; } } - private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) + private static unsafe int HandleEventRecv(State state, ref QUIC_STREAM_EVENT streamEvent) { - ref StreamEventDataReceive receiveEvent = ref evt.Data.Receive; + ref var receiveEvent = ref streamEvent.RECEIVE; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.TraceId} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) ? " with FIN flag" : "")}"); + NetEventSource.Info(state, $"{state.Handle} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.QUIC_RECEIVE_FLAG_FIN) ? " with FIN flag" : "")}"); } int readLength; @@ -991,12 +994,12 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) if ((uint)state.ReceiveQuicBuffers.Length < receiveEvent.BufferCount) { - QuicBuffer[] oldReceiveBuffers = state.ReceiveQuicBuffers; - state.ReceiveQuicBuffers = ArrayPool.Shared.Rent((int)receiveEvent.BufferCount); + QUIC_BUFFER[] oldReceiveBuffers = state.ReceiveQuicBuffers; + state.ReceiveQuicBuffers = ArrayPool.Shared.Rent((int)receiveEvent.BufferCount); if (oldReceiveBuffers.Length != 0) // don't return Array.Empty. { - ArrayPool.Shared.Return(oldReceiveBuffers); + ArrayPool.Shared.Return(oldReceiveBuffers); } } @@ -1007,7 +1010,7 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) state.ReceiveQuicBuffersCount = (int)receiveEvent.BufferCount; state.ReceiveQuicBuffersTotalBytes = checked((int)receiveEvent.TotalBufferLength); - state.ReceiveIsFinal = receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN); + state.ReceiveIsFinal = receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.QUIC_RECEIVE_FLAG_FIN); // 0-length receive can happens once reads are finished (gracefully or otherwise). if (state.ReceiveQuicBuffersTotalBytes == 0) @@ -1019,13 +1022,13 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) } // if it was not a graceful shutdown, we defer aborting to PEER_SEND_ABORT event handler - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } else { // Normal RECEIVE - data will be buffered until user calls ReadAsync() and no new event will be issued until EnableReceive() state.ReadState = ReadState.IndividualReadComplete; - return MsQuicStatusCodes.Pending; + return QUIC_STATUS_PENDING; } case ReadState.PendingRead: @@ -1036,10 +1039,10 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) state.Stream = null; state.ReadState = ReadState.None; - readLength = CopyMsQuicBuffersToUserBuffer(new ReadOnlySpan(receiveEvent.Buffers, (int)receiveEvent.BufferCount), state.ReceiveUserBuffer.Span); + readLength = CopyMsQuicBuffersToUserBuffer(new ReadOnlySpan(receiveEvent.Buffers, (int)receiveEvent.BufferCount), state.ReceiveUserBuffer.Span); // This was a final message and we've consumed everything. We can complete the state without waiting for PEER_SEND_SHUTDOWN - if (receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) && (uint)readLength == receiveEvent.TotalBufferLength) + if (receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.QUIC_RECEIVE_FLAG_FIN) && (uint)readLength == receiveEvent.TotalBufferLength) { state.ReadState = ReadState.ReadsCompleted; } @@ -1053,7 +1056,7 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) // There was a race between a user aborting the read stream and the callback being ran. // This will eat any received data. - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } } @@ -1066,15 +1069,15 @@ private static unsafe uint HandleEventRecv(State state, ref StreamEvent evt) // Returning Success when the entire buffer hasn't been consumed will cause MsQuic to disable further receive events until EnableReceive() is called. // Returning Continue will cause a second receive event to fire immediately after this returns, but allows MsQuic to clean up its buffers. - uint ret = (uint)readLength == receiveEvent.TotalBufferLength - ? MsQuicStatusCodes.Success - : MsQuicStatusCodes.Continue; + int ret = (uint)readLength == receiveEvent.TotalBufferLength + ? QUIC_STATUS_SUCCESS + : QUIC_STATUS_CONTINUE; receiveEvent.TotalBufferLength = (uint)readLength; return ret; } - private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt) + private static int HandleEventPeerRecvAborted(State state, ref QUIC_STREAM_EVENT streamEvent) { bool shouldSendComplete = false; bool shouldShutdownWriteComplete = false; @@ -1092,7 +1095,7 @@ private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt) } state.SendState = SendState.Aborted; - state.SendErrorCode = (long)evt.Data.PeerReceiveAborted.ErrorCode; + state.SendErrorCode = (long)streamEvent.PEER_RECEIVE_ABORTED.ErrorCode; } if (shouldSendComplete) @@ -1107,17 +1110,17 @@ private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt) ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.SendErrorCode))); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventStartComplete(State state, ref StreamEvent evt) + private static int HandleEventStartComplete(State state, ref QUIC_STREAM_EVENT streamEvent) { // Store the start status code and check it when propagating shutdown event, which we'll get since we set SHUTDOWN_ON_FAIL in StreamStart. - state.StartStatus = evt.Data.StartComplete.Status; - return MsQuicStatusCodes.Success; + state.StartStatus = streamEvent.START_COMPLETE.Status; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent evt) + private static int HandleEventSendShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent) { // Graceful will be false in three situations: // 1. The peer aborted reads and the PEER_RECEIVE_ABORTED event was raised. @@ -1128,7 +1131,7 @@ private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent // SHUTDOWN_COMPLETE event will be raised immediately after this event. It will handle completing with an error. // // Only use this event with sends gracefully completed. - if (evt.Data.SendShutdownComplete.Graceful != 0) + if (streamEvent.SEND_SHUTDOWN_COMPLETE.Graceful != 0) { bool shouldComplete = false; lock (state) @@ -1146,12 +1149,12 @@ private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent } } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt) + private static int HandleEventShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent) { - StreamEventDataShutdownComplete shutdownCompleteEvent = evt.Data.ShutdownComplete; + var shutdownCompleteEvent = streamEvent.SHUTDOWN_COMPLETE; if (shutdownCompleteEvent.ConnectionShutdown != 0) { @@ -1165,7 +1168,7 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt lock (state) { // This event won't occur within the middle of a receive. - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.Handle} Stream completing resettable event source."); shouldReadComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted); @@ -1187,27 +1190,27 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt if (shouldReadComplete) { - if (state.StartStatus == MsQuicStatusCodes.Success) + if (state.StartStatus == QUIC_STATUS_SUCCESS) { state.ReceiveResettableCompletionSource.Complete(0); } else { state.ReceiveResettableCompletionSource.CompleteException( - ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException($"Stream start failed with {MsQuicStatusCodes.GetError(state.StartStatus)}"))); + ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException($"Stream start failed with {MsQuicException.GetErrorCodeForStatus(state.StartStatus)}"))); } } if (shouldShutdownWriteComplete) { - if (state.StartStatus == MsQuicStatusCodes.Success) + if (state.StartStatus == QUIC_STATUS_SUCCESS) { state.ShutdownWriteCompletionSource.SetResult(); } else { state.ShutdownWriteCompletionSource.SetException( - ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException($"Stream start failed with {MsQuicStatusCodes.GetError(state.StartStatus)}"))); + ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException($"Stream start failed with {MsQuicException.GetErrorCodeForStatus(state.StartStatus)}"))); } } @@ -1223,16 +1226,16 @@ private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt state.Cleanup(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventPeerSendAborted(State state, ref StreamEvent evt) + private static int HandleEventPeerSendAborted(State state, ref QUIC_STREAM_EVENT streamEvent) { bool shouldComplete = false; lock (state) { shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.Aborted); - state.ReadErrorCode = (long)evt.Data.PeerSendAborted.ErrorCode; + state.ReadErrorCode = (long)streamEvent.PEER_SEND_ABORTED.ErrorCode; } if (shouldComplete) @@ -1241,17 +1244,17 @@ private static uint HandleEventPeerSendAborted(State state, ref StreamEvent evt) ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.ReadErrorCode))); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventPeerSendShutdown(State state) + private static int HandleEventPeerSendShutdown(State state) { bool shouldComplete = false; lock (state) { // This event won't occur within the middle of a receive. - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.Handle} Stream completing resettable event source."); shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted); } @@ -1261,12 +1264,12 @@ private static uint HandleEventPeerSendShutdown(State state) state.ReceiveResettableCompletionSource.Complete(0); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventSendComplete(State state, ref StreamEvent evt) + private static int HandleEventSendComplete(State state, ref QUIC_STREAM_EVENT streamEvent) { - StreamEventDataSendComplete sendCompleteEvent = evt.Data.SendComplete; + var sendCompleteEvent = streamEvent.SEND_COMPLETE; bool canceled = sendCompleteEvent.Canceled != 0; bool complete = false; @@ -1291,7 +1294,7 @@ private static uint HandleEventSendComplete(State state, ref StreamEvent evt) if (!canceled) { - state.SendResettableCompletionSource.Complete(MsQuicStatusCodes.Success); + state.SendResettableCompletionSource.Complete(QUIC_STATUS_SUCCESS); } else { @@ -1308,7 +1311,7 @@ private static uint HandleEventSendComplete(State state, ref StreamEvent evt) } } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } private static void CleanupSendState(State state) @@ -1332,10 +1335,10 @@ private unsafe ValueTask SendReadOnlyMemoryAsync( { if (buffer.IsEmpty) { - if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) + if ((flags & QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) == QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) { // Start graceful shutdown sequence if passed in the fin flag and there is an empty buffer. - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, errorCode: 0); } return default; } @@ -1343,11 +1346,11 @@ private unsafe ValueTask SendReadOnlyMemoryAsync( MemoryHandle handle = buffer.Pin(); if (_state.SendQuicBuffers == IntPtr.Zero) { - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer)); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER)); _state.SendBufferMaxCount = 1; } - QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; + QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; quicBuffers->Length = (uint)buffer.Length; quicBuffers->Buffer = (byte*)handle.Pointer; @@ -1355,24 +1358,23 @@ private unsafe ValueTask SendReadOnlyMemoryAsync( _state.SendBufferCount = 1; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamSendDelegate( - _state.Handle, + int status = MsQuicApi.Api.ApiTable->StreamSend( + _state.Handle.QuicHandle, quicBuffers, - bufferCount: 1, + 1, flags, - IntPtr.Zero); + (void*)IntPtr.Zero); - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) + if (!StatusSucceeded(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == MsQuicStatusCodes.Aborted) + if (status == QUIC_STATUS_ABORTED) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - QuicExceptionHelpers.ThrowIfFailed(status, - "Could not send data to peer."); + ThrowIfFailure(status, "Could not send data to peer"); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); @@ -1384,10 +1386,10 @@ private unsafe ValueTask SendReadOnlySequenceAsync( { if (buffers.IsEmpty) { - if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) + if ((flags & QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) == QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) { // Start graceful shutdown sequence if passed in the fin flag and there is an empty buffer. - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, errorCode: 0); } return default; } @@ -1403,7 +1405,7 @@ private unsafe ValueTask SendReadOnlySequenceAsync( { Marshal.FreeHGlobal(_state.SendQuicBuffers); _state.SendQuicBuffers = IntPtr.Zero; - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * count); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * count); _state.SendBufferMaxCount = count; _state.BufferArrays = new MemoryHandle[count]; } @@ -1411,7 +1413,7 @@ private unsafe ValueTask SendReadOnlySequenceAsync( _state.SendBufferCount = count; count = 0; - QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; + QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; foreach (ReadOnlyMemory buffer in buffers) { MemoryHandle handle = buffer.Pin(); @@ -1422,24 +1424,23 @@ private unsafe ValueTask SendReadOnlySequenceAsync( } Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamSendDelegate( - _state.Handle, + int status = MsQuicApi.Api.ApiTable->StreamSend( + _state.Handle.QuicHandle, quicBuffers, (uint)count, flags, - IntPtr.Zero); + (void*)IntPtr.Zero); - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) + if (!StatusSucceeded(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == MsQuicStatusCodes.Aborted) + if (status == QUIC_STATUS_ABORTED) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - QuicExceptionHelpers.ThrowIfFailed(status, - "Could not send data to peer."); + ThrowIfFailure(status, "Could not send data to peer"); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); @@ -1451,10 +1452,10 @@ private unsafe ValueTask SendReadOnlyMemoryListAsync( { if (buffers.IsEmpty) { - if ((flags & QUIC_SEND_FLAGS.FIN) == QUIC_SEND_FLAGS.FIN) + if ((flags & QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) == QUIC_SEND_FLAGS.QUIC_SEND_FLAG_FIN) { // Start graceful shutdown sequence if passed in the fin flag and there is an empty buffer. - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.QUIC_STREAM_SHUTDOWN_FLAG_GRACEFUL, errorCode: 0); } return default; } @@ -1467,13 +1468,13 @@ private unsafe ValueTask SendReadOnlyMemoryListAsync( { Marshal.FreeHGlobal(_state.SendQuicBuffers); _state.SendQuicBuffers = IntPtr.Zero; - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * array.Length); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * array.Length); _state.SendBufferMaxCount = array.Length; _state.BufferArrays = new MemoryHandle[array.Length]; } _state.SendBufferCount = array.Length; - QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; + QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; for (int i = 0; i < length; i++) { ReadOnlyMemory buffer = array[i]; @@ -1486,39 +1487,38 @@ private unsafe ValueTask SendReadOnlyMemoryListAsync( } Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - uint status = MsQuicApi.Api.StreamSendDelegate( - _state.Handle, + int status = MsQuicApi.Api.ApiTable->StreamSend( + _state.Handle.QuicHandle, quicBuffers, length, flags, - IntPtr.Zero); + (void*)IntPtr.Zero); - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) + if (!StatusSucceeded(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == MsQuicStatusCodes.Aborted) + if (status == QUIC_STATUS_ABORTED) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - QuicExceptionHelpers.ThrowIfFailed(status, - "Could not send data to peer."); + ThrowIfFailure(status, "Could not send data to peer"); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); } - private void ReceiveComplete(int bufferLength) + private unsafe void ReceiveComplete(int bufferLength) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.StreamReceiveCompleteDelegate(_state.Handle, (ulong)bufferLength); + MsQuicApi.Api.ApiTable->StreamReceiveComplete(_state.Handle.QuicHandle, (ulong)bufferLength); } // This can fail if the stream isn't started. private long GetStreamId() { - return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_STREAM.ID); + return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_STREAM_ID); } private void ThrowIfDisposed() @@ -1529,12 +1529,12 @@ private void ThrowIfDisposed() } } - private static uint HandleEventConnectionClose(State state) + private static int HandleEventConnectionClose(State state) { long errorCode = state.ConnectionState.AbortErrorCode; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.TraceId} Stream handling connection {state.ConnectionState.TraceId} close" + + NetEventSource.Info(state, $"{state.Handle} Stream handling connection {state.ConnectionState.Handle} close" + (errorCode != -1 ? $" with code {errorCode}" : "")); } @@ -1597,7 +1597,7 @@ private static uint HandleEventConnectionClose(State state) state.Cleanup(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } private static Exception GetConnectionAbortedException(State state) => diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs index 66d66f0e40987f..a848475ee83658 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/NetEventSource.Quic.cs @@ -2,11 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.Tracing; +using System.Net.Quic.Implementations.MsQuic.Internal; namespace System.Net { [EventSource(Name = "Private.InternalDiagnostics.System.Net.Quic")] internal sealed partial class NetEventSource : EventSource { + static partial void AdditionalCustomizedToString(T value, ref string? result) + { + MsQuicSafeHandle? safeHandle = value as MsQuicSafeHandle; + if (safeHandle is not null) + { + result = safeHandle.ToString(); + } + } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicException.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicException.cs index 4cd9745d82a8f7..151eb54392f1e6 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicException.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicException.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Net.Quic @@ -17,7 +17,12 @@ public QuicException(string? message, Exception? innerException) public QuicException(string? message, Exception? innerException, int result) : base(message, innerException) { - HResult = result; + // HResult 0 means OK, so do not override the default value set by Exception ctor, + // because in this case we don't have an HResult. + if (result != 0) + { + HResult = result; + } } } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs index 17793a6367b502..aa7eaa64cc0fd1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicCipherSuitesPolicyTests.cs @@ -56,7 +56,7 @@ public void NoSupportedCiphers_ThrowsArgumentException(TlsCipherSuite[] ciphers) [Fact] public async Task MismatchedCipherPolicies_ConnectAsync_ThrowsQuicException() { - await Assert.ThrowsAsync(() => TestConnection( + await Assert.ThrowsAnyAsync(() => TestConnection( new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_128_GCM_SHA256 }), new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_256_GCM_SHA384 }) )); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 9cd0dad78c32cb..81de0506410a84 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -146,7 +146,6 @@ public async Task UntrustedClientCertificateFails() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)] public async Task CertificateCallbackThrowPropagates() { using CancellationTokenSource cts = new CancellationTokenSource(PassingTestTimeout); @@ -188,7 +187,6 @@ public async Task CertificateCallbackThrowPropagates() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)] public async Task ConnectWithCertificateCallback() { X509Certificate2 c1 = System.Net.Test.Common.Configuration.Certificates.GetServerCertificate(); @@ -239,7 +237,7 @@ public async Task ConnectWithCertificateCallback() clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions); Task clientTask = clientConnection.ConnectAsync(cts.Token).AsTask(); - await Assert.ThrowsAsync(() => clientTask); + await Assert.ThrowsAnyAsync(() => clientTask); Assert.Equal(clientOptions.ClientAuthenticationOptions.TargetHost, receivedHostName); clientConnection.Dispose(); @@ -319,12 +317,6 @@ public async Task ConnectWithCertificateForLoopbackIP_IndicatesExpectedError(str { var ipAddress = IPAddress.Parse(ipString); - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && ipAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - // [ActiveIssue("https://github.com/dotnet/runtime/issues/67301")] - throw new SkipTestException("IPv6 on Linux is temporarily broken"); - } - (X509Certificate2 certificate, _) = System.Net.Security.Tests.TestHelper.GenerateCertificates(expectsError ? "badhost" : "localhost"); var listenerOptions = new QuicListenerOptions(); @@ -403,7 +395,7 @@ public async Task WaitForAvailableUnidirectionStreamsAsyncWorks() QuicStream stream = clientConnection.OpenUnidirectionalStream(); ValueTask waitTask = clientConnection.WaitForAvailableUnidirectionalStreamsAsync(); Assert.False(waitTask.IsCompleted); - Assert.Throws(() => clientConnection.OpenUnidirectionalStream()); + Assert.ThrowsAny(() => clientConnection.OpenUnidirectionalStream()); // Close the streams, the waitTask should finish as a result. stream.Dispose(); QuicStream newStream = await serverConnection.AcceptStreamAsync(); @@ -429,7 +421,7 @@ public async Task WaitForAvailableBidirectionStreamsAsyncWorks() QuicStream stream = clientConnection.OpenBidirectionalStream(); ValueTask waitTask = clientConnection.WaitForAvailableBidirectionalStreamsAsync(); Assert.False(waitTask.IsCompleted); - Assert.Throws(() => clientConnection.OpenBidirectionalStream()); + Assert.ThrowsAny(() => clientConnection.OpenBidirectionalStream()); // Close the streams, the waitTask should finish as a result. stream.Dispose(); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index d4d1a89f11fa48..de5a5b81c999a9 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs @@ -86,7 +86,7 @@ await RunClientServer( else { await Assert.ThrowsAsync(async () => await serverConnection.AcceptStreamAsync()); - await Assert.ThrowsAsync(() => OpenAndUseStreamAsync(serverConnection)); + await Assert.ThrowsAnyAsync(() => OpenAndUseStreamAsync(serverConnection)); } }); } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index bacc79bc968351..e7586a31d9feb8 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -28,7 +28,6 @@ await Task.Run(async () => } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)] public async Task Listener_Backlog_Success_IPv6() { await Task.Run(async () => diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index 7c78b34244a4b3..54aea8510c39a5 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -838,7 +838,7 @@ await RunBidirectionalClientServer( }, async serverStream => { - // It may happen, that the WriteAsync call finishes early (before the AbortWrite + // It may happen, that the WriteAsync call finishes early (before the AbortWrite // below), and we hit a check on the next iteration of the WriteForever. // But in most cases it will still exercise aborting the outstanding write task.