Sync shared code from runtime (#25435)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
50f739a4bc
commit
2ea674021f
|
|
@ -14,7 +14,7 @@ namespace System.Net.Quic.Implementations.Mock
|
|||
{
|
||||
private readonly bool _isClient;
|
||||
private bool _disposed;
|
||||
private IPEndPoint? _remoteEndPoint;
|
||||
private EndPoint? _remoteEndPoint;
|
||||
private IPEndPoint? _localEndPoint;
|
||||
private object _syncObject = new object();
|
||||
private Socket? _socket;
|
||||
|
|
@ -24,7 +24,7 @@ namespace System.Net.Quic.Implementations.Mock
|
|||
private long _nextOutboundUnidirectionalStream;
|
||||
|
||||
// Constructor for outbound connections
|
||||
internal MockConnection(IPEndPoint? remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
internal MockConnection(EndPoint? remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
{
|
||||
_remoteEndPoint = remoteEndPoint;
|
||||
_localEndPoint = localEndPoint;
|
||||
|
|
@ -59,7 +59,7 @@ namespace System.Net.Quic.Implementations.Mock
|
|||
|
||||
internal override IPEndPoint LocalEndPoint => new IPEndPoint(_localEndPoint!.Address, _localEndPoint.Port);
|
||||
|
||||
internal override IPEndPoint RemoteEndPoint => new IPEndPoint(_remoteEndPoint!.Address, _remoteEndPoint.Port);
|
||||
internal override EndPoint RemoteEndPoint => _remoteEndPoint!;
|
||||
|
||||
internal override SslApplicationProtocol NegotiatedApplicationProtocol => throw new NotImplementedException();
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#nullable enable
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.InteropServices;
|
||||
|
|
@ -318,26 +320,72 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
return secConfig;
|
||||
}
|
||||
|
||||
public unsafe IntPtr SessionOpen(byte[] alpn)
|
||||
public unsafe IntPtr SessionOpen(List<SslApplicationProtocol> alpnProtocols)
|
||||
{
|
||||
if (alpnProtocols.Count == 1)
|
||||
{
|
||||
return SessionOpen(alpnProtocols[0]);
|
||||
}
|
||||
|
||||
var memoryHandles = ArrayPool<MemoryHandle>.Shared.Rent(alpnProtocols.Count);
|
||||
var quicBuffers = ArrayPool<MsQuicNativeMethods.QuicBuffer>.Shared.Rent(alpnProtocols.Count);
|
||||
|
||||
try
|
||||
{
|
||||
for (int i = 0; i < alpnProtocols.Count; ++i)
|
||||
{
|
||||
ReadOnlyMemory<byte> alpnProtocol = alpnProtocols[i].Protocol;
|
||||
MemoryHandle h = alpnProtocol.Pin();
|
||||
|
||||
memoryHandles[i] = h;
|
||||
quicBuffers[i].Buffer = (byte*)h.Pointer;
|
||||
quicBuffers[i].Length = (uint)alpnProtocol.Length;
|
||||
}
|
||||
|
||||
IntPtr session;
|
||||
|
||||
fixed (MsQuicNativeMethods.QuicBuffer* pQuicBuffers = quicBuffers)
|
||||
{
|
||||
session = SessionOpen(pQuicBuffers, (uint)alpnProtocols.Count);
|
||||
}
|
||||
|
||||
ArrayPool<MsQuicNativeMethods.QuicBuffer>.Shared.Return(quicBuffers);
|
||||
ArrayPool<MemoryHandle>.Shared.Return(memoryHandles);
|
||||
|
||||
return session;
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (MemoryHandle handle in memoryHandles)
|
||||
{
|
||||
handle.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe IntPtr SessionOpen(SslApplicationProtocol alpnProtocol)
|
||||
{
|
||||
ReadOnlyMemory<byte> memory = alpnProtocol.Protocol;
|
||||
using MemoryHandle h = memory.Pin();
|
||||
|
||||
var quicBuffer = new MsQuicNativeMethods.QuicBuffer()
|
||||
{
|
||||
Buffer = (byte*)h.Pointer,
|
||||
Length = (uint)memory.Length
|
||||
};
|
||||
|
||||
return SessionOpen(&quicBuffer, 1);
|
||||
}
|
||||
|
||||
private unsafe IntPtr SessionOpen(MsQuicNativeMethods.QuicBuffer *alpnBuffers, uint bufferCount)
|
||||
{
|
||||
IntPtr sessionPtr = IntPtr.Zero;
|
||||
uint status;
|
||||
|
||||
fixed (byte* pAlpn = alpn)
|
||||
{
|
||||
var alpnBuffer = new MsQuicNativeMethods.QuicBuffer
|
||||
{
|
||||
Length = (uint)alpn.Length,
|
||||
Buffer = pAlpn
|
||||
};
|
||||
|
||||
status = SessionOpenDelegate(
|
||||
_registrationContext,
|
||||
&alpnBuffer,
|
||||
1,
|
||||
IntPtr.Zero,
|
||||
ref sessionPtr);
|
||||
}
|
||||
uint status = SessionOpenDelegate(
|
||||
_registrationContext,
|
||||
alpnBuffers,
|
||||
bufferCount,
|
||||
IntPtr.Zero,
|
||||
ref sessionPtr);
|
||||
|
||||
QuicExceptionHelpers.ThrowIfFailed(status, "Could not open session.");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Security;
|
||||
|
||||
namespace System.Net.Quic.Implementations.MsQuic.Internal
|
||||
{
|
||||
|
|
@ -21,7 +23,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
{
|
||||
if (!_opened)
|
||||
{
|
||||
OpenSession(options.ClientAuthenticationOptions!.ApplicationProtocols![0].Protocol.ToArray(),
|
||||
OpenSession(options.ClientAuthenticationOptions!.ApplicationProtocols!,
|
||||
(ushort)options.MaxBidirectionalStreams,
|
||||
(ushort)options.MaxUnidirectionalStreams);
|
||||
}
|
||||
|
|
@ -36,7 +38,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
return connectionPtr;
|
||||
}
|
||||
|
||||
private void OpenSession(byte[] alpn, ushort bidirectionalStreamCount, ushort undirectionalStreamCount)
|
||||
private void OpenSession(List<SslApplicationProtocol> alpn, ushort bidirectionalStreamCount, ushort undirectionalStreamCount)
|
||||
{
|
||||
_opened = true;
|
||||
_nativeObjPtr = MsQuicApi.Api.SessionOpen(alpn);
|
||||
|
|
@ -49,7 +51,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
{
|
||||
if (!_opened)
|
||||
{
|
||||
OpenSession(options.ServerAuthenticationOptions!.ApplicationProtocols![0].Protocol.ToArray(),
|
||||
OpenSession(options.ServerAuthenticationOptions!.ApplicationProtocols!,
|
||||
(ushort)options.MaxBidirectionalStreams,
|
||||
(ushort)options.MaxUnidirectionalStreams);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,13 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
{
|
||||
if (!MsQuicStatusHelper.SuccessfulStatusCode(status))
|
||||
{
|
||||
throw new QuicException($"{message} Error Code: {MsQuicStatusCodes.GetError(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.Net.Quic.Implementations.MsQuic.Internal;
|
||||
using System.Net.Security;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
|
@ -32,7 +33,7 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
|
||||
// Endpoint to either connect to or the endpoint already accepted.
|
||||
private IPEndPoint? _localEndPoint;
|
||||
private readonly IPEndPoint _remoteEndPoint;
|
||||
private readonly EndPoint _remoteEndPoint;
|
||||
|
||||
private SslApplicationProtocol _negotiatedAlpnProtocol;
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
MsQuicParameterHelpers.SetSecurityConfig(MsQuicApi.Api, _ptr, (uint)QUIC_PARAM_LEVEL.CONNECTION, (uint)QUIC_PARAM_CONN.SEC_CONFIG, _securityConfig!.NativeObjPtr);
|
||||
}
|
||||
|
||||
internal override IPEndPoint RemoteEndPoint => new IPEndPoint(_remoteEndPoint.Address, _remoteEndPoint.Port);
|
||||
internal override EndPoint RemoteEndPoint => _remoteEndPoint;
|
||||
|
||||
internal override SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedAlpnProtocol;
|
||||
|
||||
|
|
@ -155,7 +156,9 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
{
|
||||
if (!_connected)
|
||||
{
|
||||
_connectTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(new IOException("Connection has been shutdown.")));
|
||||
uint hresult = connectionEvent.Data.ShutdownInitiatedByTransport.Status;
|
||||
Exception ex = QuicExceptionHelpers.CreateExceptionForHResult(hresult, "Connection has been shutdown by transport.");
|
||||
_connectTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex));
|
||||
}
|
||||
|
||||
_acceptQueue.Writer.Complete();
|
||||
|
|
@ -243,12 +246,28 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
(string address, int port) = _remoteEndPoint switch
|
||||
{
|
||||
DnsEndPoint dnsEp => (dnsEp.Host, dnsEp.Port),
|
||||
IPEndPoint ipEp => (ipEp.Address.ToString(), ipEp.Port),
|
||||
_ => throw new Exception($"Unsupported remote endpoint type '{_remoteEndPoint.GetType()}'.")
|
||||
};
|
||||
|
||||
// values taken from https://github.com/microsoft/msquic/blob/main/docs/api/ConnectionStart.md
|
||||
int af = _remoteEndPoint.AddressFamily switch
|
||||
{
|
||||
AddressFamily.Unspecified => 0,
|
||||
AddressFamily.InterNetwork => 2,
|
||||
AddressFamily.InterNetworkV6 => 23,
|
||||
_ => throw new Exception($"Unsupported address family of '{_remoteEndPoint.AddressFamily}' for remote endpoint.")
|
||||
};
|
||||
|
||||
QuicExceptionHelpers.ThrowIfFailed(
|
||||
MsQuicApi.Api.ConnectionStartDelegate(
|
||||
_ptr,
|
||||
(ushort)_remoteEndPoint.AddressFamily,
|
||||
_remoteEndPoint.Address.ToString(),
|
||||
(ushort)_remoteEndPoint.Port),
|
||||
(ushort)af,
|
||||
address,
|
||||
(ushort)port),
|
||||
"Failed to connect to peer.");
|
||||
|
||||
return new ValueTask(_connectTcs.Task);
|
||||
|
|
|
|||
|
|
@ -225,6 +225,11 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
throw new InvalidOperationException("Reading is not allowed on stream.");
|
||||
}
|
||||
|
||||
if (NetEventSource.IsEnabled)
|
||||
{
|
||||
NetEventSource.Info(this, $"[{GetHashCode()}] reading into Memory of '{destination.Length}' bytes.");
|
||||
}
|
||||
|
||||
lock (_sync)
|
||||
{
|
||||
if (_readState == ReadState.ReadsCompleted)
|
||||
|
|
@ -474,6 +479,11 @@ namespace System.Net.Quic.Implementations.MsQuic
|
|||
|
||||
private uint HandleEvent(ref StreamEvent evt)
|
||||
{
|
||||
if (NetEventSource.IsEnabled)
|
||||
{
|
||||
NetEventSource.Info(this, $"[{GetHashCode()}] handling event '{evt.Type}'.");
|
||||
}
|
||||
|
||||
uint status = MsQuicStatusCodes.Success;
|
||||
|
||||
try
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace System.Net.Quic.Implementations
|
|||
|
||||
internal abstract IPEndPoint LocalEndPoint { get; }
|
||||
|
||||
internal abstract IPEndPoint RemoteEndPoint { get; }
|
||||
internal abstract EndPoint RemoteEndPoint { get; }
|
||||
|
||||
internal abstract ValueTask ConnectAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,16 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
internal const uint HandshakeFailure = 0x80410000;
|
||||
internal const uint Aborted = 0x80004004;
|
||||
internal const uint AddressInUse = 0x80072740;
|
||||
internal const uint ConnectionTimeout = 0x800704CF;
|
||||
internal const uint ConnectionIdle = 0x800704D4;
|
||||
internal const uint InternalError = 0x80004005;
|
||||
internal const uint ServerBusy = 0x800704C9;
|
||||
internal const uint ProtocolError = 0x800704CD;
|
||||
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;
|
||||
|
||||
// TODO return better error messages here.
|
||||
public static string GetError(uint status)
|
||||
|
|
@ -53,11 +56,15 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
AddressInUse => "ADDRESS_IN_USE",
|
||||
ConnectionTimeout => "CONNECTION_TIMEOUT",
|
||||
ConnectionIdle => "CONNECTION_IDLE",
|
||||
HostUnreachable => "UNREACHABLE",
|
||||
InternalError => "INTERNAL_ERROR",
|
||||
ServerBusy => "SERVER_BUSY",
|
||||
ConnectionRefused => "CONNECTION_REFUSED",
|
||||
ProtocolError => "PROTOCOL_ERROR",
|
||||
VerNegError => "VER_NEG_ERROR",
|
||||
_ => status.ToString()
|
||||
TlsError => "TLS_ERROR",
|
||||
UserCanceled => "USER_CANCELED",
|
||||
AlpnNegotiationFailure => "ALPN_NEG_FAILURE",
|
||||
_ => $"0x{status:X8}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -79,9 +86,15 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
internal const uint ConnectionTimeout = 110;
|
||||
internal const uint ConnectionIdle = 200000011;
|
||||
internal const uint InternalError = 200000012;
|
||||
internal const uint ServerBusy = 200000007;
|
||||
internal const uint ConnectionRefused = 200000007;
|
||||
internal const uint ProtocolError = 200000013;
|
||||
internal const uint VerNegError = 200000014;
|
||||
internal const uint EpollError = 200000015;
|
||||
internal const uint DnsResolutionError = 200000016;
|
||||
internal const uint SocketError = 200000017;
|
||||
internal const uint TlsError = 200000018;
|
||||
internal const uint UserCanceled = 200000019;
|
||||
internal const uint AlpnNegotiationFailure = 200000020;
|
||||
|
||||
// TODO return better error messages here.
|
||||
public static string GetError(uint status)
|
||||
|
|
@ -103,10 +116,16 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
|
|||
ConnectionTimeout => "CONNECTION_TIMEOUT",
|
||||
ConnectionIdle => "CONNECTION_IDLE",
|
||||
InternalError => "INTERNAL_ERROR",
|
||||
ServerBusy => "SERVER_BUSY",
|
||||
ConnectionRefused => "CONNECTION_REFUSED",
|
||||
ProtocolError => "PROTOCOL_ERROR",
|
||||
VerNegError => "VER_NEG_ERROR",
|
||||
_ => status.ToString()
|
||||
EpollError => "EPOLL_ERROR",
|
||||
DnsResolutionError => "DNS_RESOLUTION_ERROR",
|
||||
SocketError => "SOCKET_ERROR",
|
||||
TlsError => "TLS_ERROR",
|
||||
UserCanceled => "USER_CANCELED",
|
||||
AlpnNegotiationFailure => "ALPN_NEG_FAILURE",
|
||||
_ => $"0x{status:X8}"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace System.Net.Quic
|
|||
/// <summary>
|
||||
/// The endpoint to connect to.
|
||||
/// </summary>
|
||||
public IPEndPoint? RemoteEndPoint { get; set; }
|
||||
public EndPoint? RemoteEndPoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Limit on the number of bidirectional streams the peer connection can create
|
||||
|
|
|
|||
|
|
@ -22,13 +22,13 @@ namespace System.Net.Quic
|
|||
/// <param name="remoteEndPoint">The remote endpoint to connect to.</param>
|
||||
/// <param name="sslClientAuthenticationOptions">TLS options</param>
|
||||
/// <param name="localEndPoint">The local endpoint to connect from.</param>
|
||||
public QuicConnection(IPEndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
public QuicConnection(EndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
: this(QuicImplementationProviders.Default, remoteEndPoint, sslClientAuthenticationOptions, localEndPoint)
|
||||
{
|
||||
}
|
||||
|
||||
// !!! TEMPORARY: Remove "implementationProvider" before shipping
|
||||
public QuicConnection(QuicImplementationProvider implementationProvider, IPEndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
public QuicConnection(QuicImplementationProvider implementationProvider, EndPoint remoteEndPoint, SslClientAuthenticationOptions? sslClientAuthenticationOptions, IPEndPoint? localEndPoint = null)
|
||||
: this(implementationProvider, new QuicClientConnectionOptions() { RemoteEndPoint = remoteEndPoint, ClientAuthenticationOptions = sslClientAuthenticationOptions, LocalEndPoint = localEndPoint })
|
||||
{
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ namespace System.Net.Quic
|
|||
|
||||
public IPEndPoint LocalEndPoint => _provider.LocalEndPoint;
|
||||
|
||||
public IPEndPoint RemoteEndPoint => _provider.RemoteEndPoint;
|
||||
public EndPoint RemoteEndPoint => _provider.RemoteEndPoint;
|
||||
|
||||
public SslApplicationProtocol NegotiatedApplicationProtocol => _provider.NegotiatedApplicationProtocol;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
#nullable enable
|
||||
namespace System.Net.Quic
|
||||
{
|
||||
internal class QuicException : Exception
|
||||
{
|
||||
public QuicException(string message)
|
||||
: base (message)
|
||||
public QuicException(string? message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
public QuicException(string? message, Exception? innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue