public static void ProcessFrame(FrameType frameType, byte[] data, Action <string> onMessage, Action onClose, Action <byte[]> onBinary, Action <byte[]> onPing, Action <byte[]> onPong) { switch (frameType) { case FrameType.Close: if (data.Length == 1 || data.Length > 125) { throw new WebSocketException(WebSocketStatusCodes.ProtocolError); } if (data.Length >= 2) { //var closeCode = (ushort)data.Take(2).ToArray().ToLittleEndianInt(); byte[] _codeAry = new byte[] { data[0], data[1] }; var closeCode = (ushort)IntExtensions.ToLittleEndianInt(_codeAry); if ( //!WebSocketStatusCodes.ValidCloseCodes.Contains(closeCode) -1 == Array.IndexOf(WebSocketStatusCodes.ValidCloseCodes, closeCode) && (closeCode < 3000 || closeCode > 4999)) { throw new WebSocketException(WebSocketStatusCodes.ProtocolError); } } if (data.Length > 2) { //ReadUTF8PayloadData(data.Skip(2).ToArray()); var _dataAry = LinqExtensions.SkipTakeToArray(data, 2); ReadUTF8PayloadData(_dataAry); } onClose(); break; case FrameType.Binary: onBinary(data); break; case FrameType.Ping: onPing(data); break; case FrameType.Pong: onPong(data); break; case FrameType.Text: onMessage(ReadUTF8PayloadData(data)); break; default: FleckLog.Debug("Received unhandled " + frameType); break; } }
public static void ReceiveData(List <byte> data, ReadState readState, Action <FrameType, byte[]> processFrame) { while (data.Count >= 2) { var isFinal = (data[0] & 128) != 0; var reservedBits = (data[0] & 112); var frameType = (FrameType)(data[0] & 15); var isMasked = (data[1] & 128) != 0; var length = (data[1] & 127); if (!isMasked || !Enum.IsDefined(typeof(FrameType), frameType) || reservedBits != 0 || //Must be zero per spec 5.2 (frameType == FrameType.Continuation && !readState.FrameType.HasValue)) { throw new WebSocketException(WebSocketStatusCodes.ProtocolError); } var index = 2; int payloadLength; if (length == 127) { if (data.Count < index + 8) { return; //Not complete } //payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); var _data = LinqExtensions.SkipTakeToArray( data.ToArray(), index, 8 ); payloadLength = IntExtensions.ToLittleEndianInt(_data); index += 8; } else if (length == 126) { if (data.Count < index + 2) { return; //Not complete } //payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); var _data = LinqExtensions.SkipTakeToArray( data.ToArray(), index, 2 ); payloadLength = IntExtensions.ToLittleEndianInt(_data); index += 2; } else { payloadLength = length; } if (data.Count < index + 4) { return; //Not complete } //var maskBytes = data.Skip(index).Take(4).ToArray(); var maskBytes = LinqExtensions.SkipTakeToArray( data.ToArray(), index, 4 ); index += 4; if (data.Count < index + payloadLength) { return; //Not complete } //var payload = data //.Skip(index) //.Take(payloadLength) //.Select((x, idx) => (byte)(x ^ maskBytes[idx % 4])); var payload = LinqExtensions.SkipTakeToArray( data.ToArray(), index, payloadLength, (x, idx) => (byte)(x ^ maskBytes[idx % 4]) ); readState.Data.AddRange(payload); data.RemoveRange(0, index + payloadLength); if (frameType != FrameType.Continuation) { readState.FrameType = frameType; } if (isFinal && readState.FrameType.HasValue) { var stateData = readState.Data.ToArray(); var stateFrameType = readState.FrameType; readState.Clear(); processFrame(stateFrameType.Value, stateData); } } }