private bool ReceiveFrame() { // check if enough bytes ready ushort required_count = this.currentHeader.Length; if (this.pendingBytes.Count < required_count) { return(false); } this.ReceiveState = ReceiveStates.ReceiveStartByte; // create emission description EmissionDescriptor desc = new EmissionDescriptor(this.currentHeader, this.pendingBytes.Take(required_count).ToList()); this.mutexEmissions.WaitOne(); this.emissions.Add(desc); this.mutexEmissions.ReleaseMutex(); // remove emission bytes this.pendingBytes.RemoveRange(0, required_count); // invoke callback if (this.OnEmission != null) { this.OnEmission(this, desc); } return(true); }
// Handle data read in worker thread private void ReceivedDataEvent(byte[] ReadBuffer, int BufferLength) { for (int x = 0; x < BufferLength; x++) { switch (CurrentState) { case ReceiveStates.HEADER1: if (ReadBuffer[x] == PacketHeader[0]) { CurrentState = ReceiveStates.HEADER2; } break; case ReceiveStates.HEADER2: if (ReadBuffer[x] == PacketHeader[1]) { CurrentState = ReceiveStates.SIZE; } else { CurrentState = ReceiveStates.HEADER1; } break; case ReceiveStates.SIZE: CurrentPayloadSize = ReadBuffer[x]; CurrentState = ReceiveStates.TYPE; break; case ReceiveStates.TYPE: CurrentPayloadType = ReadBuffer[x]; CurrentBytesRead = 0; CurrentState = ReceiveStates.PAYLOAD; break; case ReceiveStates.PAYLOAD: PayloadBuffer[CurrentBytesRead] = ReadBuffer[x]; CurrentBytesRead++; if (CurrentBytesRead == CurrentPayloadSize) { OnPacketReceived(CurrentPayloadType, PayloadBuffer, CurrentBytesRead); CurrentState = ReceiveStates.HEADER1; } break; } } }
private bool ReceiveHeader() { // check if enough bytes ready int required_count = CONSTANTS.EMISSION_HEADER_SIZE; if (this.pendingBytes.Count < required_count) { return(false); } this.ReceiveState = ReceiveStates.ReceiveFrame; // decode header this.currentHeader.Unpack(this.pendingBytes.Take(required_count).ToList()); // remove header bytes this.pendingBytes.RemoveRange(0, required_count); return(true); }
private bool ReceiveStartByte() { // find start byte bool success = false; int index = this.pendingBytes.FindIndex(b => b == CONSTANTS.FRAME_START_BYTE); // determine success if (index < 0) // if start byte not found, remove all bytes { index = this.pendingBytes.Count; } else { this.ReceiveState = ReceiveStates.ReceiveHeader; success = true; // if start byte found, remove bytes leading up to it and indicate success } // remove all bytes leading up to start byte if (index > 0) { this.pendingBytes.RemoveRange(0, index); } return(success); }
/// <summary> /// Get packets out of the received data. Check length, checksum and header. /// Modified version of the original code from KSPSerialIO. /// The original code made sure, that it's possible to receive the data in packs /// smaller than one full frame. The Tcp Server receives the data in whole frames, /// in worst case multiple frames are buffered. So CurrentState has not to be saved /// between multiple calls. /// </summary> /// <param name="data">Received data</param> private void ReceivedDataEvent(byte[] data) { ReceiveStates CurrentState = ReceiveStates.FIRSTHEADER; byte CurrentPacketLength = 0; byte CurrentBytesRead = 0; byte[] PayloadBuffer = new byte[DataPackets.MaxPayloadSize]; byte[] NewPacketBuffer = new byte[DataPackets.MaxPayloadSize]; for (int x = 0; x < data.Length; x++) { switch (CurrentState) { case ReceiveStates.FIRSTHEADER: if (data[x] == 0xBE) { CurrentState = ReceiveStates.SECONDHEADER; } break; case ReceiveStates.SECONDHEADER: if (data[x] == 0xEF) { CurrentState = ReceiveStates.SIZE; } else { CurrentState = ReceiveStates.FIRSTHEADER; } break; case ReceiveStates.SIZE: CurrentPacketLength = data[x]; CurrentBytesRead = 0; CurrentState = ReceiveStates.PAYLOAD; break; case ReceiveStates.PAYLOAD: PayloadBuffer[CurrentBytesRead] = data[x]; CurrentBytesRead++; if (CurrentBytesRead == CurrentPacketLength) { CurrentState = ReceiveStates.CS; } break; case ReceiveStates.CS: if (CompareChecksum(data[x], CurrentPacketLength, PayloadBuffer)) { Buffer.BlockCopy(PayloadBuffer, 0, NewPacketBuffer, 0, CurrentBytesRead); InboundPacketHandler(NewPacketBuffer); } else { Debug.LogWarning("[KSPEthernetIO]: Checksum error"); } CurrentState = ReceiveStates.FIRSTHEADER; break; } } }
private async Task <ReceivedWapMessage> ReceiveMessage(CancellationToken ct) { ReceiveStates state = ReceiveStates.Idle; List <byte> msgBytes = new List <byte>(); await _rxSem.WaitAsync(ct); while (true) { if (ct.IsCancellationRequested) { _rxSem.Release(); ct.ThrowIfCancellationRequested(); } byte[] bs; if (_bufBytes.Count > 0) { bs = _bufBytes.ToArray(); _bufBytes.Clear(); } else { byte[] buf = new byte[ReadBlockSize]; int count = await _stream.ReadAsync(buf, 0, ReadBlockSize, ct).ConfigureAwait(false); if (count == 0) { _rxSem.Release(); throw new OperationCanceledException("End of Stream reached during reading"); } bs = new byte[count]; Array.Copy(buf, bs, count); } for (int i = 0; i < bs.Length; i++) { byte b = bs[i]; switch (state) { case ReceiveStates.Idle: if (b == StartByte) { state = ReceiveStates.Reading; } break; case ReceiveStates.Reading: if (b == StartByte) { _rxSem.Release(); throw new BrokenFrameException("Unexpected start byte", msgBytes); } else if (b == EndByte) { ReceivedWapMessage msg; try { msg = new ReceivedWapMessage(msgBytes.ToArray()); } catch (Exception ex) { _rxSem.Release(); throw new BrokenFrameException("Parsing failed", msgBytes, ex); } _bufBytes.AddRange(bs.Skip(i + 1)); _rxSem.Release(); return(msg); } else if (b == EscapeByte) { state = ReceiveStates.ReadingEscaped; } else { msgBytes.Add(b); } break; case ReceiveStates.ReadingEscaped: if (b < EscapeOffset) { msgBytes.Add(b); _rxSem.Release(); throw new BrokenFrameException("Illegal escaped sequence", msgBytes); } else { b -= EscapeOffset; msgBytes.Add(b); state = ReceiveStates.Reading; } break; } } } }
/// <summary> /// Waits for a complete TPDU frame, checks the checksum and sends the ACK, NAK /// </summary> /// <returns></returns> private byte[] ReceiveTpduFrame() { bool frameComplete = false; List <byte> frameData = new List <byte>(); //Time measurement, the receive of a whole Frame should not exceed BLOCK_TIMEOUT int startTick = Environment.TickCount; ReceiveStates currentState = ReceiveStates.WaitForStartingDLE; int myTimeout = RECEIVE_RESPONSE_TIMEOUT; if (!_masterMode) { myTimeout = MASTER_RESPONES_TIMEOUT; } while (!frameComplete && (!_masterMode || Environment.TickCount - startTick < RECEIVE_RESPONSE_TIMEOUT)) { //For the first [DLE] the timeout is BLOCK_TIMEOUT, after the DLE was received //only BYTE_TIMEOUT is allowed during the bytes byte?myByte = _buffer.WaitForByte(myTimeout, true); //A Timeout occured, set state to error state and send nak if (myByte == null) { _log.Debug("ReceiveTpduFrame: timeout occured, going into error state"); frameComplete = true; currentState = ReceiveStates.Error; continue; } if (currentState != ReceiveStates.WaitForStartingDLE) { frameData.Add(myByte.Value); } //Simple Statemachine implementation see ReceiveStates for possible state transitions if (currentState == ReceiveStates.WaitForStartingDLE && myByte.Value == RS232Tpdu.DLE) { frameData.Add(myByte.Value); currentState = ReceiveStates.WaitForSTX; } else if (currentState == ReceiveStates.WaitForSTX && myByte.Value == RS232Tpdu.STX) { currentState = ReceiveStates.APDUData; } else if (currentState == ReceiveStates.WaitForSTX) { _log.Debug("ReceiveTpduFrame: No STX after DLE, resetting and waiting for DLE"); currentState = ReceiveStates.WaitForStartingDLE; frameData.Clear(); } else if (currentState == ReceiveStates.APDUData && myByte.Value == RS232Tpdu.DLE) { currentState = ReceiveStates.WaitForDoubleDLE; } else if (currentState == ReceiveStates.WaitForDoubleDLE && myByte.Value == RS232Tpdu.DLE) { currentState = ReceiveStates.APDUData; } else if (currentState == ReceiveStates.WaitForDoubleDLE && myByte.Value == RS232Tpdu.ETX) { currentState = ReceiveStates.WaitForCRCLow; } else if (currentState == ReceiveStates.WaitForDoubleDLE) { _log.Debug("ReceiveTpduFrame: Invalid byte after DLE, received {0:X2}", myByte.Value); frameComplete = true; currentState = ReceiveStates.Error; } else if (currentState == ReceiveStates.WaitForCRCLow) { currentState = ReceiveStates.WaitForCRCHigh; } else if (currentState == ReceiveStates.WaitForCRCHigh) { _log.Debug("ReceiveTpduFrame: {0}", ByteHelpers.ByteToString(frameData.ToArray())); frameComplete = true; currentState = ReceiveStates.Completed; } } if (currentState == ReceiveStates.Completed) { return(frameData.ToArray()); } else { return(null); } }