private static bool IsAnythingReceived(SocketReceiveResult result) => result != null && result.ContentBytes != null && result.ContentBytes.Length != 0;
private async Task ConnectionLoopAsync() { Exception closeException = null; try { _lastMessageID = 7; _connectionCts = new CancellationTokenSource(); ArraySegment <byte> buffer = new ArraySegment <byte>(new byte[1024]); while (_connectionCts?.Token.IsCancellationRequested != true) { // read from stream SocketReceiveResult receivedMessage = await ReceiveAsync(buffer, _connectionCts.Token).ConfigureAwait(false); if (!IsAnythingReceived(receivedMessage)) { continue; } // parse the message if (receivedMessage.MessageType == WebSocketMessageType.Text) { SocketMessage msg = SocketMessage.Parse(this.MessageEncoding.GetString(receivedMessage.ContentBytes)); // if message is binary, read them from stream as well List <byte[]> binaryMessages = new List <byte[]>(msg.BinaryMessagesCount); for (int i = 0; i < msg.BinaryMessagesCount; i++) { SocketReceiveResult receivedBinaryMessage = await ReceiveAsync(buffer, _connectionCts.Token).ConfigureAwait(false); if (!IsAnythingReceived(receivedBinaryMessage)) { continue; } if (receivedBinaryMessage.MessageType == WebSocketMessageType.Text) { throw new InvalidDataException("Received a text message while a binary message was expected"); } binaryMessages.Add(receivedBinaryMessage.ContentBytes); } // raise event OnTextMessageReceived(msg, binaryMessages); } else { throw new InvalidDataException("Received a binary message while a text message was expected"); } } } catch (Exception ex) { closeException = ex; // ignore premature close and task cancellations // these should be treated as normal close event, not an error if (!IsClosedPrematurelyException(ex) && !(ex is OperationCanceledException)) { ErrorRaised?.Invoke(this, new UnhandledExceptionEventArgs(ex, true)); } } finally { // craft closed event, keeping the exception in mind WebSocketCloseStatus status = _websocketClient?.CloseStatus ?? // websocketclient reported status has priority (IsClosedPrematurelyException(closeException) ? WebSocketCloseStatus.ProtocolError : // if premature close, report as protocol error (closeException is OperationCanceledException) ? WebSocketCloseStatus.NormalClosure : // if operation canceled, report as normal closure WebSocketCloseStatus.Empty); // otherwise report unknown status string message = _websocketClient?.CloseStatusDescription ?? closeException?.Message; // clear cancels and nulls cts, so IsConnected will start returning false this.Clear(); Disconnected?.Invoke(this, new SocketClosedEventArgs(status, message, closeException)); } }