From f80d6a8c88e54c40193069218aa72fcbe18acefd Mon Sep 17 00:00:00 2001 From: ManickaP Date: Tue, 12 Sep 2023 18:27:06 +0200 Subject: [PATCH 1/3] Unsealead --- .../System.Net.Quic/ref/System.Net.Quic.cs | 44 +++++++++---------- .../src/System/Net/Quic/QuicConnection.cs | 24 ++++++---- .../src/System/Net/Quic/QuicListener.cs | 22 +++++++--- .../src/System/Net/Quic/QuicStream.cs | 22 ++++++---- 4 files changed, 67 insertions(+), 45 deletions(-) diff --git a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs index dcebe2b547ea3d..fc9b56e326f29e 100644 --- a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs +++ b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs @@ -20,20 +20,20 @@ public QuicClientConnectionOptions() { } public System.Net.IPEndPoint? LocalEndPoint { get { throw null; } set { } } public System.Net.EndPoint RemoteEndPoint { get { throw null; } set { } } } - public sealed partial class QuicConnection : System.IAsyncDisposable + public partial class QuicConnection : System.IAsyncDisposable { - internal QuicConnection() { } + protected QuicConnection(bool managed) { } public static bool IsSupported { get { throw null; } } - public System.Net.IPEndPoint LocalEndPoint { get { throw null; } } - public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } } - public System.Net.IPEndPoint RemoteEndPoint { get { throw null; } } - public string TargetHostName { get { throw null; } } - public System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Net.IPEndPoint LocalEndPoint { get { throw null; } } + public virtual System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } + public virtual System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } } + public virtual System.Net.IPEndPoint RemoteEndPoint { get { throw null; } } + public virtual string TargetHostName { get { throw null; } } + public virtual System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask ConnectAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override string ToString() { throw null; } } public abstract partial class QuicConnectionOptions @@ -67,11 +67,11 @@ public QuicException(System.Net.Quic.QuicError error, long? applicationErrorCode public System.Net.Quic.QuicError QuicError { get { throw null; } } public long? TransportErrorCode { get { throw null; } } } - public sealed partial class QuicListener : System.IAsyncDisposable + public partial class QuicListener : System.IAsyncDisposable { - internal QuicListener() { } + protected QuicListener(bool managed) { } public static bool IsSupported { get { throw null; } } - public System.Net.IPEndPoint LocalEndPoint { get { throw null; } } + public virtual System.Net.IPEndPoint LocalEndPoint { get { throw null; } } public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public static System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -90,25 +90,25 @@ public sealed partial class QuicServerConnectionOptions : System.Net.Quic.QuicCo public QuicServerConnectionOptions() { } public System.Net.Security.SslServerAuthenticationOptions ServerAuthenticationOptions { get { throw null; } set { } } } - public sealed partial class QuicStream : System.IO.Stream + public partial class QuicStream : System.IO.Stream { - internal QuicStream() { } + protected QuicStream(bool managed) { } public override bool CanRead { get { throw null; } } public override bool CanSeek { get { throw null; } } public override bool CanTimeout { get { throw null; } } public override bool CanWrite { get { throw null; } } - public long Id { get { throw null; } } + public virtual long Id { get { throw null; } } public override long Length { get { throw null; } } public override long Position { get { throw null; } set { } } - public System.Threading.Tasks.Task ReadsClosed { get { throw null; } } + public virtual System.Threading.Tasks.Task ReadsClosed { get { throw null; } } public override int ReadTimeout { get { throw null; } set { } } - public System.Net.Quic.QuicStreamType Type { get { throw null; } } - public System.Threading.Tasks.Task WritesClosed { get { throw null; } } + public virtual System.Net.Quic.QuicStreamType Type { get { throw null; } } + public virtual System.Threading.Tasks.Task WritesClosed { get { throw null; } } public override int WriteTimeout { get { throw null; } set { } } - public void Abort(System.Net.Quic.QuicAbortDirection abortDirection, long errorCode) { } + public virtual void Abort(System.Net.Quic.QuicAbortDirection abortDirection, long errorCode) { } public override System.IAsyncResult BeginRead(byte[] buffer, int offset, int count, System.AsyncCallback? callback, object? state) { throw null; } public override System.IAsyncResult BeginWrite(byte[] buffer, int offset, int count, System.AsyncCallback? callback, object? state) { throw null; } - public void CompleteWrites() { } + public virtual void CompleteWrites() { } protected override void Dispose(bool disposing) { } public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public override int EndRead(System.IAsyncResult asyncResult) { throw null; } @@ -126,7 +126,7 @@ public override void SetLength(long value) { } public override void Write(byte[] buffer, int offset, int count) { } public override void Write(System.ReadOnlySpan buffer) { } public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, bool completeWrites, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, bool completeWrites, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override void WriteByte(byte value) { } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index a2ade033afe59f..bf8a56c4a0107d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -36,7 +36,7 @@ namespace System.Net.Quic; /// Each connection can then open outbound stream: , /// or accept an inbound stream: . /// -public sealed partial class QuicConnection : IAsyncDisposable +public partial class QuicConnection : IAsyncDisposable { #if DEBUG /// @@ -155,23 +155,23 @@ static async ValueTask StartConnectAsync(QuicClientConnectionOpt /// /// The remote endpoint used for this connection. /// - public IPEndPoint RemoteEndPoint => _remoteEndPoint; + public virtual IPEndPoint RemoteEndPoint => _remoteEndPoint; /// /// The local endpoint used for this connection. /// - public IPEndPoint LocalEndPoint => _localEndPoint; + public virtual IPEndPoint LocalEndPoint => _localEndPoint; /// /// Gets the name of the server the client is trying to connect to. That name is used for server certificate validation. It can be a DNS name or an IP address. /// /// The name of the server the client is trying to connect to. - public string TargetHostName => _sslConnectionOptions.TargetHost ?? string.Empty; + public virtual string TargetHostName => _sslConnectionOptions.TargetHost ?? string.Empty; /// /// The certificate provided by the peer. /// For an outbound/client connection will always have the peer's (server) certificate; for an inbound/server one, only if the connection requested and the peer (client) provided one. /// - public X509Certificate? RemoteCertificate + public virtual X509Certificate? RemoteCertificate { get { @@ -183,11 +183,17 @@ public X509Certificate? RemoteCertificate /// /// Final, negotiated application protocol. /// - public SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedApplicationProtocol; + public virtual SslApplicationProtocol NegotiatedApplicationProtocol => _negotiatedApplicationProtocol; /// public override string ToString() => _handle.ToString(); + protected QuicConnection(bool managed) + { + Debug.Assert(managed); + _handle = null!; + } + /// /// Initializes a new instance of an outbound . /// @@ -366,7 +372,7 @@ internal ValueTask FinishHandshakeAsync(QuicServerConnectionOptions options, str /// The type of the stream, i.e. unidirectional or bidirectional. /// A cancellation token that can be used to cancel the asynchronous operation. /// An asynchronous task that completes with the opened . - public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, CancellationToken cancellationToken = default) + public virtual async ValueTask OpenOutboundStreamAsync(QuicStreamType type, CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); @@ -397,7 +403,7 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, /// /// A cancellation token that can be used to cancel the asynchronous operation. /// An asynchronous task that completes with the accepted . - public async ValueTask AcceptInboundStreamAsync(CancellationToken cancellationToken = default) + public virtual async ValueTask AcceptInboundStreamAsync(CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); @@ -436,7 +442,7 @@ public async ValueTask AcceptInboundStreamAsync(CancellationToken ca /// Application provided code with the reason for closure. /// A cancellation token that can be used to cancel the asynchronous operation. /// An asynchronous task that completes when the connection is closed. - public ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) + public virtual ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index fcbfba56336acc..ec679130be8e70 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -27,7 +27,7 @@ namespace System.Net.Quic; /// Unlike the connection and stream, lifetime is not linked to any of the accepted connections. /// It can be safely disposed while keeping the accepted connection alive. The will only stop listening for any other inbound connections. /// -public sealed partial class QuicListener : IAsyncDisposable +public partial class QuicListener : IAsyncDisposable { /// /// Returns true if QUIC is supported on the current machine and can be used; otherwise, false. @@ -87,12 +87,12 @@ public static ValueTask ListenAsync(QuicListenerOptions options, C /// /// Selects connection options for incoming connections. /// - private readonly Func> _connectionOptionsCallback; + private readonly Func> _connectionOptionsCallback = null!; /// /// Incoming connections waiting to be accepted via AcceptAsync. The item will either be fully connected or if the handshake failed. /// - private readonly Channel _acceptQueue; + private readonly Channel _acceptQueue = Channel.CreateUnbounded(); /// /// Allowed number of pending incoming connections. /// Actual value correspond to - # in progress - .Count and is always >= 0. @@ -100,14 +100,25 @@ public static ValueTask ListenAsync(QuicListenerOptions options, C /// private int _pendingConnectionsCapacity; + /// + /// Set when listener is started. + /// + private IPEndPoint _localEndPoint = null!; + /// /// The actual listening endpoint. /// - public IPEndPoint LocalEndPoint { get; } + public virtual IPEndPoint LocalEndPoint => _localEndPoint; /// public override string ToString() => _handle.ToString(); + protected QuicListener(bool managed) + { + Debug.Assert(managed); + _handle = null!; + } + /// /// Initializes and starts a new instance of a . /// @@ -134,7 +145,6 @@ private unsafe QuicListener(QuicListenerOptions options) // Save the connection options before starting the listener _connectionOptionsCallback = options.ConnectionOptionsCallback; - _acceptQueue = Channel.CreateUnbounded(); _pendingConnectionsCapacity = options.ListenBacklog; // Start the listener, from now on MsQuic events will come. @@ -157,7 +167,7 @@ private unsafe QuicListener(QuicListenerOptions options) // Get the actual listening endpoint. address = GetMsQuicParameter(_handle, QUIC_PARAM_LISTENER_LOCAL_ADDRESS); - LocalEndPoint = MsQuicHelpers.QuicAddrToIPEndPoint(&address, options.ListenEndPoint.AddressFamily); + _localEndPoint = QuicAddrToIPEndPoint(&address, options.ListenEndPoint.AddressFamily); } /// diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs index 6165f2085cb5f0..7ac76b4a06aff8 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicStream.cs @@ -52,7 +52,7 @@ namespace System.Net.Quic; /// /// /// -public sealed partial class QuicStream +public partial class QuicStream { /// /// Handle to MsQuic connection object. @@ -122,12 +122,12 @@ public sealed partial class QuicStream /// /// Stream id, see . /// - public long Id => _id; + public virtual long Id => _id; /// /// Stream type, see . /// - public QuicStreamType Type => _type; + public virtual QuicStreamType Type => _type; /// /// A that will get completed once reading side has been closed. @@ -135,7 +135,7 @@ public sealed partial class QuicStream /// or when for is called, /// or when the peer called for . /// - public Task ReadsClosed => _receiveTcs.GetFinalTask(); + public virtual Task ReadsClosed => _receiveTcs.GetFinalTask(); /// /// A that will get completed once writing side has been closed. @@ -144,11 +144,17 @@ public sealed partial class QuicStream /// or when for is called, /// or when the peer called for . /// - public Task WritesClosed => _sendTcs.GetFinalTask(); + public virtual Task WritesClosed => _sendTcs.GetFinalTask(); /// public override string ToString() => _handle.ToString(); + protected QuicStream(bool managed) + { + Debug.Assert(managed); + _handle = null!; + } + /// /// Initializes a new instance of an outbound . /// @@ -334,7 +340,7 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo /// The region of memory to write data from. /// The token to monitor for cancellation requests. The default value is . /// Notifies the peer about gracefully closing the write side, i.e.: sends FIN flag with the data. - public ValueTask WriteAsync(ReadOnlyMemory buffer, bool completeWrites, CancellationToken cancellationToken = default) + public virtual ValueTask WriteAsync(ReadOnlyMemory buffer, bool completeWrites, CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); @@ -421,7 +427,7 @@ public ValueTask WriteAsync(ReadOnlyMemory buffer, bool completeWrites, Ca /// /// The direction of the stream to abort. /// The error code with which to abort the stream, this value is application protocol (layer above QUIC) dependent. - public void Abort(QuicAbortDirection abortDirection, long errorCode) + public virtual void Abort(QuicAbortDirection abortDirection, long errorCode) { if (_disposed == 1) { @@ -471,7 +477,7 @@ public void Abort(QuicAbortDirection abortDirection, long errorCode) /// /// Corresponds to an empty STREAM frame with FIN flag set to true. /// - public void CompleteWrites() + public virtual void CompleteWrites() { ObjectDisposedException.ThrowIf(_disposed == 1, this); From fc78c9c4c8695955caa34802f6119dbbd0ab2228 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Wed, 13 Sep 2023 10:25:31 +0200 Subject: [PATCH 2/3] Fixed unsupported stubs --- .../src/System/Net/Quic/QuicConnection.Unsupported.cs | 2 +- .../src/System/Net/Quic/QuicListener.Unsupported.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs index e32239db6d5682..62c8059698cf89 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.Unsupported.cs @@ -3,7 +3,7 @@ namespace System.Net.Quic; -public sealed partial class QuicConnection +public partial class QuicConnection { public static bool IsSupported => false; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs index 71f83a2abac790..d9ebdc4f5468c4 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.Unsupported.cs @@ -3,7 +3,7 @@ namespace System.Net.Quic; -public sealed partial class QuicListener +public partial class QuicListener { public static bool IsSupported => false; } From f6a3391234a0fd34e6f48a509ce090d7821ef672 Mon Sep 17 00:00:00 2001 From: ManickaP Date: Wed, 13 Sep 2023 10:39:51 +0200 Subject: [PATCH 3/3] Managed derives from official --- .../System.Net.Quic/ref/System.Net.Quic.cs | 54 +++++++++---------- .../Managed/ManagedQuicConnection.cs | 23 ++++---- .../Managed/ManagedQuicListener.cs | 16 +++--- .../Managed/ManagedQuicStream.cs | 19 ++++--- .../src/System/Net/Quic/QuicConnection.cs | 2 +- .../src/System/Net/Quic/QuicListener.cs | 4 +- 6 files changed, 58 insertions(+), 60 deletions(-) diff --git a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs index fc9b56e326f29e..79e69e365250e9 100644 --- a/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs +++ b/src/libraries/System.Net.Quic/ref/System.Net.Quic.cs @@ -32,7 +32,7 @@ protected QuicConnection(bool managed) { } public virtual System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public virtual System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask ConnectAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public virtual System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public virtual System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override string ToString() { throw null; } } @@ -72,8 +72,8 @@ public partial class QuicListener : System.IAsyncDisposable protected QuicListener(bool managed) { } public static bool IsSupported { get { throw null; } } public virtual System.Net.IPEndPoint LocalEndPoint { get { throw null; } } - public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public virtual System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public static System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override string ToString() { throw null; } } @@ -138,43 +138,43 @@ public enum QuicStreamType } namespace System.Net.Quic.Implementations.Managed { - public sealed partial class ManagedQuicConnection : System.IAsyncDisposable + public sealed partial class ManagedQuicConnection : System.Net.Quic.QuicConnection, System.IAsyncDisposable { - public ManagedQuicConnection(System.Net.Quic.QuicClientConnectionOptions options) { } - public System.Net.IPEndPoint LocalEndPoint { get { throw null; } } - public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } - public System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } } - public System.Net.EndPoint RemoteEndPoint { get { throw null; } } - public System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public ManagedQuicConnection(System.Net.Quic.QuicClientConnectionOptions options) : base (default(bool)) { } + public override System.Net.IPEndPoint LocalEndPoint { get { throw null; } } + public override System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get { throw null; } } + public override System.Security.Cryptography.X509Certificates.X509Certificate? RemoteCertificate { get { throw null; } } + public override System.Net.IPEndPoint RemoteEndPoint { get { throw null; } } + public override System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask CloseAsync(long errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public override System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } - public sealed partial class ManagedQuicListener : System.IAsyncDisposable + public sealed partial class ManagedQuicListener : System.Net.Quic.QuicListener, System.IAsyncDisposable { - internal ManagedQuicListener() { } - public static bool IsSupported { get { throw null; } } + internal ManagedQuicListener() : base (default(bool)) { } + public static new bool IsSupported { get { throw null; } } public System.Net.IPEndPoint ListenEndPoint { get { throw null; } } - public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } - public static System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } + public static new System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } } - public sealed partial class ManagedQuicStream : System.IO.Stream + public sealed partial class ManagedQuicStream : System.Net.Quic.QuicStream { - internal ManagedQuicStream() { } + internal ManagedQuicStream() : base (default(bool)) { } public override bool CanRead { get { throw null; } } public override bool CanSeek { get { throw null; } } public override bool CanTimeout { get { throw null; } } public override bool CanWrite { get { throw null; } } - public long Id { get { throw null; } } + public override long Id { get { throw null; } } public override long Length { get { throw null; } } public override long Position { get { throw null; } set { } } - public System.Threading.Tasks.Task ReadClosed { get { throw null; } } + public override System.Threading.Tasks.Task ReadsClosed { get { throw null; } } public override int ReadTimeout { get { throw null; } set { } } - public System.Threading.Tasks.Task WriteClosed { get { throw null; } } + public override System.Threading.Tasks.Task WritesClosed { get { throw null; } } public override int WriteTimeout { get { throw null; } set { } } - public void Abort(System.Net.Quic.QuicAbortDirection abortDirection, long errorCode) { } - public void CompleteWrites() { } + public override void Abort(System.Net.Quic.QuicAbortDirection abortDirection, long errorCode) { } + public override void CompleteWrites() { } protected override void Dispose(bool disposing) { } public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; } public override void Flush() { } @@ -190,7 +190,7 @@ public override void Write(System.ReadOnlySpan buffer) { } public void Write(System.ReadOnlySpan buffer, bool endStream) { } public System.Threading.Tasks.ValueTask WriteAsync(System.Buffers.ReadOnlySequence buffers, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask WriteAsync(System.Buffers.ReadOnlySequence buffers, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } - public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, bool completeWrites, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory> buffers, bool endStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory> buffers, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs index 3ebfa33f1bec9d..2d1ec57a180c61 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicConnection.cs @@ -14,19 +14,17 @@ using System.Net.Quic.Implementations.Managed.Internal.Streams; using System.Net.Quic.Implementations.Managed.Internal.Tracing; using System.Net.Quic.Implementations.Managed.Internal.Tls; -using System.Net.Quic.Implementations.Managed.Internal.Tls.OpenSsl; using System.Net.Security; using System.Threading; using System.Threading.Tasks; using System.Security.Cryptography.X509Certificates; using System.Threading.Channels; -using System.Diagnostics.CodeAnalysis; #pragma warning disable IDE0060 namespace System.Net.Quic.Implementations.Managed { - public sealed partial class ManagedQuicConnection : IAsyncDisposable + public sealed partial class ManagedQuicConnection : QuicConnection, IAsyncDisposable { // This limit should ensure that if we can fit at least an ack frame into the packet, private const int RequiredAllowanceForSending = 2 * ConnectionId.MaximumLength + 40; @@ -235,6 +233,7 @@ public ManagedQuicConnection(QuicClientConnectionOptions options) : this(options // client constructor internal ManagedQuicConnection(QuicClientConnectionOptions options, TlsFactory tlsFactory) + : base(true) { IsServer = false; _remoteEndpoint = options.RemoteEndPoint!; @@ -263,6 +262,7 @@ internal ManagedQuicConnection(QuicClientConnectionOptions options, TlsFactory t // server constructor internal ManagedQuicConnection(QuicServerConnectionOptions options, QuicConnectionContext socketContext, EndPoint remoteEndpoint, ReadOnlySpan odcid, TlsFactory tlsFactory) + : base(true) { IsServer = true; _socketContext = socketContext; @@ -636,7 +636,7 @@ internal ValueTask DisposeAsync(long errorCode) return _closeTcs.GetTask(); } - public ValueTask DisposeAsync() + public override ValueTask DisposeAsync() { return DisposeAsync((long)TransportErrorCode.NoError); } @@ -708,10 +708,11 @@ private enum ProcessPacketResult #region Public API - public IPEndPoint LocalEndPoint => _socketContext.LocalEndPoint; + public override IPEndPoint LocalEndPoint => _socketContext.LocalEndPoint; // TODO-RZ: create a defensive copy of the endpoint - public EndPoint RemoteEndPoint => _remoteEndpoint; + // TODO: get the IP endpoint from the connected socket, not from input options as it might be DNS endpoint that needs to be resolved + public override IPEndPoint RemoteEndPoint => (IPEndPoint)_remoteEndpoint; #pragma warning disable IDE0060 // Remove unused parameter internal ValueTask ConnectAsync(CancellationToken cancellationToken = default) @@ -728,7 +729,7 @@ internal ValueTask ConnectAsync(CancellationToken cancellationToken = default) return _connectTcs.GetTask(); } - public async ValueTask OpenOutboundStreamAsync(QuicStreamType type, CancellationToken cancellationToken = default) + public override async ValueTask OpenOutboundStreamAsync(QuicStreamType type, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfError(); @@ -736,7 +737,7 @@ public async ValueTask OpenOutboundStreamAsync(QuicStreamType return await OpenStream(type == QuicStreamType.Unidirectional, cancellationToken).ConfigureAwait(false); } - public async ValueTask AcceptInboundStreamAsync(CancellationToken cancellationToken = default) + public override async ValueTask AcceptInboundStreamAsync(CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfError(); @@ -751,7 +752,7 @@ public async ValueTask AcceptInboundStreamAsync(CancellationT } } - public SslApplicationProtocol NegotiatedApplicationProtocol + public override SslApplicationProtocol NegotiatedApplicationProtocol { get { @@ -760,9 +761,9 @@ public SslApplicationProtocol NegotiatedApplicationProtocol } } - public X509Certificate? RemoteCertificate => throw new NotImplementedException(); + public override X509Certificate? RemoteCertificate => throw new NotImplementedException(); - public ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) + public override ValueTask CloseAsync(long errorCode, CancellationToken cancellationToken = default) { return DisposeAsync(errorCode); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicListener.cs index 7b51c78f2ec519..63227d92552df5 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicListener.cs @@ -1,21 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.IO; -using System.Net.Quic.Implementations.Managed.Internal; using System.Net.Quic.Implementations.Managed.Internal.Sockets; using System.Net.Quic.Implementations.Managed.Internal.Tls; -using System.Net.Quic.Implementations.Managed.Internal.Tls.OpenSsl; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; namespace System.Net.Quic.Implementations.Managed { - public sealed class ManagedQuicListener : IAsyncDisposable + public sealed class ManagedQuicListener : QuicListener, IAsyncDisposable { - public static bool IsSupported => true; - public static ValueTask ListenAsync(QuicListenerOptions options, CancellationToken cancellationToken = default) + public static new bool IsSupported => true; + public static new ValueTask ListenAsync(QuicListenerOptions options, CancellationToken cancellationToken = default) { return ValueTask.FromResult(new ManagedQuicListener(options)); } @@ -26,6 +23,7 @@ public static ValueTask ListenAsync(QuicListenerOptions opt private readonly QuicServerSocketContext _socketContext; private ManagedQuicListener(QuicListenerOptions options) + : base(true) { var listenEndPoint = options.ListenEndPoint ?? new IPEndPoint(IPAddress.Any, 0); @@ -43,14 +41,14 @@ private ManagedQuicListener(QuicListenerOptions options) public IPEndPoint ListenEndPoint => _socketContext.LocalEndPoint; - public ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) + public override async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed, this); - return _acceptQueue.ReadAsync(cancellationToken); + return await _acceptQueue.ReadAsync(cancellationToken).ConfigureAwait(false); } - public ValueTask DisposeAsync() + public override ValueTask DisposeAsync() { if (_disposed) return ValueTask.CompletedTask; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs index 49bde63a07866e..0f1f8cb6f1dcdf 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/Managed/ManagedQuicStream.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#nullable enable - using System.Buffers; using System.Collections.Generic; using System.Diagnostics; @@ -14,7 +12,7 @@ namespace System.Net.Quic.Implementations.Managed { - public sealed class ManagedQuicStream : Stream + public sealed class ManagedQuicStream : QuicStream { /// /// Node to the linked list of all flushable streams. Should be accessed only by the class. @@ -58,6 +56,7 @@ public sealed class ManagedQuicStream : Stream internal SendStream? SendStream { get; } internal ManagedQuicStream(long streamId, ReceiveStream? receiveStream, SendStream? sendStream, ManagedQuicConnection connection) + : base(true) { // trivial check whether buffer nullable combination makes sense with respect to streamId Debug.Assert(receiveStream != null || sendStream != null); @@ -78,17 +77,17 @@ internal ManagedQuicStream(long streamId, ReceiveStream? receiveStream, SendStre public override bool CanSeek => false; public override bool CanTimeout => false; - public long Id { get; } + public override long Id { get; } public override long Length => throw new NotSupportedException(); public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - public Task ReadClosed => throw new NotImplementedException(); + public override Task ReadsClosed => throw new NotImplementedException(); public override int ReadTimeout { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - public Task WriteClosed => throw new NotImplementedException(); + public override Task WritesClosed => throw new NotImplementedException(); public override int WriteTimeout { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } - public void Abort(QuicAbortDirection abortDirection, long errorCode) + public override void Abort(QuicAbortDirection abortDirection, long errorCode) { ThrowIfDisposed(); @@ -103,7 +102,7 @@ public void Abort(QuicAbortDirection abortDirection, long errorCode) } } - public void CompleteWrites() + public override void CompleteWrites() { ThrowIfDisposed(); ThrowIfConnectionError(); @@ -209,14 +208,14 @@ public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationTo return WriteAsync(buffer, false, cancellationToken); } - public async ValueTask WriteAsync(ReadOnlyMemory buffer, bool endStream, CancellationToken cancellationToken = default) + public override async ValueTask WriteAsync(ReadOnlyMemory buffer, bool completeWrites, CancellationToken cancellationToken = default) { ThrowIfDisposed(); ThrowIfConnectionError(); ThrowIfNotWritable(); // TODO-RZ: optimize away some of the copying - await WriteAsyncInternal(buffer, endStream, cancellationToken).ConfigureAwait(false); + await WriteAsyncInternal(buffer, completeWrites, cancellationToken).ConfigureAwait(false); await FlushAsync(cancellationToken).ConfigureAwait(false); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs index bf8a56c4a0107d..91fbf6f7caae6d 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.cs @@ -592,7 +592,7 @@ private static unsafe int NativeCallback(QUIC_HANDLE* connection, void* context, /// And releases all resources associated with the connection. /// /// A task that represents the asynchronous dispose operation. - public async ValueTask DisposeAsync() + public virtual async ValueTask DisposeAsync() { if (Interlocked.Exchange(ref _disposed, 1) != 0) { diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs index ec679130be8e70..4a179c0fb3a567 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicListener.cs @@ -179,7 +179,7 @@ private unsafe QuicListener(QuicListenerOptions options) /// /// A cancellation token that can be used to cancel the asynchronous operation. /// A task that will contain a fully connected which successfully finished the handshake and is ready to be used. - public async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) + public virtual async ValueTask AcceptConnectionAsync(CancellationToken cancellationToken = default) { ObjectDisposedException.ThrowIf(_disposed == 1, this); @@ -367,7 +367,7 @@ private static unsafe int NativeCallback(QUIC_HANDLE* listener, void* context, Q /// Stops listening for new connections and releases all resources associated with the listener. /// /// A task that represents the asynchronous dispose operation. - public async ValueTask DisposeAsync() + public virtual async ValueTask DisposeAsync() { if (Interlocked.Exchange(ref _disposed, 1) != 0) {