Sync shared code from runtime (#24630)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
github-actions[bot] 2020-08-06 21:26:32 +00:00 committed by GitHub
parent 6c35e2e84d
commit 973a97fc4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 249 additions and 173 deletions

View File

@ -11,7 +11,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal const ushort IPv4 = 2;
internal const ushort IPv6 = 23;
internal static unsafe IPEndPoint INetToIPEndPoint(SOCKADDR_INET inetAddress)
internal static unsafe IPEndPoint INetToIPEndPoint(ref SOCKADDR_INET inetAddress)
{
if (inetAddress.si_family == IPv4)
{

View File

@ -23,7 +23,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
try
{
uint status = Interop.MsQuic.MsQuicOpen(version: 1, out registration);
uint status = Interop.MsQuic.MsQuicOpen(out registration);
if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
{
throw new NotSupportedException(SR.net_quic_notsupported);
@ -123,7 +123,13 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
Marshal.GetDelegateForFunctionPointer<MsQuicNativeMethods.GetParamDelegate>(
nativeRegistration.GetParam);
RegistrationOpenDelegate(Encoding.UTF8.GetBytes("SystemNetQuic"), out IntPtr ctx);
var registrationConfig = new MsQuicNativeMethods.RegistrationConfig
{
AppName = "SystemNetQuic",
ExecutionProfile = QUIC_EXECUTION_PROFILE.QUIC_EXECUTION_PROFILE_LOW_LATENCY
};
RegistrationOpenDelegate(ref registrationConfig, out IntPtr ctx);
_registrationContext = ctx;
}
@ -312,15 +318,26 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
return secConfig;
}
public IntPtr SessionOpen(byte[] alpn)
public unsafe IntPtr SessionOpen(byte[] alpn)
{
IntPtr sessionPtr = IntPtr.Zero;
uint status;
uint status = SessionOpenDelegate(
_registrationContext,
alpn,
IntPtr.Zero,
ref sessionPtr);
fixed (byte* pAlpn = alpn)
{
var alpnBuffer = new MsQuicNativeMethods.QuicBuffer
{
Length = (uint)alpn.Length,
Buffer = pAlpn
};
status = SessionOpenDelegate(
_registrationContext,
&alpnBuffer,
1,
IntPtr.Zero,
ref sessionPtr);
}
QuicExceptionHelpers.ThrowIfFailed(status, "Could not open session.");

View File

@ -28,7 +28,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
QuicExceptionHelpers.ThrowIfFailed(MsQuicApi.Api.ConnectionOpenDelegate(
_nativeObjPtr,
MsQuicConnection.NativeCallbackHandler,
MsQuicConnection.s_connectionDelegate,
IntPtr.Zero,
out IntPtr connectionPtr),
"Could not open the connection.");
@ -83,15 +83,15 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
public void SetPeerBiDirectionalStreamCount(ushort count)
{
SetUshortParamter(QUIC_PARAM_SESSION.PEER_BIDI_STREAM_COUNT, count);
SetUshortParameter(QUIC_PARAM_SESSION.PEER_BIDI_STREAM_COUNT, count);
}
public void SetPeerUnidirectionalStreamCount(ushort count)
{
SetUshortParamter(QUIC_PARAM_SESSION.PEER_UNIDI_STREAM_COUNT, count);
SetUshortParameter(QUIC_PARAM_SESSION.PEER_UNIDI_STREAM_COUNT, count);
}
private unsafe void SetUshortParamter(QUIC_PARAM_SESSION param, ushort count)
private unsafe void SetUshortParameter(QUIC_PARAM_SESSION param, ushort count)
{
var buffer = new MsQuicNativeMethods.QuicBuffer()
{

View File

@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
#nullable enable
using System.Diagnostics;
using System.IO;
using System.Net.Quic.Implementations.MsQuic.Internal;
using System.Net.Security;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
@ -16,7 +18,7 @@ namespace System.Net.Quic.Implementations.MsQuic
{
internal sealed class MsQuicConnection : QuicConnectionProvider
{
private MsQuicSession? _session;
private readonly MsQuicSession? _session;
// Pointer to the underlying connection
// TODO replace all IntPtr with SafeHandles
@ -26,15 +28,17 @@ namespace System.Net.Quic.Implementations.MsQuic
private GCHandle _handle;
// Delegate that wraps the static function that will be called when receiving an event.
// TODO investigate if the delegate can be static instead.
private ConnectionCallbackDelegate? _connectionDelegate;
internal static readonly ConnectionCallbackDelegate s_connectionDelegate = new ConnectionCallbackDelegate(NativeCallbackHandler);
// Endpoint to either connect to or the endpoint already accepted.
private IPEndPoint? _localEndPoint;
private readonly IPEndPoint _remoteEndPoint;
private readonly ResettableCompletionSource<uint> _connectTcs = new ResettableCompletionSource<uint>();
private readonly ResettableCompletionSource<uint> _shutdownTcs = new ResettableCompletionSource<uint>();
private SslApplicationProtocol _negotiatedAlpnProtocol;
// TODO: only allocate these when there is an outstanding connect/shutdown.
private readonly TaskCompletionSource<uint> _connectTcs = new TaskCompletionSource<uint>();
private readonly TaskCompletionSource<uint> _shutdownTcs = new TaskCompletionSource<uint>();
private bool _disposed;
private bool _connected;
@ -54,6 +58,7 @@ namespace System.Net.Quic.Implementations.MsQuic
_localEndPoint = localEndPoint;
_remoteEndPoint = remoteEndPoint;
_ptr = nativeObjPtr;
_connected = true;
SetCallbackHandler();
SetIdleTimeout(TimeSpan.FromSeconds(120));
@ -89,125 +94,96 @@ namespace System.Net.Quic.Implementations.MsQuic
internal override IPEndPoint RemoteEndPoint => new IPEndPoint(_remoteEndPoint.Address, _remoteEndPoint.Port);
internal override SslApplicationProtocol NegotiatedApplicationProtocol => throw new NotImplementedException();
internal override SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedAlpnProtocol;
internal override bool Connected => _connected;
internal uint HandleEvent(ref ConnectionEvent connectionEvent)
{
uint status = MsQuicStatusCodes.Success;
try
{
switch (connectionEvent.Type)
{
// Connection is connected, can start to create streams.
case QUIC_CONNECTION_EVENT.CONNECTED:
{
status = HandleEventConnected(
connectionEvent);
}
break;
// Connection is being closed by the transport
return HandleEventConnected(ref connectionEvent);
case QUIC_CONNECTION_EVENT.SHUTDOWN_INITIATED_BY_TRANSPORT:
{
status = HandleEventShutdownInitiatedByTransport(
connectionEvent);
}
break;
// Connection is being closed by the peer
return HandleEventShutdownInitiatedByTransport(ref connectionEvent);
case QUIC_CONNECTION_EVENT.SHUTDOWN_INITIATED_BY_PEER:
{
status = HandleEventShutdownInitiatedByPeer(
connectionEvent);
}
break;
// Connection has been shutdown
return HandleEventShutdownInitiatedByPeer(ref connectionEvent);
case QUIC_CONNECTION_EVENT.SHUTDOWN_COMPLETE:
{
status = HandleEventShutdownComplete(
connectionEvent);
}
break;
return HandleEventShutdownComplete(ref connectionEvent);
case QUIC_CONNECTION_EVENT.PEER_STREAM_STARTED:
{
status = HandleEventNewStream(
connectionEvent);
}
break;
return HandleEventNewStream(ref connectionEvent);
case QUIC_CONNECTION_EVENT.STREAMS_AVAILABLE:
{
status = HandleEventStreamsAvailable(
connectionEvent);
}
break;
return HandleEventStreamsAvailable(ref connectionEvent);
default:
break;
return MsQuicStatusCodes.Success;
}
}
catch (Exception)
catch (Exception ex)
{
// TODO we may want to either add a debug assert here or return specific error codes
// based on the exception caught.
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Error(this, $"Exception occurred during connection callback: {ex.Message}");
}
// TODO: trigger an exception on any outstanding async calls.
return MsQuicStatusCodes.InternalError;
}
return status;
}
private uint HandleEventConnected(ConnectionEvent connectionEvent)
{
SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, _ptr, (uint)QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS);
_localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(inetAddress);
_connected = true;
// I don't believe we need to lock here because
// handle event connected will not be called at the same time as
// handle event shutdown initiated by transport
_connectTcs.Complete(MsQuicStatusCodes.Success);
return MsQuicStatusCodes.Success;
}
private uint HandleEventShutdownInitiatedByTransport(ConnectionEvent connectionEvent)
private uint HandleEventConnected(ref ConnectionEvent connectionEvent)
{
if (!_connected)
{
_connectTcs.CompleteException(new IOException("Connection has been shutdown."));
// _connected will already be true for connections accepted from a listener.
SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, _ptr, (uint)QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.LOCAL_ADDRESS);
_localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref inetAddress);
SetNegotiatedAlpn(connectionEvent.Data.Connected.NegotiatedAlpn, connectionEvent.Data.Connected.NegotiatedAlpnLength);
_connected = true;
_connectTcs.SetResult(MsQuicStatusCodes.Success);
}
return MsQuicStatusCodes.Success;
}
private uint HandleEventShutdownInitiatedByTransport(ref ConnectionEvent connectionEvent)
{
if (!_connected)
{
_connectTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(new IOException("Connection has been shutdown.")));
}
_acceptQueue.Writer.Complete();
return MsQuicStatusCodes.Success;
}
private uint HandleEventShutdownInitiatedByPeer(ConnectionEvent connectionEvent)
private uint HandleEventShutdownInitiatedByPeer(ref ConnectionEvent connectionEvent)
{
_abortErrorCode = connectionEvent.Data.ShutdownBeginPeer.ErrorCode;
_abortErrorCode = connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode;
_acceptQueue.Writer.Complete();
return MsQuicStatusCodes.Success;
}
private uint HandleEventShutdownComplete(ConnectionEvent connectionEvent)
private uint HandleEventShutdownComplete(ref ConnectionEvent connectionEvent)
{
_shutdownTcs.Complete(MsQuicStatusCodes.Success);
_shutdownTcs.SetResult(MsQuicStatusCodes.Success);
return MsQuicStatusCodes.Success;
}
private uint HandleEventNewStream(ConnectionEvent connectionEvent)
private uint HandleEventNewStream(ref ConnectionEvent connectionEvent)
{
MsQuicStream msQuicStream = new MsQuicStream(this, connectionEvent.StreamFlags, connectionEvent.Data.NewStream.Stream, inbound: true);
MsQuicStream msQuicStream = new MsQuicStream(this, connectionEvent.StreamFlags, connectionEvent.Data.StreamStarted.Stream, inbound: true);
_acceptQueue.Writer.TryWrite(msQuicStream);
return MsQuicStatusCodes.Success;
}
private uint HandleEventStreamsAvailable(ConnectionEvent connectionEvent)
private uint HandleEventStreamsAvailable(ref ConnectionEvent connectionEvent)
{
return MsQuicStatusCodes.Success;
}
@ -275,7 +251,7 @@ namespace System.Net.Quic.Implementations.MsQuic
(ushort)_remoteEndPoint.Port),
"Failed to connect to peer.");
return _connectTcs.GetTypelessValueTask();
return new ValueTask(_connectTcs.Task);
}
private MsQuicStream StreamOpen(
@ -286,7 +262,7 @@ namespace System.Net.Quic.Implementations.MsQuic
MsQuicApi.Api.StreamOpenDelegate(
_ptr,
(uint)flags,
MsQuicStream.NativeCallbackHandler,
MsQuicStream.s_streamDelegate,
IntPtr.Zero,
out streamPtr),
"Failed to open stream to peer.");
@ -296,11 +272,12 @@ namespace System.Net.Quic.Implementations.MsQuic
private void SetCallbackHandler()
{
Debug.Assert(!_handle.IsAllocated);
_handle = GCHandle.Alloc(this);
_connectionDelegate = new ConnectionCallbackDelegate(NativeCallbackHandler);
MsQuicApi.Api.SetCallbackHandlerDelegate(
_ptr,
_connectionDelegate,
s_connectionDelegate,
GCHandle.ToIntPtr(_handle));
}
@ -314,10 +291,20 @@ namespace System.Net.Quic.Implementations.MsQuic
ErrorCode);
QuicExceptionHelpers.ThrowIfFailed(status, "Failed to shutdown connection.");
return _shutdownTcs.GetTypelessValueTask();
return new ValueTask(_shutdownTcs.Task);
}
internal static uint NativeCallbackHandler(
internal void SetNegotiatedAlpn(IntPtr alpn, int alpnLength)
{
if (alpn != IntPtr.Zero && alpnLength != 0)
{
var buffer = new byte[alpnLength];
Marshal.Copy(alpn, buffer, 0, alpnLength);
_negotiatedAlpnProtocol = new SslApplicationProtocol(buffer);
}
}
private static uint NativeCallbackHandler(
IntPtr connection,
IntPtr context,
ref ConnectionEvent connectionEventStruct)

View File

@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
#nullable enable
using System.Diagnostics;
using System.Net.Quic.Implementations.MsQuic.Internal;
using System.Net.Security;
using System.Runtime.InteropServices;
@ -15,7 +16,7 @@ namespace System.Net.Quic.Implementations.MsQuic
internal sealed class MsQuicListener : QuicListenerProvider, IDisposable
{
// Security configuration for MsQuic
private MsQuicSession _session;
private readonly MsQuicSession _session;
// Pointer to the underlying listener
// TODO replace all IntPtr with SafeHandles
@ -25,10 +26,10 @@ namespace System.Net.Quic.Implementations.MsQuic
private GCHandle _handle;
// Delegate that wraps the static function that will be called when receiving an event.
private ListenerCallbackDelegate? _listenerDelegate;
private static readonly ListenerCallbackDelegate s_listenerDelegate = new ListenerCallbackDelegate(NativeCallbackHandler);
// Ssl listening options (ALPN, cert, etc)
private SslServerAuthenticationOptions _sslOptions;
private readonly SslServerAuthenticationOptions _sslOptions;
private QuicListenerOptions _options;
private volatile bool _disposed;
@ -142,11 +143,10 @@ namespace System.Net.Quic.Implementations.MsQuic
{
SOCKADDR_INET inetAddress = MsQuicParameterHelpers.GetINetParam(MsQuicApi.Api, _ptr, (uint)QUIC_PARAM_LEVEL.LISTENER, (uint)QUIC_PARAM_LISTENER.LOCAL_ADDRESS);
_listenEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(inetAddress);
_listenEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref inetAddress);
}
internal unsafe uint ListenerCallbackHandler(
ref ListenerEvent evt)
internal unsafe uint ListenerCallbackHandler(ref ListenerEvent evt)
{
try
{
@ -154,10 +154,14 @@ namespace System.Net.Quic.Implementations.MsQuic
{
case QUIC_LISTENER_EVENT.NEW_CONNECTION:
{
NewConnectionInfo connectionInfo = *(NewConnectionInfo*)evt.Data.NewConnection.Info;
IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(*(SOCKADDR_INET*)connectionInfo.LocalAddress);
IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(*(SOCKADDR_INET*)connectionInfo.RemoteAddress);
ref NewConnectionInfo connectionInfo = ref *(NewConnectionInfo*)evt.Data.NewConnection.Info;
IPEndPoint localEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET*)connectionInfo.LocalAddress);
IPEndPoint remoteEndPoint = MsQuicAddressHelpers.INetToIPEndPoint(ref *(SOCKADDR_INET*)connectionInfo.RemoteAddress);
MsQuicConnection msQuicConnection = new MsQuicConnection(localEndPoint, remoteEndPoint, evt.Data.NewConnection.Connection);
msQuicConnection.SetNegotiatedAlpn(connectionInfo.NegotiatedAlpn, connectionInfo.NegotiatedAlpnLength);
_acceptConnectionQueue.Writer.TryWrite(msQuicConnection);
}
// Always pend the new connection to wait for the security config to be resolved
@ -167,8 +171,15 @@ namespace System.Net.Quic.Implementations.MsQuic
return MsQuicStatusCodes.InternalError;
}
}
catch (Exception)
catch (Exception ex)
{
if (NetEventSource.Log.IsEnabled())
{
NetEventSource.Error(this, $"Exception occurred during connection callback: {ex.Message}");
}
// TODO: trigger an exception on any outstanding async calls.
return MsQuicStatusCodes.InternalError;
}
}
@ -191,11 +202,12 @@ namespace System.Net.Quic.Implementations.MsQuic
internal void SetCallbackHandler()
{
Debug.Assert(!_handle.IsAllocated);
_handle = GCHandle.Alloc(this);
_listenerDelegate = new ListenerCallbackDelegate(NativeCallbackHandler);
MsQuicApi.Api.SetCallbackHandlerDelegate(
_ptr,
_listenerDelegate,
s_listenerDelegate,
GCHandle.ToIntPtr(_handle));
}

View File

@ -23,7 +23,7 @@ namespace System.Net.Quic.Implementations.MsQuic
private GCHandle _handle;
// Delegate that wraps the static function that will be called when receiving an event.
private StreamCallbackDelegate? _callback;
internal static readonly StreamCallbackDelegate s_streamDelegate = new StreamCallbackDelegate(NativeCallbackHandler);
// Backing for StreamId
private long _streamId = -1;
@ -62,10 +62,10 @@ namespace System.Net.Quic.Implementations.MsQuic
private volatile bool _disposed;
private List<QuicBuffer> _receiveQuicBuffers = new List<QuicBuffer>();
private readonly List<QuicBuffer> _receiveQuicBuffers = new List<QuicBuffer>();
// TODO consider using Interlocked.Exchange instead of a sync if we can avoid it.
private object _sync = new object();
private readonly object _sync = new object();
// Creates a new MsQuicStream
internal MsQuicStream(MsQuicConnection connection, QUIC_STREAM_OPEN_FLAG flags, IntPtr nativeObjPtr, bool inbound)
@ -79,17 +79,19 @@ namespace System.Net.Quic.Implementations.MsQuic
_shutdownWriteResettableCompletionSource = new ResettableCompletionSource<uint>();
SetCallbackHandler();
bool isBidirectional = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);
if (inbound)
{
_started = true;
_canWrite = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);
_canRead = true;
_canWrite = isBidirectional;
_started = true;
}
else
{
_canRead = isBidirectional;
_canWrite = true;
_canRead = !flags.HasFlag(QUIC_STREAM_OPEN_FLAG.UNIDIRECTIONAL);
StartWrites();
StartLocalStream();
}
}
@ -715,7 +717,6 @@ namespace System.Net.Quic.Implementations.MsQuic
CleanupSendState();
// TODO throw if a write was canceled.
uint errorCode = evt.Data.SendComplete.Canceled;
bool shouldComplete = false;
lock (_sync)
@ -753,10 +754,9 @@ namespace System.Net.Quic.Implementations.MsQuic
{
_handle = GCHandle.Alloc(this);
_callback = new StreamCallbackDelegate(NativeCallbackHandler);
MsQuicApi.Api.SetCallbackHandlerDelegate(
_ptr,
_callback,
s_streamDelegate,
GCHandle.ToIntPtr(_handle));
}
@ -921,7 +921,10 @@ namespace System.Net.Quic.Implementations.MsQuic
return _sendResettableCompletionSource.GetTypelessValueTask();
}
private void StartWrites()
/// <summary>
/// Assigns a stream ID and begins process the stream.
/// </summary>
private void StartLocalStream()
{
Debug.Assert(!_started);
uint status = MsQuicApi.Api.StreamStartDelegate(

View File

@ -9,7 +9,7 @@ internal static partial class Interop
{
internal static class MsQuic
{
[DllImport(Libraries.MsQuic)]
internal static unsafe extern uint MsQuicOpen(int version, out MsQuicNativeMethods.NativeApi* registration);
[DllImport(Libraries.MsQuic, CallingConvention = CallingConvention.Cdecl)]
internal static unsafe extern uint MsQuicOpen(out MsQuicNativeMethods.NativeApi* registration);
}
}

View File

@ -3,19 +3,26 @@
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
}
/// <summary>
/// Flags to pass when creating a security config.
/// </summary>
[Flags]
internal enum QUIC_SEC_CONFIG_FLAG : uint
{
NONE = 0,
CERT_HASH = 0x00000001,
CERT_HASH_STORE = 0x00000002,
CERT_CONTEXT = 0x00000004,
CERT_FILE = 0x00000008,
ENABL_OCSP = 0x00000010,
CERT_NULL = 0xF0000000,
CERT_NULL = 0xF0000000 // TODO: only valid for stub TLS.
}
[Flags]
@ -67,22 +74,30 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
NONE = 0,
ALLOW_0_RTT = 0x00000001,
FIN = 0x00000002,
DGRAM_PRIORITY = 0x00000004
}
internal enum QUIC_PARAM_LEVEL : uint
{
REGISTRATION = 0,
SESSION = 1,
LISTENER = 2,
CONNECTION = 3,
TLS = 4,
STREAM = 5,
GLOBAL,
REGISTRATION,
SESSION,
LISTENER,
CONNECTION,
TLS,
STREAM
}
internal enum QUIC_PARAM_GLOBAL : uint
{
RETRY_MEMORY_PERCENT = 0,
SUPPORTED_VERSIONS = 1,
LOAD_BALANCING_MODE = 2,
}
internal enum QUIC_PARAM_REGISTRATION : uint
{
RETRY_MEMORY_PERCENT = 0,
CID_PREFIX = 1
CID_PREFIX = 0
}
internal enum QUIC_PARAM_SESSION : uint
@ -92,7 +107,10 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
PEER_UNIDI_STREAM_COUNT = 2,
IDLE_TIMEOUT = 3,
DISCONNECT_TIMEOUT = 4,
MAX_BYTES_PER_KEY = 5
MAX_BYTES_PER_KEY = 5,
MIGRATION_ENABLED = 6,
DATAGRAM_RECEIVE_ENABLED = 7,
SERVER_RESUMPTION_LEVEL = 8
}
internal enum QUIC_PARAM_LISTENER : uint
@ -122,7 +140,11 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
SEND_PACING = 16,
SHARE_UDP_BINDING = 17,
IDEAL_PROCESSOR = 18,
MAX_STREAM_IDS = 19
MAX_STREAM_IDS = 19,
STREAM_SCHEDULING_SCHEME = 20,
DATAGRAM_RECEIVE_ENABLED = 21,
DATAGRAM_SEND_ENABLED = 22,
DISABLE_1RTT_ENCRYPTION = 23
}
internal enum QUIC_PARAM_STREAM : uint
@ -149,6 +171,11 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
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
}
internal enum QUIC_STREAM_EVENT : uint

View File

@ -16,8 +16,6 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
[StructLayout(LayoutKind.Sequential)]
internal struct NativeApi
{
internal uint Version;
internal IntPtr SetContext;
internal IntPtr GetContext;
internal IntPtr SetCallbackHandler;
@ -44,6 +42,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal IntPtr ConnectionClose;
internal IntPtr ConnectionShutdown;
internal IntPtr ConnectionStart;
internal IntPtr ConnectionSendResumptionTicket;
internal IntPtr StreamOpen;
internal IntPtr StreamClose;
@ -52,20 +51,26 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal IntPtr StreamSend;
internal IntPtr StreamReceiveComplete;
internal IntPtr StreamReceiveSetEnabled;
internal IntPtr DatagramSend;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint SetContextDelegate(
IntPtr handle,
IntPtr context);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate IntPtr GetContextDelegate(
IntPtr handle);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SetCallbackHandlerDelegate(
IntPtr handle,
Delegate del,
IntPtr context);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint SetParamDelegate(
IntPtr handle,
uint level,
@ -73,6 +78,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
uint bufferLength,
byte* buffer);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint GetParamDelegate(
IntPtr handle,
uint level,
@ -80,36 +86,53 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
uint* bufferLength,
byte* buffer);
internal delegate uint RegistrationOpenDelegate(byte[] appName, out IntPtr registrationContext);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint RegistrationOpenDelegate(ref RegistrationConfig config, out IntPtr registrationContext);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void RegistrationCloseDelegate(IntPtr registrationContext);
[StructLayout(LayoutKind.Sequential)]
internal struct RegistrationConfig
{
[MarshalAs(UnmanagedType.LPUTF8Str)]
internal string AppName;
internal QUIC_EXECUTION_PROFILE ExecutionProfile;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SecConfigCreateCompleteDelegate(IntPtr context, uint status, IntPtr securityConfig);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint SecConfigCreateDelegate(
IntPtr registrationContext,
uint flags,
IntPtr certificate,
[MarshalAs(UnmanagedType.LPStr)]string? principal,
[MarshalAs(UnmanagedType.LPUTF8Str)]string? principal,
IntPtr context,
SecConfigCreateCompleteDelegate completionHandler);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SecConfigDeleteDelegate(
IntPtr securityConfig);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint SessionOpenDelegate(
IntPtr registrationContext,
byte[] utf8String,
QuicBuffer *alpnBuffers,
uint alpnBufferCount,
IntPtr context,
ref IntPtr session);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SessionCloseDelegate(
IntPtr session);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void SessionShutdownDelegate(
IntPtr session,
uint flags,
ushort errorCode);
ulong errorCode);
[StructLayout(LayoutKind.Sequential)]
internal struct ListenerEvent
@ -139,49 +162,58 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal uint QuicVersion;
internal IntPtr LocalAddress;
internal IntPtr RemoteAddress;
internal ushort CryptoBufferLength;
internal uint CryptoBufferLength;
internal ushort AlpnListLength;
internal ushort ServerNameLength;
internal byte NegotiatedAlpnLength;
internal IntPtr CryptoBuffer;
internal IntPtr AlpnList;
internal IntPtr ClientAlpnList;
internal IntPtr NegotiatedAlpn;
internal IntPtr ServerName;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ListenerCallbackDelegate(
IntPtr listener,
IntPtr context,
ref ListenerEvent evt);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ListenerOpenDelegate(
IntPtr session,
ListenerCallbackDelegate handler,
IntPtr context,
out IntPtr listener);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ListenerCloseDelegate(
IntPtr listener);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ListenerStartDelegate(
IntPtr listener,
ref SOCKADDR_INET localAddress);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ListenerStopDelegate(
IntPtr listener);
[StructLayout(LayoutKind.Sequential)]
internal struct ConnectionEventDataConnected
{
internal bool EarlyDataAccepted;
internal bool SessionResumed;
internal byte NegotiatedAlpnLength;
internal IntPtr NegotiatedAlpn;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ConnectionEventDataShutdownBegin
internal struct ConnectionEventDataShutdownInitiatedByTransport
{
internal uint Status;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ConnectionEventDataShutdownBeginPeer
internal struct ConnectionEventDataShutdownInitiatedByPeer
{
internal long ErrorCode;
}
@ -205,7 +237,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
}
[StructLayout(LayoutKind.Sequential)]
internal struct ConnectionEventDataNewStream
internal struct ConnectionEventDataStreamStarted
{
internal IntPtr Stream;
internal QUIC_STREAM_OPEN_FLAG Flags;
@ -218,12 +250,6 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal ushort UniDirectionalCount;
}
[StructLayout(LayoutKind.Sequential)]
internal struct ConnectionEventDataIdealSendBuffer
{
internal ulong NumBytes;
}
[StructLayout(LayoutKind.Explicit)]
internal struct ConnectionEventDataUnion
{
@ -231,10 +257,10 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal ConnectionEventDataConnected Connected;
[FieldOffset(0)]
internal ConnectionEventDataShutdownBegin ShutdownBegin;
internal ConnectionEventDataShutdownInitiatedByTransport ShutdownInitiatedByTransport;
[FieldOffset(0)]
internal ConnectionEventDataShutdownBeginPeer ShutdownBeginPeer;
internal ConnectionEventDataShutdownInitiatedByPeer ShutdownInitiatedByPeer;
[FieldOffset(0)]
internal ConnectionEventDataShutdownComplete ShutdownComplete;
@ -246,13 +272,10 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal ConnectionEventDataPeerAddrChanged PeerAddrChanged;
[FieldOffset(0)]
internal ConnectionEventDataNewStream NewStream;
internal ConnectionEventDataStreamStarted StreamStarted;
[FieldOffset(0)]
internal ConnectionEventDataStreamsAvailable StreamsAvailable;
[FieldOffset(0)]
internal ConnectionEventDataIdealSendBuffer IdealSendBuffer;
}
[StructLayout(LayoutKind.Sequential)]
@ -261,37 +284,42 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal QUIC_CONNECTION_EVENT Type;
internal ConnectionEventDataUnion Data;
internal bool EarlyDataAccepted => Data.Connected.EarlyDataAccepted;
internal ulong NumBytes => Data.IdealSendBuffer.NumBytes;
internal uint ShutdownBeginStatus => Data.ShutdownBegin.Status;
internal long ShutdownBeginPeerStatus => Data.ShutdownBeginPeer.ErrorCode;
internal bool EarlyDataAccepted => Data.Connected.SessionResumed;
//internal ulong NumBytes => Data.IdealSendBuffer.NumBytes;
internal uint ShutdownBeginStatus => Data.ShutdownInitiatedByTransport.Status;
internal long ShutdownBeginPeerStatus => Data.ShutdownInitiatedByPeer.ErrorCode;
internal bool ShutdownTimedOut => Data.ShutdownComplete.TimedOut;
internal ushort BiDirectionalCount => Data.StreamsAvailable.BiDirectionalCount;
internal ushort UniDirectionalCount => Data.StreamsAvailable.UniDirectionalCount;
internal QUIC_STREAM_OPEN_FLAG StreamFlags => Data.NewStream.Flags;
internal QUIC_STREAM_OPEN_FLAG StreamFlags => Data.StreamStarted.Flags;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ConnectionCallbackDelegate(
IntPtr connection,
IntPtr context,
ref ConnectionEvent connectionEvent);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ConnectionOpenDelegate(
IntPtr session,
ConnectionCallbackDelegate handler,
IntPtr context,
out IntPtr connection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ConnectionCloseDelegate(
IntPtr connection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ConnectionStartDelegate(
IntPtr connection,
ushort family,
[MarshalAs(UnmanagedType.LPStr)]
[MarshalAs(UnmanagedType.LPUTF8Str)]
string serverName,
ushort serverPort);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint ConnectionShutdownDelegate(
IntPtr connection,
uint flags,
@ -304,21 +332,14 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal ulong TotalBufferLength;
internal QuicBuffer* Buffers;
internal uint BufferCount;
internal uint Flags;
internal QUIC_RECEIVE_FLAG Flags;
}
[StructLayout(LayoutKind.Explicit)]
[StructLayout(LayoutKind.Sequential)]
internal struct StreamEventDataSendComplete
{
[FieldOffset(0)]
internal byte Canceled;
[FieldOffset(1)]
internal bool Canceled;
internal IntPtr ClientContext;
internal bool IsCanceled()
{
return Canceled != 0;
}
}
[StructLayout(LayoutKind.Sequential)]
@ -432,11 +453,13 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
internal ushort si_family;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamCallbackDelegate(
IntPtr stream,
IntPtr context,
ref StreamEvent streamEvent);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamOpenDelegate(
IntPtr connection,
uint flags,
@ -444,18 +467,22 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
IntPtr context,
out IntPtr stream);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamStartDelegate(
IntPtr stream,
uint flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamCloseDelegate(
IntPtr stream);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamShutdownDelegate(
IntPtr stream,
uint flags,
long errorCode);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamSendDelegate(
IntPtr stream,
QuicBuffer* buffers,
@ -463,12 +490,15 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
uint flags,
IntPtr clientSendContext);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamReceiveCompleteDelegate(
IntPtr stream,
ulong bufferLength);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate uint StreamReceiveSetEnabledDelegate(
IntPtr stream,
[MarshalAs(UnmanagedType.U1)]
bool enabled);
[StructLayout(LayoutKind.Sequential)]