/// <summary> /// Closes the transport. /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> /// <exception cref="System.NotImplementedException"></exception> protected override Task PerformCloseAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _stream?.Close(); _tcpClient.Close(); return(_envelopePipe.StopAsync(cancellationToken)); }
/// <summary> /// Closes the transport, implementing the websocket close handshake. /// </summary> /// <param name="cancellationToken"></param> /// <returns></returns> /// <exception cref="InvalidOperationException">The listener is not active</exception> protected override async Task PerformCloseAsync(CancellationToken cancellationToken) { await _closeSemaphore.WaitAsync(cancellationToken); try { await _envelopePipe.StopAsync(cancellationToken); // Awaits for the client to send the close connection frame. // If the session was clearly closed, the client should received the finished envelope and is closing the connection. using (var cts = new CancellationTokenSource(CloseTimeout)) using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token)) { if (WebSocket.State == WebSocketState.Open || WebSocket.State == WebSocketState.CloseReceived) { if (_closeGracefully) { await WebSocket.CloseAsync(_closeStatus, _closeStatusDescription, linkedCts.Token) .ConfigureAwait(false); } else { await WebSocket.CloseOutputAsync(_closeStatus, _closeStatusDescription, linkedCts.Token) .ConfigureAwait(false); } } } } finally { _closeSemaphore.Release(); } }