def process_group_management_message( ts: 'datetime', packet: bytes, header: bytes, messages_to_flask: 'Queue[Tuple[Union[bytes, str], bytes]]') -> None: """Parse and display group management message.""" header_str = header.decode() group_id, packet = separate_header(packet, GROUP_ID_LENGTH) if header in [GROUP_MSG_INVITE_HEADER, GROUP_MSG_JOIN_HEADER]: pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) for onion_pub_key in pub_keys: others = [k for k in pub_keys if k != onion_pub_key] packet_str = header_str + b85encode(group_id + b''.join(others)) queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header) elif header in [GROUP_MSG_MEMBER_ADD_HEADER, GROUP_MSG_MEMBER_REM_HEADER]: first_list_len_b, packet = separate_header(packet, ENCODED_INTEGER_LENGTH) first_list_length = bytes_to_int(first_list_len_b) pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) before_adding = remaining = pub_keys[:first_list_length] new_in_group = removable = pub_keys[first_list_length:] if header == GROUP_MSG_MEMBER_ADD_HEADER: packet_str = GROUP_MSG_MEMBER_ADD_HEADER.decode() + b85encode( group_id + b''.join(new_in_group)) for onion_pub_key in before_adding: queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header) for onion_pub_key in new_in_group: other_new = [k for k in new_in_group if k != onion_pub_key] packet_str = ( GROUP_MSG_INVITE_HEADER.decode() + b85encode(group_id + b''.join(other_new + before_adding))) queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header) elif header == GROUP_MSG_MEMBER_REM_HEADER: packet_str = header_str + b85encode(group_id + b''.join(removable)) for onion_pub_key in remaining: queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header) elif header == GROUP_MSG_EXIT_GROUP_HEADER: pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) packet_str = header_str + b85encode(group_id) for onion_pub_key in pub_keys: queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header)
def src_incoming(queues: 'QueueDict', gateway: 'Gateway', unittest: bool = False ) -> None: """\ Redirect messages received from Source Computer to appropriate queues. """ packets_from_sc = queues[GATEWAY_QUEUE] packets_to_dc = queues[DST_MESSAGE_QUEUE] commands_to_dc = queues[DST_COMMAND_QUEUE] messages_to_flask = queues[M_TO_FLASK_QUEUE] files_to_flask = queues[F_TO_FLASK_QUEUE] commands_to_relay = queues[SRC_TO_RELAY_QUEUE] while True: with ignored(EOFError, KeyboardInterrupt): while packets_from_sc.qsize() == 0: time.sleep(0.01) ts, packet = packets_from_sc.get() # type: datetime, bytes ts_bytes = int_to_bytes(int(ts.strftime('%Y%m%d%H%M%S%f')[:-4])) try: packet = gateway.detect_errors(packet) except FunctionReturn: continue header, packet = separate_header(packet, DATAGRAM_HEADER_LENGTH) if header == UNENCRYPTED_DATAGRAM_HEADER: commands_to_relay.put(packet) elif header in [COMMAND_DATAGRAM_HEADER, LOCAL_KEY_DATAGRAM_HEADER]: commands_to_dc.put(header + ts_bytes + packet) p_type = 'Command ' if header == COMMAND_DATAGRAM_HEADER else 'Local key' rp_print(f"{p_type} to local Receiver", ts) elif header in [MESSAGE_DATAGRAM_HEADER, PUBLIC_KEY_DATAGRAM_HEADER]: onion_pub_key, payload = separate_header(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) packet_str = header.decode() + b85encode(payload) queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header) if header == MESSAGE_DATAGRAM_HEADER: packets_to_dc.put(header + ts_bytes + onion_pub_key + ORIGIN_USER_HEADER + payload) elif header == FILE_DATAGRAM_HEADER: no_contacts_b, payload = separate_header(packet, ENCODED_INTEGER_LENGTH) no_contacts = bytes_to_int(no_contacts_b) ser_accounts, file_ct = separate_header(payload, no_contacts * ONION_SERVICE_PUBLIC_KEY_LENGTH) pub_keys = split_byte_string(ser_accounts, item_len=ONION_SERVICE_PUBLIC_KEY_LENGTH) for onion_pub_key in pub_keys: queue_to_flask(file_ct, onion_pub_key, files_to_flask, ts, header) elif header in [GROUP_MSG_INVITE_HEADER, GROUP_MSG_JOIN_HEADER, GROUP_MSG_MEMBER_ADD_HEADER, GROUP_MSG_MEMBER_REM_HEADER, GROUP_MSG_EXIT_GROUP_HEADER]: process_group_management_message(ts, packet, header, messages_to_flask) if unittest: break
def process_add_or_group_remove_member(ts: 'datetime', header: bytes, buf_key: bytes, header_str: str, group_id: bytes, remaining: List[bytes], removable: List[bytes]) -> None: """Process group add or remove member packet.""" packet_str = header_str + b85encode(group_id + b"".join(removable)) for onion_pub_key in remaining: buffer_to_flask(packet_str, onion_pub_key, ts, header, buf_key)
def process_group_management_message( ts: 'datetime', packet: bytes, header: bytes, buf_key: bytes, ) -> None: """Parse and display group management message.""" header_str = header.decode() group_id, packet = separate_header(packet, GROUP_ID_LENGTH) if header in [GROUP_MSG_INVITE_HEADER, GROUP_MSG_JOIN_HEADER]: pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) for onion_pub_key in pub_keys: others = [k for k in pub_keys if k != onion_pub_key] packet_str = header_str + b85encode(group_id + b''.join(others)) buffer_to_flask(packet_str, onion_pub_key, ts, header, buf_key) elif header in [GROUP_MSG_MEMBER_ADD_HEADER, GROUP_MSG_MEMBER_REM_HEADER]: first_list_len_b, packet = separate_header(packet, ENCODED_INTEGER_LENGTH) first_list_length = bytes_to_int(first_list_len_b) pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) before_adding = remaining = pub_keys[:first_list_length] new_in_group = removable = pub_keys[first_list_length:] if header == GROUP_MSG_MEMBER_ADD_HEADER: process_add_or_group_remove_member(ts, header, buf_key, header_str, group_id, before_adding, new_in_group) for onion_pub_key in new_in_group: other_new = [k for k in new_in_group if k != onion_pub_key] packet_str = ( GROUP_MSG_INVITE_HEADER.decode() + b85encode(group_id + b''.join(other_new + before_adding))) buffer_to_flask(packet_str, onion_pub_key, ts, header, buf_key) elif header == GROUP_MSG_MEMBER_REM_HEADER: process_add_or_group_remove_member(ts, header, buf_key, header_str, group_id, remaining, removable) elif header == GROUP_MSG_EXIT_GROUP_HEADER: process_group_exit_header(ts, packet, header, buf_key, header_str, group_id)
def process_add_or_group_remove_member( ts: 'datetime', header: bytes, header_str: str, group_id: bytes, messages_to_flask: 'Queue[Tuple[Union[bytes, str], bytes]]', remaining: List[bytes], removable: List[bytes]) -> None: """Process group add or remove member packet.""" packet_str = header_str + b85encode(group_id + b"".join(removable)) for onion_pub_key in remaining: queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header)
def process_group_exit_header( ts: 'datetime', packet: bytes, header: bytes, header_str: str, group_id: bytes, messages_to_flask: 'Queue[Tuple[Union[bytes, str], bytes]]') -> None: """Process group exit packet.""" pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) packet_str = header_str + b85encode(group_id) for onion_pub_key in pub_keys: queue_to_flask(packet_str, onion_pub_key, messages_to_flask, ts, header)
def process_group_exit_header( ts: 'datetime', packet: bytes, header: bytes, buf_key: bytes, header_str: str, group_id: bytes, ) -> None: """Process group exit packet.""" pub_keys = split_byte_string(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) packet_str = header_str + b85encode(group_id) for onion_pub_key in pub_keys: buffer_to_flask(packet_str, onion_pub_key, ts, header, buf_key)
def process_message_datagram(ts: 'datetime', packet: bytes, header: bytes, buf_key: bytes, queues: 'QueueDict') -> None: """Process message or public key datagram.""" packets_to_dst = queues[DST_MESSAGE_QUEUE] onion_pub_key, payload = separate_header(packet, ONION_SERVICE_PUBLIC_KEY_LENGTH) packet_str = header.decode() + b85encode(payload) ts_bytes = int_to_bytes(int(ts.strftime("%Y%m%d%H%M%S%f")[:-4])) buffer_to_flask(packet_str, onion_pub_key, ts, header, buf_key) if header == MESSAGE_DATAGRAM_HEADER: packets_to_dst.put(header + ts_bytes + onion_pub_key + ORIGIN_USER_HEADER + payload)
def test_b85encode(self): message = os.urandom(100) self.assertEqual(b85encode(message), base64.b85encode(message).decode())