def decode_frame(raw_data): """ Try to create a frame instance from the raw data. It's assumed that raw_data is a buffer and can still be incomplete to create a valid frame or it has multiple frames packed into it. Arguments: raw_data - byte() with the raw data of the buffer Returns (bytes consumed, frame instance) or (0, None) if no complete frame is in the buffer Raises FrameException if an invalid frame was detected. """ log.debug("RAW DATA: %r" % raw_data) try: msg_type, payload_size = struct.unpack(FRAME_HEADER_STRUCT, raw_data[:FRAME_HEADER_SIZE]) except struct.error: log.debug("Invalid frame - couldn't unpack headers") return 0, None frame_end = FRAME_HEADER_SIZE + payload_size + FRAME_END_SIZE if len(raw_data) < frame_end: log.debug("Invalid frame - incomplete frame (%d, %d)" % \ (len(raw_data), frame_end)) return 0, None if raw_data[frame_end - FRAME_END_SIZE] != FRAME_END: raise FrameException( "Frame doesn't end with the expected FRAME_END marker") payload = raw_data[FRAME_HEADER_SIZE:frame_end-FRAME_END_SIZE] log.debug("PAYLOAD: %r" % payload) if msg_type not in MessageType.values(): raise FrameException("Frame has invalid message type") return frame_end, Frame(msg_type, payload)