예제 #1
0
        protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(ValueTask.FromCanceled(cancellationToken));
            }

            try
            {
                if (method != ConnectionCloseMethod.GracefulShutdown)
                {
                    // Dispose must be called first in order to cause a connection reset,
                    // as NetworkStream.Dispose() will call Shutdown(Both).
                    _socket.Dispose();
                }

                // Since CreatePipe() calls CreateStream(), so _stream should be present even in the pipe case:
                _stream?.Dispose();
            }
            catch (SocketException socketException)
            {
                return(ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(socketException)));
            }
            catch (Exception ex)
            {
                return(ValueTask.FromException(ex));
            }

            return(default);
예제 #2
0
        public async Task Connection_CloseAsync_ClosesSocket(bool usePipe, ConnectionCloseMethod method)
        {
            using var server = SocketTestServer.SocketTestServerFactory(SocketImplementationType.Async, IPAddress.Loopback);
            using SocketsConnectionFactory factory = new SocketsConnectionFactory(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            Connection connection = await factory.ConnectAsync(server.EndPoint);

            Stream stream = null;

            if (usePipe)
            {
                _ = connection.Pipe;
            }
            else
            {
                stream = connection.Stream;
            }

            connection.ConnectionProperties.TryGet(out Socket socket);

            await connection.CloseAsync(method);

            Assert.Throws <ObjectDisposedException>(() => socket.Send(new byte[1]));

            if (!usePipe) // No way to observe the stream if we work with the pipe
            {
                Assert.Throws <ObjectDisposedException>(() => stream.Write(new byte[1]));
            }
        }
예제 #3
0
        protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(ValueTask.FromCanceled(cancellationToken));
            }

            try
            {
                if (method != ConnectionCloseMethod.GracefulShutdown)
                {
                    // Dispose must be called first in order to cause a connection reset,
                    // as NetworkStream.Dispose() will call Shutdown(Both).
                    _stream.Socket.Dispose();
                }

                _stream.Dispose();
            }
            catch (SocketException socketException)
            {
                return(ValueTask.FromException(ExceptionDispatchInfo.SetCurrentStackTrace(NetworkErrorHelper.MapSocketException(socketException))));
            }
            catch (Exception ex)
            {
                return(ValueTask.FromException(ex));
            }

            return(default);
예제 #4
0
        public async Task FromPipe_CloseMethod_Flushed(ConnectionCloseMethod method, bool shouldFlush)
        {
            bool pipeFlushed = false;

            var pipe = new MockPipe
            {
                Input = new MockPipeReader()
                {
                    OnCompleteAsync = _ => default
                },
예제 #5
0
        /// <summary>
        /// Closes the connection.
        /// </summary>
        /// <param name="method">The method to use when closing the connection.</param>
        /// <param name="cancellationToken">A cancellation token for the asynchronous operation.</param>
        /// <returns>A <see cref="ValueTask"/> for the asynchronous operation.</returns>
        public async ValueTask CloseAsync(ConnectionCloseMethod method = ConnectionCloseMethod.GracefulShutdown, CancellationToken cancellationToken = default)
        {
            if (!_disposed)
            {
                await CloseAsyncCore(method, cancellationToken).ConfigureAwait(false);

                _disposed = true;
            }
            GC.SuppressFinalize(this);
        }
예제 #6
0
            protected override async ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
            {
                if (_originalPipe == null)
                {
                    return;
                }

                Exception?inputException, outputException;

                if (method == ConnectionCloseMethod.GracefulShutdown)
                {
                    // Flush happens implicitly from CompleteAsync(null), so only flush here if we need cancellation.
                    if (cancellationToken.CanBeCanceled)
                    {
                        FlushResult r = await _originalPipe.Output.FlushAsync(cancellationToken).ConfigureAwait(false);

                        if (r.IsCanceled)
                        {
                            cancellationToken.ThrowIfCancellationRequested();
                        }
                    }

                    inputException  = null;
                    outputException = null;
                }
                else
                {
                    inputException  = ExceptionDispatchInfo.SetCurrentStackTrace(new ObjectDisposedException(nameof(Connection)));
                    outputException = ExceptionDispatchInfo.SetCurrentStackTrace(new ObjectDisposedException(nameof(Connection)));
                }

                await _originalPipe.Input.CompleteAsync(inputException).ConfigureAwait(false);

                await _originalPipe.Output.CompleteAsync(outputException).ConfigureAwait(false);

                if (!_leaveOpen)
                {
                    switch (_originalPipe)
                    {
                    case IAsyncDisposable d:
                        await d.DisposeAsync().ConfigureAwait(false);

                        break;

                    case IDisposable d:
                        d.Dispose();
                        break;
                    }
                }

                _originalPipe = null;
            }
예제 #7
0
        public async Task FromStream_CloseMethod_Flushed(ConnectionCloseMethod method, bool shouldFlush)
        {
            bool streamFlushed = false;

            var stream = new MockStream
            {
                OnFlushAsync = _ => { streamFlushed = true; return(Task.CompletedTask); }
            };

            var con = Connection.FromStream(stream, leaveOpen: true);

            await con.CloseAsync(method);

            Assert.Equal(shouldFlush, streamFlushed);
        }
예제 #8
0
            protected override async ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
            {
                if (_originalStream == null)
                {
                    return;
                }

                if (method == ConnectionCloseMethod.GracefulShutdown)
                {
                    await _originalStream.FlushAsync(cancellationToken).ConfigureAwait(false);
                }

                if (!_leaveOpen)
                {
                    await _originalStream.DisposeAsync().ConfigureAwait(false);
                }

                _originalStream = null;
            }
예제 #9
0
        protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(ValueTask.FromCanceled(cancellationToken));
            }

            try
            {
                if (method != ConnectionCloseMethod.GracefulShutdown)
                {
                    this.socket.Dispose();
                }

                this.stream?.Dispose();
            }
            catch (Exception ex)
            {
                return(ValueTask.FromException(ex));
            }

            return(default);
예제 #10
0
        protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(ValueTask.FromCanceled(cancellationToken));
            }

            try
            {
                if (method != ConnectionCloseMethod.GracefulShutdown)
                {
                    // Dispose must be called first in order to cause a connection reset,
                    // as NetworkStream.Dispose() will call Shutdown(Both).
                    _stream.Socket.Dispose();
                }

                _stream.DisposeWithoutClosingConnection();
            }
            catch (Exception ex)
            {
                return(ValueTask.FromException(ex));
            }

            return(default);
예제 #11
0
 /// <summary>
 /// Closes the connection.
 /// </summary>
 /// <param name="method">The method to use when closing the connection.</param>
 /// <param name="cancellationToken">A cancellation token for the asynchronous operation.</param>
 /// <returns>A <see cref="ValueTask"/> for the asynchronous operation.</returns>
 protected abstract ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken);
예제 #12
0
 protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken) =>
 OnCloseAsyncCore(method, cancellationToken);
예제 #13
0
 protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }