From: Jan Kotas Date: Fri, 6 May 2022 02:20:52 +0000 (-0700) Subject: Revert "[QUIC] Adopted msquic generated interop (#68288)" (#68940) X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~9328 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4820674a4471872d742c380f38e766b80dc79385;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Revert "[QUIC] Adopted msquic generated interop (#68288)" (#68940) This reverts commit 992b395a72d161bb2346258a726fb93b10f0d7e7. --- diff --git a/THIRD-PARTY-NOTICES.TXT b/THIRD-PARTY-NOTICES.TXT index fc250aa..2a94ef5 100644 --- a/THIRD-PARTY-NOTICES.TXT +++ b/THIRD-PARTY-NOTICES.TXT @@ -1065,11 +1065,3 @@ 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/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 5a80b1d..0ecfed9 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -29,9 +29,21 @@ - + + + + + + + + + + + + + Common\DisableRuntimeMarshalling.cs + - @@ -39,6 +51,7 @@ + @@ -61,6 +74,7 @@ + @@ -93,21 +107,26 @@ - + + + + + + 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 { - var cfg = new QUIC_REGISTRATION_CONFIG { - AppName = (sbyte*)pAppName, - ExecutionProfile = QUIC_EXECUTION_PROFILE.LOW_LATENCY - }; + AppName = ".NET", + ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY + }; - QUIC_HANDLE* handle; - ThrowIfFailure(ApiTable->RegistrationOpen(&cfg, &handle), "RegistrationOpen failed"); + status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle); + QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed."); - Registration = new SafeMsQuicRegistrationHandle(handle); - } + Registration = handle; } internal static MsQuicApi Api { get; } = null!; internal static bool IsQuicSupported { get; } + private const int MsQuicVersion = 2; + internal static bool Tls13MayBeDisabled { get; } static MsQuicApi() @@ -76,36 +129,21 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal } IntPtr msQuicHandle; - if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || + if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) { try { if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress)) { - QUIC_API_TABLE* apiTable; - delegate* unmanaged[Cdecl] msQuicOpenVersion = (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; - if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable))) + NativeApi* vtable; + delegate* unmanaged[Cdecl] msQuicOpenVersion = + (delegate* unmanaged[Cdecl])msQuicOpenVersionAddress; + uint status = msQuicOpenVersion(MsQuicVersion, &vtable); + if (MsQuicStatusHelper.SuccessfulStatusCode(status)) { - 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}'"); - } - } - } + IsQuicSupported = true; + Api = new MsQuicApi(vtable); } } } @@ -144,5 +182,38 @@ 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 deleted file mode 100644 index e98e977..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicBuffers.cs +++ /dev/null @@ -1,94 +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.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 784d895..7fef8a8 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 Microsoft.Quic.MsQuic; +using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; namespace System.Net.Quic.Implementations.MsQuic.Internal { internal static class MsQuicParameterHelpers { - internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param) + internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param) { // MsQuic always uses storage size as if IPv6 was used uint valueLen = (uint)Internals.SocketAddress.IPv6AddressSize; @@ -18,19 +18,17 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal fixed (byte* paddress = &MemoryMarshal.GetReference(address)) { - ThrowIfFailure(api.ApiTable->GetParam( - nativeObject.QuicHandle, - param, - &valueLen, - paddress), "GetIPEndPointParam failed."); + uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, paddress); + QuicExceptionHelpers.ThrowIfFailed(status, "GetIPEndPointParam failed."); } address = address.Slice(0, (int)valueLen); - return new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address).GetIPEndPoint(); + return new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address) + .GetIPEndPoint(); } - internal static unsafe void SetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, IPEndPoint value) + internal static unsafe void SetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param, IPEndPoint value) { Internals.SocketAddress socketAddress = IPEndPointExtensions.Serialize(value); @@ -41,60 +39,48 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal fixed (byte* paddress = &MemoryMarshal.GetReference(address)) { - ThrowIfFailure(api.ApiTable->SetParam( - nativeObject.QuicHandle, - param, - (uint)address.Length, - paddress), "Could not set IPEndPoint"); + QuicExceptionHelpers.ThrowIfFailed( + api.SetParamDelegate(nativeObject, param, (uint)address.Length, paddress), + "Could not set IPEndPoint"); } } - internal static unsafe ushort GetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param) + internal static unsafe ushort GetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param) { ushort value; uint valueLen = (uint)sizeof(ushort); - ThrowIfFailure(api.ApiTable->GetParam( - nativeObject.QuicHandle, - param, - &valueLen, - (byte*)&value), "GetUShortParam failed"); + uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte*)&value); + QuicExceptionHelpers.ThrowIfFailed(status, "GetUShortParam failed."); Debug.Assert(valueLen == sizeof(ushort)); return value; } - internal static unsafe void SetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ushort value) + internal static unsafe void SetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param, ushort value) { - ThrowIfFailure(api.ApiTable->SetParam( - nativeObject.QuicHandle, - param, - sizeof(ushort), - (byte*)&value), "Could not set ushort"); + QuicExceptionHelpers.ThrowIfFailed( + api.SetParamDelegate(nativeObject, param, sizeof(ushort), (byte*)&value), + "Could not set ushort."); } - internal static unsafe ulong GetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param) + internal static unsafe ulong GetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param) { ulong value; uint valueLen = (uint)sizeof(ulong); - ThrowIfFailure(api.ApiTable->GetParam( - nativeObject.QuicHandle, - param, - &valueLen, - (byte*)&value), "GetULongParam failed"); + uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte*)&value); + QuicExceptionHelpers.ThrowIfFailed(status, "GetULongParam failed."); Debug.Assert(valueLen == sizeof(ulong)); return value; } - internal static unsafe void SetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ulong value) + internal static unsafe void SetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param, ulong value) { - ThrowIfFailure(api.ApiTable->SetParam( - nativeObject.QuicHandle, - param, - sizeof(ulong), - (byte*)&value), "Could not set ulong"); + QuicExceptionHelpers.ThrowIfFailed( + api.SetParamDelegate(nativeObject, 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 new file mode 100644 index 0000000..680069b --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/QuicExceptionHelpers.cs @@ -0,0 +1,38 @@ +// 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 new file mode 100644 index 0000000..916cfc4 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicAlpnHelper.cs @@ -0,0 +1,58 @@ +// 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 new file mode 100644 index 0000000..8745dd5 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicEnums.cs @@ -0,0 +1,229 @@ +// 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 deleted file mode 100644 index 2dd3f11..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicException.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Net.Quic; -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 new file mode 100644 index 0000000..165a4b2 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicNativeMethods.cs @@ -0,0 +1,1438 @@ +// 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 deleted file mode 100644 index 9b2095b..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicSafeHandle.cs +++ /dev/null @@ -1,65 +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 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 new file mode 100644 index 0000000..d99df79 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Linux.cs @@ -0,0 +1,32 @@ +// 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 new file mode 100644 index 0000000..03fc254 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.OSX.cs @@ -0,0 +1,32 @@ +// 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 new file mode 100644 index 0000000..003aaa8 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.Windows.cs @@ -0,0 +1,32 @@ +// 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 new file mode 100644 index 0000000..50bc061 --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusCodes.cs @@ -0,0 +1,40 @@ +// 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 new file mode 100644 index 0000000..4f2bedb --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicStatusHelper.cs @@ -0,0 +1,23 @@ +// 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 new file mode 100644 index 0000000..cd7b4ba --- /dev/null +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/MsQuicTraceHelper.cs @@ -0,0 +1,30 @@ +// 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 a04f131..adcce1b 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,17 +8,25 @@ using System.Net.Security; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Threading; -using Microsoft.Quic; -using static Microsoft.Quic.MsQuic; +using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicConfigurationHandle : MsQuicSafeHandle + internal sealed class SafeMsQuicConfigurationHandle : SafeHandle { - public unsafe SafeMsQuicConfigurationHandle(QUIC_HANDLE* handle) - : base(handle, ptr => MsQuicApi.Api.ApiTable->ConfigurationClose((QUIC_HANDLE*)ptr), SafeHandleType.Configuration) + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeMsQuicConfigurationHandle() + : base(IntPtr.Zero, ownsHandle: true) { } + 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) { @@ -122,42 +130,50 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal Debug.Assert(!MsQuicApi.Api.Registration.IsInvalid); - QUIC_SETTINGS settings = default(QUIC_SETTINGS); - settings.IsSet.PeerUnidiStreamCount = 1; - settings.PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams; - settings.IsSet.PeerBidiStreamCount = 1; - settings.PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams; + var settings = new QuicSettings + { + IsSetFlags = QuicSettingsIsSetFlags.PeerBidiStreamCount | + QuicSettingsIsSetFlags.PeerUnidiStreamCount, + PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams, + PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams + }; - 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; - SafeMsQuicConfigurationHandle configurationHandle; + uint status; + SafeMsQuicConfigurationHandle? configurationHandle; X509Certificate2[]? intermediates = null; - 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); + 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."); try { - QUIC_CREDENTIAL_CONFIG config = default; + CredentialConfig config = default; config.Flags = flags; // TODO: consider using LOAD_ASYNCHRONOUS with a callback. if (cipherSuitesPolicy != null) @@ -172,17 +188,17 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal intermediates = certificateContext.IntermediateCertificates; } - int status; if (certificate != null) { if (OperatingSystem.IsWindows()) { - config.Type = QUIC_CREDENTIAL_TYPE.CERTIFICATE_CONTEXT; - config.CertificateContext = (void*)certificate.Handle; - status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); + config.Type = QUIC_CREDENTIAL_TYPE.CONTEXT; + config.Certificate = certificate.Handle; + status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config); } else { + CredentialConfigCertificatePkcs12 pkcs12Config; byte[] asn1; if (intermediates?.Length > 0) @@ -201,35 +217,32 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal asn1 = certificate.Export(X509ContentType.Pkcs12); } - fixed (byte* ptr = asn1) + fixed (void* ptr = asn1) { - 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); + 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); } } } else { config.Type = QUIC_CREDENTIAL_TYPE.NONE; - status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); + status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config); } #if TARGET_WINDOWS if ((Interop.SECURITY_STATUS)status == Interop.SECURITY_STATUS.AlgorithmMismatch && MsQuicApi.Tls13MayBeDisabled) { - throw new MsQuicException(status, SR.net_ssl_app_protocols_invalid); + throw new QuicException(SR.net_ssl_app_protocols_invalid, null, (int)status); } #endif - ThrowIfFailure(status, "ConfigurationLoadCredential failed"); + QuicExceptionHelpers.ThrowIfFailed(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 4d308bd..9354ce0 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,14 +1,29 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Quic; +using System.Runtime.InteropServices; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicConnectionHandle : MsQuicSafeHandle + internal sealed class SafeMsQuicConnectionHandle : SafeHandle { - public unsafe SafeMsQuicConnectionHandle(QUIC_HANDLE* handle) - : base(handle, ptr => MsQuicApi.Api.ApiTable->ConnectionClose((QUIC_HANDLE*)ptr), SafeHandleType.Connection) + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeMsQuicConnectionHandle() + : base(IntPtr.Zero, ownsHandle: true) { } + + 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 1188efd..f0f7555 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,14 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Quic; +using System.Runtime.InteropServices; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicListenerHandle : MsQuicSafeHandle + internal sealed class SafeMsQuicListenerHandle : SafeHandle { - public unsafe SafeMsQuicListenerHandle(QUIC_HANDLE* handle) - : base(handle, ptr => MsQuicApi.Api.ApiTable->ListenerClose((QUIC_HANDLE*)ptr), SafeHandleType.Listener) + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeMsQuicListenerHandle() + : base(IntPtr.Zero, ownsHandle: true) { } + + 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 629946e..798636b 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,14 +1,23 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Quic; +using System.Runtime.InteropServices; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicRegistrationHandle : MsQuicSafeHandle + internal sealed class SafeMsQuicRegistrationHandle : SafeHandle { - public unsafe SafeMsQuicRegistrationHandle(QUIC_HANDLE* handle) - : base(handle, ptr => MsQuicApi.Api.ApiTable->RegistrationClose((QUIC_HANDLE*)ptr), SafeHandleType.Registration) + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeMsQuicRegistrationHandle() + : base(IntPtr.Zero, ownsHandle: true) { } + + 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 4cbf56d..179bdd3 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,14 +1,29 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Quic; +using System.Runtime.InteropServices; namespace System.Net.Quic.Implementations.MsQuic.Internal { - internal sealed class SafeMsQuicStreamHandle : MsQuicSafeHandle + internal sealed class SafeMsQuicStreamHandle : SafeHandle { - public unsafe SafeMsQuicStreamHandle(QUIC_HANDLE* handle) - : base(handle, ptr => MsQuicApi.Api.ApiTable->StreamClose((QUIC_HANDLE*)ptr), SafeHandleType.Stream) + public override bool IsInvalid => handle == IntPtr.Zero; + + public SafeMsQuicStreamHandle() + : base(IntPtr.Zero, ownsHandle: true) { } + + 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 deleted file mode 100644 index 96b83d6..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic.cs +++ /dev/null @@ -1,192 +0,0 @@ -#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 deleted file mode 100644 index f26a48f..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated.cs +++ /dev/null @@ -1,2677 +0,0 @@ -#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 deleted file mode 100644 index 67e3967..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_linux.cs +++ /dev/null @@ -1,109 +0,0 @@ -#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 deleted file mode 100644 index 00a3ad79..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_macos.cs +++ /dev/null @@ -1,109 +0,0 @@ -#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 deleted file mode 100644 index ee8cf6b..0000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/msquic_generated_windows.cs +++ /dev/null @@ -1,109 +0,0 @@ -#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 c2483d6..f5d3aba 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,7 +5,6 @@ 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; @@ -14,8 +13,7 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; -using Microsoft.Quic; -using static Microsoft.Quic.MsQuic; +using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; namespace System.Net.Quic.Implementations.MsQuic { @@ -25,6 +23,9 @@ 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; @@ -39,6 +40,7 @@ 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; @@ -46,9 +48,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; @@ -82,7 +84,7 @@ namespace System.Net.Quic.Implementations.MsQuic if (releaseHandles) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handle after last stream."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handle after last stream."); Handle?.Dispose(); } } @@ -125,8 +127,10 @@ namespace System.Net.Quic.Implementations.MsQuic } } + internal string TraceId() => _state.TraceId; + // constructor for inbound connections - 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) + public 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); @@ -140,11 +144,10 @@ namespace System.Net.Quic.Implementations.MsQuic try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; - MsQuicApi.Api.ApiTable->SetCallbackHandler( - _state.Handle.QuicHandle, - nativeCallback, - (void*)GCHandle.ToIntPtr(_state.StateGCHandle)); + MsQuicApi.Api.SetCallbackHandlerDelegate( + _state.Handle, + s_connectionDelegate, + GCHandle.ToIntPtr(_state.StateGCHandle)); } catch { @@ -153,14 +156,15 @@ namespace System.Net.Quic.Implementations.MsQuic } _state.ListenerState = listenerState; + _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{handle} Inbound connection created"); + NetEventSource.Info(_state, $"{TraceId()} Inbound connection created"); } } // constructor for outbound connections - public unsafe MsQuicConnection(QuicClientConnectionOptions options) + public MsQuicConnection(QuicClientConnectionOptions options) { ArgumentNullException.ThrowIfNull(options.RemoteEndPoint, nameof(options.RemoteEndPoint)); @@ -177,14 +181,14 @@ namespace System.Net.Quic.Implementations.MsQuic _state.StateGCHandle = GCHandle.Alloc(_state); try { - QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - 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); + 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."); } catch { @@ -192,9 +196,10 @@ namespace System.Net.Quic.Implementations.MsQuic throw; } + _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.Handle} Outbound connection created"); + NetEventSource.Info(_state, $"{TraceId()} Outbound connection created"); } } @@ -208,11 +213,11 @@ namespace System.Net.Quic.Implementations.MsQuic internal override bool Connected => _state.Connected; - private static unsafe int HandleEventConnected(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventConnected(State state, ref ConnectionEvent connectionEvent) { if (state.Connected) { - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } if (state.IsServer) @@ -228,14 +233,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 QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } // Listener is closed connection.Dispose(); } } - return QUIC_STATUS_USER_CANCELED; + return MsQuicStatusCodes.UserCanceled; } else { @@ -244,26 +249,27 @@ namespace System.Net.Quic.Implementations.MsQuic Debug.Assert(state.Connection != null); - 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._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 = null; state.Connected = true; - state.ConnectTcs!.SetResult(QUIC_STATUS_SUCCESS); + state.ConnectTcs!.SetResult(MsQuicStatusCodes.Success); state.ConnectTcs = null; } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventShutdownInitiatedByTransport(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventShutdownInitiatedByTransport(State state, ref ConnectionEvent connectionEvent) { if (!state.Connected && state.ConnectTcs != null) { Debug.Assert(state.Connection != null); state.Connection = null; - Exception ex = new MsQuicException(connectionEvent.SHUTDOWN_INITIATED_BY_TRANSPORT.Status, "Connection has been shutdown by transport"); + uint hresult = connectionEvent.Data.ShutdownInitiatedByTransport.Status; + Exception ex = QuicExceptionHelpers.CreateExceptionForHResult(hresult, "Connection has been shutdown by transport."); state.ConnectTcs!.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex)); state.ConnectTcs = null; } @@ -274,24 +280,24 @@ namespace System.Net.Quic.Implementations.MsQuic // See: https://github.com/dotnet/runtime/issues/60133 state.AbortErrorCode = 0; state.AcceptQueue.Writer.TryComplete(); - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventShutdownInitiatedByPeer(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventShutdownInitiatedByPeer(State state, ref ConnectionEvent connectionEvent) { - state.AbortErrorCode = (long)connectionEvent.SHUTDOWN_INITIATED_BY_PEER.ErrorCode; + state.AbortErrorCode = (long)connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode; state.AcceptQueue.Writer.TryComplete(); - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventShutdownComplete(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent 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 - because of TLS validation or some other reason. + // This is inbound connection that never got connected - becasue 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)) { @@ -303,33 +309,33 @@ namespace System.Net.Quic.Implementations.MsQuic state.Connection = null; - state.ShutdownTcs.SetResult(QUIC_STATUS_SUCCESS); + state.ShutdownTcs.SetResult(MsQuicStatusCodes.Success); // Stop accepting new streams. state.AcceptQueue.Writer.TryComplete(); - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static unsafe int HandleEventNewStream(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventNewStream(State state, ref ConnectionEvent connectionEvent) { - var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.PEER_STREAM_STARTED.Stream); - if (!state.TryQueueNewStream(streamHandle, connectionEvent.PEER_STREAM_STARTED.Flags)) + var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.Data.PeerStreamStarted.Stream); + if (!state.TryQueueNewStream(streamHandle, connectionEvent.Data.PeerStreamStarted.Flags)) { // This will call StreamCloseDelegate and free the stream. // We will return Success to the MsQuic to prevent double free. streamHandle.Dispose(); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventStreamsAvailable(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventStreamsAvailable(State state, ref ConnectionEvent connectionEvent) { - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static unsafe int HandleEventPeerCertificateReceived(State state, ref QUIC_CONNECTION_EVENT connectionEvent) + private static uint HandleEventPeerCertificateReceived(State state, ref ConnectionEvent connectionEvent) { SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None; X509Chain? chain = null; @@ -340,26 +346,24 @@ namespace System.Net.Quic.Implementations.MsQuic try { - IntPtr certificateHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Certificate; - if (certificateHandle != IntPtr.Zero) + if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle != IntPtr.Zero) { if (OperatingSystem.IsWindows()) { - certificate = new X509Certificate2(certificateHandle); + certificate = new X509Certificate2(connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle); } else { unsafe { - ReadOnlySpan quicBuffer = new ReadOnlySpan((void*)certificateHandle, sizeof(QUIC_BUFFER)); + ReadOnlySpan quicBuffer = new ReadOnlySpan((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle, sizeof(QuicBuffer)); certificate = new X509Certificate2(new ReadOnlySpan(quicBuffer[0].Buffer, (int)quicBuffer[0].Length)); certificateBuffer = (IntPtr)quicBuffer[0].Buffer; certificateLength = (int)quicBuffer[0].Length; - IntPtr chainHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Chain; - if (chainHandle != IntPtr.Zero) + if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle != IntPtr.Zero) { - quicBuffer = new ReadOnlySpan((void*)chainHandle, sizeof(QUIC_BUFFER)); + quicBuffer = new ReadOnlySpan((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle, sizeof(QuicBuffer)); if (quicBuffer[0].Length != 0 && quicBuffer[0].Buffer != null) { additionalCertificates = new X509Certificate2Collection(); @@ -372,7 +376,7 @@ namespace System.Net.Quic.Implementations.MsQuic if (certificate == null) { - if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.Handle} Remote certificate required, but no remote certificate received"); + if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.TraceId} Remote certificate required, but no remote certificate received"); sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable; } else @@ -405,40 +409,40 @@ namespace System.Net.Quic.Implementations.MsQuic state.RemoteCertificateValidationCallback = (_, _, _, _) => success; if (!success && NetEventSource.Log.IsEnabled()) - NetEventSource.Error(state, $"{state.Handle} Remote certificate rejected by verification callback"); + NetEventSource.Error(state, $"{state.TraceId} Remote certificate rejected by verification callback"); if (!success) { if (state.IsServer) { - return QUIC_STATUS_USER_CANCELED; + return MsQuicStatusCodes.UserCanceled; } throw new AuthenticationException(SR.net_quic_cert_custom_validation); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } if (NetEventSource.Log.IsEnabled()) - NetEventSource.Info(state, $"{state.Handle} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}"); + NetEventSource.Info(state, $"{state.TraceId} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}"); if (sslPolicyErrors != SslPolicyErrors.None) { if (state.IsServer) { - return QUIC_STATUS_HANDSHAKE_FAILURE; + return MsQuicStatusCodes.HandshakeFailure; } throw new AuthenticationException(SR.Format(SR.net_quic_cert_chain_validation, sslPolicyErrors)); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } catch (Exception ex) { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.Handle} Certificate validation failed ${ex.Message}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.TraceId} Certificate validation failed ${ex.Message}"); throw; } } @@ -484,24 +488,22 @@ 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, QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT); + return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)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, QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT); + return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT); } - internal unsafe override ValueTask ConnectAsync(CancellationToken cancellationToken = default) + internal override ValueTask ConnectAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); @@ -510,24 +512,25 @@ namespace System.Net.Quic.Implementations.MsQuic throw new InvalidOperationException($"{nameof(ConnectAsync)} must not be called on a connection obtained from a listener."); } - ushort af = _remoteEndPoint.AddressFamily switch + QUIC_ADDRESS_FAMILY af = _remoteEndPoint.AddressFamily switch { - AddressFamily.Unspecified => (ushort)QUIC_ADDRESS_FAMILY_UNSPEC, - AddressFamily.InterNetwork => (ushort)QUIC_ADDRESS_FAMILY_INET, - AddressFamily.InterNetworkV6 => (ushort)QUIC_ADDRESS_FAMILY_INET6, + AddressFamily.Unspecified => QUIC_ADDRESS_FAMILY.UNSPEC, + AddressFamily.InterNetwork => QUIC_ADDRESS_FAMILY.INET, + AddressFamily.InterNetworkV6 => 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, QUIC_PARAM_CONN_REMOTE_ADDRESS, ipEndPoint); + MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, ipEndPoint); targetHost = _state.TargetHost ?? ((IPEndPoint)_remoteEndPoint).Address.ToString(); port = ((IPEndPoint)_remoteEndPoint).Port; @@ -544,7 +547,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, QUIC_PARAM_CONN_REMOTE_ADDRESS, new IPEndPoint(address, port)); + MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, new IPEndPoint(address, port)); targetHost = _state.TargetHost!; } else @@ -558,18 +561,19 @@ 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)"); - ThrowIfFailure(MsQuicApi.Api.ApiTable->ConnectionStart( - _state.Handle.QuicHandle, - _configuration.QuicHandle, + status = MsQuicApi.Api.ConnectionStartDelegate( + _state.Handle, + _configuration, af, - (sbyte*)pTargetHost, - (ushort)port), "Failed to connect to peer"); + targetHost, + (ushort)port); + + QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer."); // this handle is ref counted by MsQuic, so safe to dispose here. _configuration.Dispose(); @@ -580,15 +584,11 @@ namespace System.Net.Quic.Implementations.MsQuic _state.Connection = null; throw; } - finally - { - Marshal.FreeCoTaskMem(pTargetHost); - } return new ValueTask(tcs.Task); } - private unsafe ValueTask ShutdownAsync( + private 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.ApiTable->ConnectionShutdown( - _state.Handle.QuicHandle, + MsQuicApi.Api.ConnectionShutdownDelegate( + _state.Handle, Flags, - (ulong)ErrorCode); + ErrorCode); } catch { @@ -623,19 +623,19 @@ namespace System.Net.Quic.Implementations.MsQuic } } -#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) + private static unsafe uint NativeCallbackHandler( + IntPtr connection, + IntPtr context, + ConnectionEvent* connectionEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); + GCHandle gcHandle = GCHandle.FromIntPtr(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.Handle} Connection received event {connectionEvent->Type}"); + NetEventSource.Info(state, $"{state.TraceId} 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 QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); + NetEventSource.Error(state, $"{state.TraceId} 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.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); + Debug.Fail($"{state.TraceId} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}"); } // TODO: trigger an exception on any outstanding async calls. - return QUIC_STATUS_INTERNAL_ERROR; + return MsQuicStatusCodes.InternalError; } } @@ -712,7 +712,7 @@ namespace System.Net.Quic.Implementations.MsQuic } } - private unsafe void Dispose(bool disposing) + private 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, $"{_state.Handle} Connection disposing {disposing}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} 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.ApiTable->ConnectionShutdown( - _state.Handle.QuicHandle, + MsQuicApi.Api.ConnectionShutdownDelegate( + _state.Handle, 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, $"{_state.Handle} Connection releasing handle"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} 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 8ae290b..7c68313 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,6 +31,7 @@ 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); @@ -82,7 +83,7 @@ namespace System.Net.Quic.Implementations.MsQuic } } - internal unsafe MsQuicListener(QuicListenerOptions options) + internal MsQuicListener(QuicListenerOptions options) { ArgumentNullException.ThrowIfNull(options.ListenEndPoint, nameof(options.ListenEndPoint)); @@ -90,14 +91,14 @@ namespace System.Net.Quic.Implementations.MsQuic _stateHandle = GCHandle.Alloc(_state); try { - QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerOpen( - MsQuicApi.Api.Registration.QuicHandle, - &NativeCallback, - (void*)GCHandle.ToIntPtr(_stateHandle), - &handle), "ListenerOpen failed"); - _state.Handle = new SafeMsQuicListenerHandle(handle); + uint status = MsQuicApi.Api.ListenerOpenDelegate( + MsQuicApi.Api.Registration, + s_listenerDelegate, + GCHandle.ToIntPtr(_stateHandle), + out _state.Handle); + + QuicExceptionHelpers.ThrowIfFailed(status, "ListenerOpen failed."); } catch { @@ -105,16 +106,17 @@ namespace System.Net.Quic.Implementations.MsQuic throw; } + _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.Handle} Listener created"); + NetEventSource.Info(_state, $"{_state.TraceId} Listener created"); } _listenEndPoint = Start(options); if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.Handle} Listener started"); + NetEventSource.Info(_state, $"{_state.TraceId} Listener started"); } } @@ -181,23 +183,19 @@ 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)"); - 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) + MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers); fixed (byte* paddress = address.Buffer) { - ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerStart( - _state.Handle.QuicHandle, - msquicBuffers.Buffers, - (uint)applicationProtocols.Count, - (QuicAddr*)paddress), "ListenerStart failed"); + status = MsQuicApi.Api.ListenerStartDelegate(_state.Handle, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)applicationProtocols.Count, paddress); } } catch @@ -205,12 +203,18 @@ 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, QUIC_PARAM_LISTENER_LOCAL_ADDRESS); + return MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_LISTENER.LOCAL_ADDRESS); } - private unsafe Task StopAsync() + private Task StopAsync() { // TODO finalizers are called even if the object construction fails. if (_state == null) @@ -223,47 +227,47 @@ namespace System.Net.Quic.Implementations.MsQuic if (_state.Handle != null) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.ApiTable->ListenerStop(_state.Handle.QuicHandle); + MsQuicApi.Api.ListenerStopDelegate(_state.Handle); } return _state.StopCompletion.Task; } -#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) + private static unsafe uint NativeCallbackHandler( + IntPtr listener, + IntPtr context, + ListenerEvent* listenerEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); + GCHandle gcHandle = GCHandle.FromIntPtr(context); Debug.Assert(gcHandle.IsAllocated); Debug.Assert(gcHandle.Target is not null); var state = (State)gcHandle.Target; - if (listenerEvent->Type == QUIC_LISTENER_EVENT_TYPE.STOP_COMPLETE) + if (listenerEvent->Type == QUIC_LISTENER_EVENT.STOP_COMPLETE) { state.StopCompletion.TrySetResult(); - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - if (listenerEvent->Type != QUIC_LISTENER_EVENT_TYPE.NEW_CONNECTION) + if (listenerEvent->Type != QUIC_LISTENER_EVENT.NEW_CONNECTION) { - return QUIC_STATUS_INTERNAL_ERROR; + return MsQuicStatusCodes.InternalError; } SafeMsQuicConnectionHandle? connectionHandle = null; MsQuicConnection? msQuicConnection = null; try { - ref QUIC_NEW_CONNECTION_INFO connectionInfo = ref *listenerEvent->NEW_CONNECTION.Info; + ref NewConnectionInfo connectionInfo = ref *listenerEvent->Data.NewConnection.Info; - IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.LocalAddress); - IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.RemoteAddress); + IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.LocalAddress); + IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.RemoteAddress); string targetHost = string.Empty; // compat with SslStream - if (connectionInfo.ServerNameLength > 0 && (IntPtr)connectionInfo.ServerName != IntPtr.Zero) + if (connectionInfo.ServerNameLength > 0 && connectionInfo.ServerName != IntPtr.Zero) { // TBD We should figure out what to do with international names. - targetHost = Marshal.PtrToStringAnsi((IntPtr)connectionInfo.ServerName, connectionInfo.ServerNameLength); + targetHost = Marshal.PtrToStringAnsi(connectionInfo.ServerName, connectionInfo.ServerNameLength); } SafeMsQuicConfigurationHandle? connectionConfiguration = state.ConnectionConfiguration; @@ -287,25 +291,25 @@ namespace System.Net.Quic.Implementations.MsQuic if (connectionConfiguration == null) { // We don't have safe handle yet so MsQuic will cleanup new connection. - return QUIC_STATUS_INTERNAL_ERROR; + return MsQuicStatusCodes.InternalError; } } - connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->NEW_CONNECTION.Connection); + connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->Data.NewConnection.Connection); Debug.Assert(!Monitor.IsEntered(state), "!Monitor.IsEntered(state)"); - int status = MsQuicApi.Api.ApiTable->ConnectionSetConfiguration(connectionHandle.QuicHandle, connectionConfiguration.QuicHandle); - if (StatusSucceeded(status)) + uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, connectionConfiguration); + if (MsQuicStatusHelper.SuccessfulStatusCode(status)) { msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, state, connectionHandle, state.AuthenticationOptions.ClientCertificateRequired, state.AuthenticationOptions.CertificateRevocationCheckMode, state.AuthenticationOptions.RemoteCertificateValidationCallback); - msQuicConnection.SetNegotiatedAlpn((IntPtr)connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); + msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength); if (!state.PendingConnections.TryAdd(connectionHandle.DangerousGetHandle(), msQuicConnection)) { msQuicConnection.Dispose(); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } // If we fall-through here something wrong happened. @@ -314,14 +318,14 @@ namespace System.Net.Quic.Implementations.MsQuic { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {listenerEvent->Type} connection callback: {ex}"); + NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {(QUIC_LISTENER_EVENT)listenerEvent->Type} connection callback: {ex}"); } } // This handle will be cleaned up by MsQuic by returning InternalError. connectionHandle?.SetHandleAsInvalid(); msQuicConnection?.Dispose(); - return QUIC_STATUS_INTERNAL_ERROR; + return MsQuicStatusCodes.InternalError; } 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 7af82fe..ff98028 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,18 +5,19 @@ 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 Microsoft.Quic; -using static Microsoft.Quic.MsQuic; +using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods; 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(); @@ -37,6 +38,7 @@ 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; @@ -44,7 +46,7 @@ namespace System.Net.Quic.Implementations.MsQuic public long ReadErrorCode = -1; // filled when ReadState.BuffersAvailable: - public QUIC_BUFFER[] ReceiveQuicBuffers = Array.Empty(); + public QuicBuffer[] ReceiveQuicBuffers = Array.Empty(); public int ReceiveQuicBuffersCount; public int ReceiveQuicBuffersTotalBytes; public bool ReceiveIsFinal; @@ -65,7 +67,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; @@ -87,7 +89,7 @@ namespace System.Net.Quic.Implementations.MsQuic public void Cleanup() { - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handles."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handles."); ShutdownState = ShutdownState.Finished; CleanupSendState(this); @@ -99,8 +101,10 @@ namespace System.Net.Quic.Implementations.MsQuic } } + internal string TraceId() => _state.TraceId; + // inbound. - internal unsafe MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) + internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags) { if (!connectionState.TryAddStream(this)) { @@ -125,11 +129,10 @@ namespace System.Net.Quic.Implementations.MsQuic try { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - delegate* unmanaged[Cdecl] nativeCallback = &NativeCallback; - MsQuicApi.Api.ApiTable->SetCallbackHandler( - _state.Handle.QuicHandle, - nativeCallback, - (void*)GCHandle.ToIntPtr(_state.StateGCHandle)); + MsQuicApi.Api.SetCallbackHandlerDelegate( + _state.Handle, + s_streamDelegate, + GCHandle.ToIntPtr(_state.StateGCHandle)); } catch { @@ -138,17 +141,18 @@ namespace System.Net.Quic.Implementations.MsQuic throw; } + _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, - $"{_state.Handle} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + - $"in connection {_state.ConnectionState.Handle}."); + $"{TraceId()} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + + $"in connection {_state.ConnectionState.TraceId}."); } } // outbound. - internal unsafe MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags) + internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags) { Debug.Assert(connectionState.Handle != null); @@ -171,23 +175,21 @@ namespace System.Net.Quic.Implementations.MsQuic try { - QUIC_HANDLE* handle; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - int status = MsQuicApi.Api.ApiTable->StreamOpen( - connectionState.Handle.QuicHandle, + uint status = MsQuicApi.Api.StreamOpenDelegate( + connectionState.Handle, flags, - &NativeCallback, - (void*)GCHandle.ToIntPtr(_state.StateGCHandle), - &handle); + s_streamDelegate, + GCHandle.ToIntPtr(_state.StateGCHandle), + out _state.Handle); - if (status == QUIC_STATUS_ABORTED) + if (status == MsQuicStatusCodes.Aborted) { // connection already aborted by peer, throw relevant exception throw ThrowHelper.GetConnectionAbortedException(connectionState.AbortErrorCode); } - ThrowIfFailure(status, "Failed to open stream to peer"); - _state.Handle = new SafeMsQuicStreamHandle(handle); + QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer."); } catch { @@ -196,12 +198,13 @@ namespace System.Net.Quic.Implementations.MsQuic throw; } + _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle); if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info( _state, - $"{_state.Handle} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + - $"in connection {_state.ConnectionState.Handle}."); + $"{_state.TraceId} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " + + $"in connection {_state.ConnectionState.TraceId}."); } } @@ -434,7 +437,7 @@ namespace System.Net.Quic.Implementations.MsQuic if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(_state, $"{_state.Handle} Stream reading into Memory of '{destination.Length}' bytes."); + NetEventSource.Info(_state, $"{TraceId()} Stream reading into Memory of '{destination.Length}' bytes."); } ReadState initialReadState; // value before transitions @@ -573,7 +576,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) { @@ -581,7 +584,7 @@ namespace System.Net.Quic.Implementations.MsQuic } int originalDestinationLength = destinationBuffer.Length; - QUIC_BUFFER nativeBuffer; + QuicBuffer nativeBuffer; int takeLength; int i = 0; @@ -668,13 +671,11 @@ namespace System.Net.Quic.Implementations.MsQuic StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_SEND, errorCode); } - private unsafe void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) + private void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamShutdown( - _state.Handle.QuicHandle, - flags, - (uint)errorCode), "StreamShutdown failed"); + uint status = MsQuicApi.Api.StreamShutdownDelegate(_state.Handle, flags, errorCode); + QuicExceptionHelpers.ThrowIfFailed(status, "StreamShutdown failed."); } internal override async ValueTask ShutdownCompleted(CancellationToken cancellationToken = default) @@ -842,7 +843,7 @@ namespace System.Net.Quic.Implementations.MsQuic } - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposing {disposing}"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposing {disposing}"); bool callShutdown = false; bool abortRead = false; @@ -876,27 +877,24 @@ namespace System.Net.Quic.Implementations.MsQuic } } - if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed) + if (callShutdown) { - if (callShutdown) + try { - try - { - // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE. - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); - } - catch (ObjectDisposedException) { }; + // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE. + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0); } + catch (ObjectDisposedException) { }; + } - if (abortRead) + if (abortRead) + { + try { - try - { - // TODO: error code used here MUST be specified by the application layer - StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff); - } - catch (ObjectDisposedException) { }; + // TODO: error code used here MUST be specified by the application layer + StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff); } + catch (ObjectDisposedException) { }; } if (completeRead) @@ -910,32 +908,33 @@ namespace System.Net.Quic.Implementations.MsQuic _state.Cleanup(); } - if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposed"); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposed"); } - private unsafe void EnableReceive() + private void EnableReceive() { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamReceiveSetEnabled(_state.Handle.QuicHandle, 1), "StreamReceiveSetEnabled failed"); + uint status = MsQuicApi.Api.StreamReceiveSetEnabledDelegate(_state.Handle, enabled: true); + QuicExceptionHelpers.ThrowIfFailed(status, "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. /// -#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) + private static unsafe uint NativeCallbackHandler( + IntPtr stream, + IntPtr context, + StreamEvent* streamEvent) { - GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context); + GCHandle gcHandle = GCHandle.FromIntPtr(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.Handle} Stream received event {streamEvent->Type}"); + NetEventSource.Info(state, $"{state.TraceId} Stream received event {streamEvent->Type}"); } try @@ -974,29 +973,29 @@ namespace System.Net.Quic.Implementations.MsQuic case QUIC_STREAM_EVENT_TYPE.PEER_ACCEPTED: return HandleEventPeerAccepted(state); default: - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } } catch (Exception ex) { if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); + NetEventSource.Error(state, $"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); } - Debug.Fail($"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); + Debug.Fail($"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}"); - return QUIC_STATUS_INTERNAL_ERROR; + return MsQuicStatusCodes.InternalError; } } - private static unsafe int HandleEventReceive(State state, ref QUIC_STREAM_EVENT streamEvent) + private static unsafe uint HandleEventReceive(State state, ref StreamEvent evt) { - ref var receiveEvent = ref streamEvent.RECEIVE; + ref StreamEventDataReceive receiveEvent = ref evt.Data.Receive; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.Handle} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) ? " with FIN flag" : "")}"); + NetEventSource.Info(state, $"{state.TraceId} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) ? " with FIN flag" : "")}"); } int readLength; @@ -1021,12 +1020,12 @@ namespace System.Net.Quic.Implementations.MsQuic if ((uint)state.ReceiveQuicBuffers.Length < receiveEvent.BufferCount) { - QUIC_BUFFER[] oldReceiveBuffers = state.ReceiveQuicBuffers; - state.ReceiveQuicBuffers = ArrayPool.Shared.Rent((int)receiveEvent.BufferCount); + QuicBuffer[] 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); } } @@ -1049,13 +1048,13 @@ namespace System.Net.Quic.Implementations.MsQuic } // if it was not a graceful shutdown, we defer aborting to PEER_SEND_ABORT event handler - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.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 QUIC_STATUS_PENDING; + return MsQuicStatusCodes.Pending; } case ReadState.PendingRead: @@ -1067,7 +1066,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) @@ -1084,7 +1083,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 QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } } @@ -1097,15 +1096,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. - int ret = (uint)readLength == receiveEvent.TotalBufferLength - ? QUIC_STATUS_SUCCESS - : QUIC_STATUS_CONTINUE; + uint ret = (uint)readLength == receiveEvent.TotalBufferLength + ? MsQuicStatusCodes.Success + : MsQuicStatusCodes.Continue; receiveEvent.TotalBufferLength = (uint)readLength; return ret; } - private static int HandleEventPeerRecvAborted(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt) { bool shouldSendComplete = false; bool shouldShutdownWriteComplete = false; @@ -1123,7 +1122,7 @@ namespace System.Net.Quic.Implementations.MsQuic } state.SendState = SendState.Aborted; - state.SendErrorCode = (long)streamEvent.PEER_RECEIVE_ABORTED.ErrorCode; + state.SendErrorCode = (long)evt.Data.PeerReceiveAborted.ErrorCode; } if (shouldSendComplete) @@ -1138,26 +1137,26 @@ namespace System.Net.Quic.Implementations.MsQuic ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.SendErrorCode))); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventStartComplete(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventStartComplete(State state, ref StreamEvent evt) { - int status = streamEvent.START_COMPLETE.Status; + uint status = evt.Data.StartComplete.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 != QUIC_STATUS_SUCCESS) + if (status != MsQuicStatusCodes.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 == QUIC_STATUS_ABORTED) + if (status == MsQuicStatusCodes.Aborted) { state.StartCompletionSource.TrySetException( ExceptionDispatchInfo.SetCurrentStackTrace(GetConnectionAbortedException(state))); @@ -1167,10 +1166,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 MsQuicException(status, "StreamStart failed"))); + ExceptionDispatchInfo.SetCurrentStackTrace(new QuicException($"StreamStart finished with status {MsQuicStatusCodes.GetError(status)}"))); } } - else if ((streamEvent.START_COMPLETE.PeerAccepted & 1) != 0) + else if ((evt.Data.StartComplete.PeerAccepted & 1) != 0) { // Start succeeded and we were within stream limits, stream already usable. state.StartCompletionSource.TrySetResult(); @@ -1178,10 +1177,10 @@ namespace System.Net.Quic.Implementations.MsQuic // if PeerAccepted == 0, we will later receive PEER_ACCEPTED event, which will // complete the StartCompletionSource - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventSendShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent evt) { // Graceful will be false in three situations: // 1. The peer aborted reads and the PEER_RECEIVE_ABORTED event was raised. @@ -1192,7 +1191,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 (streamEvent.SEND_SHUTDOWN_COMPLETE.Graceful != 0) + if (evt.Data.SendShutdownComplete.Graceful != 0) { bool shouldComplete = false; lock (state) @@ -1210,12 +1209,12 @@ namespace System.Net.Quic.Implementations.MsQuic } } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt) { - var shutdownCompleteEvent = streamEvent.SHUTDOWN_COMPLETE; + StreamEventDataShutdownComplete shutdownCompleteEvent = evt.Data.ShutdownComplete; if (shutdownCompleteEvent.ConnectionShutdown != 0) { @@ -1229,7 +1228,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.Handle} Stream completing resettable event source."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source."); shouldReadComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted); @@ -1291,22 +1290,22 @@ namespace System.Net.Quic.Implementations.MsQuic state.Cleanup(); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventPeerAccepted(State state) + private static uint HandleEventPeerAccepted(State state) { state.StartCompletionSource.TrySetResult(); - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventPeerSendAborted(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventPeerSendAborted(State state, ref StreamEvent evt) { bool shouldComplete = false; lock (state) { shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.Aborted); - state.ReadErrorCode = (long)streamEvent.PEER_SEND_ABORTED.ErrorCode; + state.ReadErrorCode = (long)evt.Data.PeerSendAborted.ErrorCode; } if (shouldComplete) @@ -1315,17 +1314,17 @@ namespace System.Net.Quic.Implementations.MsQuic ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.ReadErrorCode))); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventPeerSendShutdown(State state) + private static uint 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.Handle} Stream completing resettable event source."); + if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source."); shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted); } @@ -1335,12 +1334,12 @@ namespace System.Net.Quic.Implementations.MsQuic state.ReceiveResettableCompletionSource.Complete(0); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } - private static int HandleEventSendComplete(State state, ref QUIC_STREAM_EVENT streamEvent) + private static uint HandleEventSendComplete(State state, ref StreamEvent evt) { - var sendCompleteEvent = streamEvent.SEND_COMPLETE; + StreamEventDataSendComplete sendCompleteEvent = evt.Data.SendComplete; bool canceled = sendCompleteEvent.Canceled != 0; bool complete = false; @@ -1365,7 +1364,7 @@ namespace System.Net.Quic.Implementations.MsQuic if (!canceled) { - state.SendResettableCompletionSource.Complete(QUIC_STATUS_SUCCESS); + state.SendResettableCompletionSource.Complete(MsQuicStatusCodes.Success); } else { @@ -1382,7 +1381,7 @@ namespace System.Net.Quic.Implementations.MsQuic } } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } private static void CleanupSendState(State state) @@ -1417,11 +1416,11 @@ namespace System.Net.Quic.Implementations.MsQuic MemoryHandle handle = buffer.Pin(); if (_state.SendQuicBuffers == IntPtr.Zero) { - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER)); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer)); _state.SendBufferMaxCount = 1; } - QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; + QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; quicBuffers->Length = (uint)buffer.Length; quicBuffers->Buffer = (byte*)handle.Pointer; @@ -1429,23 +1428,24 @@ namespace System.Net.Quic.Implementations.MsQuic _state.SendBufferCount = 1; Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - int status = MsQuicApi.Api.ApiTable->StreamSend( - _state.Handle.QuicHandle, + uint status = MsQuicApi.Api.StreamSendDelegate( + _state.Handle, quicBuffers, - 1, + bufferCount: 1, flags, - (void*)IntPtr.Zero); + IntPtr.Zero); - if (!StatusSucceeded(status)) + if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == QUIC_STATUS_ABORTED) + if (status == MsQuicStatusCodes.Aborted) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - ThrowIfFailure(status, "Could not send data to peer"); + QuicExceptionHelpers.ThrowIfFailed(status, + "Could not send data to peer."); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); @@ -1476,7 +1476,7 @@ namespace System.Net.Quic.Implementations.MsQuic { Marshal.FreeHGlobal(_state.SendQuicBuffers); _state.SendQuicBuffers = IntPtr.Zero; - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * count); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * count); _state.SendBufferMaxCount = count; _state.BufferArrays = new MemoryHandle[count]; } @@ -1484,7 +1484,7 @@ namespace System.Net.Quic.Implementations.MsQuic _state.SendBufferCount = count; count = 0; - QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; + QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; foreach (ReadOnlyMemory buffer in buffers) { MemoryHandle handle = buffer.Pin(); @@ -1495,23 +1495,24 @@ namespace System.Net.Quic.Implementations.MsQuic } Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - int status = MsQuicApi.Api.ApiTable->StreamSend( - _state.Handle.QuicHandle, + uint status = MsQuicApi.Api.StreamSendDelegate( + _state.Handle, quicBuffers, (uint)count, flags, - (void*)IntPtr.Zero); + IntPtr.Zero); - if (!StatusSucceeded(status)) + if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == QUIC_STATUS_ABORTED) + if (status == MsQuicStatusCodes.Aborted) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - ThrowIfFailure(status, "Could not send data to peer"); + QuicExceptionHelpers.ThrowIfFailed(status, + "Could not send data to peer."); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); @@ -1539,13 +1540,13 @@ namespace System.Net.Quic.Implementations.MsQuic { Marshal.FreeHGlobal(_state.SendQuicBuffers); _state.SendQuicBuffers = IntPtr.Zero; - _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * array.Length); + _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * array.Length); _state.SendBufferMaxCount = array.Length; _state.BufferArrays = new MemoryHandle[array.Length]; } _state.SendBufferCount = array.Length; - QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers; + QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers; for (int i = 0; i < length; i++) { ReadOnlyMemory buffer = array[i]; @@ -1558,38 +1559,39 @@ namespace System.Net.Quic.Implementations.MsQuic } Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - int status = MsQuicApi.Api.ApiTable->StreamSend( - _state.Handle.QuicHandle, + uint status = MsQuicApi.Api.StreamSendDelegate( + _state.Handle, quicBuffers, length, flags, - (void*)IntPtr.Zero); + IntPtr.Zero); - if (!StatusSucceeded(status)) + if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) { CleanupWriteFailedState(); CleanupSendState(_state); - if (status == QUIC_STATUS_ABORTED) + if (status == MsQuicStatusCodes.Aborted) { throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode); } - ThrowIfFailure(status, "Could not send data to peer"); + QuicExceptionHelpers.ThrowIfFailed(status, + "Could not send data to peer."); } return _state.SendResettableCompletionSource.GetTypelessValueTask(); } - private unsafe void ReceiveComplete(int bufferLength) + private void ReceiveComplete(int bufferLength) { Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)"); - MsQuicApi.Api.ApiTable->StreamReceiveComplete(_state.Handle.QuicHandle, (ulong)bufferLength); + MsQuicApi.Api.StreamReceiveCompleteDelegate(_state.Handle, (ulong)bufferLength); } // This can fail if the stream isn't started. private long GetStreamId() { - return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_STREAM_ID); + return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_STREAM.ID); } private void ThrowIfDisposed() @@ -1600,12 +1602,12 @@ namespace System.Net.Quic.Implementations.MsQuic } } - private static int HandleEventConnectionClose(State state) + private static uint HandleEventConnectionClose(State state) { long errorCode = state.ConnectionState.AbortErrorCode; if (NetEventSource.Log.IsEnabled()) { - NetEventSource.Info(state, $"{state.Handle} Stream handling connection {state.ConnectionState.Handle} close" + + NetEventSource.Info(state, $"{state.TraceId} Stream handling connection {state.ConnectionState.TraceId} close" + (errorCode != -1 ? $" with code {errorCode}" : "")); } @@ -1674,7 +1676,7 @@ namespace System.Net.Quic.Implementations.MsQuic state.Cleanup(); } - return QUIC_STATUS_SUCCESS; + return MsQuicStatusCodes.Success; } private static Exception GetConnectionAbortedException(State state) => @@ -1709,19 +1711,12 @@ namespace System.Net.Quic.Implementations.MsQuic ((State)state!).StartCompletionSource.TrySetCanceled(token); }, _state); - 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); - } + uint status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT); - if (!StatusSucceeded(status)) + if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) { - Exception exception = new MsQuicException(status, "Could not start stream"); - _state.StartCompletionSource.TrySetException(ExceptionDispatchInfo.SetCurrentStackTrace(exception)); - throw exception; + _state.StartCompletionSource.TrySetException(QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream.")); + throw QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream."); } 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 a848475..66d66f0 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,20 +2,11 @@ // 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 151eb54..4cd9745 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,12 +17,7 @@ namespace System.Net.Quic public QuicException(string? message, Exception? innerException, int result) : base(message, innerException) { - // 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; - } + 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 aa7eaa6..17793a6 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.ThrowsAnyAsync(() => TestConnection( + await Assert.ThrowsAsync(() => 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 0559db5..ca29a79 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -146,6 +146,7 @@ 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); @@ -187,6 +188,7 @@ 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(); @@ -237,7 +239,7 @@ namespace System.Net.Quic.Tests clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions); Task clientTask = clientConnection.ConnectAsync(cts.Token).AsTask(); - await Assert.ThrowsAnyAsync(() => clientTask); + await Assert.ThrowsAsync(() => clientTask); Assert.Equal(clientOptions.ClientAuthenticationOptions.TargetHost, receivedHostName); clientConnection.Dispose(); @@ -317,6 +319,12 @@ 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 411b5d3..644245d 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.ThrowsAnyAsync(() => OpenAndUseStreamAsync(serverConnection)); + await Assert.ThrowsAsync(() => 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 e7586a3..bacc79b 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -28,6 +28,7 @@ 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 7f4e03a..e6a7a12 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.