diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs index fcc975f021dd2060c9b6ed1a5e2051accb8f2c53..ee5dba0ef41b42cf1a29e5c777704f2786c40619 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs @@ -161,21 +161,21 @@ private uint HandleEventShutdownInitiatedByTransport(ref ConnectionEvent connect _connectTcs.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex)); } - _acceptQueue.Writer.Complete(); - return MsQuicStatusCodes.Success; } private uint HandleEventShutdownInitiatedByPeer(ref ConnectionEvent connectionEvent) { _abortErrorCode = connectionEvent.Data.ShutdownInitiatedByPeer.ErrorCode; - _acceptQueue.Writer.Complete(); return MsQuicStatusCodes.Success; } private uint HandleEventShutdownComplete(ref ConnectionEvent connectionEvent) { _shutdownTcs.SetResult(MsQuicStatusCodes.Success); + + // Stop accepting new streams. + _acceptQueue?.Writer.Complete(); return MsQuicStatusCodes.Success; } @@ -291,7 +291,7 @@ internal override ValueTask ConnectAsync(CancellationToken cancellationToken = d private void SetCallbackHandler() { - Debug.Assert(!_handle.IsAllocated); + Debug.Assert(!_handle.IsAllocated, "callback handler allocated already"); _handle = GCHandle.Alloc(this); MsQuicApi.Api.SetCallbackHandlerDelegate( @@ -310,8 +310,6 @@ private void SetCallbackHandler() ErrorCode); QuicExceptionHelpers.ThrowIfFailed(status, "Failed to shutdown connection."); - Debug.Assert(_shutdownTcs.Task.IsCompleted == false); - return new ValueTask(_shutdownTcs.Task); } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs index 60b17a6ad0e01594afa6b83d2b360f6d6eef494d..192085132b963b8f9850588078eb2b76184d23c9 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicListener.cs @@ -34,7 +34,7 @@ internal sealed class MsQuicListener : QuicListenerProvider, IDisposable private QuicListenerOptions _options; private volatile bool _disposed; private IPEndPoint _listenEndPoint; - + private bool _started; private readonly Channel _acceptConnectionQueue; internal MsQuicListener(QuicListenerOptions options) @@ -120,6 +120,13 @@ internal override void Start() { ThrowIfDisposed(); + // protect against double starts. + if (_started) + { + throw new QuicException("Cannot start Listener multiple times"); + } + + _started = true; SetCallbackHandler(); SOCKADDR_INET address = MsQuicAddressHelpers.IPEndPointToINet(_listenEndPoint); @@ -202,7 +209,7 @@ private void StopAcceptingConnections() internal void SetCallbackHandler() { - Debug.Assert(!_handle.IsAllocated); + Debug.Assert(!_handle.IsAllocated, "listener allocated"); _handle = GCHandle.Alloc(this); MsQuicApi.Api.SetCallbackHandlerDelegate( diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs index 5379f1ff1ce00b7929c72d1049f02592d9be01d4..66ea94d218b4d238d9eb935e8db7739bc1bb78c8 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs @@ -71,7 +71,7 @@ internal sealed class MsQuicStream : QuicStreamProvider // Creates a new MsQuicStream internal MsQuicStream(MsQuicConnection connection, QUIC_STREAM_OPEN_FLAG flags, IntPtr nativeObjPtr, bool inbound) { - Debug.Assert(connection != null); + Debug.Assert(connection != null, "Connection null"); _ptr = nativeObjPtr; @@ -936,7 +936,7 @@ private void SetCallbackHandler() /// private void StartLocalStream() { - Debug.Assert(!_started); + Debug.Assert(!_started, "start local stream"); uint status = MsQuicApi.Api.StreamStartDelegate( _ptr, (uint)QUIC_STREAM_START_FLAG.ASYNC); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs index 21388ed3702306b8f7ebc6fabeb15daf7e5e48c2..2614a7a49d7dbe698fc1ac8e5904d8360f038691 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs @@ -177,6 +177,23 @@ public async Task CallDifferentWriteMethodsWorks() Assert.Equal(24, res); } + [Fact] + public async Task CloseAsync_ByServer_AcceptThrows() + { + await RunClientServer( + clientConnection => + { + return Task.CompletedTask; + }, + async serverConnection => + { + var acceptTask = serverConnection.AcceptStreamAsync(); + await serverConnection.CloseAsync(errorCode: 0); + // make sure + await Assert.ThrowsAsync(() => acceptTask.AsTask()); + }); + } + private static ReadOnlySequence CreateReadOnlySequenceFromBytes(byte[] data) { List segments = new List diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs index a1e9bf3b72bae1534e972fa43a7d689393c82f92..3fbfcaf75c653e20e7c3d2abe1e2d60a2b706441 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicListenerTests.cs @@ -21,10 +21,11 @@ public async Task Listener_Backlog_Success() using QuicListener listener = CreateQuicListener(); using QuicConnection clientConnection = CreateQuicConnection(listener.ListenEndPoint); - await clientConnection.ConnectAsync(); + var clientStreamTask = clientConnection.ConnectAsync(); using QuicConnection serverConnection = await listener.AcceptConnectionAsync(); - }).TimeoutAfter(millisecondsTimeout: 5_000); + await clientStreamTask; + }).TimeoutAfter(millisecondsTimeout: 6_000); } } diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs index e339ac1a30ac65aab353356cd10834ff84a8b07e..3da7e7e9bf8d36ee644241f780da72d3b923751e 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicStreamTests.cs @@ -305,8 +305,6 @@ public async Task LargeDataSentAndReceived() } } - - [Fact] public async Task TestStreams() {