internal async Task CleanupAsync() { switch (_gameSocket.State) { case GameSocketState.Closed: // Closed gracefully, no action needed. case GameSocketState.Aborted: // Closed abortively, no action needed. break; case GameSocketState.CloseReceived: // Echo what the client said, if anything. await _gameSocket.CloseAsync(_gameSocket.CloseStatus ?? GameSocketCloseStatus.NormalClosure, _gameSocket.CloseStatusDescription ?? string.Empty, _cancellationToken); break; case GameSocketState.Open: case GameSocketState.CloseSent: // No close received, abort so we don't have to drain the pipe. _gameSocket.Abort(); break; default: throw new NotSupportedException($"Unsupported {nameof(GameSocketState)} value: {_gameSocket.State}."); } }