def test_one_participant(self): """ Test a simple protocol with preamble, sync and length field (8 bit) and some random data :return: """ mb = MessageTypeBuilder("simple_address_test") mb.add_label(FieldType.Function.PREAMBLE, 8) mb.add_label(FieldType.Function.SYNC, 16) mb.add_label(FieldType.Function.LENGTH, 8) mb.add_label(FieldType.Function.SRC_ADDRESS, 16) num_messages_by_data_length = {8: 5, 16: 10, 32: 15} pg = ProtocolGenerator([mb.message_type], syncs_by_mt={mb.message_type: "0x9a9d"}, participants=[self.alice]) for data_length, num_messages in num_messages_by_data_length.items(): for i in range(num_messages): pg.generate_message(data=pg.decimal_to_bits( 22 * i, data_length), source=self.alice) #self.save_protocol("address_one_participant", pg) self.clear_message_types(pg.protocol.messages) ff = FormatFinder(pg.protocol.messages) address_engine = AddressEngine(ff.hexvectors, ff.participant_indices) address_dict = address_engine.find_addresses() self.assertEqual(len(address_dict), 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" ])
def test_medium_protocol(self): """ Protocol with two message types. Length field only present in one of them :return: """ mb1 = MessageTypeBuilder("data") mb1.add_label(FieldType.Function.PREAMBLE, 8) mb1.add_label(FieldType.Function.SYNC, 8) mb1.add_label(FieldType.Function.LENGTH, 8) mb1.add_label(FieldType.Function.SEQUENCE_NUMBER, 8) mb2 = MessageTypeBuilder("ack") mb2.add_label(FieldType.Function.PREAMBLE, 8) mb2.add_label(FieldType.Function.SYNC, 8) pg = ProtocolGenerator([mb1.message_type, mb2.message_type], syncs_by_mt={ mb1.message_type: "11110011", mb2.message_type: "11110011" }) num_messages_by_data_length = {8: 5, 16: 10, 32: 5} for data_length, num_messages in num_messages_by_data_length.items(): for i in range(num_messages): pg.generate_message(data=pg.decimal_to_bits( 10 * i, data_length), message_type=mb1.message_type) pg.generate_message(message_type=mb2.message_type, data="0xaf") #self.save_protocol("medium_length", pg) self.clear_message_types(pg.protocol.messages) ff = FormatFinder(pg.protocol.messages) ff.perform_iteration() self.assertEqual(len(ff.message_types), 2) length_mt = next(mt for mt in ff.message_types if mt.get_first_label_with_type( FieldType.Function.LENGTH) is not None) length_label = length_mt.get_first_label_with_type( FieldType.Function.LENGTH) for i, sync_end in enumerate(ff.sync_ends): self.assertEqual(sync_end, 16, msg=str(i)) self.assertEqual(16, length_label.start) self.assertEqual(8, length_label.length)
def __prepare_example_protocol(self) -> ProtocolAnalyzer: alice = Participant("Alice", "A", address_hex="1234") bob = Participant("Bob", "B", address_hex="cafe") mb = MessageTypeBuilder("data") mb.add_label(FieldType.Function.PREAMBLE, 8) mb.add_label(FieldType.Function.SYNC, 16) mb.add_label(FieldType.Function.LENGTH, 8) mb.add_label(FieldType.Function.TYPE, 8) mb.add_label(FieldType.Function.DST_ADDRESS, 16) mb.add_label(FieldType.Function.SRC_ADDRESS, 16) mb_ack = MessageTypeBuilder("ack") mb_ack.add_label(FieldType.Function.PREAMBLE, 8) mb_ack.add_label(FieldType.Function.SYNC, 16) mb_ack.add_label(FieldType.Function.LENGTH, 8) mb_ack.add_label(FieldType.Function.DST_ADDRESS, 16) num_messages = 50 pg = ProtocolGenerator([mb.message_type, mb_ack.message_type], syncs_by_mt={ mb.message_type: "0x6768", mb_ack.message_type: "0x6768" }, 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) pg.generate_message(data="", message_type=mb_ack.message_type, destination=source, source=destination) #self.save_protocol("labeled_protocol", pg) return pg.protocol
def build_protocol_generator(preamble_syncs: list, num_messages: tuple, data: tuple) -> ProtocolGenerator: message_types = [] preambles_by_mt = dict() syncs_by_mt = dict() assert len(preamble_syncs) == len(num_messages) == len(data) for i, (preamble, sync_word) in enumerate(preamble_syncs): assert isinstance(preamble, str) assert isinstance(sync_word, str) preamble, sync_word = map(ProtocolGenerator.to_bits, (preamble, sync_word)) mb = MessageTypeBuilder("message type #{0}".format(i)) mb.add_label(FieldType.Function.PREAMBLE, len(preamble)) mb.add_label(FieldType.Function.SYNC, len(sync_word)) message_types.append(mb.message_type) preambles_by_mt[mb.message_type] = preamble syncs_by_mt[mb.message_type] = sync_word pg = ProtocolGenerator(message_types, preambles_by_mt=preambles_by_mt, syncs_by_mt=syncs_by_mt) for i, msg_type in enumerate(message_types): for j in range(num_messages[i]): if callable(data[i]): msg_data = pg.decimal_to_bits(data[i](j), num_bits=8) else: msg_data = data[i] pg.generate_message(message_type=msg_type, data=msg_data) return pg
def test_two_participants(self): mb = MessageTypeBuilder("address_two_participants") mb.add_label(FieldType.Function.PREAMBLE, 8) mb.add_label(FieldType.Function.SYNC, 16) mb.add_label(FieldType.Function.LENGTH, 8) mb.add_label(FieldType.Function.SRC_ADDRESS, 16) mb.add_label(FieldType.Function.DST_ADDRESS, 16) num_messages = 50 pg = ProtocolGenerator([mb.message_type], syncs_by_mt={mb.message_type: "0x9a9d"}, participants=[self.alice, self.bob]) for i in range(num_messages): if i % 2 == 0: source, destination = self.alice, self.bob data_length = 8 else: source, destination = self.bob, self.alice data_length = 16 pg.generate_message(data=pg.decimal_to_bits(4 * i, data_length), source=source, destination=destination) #self.save_protocol("address_two_participants", pg) self.clear_message_types(pg.protocol.messages) ff = FormatFinder(pg.protocol.messages) address_engine = AddressEngine(ff.hexvectors, ff.participant_indices) address_dict = address_engine.find_addresses() self.assertEqual(len(address_dict), 2) addresses_1 = list( map(util.convert_numbers_to_hex_string, address_dict[0])) addresses_2 = list( map(util.convert_numbers_to_hex_string, address_dict[1])) self.assertIn(self.alice.address_hex, addresses_1) self.assertIn(self.alice.address_hex, addresses_2) self.assertIn(self.bob.address_hex, addresses_1) self.assertIn(self.bob.address_hex, addresses_2) ff.known_participant_addresses.clear() self.assertEqual(len(ff.known_participant_addresses), 0) ff.perform_iteration() self.assertEqual(len(ff.known_participant_addresses), 2) self.assertIn(bytes([int(h, 16) for h in self.alice.address_hex]), map(bytes, ff.known_participant_addresses.values())) self.assertIn(bytes([int(h, 16) for h in self.bob.address_hex]), map(bytes, ff.known_participant_addresses.values())) self.assertEqual(len(ff.message_types), 1) mt = ff.message_types[0] dst_addr = mt.get_first_label_with_type(FieldType.Function.DST_ADDRESS) self.assertIsNotNone(dst_addr) self.assertEqual(dst_addr.start, 32) self.assertEqual(dst_addr.length, 16) src_addr = mt.get_first_label_with_type(FieldType.Function.SRC_ADDRESS) self.assertIsNotNone(src_addr) self.assertEqual(src_addr.start, 48) self.assertEqual(src_addr.length, 16)