public static void ReceiveData(List <byte> data, ReadState readState, Fleck2Extensions.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; switch (length) { case 127: if (data.Count < index + 8) { return; //Not complete } payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; break; case 126: if (data.Count < index + 2) { return; //Not complete } payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; break; default: payloadLength = length; break; } if (data.Count < index + 4) { return; //Not complete } var maskBytes = data.Skip(index).Take(4).ToList(); index += 4; if (data.Count < index + payloadLength) { return; //Not complete } var i = 0; var payload = data.Skip(index) .Take(payloadLength) .Select(value => (byte)(value ^ maskBytes[i++ % 4])); readState.Data.AddRange(payload); data.RemoveRange(0, index + payloadLength); if (frameType != FrameType.Continuation) { readState.FrameType = frameType; } if (!isFinal || !readState.FrameType.HasValue) { continue; } var stateData = readState.Data.ToArray(); var stateFrameType = readState.FrameType; readState.Clear(); processFrame(stateFrameType.Value, stateData); } }
public static void ReceiveData(List<byte> data, ReadState readState, Action<FrameType, byte[]> processFrame) { while (data.Count >= 2) { var isFinal = (data[0] & 128) != 0; var frameType = (FrameType)(data[0] & 15); var isMasked = (data[1] & 128) != 0; var length = (data[1] & 127); if (!isMasked) throw new WebSocketException("Client data must be masked"); if (frameType == FrameType.Continuation && !readState.FrameType.HasValue) throw new WebSocketException("Unexpected continuation frame received"); var index = 2; int payloadLength; if (length == 127) { if (data.Count < index + 8) return; //Not complete payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; } else if (length == 126) { if (data.Count < index + 2) return; //Not complete payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; } else { payloadLength = length; } if (data.Count < index + 4) return; //Not complete var maskBytes = data.Skip(index).Take(4).ToArray(); index += 4; if (data.Count < index + payloadLength) return; //Not complete var payload = data .Skip(index) .Take(payloadLength) .Select((x, i) => (byte)(x ^ maskBytes[i % 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); } } }
public static void ReceiveData(List<byte> data, ReadState readState, Fleck2Extensions.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; switch (length) { case 127: if (data.Count < index + 8) return; //Not complete payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; break; case 126: if (data.Count < index + 2) return; //Not complete payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; break; default: payloadLength = length; break; } if (data.Count < index + 4) return; //Not complete var maskBytes = data.Skip(index).Take(4).ToList(); index += 4; if (data.Count < index + payloadLength) return; //Not complete var i = 0; var payload = data.Skip(index) .Take(payloadLength) .Select(value => (byte)(value ^ maskBytes[i++ % 4])); readState.Data.AddRange(payload); data.RemoveRange(0, index + payloadLength); if (frameType != FrameType.Continuation) readState.FrameType = frameType; if (!isFinal || !readState.FrameType.HasValue) { continue; } var stateData = readState.Data.ToArray(); var stateFrameType = readState.FrameType; readState.Clear(); processFrame(stateFrameType.Value, stateData); } }
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); } } }
public static void ReceiveData(List <byte> data, ReadState readState, Action <FrameType, byte[]> processFrame) { while (data.Count >= 2) { var isFinal = (data[0] & 128) != 0; var frameType = (FrameType)(data[0] & 15); var isMasked = (data[1] & 128) != 0; var length = (data[1] & 127); if (!isMasked) { throw new WebSocketException("Client data must be masked"); } if (frameType == FrameType.Continuation && !readState.FrameType.HasValue) { throw new WebSocketException("Unexpected continuation frame received"); } var index = 2; int payloadLength; if (length == 127) { if (data.Count < index + 8) { return; //Not complete } payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; } else if (length == 126) { if (data.Count < index + 2) { return; //Not complete } payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; } else { payloadLength = length; } if (data.Count < index + 4) { return; //Not complete } var maskBytes = data.Skip(index).Take(4).ToArray(); index += 4; if (data.Count < index + payloadLength) { return; //Not complete } var payload = data .Skip(index) .Take(payloadLength) .Select((x, i) => (byte)(x ^ maskBytes[i % 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); } } }
private void ProcessData(ArraySegment <byte> data, Action <IList <byte>, FrameType> processFrame) { var buffer = new byte[data.Count]; Array.Copy(data.Array, buffer, data.Count); readState.Data.AddRange(buffer); while (readState.Data.Count() > 2) { var bytesRead = readState.Data.Count; var reservedBits = (readState.Data[0] & 112); bool isFinal = (readState.Data[0] & 128) != 0; //bool isMasked = (readState.Data[1] & 128) != 0; var frameType = (FrameType)(readState.Data[0] & 15); if (reservedBits != 0) { return; } int length = (readState.Data[1] & 127); int index = 2; switch (length) { case 127: if (bytesRead < index + 8) { return; } readState.Length = readState.Data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; break; case 126: if (bytesRead < index + 2) { return; } readState.Length = readState.Data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; break; default: readState.Length = length; break; } if (readState.Data.Count < index + 4) { return; } if (bytesRead < readState.Length + index) { return; } var payload = readState.Data.GetRange(index, readState.Length); readState.Data.RemoveRange(0, index + readState.Length); readState.FrameBytes.AddRange(payload); if (frameType != FrameType.Continuation) { readState.FrameType = frameType; } if (!isFinal && readState.FrameType.HasValue) { continue; } if (!readState.FrameType.HasValue) { throw new Exception("FrameType unknown"); } processFrame(readState.FrameBytes, readState.FrameType.Value); readState.Clear(); } }
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); var isControlFrame = (data[0]&15) >= 0x08 && (data[0]&15) <= 0x0F; 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; // control frame types may only have a maximum payload length of 125 (autobahn test case 2.5) if (isControlFrame && length > 125) throw new WebSocketException(WebSocketStatusCodes.ProtocolError); // control frames must not be fragmented (autobahn test case 5.1) if (isControlFrame && !isFinal) throw new WebSocketException(WebSocketStatusCodes.ProtocolError); // a close frame MAY contain data, but if it does, it must be at least 2 bytes (autobahn test case 7.3.2) if (frameType == FrameType.Close && length == 1) throw new WebSocketException(WebSocketStatusCodes.ProtocolError); if (length == 127) { if (data.Count < index + 8) return; //Not complete payloadLength = data.Skip(index).Take(8).ToArray().ToLittleEndianInt(); index += 8; } else if (length == 126) { if (data.Count < index + 2) return; //Not complete payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; } else { payloadLength = length; } if (data.Count < index + 4) return; //Not complete var maskBytes = data.Skip(index).Take(4).ToArray(); index += 4; if (data.Count < index + payloadLength) return; //Not complete var payload = data .Skip(index) .Take(payloadLength) .Select((x, i) => (byte)(x ^ maskBytes[i % 4])); // control frames are processed immediatly (since they cannot be fragmented) and can be receive in between // and can be received and processed between a fragmented frame (autobahn test case 5.6) if (isControlFrame) { processFrame(frameType, payload.ToArray()); data.RemoveRange(0, index + payloadLength); } else { readState.Data.AddRange(payload); data.RemoveRange(0, index + payloadLength); // frame types for multiple fragments are sent on the first frame, and the rest of the fragments must // have a frame type of continuation (autobahn test case 5.18) if (readState.FragmentNumber == 1) readState.FrameType = frameType; else if(frameType != FrameType.Continuation) throw new WebSocketException(WebSocketStatusCodes.ProtocolError); readState.FragmentNumber++; if (isFinal && readState.FrameType.HasValue) { var stateData = readState.Data.ToArray(); var stateFrameType = readState.FrameType; readState.Clear(); processFrame(stateFrameType.Value, stateData); } } } }
private 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(); index += 8; } else if (length == 126) { if (data.Count < index + 2) { return; //Not complete } payloadLength = data.Skip(index).Take(2).ToArray().ToLittleEndianInt(); index += 2; } else { payloadLength = length; } if (data.Count < index + 4) { return; //Not complete } var maskBytes = data.Skip(index).Take(4).ToArray(); index += 4; if (data.Count < index + payloadLength) { return; //Not complete } byte[] payloadData = new byte[payloadLength]; for (int i = 0; i < payloadLength; i++) { payloadData[i] = (byte)(data[index + i] ^ maskBytes[i % 4]); } readState.Data.AddRange(payloadData); 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); } } }