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
<Compile Include="System\Net\Quic\Implementations\Mock\*.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\*.cs" />
<Compile Include="System\Net\Quic\Implementations\MsQuic\Internal\*.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicAlpnHelper.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicEnums.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicNativeMethods.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusHelper.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicTraceHelper.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConfigurationHandle.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicConnectionHandle.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicListenerHandle.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicRegistrationHandle.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\SafeMsQuicStreamHandle.cs" />
- <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs">
- <Link>Common\DisableRuntimeMarshalling.cs</Link>
- </Compile>
+ <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\*.cs" />
<!-- System.Net common -->
+ <Compile Include="$(CommonPath)DisableRuntimeMarshalling.cs" Link="Common\DisableRuntimeMarshalling.cs" />
<Compile Include="$(CommonPath)System\Threading\Tasks\TaskToApm.cs" Link="Common\System\Threading\Tasks\TaskToApm.cs" />
<Compile Include="$(CommonPath)System\Net\ArrayBuffer.cs" Link="Common\System\Net\ArrayBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\MultiArrayBuffer.cs" Link="Common\System\Net\MultiArrayBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\StreamBuffer.cs" Link="Common\System\Net\StreamBuffer.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddress.cs" Link="Common\System\Net\SocketAddress.cs" />
<Compile Include="$(CommonPath)System\Net\IPAddressParserStatics.cs" Link="Common\System\Net\IPAddressParserStatics.cs" />
- <!-- System.Net.Internals -->
<Compile Include="$(CommonPath)System\Net\Internals\IPEndPointExtensions.cs" Link="Common\System\Net\Internals\IPEndPointExtensions.cs" />
</ItemGroup>
<!-- Unsupported platforms -->
<Compile Include="$(CommonPath)Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" Link="Common\Interop\Windows\SChannel\Interop.SECURITY_STATUS.cs" />
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Windows.cs" Link="Common\System\Net\Security\CertificateValidation.Windows.cs" />
<Compile Include="$(CommonPath)System\Net\SocketAddressPal.Windows.cs" Link="Common\System\Net\SocketAddressPal.Windows.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Windows.cs" />
</ItemGroup>
<!-- Unix (OSX + Linux) specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux' or '$(TargetPlatformIdentifier)' == 'OSX' or '$(TargetPlatformIdentifier)' == 'FreeBSD'">
</ItemGroup>
<!-- Linux specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'Linux'">
- <Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.Linux.cs" />
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
+ <Compile Include="$(CommonPath)Interop\Linux\Interop.Libraries.cs" Link="Common\Interop\Linux\Interop.Libraries.cs" />
</ItemGroup>
<!-- FreeBSD specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'FreeBSD' ">
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs" Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
<Compile Include="$(CommonPath)Interop\FreeBSD\Interop.Libraries.cs" Link="Common\Interop\FreeBSD\Interop.Libraries.cs" />
- <!-- Assume similarity with OSX for now -->
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
</ItemGroup>
<!-- OSX specific files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'OSX'">
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.OSX.cs" Link="Common\System\Net\Security\CertificateValidation.OSX.cs" />
<Compile Include="$(CommonPath)Interop\OSX\Interop.Libraries.cs" Link="Common\Interop\OSX\Interop.Libraries.cs" />
- <Compile Include="System\Net\Quic\Implementations\MsQuic\Interop\MsQuicStatusCodes.OSX.cs" />
</ItemGroup>
<!-- Project references -->
-
<ItemGroup>
<PackageReference Include="System.Net.MsQuic.Transport"
Version="$(SystemNetMsQuicTransportVersion)"
// 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;
-using System.Runtime.InteropServices;
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
-
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
internal static class MsQuicAddressHelpers
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
+using System.Text;
+using Microsoft.Quic;
+
+using static Microsoft.Quic.MsQuic;
#if TARGET_WINDOWS
using Microsoft.Win32;
#endif
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
-
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
internal sealed unsafe class MsQuicApi
{
+ private static readonly byte[] s_appName = Encoding.ASCII.GetBytes("System.Net.Quic");
+
private static readonly Version MinWindowsVersion = new Version(10, 0, 20145, 1000);
+ private static readonly Version MsQuicVersion = new Version(2, 0);
+
public SafeMsQuicRegistrationHandle Registration { get; }
+ public QUIC_API_TABLE* ApiTable { get; }
+
// This is workaround for a bug in ILTrimmer.
// Without these DynamicDependency attributes, .ctor() will be removed from the safe handles.
// Remove once fixed: https://github.com/mono/linker/issues/1660
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicListenerHandle))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicConnectionHandle))]
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(SafeMsQuicStreamHandle))]
- private MsQuicApi(NativeApi* vtable)
+ private MsQuicApi(QUIC_API_TABLE* apiTable)
{
- uint status;
-
- SetParamDelegate =
- new SetParamDelegate(new DelegateHelper(vtable->SetParam).SetParam);
-
- GetParamDelegate =
- new GetParamDelegate(new DelegateHelper(vtable->GetParam).GetParam);
-
- SetCallbackHandlerDelegate =
- new SetCallbackHandlerDelegate(new DelegateHelper(vtable->SetCallbackHandler).SetCallbackHandler);
-
- RegistrationOpenDelegate =
- new RegistrationOpenDelegate(new DelegateHelper(vtable->RegistrationOpen).RegistrationOpen);
- RegistrationCloseDelegate =
- Marshal.GetDelegateForFunctionPointer<RegistrationCloseDelegate>(
- vtable->RegistrationClose);
-
- ConfigurationOpenDelegate =
- new ConfigurationOpenDelegate(new DelegateHelper(vtable->ConfigurationOpen).ConfigurationOpen);
- ConfigurationCloseDelegate =
- Marshal.GetDelegateForFunctionPointer<ConfigurationCloseDelegate>(
- vtable->ConfigurationClose);
- ConfigurationLoadCredentialDelegate =
- new ConfigurationLoadCredentialDelegate(new DelegateHelper(vtable->ConfigurationLoadCredential).ConfigurationLoadCredential);
-
- ListenerOpenDelegate =
- new ListenerOpenDelegate(new DelegateHelper(vtable->ListenerOpen).ListenerOpen);
- ListenerCloseDelegate =
- Marshal.GetDelegateForFunctionPointer<ListenerCloseDelegate>(
- 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<ConnectionCloseDelegate>(
- 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<StreamCloseDelegate>(
- vtable->StreamClose);
- StreamStartDelegate =
- new StreamStartDelegate(new DelegateHelper(vtable->StreamStart).StreamStart);
- StreamShutdownDelegate =
- new StreamShutdownDelegate(new DelegateHelper(vtable->StreamShutdown).StreamShutdown);
- StreamSendDelegate =
- new StreamSendDelegate(new DelegateHelper(vtable->StreamSend).StreamSend);
- StreamReceiveCompleteDelegate =
- new StreamReceiveCompleteDelegate(new DelegateHelper(vtable->StreamReceiveComplete).StreamReceiveComplete);
- StreamReceiveSetEnabledDelegate =
- new StreamReceiveSetEnabledDelegate(new DelegateHelper(vtable->StreamReceiveSetEnabled).StreamReceiveSetEnabled);
-
- var cfg = new RegistrationConfig
+ ApiTable = apiTable;
+
+ fixed (byte* pAppName = s_appName)
{
- AppName = ".NET",
- ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
- };
+ var cfg = new QUIC_REGISTRATION_CONFIG {
+ AppName = (sbyte*)pAppName,
+ ExecutionProfile = QUIC_EXECUTION_PROFILE.LOW_LATENCY
+ };
- status = RegistrationOpenDelegate(ref cfg, out SafeMsQuicRegistrationHandle handle);
- QuicExceptionHelpers.ThrowIfFailed(status, "RegistrationOpen failed.");
+ QUIC_HANDLE* handle;
+ ThrowIfFailure(ApiTable->RegistrationOpen(&cfg, &handle), "RegistrationOpen failed");
- Registration = handle;
+ Registration = new SafeMsQuicRegistrationHandle(handle);
+ }
}
internal static MsQuicApi Api { get; } = null!;
internal static bool IsQuicSupported { get; }
- private const int MsQuicVersion = 2;
-
internal static bool Tls13MayBeDisabled { get; }
static MsQuicApi()
}
IntPtr msQuicHandle;
- if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
+ if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) ||
NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle))
{
try
{
if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpenVersion", out IntPtr msQuicOpenVersionAddress))
{
- NativeApi* vtable;
- delegate* unmanaged[Cdecl]<uint, NativeApi**, uint> msQuicOpenVersion =
- (delegate* unmanaged[Cdecl]<uint, NativeApi**, uint>)msQuicOpenVersionAddress;
- uint status = msQuicOpenVersion(MsQuicVersion, &vtable);
- if (MsQuicStatusHelper.SuccessfulStatusCode(status))
+ QUIC_API_TABLE* apiTable;
+ delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int> msQuicOpenVersion = (delegate* unmanaged[Cdecl]<uint, QUIC_API_TABLE**, int>)msQuicOpenVersionAddress;
+ if (StatusSucceeded(msQuicOpenVersion((uint)MsQuicVersion.Major, &apiTable)))
{
- IsQuicSupported = true;
- Api = new MsQuicApi(vtable);
+ int arraySize = 4;
+ uint* libVersion = stackalloc uint[arraySize];
+ uint size = (uint)arraySize * sizeof(uint);
+ if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion)))
+ {
+ var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]);
+ if (version >= MsQuicVersion)
+ {
+ Api = new MsQuicApi(apiTable);
+ IsQuicSupported = true;
+ }
+ else
+ {
+ if (NetEventSource.Log.IsEnabled())
+ {
+ NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'");
+ }
+ }
+ }
}
}
}
#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; }
}
}
--- /dev/null
+// 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;
+
+/// <summary>
+/// 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.
+/// </summary>
+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<MemoryHandle>();
+ _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);
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ /// <param name="inputs">Inputs to get their byte array, pin them and pepare them to be passed to MsQuic as QUIC_BUFFER*.</param>
+ /// <param name="toBuffer">Method extracting byte array from the inputs, e.g. applicationProtocol.Protocol.</param>
+ /// <typeparam name="T">The type of the inputs.</typeparam>
+ public void Initialize<T>(IList<T> inputs, Func<T, ReadOnlyMemory<byte>> 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<byte> buffer = toBuffer(inputs[i]);
+ MemoryHandle handle = buffer.Pin();
+
+ _handles[i] = handle;
+ _buffers[i].Buffer = (byte*)handle.Pointer;
+ _buffers[i].Length = (uint)buffer.Length;
+ }
+ }
+
+ /// <summary>
+ /// Unpins the managed memory and allows reuse of this struct.
+ /// </summary>
+ public void Reset()
+ {
+ for (int i = 0; i < _count; ++i)
+ {
+ _handles[i].Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Apart from unpinning the managed memory, it returns the shared buffer,
+ /// but most importantly it releases the unmanaged memory.
+ /// </summary>
+ public void Dispose()
+ {
+ Reset();
+ FreeNativeMemory();
+ }
+}
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Net.Sockets;
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
+using static Microsoft.Quic.MsQuic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
internal static class MsQuicParameterHelpers
{
- internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param)
+ internal static unsafe IPEndPoint GetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param)
{
// MsQuic always uses storage size as if IPv6 was used
uint valueLen = (uint)Internals.SocketAddress.IPv6AddressSize;
fixed (byte* paddress = &MemoryMarshal.GetReference(address))
{
- uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, paddress);
- QuicExceptionHelpers.ThrowIfFailed(status, "GetIPEndPointParam failed.");
+ ThrowIfFailure(api.ApiTable->GetParam(
+ nativeObject.QuicHandle,
+ param,
+ &valueLen,
+ paddress), "GetIPEndPointParam failed.");
}
address = address.Slice(0, (int)valueLen);
- return new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address)
- .GetIPEndPoint();
+ return new Internals.SocketAddress(SocketAddressPal.GetAddressFamily(address), address).GetIPEndPoint();
}
- internal static unsafe void SetIPEndPointParam(MsQuicApi api, SafeHandle nativeObject, uint param, IPEndPoint value)
+ internal static unsafe void SetIPEndPointParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, IPEndPoint value)
{
Internals.SocketAddress socketAddress = IPEndPointExtensions.Serialize(value);
fixed (byte* paddress = &MemoryMarshal.GetReference(address))
{
- QuicExceptionHelpers.ThrowIfFailed(
- api.SetParamDelegate(nativeObject, param, (uint)address.Length, paddress),
- "Could not set IPEndPoint");
+ ThrowIfFailure(api.ApiTable->SetParam(
+ nativeObject.QuicHandle,
+ param,
+ (uint)address.Length,
+ paddress), "Could not set IPEndPoint");
}
}
- internal static unsafe ushort GetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param)
+ internal static unsafe ushort GetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param)
{
ushort value;
uint valueLen = (uint)sizeof(ushort);
- uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte*)&value);
- QuicExceptionHelpers.ThrowIfFailed(status, "GetUShortParam failed.");
+ ThrowIfFailure(api.ApiTable->GetParam(
+ nativeObject.QuicHandle,
+ param,
+ &valueLen,
+ (byte*)&value), "GetUShortParam failed");
Debug.Assert(valueLen == sizeof(ushort));
return value;
}
- internal static unsafe void SetUShortParam(MsQuicApi api, SafeHandle nativeObject, uint param, ushort value)
+ internal static unsafe void SetUShortParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ushort value)
{
- QuicExceptionHelpers.ThrowIfFailed(
- api.SetParamDelegate(nativeObject, param, sizeof(ushort), (byte*)&value),
- "Could not set ushort.");
+ ThrowIfFailure(api.ApiTable->SetParam(
+ nativeObject.QuicHandle,
+ param,
+ sizeof(ushort),
+ (byte*)&value), "Could not set ushort");
}
- internal static unsafe ulong GetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param)
+ internal static unsafe ulong GetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param)
{
ulong value;
uint valueLen = (uint)sizeof(ulong);
- uint status = api.GetParamDelegate(nativeObject, param, ref valueLen, (byte*)&value);
- QuicExceptionHelpers.ThrowIfFailed(status, "GetULongParam failed.");
+ ThrowIfFailure(api.ApiTable->GetParam(
+ nativeObject.QuicHandle,
+ param,
+ &valueLen,
+ (byte*)&value), "GetULongParam failed");
Debug.Assert(valueLen == sizeof(ulong));
return value;
}
- internal static unsafe void SetULongParam(MsQuicApi api, SafeHandle nativeObject, uint param, ulong value)
+ internal static unsafe void SetULongParam(MsQuicApi api, MsQuicSafeHandle nativeObject, uint param, ulong value)
{
- QuicExceptionHelpers.ThrowIfFailed(
- api.SetParamDelegate(nativeObject, param, sizeof(ulong), (byte*)&value),
- "Could not set ulong.");
+ ThrowIfFailure(api.ApiTable->SetParam(
+ nativeObject.QuicHandle,
+ param,
+ sizeof(ulong),
+ (byte*)&value), "Could not set ulong");
}
}
}
+++ /dev/null
-// 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;
- }
- }
- }
-}
+++ /dev/null
-// 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<SslApplicationProtocol> alpnProtocols, [NotNull] out MemoryHandle[]? handles, [NotNull] out QuicBuffer[]? buffers)
- {
- handles = ArrayPool<MemoryHandle>.Shared.Rent(alpnProtocols.Count);
- buffers = ArrayPool<QuicBuffer>.Shared.Rent(alpnProtocols.Count);
-
- try
- {
- for (int i = 0; i < alpnProtocols.Count; ++i)
- {
- ReadOnlyMemory<byte> 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<MemoryHandle>.Shared.Return(notNullHandles);
- }
-
- if (buffers is QuicBuffer[] notNullBuffers)
- {
- buffers = null;
- ArrayPool<QuicBuffer>.Shared.Return(notNullBuffers);
- }
- }
- }
-}
+++ /dev/null
-// 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,
- }
-}
--- /dev/null
+// 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;
+ }
+ }
+}
+++ /dev/null
-// 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
-{
- /// <summary>
- /// Contains all native delegates and structs that are used with MsQuic.
- /// </summary>
- 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]<IntPtr, IntPtr, uint>)_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]<IntPtr, IntPtr>)_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]<IntPtr, IntPtr, IntPtr, void>)_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]<IntPtr, uint, uint, byte*, uint>)_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]<IntPtr, uint, uint*, byte*, uint>)_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]<RegistrationConfig.Native*, IntPtr*, uint>)_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]<IntPtr, QuicBuffer*, uint, QuicSettings*, uint, IntPtr, IntPtr*, uint>)_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]<IntPtr, CredentialConfig.Native*, uint>)_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]<IntPtr, IntPtr, IntPtr, IntPtr*, uint>)_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]<IntPtr, QuicBuffer*, uint, byte*, uint>)_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]<IntPtr, void>)_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]<IntPtr, IntPtr, IntPtr, IntPtr*, uint>)_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]<IntPtr, IntPtr, uint>)_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<byte>(__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]<IntPtr, IntPtr, QUIC_ADDRESS_FAMILY, byte*, ushort, uint>)_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]<IntPtr, QUIC_CONNECTION_SHUTDOWN_FLAGS, long, void>)_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]<IntPtr, QUIC_STREAM_OPEN_FLAGS, IntPtr, IntPtr, IntPtr*, uint>)_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]<IntPtr, QUIC_STREAM_START_FLAGS, uint>)_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]<IntPtr, QUIC_STREAM_SHUTDOWN_FLAGS, long, uint>)_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]<IntPtr, QuicBuffer*, uint, QUIC_SEND_FLAGS, IntPtr, uint>)_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]<IntPtr, ulong, void>)_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]<IntPtr, byte, uint>)_functionPointer)(__stream_gen_native, __enabled_gen_native);
- }
- finally
- {
- //
- // Cleanup
- //
- if (stream__addRefd)
- stream.DangerousRelease();
- }
-
- return __retVal;
- }
- }
- }
-}
--- /dev/null
+// 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<IntPtr> _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<IntPtr> 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
+ }
+}
+++ /dev/null
-// 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
- }
-}
+++ /dev/null
-// 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
- }
-}
+++ /dev/null
-// 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;
- }
-}
+++ /dev/null
-// 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}"
- };
- }
- }
-}
+++ /dev/null
-// 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;
- }
- }
-}
+++ /dev/null
-// 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");
- }
- }
-}
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
+using Microsoft.Quic;
+using static Microsoft.Quic.MsQuic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
- internal sealed class SafeMsQuicConfigurationHandle : SafeHandle
+ internal sealed class SafeMsQuicConfigurationHandle : MsQuicSafeHandle
{
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public SafeMsQuicConfigurationHandle()
- : base(IntPtr.Zero, ownsHandle: true)
+ public unsafe SafeMsQuicConfigurationHandle(QUIC_HANDLE* handle)
+ : base(handle, ptr => MsQuicApi.Api.ApiTable->ConfigurationClose((QUIC_HANDLE*)ptr), SafeHandleType.Configuration)
{ }
- protected override bool ReleaseHandle()
- {
- MsQuicApi.Api.ConfigurationCloseDelegate(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
-
// TODO: consider moving the static code from here to keep all the handle classes small and simple.
public static SafeMsQuicConfigurationHandle Create(QuicClientConnectionOptions options)
{
Debug.Assert(!MsQuicApi.Api.Registration.IsInvalid);
- var settings = new QuicSettings
- {
- IsSetFlags = QuicSettingsIsSetFlags.PeerBidiStreamCount |
- QuicSettingsIsSetFlags.PeerUnidiStreamCount,
- PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams,
- PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams
- };
+ QUIC_SETTINGS settings = default(QUIC_SETTINGS);
+ settings.IsSet.PeerUnidiStreamCount = 1;
+ settings.PeerUnidiStreamCount = (ushort)options.MaxUnidirectionalStreams;
+ settings.IsSet.PeerBidiStreamCount = 1;
+ settings.PeerBidiStreamCount = (ushort)options.MaxBidirectionalStreams;
+ settings.IsSet.IdleTimeoutMs = 1;
if (options.IdleTimeout != Timeout.InfiniteTimeSpan)
{
if (options.IdleTimeout <= TimeSpan.Zero) throw new Exception("IdleTimeout must not be negative.");
-
- ulong ms = (ulong)options.IdleTimeout.Ticks / TimeSpan.TicksPerMillisecond;
- if (ms > (1ul << 62) - 1) throw new Exception("IdleTimeout is too large (max 2^62-1 milliseconds)");
-
settings.IdleTimeoutMs = (ulong)options.IdleTimeout.TotalMilliseconds;
}
else
{
settings.IdleTimeoutMs = 0;
}
- settings.IsSetFlags |= QuicSettingsIsSetFlags.IdleTimeoutMs;
- uint status;
- SafeMsQuicConfigurationHandle? configurationHandle;
+ SafeMsQuicConfigurationHandle configurationHandle;
X509Certificate2[]? intermediates = null;
- MemoryHandle[]? handles = null;
- QuicBuffer[]? buffers = null;
- try
- {
- MsQuicAlpnHelper.Prepare(alpnProtocols, out handles, out buffers);
- status = MsQuicApi.Api.ConfigurationOpenDelegate(MsQuicApi.Api.Registration, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)alpnProtocols.Count, ref settings, (uint)sizeof(QuicSettings), context: IntPtr.Zero, out configurationHandle);
- }
- finally
- {
- MsQuicAlpnHelper.Return(ref handles, ref buffers);
- }
-
- QuicExceptionHelpers.ThrowIfFailed(status, "ConfigurationOpen failed.");
+ QUIC_HANDLE* handle;
+ using var msquicBuffers = new MsQuicBuffers();
+ msquicBuffers.Initialize(alpnProtocols, alpnProtocol => alpnProtocol.Protocol);
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->ConfigurationOpen(
+ MsQuicApi.Api.Registration.QuicHandle,
+ msquicBuffers.Buffers,
+ (uint)alpnProtocols.Count,
+ &settings,
+ (uint)sizeof(QUIC_SETTINGS),
+ (void*)IntPtr.Zero,
+ &handle), "ConfigurationOpen failed");
+ configurationHandle = new SafeMsQuicConfigurationHandle(handle);
try
{
- CredentialConfig config = default;
+ QUIC_CREDENTIAL_CONFIG config = default;
config.Flags = flags; // TODO: consider using LOAD_ASYNCHRONOUS with a callback.
if (cipherSuitesPolicy != null)
intermediates = certificateContext.IntermediateCertificates;
}
+ int status;
if (certificate != null)
{
if (OperatingSystem.IsWindows())
{
- config.Type = QUIC_CREDENTIAL_TYPE.CONTEXT;
- config.Certificate = certificate.Handle;
- status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config);
+ config.Type = QUIC_CREDENTIAL_TYPE.CERTIFICATE_CONTEXT;
+ config.CertificateContext = (void*)certificate.Handle;
+ status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config);
}
else
{
- CredentialConfigCertificatePkcs12 pkcs12Config;
byte[] asn1;
if (intermediates?.Length > 0)
asn1 = certificate.Export(X509ContentType.Pkcs12);
}
- fixed (void* ptr = asn1)
+ fixed (byte* ptr = asn1)
{
- pkcs12Config.Asn1Blob = (IntPtr)ptr;
- pkcs12Config.Asn1BlobLength = (uint)asn1.Length;
- pkcs12Config.PrivateKeyPassword = IntPtr.Zero;
-
- config.Type = QUIC_CREDENTIAL_TYPE.PKCS12;
- config.Certificate = (IntPtr)(&pkcs12Config);
- status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config);
+ QUIC_CERTIFICATE_PKCS12 pkcs12Config = new QUIC_CERTIFICATE_PKCS12
+ {
+ Asn1Blob = ptr,
+ Asn1BlobLength = (uint)asn1.Length,
+ PrivateKeyPassword = (sbyte*)IntPtr.Zero
+ };
+
+ config.Type = QUIC_CREDENTIAL_TYPE.CERTIFICATE_PKCS12;
+ config.CertificatePkcs12 = &pkcs12Config;
+ status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config);
}
}
}
else
{
config.Type = QUIC_CREDENTIAL_TYPE.NONE;
- status = MsQuicApi.Api.ConfigurationLoadCredentialDelegate(configurationHandle, ref config);
+ status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config);
}
#if TARGET_WINDOWS
if ((Interop.SECURITY_STATUS)status == Interop.SECURITY_STATUS.AlgorithmMismatch && MsQuicApi.Tls13MayBeDisabled)
{
- throw new QuicException(SR.net_ssl_app_protocols_invalid, null, (int)status);
+ throw new MsQuicException(status, SR.net_ssl_app_protocols_invalid);
}
#endif
- QuicExceptionHelpers.ThrowIfFailed(status, "ConfigurationLoadCredential failed.");
+ ThrowIfFailure(status, "ConfigurationLoadCredential failed");
}
catch
{
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.InteropServices;
+using Microsoft.Quic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
- internal sealed class SafeMsQuicConnectionHandle : SafeHandle
+ internal sealed class SafeMsQuicConnectionHandle : MsQuicSafeHandle
{
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public SafeMsQuicConnectionHandle()
- : base(IntPtr.Zero, ownsHandle: true)
+ public unsafe SafeMsQuicConnectionHandle(QUIC_HANDLE* handle)
+ : base(handle, ptr => MsQuicApi.Api.ApiTable->ConnectionClose((QUIC_HANDLE*)ptr), SafeHandleType.Connection)
{ }
-
- public SafeMsQuicConnectionHandle(IntPtr connectionHandle)
- : this()
- {
- SetHandle(connectionHandle);
- }
-
- protected override bool ReleaseHandle()
- {
- MsQuicApi.Api.ConnectionCloseDelegate(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.InteropServices;
+using Microsoft.Quic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
- internal sealed class SafeMsQuicListenerHandle : SafeHandle
+ internal sealed class SafeMsQuicListenerHandle : MsQuicSafeHandle
{
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public SafeMsQuicListenerHandle()
- : base(IntPtr.Zero, ownsHandle: true)
+ public unsafe SafeMsQuicListenerHandle(QUIC_HANDLE* handle)
+ : base(handle, ptr => MsQuicApi.Api.ApiTable->ListenerClose((QUIC_HANDLE*)ptr), SafeHandleType.Listener)
{ }
-
- protected override bool ReleaseHandle()
- {
- MsQuicApi.Api.ListenerCloseDelegate(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.InteropServices;
+using Microsoft.Quic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
- internal sealed class SafeMsQuicRegistrationHandle : SafeHandle
+ internal sealed class SafeMsQuicRegistrationHandle : MsQuicSafeHandle
{
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public SafeMsQuicRegistrationHandle()
- : base(IntPtr.Zero, ownsHandle: true)
+ public unsafe SafeMsQuicRegistrationHandle(QUIC_HANDLE* handle)
+ : base(handle, ptr => MsQuicApi.Api.ApiTable->RegistrationClose((QUIC_HANDLE*)ptr), SafeHandleType.Registration)
{ }
-
- protected override bool ReleaseHandle()
- {
- MsQuicApi.Api.RegistrationCloseDelegate(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System.Runtime.InteropServices;
+using Microsoft.Quic;
namespace System.Net.Quic.Implementations.MsQuic.Internal
{
- internal sealed class SafeMsQuicStreamHandle : SafeHandle
+ internal sealed class SafeMsQuicStreamHandle : MsQuicSafeHandle
{
- public override bool IsInvalid => handle == IntPtr.Zero;
-
- public SafeMsQuicStreamHandle()
- : base(IntPtr.Zero, ownsHandle: true)
+ public unsafe SafeMsQuicStreamHandle(QUIC_HANDLE* handle)
+ : base(handle, ptr => MsQuicApi.Api.ApiTable->StreamClose((QUIC_HANDLE*)ptr), SafeHandleType.Stream)
{ }
-
- public SafeMsQuicStreamHandle(IntPtr streamHandle)
- : this()
- {
- SetHandle(streamHandle);
- }
-
- protected override bool ReleaseHandle()
- {
- MsQuicApi.Api.StreamCloseDelegate(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
}
}
--- /dev/null
+#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<byte> 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;
+ }
+
+ /// <summary>Defines the type of a member as it was used in the native signature.</summary>
+ [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;
+
+ /// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
+ /// <param name="name">The name of the type that was used in the native signature.</param>
+ public NativeTypeNameAttribute(string name)
+ {
+ _name = name;
+ }
+
+ /// <summary>Gets the name of the type that was used in the native signature.</summary>
+ 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;
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+#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]<QUIC_HANDLE*, void*, int, void> 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]<QUIC_HANDLE*, void*, void> SetContext;
+
+ [NativeTypeName("QUIC_GET_CONTEXT_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*> GetContext;
+
+ [NativeTypeName("QUIC_SET_CALLBACK_HANDLER_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, void*, void> SetCallbackHandler;
+
+ [NativeTypeName("QUIC_SET_PARAM_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, uint, uint, void*, int> SetParam;
+
+ [NativeTypeName("QUIC_GET_PARAM_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, uint, uint*, void*, int> GetParam;
+
+ [NativeTypeName("QUIC_REGISTRATION_OPEN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_REGISTRATION_CONFIG*, QUIC_HANDLE**, int> RegistrationOpen;
+
+ [NativeTypeName("QUIC_REGISTRATION_CLOSE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> RegistrationClose;
+
+ [NativeTypeName("QUIC_REGISTRATION_SHUTDOWN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_CONNECTION_SHUTDOWN_FLAGS, ulong, void> RegistrationShutdown;
+
+ [NativeTypeName("QUIC_CONFIGURATION_OPEN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_BUFFER*, uint, QUIC_SETTINGS*, uint, void*, QUIC_HANDLE**, int> ConfigurationOpen;
+
+ [NativeTypeName("QUIC_CONFIGURATION_CLOSE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> ConfigurationClose;
+
+ [NativeTypeName("QUIC_CONFIGURATION_LOAD_CREDENTIAL_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_CREDENTIAL_CONFIG*, int> ConfigurationLoadCredential;
+
+ [NativeTypeName("QUIC_LISTENER_OPEN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, QUIC_LISTENER_EVENT*, int>, void*, QUIC_HANDLE**, int> ListenerOpen;
+
+ [NativeTypeName("QUIC_LISTENER_CLOSE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> ListenerClose;
+
+ [NativeTypeName("QUIC_LISTENER_START_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_BUFFER*, uint, QuicAddr*, int> ListenerStart;
+
+ [NativeTypeName("QUIC_LISTENER_STOP_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> ListenerStop;
+
+ [NativeTypeName("QUIC_CONNECTION_OPEN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, QUIC_CONNECTION_EVENT*, int>, void*, QUIC_HANDLE**, int> ConnectionOpen;
+
+ [NativeTypeName("QUIC_CONNECTION_CLOSE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> ConnectionClose;
+
+ [NativeTypeName("QUIC_CONNECTION_SHUTDOWN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_CONNECTION_SHUTDOWN_FLAGS, ulong, void> ConnectionShutdown;
+
+ [NativeTypeName("QUIC_CONNECTION_START_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_HANDLE*, ushort, sbyte*, ushort, int> ConnectionStart;
+
+ [NativeTypeName("QUIC_CONNECTION_SET_CONFIGURATION_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_HANDLE*, int> ConnectionSetConfiguration;
+
+ [NativeTypeName("QUIC_CONNECTION_SEND_RESUMPTION_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_SEND_RESUMPTION_FLAGS, ushort, byte*, int> ConnectionSendResumptionTicket;
+
+ [NativeTypeName("QUIC_STREAM_OPEN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_STREAM_OPEN_FLAGS, delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, QUIC_STREAM_EVENT*, int>, void*, QUIC_HANDLE**, int> StreamOpen;
+
+ [NativeTypeName("QUIC_STREAM_CLOSE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void> StreamClose;
+
+ [NativeTypeName("QUIC_STREAM_START_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_STREAM_START_FLAGS, int> StreamStart;
+
+ [NativeTypeName("QUIC_STREAM_SHUTDOWN_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_STREAM_SHUTDOWN_FLAGS, ulong, int> StreamShutdown;
+
+ [NativeTypeName("QUIC_STREAM_SEND_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_BUFFER*, uint, QUIC_SEND_FLAGS, void*, int> StreamSend;
+
+ [NativeTypeName("QUIC_STREAM_RECEIVE_COMPLETE_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, ulong, void> StreamReceiveComplete;
+
+ [NativeTypeName("QUIC_STREAM_RECEIVE_SET_ENABLED_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, byte, int> StreamReceiveSetEnabled;
+
+ [NativeTypeName("QUIC_DATAGRAM_SEND_FN")]
+ internal delegate* unmanaged[Cdecl]<QUIC_HANDLE*, QUIC_BUFFER*, uint, QUIC_SEND_FLAGS, void*, int> 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;
+ }
+}
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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;
+ }
+}
--- /dev/null
+#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;
+ }
+}
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;
using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
+using Microsoft.Quic;
+using static Microsoft.Quic.MsQuic;
namespace System.Net.Quic.Implementations.MsQuic
{
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;
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;
public MsQuicConnection? Connection;
public MsQuicListener.State? ListenerState;
- public TaskCompletionSource<uint>? ConnectTcs;
+ public TaskCompletionSource<int>? ConnectTcs;
// TODO: only allocate these when there is an outstanding shutdown.
- public readonly TaskCompletionSource<uint> ShutdownTcs = new TaskCompletionSource<uint>(TaskCreationOptions.RunContinuationsAsynchronously);
+ public readonly TaskCompletionSource<int> ShutdownTcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
public bool Connected;
public long AbortErrorCode = -1;
if (releaseHandles)
{
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handle after last stream.");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handle after last stream.");
Handle?.Dispose();
}
}
}
}
- internal string TraceId() => _state.TraceId;
-
// constructor for inbound connections
- public MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQuicListener.State listenerState, SafeMsQuicConnectionHandle handle, bool remoteCertificateRequired = false, X509RevocationMode revocationMode = X509RevocationMode.Offline, RemoteCertificateValidationCallback? remoteCertificateValidationCallback = null, ServerCertificateSelectionCallback? serverCertificateSelectionCallback = null)
+ public unsafe MsQuicConnection(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, MsQuicListener.State listenerState, SafeMsQuicConnectionHandle handle, bool remoteCertificateRequired = false, X509RevocationMode revocationMode = X509RevocationMode.Offline, RemoteCertificateValidationCallback? remoteCertificateValidationCallback = null, ServerCertificateSelectionCallback? serverCertificateSelectionCallback = null)
{
_state.Handle = handle;
_state.StateGCHandle = GCHandle.Alloc(_state);
try
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.SetCallbackHandlerDelegate(
- _state.Handle,
- s_connectionDelegate,
- GCHandle.ToIntPtr(_state.StateGCHandle));
+ delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, QUIC_CONNECTION_EVENT*, int> nativeCallback = &NativeCallback;
+ MsQuicApi.Api.ApiTable->SetCallbackHandler(
+ _state.Handle.QuicHandle,
+ nativeCallback,
+ (void*)GCHandle.ToIntPtr(_state.StateGCHandle));
}
catch
{
}
_state.ListenerState = listenerState;
- _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle);
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(_state, $"{TraceId()} Inbound connection created");
+ NetEventSource.Info(_state, $"{handle} Inbound connection created");
}
}
// constructor for outbound connections
- public MsQuicConnection(QuicClientConnectionOptions options)
+ public unsafe MsQuicConnection(QuicClientConnectionOptions options)
{
ArgumentNullException.ThrowIfNull(options.RemoteEndPoint, nameof(options.RemoteEndPoint));
_state.StateGCHandle = GCHandle.Alloc(_state);
try
{
+ QUIC_HANDLE* handle;
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.ConnectionOpenDelegate(
- MsQuicApi.Api.Registration,
- s_connectionDelegate,
- GCHandle.ToIntPtr(_state.StateGCHandle),
- out _state.Handle);
-
- QuicExceptionHelpers.ThrowIfFailed(status, "Could not open the connection.");
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->ConnectionOpen(
+ MsQuicApi.Api.Registration.QuicHandle,
+ &NativeCallback,
+ (void*)GCHandle.ToIntPtr(_state.StateGCHandle),
+ &handle), "Could not open the connection");
+ _state.Handle = new SafeMsQuicConnectionHandle(handle);
}
catch
{
throw;
}
- _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle);
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(_state, $"{TraceId()} Outbound connection created");
+ NetEventSource.Info(_state, $"{_state.Handle} Outbound connection created");
}
}
internal override bool Connected => _state.Connected;
- private static uint HandleEventConnected(State state, ref ConnectionEvent connectionEvent)
+ private static unsafe int HandleEventConnected(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
if (state.Connected)
{
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
if (state.IsServer)
// Move connection from pending to Accept queue and hand it out.
if (listenerState.AcceptConnectionQueue.Writer.TryWrite(connection))
{
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
// Listener is closed
connection.Dispose();
}
}
- return MsQuicStatusCodes.UserCanceled;
+ return QUIC_STATUS_USER_CANCELED;
}
else
{
Debug.Assert(state.Connection != null);
- state.Connection._localEndPoint = MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS);
- state.Connection.SetNegotiatedAlpn(connectionEvent.Data.Connected.NegotiatedAlpn, connectionEvent.Data.Connected.NegotiatedAlpnLength);
+ state.Connection._localEndPoint = MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, state.Handle, QUIC_PARAM_CONN_LOCAL_ADDRESS);
+ state.Connection.SetNegotiatedAlpn((IntPtr)connectionEvent.CONNECTED.NegotiatedAlpn, connectionEvent.CONNECTED.NegotiatedAlpnLength);
state.Connection = null;
state.Connected = true;
- state.ConnectTcs!.SetResult(MsQuicStatusCodes.Success);
+ state.ConnectTcs!.SetResult(QUIC_STATUS_SUCCESS);
state.ConnectTcs = null;
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventShutdownInitiatedByTransport(State state, ref ConnectionEvent connectionEvent)
+ private static int HandleEventShutdownInitiatedByTransport(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
if (!state.Connected && state.ConnectTcs != null)
{
Debug.Assert(state.Connection != null);
state.Connection = null;
- uint hresult = connectionEvent.Data.ShutdownInitiatedByTransport.Status;
- Exception ex = QuicExceptionHelpers.CreateExceptionForHResult(hresult, "Connection has been shutdown by transport.");
+ Exception ex = new MsQuicException(connectionEvent.SHUTDOWN_INITIATED_BY_TRANSPORT.Status, "Connection has been shutdown by transport");
state.ConnectTcs!.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex));
state.ConnectTcs = null;
}
// See: https://github.com/dotnet/runtime/issues/60133
state.AbortErrorCode = 0;
state.AcceptQueue.Writer.TryComplete();
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventShutdownInitiatedByPeer(State state, ref ConnectionEvent connectionEvent)
+ private static int HandleEventShutdownInitiatedByPeer(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
- state.AbortErrorCode = (long)connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode;
+ state.AbortErrorCode = (long)connectionEvent.SHUTDOWN_INITIATED_BY_PEER.ErrorCode;
state.AcceptQueue.Writer.TryComplete();
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventShutdownComplete(State state, ref ConnectionEvent connectionEvent)
+ private static int HandleEventShutdownComplete(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
// This is the final event on the connection, so free the GCHandle used by the event callback.
state.StateGCHandle.Free();
if (state.ListenerState != null)
{
- // This is inbound connection that never got connected - becasue of TLS validation or some other reason.
+ // This is inbound connection that never got connected - because of TLS validation or some other reason.
// Remove connection from pending queue and dispose it.
if (state.ListenerState.PendingConnections.TryRemove(state.Handle.DangerousGetHandle(), out MsQuicConnection? connection))
{
state.Connection = null;
- state.ShutdownTcs.SetResult(MsQuicStatusCodes.Success);
+ state.ShutdownTcs.SetResult(QUIC_STATUS_SUCCESS);
// Stop accepting new streams.
state.AcceptQueue.Writer.TryComplete();
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventNewStream(State state, ref ConnectionEvent connectionEvent)
+ private static unsafe int HandleEventNewStream(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
- var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.Data.PeerStreamStarted.Stream);
- if (!state.TryQueueNewStream(streamHandle, connectionEvent.Data.PeerStreamStarted.Flags))
+ var streamHandle = new SafeMsQuicStreamHandle(connectionEvent.PEER_STREAM_STARTED.Stream);
+ if (!state.TryQueueNewStream(streamHandle, connectionEvent.PEER_STREAM_STARTED.Flags))
{
// This will call StreamCloseDelegate and free the stream.
// We will return Success to the MsQuic to prevent double free.
streamHandle.Dispose();
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventStreamsAvailable(State state, ref ConnectionEvent connectionEvent)
+ private static int HandleEventStreamsAvailable(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventPeerCertificateReceived(State state, ref ConnectionEvent connectionEvent)
+ private static unsafe int HandleEventPeerCertificateReceived(State state, ref QUIC_CONNECTION_EVENT connectionEvent)
{
SslPolicyErrors sslPolicyErrors = SslPolicyErrors.None;
X509Chain? chain = null;
try
{
- if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle != IntPtr.Zero)
+ IntPtr certificateHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Certificate;
+ if (certificateHandle != IntPtr.Zero)
{
if (OperatingSystem.IsWindows())
{
- certificate = new X509Certificate2(connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle);
+ certificate = new X509Certificate2(certificateHandle);
}
else
{
unsafe
{
- ReadOnlySpan<QuicBuffer> quicBuffer = new ReadOnlySpan<QuicBuffer>((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateHandle, sizeof(QuicBuffer));
+ ReadOnlySpan<QUIC_BUFFER> quicBuffer = new ReadOnlySpan<QUIC_BUFFER>((void*)certificateHandle, sizeof(QUIC_BUFFER));
certificate = new X509Certificate2(new ReadOnlySpan<byte>(quicBuffer[0].Buffer, (int)quicBuffer[0].Length));
certificateBuffer = (IntPtr)quicBuffer[0].Buffer;
certificateLength = (int)quicBuffer[0].Length;
- if (connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle != IntPtr.Zero)
+ IntPtr chainHandle = (IntPtr)connectionEvent.PEER_CERTIFICATE_RECEIVED.Chain;
+ if (chainHandle != IntPtr.Zero)
{
- quicBuffer = new ReadOnlySpan<QuicBuffer>((void*)connectionEvent.Data.PeerCertificateReceived.PlatformCertificateChainHandle, sizeof(QuicBuffer));
+ quicBuffer = new ReadOnlySpan<QUIC_BUFFER>((void*)chainHandle, sizeof(QUIC_BUFFER));
if (quicBuffer[0].Length != 0 && quicBuffer[0].Buffer != null)
{
additionalCertificates = new X509Certificate2Collection();
if (certificate == null)
{
- if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.TraceId} Remote certificate required, but no remote certificate received");
+ if (NetEventSource.Log.IsEnabled() && state.RemoteCertificateRequired) NetEventSource.Error(state, $"{state.Handle} Remote certificate required, but no remote certificate received");
sslPolicyErrors |= SslPolicyErrors.RemoteCertificateNotAvailable;
}
else
state.RemoteCertificateValidationCallback = (_, _, _, _) => success;
if (!success && NetEventSource.Log.IsEnabled())
- NetEventSource.Error(state, $"{state.TraceId} Remote certificate rejected by verification callback");
+ NetEventSource.Error(state, $"{state.Handle} Remote certificate rejected by verification callback");
if (!success)
{
if (state.IsServer)
{
- return MsQuicStatusCodes.UserCanceled;
+ return QUIC_STATUS_USER_CANCELED;
}
throw new AuthenticationException(SR.net_quic_cert_custom_validation);
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
if (NetEventSource.Log.IsEnabled())
- NetEventSource.Info(state, $"{state.TraceId} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}");
+ NetEventSource.Info(state, $"{state.Handle} Certificate validation for '${certificate?.Subject}' finished with ${sslPolicyErrors}");
if (sslPolicyErrors != SslPolicyErrors.None)
{
if (state.IsServer)
{
- return MsQuicStatusCodes.HandshakeFailure;
+ return QUIC_STATUS_HANDSHAKE_FAILURE;
}
throw new AuthenticationException(SR.Format(SR.net_quic_cert_chain_validation, sslPolicyErrors));
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
catch (Exception ex)
{
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.TraceId} Certificate validation failed ${ex.Message}");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Error(state, $"{state.Handle} Certificate validation failed ${ex.Message}");
throw;
}
}
return stream;
}
- internal override ValueTask<QuicStreamProvider> OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL, cancellationToken);
- internal override ValueTask<QuicStreamProvider> OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default) => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.NONE, cancellationToken);
+ internal override ValueTask<QuicStreamProvider> OpenUnidirectionalStreamAsync(CancellationToken cancellationToken = default)
+ => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL, cancellationToken);
+ internal override ValueTask<QuicStreamProvider> OpenBidirectionalStreamAsync(CancellationToken cancellationToken = default)
+ => OpenStreamAsync(QUIC_STREAM_OPEN_FLAGS.NONE, cancellationToken);
internal override int GetRemoteAvailableUnidirectionalStreamCount()
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_UNIDI_STREAM_COUNT);
+ return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_UNIDI_STREAM_COUNT);
}
internal override int GetRemoteAvailableBidirectionalStreamCount()
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.LOCAL_BIDI_STREAM_COUNT);
+ return MsQuicParameterHelpers.GetUShortParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_LOCAL_BIDI_STREAM_COUNT);
}
- internal override ValueTask ConnectAsync(CancellationToken cancellationToken = default)
+ internal unsafe override ValueTask ConnectAsync(CancellationToken cancellationToken = default)
{
ThrowIfDisposed();
throw new InvalidOperationException($"{nameof(ConnectAsync)} must not be called on a connection obtained from a listener.");
}
- QUIC_ADDRESS_FAMILY af = _remoteEndPoint.AddressFamily switch
+ ushort af = _remoteEndPoint.AddressFamily switch
{
- AddressFamily.Unspecified => QUIC_ADDRESS_FAMILY.UNSPEC,
- AddressFamily.InterNetwork => QUIC_ADDRESS_FAMILY.INET,
- AddressFamily.InterNetworkV6 => QUIC_ADDRESS_FAMILY.INET6,
+ AddressFamily.Unspecified => (ushort)QUIC_ADDRESS_FAMILY_UNSPEC,
+ AddressFamily.InterNetwork => (ushort)QUIC_ADDRESS_FAMILY_INET,
+ AddressFamily.InterNetworkV6 => (ushort)QUIC_ADDRESS_FAMILY_INET6,
_ => throw new ArgumentException(SR.Format(SR.net_quic_unsupported_address_family, _remoteEndPoint.AddressFamily))
};
Debug.Assert(_state.StateGCHandle.IsAllocated);
_state.Connection = this;
- uint status;
string targetHost;
int port;
if (_remoteEndPoint is IPEndPoint ipEndPoint)
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, ipEndPoint);
+ MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_REMOTE_ADDRESS, ipEndPoint);
targetHost = _state.TargetHost ?? ((IPEndPoint)_remoteEndPoint).Address.ToString();
port = ((IPEndPoint)_remoteEndPoint).Port;
{
// This is form of IPAddress and _state.TargetHost is set to different string
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_CONN.REMOTE_ADDRESS, new IPEndPoint(address, port));
+ MsQuicParameterHelpers.SetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_CONN_REMOTE_ADDRESS, new IPEndPoint(address, port));
targetHost = _state.TargetHost!;
}
else
}
// 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<uint>(TaskCreationOptions.RunContinuationsAsynchronously);
+ var tcs = _state.ConnectTcs = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
+ IntPtr pTargetHost = Marshal.StringToCoTaskMemAnsi(targetHost);
try
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- status = MsQuicApi.Api.ConnectionStartDelegate(
- _state.Handle,
- _configuration,
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->ConnectionStart(
+ _state.Handle.QuicHandle,
+ _configuration.QuicHandle,
af,
- targetHost,
- (ushort)port);
-
- QuicExceptionHelpers.ThrowIfFailed(status, "Failed to connect to peer.");
+ (sbyte*)pTargetHost,
+ (ushort)port), "Failed to connect to peer");
// this handle is ref counted by MsQuic, so safe to dispose here.
_configuration.Dispose();
_state.Connection = null;
throw;
}
+ finally
+ {
+ Marshal.FreeCoTaskMem(pTargetHost);
+ }
return new ValueTask(tcs.Task);
}
- private ValueTask ShutdownAsync(
+ private unsafe ValueTask ShutdownAsync(
QUIC_CONNECTION_SHUTDOWN_FLAGS Flags,
long ErrorCode)
{
try
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.ConnectionShutdownDelegate(
- _state.Handle,
+ MsQuicApi.Api.ApiTable->ConnectionShutdown(
+ _state.Handle.QuicHandle,
Flags,
- ErrorCode);
+ (ulong)ErrorCode);
}
catch
{
}
}
- private static unsafe uint NativeCallbackHandler(
- IntPtr connection,
- IntPtr context,
- ConnectionEvent* connectionEvent)
+#pragma warning disable CS3016
+ [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+#pragma warning restore CS3016
+ private static unsafe int NativeCallback(QUIC_HANDLE* connection, void* context, QUIC_CONNECTION_EVENT* connectionEvent)
{
- GCHandle gcHandle = GCHandle.FromIntPtr(context);
+ GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(state, $"{state.TraceId} Connection received event {connectionEvent->Type}");
+ NetEventSource.Info(state, $"{state.Handle} Connection received event {connectionEvent->Type}");
}
try
case QUIC_CONNECTION_EVENT_TYPE.PEER_CERTIFICATE_RECEIVED:
return HandleEventPeerCertificateReceived(state, ref *connectionEvent);
default:
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
}
catch (Exception ex)
{
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Error(state, $"{state.TraceId} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}");
+ NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}");
}
if (state.ConnectTcs != null)
}
else
{
- Debug.Fail($"{state.TraceId} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}");
+ Debug.Fail($"{state.Handle} Exception occurred during handling {connectionEvent->Type} connection callback: {ex}");
}
// TODO: trigger an exception on any outstanding async calls.
- return MsQuicStatusCodes.InternalError;
+ return QUIC_STATUS_INTERNAL_ERROR;
}
}
}
}
- private void Dispose(bool disposing)
+ private unsafe void Dispose(bool disposing)
{
int disposed = Interlocked.Exchange(ref _disposed, 1);
if (disposed != 0)
return;
}
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Connection disposing {disposing}");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Connection disposing {disposing}");
// If we haven't already shutdown gracefully (via a successful CloseAsync call), then force an abortive shutdown.
if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed)
{
// Handle can be null if outbound constructor failed and we are called from finalizer.
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.ConnectionShutdownDelegate(
- _state.Handle,
+ MsQuicApi.Api.ApiTable->ConnectionShutdown(
+ _state.Handle.QuicHandle,
QUIC_CONNECTION_SHUTDOWN_FLAGS.SILENT,
0);
}
_configuration?.Dispose();
if (releaseHandles)
{
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Connection releasing handle");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Connection releasing handle");
// We may not be fully initialized if constructor fails.
_state.Handle?.Dispose();
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;
{
// 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);
}
}
- internal MsQuicListener(QuicListenerOptions options)
+ internal unsafe MsQuicListener(QuicListenerOptions options)
{
ArgumentNullException.ThrowIfNull(options.ListenEndPoint, nameof(options.ListenEndPoint));
_stateHandle = GCHandle.Alloc(_state);
try
{
+ QUIC_HANDLE* handle;
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.ListenerOpenDelegate(
- MsQuicApi.Api.Registration,
- s_listenerDelegate,
- GCHandle.ToIntPtr(_stateHandle),
- out _state.Handle);
-
- QuicExceptionHelpers.ThrowIfFailed(status, "ListenerOpen failed.");
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerOpen(
+ MsQuicApi.Api.Registration.QuicHandle,
+ &NativeCallback,
+ (void*)GCHandle.ToIntPtr(_stateHandle),
+ &handle), "ListenerOpen failed");
+ _state.Handle = new SafeMsQuicListenerHandle(handle);
}
catch
{
throw;
}
- _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle);
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(_state, $"{_state.TraceId} Listener created");
+ NetEventSource.Info(_state, $"{_state.Handle} Listener created");
}
_listenEndPoint = Start(options);
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(_state, $"{_state.TraceId} Listener started");
+ NetEventSource.Info(_state, $"{_state.Handle} Listener started");
}
}
Internals.SocketAddress address = IPEndPointExtensions.Serialize(listenEndPoint);
- uint status;
-
Debug.Assert(_stateHandle.IsAllocated);
-
- MemoryHandle[]? handles = null;
- QuicBuffer[]? buffers = null;
try
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicAlpnHelper.Prepare(applicationProtocols, out handles, out buffers);
+ using var msquicBuffers = new MsQuicBuffers();
+ msquicBuffers.Initialize(applicationProtocols, applicationProtocol => applicationProtocol.Protocol);
+ // TODO: is the layout same for SocketAddress.Buffer and QuicAddr?
+ // TODO: maybe add simple extensions/helpers:
+ // - QuicAddr ToQuicAddr(this IPEndPoint ipEndPoint)
+ // - IPEndPoint ToIPEndPoint(this ref QuicAddr quicAddress)
fixed (byte* paddress = address.Buffer)
{
- status = MsQuicApi.Api.ListenerStartDelegate(_state.Handle, (QuicBuffer*)Marshal.UnsafeAddrOfPinnedArrayElement(buffers, 0), (uint)applicationProtocols.Count, paddress);
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->ListenerStart(
+ _state.Handle.QuicHandle,
+ msquicBuffers.Buffers,
+ (uint)applicationProtocols.Count,
+ (QuicAddr*)paddress), "ListenerStart failed");
}
}
catch
_stateHandle.Free();
throw;
}
- finally
- {
- MsQuicAlpnHelper.Return(ref handles, ref buffers);
- }
-
- QuicExceptionHelpers.ThrowIfFailed(status, "ListenerStart failed.");
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- return MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_LISTENER.LOCAL_ADDRESS);
+ return MsQuicParameterHelpers.GetIPEndPointParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_LISTENER_LOCAL_ADDRESS);
}
- private Task StopAsync()
+ private unsafe Task StopAsync()
{
// TODO finalizers are called even if the object construction fails.
if (_state == null)
if (_state.Handle != null)
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.ListenerStopDelegate(_state.Handle);
+ MsQuicApi.Api.ApiTable->ListenerStop(_state.Handle.QuicHandle);
}
return _state.StopCompletion.Task;
}
- private static unsafe uint NativeCallbackHandler(
- IntPtr listener,
- IntPtr context,
- ListenerEvent* listenerEvent)
+#pragma warning disable CS3016
+ [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+#pragma warning restore CS3016
+ private static unsafe int NativeCallback(QUIC_HANDLE* listener, void* context, QUIC_LISTENER_EVENT* listenerEvent)
{
- GCHandle gcHandle = GCHandle.FromIntPtr(context);
+ GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;
- if (listenerEvent->Type == QUIC_LISTENER_EVENT.STOP_COMPLETE)
+ if (listenerEvent->Type == QUIC_LISTENER_EVENT_TYPE.STOP_COMPLETE)
{
state.StopCompletion.TrySetResult();
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- if (listenerEvent->Type != QUIC_LISTENER_EVENT.NEW_CONNECTION)
+ if (listenerEvent->Type != QUIC_LISTENER_EVENT_TYPE.NEW_CONNECTION)
{
- return MsQuicStatusCodes.InternalError;
+ return QUIC_STATUS_INTERNAL_ERROR;
}
SafeMsQuicConnectionHandle? connectionHandle = null;
MsQuicConnection? msQuicConnection = null;
try
{
- ref NewConnectionInfo connectionInfo = ref *listenerEvent->Data.NewConnection.Info;
+ ref QUIC_NEW_CONNECTION_INFO connectionInfo = ref *listenerEvent->NEW_CONNECTION.Info;
- IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.LocalAddress);
- IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(connectionInfo.RemoteAddress);
+ IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.LocalAddress);
+ IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint((IntPtr)connectionInfo.RemoteAddress);
string targetHost = string.Empty; // compat with SslStream
- if (connectionInfo.ServerNameLength > 0 && connectionInfo.ServerName != IntPtr.Zero)
+ if (connectionInfo.ServerNameLength > 0 && (IntPtr)connectionInfo.ServerName != IntPtr.Zero)
{
// TBD We should figure out what to do with international names.
- targetHost = Marshal.PtrToStringAnsi(connectionInfo.ServerName, connectionInfo.ServerNameLength);
+ targetHost = Marshal.PtrToStringAnsi((IntPtr)connectionInfo.ServerName, connectionInfo.ServerNameLength);
}
SafeMsQuicConfigurationHandle? connectionConfiguration = state.ConnectionConfiguration;
if (connectionConfiguration == null)
{
// We don't have safe handle yet so MsQuic will cleanup new connection.
- return MsQuicStatusCodes.InternalError;
+ return QUIC_STATUS_INTERNAL_ERROR;
}
}
- connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->Data.NewConnection.Connection);
+ connectionHandle = new SafeMsQuicConnectionHandle(listenerEvent->NEW_CONNECTION.Connection);
Debug.Assert(!Monitor.IsEntered(state), "!Monitor.IsEntered(state)");
- uint status = MsQuicApi.Api.ConnectionSetConfigurationDelegate(connectionHandle, connectionConfiguration);
- if (MsQuicStatusHelper.SuccessfulStatusCode(status))
+ int status = MsQuicApi.Api.ApiTable->ConnectionSetConfiguration(connectionHandle.QuicHandle, connectionConfiguration.QuicHandle);
+ if (StatusSucceeded(status))
{
msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, state, connectionHandle, state.AuthenticationOptions.ClientCertificateRequired, state.AuthenticationOptions.CertificateRevocationCheckMode, state.AuthenticationOptions.RemoteCertificateValidationCallback);
- msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength);
+ msQuicConnection.SetNegotiatedAlpn((IntPtr)connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength);
if (!state.PendingConnections.TryAdd(connectionHandle.DangerousGetHandle(), msQuicConnection))
{
msQuicConnection.Dispose();
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
// If we fall-through here something wrong happened.
{
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {(QUIC_LISTENER_EVENT)listenerEvent->Type} connection callback: {ex}");
+ NetEventSource.Error(state, $"[Listener#{state.GetHashCode()}] Exception occurred during handling {listenerEvent->Type} connection callback: {ex}");
}
}
// This handle will be cleaned up by MsQuic by returning InternalError.
connectionHandle?.SetHandleAsInvalid();
msQuicConnection?.Dispose();
- return MsQuicStatusCodes.InternalError;
+ return QUIC_STATUS_INTERNAL_ERROR;
}
private void ThrowIfDisposed()
using System.Diagnostics;
using System.IO;
using System.Net.Quic.Implementations.MsQuic.Internal;
+using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
-using static System.Net.Quic.Implementations.MsQuic.Internal.MsQuicNativeMethods;
+using Microsoft.Quic;
+using static Microsoft.Quic.MsQuic;
namespace System.Net.Quic.Implementations.MsQuic
{
internal sealed class MsQuicStream : QuicStreamProvider
{
- // Delegate that wraps the static function that will be called when receiving an event.
- internal static unsafe readonly StreamCallbackDelegate s_streamDelegate = new StreamCallbackDelegate(NativeCallbackHandler);
-
// The state is passed to msquic and then it's passed back by msquic to the callback handler.
private readonly State _state = new State();
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;
public long ReadErrorCode = -1;
// filled when ReadState.BuffersAvailable:
- public QuicBuffer[] ReceiveQuicBuffers = Array.Empty<QuicBuffer>();
+ public QUIC_BUFFER[] ReceiveQuicBuffers = Array.Empty<QUIC_BUFFER>();
public int ReceiveQuicBuffersCount;
public int ReceiveQuicBuffersTotalBytes;
public bool ReceiveIsFinal;
public int SendBufferCount;
// Resettable completions to be used for multiple calls to send.
- public readonly ResettableCompletionSource<uint> SendResettableCompletionSource = new ResettableCompletionSource<uint>();
+ public readonly ResettableCompletionSource<int> SendResettableCompletionSource = new ResettableCompletionSource<int>();
public ShutdownWriteState ShutdownWriteState;
public void Cleanup()
{
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{TraceId} releasing handles.");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(this, $"{Handle} releasing handles.");
ShutdownState = ShutdownState.Finished;
CleanupSendState(this);
}
}
- internal string TraceId() => _state.TraceId;
-
// inbound.
- internal MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags)
+ internal unsafe MsQuicStream(MsQuicConnection.State connectionState, SafeMsQuicStreamHandle streamHandle, QUIC_STREAM_OPEN_FLAGS flags)
{
if (!connectionState.TryAddStream(this))
{
try
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.SetCallbackHandlerDelegate(
- _state.Handle,
- s_streamDelegate,
- GCHandle.ToIntPtr(_state.StateGCHandle));
+ delegate* unmanaged[Cdecl]<QUIC_HANDLE*, void*, QUIC_STREAM_EVENT*, int> nativeCallback = &NativeCallback;
+ MsQuicApi.Api.ApiTable->SetCallbackHandler(
+ _state.Handle.QuicHandle,
+ nativeCallback,
+ (void*)GCHandle.ToIntPtr(_state.StateGCHandle));
}
catch
{
throw;
}
- _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle);
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(
_state,
- $"{TraceId()} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " +
- $"in connection {_state.ConnectionState.TraceId}.");
+ $"{_state.Handle} Inbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " +
+ $"in connection {_state.ConnectionState.Handle}.");
}
}
// outbound.
- internal MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags)
+ internal unsafe MsQuicStream(MsQuicConnection.State connectionState, QUIC_STREAM_OPEN_FLAGS flags)
{
Debug.Assert(connectionState.Handle != null);
try
{
+ QUIC_HANDLE* handle;
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamOpenDelegate(
- connectionState.Handle,
+ int status = MsQuicApi.Api.ApiTable->StreamOpen(
+ connectionState.Handle.QuicHandle,
flags,
- s_streamDelegate,
- GCHandle.ToIntPtr(_state.StateGCHandle),
- out _state.Handle);
+ &NativeCallback,
+ (void*)GCHandle.ToIntPtr(_state.StateGCHandle),
+ &handle);
- if (status == MsQuicStatusCodes.Aborted)
+ if (status == QUIC_STATUS_ABORTED)
{
// connection already aborted by peer, throw relevant exception
throw ThrowHelper.GetConnectionAbortedException(connectionState.AbortErrorCode);
}
- QuicExceptionHelpers.ThrowIfFailed(status, "Failed to open stream to peer.");
+ ThrowIfFailure(status, "Failed to open stream to peer");
+ _state.Handle = new SafeMsQuicStreamHandle(handle);
}
catch
{
throw;
}
- _state.TraceId = MsQuicTraceHelper.GetTraceId(_state.Handle);
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Info(
_state,
- $"{_state.TraceId} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " +
- $"in connection {_state.ConnectionState.TraceId}.");
+ $"{_state.Handle} Outbound {(flags.HasFlag(QUIC_STREAM_OPEN_FLAGS.UNIDIRECTIONAL) ? "uni" : "bi")}directional stream created " +
+ $"in connection {_state.ConnectionState.Handle}.");
}
}
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(_state, $"{TraceId()} Stream reading into Memory of '{destination.Length}' bytes.");
+ NetEventSource.Info(_state, $"{_state.Handle} Stream reading into Memory of '{destination.Length}' bytes.");
}
ReadState initialReadState; // value before transitions
}
/// <returns>The number of bytes copied.</returns>
- private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan<QuicBuffer> sourceBuffers, Span<byte> destinationBuffer)
+ private static unsafe int CopyMsQuicBuffersToUserBuffer(ReadOnlySpan<QUIC_BUFFER> sourceBuffers, Span<byte> destinationBuffer)
{
if (sourceBuffers.Length == 0)
{
}
int originalDestinationLength = destinationBuffer.Length;
- QuicBuffer nativeBuffer;
+ QUIC_BUFFER nativeBuffer;
int takeLength;
int i = 0;
StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_SEND, errorCode);
}
- private void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode)
+ private unsafe void StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS flags, long errorCode)
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamShutdownDelegate(_state.Handle, flags, errorCode);
- QuicExceptionHelpers.ThrowIfFailed(status, "StreamShutdown failed.");
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamShutdown(
+ _state.Handle.QuicHandle,
+ flags,
+ (uint)errorCode), "StreamShutdown failed");
}
internal override async ValueTask ShutdownCompleted(CancellationToken cancellationToken = default)
}
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposing {disposing}");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposing {disposing}");
bool callShutdown = false;
bool abortRead = false;
}
}
- if (callShutdown)
+ if (_state.Handle != null && !_state.Handle.IsInvalid && !_state.Handle.IsClosed)
{
- try
+ if (callShutdown)
{
- // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE.
- StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0);
+ try
+ {
+ // Handle race condition when stream can be closed handling SHUTDOWN_COMPLETE.
+ StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.GRACEFUL, errorCode: 0);
+ }
+ catch (ObjectDisposedException) { };
}
- catch (ObjectDisposedException) { };
- }
- if (abortRead)
- {
- try
+ if (abortRead)
{
- // TODO: error code used here MUST be specified by the application layer
- StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff);
+ try
+ {
+ // TODO: error code used here MUST be specified by the application layer
+ StartShutdown(QUIC_STREAM_SHUTDOWN_FLAGS.ABORT_RECEIVE, 0xffffffff);
+ }
+ catch (ObjectDisposedException) { };
}
- catch (ObjectDisposedException) { };
}
if (completeRead)
_state.Cleanup();
}
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{TraceId()} Stream disposed");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(_state, $"{_state.Handle} Stream disposed");
}
- private void EnableReceive()
+ private unsafe void EnableReceive()
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamReceiveSetEnabledDelegate(_state.Handle, enabled: true);
- QuicExceptionHelpers.ThrowIfFailed(status, "StreamReceiveSetEnabled failed.");
+ ThrowIfFailure(MsQuicApi.Api.ApiTable->StreamReceiveSetEnabled(_state.Handle.QuicHandle, 1), "StreamReceiveSetEnabled failed");
}
/// <summary>
/// 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.
/// </summary>
- private static unsafe uint NativeCallbackHandler(
- IntPtr stream,
- IntPtr context,
- StreamEvent* streamEvent)
+#pragma warning disable CS3016
+ [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+#pragma warning restore CS3016
+ private static unsafe int NativeCallback(QUIC_HANDLE* stream, void* context, QUIC_STREAM_EVENT* streamEvent)
{
- GCHandle gcHandle = GCHandle.FromIntPtr(context);
+ GCHandle gcHandle = GCHandle.FromIntPtr((IntPtr)context);
Debug.Assert(gcHandle.IsAllocated);
Debug.Assert(gcHandle.Target is not null);
var state = (State)gcHandle.Target;
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(state, $"{state.TraceId} Stream received event {streamEvent->Type}");
+ NetEventSource.Info(state, $"{state.Handle} Stream received event {streamEvent->Type}");
}
try
case QUIC_STREAM_EVENT_TYPE.PEER_ACCEPTED:
return HandleEventPeerAccepted(state);
default:
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
}
catch (Exception ex)
{
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Error(state, $"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}");
+ NetEventSource.Error(state, $"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}");
}
- Debug.Fail($"{state.TraceId} Exception occurred during handling Stream {streamEvent->Type} event: {ex}");
+ Debug.Fail($"{state.Handle} Exception occurred during handling Stream {streamEvent->Type} event: {ex}");
- return MsQuicStatusCodes.InternalError;
+ return QUIC_STATUS_INTERNAL_ERROR;
}
}
- private static unsafe uint HandleEventReceive(State state, ref StreamEvent evt)
+ private static unsafe int HandleEventReceive(State state, ref QUIC_STREAM_EVENT streamEvent)
{
- ref StreamEventDataReceive receiveEvent = ref evt.Data.Receive;
+ ref var receiveEvent = ref streamEvent.RECEIVE;
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(state, $"{state.TraceId} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) ? " with FIN flag" : "")}");
+ NetEventSource.Info(state, $"{state.Handle} Stream received {receiveEvent.TotalBufferLength} bytes{(receiveEvent.Flags.HasFlag(QUIC_RECEIVE_FLAGS.FIN) ? " with FIN flag" : "")}");
}
int readLength;
if ((uint)state.ReceiveQuicBuffers.Length < receiveEvent.BufferCount)
{
- QuicBuffer[] oldReceiveBuffers = state.ReceiveQuicBuffers;
- state.ReceiveQuicBuffers = ArrayPool<QuicBuffer>.Shared.Rent((int)receiveEvent.BufferCount);
+ QUIC_BUFFER[] oldReceiveBuffers = state.ReceiveQuicBuffers;
+ state.ReceiveQuicBuffers = ArrayPool<QUIC_BUFFER>.Shared.Rent((int)receiveEvent.BufferCount);
if (oldReceiveBuffers.Length != 0) // don't return Array.Empty.
{
- ArrayPool<QuicBuffer>.Shared.Return(oldReceiveBuffers);
+ ArrayPool<QUIC_BUFFER>.Shared.Return(oldReceiveBuffers);
}
}
}
// if it was not a graceful shutdown, we defer aborting to PEER_SEND_ABORT event handler
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
else
{
// Normal RECEIVE - data will be buffered until user calls ReadAsync() and no new event will be issued until EnableReceive()
state.ReadState = ReadState.IndividualReadComplete;
- return MsQuicStatusCodes.Pending;
+ return QUIC_STATUS_PENDING;
}
case ReadState.PendingRead:
state.ReadState = ReadState.PendingReadFinished;
// state.ReadState will be set to None later once the ReceiveResettableCompletionSource is awaited.
- readLength = CopyMsQuicBuffersToUserBuffer(new ReadOnlySpan<QuicBuffer>(receiveEvent.Buffers, (int)receiveEvent.BufferCount), state.ReceiveUserBuffer.Span);
+ readLength = CopyMsQuicBuffersToUserBuffer(new ReadOnlySpan<QUIC_BUFFER>(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)
// There was a race between a user aborting the read stream and the callback being ran.
// This will eat any received data.
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
}
// Returning Success when the entire buffer hasn't been consumed will cause MsQuic to disable further receive events until EnableReceive() is called.
// Returning Continue will cause a second receive event to fire immediately after this returns, but allows MsQuic to clean up its buffers.
- uint ret = (uint)readLength == receiveEvent.TotalBufferLength
- ? MsQuicStatusCodes.Success
- : MsQuicStatusCodes.Continue;
+ int ret = (uint)readLength == receiveEvent.TotalBufferLength
+ ? QUIC_STATUS_SUCCESS
+ : QUIC_STATUS_CONTINUE;
receiveEvent.TotalBufferLength = (uint)readLength;
return ret;
}
- private static uint HandleEventPeerRecvAborted(State state, ref StreamEvent evt)
+ private static int HandleEventPeerRecvAborted(State state, ref QUIC_STREAM_EVENT streamEvent)
{
bool shouldSendComplete = false;
bool shouldShutdownWriteComplete = false;
}
state.SendState = SendState.Aborted;
- state.SendErrorCode = (long)evt.Data.PeerReceiveAborted.ErrorCode;
+ state.SendErrorCode = (long)streamEvent.PEER_RECEIVE_ABORTED.ErrorCode;
}
if (shouldSendComplete)
ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.SendErrorCode)));
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventStartComplete(State state, ref StreamEvent evt)
+ private static int HandleEventStartComplete(State state, ref QUIC_STREAM_EVENT streamEvent)
{
- uint status = evt.Data.StartComplete.Status;
+ int status = streamEvent.START_COMPLETE.Status;
// The way we expose Open(Uni|Bi)directionalStreamAsync operations is that the stream
// is also accepted by the peer (i.e. it is within advertised stream limits). However,
// We may receive START_COMPLETE notification before the stream is accepted, so we defer
// completing the StartcompletionSource until we get PeerAccepted notification.
- if (status != MsQuicStatusCodes.Success)
+ if (status != QUIC_STATUS_SUCCESS)
{
// Start irrecoverably failed. The possible status codes are:
// - Aborted - connection aborted by peer
// - InvalidState - stream already started before, or connection aborted locally
// - StreamLimitReached - only if QUIC_STREAM_START_FLAG_FAIL_BLOCKED was specified (not in our case).
//
- if (status == MsQuicStatusCodes.Aborted)
+ if (status == QUIC_STATUS_ABORTED)
{
state.StartCompletionSource.TrySetException(
ExceptionDispatchInfo.SetCurrentStackTrace(GetConnectionAbortedException(state)));
// TODO: Should we throw QuicOperationAbortedException when status is InvalidState?
// [ActiveIssue("https://github.com/dotnet/runtime/issues/55619")]
state.StartCompletionSource.TrySetException(
- ExceptionDispatchInfo.SetCurrentStackTrace(new QuicException($"StreamStart finished with status {MsQuicStatusCodes.GetError(status)}")));
+ ExceptionDispatchInfo.SetCurrentStackTrace(new MsQuicException(status, "StreamStart failed")));
}
}
- else if ((evt.Data.StartComplete.PeerAccepted & 1) != 0)
+ else if ((streamEvent.START_COMPLETE.PeerAccepted & 1) != 0)
{
// Start succeeded and we were within stream limits, stream already usable.
state.StartCompletionSource.TrySetResult();
// if PeerAccepted == 0, we will later receive PEER_ACCEPTED event, which will
// complete the StartCompletionSource
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventSendShutdownComplete(State state, ref StreamEvent evt)
+ private static int HandleEventSendShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent)
{
// Graceful will be false in three situations:
// 1. The peer aborted reads and the PEER_RECEIVE_ABORTED event was raised.
// SHUTDOWN_COMPLETE event will be raised immediately after this event. It will handle completing with an error.
//
// Only use this event with sends gracefully completed.
- if (evt.Data.SendShutdownComplete.Graceful != 0)
+ if (streamEvent.SEND_SHUTDOWN_COMPLETE.Graceful != 0)
{
bool shouldComplete = false;
lock (state)
}
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventShutdownComplete(State state, ref StreamEvent evt)
+ private static int HandleEventShutdownComplete(State state, ref QUIC_STREAM_EVENT streamEvent)
{
- StreamEventDataShutdownComplete shutdownCompleteEvent = evt.Data.ShutdownComplete;
+ var shutdownCompleteEvent = streamEvent.SHUTDOWN_COMPLETE;
if (shutdownCompleteEvent.ConnectionShutdown != 0)
{
lock (state)
{
// This event won't occur within the middle of a receive.
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source.");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.Handle} Stream completing resettable event source.");
shouldReadComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted);
state.Cleanup();
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventPeerAccepted(State state)
+ private static int HandleEventPeerAccepted(State state)
{
state.StartCompletionSource.TrySetResult();
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventPeerSendAborted(State state, ref StreamEvent evt)
+ private static int HandleEventPeerSendAborted(State state, ref QUIC_STREAM_EVENT streamEvent)
{
bool shouldComplete = false;
lock (state)
{
shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.Aborted);
- state.ReadErrorCode = (long)evt.Data.PeerSendAborted.ErrorCode;
+ state.ReadErrorCode = (long)streamEvent.PEER_SEND_ABORTED.ErrorCode;
}
if (shouldComplete)
ExceptionDispatchInfo.SetCurrentStackTrace(new QuicStreamAbortedException(state.ReadErrorCode)));
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventPeerSendShutdown(State state)
+ private static int HandleEventPeerSendShutdown(State state)
{
bool shouldComplete = false;
lock (state)
{
// This event won't occur within the middle of a receive.
- if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.TraceId} Stream completing resettable event source.");
+ if (NetEventSource.Log.IsEnabled()) NetEventSource.Info(state, $"{state.Handle} Stream completing resettable event source.");
shouldComplete = CleanupReadStateAndCheckPending(state, ReadState.ReadsCompleted);
}
state.ReceiveResettableCompletionSource.Complete(0);
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
- private static uint HandleEventSendComplete(State state, ref StreamEvent evt)
+ private static int HandleEventSendComplete(State state, ref QUIC_STREAM_EVENT streamEvent)
{
- StreamEventDataSendComplete sendCompleteEvent = evt.Data.SendComplete;
+ var sendCompleteEvent = streamEvent.SEND_COMPLETE;
bool canceled = sendCompleteEvent.Canceled != 0;
bool complete = false;
if (!canceled)
{
- state.SendResettableCompletionSource.Complete(MsQuicStatusCodes.Success);
+ state.SendResettableCompletionSource.Complete(QUIC_STATUS_SUCCESS);
}
else
{
}
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
private static void CleanupSendState(State state)
MemoryHandle handle = buffer.Pin();
if (_state.SendQuicBuffers == IntPtr.Zero)
{
- _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer));
+ _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER));
_state.SendBufferMaxCount = 1;
}
- QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers;
+ QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers;
quicBuffers->Length = (uint)buffer.Length;
quicBuffers->Buffer = (byte*)handle.Pointer;
_state.SendBufferCount = 1;
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamSendDelegate(
- _state.Handle,
+ int status = MsQuicApi.Api.ApiTable->StreamSend(
+ _state.Handle.QuicHandle,
quicBuffers,
- bufferCount: 1,
+ 1,
flags,
- IntPtr.Zero);
+ (void*)IntPtr.Zero);
- if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
+ if (!StatusSucceeded(status))
{
CleanupWriteFailedState();
CleanupSendState(_state);
- if (status == MsQuicStatusCodes.Aborted)
+ if (status == QUIC_STATUS_ABORTED)
{
throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode);
}
- QuicExceptionHelpers.ThrowIfFailed(status,
- "Could not send data to peer.");
+ ThrowIfFailure(status, "Could not send data to peer");
}
return _state.SendResettableCompletionSource.GetTypelessValueTask();
{
Marshal.FreeHGlobal(_state.SendQuicBuffers);
_state.SendQuicBuffers = IntPtr.Zero;
- _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * count);
+ _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * count);
_state.SendBufferMaxCount = count;
_state.BufferArrays = new MemoryHandle[count];
}
_state.SendBufferCount = count;
count = 0;
- QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers;
+ QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers;
foreach (ReadOnlyMemory<byte> buffer in buffers)
{
MemoryHandle handle = buffer.Pin();
}
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamSendDelegate(
- _state.Handle,
+ int status = MsQuicApi.Api.ApiTable->StreamSend(
+ _state.Handle.QuicHandle,
quicBuffers,
(uint)count,
flags,
- IntPtr.Zero);
+ (void*)IntPtr.Zero);
- if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
+ if (!StatusSucceeded(status))
{
CleanupWriteFailedState();
CleanupSendState(_state);
- if (status == MsQuicStatusCodes.Aborted)
+ if (status == QUIC_STATUS_ABORTED)
{
throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode);
}
- QuicExceptionHelpers.ThrowIfFailed(status,
- "Could not send data to peer.");
+ ThrowIfFailure(status, "Could not send data to peer");
}
return _state.SendResettableCompletionSource.GetTypelessValueTask();
{
Marshal.FreeHGlobal(_state.SendQuicBuffers);
_state.SendQuicBuffers = IntPtr.Zero;
- _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QuicBuffer) * array.Length);
+ _state.SendQuicBuffers = Marshal.AllocHGlobal(sizeof(QUIC_BUFFER) * array.Length);
_state.SendBufferMaxCount = array.Length;
_state.BufferArrays = new MemoryHandle[array.Length];
}
_state.SendBufferCount = array.Length;
- QuicBuffer* quicBuffers = (QuicBuffer*)_state.SendQuicBuffers;
+ QUIC_BUFFER* quicBuffers = (QUIC_BUFFER*)_state.SendQuicBuffers;
for (int i = 0; i < length; i++)
{
ReadOnlyMemory<byte> buffer = array[i];
}
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- uint status = MsQuicApi.Api.StreamSendDelegate(
- _state.Handle,
+ int status = MsQuicApi.Api.ApiTable->StreamSend(
+ _state.Handle.QuicHandle,
quicBuffers,
length,
flags,
- IntPtr.Zero);
+ (void*)IntPtr.Zero);
- if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
+ if (!StatusSucceeded(status))
{
CleanupWriteFailedState();
CleanupSendState(_state);
- if (status == MsQuicStatusCodes.Aborted)
+ if (status == QUIC_STATUS_ABORTED)
{
throw ThrowHelper.GetConnectionAbortedException(_state.ConnectionState.AbortErrorCode);
}
- QuicExceptionHelpers.ThrowIfFailed(status,
- "Could not send data to peer.");
+ ThrowIfFailure(status, "Could not send data to peer");
}
return _state.SendResettableCompletionSource.GetTypelessValueTask();
}
- private void ReceiveComplete(int bufferLength)
+ private unsafe void ReceiveComplete(int bufferLength)
{
Debug.Assert(!Monitor.IsEntered(_state), "!Monitor.IsEntered(_state)");
- MsQuicApi.Api.StreamReceiveCompleteDelegate(_state.Handle, (ulong)bufferLength);
+ MsQuicApi.Api.ApiTable->StreamReceiveComplete(_state.Handle.QuicHandle, (ulong)bufferLength);
}
// This can fail if the stream isn't started.
private long GetStreamId()
{
- return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, (uint)QUIC_PARAM_STREAM.ID);
+ return (long)MsQuicParameterHelpers.GetULongParam(MsQuicApi.Api, _state.Handle, QUIC_PARAM_STREAM_ID);
}
private void ThrowIfDisposed()
}
}
- private static uint HandleEventConnectionClose(State state)
+ private static int HandleEventConnectionClose(State state)
{
long errorCode = state.ConnectionState.AbortErrorCode;
if (NetEventSource.Log.IsEnabled())
{
- NetEventSource.Info(state, $"{state.TraceId} Stream handling connection {state.ConnectionState.TraceId} close" +
+ NetEventSource.Info(state, $"{state.Handle} Stream handling connection {state.ConnectionState.Handle} close" +
(errorCode != -1 ? $" with code {errorCode}" : ""));
}
state.Cleanup();
}
- return MsQuicStatusCodes.Success;
+ return QUIC_STATUS_SUCCESS;
}
private static Exception GetConnectionAbortedException(State state) =>
((State)state!).StartCompletionSource.TrySetCanceled(token);
}, _state);
- uint status = MsQuicApi.Api.StreamStartDelegate(_state.Handle, QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT);
+ int status;
+ unsafe
+ {
+ status = MsQuicApi.Api.ApiTable->StreamStart(
+ _state.Handle.QuicHandle,
+ QUIC_STREAM_START_FLAGS.SHUTDOWN_ON_FAIL | QUIC_STREAM_START_FLAGS.INDICATE_PEER_ACCEPT);
+ }
- if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
+ if (!StatusSucceeded(status))
{
- _state.StartCompletionSource.TrySetException(QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream."));
- throw QuicExceptionHelpers.CreateExceptionForHResult(status, "Could not start stream.");
+ Exception exception = new MsQuicException(status, "Could not start stream");
+ _state.StartCompletionSource.TrySetException(ExceptionDispatchInfo.SetCurrentStackTrace(exception));
+ throw exception;
}
await _state.StartCompletionSource.Task.ConfigureAwait(false);
// 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>(T value, ref string? result)
+ {
+ MsQuicSafeHandle? safeHandle = value as MsQuicSafeHandle;
+ if (safeHandle is not null)
+ {
+ result = safeHandle.ToString();
+ }
+ }
}
}
-// 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
public QuicException(string? message, Exception? innerException, int result)
: base(message, innerException)
{
- HResult = result;
+ // HResult 0 means OK, so do not override the default value set by Exception ctor,
+ // because in this case we don't have an HResult.
+ if (result != 0)
+ {
+ HResult = result;
+ }
}
}
}
[Fact]
public async Task MismatchedCipherPolicies_ConnectAsync_ThrowsQuicException()
{
- await Assert.ThrowsAsync<QuicException>(() => TestConnection(
+ await Assert.ThrowsAnyAsync<QuicException>(() => TestConnection(
new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_128_GCM_SHA256 }),
new CipherSuitesPolicy(new[] { TlsCipherSuite.TLS_AES_256_GCM_SHA384 })
));
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)]
public async Task CertificateCallbackThrowPropagates()
{
using CancellationTokenSource cts = new CancellationTokenSource(PassingTestTimeout);
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)]
public async Task ConnectWithCertificateCallback()
{
X509Certificate2 c1 = System.Net.Test.Common.Configuration.Certificates.GetServerCertificate();
clientConnection = new QuicConnection(QuicImplementationProviders.MsQuic, clientOptions);
Task clientTask = clientConnection.ConnectAsync(cts.Token).AsTask();
- await Assert.ThrowsAsync<QuicException>(() => clientTask);
+ await Assert.ThrowsAnyAsync<QuicException>(() => clientTask);
Assert.Equal(clientOptions.ClientAuthenticationOptions.TargetHost, receivedHostName);
clientConnection.Dispose();
{
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();
else
{
await Assert.ThrowsAsync<QuicOperationAbortedException>(async () => await serverConnection.AcceptStreamAsync());
- await Assert.ThrowsAsync<QuicException>(() => OpenAndUseStreamAsync(serverConnection));
+ await Assert.ThrowsAnyAsync<QuicException>(() => OpenAndUseStreamAsync(serverConnection));
}
});
}
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/runtime/issues/67301", TestPlatforms.Linux)]
public async Task Listener_Backlog_Success_IPv6()
{
await Task.Run(async () =>
},
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.