From: Marie Píchová <11718369+ManickaP@users.noreply.github.com> Date: Wed, 11 May 2022 14:29:45 +0000 (+0200) Subject: "[QUIC] Adopted msquic generated interop (#68288)" attempt no 2 (#69009) X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~9234 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=122c9d025daf5a50f5571a14ba2ff3ca67aa8622;p=platform%2Fupstream%2Fdotnet%2Fruntime.git "[QUIC] Adopted msquic generated interop (#68288)" attempt no 2 (#69009) * Revert "Revert "[QUIC] Adopted msquic generated interop (#68288)" (#68940)" This reverts commit 4820674a4471872d742c380f38e766b80dc79385. * Exclude S.N.Quic from Mono AOT * Fix #68954 --- diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index 2a94ef5..fc250aa 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -1065,3 +1065,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +License notice for MsQuic +-------------------------------------- + +Copyright (c) Microsoft Corporation. +Licensed under the MIT License. + +Available at +https://github.com/microsoft/msquic/blob/main/LICENSE \ No newline at end of file diff --git a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs index 347bb98..15c4115 100644 --- a/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs +++ b/src/libraries/Common/tests/System/Net/Http/Http3LoopbackConnection.cs @@ -129,6 +129,8 @@ namespace System.Net.Test.Common throw new Exception("Received second control stream from client???"); } + Assert.False(controlStream.CanWrite); + long? streamType = await controlStream.ReadIntegerAsync(); Assert.Equal(Http3LoopbackStream.ControlStream, streamType); @@ -143,19 +145,37 @@ namespace System.Net.Test.Common // This will automatically handle the control stream, including validating its contents public async Task AcceptRequestStreamAsync() { - Http3LoopbackStream stream; + Http3LoopbackStream requestStream = null; while (true) { - stream = await AcceptStreamAsync().ConfigureAwait(false); + var stream = await AcceptStreamAsync().ConfigureAwait(false); + // Accepted request stream. if (stream.CanWrite) { - return stream; + // Only one expected. + Assert.True(requestStream is null, "Expected single request stream, got a second"); + + // Control stream is set --> return the request stream. + if (_inboundControlStream is not null) + { + return stream; + } + + // Control stream not set --> need to accept another stream. + requestStream = stream; + continue; } - // Must be the control stream + // Must be the control stream. await HandleControlStreamAsync(stream); + + // We've already accepted request stream --> return it. + if (requestStream is not null) + { + return requestStream; + } } } 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 0ecfed9..5a80b1d 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -29,21 +29,9 @@ - - - - - - - - - - - - - Common\DisableRuntimeMarshalling.cs - + + @@ -51,7 +39,6 @@ - @@ -74,7 +61,6 @@ - @@ -107,26 +93,21 @@ - - + - - - - 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.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!; internal static bool IsQuicSupported { get; } - private const int MsQuicVersion = 2; - internal static bool Tls13MayBeDisabled { get; } static MsQuicApi() @@ -129,21 +76,36 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal } IntPtr msQuicHandle; - if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || + if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) { try { if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) { - 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; + if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable))) { - IsQuicSupported = true; - Api = new MsQuicApi(vtable); + int arraySize = 4; + uint* libVersion = stackalloc uint[arraySize]; + uint size = (uint)arraySize * sizeof(uint); + if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) + { + var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); + if (version >= MsQuicVersion) + { + Api = new MsQuicApi(apiTable); + IsQuicSupported = true; + } + else + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); + } + } + } } } } @@ -182,38 +144,5 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal #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/MsQuicBuffers.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicBuffers.cs new file mode 100644 index 0000000..e98e977 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicBuffers.cs @@ -0,0 +1,94 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Microsoft.Quic; + +namespace System.Net.Quic.Implementations.MsQuic.Internal; + +/// +/// Helper class to convert managed data into QUIC_BUFFER* consumable by MsQuic. +/// It also allows reuse with repeated Reset/Initialize calls, e.g. new, Initialize, (use), Reset, Initialize, (use), Reset, Initialize, (use), Dispose. +/// Note that since this is struct and there's no finalizer, Dispose must be always called to release the unmanaged memory allocated by this struct. +/// +internal unsafe struct MsQuicBuffers : IDisposable +{ + // Handles to pinned memory blocks from the user. + private MemoryHandle[] _handles; + // Native memory block which holds the pinned memory pointers from _handles and can be passed to MsQuic as QUIC_BUFFER*. + private QUIC_BUFFER* _buffers; + // Number of QUIC_BUFFER instance currently allocated in _buffers, so that we can reuse the memory instead of reallocating. + private int _count; + + public MsQuicBuffers() + { + _handles = Array.Empty(); + _buffers = null; + _count = 0; + } + + public QUIC_BUFFER* Buffers => _buffers; + public int Count => _count; + + private void FreeNativeMemory() + { + QUIC_BUFFER* buffers = _buffers; + _buffers = null; + NativeMemory.Free(buffers); + } + + /// + /// The method initializes QUIC_BUFFER* with data from inputs, converted via toBuffer. + /// Note that the struct either needs to be freshly created via new or previously cleaned up with Reset. + /// + /// Inputs to get their byte array, pin them and pepare them to be passed to MsQuic as QUIC_BUFFER*. + /// Method extracting byte array from the inputs, e.g. applicationProtocol.Protocol. + /// The type of the inputs. + public void Initialize(IList inputs, Func> toBuffer) + { + if (_handles.Length < inputs.Count) + { + _handles = new MemoryHandle[inputs.Count]; + } + if (_count < inputs.Count) + { + FreeNativeMemory(); + _buffers = (QUIC_BUFFER*)NativeMemory.Alloc((nuint)sizeof(QUIC_BUFFER), (nuint)inputs.Count); + } + + _count = inputs.Count; + + for (int i = 0; i < inputs.Count; ++i) + { + ReadOnlyMemory buffer = toBuffer(inputs[i]); + MemoryHandle handle = buffer.Pin(); + + _handles[i] = handle; + _buffers[i].Buffer = (byte*)handle.Pointer; + _buffers[i].Length = (uint)buffer.Length; + } + } + + /// + /// Unpins the managed memory and allows reuse of this struct. + /// + public void Reset() + { + for (int i = 0; i < _count; ++i) + { + _handles[i].Dispose(); + } + } + + /// + /// Apart from unpinning the managed memory, it returns the shared buffer, + /// but most importantly it releases the unmanaged memory. + /// + public void Dispose() + { + Reset(); + FreeNativeMemory(); + } +} 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 7fef8a8..784d895 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 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal 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 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal 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 680069b..0000000 --- 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/MsQuicAlpnHelper.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicAlpnHelper.cs deleted file mode 100644 index 916cfc4..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicAlpnHelper.cs +++ /dev/null @@ -1,58 +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.Buffers; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Net.Security; -using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; - -namespace System.Net.Quic.Implementations.MsQuic.Internal -{ - internal static class MsQuicAlpnHelper - { - public static unsafe void Prepare(List alpnProtocols, [NotNull] out MemoryHandle[]? handles, [NotNull] out QuicBuffer[]? buffers) - { - handles = ArrayPool.Shared.Rent(alpnProtocols.Count); - buffers = ArrayPool.Shared.Rent(alpnProtocols.Count); - - try - { - for (int i = 0; i < alpnProtocols.Count; ++i) - { - ReadOnlyMemory alpnProtocol = alpnProtocols[i].Protocol; - MemoryHandle h = alpnProtocol.Pin(); - - handles[i] = h; - buffers[i].Buffer = (byte*)h.Pointer; - buffers[i].Length = (uint)alpnProtocol.Length; - } - } - catch - { - Return(ref handles, ref buffers); - throw; - } - } - - public static void Return(ref MemoryHandle[]? handles, ref QuicBuffer[]? buffers) - { - if (handles is MemoryHandle[] notNullHandles) - { - foreach (MemoryHandle h in notNullHandles) - { - h.Dispose(); - } - - handles = null; - ArrayPool.Shared.Return(notNullHandles); - } - - if (buffers is QuicBuffer[] notNullBuffers) - { - buffers = null; - ArrayPool.Shared.Return(notNullBuffers); - } - } - } -} 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 8745dd5..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicEnums.cs +++ /dev/null @@ -1,229 +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, - PEER_ACCEPTED = 9 - } - -#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 0000000..2dd3f11 --- /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 sealed 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 165a4b2..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs +++ /dev/null @@ -1,1438 +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; -using System.Runtime.InteropServices.Marshalling; - -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 0000000..9b2095b --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicSafeHandle.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.Runtime.InteropServices; +using Microsoft.Quic; + +namespace System.Net.Quic.Implementations.MsQuic.Internal +{ + internal abstract class MsQuicSafeHandle : SafeHandle + { + // The index must corespond to SafeHandleType enum value and the value must correspond to MsQuic logging abbreviation string. + // This is used for our logging that uses the same format of object identification as MsQuic to easily correlate log events. + private static readonly string[] TypeName = new string[] + { + " reg", + "cnfg", + "list", + "conn", + "strm" + }; + + 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, SafeHandleType safeHandleType) + : base((IntPtr)handle, ownsHandle: true) + { + _releaseAction = releaseAction; + _traceId = $"[{TypeName[(int)safeHandleType]}][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; + } + + internal enum SafeHandleType + { + Registration, + Configuration, + Listener, + Connection, + Stream + } +} 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 d99df79..0000000 --- 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 03fc254..0000000 --- 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 003aaa8..0000000 --- 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 50bc061..0000000 --- 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 4f2bedb..0000000 --- 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 cd7b4ba..0000000 --- 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 adcce1b..a04f131 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 @@ -8,25 +8,17 @@ using System.Net.Security; 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 { - 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), SafeHandleType.Configuration) { } - 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) { @@ -130,50 +122,42 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal 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; - try - { - 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); - } - finally - { - MsQuicAlpnHelper.Return(ref handles, ref buffers); - } - - QuicExceptionHelpers.ThrowIfFailed(status, "ConfigurationOpen failed."); + QUIC_HANDLE* handle; + using var msquicBuffers = new MsQuicBuffers(); + msquicBuffers.Initialize(alpnProtocols, alpnProtocol => alpnProtocol.Protocol); + ThrowIfFailure(MsQuicApi.Api.ApiTable->ConfigurationOpen( + MsQuicApi.Api.Registration.QuicHandle, + msquicBuffers.Buffers, + (uint)alpnProtocols.Count, + &settings, + (uint)sizeof(QUIC_SETTINGS), + (void*)IntPtr.Zero, + &handle), "ConfigurationOpen failed"); + configurationHandle = new SafeMsQuicConfigurationHandle(handle); try { - CredentialConfig config = default; + QUIC_CREDENTIAL_CONFIG config = default; config.Flags = flags; // TODO: consider using LOAD_ASYNCHRONOUS with a callback. if (cipherSuitesPolicy != null) @@ -188,17 +172,17 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal intermediates = certificateContext.IntermediateCertificates; } + 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.CERTIFICATE_CONTEXT; + config.CertificateContext = (void*)certificate.Handle; + status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); } else { - CredentialConfigCertificatePkcs12 pkcs12Config; byte[] asn1; if (intermediates?.Length > 0) @@ -217,32 +201,35 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal 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.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); + 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 { 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 9354ce0..4d308bd 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), SafeHandleType.Connection) { } - - 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 f0f7555..1188efd 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), SafeHandleType.Listener) { } - - 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 798636b..629946e 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), SafeHandleType.Registration) { } - - 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 179bdd3..4cbf56d 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), SafeHandleType.Stream) { } - - 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 0000000..96b83d6 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic.cs @@ -0,0 +1,192 @@ +#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 (OperatingSystem.IsWindows()) + { + return status >= 0; + } + else + { + return status <= 0; + } + } + + public static bool StatusFailed(int status) + { + if (OperatingSystem.IsWindows()) + { + return status < 0; + } + else + { + return status > 0; + } + } + + public static int QUIC_STATUS_SUCCESS => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_SUCCESS : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_SUCCESS : MsQuic_MacOS.QUIC_STATUS_SUCCESS; + public static int QUIC_STATUS_PENDING => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_PENDING : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_PENDING : MsQuic_Linux.QUIC_STATUS_PENDING; + public static int QUIC_STATUS_CONTINUE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CONTINUE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CONTINUE : MsQuic_Linux.QUIC_STATUS_CONTINUE; + public static int QUIC_STATUS_OUT_OF_MEMORY => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_OUT_OF_MEMORY : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_OUT_OF_MEMORY : MsQuic_Linux.QUIC_STATUS_OUT_OF_MEMORY; + public static int QUIC_STATUS_INVALID_PARAMETER => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_INVALID_PARAMETER : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_INVALID_PARAMETER : MsQuic_Linux.QUIC_STATUS_INVALID_PARAMETER; + public static int QUIC_STATUS_INVALID_STATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_INVALID_STATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_INVALID_STATE : MsQuic_Linux.QUIC_STATUS_INVALID_STATE; + public static int QUIC_STATUS_NOT_SUPPORTED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_NOT_SUPPORTED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_NOT_SUPPORTED : MsQuic_Linux.QUIC_STATUS_NOT_SUPPORTED; + public static int QUIC_STATUS_NOT_FOUND => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_NOT_FOUND : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_NOT_FOUND : MsQuic_Linux.QUIC_STATUS_NOT_FOUND; + public static int QUIC_STATUS_BUFFER_TOO_SMALL => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_BUFFER_TOO_SMALL : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_BUFFER_TOO_SMALL : MsQuic_Linux.QUIC_STATUS_BUFFER_TOO_SMALL; + public static int QUIC_STATUS_HANDSHAKE_FAILURE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_HANDSHAKE_FAILURE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_HANDSHAKE_FAILURE : MsQuic_Linux.QUIC_STATUS_HANDSHAKE_FAILURE; + public static int QUIC_STATUS_ABORTED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_ABORTED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_ABORTED : MsQuic_Linux.QUIC_STATUS_ABORTED; + public static int QUIC_STATUS_ADDRESS_IN_USE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_ADDRESS_IN_USE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_ADDRESS_IN_USE : MsQuic_Linux.QUIC_STATUS_ADDRESS_IN_USE; + public static int QUIC_STATUS_CONNECTION_TIMEOUT => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CONNECTION_TIMEOUT : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CONNECTION_TIMEOUT : MsQuic_Linux.QUIC_STATUS_CONNECTION_TIMEOUT; + public static int QUIC_STATUS_CONNECTION_IDLE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CONNECTION_IDLE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CONNECTION_IDLE : MsQuic_Linux.QUIC_STATUS_CONNECTION_IDLE; + public static int QUIC_STATUS_UNREACHABLE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_UNREACHABLE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_UNREACHABLE : MsQuic_Linux.QUIC_STATUS_UNREACHABLE; + public static int QUIC_STATUS_INTERNAL_ERROR => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_INTERNAL_ERROR : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_INTERNAL_ERROR : MsQuic_Linux.QUIC_STATUS_INTERNAL_ERROR; + public static int QUIC_STATUS_CONNECTION_REFUSED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CONNECTION_REFUSED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CONNECTION_REFUSED : MsQuic_Linux.QUIC_STATUS_CONNECTION_REFUSED; + public static int QUIC_STATUS_PROTOCOL_ERROR => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_PROTOCOL_ERROR : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_PROTOCOL_ERROR : MsQuic_Linux.QUIC_STATUS_PROTOCOL_ERROR; + public static int QUIC_STATUS_VER_NEG_ERROR => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_VER_NEG_ERROR : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_VER_NEG_ERROR : MsQuic_Linux.QUIC_STATUS_VER_NEG_ERROR; + public static int QUIC_STATUS_TLS_ERROR => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_TLS_ERROR : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_TLS_ERROR : MsQuic_Linux.QUIC_STATUS_TLS_ERROR; + public static int QUIC_STATUS_USER_CANCELED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_USER_CANCELED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_USER_CANCELED : MsQuic_Linux.QUIC_STATUS_USER_CANCELED; + public static int QUIC_STATUS_ALPN_NEG_FAILURE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_ALPN_NEG_FAILURE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_ALPN_NEG_FAILURE : MsQuic_Linux.QUIC_STATUS_ALPN_NEG_FAILURE; + public static int QUIC_STATUS_STREAM_LIMIT_REACHED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_STREAM_LIMIT_REACHED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_STREAM_LIMIT_REACHED : MsQuic_Linux.QUIC_STATUS_STREAM_LIMIT_REACHED; + public static int QUIC_STATUS_CLOSE_NOTIFY => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CLOSE_NOTIFY : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CLOSE_NOTIFY : MsQuic_Linux.QUIC_STATUS_CLOSE_NOTIFY; + public static int QUIC_STATUS_BAD_CERTIFICATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_BAD_CERTIFICATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_BAD_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_BAD_CERTIFICATE; + public static int QUIC_STATUS_UNSUPPORTED_CERTIFICATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_UNSUPPORTED_CERTIFICATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_UNSUPPORTED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_UNSUPPORTED_CERTIFICATE; + public static int QUIC_STATUS_REVOKED_CERTIFICATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_REVOKED_CERTIFICATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_REVOKED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_REVOKED_CERTIFICATE; + public static int QUIC_STATUS_EXPIRED_CERTIFICATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_EXPIRED_CERTIFICATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_EXPIRED_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_EXPIRED_CERTIFICATE; + public static int QUIC_STATUS_UNKNOWN_CERTIFICATE => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_UNKNOWN_CERTIFICATE : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_UNKNOWN_CERTIFICATE : MsQuic_Linux.QUIC_STATUS_UNKNOWN_CERTIFICATE; + public static int QUIC_STATUS_CERT_EXPIRED => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CERT_EXPIRED : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CERT_EXPIRED : MsQuic_Linux.QUIC_STATUS_CERT_EXPIRED; + public static int QUIC_STATUS_CERT_UNTRUSTED_ROOT => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_STATUS_CERT_UNTRUSTED_ROOT : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_STATUS_CERT_UNTRUSTED_ROOT : MsQuic_Linux.QUIC_STATUS_CERT_UNTRUSTED_ROOT; + + public static int QUIC_ADDRESS_FAMILY_UNSPEC => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_UNSPEC : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_ADDRESS_FAMILY_UNSPEC : MsQuic_Linux.QUIC_ADDRESS_FAMILY_UNSPEC; + public static int QUIC_ADDRESS_FAMILY_INET => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_INET : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.QUIC_ADDRESS_FAMILY_INET : MsQuic_Linux.QUIC_ADDRESS_FAMILY_INET; + public static int QUIC_ADDRESS_FAMILY_INET6 => OperatingSystem.IsWindows() ? MsQuic_Windows.QUIC_ADDRESS_FAMILY_INET6 : (OperatingSystem.IsLinux() || OperatingSystem.IsAndroid()) ? MsQuic_Linux.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]; + } + + [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 static bool SockaddrHasLength => OperatingSystem.IsFreeBSD() || OperatingSystem.IsIOS() || OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst() || OperatingSystem.IsTvOS() || OperatingSystem.IsWatchOS(); + + public int Family + { + get + { + if (SockaddrHasLength) + { + return FamilyLen.sin_family_bsd; + } + else + { + return FamilyLen.sin_family; + } + } + set + { + if (SockaddrHasLength) + { + 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 0000000..f26a48f --- /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 + +#pragma warning disable CS0649 + +using System.Runtime.InteropServices; + +namespace Microsoft.Quic +{ + internal partial struct QUIC_HANDLE + { + } + + internal enum QUIC_EXECUTION_PROFILE + { + LOW_LATENCY, + MAX_THROUGHPUT, + SCAVENGER, + REAL_TIME, + } + + internal enum QUIC_LOAD_BALANCING_MODE + { + DISABLED, + SERVER_ID_IP, + } + + internal enum QUIC_CREDENTIAL_TYPE + { + NONE, + CERTIFICATE_HASH, + CERTIFICATE_HASH_STORE, + CERTIFICATE_CONTEXT, + CERTIFICATE_FILE, + CERTIFICATE_FILE_PROTECTED, + CERTIFICATE_PKCS12, + } + + [System.Flags] + internal enum QUIC_CREDENTIAL_FLAGS + { + NONE = 0x00000000, + CLIENT = 0x00000001, + LOAD_ASYNCHRONOUS = 0x00000002, + NO_CERTIFICATE_VALIDATION = 0x00000004, + ENABLE_OCSP = 0x00000008, + INDICATE_CERTIFICATE_RECEIVED = 0x00000010, + DEFER_CERTIFICATE_VALIDATION = 0x00000020, + REQUIRE_CLIENT_AUTHENTICATION = 0x00000040, + USE_TLS_BUILTIN_CERTIFICATE_VALIDATION = 0x00000080, + REVOCATION_CHECK_END_CERT = 0x00000100, + REVOCATION_CHECK_CHAIN = 0x00000200, + REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT = 0x00000400, + IGNORE_NO_REVOCATION_CHECK = 0x00000800, + IGNORE_REVOCATION_OFFLINE = 0x00001000, + SET_ALLOWED_CIPHER_SUITES = 0x00002000, + USE_PORTABLE_CERTIFICATES = 0x00004000, + USE_SUPPLIED_CREDENTIALS = 0x00008000, + } + + [System.Flags] + internal enum QUIC_ALLOWED_CIPHER_SUITE_FLAGS + { + NONE = 0x0, + AES_128_GCM_SHA256 = 0x1, + AES_256_GCM_SHA384 = 0x2, + CHACHA20_POLY1305_SHA256 = 0x4, + } + + [System.Flags] + internal enum QUIC_CERTIFICATE_HASH_STORE_FLAGS + { + NONE = 0x0000, + MACHINE_STORE = 0x0001, + } + + [System.Flags] + internal enum QUIC_CONNECTION_SHUTDOWN_FLAGS + { + NONE = 0x0000, + SILENT = 0x0001, + } + + internal enum QUIC_SERVER_RESUMPTION_LEVEL + { + NO_RESUME, + RESUME_ONLY, + RESUME_AND_ZERORTT, + } + + [System.Flags] + internal enum QUIC_SEND_RESUMPTION_FLAGS + { + NONE = 0x0000, + FINAL = 0x0001, + } + + internal enum QUIC_STREAM_SCHEDULING_SCHEME + { + FIFO = 0x0000, + ROUND_ROBIN = 0x0001, + COUNT, + } + + [System.Flags] + internal enum QUIC_STREAM_OPEN_FLAGS + { + NONE = 0x0000, + UNIDIRECTIONAL = 0x0001, + ZERO_RTT = 0x0002, + } + + [System.Flags] + internal enum QUIC_STREAM_START_FLAGS + { + NONE = 0x0000, + IMMEDIATE = 0x0001, + FAIL_BLOCKED = 0x0002, + SHUTDOWN_ON_FAIL = 0x0004, + INDICATE_PEER_ACCEPT = 0x0008, + } + + [System.Flags] + internal enum QUIC_STREAM_SHUTDOWN_FLAGS + { + NONE = 0x0000, + GRACEFUL = 0x0001, + ABORT_SEND = 0x0002, + ABORT_RECEIVE = 0x0004, + ABORT = 0x0006, + IMMEDIATE = 0x0008, + INLINE = 0x0010, + } + + [System.Flags] + internal enum QUIC_RECEIVE_FLAGS + { + NONE = 0x0000, + ZERO_RTT = 0x0001, + FIN = 0x0002, + } + + [System.Flags] + internal enum QUIC_SEND_FLAGS + { + NONE = 0x0000, + ALLOW_0_RTT = 0x0001, + START = 0x0002, + FIN = 0x0004, + DGRAM_PRIORITY = 0x0008, + DELAY_SEND = 0x0010, + } + + internal enum QUIC_DATAGRAM_SEND_STATE + { + UNKNOWN, + SENT, + LOST_SUSPECT, + LOST_DISCARDED, + ACKNOWLEDGED, + ACKNOWLEDGED_SPURIOUS, + CANCELED, + } + + internal unsafe partial struct QUIC_REGISTRATION_CONFIG + { + [NativeTypeName("const char *")] + internal sbyte* AppName; + + internal QUIC_EXECUTION_PROFILE ExecutionProfile; + } + + internal unsafe partial struct QUIC_CERTIFICATE_HASH + { + [NativeTypeName("uint8_t [20]")] + internal fixed byte ShaHash[20]; + } + + internal unsafe partial struct QUIC_CERTIFICATE_HASH_STORE + { + internal QUIC_CERTIFICATE_HASH_STORE_FLAGS Flags; + + [NativeTypeName("uint8_t [20]")] + internal fixed byte ShaHash[20]; + + [NativeTypeName("char [128]")] + internal fixed sbyte StoreName[128]; + } + + internal unsafe partial struct QUIC_CERTIFICATE_FILE + { + [NativeTypeName("const char *")] + internal sbyte* PrivateKeyFile; + + [NativeTypeName("const char *")] + internal sbyte* CertificateFile; + } + + internal unsafe partial struct QUIC_CERTIFICATE_FILE_PROTECTED + { + [NativeTypeName("const char *")] + internal sbyte* PrivateKeyFile; + + [NativeTypeName("const char *")] + internal sbyte* CertificateFile; + + [NativeTypeName("const char *")] + internal sbyte* PrivateKeyPassword; + } + + internal unsafe partial struct QUIC_CERTIFICATE_PKCS12 + { + [NativeTypeName("const uint8_t *")] + internal byte* Asn1Blob; + + [NativeTypeName("uint32_t")] + internal uint Asn1BlobLength; + + [NativeTypeName("const char *")] + internal sbyte* PrivateKeyPassword; + } + + internal unsafe partial struct QUIC_CREDENTIAL_CONFIG + { + internal QUIC_CREDENTIAL_TYPE Type; + + internal QUIC_CREDENTIAL_FLAGS Flags; + + [NativeTypeName("QUIC_CREDENTIAL_CONFIG::(anonymous union)")] + internal _Anonymous_e__Union Anonymous; + + [NativeTypeName("const char *")] + internal sbyte* Principal; + + internal void* Reserved; + + [NativeTypeName("QUIC_CREDENTIAL_LOAD_COMPLETE_HANDLER")] + internal delegate* unmanaged[Cdecl] AsyncHandler; + + internal QUIC_ALLOWED_CIPHER_SUITE_FLAGS AllowedCipherSuites; + + internal ref QUIC_CERTIFICATE_HASH* CertificateHash + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateHash; + } + } + + internal ref QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateHashStore; + } + } + + internal ref void* CertificateContext + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateContext; + } + } + + internal ref QUIC_CERTIFICATE_FILE* CertificateFile + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateFile; + } + } + + internal ref QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref this, 1)).Anonymous.CertificateFileProtected; + } + } + + internal 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)] + internal QUIC_CERTIFICATE_HASH* CertificateHash; + + [FieldOffset(0)] + internal QUIC_CERTIFICATE_HASH_STORE* CertificateHashStore; + + [FieldOffset(0)] + [NativeTypeName("QUIC_CERTIFICATE *")] + internal void* CertificateContext; + + [FieldOffset(0)] + internal QUIC_CERTIFICATE_FILE* CertificateFile; + + [FieldOffset(0)] + internal QUIC_CERTIFICATE_FILE_PROTECTED* CertificateFileProtected; + + [FieldOffset(0)] + internal QUIC_CERTIFICATE_PKCS12* CertificatePkcs12; + } + } + + internal unsafe partial struct QUIC_TICKET_KEY_CONFIG + { + [NativeTypeName("uint8_t [16]")] + internal fixed byte Id[16]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte Material[64]; + + [NativeTypeName("uint8_t")] + internal byte MaterialLength; + } + + internal unsafe partial struct QUIC_BUFFER + { + [NativeTypeName("uint32_t")] + internal uint Length; + + [NativeTypeName("uint8_t *")] + internal byte* Buffer; + } + + internal unsafe partial struct QUIC_NEW_CONNECTION_INFO + { + [NativeTypeName("uint32_t")] + internal uint QuicVersion; + + [NativeTypeName("const QUIC_ADDR *")] + internal QuicAddr* LocalAddress; + + [NativeTypeName("const QUIC_ADDR *")] + internal QuicAddr* RemoteAddress; + + [NativeTypeName("uint32_t")] + internal uint CryptoBufferLength; + + [NativeTypeName("uint16_t")] + internal ushort ClientAlpnListLength; + + [NativeTypeName("uint16_t")] + internal ushort ServerNameLength; + + [NativeTypeName("uint8_t")] + internal byte NegotiatedAlpnLength; + + [NativeTypeName("const uint8_t *")] + internal byte* CryptoBuffer; + + [NativeTypeName("const uint8_t *")] + internal byte* ClientAlpnList; + + [NativeTypeName("const uint8_t *")] + internal byte* NegotiatedAlpn; + + [NativeTypeName("const char *")] + internal sbyte* ServerName; + } + + internal enum QUIC_TLS_PROTOCOL_VERSION + { + UNKNOWN = 0, + TLS_1_3 = 0x3000, + } + + internal enum QUIC_CIPHER_ALGORITHM + { + NONE = 0, + AES_128 = 0x660E, + AES_256 = 0x6610, + CHACHA20 = 0x6612, + } + + internal enum QUIC_HASH_ALGORITHM + { + NONE = 0, + SHA_256 = 0x800C, + SHA_384 = 0x800D, + } + + internal enum QUIC_KEY_EXCHANGE_ALGORITHM + { + NONE = 0, + } + + internal enum QUIC_CIPHER_SUITE + { + TLS_AES_128_GCM_SHA256 = 0x1301, + TLS_AES_256_GCM_SHA384 = 0x1302, + TLS_CHACHA20_POLY1305_SHA256 = 0x1303, + } + + internal enum QUIC_CONGESTION_CONTROL_ALGORITHM + { + CUBIC, + MAX, + } + + internal partial struct QUIC_HANDSHAKE_INFO + { + internal QUIC_TLS_PROTOCOL_VERSION TlsProtocolVersion; + + internal QUIC_CIPHER_ALGORITHM CipherAlgorithm; + + [NativeTypeName("int32_t")] + internal int CipherStrength; + + internal QUIC_HASH_ALGORITHM Hash; + + [NativeTypeName("int32_t")] + internal int HashStrength; + + internal QUIC_KEY_EXCHANGE_ALGORITHM KeyExchangeAlgorithm; + + [NativeTypeName("int32_t")] + internal int KeyExchangeStrength; + + internal QUIC_CIPHER_SUITE CipherSuite; + } + + internal partial struct QUIC_STATISTICS + { + [NativeTypeName("uint64_t")] + internal ulong CorrelationId; + + internal uint _bitfield; + + [NativeTypeName("uint32_t : 1")] + internal uint VersionNegotiation + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint StatelessRetry + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint ResumptionAttempted + { + get + { + return (_bitfield >> 2) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint ResumptionSucceeded + { + get + { + return (_bitfield >> 3) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3); + } + } + + [NativeTypeName("uint32_t")] + internal uint Rtt; + + [NativeTypeName("uint32_t")] + internal uint MinRtt; + + [NativeTypeName("uint32_t")] + internal uint MaxRtt; + + [NativeTypeName("struct (anonymous struct)")] + internal _Timing_e__Struct Timing; + + [NativeTypeName("struct (anonymous struct)")] + internal _Handshake_e__Struct Handshake; + + [NativeTypeName("struct (anonymous struct)")] + internal _Send_e__Struct Send; + + [NativeTypeName("struct (anonymous struct)")] + internal _Recv_e__Struct Recv; + + [NativeTypeName("struct (anonymous struct)")] + internal _Misc_e__Struct Misc; + + internal partial struct _Timing_e__Struct + { + [NativeTypeName("uint64_t")] + internal ulong Start; + + [NativeTypeName("uint64_t")] + internal ulong InitialFlightEnd; + + [NativeTypeName("uint64_t")] + internal ulong HandshakeFlightEnd; + } + + internal partial struct _Handshake_e__Struct + { + [NativeTypeName("uint32_t")] + internal uint ClientFlight1Bytes; + + [NativeTypeName("uint32_t")] + internal uint ServerFlight1Bytes; + + [NativeTypeName("uint32_t")] + internal uint ClientFlight2Bytes; + } + + internal partial struct _Send_e__Struct + { + [NativeTypeName("uint16_t")] + internal ushort PathMtu; + + [NativeTypeName("uint64_t")] + internal ulong TotalPackets; + + [NativeTypeName("uint64_t")] + internal ulong RetransmittablePackets; + + [NativeTypeName("uint64_t")] + internal ulong SuspectedLostPackets; + + [NativeTypeName("uint64_t")] + internal ulong SpuriousLostPackets; + + [NativeTypeName("uint64_t")] + internal ulong TotalBytes; + + [NativeTypeName("uint64_t")] + internal ulong TotalStreamBytes; + + [NativeTypeName("uint32_t")] + internal uint CongestionCount; + + [NativeTypeName("uint32_t")] + internal uint PersistentCongestionCount; + } + + internal partial struct _Recv_e__Struct + { + [NativeTypeName("uint64_t")] + internal ulong TotalPackets; + + [NativeTypeName("uint64_t")] + internal ulong ReorderedPackets; + + [NativeTypeName("uint64_t")] + internal ulong DroppedPackets; + + [NativeTypeName("uint64_t")] + internal ulong DuplicatePackets; + + [NativeTypeName("uint64_t")] + internal ulong TotalBytes; + + [NativeTypeName("uint64_t")] + internal ulong TotalStreamBytes; + + [NativeTypeName("uint64_t")] + internal ulong DecryptionFailures; + + [NativeTypeName("uint64_t")] + internal ulong ValidAckFrames; + } + + internal partial struct _Misc_e__Struct + { + [NativeTypeName("uint32_t")] + internal uint KeyUpdateCount; + } + } + + internal partial struct QUIC_STATISTICS_V2 + { + [NativeTypeName("uint64_t")] + internal ulong CorrelationId; + + internal uint _bitfield; + + [NativeTypeName("uint32_t : 1")] + internal uint VersionNegotiation + { + get + { + return _bitfield & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~0x1u) | (value & 0x1u); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint StatelessRetry + { + get + { + return (_bitfield >> 1) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint ResumptionAttempted + { + get + { + return (_bitfield >> 2) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2); + } + } + + [NativeTypeName("uint32_t : 1")] + internal uint ResumptionSucceeded + { + get + { + return (_bitfield >> 3) & 0x1u; + } + + set + { + _bitfield = (_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3); + } + } + + [NativeTypeName("uint32_t")] + internal uint Rtt; + + [NativeTypeName("uint32_t")] + internal uint MinRtt; + + [NativeTypeName("uint32_t")] + internal uint MaxRtt; + + [NativeTypeName("uint64_t")] + internal ulong TimingStart; + + [NativeTypeName("uint64_t")] + internal ulong TimingInitialFlightEnd; + + [NativeTypeName("uint64_t")] + internal ulong TimingHandshakeFlightEnd; + + [NativeTypeName("uint32_t")] + internal uint HandshakeClientFlight1Bytes; + + [NativeTypeName("uint32_t")] + internal uint HandshakeServerFlight1Bytes; + + [NativeTypeName("uint32_t")] + internal uint HandshakeClientFlight2Bytes; + + [NativeTypeName("uint16_t")] + internal ushort SendPathMtu; + + [NativeTypeName("uint64_t")] + internal ulong SendTotalPackets; + + [NativeTypeName("uint64_t")] + internal ulong SendRetransmittablePackets; + + [NativeTypeName("uint64_t")] + internal ulong SendSuspectedLostPackets; + + [NativeTypeName("uint64_t")] + internal ulong SendSpuriousLostPackets; + + [NativeTypeName("uint64_t")] + internal ulong SendTotalBytes; + + [NativeTypeName("uint64_t")] + internal ulong SendTotalStreamBytes; + + [NativeTypeName("uint32_t")] + internal uint SendCongestionCount; + + [NativeTypeName("uint32_t")] + internal uint SendPersistentCongestionCount; + + [NativeTypeName("uint64_t")] + internal ulong RecvTotalPackets; + + [NativeTypeName("uint64_t")] + internal ulong RecvReorderedPackets; + + [NativeTypeName("uint64_t")] + internal ulong RecvDroppedPackets; + + [NativeTypeName("uint64_t")] + internal ulong RecvDuplicatePackets; + + [NativeTypeName("uint64_t")] + internal ulong RecvTotalBytes; + + [NativeTypeName("uint64_t")] + internal ulong RecvTotalStreamBytes; + + [NativeTypeName("uint64_t")] + internal ulong RecvDecryptionFailures; + + [NativeTypeName("uint64_t")] + internal ulong RecvValidAckFrames; + + [NativeTypeName("uint32_t")] + internal uint KeyUpdateCount; + + [NativeTypeName("uint32_t")] + internal uint SendCongestionWindow; + } + + internal partial struct QUIC_LISTENER_STATISTICS + { + [NativeTypeName("uint64_t")] + internal ulong TotalAcceptedConnections; + + [NativeTypeName("uint64_t")] + internal ulong TotalRejectedConnections; + + [NativeTypeName("uint64_t")] + internal ulong BindingRecvDroppedPackets; + } + + internal enum QUIC_PERFORMANCE_COUNTERS + { + CONN_CREATED, + CONN_HANDSHAKE_FAIL, + CONN_APP_REJECT, + CONN_RESUMED, + CONN_ACTIVE, + CONN_CONNECTED, + CONN_PROTOCOL_ERRORS, + CONN_NO_ALPN, + STRM_ACTIVE, + PKTS_SUSPECTED_LOST, + PKTS_DROPPED, + PKTS_DECRYPTION_FAIL, + UDP_RECV, + UDP_SEND, + UDP_RECV_BYTES, + UDP_SEND_BYTES, + UDP_RECV_EVENTS, + UDP_SEND_CALLS, + APP_SEND_BYTES, + APP_RECV_BYTES, + CONN_QUEUE_DEPTH, + CONN_OPER_QUEUE_DEPTH, + CONN_OPER_QUEUED, + CONN_OPER_COMPLETED, + WORK_OPER_QUEUE_DEPTH, + WORK_OPER_QUEUED, + WORK_OPER_COMPLETED, + PATH_VALIDATED, + PATH_FAILURE, + SEND_STATELESS_RESET, + SEND_STATELESS_RETRY, + MAX, + } + + internal unsafe partial struct QUIC_VERSION_SETTINGS + { + [NativeTypeName("uint32_t *")] + internal uint* AcceptableVersions; + + [NativeTypeName("uint32_t *")] + internal uint* OfferedVersions; + + [NativeTypeName("uint32_t *")] + internal uint* FullyDeployedVersions; + + [NativeTypeName("uint32_t")] + internal uint AcceptableVersionsLength; + + [NativeTypeName("uint32_t")] + internal uint OfferedVersionsLength; + + [NativeTypeName("uint32_t")] + internal uint FullyDeployedVersionsLength; + } + + internal partial struct QUIC_GLOBAL_SETTINGS + { + [NativeTypeName("QUIC_GLOBAL_SETTINGS::(anonymous union)")] + internal _Anonymous_e__Union Anonymous; + + [NativeTypeName("uint16_t")] + internal ushort RetryMemoryLimit; + + [NativeTypeName("uint16_t")] + internal ushort LoadBalancingMode; + + internal ref ulong IsSetFlags + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSetFlags, 1)); + } + } + + internal 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")] + internal ulong IsSetFlags; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _IsSet_e__Struct IsSet; + + internal partial struct _IsSet_e__Struct + { + internal ulong _bitfield; + + [NativeTypeName("uint64_t : 1")] + internal ulong RetryMemoryLimit + { + get + { + return _bitfield & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~0x1UL) | (value & 0x1UL); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong LoadBalancingMode + { + get + { + return (_bitfield >> 1) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 1)) | ((value & 0x1UL) << 1); + } + } + + [NativeTypeName("uint64_t : 62")] + internal 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)")] + internal _Anonymous_e__Union Anonymous; + + [NativeTypeName("uint64_t")] + internal ulong MaxBytesPerKey; + + [NativeTypeName("uint64_t")] + internal ulong HandshakeIdleTimeoutMs; + + [NativeTypeName("uint64_t")] + internal ulong IdleTimeoutMs; + + [NativeTypeName("uint64_t")] + internal ulong MtuDiscoverySearchCompleteTimeoutUs; + + [NativeTypeName("uint32_t")] + internal uint TlsClientMaxSendBuffer; + + [NativeTypeName("uint32_t")] + internal uint TlsServerMaxSendBuffer; + + [NativeTypeName("uint32_t")] + internal uint StreamRecvWindowDefault; + + [NativeTypeName("uint32_t")] + internal uint StreamRecvBufferDefault; + + [NativeTypeName("uint32_t")] + internal uint ConnFlowControlWindow; + + [NativeTypeName("uint32_t")] + internal uint MaxWorkerQueueDelayUs; + + [NativeTypeName("uint32_t")] + internal uint MaxStatelessOperations; + + [NativeTypeName("uint32_t")] + internal uint InitialWindowPackets; + + [NativeTypeName("uint32_t")] + internal uint SendIdleTimeoutMs; + + [NativeTypeName("uint32_t")] + internal uint InitialRttMs; + + [NativeTypeName("uint32_t")] + internal uint MaxAckDelayMs; + + [NativeTypeName("uint32_t")] + internal uint DisconnectTimeoutMs; + + [NativeTypeName("uint32_t")] + internal uint KeepAliveIntervalMs; + + [NativeTypeName("uint16_t")] + internal ushort CongestionControlAlgorithm; + + [NativeTypeName("uint16_t")] + internal ushort PeerBidiStreamCount; + + [NativeTypeName("uint16_t")] + internal ushort PeerUnidiStreamCount; + + [NativeTypeName("uint16_t")] + internal ushort MaxBindingStatelessOperations; + + [NativeTypeName("uint16_t")] + internal ushort StatelessOperationExpirationMs; + + [NativeTypeName("uint16_t")] + internal ushort MinimumMtu; + + [NativeTypeName("uint16_t")] + internal ushort MaximumMtu; + + internal byte _bitfield; + + [NativeTypeName("uint8_t : 1")] + internal byte SendBufferingEnabled + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte PacingEnabled + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte MigrationEnabled + { + get + { + return (byte)((_bitfield >> 2) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte DatagramReceiveEnabled + { + get + { + return (byte)((_bitfield >> 3) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3)); + } + } + + [NativeTypeName("uint8_t : 2")] + internal byte ServerResumptionLevel + { + get + { + return (byte)((_bitfield >> 4) & 0x3u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x3u << 4)) | ((value & 0x3u) << 4)); + } + } + + [NativeTypeName("uint8_t : 2")] + internal byte RESERVED + { + get + { + return (byte)((_bitfield >> 6) & 0x3u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x3u << 6)) | ((value & 0x3u) << 6)); + } + } + + [NativeTypeName("uint8_t")] + internal byte MaxOperationsPerDrain; + + [NativeTypeName("uint8_t")] + internal byte MtuDiscoveryMissingProbeCount; + + internal ref ulong IsSetFlags + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.IsSetFlags, 1)); + } + } + + internal 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")] + internal ulong IsSetFlags; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _IsSet_e__Struct IsSet; + + internal partial struct _IsSet_e__Struct + { + internal ulong _bitfield; + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxBytesPerKey + { + get + { + return _bitfield & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~0x1UL) | (value & 0x1UL); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong HandshakeIdleTimeoutMs + { + get + { + return (_bitfield >> 1) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 1)) | ((value & 0x1UL) << 1); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong IdleTimeoutMs + { + get + { + return (_bitfield >> 2) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 2)) | ((value & 0x1UL) << 2); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MtuDiscoverySearchCompleteTimeoutUs + { + get + { + return (_bitfield >> 3) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 3)) | ((value & 0x1UL) << 3); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong TlsClientMaxSendBuffer + { + get + { + return (_bitfield >> 4) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 4)) | ((value & 0x1UL) << 4); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong TlsServerMaxSendBuffer + { + get + { + return (_bitfield >> 5) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 5)) | ((value & 0x1UL) << 5); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong StreamRecvWindowDefault + { + get + { + return (_bitfield >> 6) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 6)) | ((value & 0x1UL) << 6); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong StreamRecvBufferDefault + { + get + { + return (_bitfield >> 7) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 7)) | ((value & 0x1UL) << 7); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong ConnFlowControlWindow + { + get + { + return (_bitfield >> 8) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 8)) | ((value & 0x1UL) << 8); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxWorkerQueueDelayUs + { + get + { + return (_bitfield >> 9) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 9)) | ((value & 0x1UL) << 9); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxStatelessOperations + { + get + { + return (_bitfield >> 10) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 10)) | ((value & 0x1UL) << 10); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong InitialWindowPackets + { + get + { + return (_bitfield >> 11) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 11)) | ((value & 0x1UL) << 11); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong SendIdleTimeoutMs + { + get + { + return (_bitfield >> 12) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 12)) | ((value & 0x1UL) << 12); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong InitialRttMs + { + get + { + return (_bitfield >> 13) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 13)) | ((value & 0x1UL) << 13); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxAckDelayMs + { + get + { + return (_bitfield >> 14) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 14)) | ((value & 0x1UL) << 14); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong DisconnectTimeoutMs + { + get + { + return (_bitfield >> 15) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 15)) | ((value & 0x1UL) << 15); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong KeepAliveIntervalMs + { + get + { + return (_bitfield >> 16) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 16)) | ((value & 0x1UL) << 16); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong CongestionControlAlgorithm + { + get + { + return (_bitfield >> 17) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 17)) | ((value & 0x1UL) << 17); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong PeerBidiStreamCount + { + get + { + return (_bitfield >> 18) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 18)) | ((value & 0x1UL) << 18); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong PeerUnidiStreamCount + { + get + { + return (_bitfield >> 19) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 19)) | ((value & 0x1UL) << 19); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxBindingStatelessOperations + { + get + { + return (_bitfield >> 20) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 20)) | ((value & 0x1UL) << 20); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong StatelessOperationExpirationMs + { + get + { + return (_bitfield >> 21) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 21)) | ((value & 0x1UL) << 21); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MinimumMtu + { + get + { + return (_bitfield >> 22) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 22)) | ((value & 0x1UL) << 22); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaximumMtu + { + get + { + return (_bitfield >> 23) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 23)) | ((value & 0x1UL) << 23); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong SendBufferingEnabled + { + get + { + return (_bitfield >> 24) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 24)) | ((value & 0x1UL) << 24); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong PacingEnabled + { + get + { + return (_bitfield >> 25) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 25)) | ((value & 0x1UL) << 25); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MigrationEnabled + { + get + { + return (_bitfield >> 26) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 26)) | ((value & 0x1UL) << 26); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong DatagramReceiveEnabled + { + get + { + return (_bitfield >> 27) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 27)) | ((value & 0x1UL) << 27); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong ServerResumptionLevel + { + get + { + return (_bitfield >> 28) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 28)) | ((value & 0x1UL) << 28); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MaxOperationsPerDrain + { + get + { + return (_bitfield >> 29) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 29)) | ((value & 0x1UL) << 29); + } + } + + [NativeTypeName("uint64_t : 1")] + internal ulong MtuDiscoveryMissingProbeCount + { + get + { + return (_bitfield >> 30) & 0x1UL; + } + + set + { + _bitfield = (_bitfield & ~(0x1UL << 30)) | ((value & 0x1UL) << 30); + } + } + + [NativeTypeName("uint64_t : 33")] + internal 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")] + internal byte SecretLength; + + [NativeTypeName("struct (anonymous struct)")] + internal _IsSet_e__Struct IsSet; + + [NativeTypeName("uint8_t [32]")] + internal fixed byte ClientRandom[32]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte ClientEarlyTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte ClientHandshakeTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte ServerHandshakeTrafficSecret[64]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte ClientTrafficSecret0[64]; + + [NativeTypeName("uint8_t [64]")] + internal fixed byte ServerTrafficSecret0[64]; + + internal partial struct _IsSet_e__Struct + { + internal byte _bitfield; + + [NativeTypeName("uint8_t : 1")] + internal byte ClientRandom + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte ClientEarlyTrafficSecret + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte ClientHandshakeTrafficSecret + { + get + { + return (byte)((_bitfield >> 2) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 2)) | ((value & 0x1u) << 2)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte ServerHandshakeTrafficSecret + { + get + { + return (byte)((_bitfield >> 3) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 3)) | ((value & 0x1u) << 3)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal byte ClientTrafficSecret0 + { + get + { + return (byte)((_bitfield >> 4) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 4)) | ((value & 0x1u) << 4)); + } + } + + [NativeTypeName("uint8_t : 1")] + internal 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")] + internal uint Attribute; + + internal void* Buffer; + } + + internal enum QUIC_LISTENER_EVENT_TYPE + { + NEW_CONNECTION = 0, + STOP_COMPLETE = 1, + } + + internal partial struct QUIC_LISTENER_EVENT + { + internal QUIC_LISTENER_EVENT_TYPE Type; + + [NativeTypeName("QUIC_LISTENER_EVENT::(anonymous union)")] + internal _Anonymous_e__Union Anonymous; + + internal ref _Anonymous_e__Union._NEW_CONNECTION_e__Struct NEW_CONNECTION + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.NEW_CONNECTION, 1)); + } + } + + internal 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)")] + internal _NEW_CONNECTION_e__Struct NEW_CONNECTION; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _STOP_COMPLETE_e__Struct STOP_COMPLETE; + + internal unsafe partial struct _NEW_CONNECTION_e__Struct + { + [NativeTypeName("const QUIC_NEW_CONNECTION_INFO *")] + internal QUIC_NEW_CONNECTION_INFO* Info; + + [NativeTypeName("HQUIC")] + internal QUIC_HANDLE* Connection; + } + + internal partial struct _STOP_COMPLETE_e__Struct + { + internal byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + internal byte AppCloseInProgress + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + internal byte RESERVED + { + get + { + return (byte)((_bitfield >> 1) & 0x7Fu); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x7Fu << 1)) | ((value & 0x7Fu) << 1)); + } + } + } + } + } + + internal enum QUIC_CONNECTION_EVENT_TYPE + { + CONNECTED = 0, + SHUTDOWN_INITIATED_BY_TRANSPORT = 1, + SHUTDOWN_INITIATED_BY_PEER = 2, + SHUTDOWN_COMPLETE = 3, + 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, + RESUMPTION_TICKET_RECEIVED = 14, + PEER_CERTIFICATE_RECEIVED = 15, + } + + internal partial struct QUIC_CONNECTION_EVENT + { + internal QUIC_CONNECTION_EVENT_TYPE Type; + + [NativeTypeName("QUIC_CONNECTION_EVENT::(anonymous union)")] + internal _Anonymous_e__Union Anonymous; + + internal ref _Anonymous_e__Union._CONNECTED_e__Struct CONNECTED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.CONNECTED, 1)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal ref _Anonymous_e__Union._SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_COMPLETE, 1)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal ref _Anonymous_e__Union._STREAMS_AVAILABLE_e__Struct STREAMS_AVAILABLE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.STREAMS_AVAILABLE, 1)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal ref _Anonymous_e__Union._DATAGRAM_RECEIVED_e__Struct DATAGRAM_RECEIVED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.DATAGRAM_RECEIVED, 1)); + } + } + + internal 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)); + } + } + + internal ref _Anonymous_e__Union._RESUMED_e__Struct RESUMED + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.RESUMED, 1)); + } + } + + internal 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)); + } + } + + internal 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)")] + internal _CONNECTED_e__Struct CONNECTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct SHUTDOWN_INITIATED_BY_TRANSPORT; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SHUTDOWN_INITIATED_BY_PEER_e__Struct SHUTDOWN_INITIATED_BY_PEER; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _LOCAL_ADDRESS_CHANGED_e__Struct LOCAL_ADDRESS_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _PEER_ADDRESS_CHANGED_e__Struct PEER_ADDRESS_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _PEER_STREAM_STARTED_e__Struct PEER_STREAM_STARTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _STREAMS_AVAILABLE_e__Struct STREAMS_AVAILABLE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _IDEAL_PROCESSOR_CHANGED_e__Struct IDEAL_PROCESSOR_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _DATAGRAM_STATE_CHANGED_e__Struct DATAGRAM_STATE_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _DATAGRAM_RECEIVED_e__Struct DATAGRAM_RECEIVED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _DATAGRAM_SEND_STATE_CHANGED_e__Struct DATAGRAM_SEND_STATE_CHANGED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _RESUMED_e__Struct RESUMED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _RESUMPTION_TICKET_RECEIVED_e__Struct RESUMPTION_TICKET_RECEIVED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _PEER_CERTIFICATE_RECEIVED_e__Struct PEER_CERTIFICATE_RECEIVED; + + internal unsafe partial struct _CONNECTED_e__Struct + { + [NativeTypeName("BOOLEAN")] + internal byte SessionResumed; + + [NativeTypeName("uint8_t")] + internal byte NegotiatedAlpnLength; + + [NativeTypeName("const uint8_t *")] + internal byte* NegotiatedAlpn; + } + + internal partial struct _SHUTDOWN_INITIATED_BY_TRANSPORT_e__Struct + { + [NativeTypeName("HRESULT")] + internal int Status; + } + + internal partial struct _SHUTDOWN_INITIATED_BY_PEER_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + internal ulong ErrorCode; + } + + internal partial struct _SHUTDOWN_COMPLETE_e__Struct + { + internal byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + internal byte HandshakeCompleted + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 1")] + internal byte PeerAcknowledgedShutdown + { + get + { + return (byte)((_bitfield >> 1) & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~(0x1u << 1)) | ((value & 0x1u) << 1)); + } + } + + [NativeTypeName("BOOLEAN : 1")] + internal 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 *")] + internal QuicAddr* Address; + } + + internal unsafe partial struct _PEER_ADDRESS_CHANGED_e__Struct + { + [NativeTypeName("const QUIC_ADDR *")] + internal QuicAddr* Address; + } + + internal unsafe partial struct _PEER_STREAM_STARTED_e__Struct + { + [NativeTypeName("HQUIC")] + internal QUIC_HANDLE* Stream; + + internal QUIC_STREAM_OPEN_FLAGS Flags; + } + + internal partial struct _STREAMS_AVAILABLE_e__Struct + { + [NativeTypeName("uint16_t")] + internal ushort BidirectionalCount; + + [NativeTypeName("uint16_t")] + internal ushort UnidirectionalCount; + } + + internal partial struct _IDEAL_PROCESSOR_CHANGED_e__Struct + { + [NativeTypeName("uint16_t")] + internal ushort IdealProcessor; + } + + internal partial struct _DATAGRAM_STATE_CHANGED_e__Struct + { + [NativeTypeName("BOOLEAN")] + internal byte SendEnabled; + + [NativeTypeName("uint16_t")] + internal ushort MaxSendLength; + } + + internal unsafe partial struct _DATAGRAM_RECEIVED_e__Struct + { + [NativeTypeName("const QUIC_BUFFER *")] + internal QUIC_BUFFER* Buffer; + + internal QUIC_RECEIVE_FLAGS Flags; + } + + internal unsafe partial struct _DATAGRAM_SEND_STATE_CHANGED_e__Struct + { + internal void* ClientContext; + + internal QUIC_DATAGRAM_SEND_STATE State; + } + + internal unsafe partial struct _RESUMED_e__Struct + { + [NativeTypeName("uint16_t")] + internal ushort ResumptionStateLength; + + [NativeTypeName("const uint8_t *")] + internal byte* ResumptionState; + } + + internal unsafe partial struct _RESUMPTION_TICKET_RECEIVED_e__Struct + { + [NativeTypeName("uint32_t")] + internal uint ResumptionTicketLength; + + [NativeTypeName("const uint8_t *")] + internal byte* ResumptionTicket; + } + + internal unsafe partial struct _PEER_CERTIFICATE_RECEIVED_e__Struct + { + [NativeTypeName("QUIC_CERTIFICATE *")] + internal void* Certificate; + + [NativeTypeName("uint32_t")] + internal uint DeferredErrorFlags; + + [NativeTypeName("HRESULT")] + internal int DeferredStatus; + + [NativeTypeName("QUIC_CERTIFICATE_CHAIN *")] + internal void* Chain; + } + } + } + + internal enum QUIC_STREAM_EVENT_TYPE + { + 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, + PEER_ACCEPTED = 9, + } + + internal partial struct QUIC_STREAM_EVENT + { + internal QUIC_STREAM_EVENT_TYPE Type; + + [NativeTypeName("QUIC_STREAM_EVENT::(anonymous union)")] + internal _Anonymous_e__Union Anonymous; + + internal ref _Anonymous_e__Union._START_COMPLETE_e__Struct START_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.START_COMPLETE, 1)); + } + } + + internal ref _Anonymous_e__Union._RECEIVE_e__Struct RECEIVE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.RECEIVE, 1)); + } + } + + internal ref _Anonymous_e__Union._SEND_COMPLETE_e__Struct SEND_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SEND_COMPLETE, 1)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal 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)); + } + } + + internal ref _Anonymous_e__Union._SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE + { + get + { + return ref MemoryMarshal.GetReference(MemoryMarshal.CreateSpan(ref Anonymous.SHUTDOWN_COMPLETE, 1)); + } + } + + internal 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)")] + internal _START_COMPLETE_e__Struct START_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _RECEIVE_e__Struct RECEIVE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SEND_COMPLETE_e__Struct SEND_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _PEER_SEND_ABORTED_e__Struct PEER_SEND_ABORTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _PEER_RECEIVE_ABORTED_e__Struct PEER_RECEIVE_ABORTED; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SEND_SHUTDOWN_COMPLETE_e__Struct SEND_SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _SHUTDOWN_COMPLETE_e__Struct SHUTDOWN_COMPLETE; + + [FieldOffset(0)] + [NativeTypeName("struct (anonymous struct)")] + internal _IDEAL_SEND_BUFFER_SIZE_e__Struct IDEAL_SEND_BUFFER_SIZE; + + internal partial struct _START_COMPLETE_e__Struct + { + [NativeTypeName("HRESULT")] + internal int Status; + + [NativeTypeName("QUIC_UINT62")] + internal ulong ID; + + internal byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + internal byte PeerAccepted + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + internal 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")] + internal ulong AbsoluteOffset; + + [NativeTypeName("uint64_t")] + internal ulong TotalBufferLength; + + [NativeTypeName("const QUIC_BUFFER *")] + internal QUIC_BUFFER* Buffers; + + [NativeTypeName("uint32_t")] + internal uint BufferCount; + + internal QUIC_RECEIVE_FLAGS Flags; + } + + internal unsafe partial struct _SEND_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + internal byte Canceled; + + internal void* ClientContext; + } + + internal partial struct _PEER_SEND_ABORTED_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + internal ulong ErrorCode; + } + + internal partial struct _PEER_RECEIVE_ABORTED_e__Struct + { + [NativeTypeName("QUIC_UINT62")] + internal ulong ErrorCode; + } + + internal partial struct _SEND_SHUTDOWN_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + internal byte Graceful; + } + + internal partial struct _SHUTDOWN_COMPLETE_e__Struct + { + [NativeTypeName("BOOLEAN")] + internal byte ConnectionShutdown; + + internal byte _bitfield; + + [NativeTypeName("BOOLEAN : 1")] + internal byte AppCloseInProgress + { + get + { + return (byte)(_bitfield & 0x1u); + } + + set + { + _bitfield = (byte)((_bitfield & ~0x1u) | (value & 0x1u)); + } + } + + [NativeTypeName("BOOLEAN : 7")] + internal 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")] + internal ulong ByteCount; + } + } + } + + internal unsafe partial struct QUIC_API_TABLE + { + [NativeTypeName("QUIC_SET_CONTEXT_FN")] + internal delegate* unmanaged[Cdecl] SetContext; + + [NativeTypeName("QUIC_GET_CONTEXT_FN")] + internal delegate* unmanaged[Cdecl] GetContext; + + [NativeTypeName("QUIC_SET_CALLBACK_HANDLER_FN")] + internal delegate* unmanaged[Cdecl] SetCallbackHandler; + + [NativeTypeName("QUIC_SET_PARAM_FN")] + internal delegate* unmanaged[Cdecl] SetParam; + + [NativeTypeName("QUIC_GET_PARAM_FN")] + internal delegate* unmanaged[Cdecl] GetParam; + + [NativeTypeName("QUIC_REGISTRATION_OPEN_FN")] + internal delegate* unmanaged[Cdecl] RegistrationOpen; + + [NativeTypeName("QUIC_REGISTRATION_CLOSE_FN")] + internal delegate* unmanaged[Cdecl] RegistrationClose; + + [NativeTypeName("QUIC_REGISTRATION_SHUTDOWN_FN")] + internal delegate* unmanaged[Cdecl] RegistrationShutdown; + + [NativeTypeName("QUIC_CONFIGURATION_OPEN_FN")] + internal delegate* unmanaged[Cdecl] ConfigurationOpen; + + [NativeTypeName("QUIC_CONFIGURATION_CLOSE_FN")] + internal delegate* unmanaged[Cdecl] ConfigurationClose; + + [NativeTypeName("QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN")] + internal delegate* unmanaged[Cdecl] ConfigurationLoadCredential; + + [NativeTypeName("QUIC_LISTENER_OPEN_FN")] + internal delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> ListenerOpen; + + [NativeTypeName("QUIC_LISTENER_CLOSE_FN")] + internal delegate* unmanaged[Cdecl] ListenerClose; + + [NativeTypeName("QUIC_LISTENER_START_FN")] + internal delegate* unmanaged[Cdecl] ListenerStart; + + [NativeTypeName("QUIC_LISTENER_STOP_FN")] + internal delegate* unmanaged[Cdecl] ListenerStop; + + [NativeTypeName("QUIC_CONNECTION_OPEN_FN")] + internal delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> ConnectionOpen; + + [NativeTypeName("QUIC_CONNECTION_CLOSE_FN")] + internal delegate* unmanaged[Cdecl] ConnectionClose; + + [NativeTypeName("QUIC_CONNECTION_SHUTDOWN_FN")] + internal delegate* unmanaged[Cdecl] ConnectionShutdown; + + [NativeTypeName("QUIC_CONNECTION_START_FN")] + internal delegate* unmanaged[Cdecl] ConnectionStart; + + [NativeTypeName("QUIC_CONNECTION_SET_CONFIGURATION_FN")] + internal delegate* unmanaged[Cdecl] ConnectionSetConfiguration; + + [NativeTypeName("QUIC_CONNECTION_SEND_RESUMPTION_FN")] + internal delegate* unmanaged[Cdecl] ConnectionSendResumptionTicket; + + [NativeTypeName("QUIC_STREAM_OPEN_FN")] + internal delegate* unmanaged[Cdecl], void*, QUIC_HANDLE**, int> StreamOpen; + + [NativeTypeName("QUIC_STREAM_CLOSE_FN")] + internal delegate* unmanaged[Cdecl] StreamClose; + + [NativeTypeName("QUIC_STREAM_START_FN")] + internal delegate* unmanaged[Cdecl] StreamStart; + + [NativeTypeName("QUIC_STREAM_SHUTDOWN_FN")] + internal delegate* unmanaged[Cdecl] StreamShutdown; + + [NativeTypeName("QUIC_STREAM_SEND_FN")] + internal delegate* unmanaged[Cdecl] StreamSend; + + [NativeTypeName("QUIC_STREAM_RECEIVE_COMPLETE_FN")] + internal delegate* unmanaged[Cdecl] StreamReceiveComplete; + + [NativeTypeName("QUIC_STREAM_RECEIVE_SET_ENABLED_FN")] + internal delegate* unmanaged[Cdecl] StreamReceiveSetEnabled; + + [NativeTypeName("QUIC_DATAGRAM_SEND_FN")] + internal delegate* unmanaged[Cdecl] DatagramSend; + } + + internal static unsafe partial class MsQuic + { + [DllImport("msquic", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + [return: NativeTypeName("HRESULT")] + internal static extern int MsQuicOpenVersion([NativeTypeName("uint32_t")] uint Version, [NativeTypeName("const void **")] void** QuicApi); + + [DllImport("msquic", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + internal static extern void MsQuicClose([NativeTypeName("const void *")] void* QuicApi); + + [NativeTypeName("#define QUIC_MAX_ALPN_LENGTH 255")] + internal const uint QUIC_MAX_ALPN_LENGTH = 255; + + [NativeTypeName("#define QUIC_MAX_SNI_LENGTH 65535")] + internal const uint QUIC_MAX_SNI_LENGTH = 65535; + + [NativeTypeName("#define QUIC_MAX_RESUMPTION_APP_DATA_LENGTH 1000")] + internal const uint QUIC_MAX_RESUMPTION_APP_DATA_LENGTH = 1000; + + [NativeTypeName("#define QUIC_MAX_TICKET_KEY_COUNT 16")] + internal const uint QUIC_MAX_TICKET_KEY_COUNT = 16; + + [NativeTypeName("#define QUIC_TLS_SECRETS_MAX_SECRET_LEN 64")] + internal const uint QUIC_TLS_SECRETS_MAX_SECRET_LEN = 64; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_GLOBAL 0x01000000")] + internal const uint QUIC_PARAM_PREFIX_GLOBAL = 0x01000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_REGISTRATION 0x02000000")] + internal const uint QUIC_PARAM_PREFIX_REGISTRATION = 0x02000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_CONFIGURATION 0x03000000")] + internal const uint QUIC_PARAM_PREFIX_CONFIGURATION = 0x03000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_LISTENER 0x04000000")] + internal const uint QUIC_PARAM_PREFIX_LISTENER = 0x04000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_CONNECTION 0x05000000")] + internal const uint QUIC_PARAM_PREFIX_CONNECTION = 0x05000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_TLS 0x06000000")] + internal const uint QUIC_PARAM_PREFIX_TLS = 0x06000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_TLS_SCHANNEL 0x07000000")] + internal const uint QUIC_PARAM_PREFIX_TLS_SCHANNEL = 0x07000000; + + [NativeTypeName("#define QUIC_PARAM_PREFIX_STREAM 0x08000000")] + internal const uint QUIC_PARAM_PREFIX_STREAM = 0x08000000; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT 0x01000000")] + internal const uint QUIC_PARAM_GLOBAL_RETRY_MEMORY_PERCENT = 0x01000000; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS 0x01000001")] + internal const uint QUIC_PARAM_GLOBAL_SUPPORTED_VERSIONS = 0x01000001; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE 0x01000002")] + internal const uint QUIC_PARAM_GLOBAL_LOAD_BALACING_MODE = 0x01000002; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_PERF_COUNTERS 0x01000003")] + internal const uint QUIC_PARAM_GLOBAL_PERF_COUNTERS = 0x01000003; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LIBRARY_VERSION 0x01000004")] + internal const uint QUIC_PARAM_GLOBAL_LIBRARY_VERSION = 0x01000004; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_SETTINGS 0x01000005")] + internal const uint QUIC_PARAM_GLOBAL_SETTINGS = 0x01000005; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS 0x01000006")] + internal const uint QUIC_PARAM_GLOBAL_GLOBAL_SETTINGS = 0x01000006; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_VERSION_SETTINGS 0x01000007")] + internal const uint QUIC_PARAM_GLOBAL_VERSION_SETTINGS = 0x01000007; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH 0x01000008")] + internal const uint QUIC_PARAM_GLOBAL_LIBRARY_GIT_HASH = 0x01000008; + + [NativeTypeName("#define QUIC_PARAM_GLOBAL_DATAPATH_PROCESSORS 0x01000009")] + internal const uint QUIC_PARAM_GLOBAL_DATAPATH_PROCESSORS = 0x01000009; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_SETTINGS 0x03000000")] + internal const uint QUIC_PARAM_CONFIGURATION_SETTINGS = 0x03000000; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_TICKET_KEYS 0x03000001")] + internal const uint QUIC_PARAM_CONFIGURATION_TICKET_KEYS = 0x03000001; + + [NativeTypeName("#define QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS 0x03000002")] + internal const uint QUIC_PARAM_CONFIGURATION_VERSION_SETTINGS = 0x03000002; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_LOCAL_ADDRESS 0x04000000")] + internal const uint QUIC_PARAM_LISTENER_LOCAL_ADDRESS = 0x04000000; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_STATS 0x04000001")] + internal const uint QUIC_PARAM_LISTENER_STATS = 0x04000001; + + [NativeTypeName("#define QUIC_PARAM_LISTENER_CIBIR_ID 0x04000002")] + internal const uint QUIC_PARAM_LISTENER_CIBIR_ID = 0x04000002; + + [NativeTypeName("#define QUIC_PARAM_CONN_QUIC_VERSION 0x05000000")] + internal const uint QUIC_PARAM_CONN_QUIC_VERSION = 0x05000000; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_ADDRESS 0x05000001")] + internal const uint QUIC_PARAM_CONN_LOCAL_ADDRESS = 0x05000001; + + [NativeTypeName("#define QUIC_PARAM_CONN_REMOTE_ADDRESS 0x05000002")] + internal const uint QUIC_PARAM_CONN_REMOTE_ADDRESS = 0x05000002; + + [NativeTypeName("#define QUIC_PARAM_CONN_IDEAL_PROCESSOR 0x05000003")] + internal const uint QUIC_PARAM_CONN_IDEAL_PROCESSOR = 0x05000003; + + [NativeTypeName("#define QUIC_PARAM_CONN_SETTINGS 0x05000004")] + internal const uint QUIC_PARAM_CONN_SETTINGS = 0x05000004; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS 0x05000005")] + internal const uint QUIC_PARAM_CONN_STATISTICS = 0x05000005; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_PLAT 0x05000006")] + internal const uint QUIC_PARAM_CONN_STATISTICS_PLAT = 0x05000006; + + [NativeTypeName("#define QUIC_PARAM_CONN_SHARE_UDP_BINDING 0x05000007")] + internal const uint QUIC_PARAM_CONN_SHARE_UDP_BINDING = 0x05000007; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT 0x05000008")] + internal const uint QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT = 0x05000008; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT 0x05000009")] + internal const uint QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT = 0x05000009; + + [NativeTypeName("#define QUIC_PARAM_CONN_MAX_STREAM_IDS 0x0500000A")] + internal const uint QUIC_PARAM_CONN_MAX_STREAM_IDS = 0x0500000A; + + [NativeTypeName("#define QUIC_PARAM_CONN_CLOSE_REASON_PHRASE 0x0500000B")] + internal const uint QUIC_PARAM_CONN_CLOSE_REASON_PHRASE = 0x0500000B; + + [NativeTypeName("#define QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME 0x0500000C")] + internal const uint QUIC_PARAM_CONN_STREAM_SCHEDULING_SCHEME = 0x0500000C; + + [NativeTypeName("#define QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED 0x0500000D")] + internal const uint QUIC_PARAM_CONN_DATAGRAM_RECEIVE_ENABLED = 0x0500000D; + + [NativeTypeName("#define QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED 0x0500000E")] + internal const uint QUIC_PARAM_CONN_DATAGRAM_SEND_ENABLED = 0x0500000E; + + [NativeTypeName("#define QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION 0x0500000F")] + internal const uint QUIC_PARAM_CONN_DISABLE_1RTT_ENCRYPTION = 0x0500000F; + + [NativeTypeName("#define QUIC_PARAM_CONN_RESUMPTION_TICKET 0x05000010")] + internal const uint QUIC_PARAM_CONN_RESUMPTION_TICKET = 0x05000010; + + [NativeTypeName("#define QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID 0x05000011")] + internal const uint QUIC_PARAM_CONN_PEER_CERTIFICATE_VALID = 0x05000011; + + [NativeTypeName("#define QUIC_PARAM_CONN_LOCAL_INTERFACE 0x05000012")] + internal const uint QUIC_PARAM_CONN_LOCAL_INTERFACE = 0x05000012; + + [NativeTypeName("#define QUIC_PARAM_CONN_TLS_SECRETS 0x05000013")] + internal const uint QUIC_PARAM_CONN_TLS_SECRETS = 0x05000013; + + [NativeTypeName("#define QUIC_PARAM_CONN_VERSION_SETTINGS 0x05000014")] + internal const uint QUIC_PARAM_CONN_VERSION_SETTINGS = 0x05000014; + + [NativeTypeName("#define QUIC_PARAM_CONN_CIBIR_ID 0x05000015")] + internal const uint QUIC_PARAM_CONN_CIBIR_ID = 0x05000015; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_V2 0x05000016")] + internal const uint QUIC_PARAM_CONN_STATISTICS_V2 = 0x05000016; + + [NativeTypeName("#define QUIC_PARAM_CONN_STATISTICS_V2_PLAT 0x05000017")] + internal const uint QUIC_PARAM_CONN_STATISTICS_V2_PLAT = 0x05000017; + + [NativeTypeName("#define QUIC_PARAM_TLS_HANDSHAKE_INFO 0x06000000")] + internal const uint QUIC_PARAM_TLS_HANDSHAKE_INFO = 0x06000000; + + [NativeTypeName("#define QUIC_PARAM_TLS_NEGOTIATED_ALPN 0x06000001")] + internal const uint QUIC_PARAM_TLS_NEGOTIATED_ALPN = 0x06000001; + + [NativeTypeName("#define QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W 0x07000000")] + internal const uint QUIC_PARAM_TLS_SCHANNEL_CONTEXT_ATTRIBUTE_W = 0x07000000; + + [NativeTypeName("#define QUIC_PARAM_STREAM_ID 0x08000000")] + internal const uint QUIC_PARAM_STREAM_ID = 0x08000000; + + [NativeTypeName("#define QUIC_PARAM_STREAM_0RTT_LENGTH 0x08000001")] + internal const uint QUIC_PARAM_STREAM_0RTT_LENGTH = 0x08000001; + + [NativeTypeName("#define QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE 0x08000002")] + internal const uint QUIC_PARAM_STREAM_IDEAL_SEND_BUFFER_SIZE = 0x08000002; + + [NativeTypeName("#define QUIC_PARAM_STREAM_PRIORITY 0x08000003")] + internal const uint QUIC_PARAM_STREAM_PRIORITY = 0x08000003; + + [NativeTypeName("#define QUIC_API_VERSION_2 2")] + internal const uint QUIC_API_VERSION_2 = 2; + } +} 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 0000000..67e3967 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_linux.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 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 0000000..00a3ad79 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_macos.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 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 0000000..ee8cf6b --- /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 f5d3aba..c2483d6 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.Diagnostics; 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.Security.Cryptography.X509Certificates; 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 @@ namespace System.Net.Quic.Implementations.MsQuic 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 @@ namespace System.Net.Quic.Implementations.MsQuic 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 @@ namespace System.Net.Quic.Implementations.MsQuic 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); public bool Connected; public long AbortErrorCode = -1; @@ -84,7 +82,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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(); } } @@ -127,10 +125,8 @@ namespace System.Net.Quic.Implementations.MsQuic } } - 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); @@ -144,10 +140,11 @@ namespace System.Net.Quic.Implementations.MsQuic 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 { @@ -156,15 +153,14 @@ namespace System.Net.Quic.Implementations.MsQuic } _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)); @@ -181,14 +177,14 @@ namespace System.Net.Quic.Implementations.MsQuic _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 { @@ -196,10 +192,9 @@ namespace System.Net.Quic.Implementations.MsQuic 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"); } } @@ -213,11 +208,11 @@ namespace System.Net.Quic.Implementations.MsQuic 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) @@ -233,14 +228,14 @@ namespace System.Net.Quic.Implementations.MsQuic // 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 { @@ -249,27 +244,26 @@ namespace System.Net.Quic.Implementations.MsQuic 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; } @@ -280,24 +274,24 @@ namespace System.Net.Quic.Implementations.MsQuic // 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)) { @@ -309,33 +303,33 @@ namespace System.Net.Quic.Implementations.MsQuic state.Connection = null; - state.ShutdownTcs.SetResult(MsQuicStatusCodes.Success); + state.ShutdownTcs.SetResult(QUIC_STATUS_SUCCESS); // Stop accepting new streams. state.AcceptQueue.Writer.TryComplete(); - 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) { - 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; @@ -346,24 +340,26 @@ namespace System.Net.Quic.Implementations.MsQuic 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(); @@ -376,7 +372,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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 @@ -409,40 +405,40 @@ namespace System.Net.Quic.Implementations.MsQuic 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; } } @@ -488,22 +484,24 @@ namespace System.Net.Quic.Implementations.MsQuic return stream; } - internal override ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL, cancellationToken); - internal override ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.NONE, cancellationToken); + internal override ValueTask OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default) + => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL, cancellationToken); + internal override ValueTask OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default) + => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.NONE, cancellationToken); 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(); @@ -512,25 +510,24 @@ namespace System.Net.Quic.Implementations.MsQuic 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; @@ -547,7 +544,7 @@ namespace System.Net.Quic.Implementations.MsQuic { // 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 @@ -561,19 +558,18 @@ namespace System.Net.Quic.Implementations.MsQuic } // 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(); @@ -584,11 +580,15 @@ namespace System.Net.Quic.Implementations.MsQuic _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) { @@ -599,10 +599,10 @@ namespace System.Net.Quic.Implementations.MsQuic 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 { @@ -623,19 +623,19 @@ namespace System.Net.Quic.Implementations.MsQuic } } - 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 @@ -657,14 +657,14 @@ namespace System.Net.Quic.Implementations.MsQuic case QUIC_CONNECTION_EVENT_TYPE.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) @@ -676,11 +676,11 @@ namespace System.Net.Quic.Implementations.MsQuic } 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; } } @@ -712,7 +712,7 @@ namespace System.Net.Quic.Implementations.MsQuic } } - private void Dispose(bool disposing) + private unsafe void Dispose(bool disposing) { int disposed = Interlocked.Exchange(ref _disposed, 1); if (disposed != 0) @@ -720,15 +720,15 @@ namespace System.Net.Quic.Implementations.MsQuic 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, + MsQuicApi.Api.ApiTable->ConnectionShutdown( + _state.Handle.QuicHandle, QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT, 0); } @@ -752,7 +752,7 @@ namespace System.Net.Quic.Implementations.MsQuic _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(); 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 7c68313..8ae290b 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.Runtime.InteropServices; 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 @@ namespace System.Net.Quic.Implementations.MsQuic { // 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 @@ namespace System.Net.Quic.Implementations.MsQuic } } - internal MsQuicListener(QuicListenerOptions options) + internal unsafe MsQuicListener(QuicListenerOptions options) { ArgumentNullException.ThrowIfNull(options.ListenEndPoint, nameof(options.ListenEndPoint)); @@ -91,14 +90,14 @@ namespace System.Net.Quic.Implementations.MsQuic _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 @@ namespace System.Net.Quic.Implementations.MsQuic 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,23 @@ namespace System.Net.Quic.Implementations.MsQuic Internals.SocketAddress address = IPEndPointExtensions.Serialize(listenEndPoint); - uint status; - Debug.Assert(_stateHandle.IsAllocated); - - MemoryHandle[]? handles = null; - QuicBuffer[]? buffers = null; try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers); + using var msquicBuffers = new MsQuicBuffers(); + msquicBuffers.Initialize(applicationProtocols, applicationProtocol => applicationProtocol.Protocol); + // 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, + msquicBuffers.Buffers, + (uint)applicationProtocols.Count, + (QuicAddr*)paddress), "ListenerStart failed"); } } catch @@ -203,18 +205,12 @@ namespace System.Net.Quic.Implementations.MsQuic _stateHandle.Free(); throw; } - finally - { - 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 +223,47 @@ namespace System.Net.Quic.Implementations.MsQuic 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.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.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 +287,25 @@ namespace System.Net.Quic.Implementations.MsQuic 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 +314,14 @@ namespace System.Net.Quic.Implementations.MsQuic { 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 ff98028..0ef90fc 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.Buffers; 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,7 +37,6 @@ namespace System.Net.Quic.Implementations.MsQuic 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 ReadState ReadState; @@ -46,7 +44,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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; @@ -67,7 +65,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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; @@ -89,7 +87,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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); @@ -101,10 +99,8 @@ namespace System.Net.Quic.Implementations.MsQuic } } - 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)) { @@ -129,10 +125,11 @@ namespace System.Net.Quic.Implementations.MsQuic 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 { @@ -141,18 +138,17 @@ namespace System.Net.Quic.Implementations.MsQuic 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.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); @@ -175,21 +171,23 @@ namespace System.Net.Quic.Implementations.MsQuic 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); } catch { @@ -198,13 +196,12 @@ namespace System.Net.Quic.Implementations.MsQuic 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.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + + $"in connection {_state.ConnectionState.Handle}."); } } @@ -437,7 +434,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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 @@ -576,7 +573,7 @@ namespace System.Net.Quic.Implementations.MsQuic } /// 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) { @@ -584,7 +581,7 @@ namespace System.Net.Quic.Implementations.MsQuic } int originalDestinationLength = destinationBuffer.Length; - QuicBuffer nativeBuffer; + QUIC_BUFFER nativeBuffer; int takeLength; int i = 0; @@ -671,11 +668,13 @@ namespace System.Net.Quic.Implementations.MsQuic StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.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) @@ -843,12 +842,11 @@ namespace System.Net.Quic.Implementations.MsQuic } - 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; bool completeRead = false; - bool releaseHandles = false; lock (_state) { if (_state.SendState < SendState.Aborted) @@ -868,33 +866,29 @@ namespace System.Net.Quic.Implementations.MsQuic { _state.ShutdownState = ShutdownState.Pending; } - - // Check if we already got final event. - releaseHandles = Interlocked.Exchange(ref _state.ShutdownDone, State.ShutdownDone_Disposed) == State.ShutdownDone_NotificationReceived; - if (releaseHandles) - { - _state.ShutdownState = ShutdownState.Finished; - } } - 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.GRACEFUL, errorCode: 0); + } + catch (ObjectDisposedException) { }; } - catch (ObjectDisposedException) { }; - } - if (abortRead) - { - try + if (abortRead) { - // TODO: error code used here MUST be specified by the application layer - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff); + try + { + // TODO: error code used here MUST be specified by the application layer + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff); + } + catch (ObjectDisposedException) { }; } - catch (ObjectDisposedException) { }; } if (completeRead) @@ -903,38 +897,40 @@ namespace System.Net.Quic.Implementations.MsQuic ExceptionDispatchInfo.SetCurrentStackTrace(new QuicOperationAbortedException("Read was canceled"))); } + + // Check if we already got final event. + bool releaseHandles = Interlocked.Exchange(ref _state.ShutdownDone, State.ShutdownDone_Disposed) == State.ShutdownDone_NotificationReceived; if (releaseHandles) { _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 @@ -973,29 +969,29 @@ namespace System.Net.Quic.Implementations.MsQuic case QUIC_STREAM_EVENT_TYPE.PEER_ACCEPTED: return HandleEventPeerAccepted(state); 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 HandleEventReceive(State state, ref StreamEvent evt) + private static unsafe int HandleEventReceive(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.FIN) ? " with FIN flag" : "")}"); } int readLength; @@ -1020,12 +1016,12 @@ namespace System.Net.Quic.Implementations.MsQuic 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); } } @@ -1048,13 +1044,13 @@ namespace System.Net.Quic.Implementations.MsQuic } // 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: @@ -1066,7 +1062,7 @@ namespace System.Net.Quic.Implementations.MsQuic state.ReadState = ReadState.PendingReadFinished; // state.ReadState will be set to None later once the ReceiveResettableCompletionSource is awaited. - 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) @@ -1083,7 +1079,7 @@ namespace System.Net.Quic.Implementations.MsQuic // 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; } } @@ -1096,15 +1092,15 @@ namespace System.Net.Quic.Implementations.MsQuic // 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; @@ -1122,7 +1118,7 @@ namespace System.Net.Quic.Implementations.MsQuic } state.SendState = SendState.Aborted; - state.SendErrorCode = (long)evt.Data.PeerReceiveAborted.ErrorCode; + state.SendErrorCode = (long)streamEvent.PEER_RECEIVE_ABORTED.ErrorCode; } if (shouldSendComplete) @@ -1137,26 +1133,26 @@ namespace System.Net.Quic.Implementations.MsQuic 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) { - uint status = evt.Data.StartComplete.Status; + int status = streamEvent.START_COMPLETE.Status; // The way we expose Open(Uni|Bi)directionalStreamAsync operations is that the stream // is also accepted by the peer (i.e. it is within advertised stream limits). However, // We may receive START_COMPLETE notification before the stream is accepted, so we defer // completing the StartcompletionSource until we get PeerAccepted notification. - if (status != MsQuicStatusCodes.Success) + if (status != QUIC_STATUS_SUCCESS) { // Start irrecoverably failed. The possible status codes are: // - Aborted - connection aborted by peer // - InvalidState - stream already started before, or connection aborted locally // - StreamLimitReached - only if QUIC_STREAM_START_FLAG_FAIL_BLOCKED was specified (not in our case). // - if (status == MsQuicStatusCodes.Aborted) + if (status == QUIC_STATUS_ABORTED) { state.StartCompletionSource.TrySetException( ExceptionDispatchInfo.SetCurrentStackTrace(GetConnectionAbortedException(state))); @@ -1166,10 +1162,10 @@ namespace System.Net.Quic.Implementations.MsQuic // TODO: Should we throw QuicOperationAbortedException when status is InvalidState? // [ActiveIssue("https://github.com/dotnet/runtime/issues/55619")] state.StartCompletionSource.TrySetException( - ExceptionDispatchInfo.SetCurrentStackTrace(new QuicException($"StreamStart finished with status {MsQuicStatusCodes.GetError(status)}"))); + ExceptionDispatchInfo.SetCurrentStackTrace(new MsQuicException(status, "StreamStart failed"))); } } - else if ((evt.Data.StartComplete.PeerAccepted & 1) != 0) + else if ((streamEvent.START_COMPLETE.PeerAccepted & 1) != 0) { // Start succeeded and we were within stream limits, stream already usable. state.StartCompletionSource.TrySetResult(); @@ -1177,10 +1173,10 @@ namespace System.Net.Quic.Implementations.MsQuic // if PeerAccepted == 0, we will later receive PEER_ACCEPTED event, which will // complete the StartCompletionSource - return MsQuicStatusCodes.Success; + 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. @@ -1191,7 +1187,7 @@ namespace System.Net.Quic.Implementations.MsQuic // 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) @@ -1209,12 +1205,12 @@ namespace System.Net.Quic.Implementations.MsQuic } } - 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) { @@ -1228,7 +1224,7 @@ namespace System.Net.Quic.Implementations.MsQuic 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); @@ -1290,22 +1286,22 @@ namespace System.Net.Quic.Implementations.MsQuic state.Cleanup(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } - private static uint HandleEventPeerAccepted(State state) + private static int HandleEventPeerAccepted(State state) { state.StartCompletionSource.TrySetResult(); - 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) @@ -1314,17 +1310,17 @@ namespace System.Net.Quic.Implementations.MsQuic 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); } @@ -1334,12 +1330,12 @@ namespace System.Net.Quic.Implementations.MsQuic 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; @@ -1364,7 +1360,7 @@ namespace System.Net.Quic.Implementations.MsQuic if (!canceled) { - state.SendResettableCompletionSource.Complete(MsQuicStatusCodes.Success); + state.SendResettableCompletionSource.Complete(QUIC_STATUS_SUCCESS); } else { @@ -1381,7 +1377,7 @@ namespace System.Net.Quic.Implementations.MsQuic } } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } private static void CleanupSendState(State state) @@ -1416,11 +1412,11 @@ namespace System.Net.Quic.Implementations.MsQuic 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; @@ -1428,24 +1424,23 @@ namespace System.Net.Quic.Implementations.MsQuic _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(); @@ -1476,7 +1471,7 @@ namespace System.Net.Quic.Implementations.MsQuic { 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]; } @@ -1484,7 +1479,7 @@ namespace System.Net.Quic.Implementations.MsQuic _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(); @@ -1495,24 +1490,23 @@ namespace System.Net.Quic.Implementations.MsQuic } 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(); @@ -1540,13 +1534,13 @@ namespace System.Net.Quic.Implementations.MsQuic { 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]; @@ -1559,39 +1553,38 @@ namespace System.Net.Quic.Implementations.MsQuic } 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() @@ -1602,12 +1595,12 @@ namespace System.Net.Quic.Implementations.MsQuic } } - 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}" : "")); } @@ -1676,7 +1669,7 @@ namespace System.Net.Quic.Implementations.MsQuic state.Cleanup(); } - return MsQuicStatusCodes.Success; + return QUIC_STATUS_SUCCESS; } private static Exception GetConnectionAbortedException(State state) => @@ -1711,12 +1704,19 @@ namespace System.Net.Quic.Implementations.MsQuic ((State)state!).StartCompletionSource.TrySetCanceled(token); }, _state); - uint status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); + int status; + unsafe + { + status = MsQuicApi.Api.ApiTable->StreamStart( + _state.Handle.QuicHandle, + QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); + } - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) + if (!StatusSucceeded(status)) { - _state.StartCompletionSource.TrySetException(QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream.")); - throw QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream."); + Exception exception = new MsQuicException(status, "Could not start stream"); + _state.StartCompletionSource.TrySetException(ExceptionDispatchInfo.SetCurrentStackTrace(exception)); + throw exception; } await _state.StartCompletionSource.Task.ConfigureAwait(false); 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 66d66f0..a848475 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 4cd9745..151eb54 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 @@ namespace System.Net.Quic 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 17793a6..aa7eaa6 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 @@ namespace System.Net.Quic.Tests [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 ca29a79..0559db5 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 @@ namespace System.Net.Quic.Tests } [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 @@ namespace System.Net.Quic.Tests } [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 @@ namespace System.Net.Quic.Tests 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 @@ namespace System.Net.Quic.Tests { 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(); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index 644245d..411b5d3 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs @@ -90,7 +90,7 @@ namespace System.Net.Quic.Tests 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 bacc79b..e7586a3 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 @@ namespace System.Net.Quic.Tests } [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 e6a7a12..7f4e03a 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -812,7 +812,7 @@ namespace System.Net.Quic.Tests }, 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. diff --git a/src/tests/build.proj b/src/tests/build.proj index 879d27c..063e305 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -124,7 +124,7 @@ - + diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 8959fd9..97b8df0 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -3038,6 +3038,19 @@ https://github.com/dotnet/runtime/issues/64179 + + + https://github.com/dotnet/runtime/issues/52977 + + + https://github.com/dotnet/runtime/issues/52977 + + + https://github.com/dotnet/runtime/issues/52977 + + + https://github.com/dotnet/runtime/issues/52977 +