Exemplo n.º 1
0
    def test_with_given_preamble_and_sync(self):
        preamble = "10101010"
        sync = "10011"
        pg = self.build_protocol_generator(preamble_syncs=[(preamble, sync)],
                                           num_messages=(20, ),
                                           data=(lambda i: 10 * i, ))

        # If we have a odd preamble length, the last bit of the preamble is counted to the sync
        preprocessor = Preprocessor(
            [
                np.array(msg.plain_bits, dtype=np.uint8)
                for msg in pg.protocol.messages
            ],
            existing_message_types={
                i: msg.message_type
                for i, msg in enumerate(pg.protocol.messages)
            })
        preamble_starts, preamble_lengths, sync_len = preprocessor.preprocess()

        #self.save_protocol("given_preamble", pg)

        self.assertTrue(
            all(preamble_start == 0 for preamble_start in preamble_starts))
        self.assertTrue(
            all(preamble_length == len(preamble)
                for preamble_length in preamble_lengths))
        self.assertEqual(sync_len, len(sync))
Exemplo n.º 2
0
    def test_sync_word_finding_common_prefix(self):
        """
        Messages are very similar (odd and even ones are the same)
        However, they do not have two different sync words!
        The algorithm needs to check for a common prefix of the two found sync words

        :return:
        """
        sync = "0x1337"
        num_messages = 10

        alice = Participant("Alice", address_hex="dead01")
        bob = Participant("Bob", address_hex="beef24")

        mb = MessageTypeBuilder("protocol_with_one_message_type")
        mb.add_label(FieldType.Function.PREAMBLE, 72)
        mb.add_label(FieldType.Function.SYNC, 16)
        mb.add_label(FieldType.Function.LENGTH, 8)
        mb.add_label(FieldType.Function.SRC_ADDRESS, 24)
        mb.add_label(FieldType.Function.DST_ADDRESS, 24)
        mb.add_label(FieldType.Function.SEQUENCE_NUMBER, 16)

        pg = ProtocolGenerator([mb.message_type],
                               syncs_by_mt={mb.message_type: "0x1337"},
                               preambles_by_mt={mb.message_type: "10" * 36},
                               participants=[alice, bob])

        random.seed(0)
        for i in range(num_messages):
            if i % 2 == 0:
                source, destination = alice, bob
                data_length = 8
            else:
                source, destination = bob, alice
                data_length = 16
            pg.generate_message(data=pg.decimal_to_bits(
                random.randint(0, 2**(data_length - 1)), data_length),
                                source=source,
                                destination=destination)

        preprocessor = Preprocessor([
            np.array(msg.plain_bits, dtype=np.uint8)
            for msg in pg.protocol.messages
        ])
        possible_syncs = preprocessor.find_possible_syncs()
        #self.save_protocol("sync_by_common_prefix", pg)
        self.assertEqual(len(possible_syncs), 1)

        # +0000 is okay, because this will get fixed by correction in FormatFinder
        self.assertIn(possible_syncs[0], [
            ProtocolGenerator.to_bits(sync),
            ProtocolGenerator.to_bits(sync) + "0000"
        ])
Exemplo n.º 3
0
    def test_format_finding_rwe(self):
        ff, messages = self.get_format_finder_from_protocol_file("rwe.proto.xml", return_messages=True)
        ff.run()

        sync1, sync2 = "0x9a7d9a7d", "0x67686768"

        preprocessor = Preprocessor([np.array(msg.plain_bits, dtype=np.uint8) for msg in messages])
        possible_syncs = preprocessor.find_possible_syncs()
        self.assertIn(ProtocolGenerator.to_bits(sync1), possible_syncs)
        self.assertIn(ProtocolGenerator.to_bits(sync2), possible_syncs)

        ack_messages = (3, 5, 7, 9, 11, 13, 15, 17, 20)
        ack_message_type = next(mt for mt, messages in ff.existing_message_types.items() if ack_messages[0] in messages)
        self.assertTrue(all(ack_msg in ff.existing_message_types[ack_message_type] for ack_msg in ack_messages))

        for mt in ff.message_types:
            preamble = mt.get_first_label_with_type(FieldType.Function.PREAMBLE)
            self.assertEqual(preamble.start, 0)
            self.assertEqual(preamble.length, 32)

            sync = mt.get_first_label_with_type(FieldType.Function.SYNC)
            self.assertEqual(sync.start, 32)
            self.assertEqual(sync.length, 32)

            length = mt.get_first_label_with_type(FieldType.Function.LENGTH)
            self.assertEqual(length.start, 64)
            self.assertEqual(length.length, 8)

            dst = mt.get_first_label_with_type(FieldType.Function.DST_ADDRESS)
            self.assertEqual(dst.length, 24)

            if mt == ack_message_type or 1 in ff.existing_message_types[mt]:
                self.assertEqual(dst.start, 72)
            else:
                self.assertEqual(dst.start, 88)

            if mt != ack_message_type and 1 not in ff.existing_message_types[mt]:
                src = mt.get_first_label_with_type(FieldType.Function.SRC_ADDRESS)
                self.assertEqual(src.start, 112)
                self.assertEqual(src.length, 24)
            elif 1 in ff.existing_message_types[mt]:
                # long ack
                src = mt.get_first_label_with_type(FieldType.Function.SRC_ADDRESS)
                self.assertEqual(src.start, 96)
                self.assertEqual(src.length, 24)

            crc = mt.get_first_label_with_type(FieldType.Function.CHECKSUM)
            self.assertIsNotNone(crc)
Exemplo n.º 4
0
    def test_with_three_syncs_different_preamble_lengths(self):
        ff, messages = self.get_format_finder_from_protocol_file(
            "three_syncs.proto.xml", return_messages=True)
        preprocessor = Preprocessor(ff.get_bitvectors_from_messages(messages))
        sync_words = preprocessor.find_possible_syncs()
        self.assertIn("0000010000100000", sync_words, msg="Sync 1")
        self.assertIn("0010001000100010", sync_words, msg="Sync 2")
        self.assertIn("0110011101100111", sync_words, msg="Sync 3")

        ff.run()

        expected_sync_ends = [
            32, 24, 40, 24, 32, 24, 40, 24, 32, 24, 40, 24, 32, 24, 40, 24
        ]

        for i, (s1, s2) in enumerate(zip(expected_sync_ends, ff.sync_ends)):
            self.assertEqual(s1, s2, msg=str(i))
Exemplo n.º 5
0
    def test_very_simple_sync_word_finding(self):
        preamble = "10101010"
        sync = "1101"

        pg = self.build_protocol_generator(preamble_syncs=[(preamble, sync)],
                                           num_messages=(20, ),
                                           data=(lambda i: 10 * i, ))

        preprocessor = Preprocessor([
            np.array(msg.plain_bits, dtype=np.uint8)
            for msg in pg.protocol.messages
        ])

        possible_syncs = preprocessor.find_possible_syncs()
        #self.save_protocol("very_simple_sync_test", pg)
        self.assertGreaterEqual(len(possible_syncs), 1)
        self.assertEqual(preprocessor.find_possible_syncs()[0], sync)
Exemplo n.º 6
0
 def test_sync_word_finding_with_two_sync_words(self):
     preamble = "0xaaaa"
     sync1, sync2 = "0x1234", "0xcafe"
     pg = self.build_protocol_generator(preamble_syncs=[(preamble, sync1),
                                                        (preamble, sync2)],
                                        num_messages=(15, 10),
                                        data=(lambda i: 12 * i,
                                              lambda i: 16 * i))
     preprocessor = Preprocessor([
         np.array(msg.plain_bits, dtype=np.uint8)
         for msg in pg.protocol.messages
     ])
     possible_syncs = preprocessor.find_possible_syncs()
     #self.save_protocol("two_syncs", pg)
     self.assertGreaterEqual(len(possible_syncs), 2)
     self.assertIn(ProtocolGenerator.to_bits(sync1), possible_syncs)
     self.assertIn(ProtocolGenerator.to_bits(sync2), possible_syncs)
Exemplo n.º 7
0
    def test_sync_word_finding_errored_preamble(self):
        preamble = "00010101010"  # first bits are wrong
        sync = "0110"
        pg = self.build_protocol_generator(preamble_syncs=[(preamble, sync),
                                                           (preamble + "10",
                                                            sync)],
                                           num_messages=(20, 5),
                                           data=(lambda i: 10 * i,
                                                 lambda i: i))

        # If we have a odd preamble length, the last bit of the preamble is counted to the sync
        preprocessor = Preprocessor([
            np.array(msg.plain_bits, dtype=np.uint8)
            for msg in pg.protocol.messages
        ])
        possible_syncs = preprocessor.find_possible_syncs()

        #self.save_protocol("errored_preamble", pg)
        self.assertIn(preamble[-1] + sync[:-1], possible_syncs)
Exemplo n.º 8
0
    def test_sync_word_finding_special_preamble(self):
        preamble = "111001110011100"
        sync = "0110"
        pg = self.build_protocol_generator(preamble_syncs=[(preamble, sync),
                                                           (preamble + "10",
                                                            sync)],
                                           num_messages=(20, 5),
                                           data=(lambda i: 10 * i,
                                                 lambda i: i))

        # If we have a odd preamble length, the last bit of the preamble is counted to the sync
        preprocessor = Preprocessor([
            np.array(msg.plain_bits, dtype=np.uint8)
            for msg in pg.protocol.messages
        ])
        possible_syncs = preprocessor.find_possible_syncs()

        #self.save_protocol("special_preamble", pg)
        self.assertEqual(sync, possible_syncs[0])
Exemplo n.º 9
0
    def __init__(self,
                 messages,
                 participants=None,
                 shortest_field_length=None):
        """

        :type messages: list of Message
        :param participants:
        """
        if participants is not None:
            AutoAssigner.auto_assign_participants(messages, participants)

        existing_message_types_by_msg = {
            i: msg.message_type
            for i, msg in enumerate(messages)
        }
        self.existing_message_types = defaultdict(list)
        for i, message_type in existing_message_types_by_msg.items():
            self.existing_message_types[message_type].append(i)

        preprocessor = Preprocessor(
            self.get_bitvectors_from_messages(messages),
            existing_message_types_by_msg)
        self.preamble_starts, self.preamble_lengths, sync_len = preprocessor.preprocess(
        )
        self.sync_ends = self.preamble_starts + self.preamble_lengths + sync_len

        n = shortest_field_length
        if n is None:
            # 0 = no sync found
            n = 8 if sync_len >= 8 else 4 if sync_len >= 4 else 1 if sync_len >= 1 else 0

        for i, value in enumerate(self.sync_ends):
            # In doubt it is better to under estimate the sync end
            if n > 0:
                self.sync_ends[i] = n * max(int(math.floor((value - self.preamble_starts[i]) / n)), 1) + \
                                    self.preamble_starts[i]
            else:
                self.sync_ends[i] = self.preamble_starts[i]

            if self.sync_ends[i] - self.preamble_starts[
                    i] < self.preamble_lengths[i]:
                self.preamble_lengths[
                    i] = self.sync_ends[i] - self.preamble_starts[i]

        self.bitvectors = self.get_bitvectors_from_messages(
            messages, self.sync_ends)
        self.hexvectors = self.get_hexvectors(self.bitvectors)
        self.current_iteration = 0

        participants = list(
            sorted(
                set(msg.participant for msg in messages
                    if msg.participant is not None)))
        self.participant_indices = [
            participants.index(msg.participant)
            if msg.participant is not None else -1 for msg in messages
        ]
        self.known_participant_addresses = {
            participants.index(p):
            np.array([int(h, 16) for h in p.address_hex], dtype=np.uint8)
            for p in participants if p and p.address_hex
        }