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);
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])); } }
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);
public async Task FromPipe_CloseMethod_Flushed(ConnectionCloseMethod method, bool shouldFlush) { bool pipeFlushed = false; var pipe = new MockPipe { Input = new MockPipeReader() { OnCompleteAsync = _ => default },
/// <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); }
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; }
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); }
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; }
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);
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);
/// <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);
protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken) => OnCloseAsyncCore(method, cancellationToken);
protected override ValueTask CloseAsyncCore(ConnectionCloseMethod method, CancellationToken cancellationToken) { throw new NotImplementedException(); }