class HDLCMsgParser(MsgParser): """This class is responsible for taking raw serial bytes and searching them for valid SLIP messages. Attributes: crc: CRC calculator. msg: Parsed HDLC message with HDLC bytes extracted. """ def __init__(self, config): MsgParser.__init__(self, config) self.crc = crcmod.mkCrcFun(0x11021, initCrc=0xFFFF, xorOut=0, rev=False) # CRC-16 self.crcLength = 2 self.msg = HDLCMsg(2058) def parseSerialMsg(self, msgBytes, msgStart): """Searches raw serial data for HDLC messages and then validates message integrity by comparing a computed CRC to the CRC found in the message. Valid messages are then stored for processing. Args: msgBytes: Raw serial data to be parsed. msgStart: Start location to begin looking for serial message in msgBytes data array. """ if len(msgBytes) > 0: # Process serial message self.msg.decodeMsg(msgBytes, msgStart) if self.msg.msgFound == True: # Message start found if self.msg.msgEnd != -1: # entire msg found # Check msg CRC crc = self.crc(self.msg.msg[:-self.crcLength]) if self.msg.msg[-self.crcLength:] == packData( crc, self.crcLength): # CRC matches - valid message #print("CRC matches") self.parsedMsgs.append(self.msg.msg[:-self.crcLength]) return self.msg.msgEnd else: # partial msg found pass else: # No message found pass return len( msgBytes) # all bytes parsed so return length of input message else: return 0 def encodeMsg(self, msgBytes): if msgBytes: # Add CRC crc = self.crc(msgBytes) msgBytes = msgBytes + packData(crc, self.crcLength) self.msg.encodeMsg(msgBytes) return self.msg.hdlc return msgBytes
class TestHDLCMsg: def setup_method(self, method): self.hdlcMsg = HDLCMsg(256) pass def test_encodeMsg(self): """Test encodeMsg method of HDLCMsg.""" self.hdlcMsg.encodeMsg(testMsg) assert (self.hdlcMsg.hdlc == truthHDLCMsg) def test_decodeMsg(self): """Test decodeMsg method of HDLCMsg. Will also test decodeMsgContents.""" # Test clearing of partial message self.hdlcMsg = HDLCMsg(256) self.hdlcMsg.msgFound = True self.hdlcMsg.msg = b'123' self.hdlcMsg.msgEnd = 5 self.hdlcMsg.msgLength = 10 self.hdlcMsg.decodeMsg(b'12345', 0) assert (self.hdlcMsg.msgFound == False) assert (self.hdlcMsg.msg == b'') assert (self.hdlcMsg.msgLength == 0) assert (self.hdlcMsg.msgEnd == -1) # Test decoding entire message contents self.hdlcMsg = HDLCMsg(256) self.hdlcMsg.encodeMsg(testMsg) assert (self.hdlcMsg.msgEnd == -1) self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc, 0) assert (self.hdlcMsg.msg == testMsg) # verify message contents assert (self.hdlcMsg.msgLength == len(testMsg) ) # verify message length assert (self.hdlcMsg.msgEnd == len(truthHDLCMsg) - 1 ) # verify message end location # Test decoding partial message self.hdlcMsg = HDLCMsg(256) self.hdlcMsg.encodeMsg(testMsg) self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc[:-1], 0) assert (self.hdlcMsg.msgEnd == -1) # message end not found self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc[-1:], 0) # parse remaining message assert (self.hdlcMsg.msg == testMsg) # verify message contents assert (self.hdlcMsg.msgLength == len(testMsg) ) # verify message length # Test decoding partial message in middle of escape sequence self.hdlcMsg = HDLCMsg(256) msg = b'123' + HDLC_ESC + b'456' self.hdlcMsg.encodeMsg(msg) self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc[0:4], 0) # length prior to escape sequence msgLen = self.hdlcMsg.msgLength self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc[4:5], 0) # parse HDLC_ESC assert ( msgLen == self.hdlcMsg.msgLength ) # message length should be unchanged until entire escape sequence read self.hdlcMsg.decodeMsg(self.hdlcMsg.hdlc[5:6], 0) # read entire escape sequence assert (self.hdlcMsg.msgLength == msgLen + 1) self.hdlcMsg.decodeMsg( self.hdlcMsg.hdlc[6:], 0) # test successful parsing of remainder of message assert (self.hdlcMsg.msg == msg) # verify message contents assert (self.hdlcMsg.msgLength == len(msg)) # verify message length
class TestHDLCMsg: def setup_method(self, method): self.hdlcMsg = HDLCMsg(256) self.truthCRC = packData(self.hdlcMsg.crc(testMsg), self.hdlcMsg.crcLength) pass def test_encodeMsg(self): """Test encodeMsg method of HDLCMsg.""" self.hdlcMsg.encodeMsg(testMsg) # assert(self.hdlcMsg.encoded == truthHDLCMsg + self.truthCRC) minLength = len(truthHDLCMsg + self.truthCRC) assert ( len(self.hdlcMsg.encoded) >= minLength ) # length should be at least length of encoded raw bytes plus crc (could be longer if CRC included reserved bytes) if (len(self.hdlcMsg.encoded) == minLength ): # no reserved bytes in CRC assert (self.hdlcMsg.encoded == (truthHDLCMsg[:-1] + self.truthCRC + truthHDLCMsg[-1:])) else: # CRC contained reserved bytes assert (self.hdlcMsg.encoded[:-(self.hdlcMsg.crcLength + 1)] == truthHDLCMsg[:-1] ) # skip over CRC assert (self.hdlcMsg.encoded[-1] == truthHDLCMsg[-1]) def test_decodeMsg(self): """Test decodeMsg method of HDLCMsg. Will also test decodeMsgContents.""" # Test clearing of partial message self.hdlcMsg = HDLCMsg(256) self.hdlcMsg.msgFound = True self.hdlcMsg.msg = b'123' self.hdlcMsg.msgEnd = 5 self.hdlcMsg.msgLength = 10 self.hdlcMsg.decodeMsg(b'12345', 0) assert (self.hdlcMsg.msgFound == False) assert (self.hdlcMsg.msg == b'') assert (self.hdlcMsg.msgLength == 0) assert (self.hdlcMsg.msgEnd == -1) def test_parseMsg(self): """Test parseMsg method of HLDCMsg.""" self.hdlcMsg.encodeMsg(testMsg) # encode messaging for parsing # Parse message from encoded message parsedMsg = self.hdlcMsg.parseMsg(self.hdlcMsg.encoded, 0) assert (parsedMsg == testMsg) # Parse message with surrounding bytes inputMsg = b'9876' + self.hdlcMsg.encoded + b'1234' parsedMsg = self.hdlcMsg.parseMsg(inputMsg, 0) assert (parsedMsg == testMsg) # Parse partial message self.hdlcMsg = HDLCMsg(256) self.hdlcMsg.encodeMsg(testMsg) self.hdlcMsg.parseMsg(self.hdlcMsg.encoded[:-1], 0) assert (self.hdlcMsg.msgEnd == -1) # message end not found parsedMsg = self.hdlcMsg.parseMsg(self.hdlcMsg.encoded[-1:], 0) # parse remaining message assert (parsedMsg == testMsg) # verify message contents assert (len(parsedMsg) == len(testMsg)) # verify message length # Test parsing partial message in middle of escape sequence self.hdlcMsg = HDLCMsg(256) msg = b'123' + HDLC_ESC + b'456' self.hdlcMsg.encodeMsg(msg) self.hdlcMsg.parseMsg(self.hdlcMsg.encoded[0:4], 0) # length prior to escape sequence msgLen = self.hdlcMsg.msgLength self.hdlcMsg.parseMsg(self.hdlcMsg.encoded[4:5], 0) # parse HDLC_ESC assert ( msgLen == self.hdlcMsg.msgLength ) # message length should be unchanged until entire escape sequence read self.hdlcMsg.parseMsg(self.hdlcMsg.encoded[5:6], 0) # read entire escape sequence assert (self.hdlcMsg.msgLength == msgLen + 1) parsedMsg = self.hdlcMsg.parseMsg( self.hdlcMsg.encoded[6:], 0) # test successful parsing of remainder of message assert (parsedMsg == msg) # verify message contents assert (len(parsedMsg) == len(msg)) # verify message length