def __forward_packet(self, ip_sender: str, ip_source: str, ttl: str, packet: str) -> None: """ Forward a packet in the net to neighbours :param ip_sender: ip address of sender host :param ttl: packet time to live :param packet: string representing the packet :return: None """ new_ttl = int(ttl) - 1 if new_ttl > 0: ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_source) # get the recipients list without the peer who sent the packet and the peer who forwarded it recipients = LocalData.get_super_friends_recipients(ip_sender, ip4_peer, ip6_peer) packet = packet[:80] + str(new_ttl).zfill(2) + packet[82:] for superfriend in recipients: ip4 = LocalData.get_super_friend_ip4(superfriend) ip6 = LocalData.get_super_friend_ip6(superfriend) port = LocalData.get_super_friend_port(superfriend) try: net_utils.send_packet_and_close(ip4, ip6, port, packet) self.log.write_blue(f'Forwarding to {ip4}|{ip6} [{port}] -> ', end='') self.log.write(f'{packet}') except socket.error as e: self.log.write_red(f'Unable to forward a packet to {ip4}|{ip6} [{port}]: {e}')
def __delete_packet(self, pktid: str) -> None: """ Delete a packet received from the net :param pktid: id of the packet :return: None """ if LocalData.exist_in_received_packets(pktid): LocalData.delete_received_packet(pktid)
def serve(self, sd: socket.socket) -> None: """ Handle the peer request :param sd: the socket descriptor used for read the request :return None """ try: packet = sd.recv(300).decode() except socket.error as e: self.log.write_red( f'Unable to read the packet from the socket: {e}') sd.close() return # log the packet received socket_ip_sender = sd.getpeername()[0] if ipaddress.IPv6Address(socket_ip_sender).ipv4_mapped is None: socket_ip_sender = ipaddress.IPv6Address( socket_ip_sender).compressed else: socket_ip_sender = ipaddress.IPv6Address( socket_ip_sender).ipv4_mapped.compressed socket_port_sender = sd.getpeername()[1] self.log.write_green(f'{socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{packet}') command = packet[0:4] if command == "AQUE": if len(packet) != 212: self.log.write_red( f'Invalid packet received: {packet}\nUnable to reply.') return pktid = packet[4:20] ip_peer = packet[20:75] port_peer = int(packet[75:80]) file_md5 = packet[80:112] filename = packet[112:212] if pktid != LocalData.get_sent_net_quer_packet(): return if not LocalData.exist_net_peer_file(ip_peer, port_peer, file_md5, filename): LocalData.add_net_peer_file(ip_peer, port_peer, file_md5, filename) else: self.log.write_red( f'Invalid packet received: {packet}\nUnable to reply.') return
def __broadcast_packet(self, packet: str) -> None: """ Send the packet to a pool of hosts :param packet: packet to be broadcasted :return: None """ for superfriend in LocalData.get_super_friends(): ip4 = LocalData.get_super_friend_ip4(superfriend) ip6 = LocalData.get_super_friend_ip6(superfriend) port = LocalData.get_super_friend_port(superfriend) try: net_utils.send_packet_and_close(ip4, ip6, port, packet) self.log.write_blue(f'Broadcasting to {ip4}|{ip6} [{port}] -> ', end='') self.log.write(f'{packet}') except socket.error as e: self.log.write_red(f'Unable to broadcast a packet to {ip4}|{ip6} [{port}]: {e}')
def __broadcast(self, packet: str) -> None: """ Send the packet to a pool of hosts :param packet: packet to be sent :return: None """ superfriends = LocalData.get_super_friends() for superfriend in superfriends: try: net_utils.send_packet_and_close( LocalData.get_super_friend_ip4(superfriend), LocalData.get_super_friend_ip6(superfriend), LocalData.get_super_friend_port(superfriend), packet) except socket.error as e: shell.print_red(f'\nUnable to send the packet on the socket: {e}') return
def serve(self, sd: socket.socket) -> None: """ Handle the peer request :param sd: the socket descriptor used for read the request :return None """ try: response = sd.recv(300).decode() except socket.error as e: shell.print_red(f'Unable to read the response from the socket: {e}\n') sd.close() return sd.close() command = response[0:4] if command == "AQUE": if len(response) != 212: shell.print_red(f"Invalid response: : {command} -> {response}. Expected: AQUE<pkt_id><ip_peer><port_peer><file_md5><filename>") return pktid = response[4:20] ip_peer = response[20:75] ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer) port_peer = int(response[75:80]) file_md5 = response[80:112] filename = response[112:212].lstrip().rstrip() if pktid != LocalData.get_sent_menu_quer_packet(): return if not LocalData.exist_menu_peer_file(ip4_peer, ip6_peer, port_peer, file_md5, filename): LocalData.add_menu_peer_file(ip4_peer, ip6_peer, port_peer, file_md5, filename) index = LocalData.menu_peer_file_index(ip4_peer, ip6_peer, port_peer, file_md5, filename) print(f'{index +1}] ', end='') print(f'{filename} ', end='') shell.print_yellow(f'md5={file_md5} ', end='') print(f'({ip4_peer}|{ip6_peer} [{port_peer}])') elif command == "ASUP": if len(response) != 80: shell.print_red(f"Invalid response: : {command} -> {response}. Expected: ASUP<pkt_id><ip_peer><port_peer>") return pktid = response[4:20] ip_peer = response[20:75] ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer) port_peer = int(response[75:80]) if pktid != LocalData.get_sent_supe_packet(): return if not LocalData.is_super_friend(ip4_peer, ip6_peer, port_peer): LocalData.add_super_friend(ip4_peer, ip6_peer, port_peer) shell.print_green('New superfriend found: ', end='') print(f'{ip4_peer}|{ip6_peer} [{port_peer}]') else: shell.print_red(f"\nInvalid response: {command} -> {response}\n") return
def serve(self, choice: str) -> None: """ Handle the peer packet :param choice: the choice to handle :return: None """ if choice == "SUPE": # SUPE[4B].Packet_Id[16B].IP_Peer[55B].Port_Peer[5B].TTL[2B] pktid = str(uuid.uuid4().hex[:16].upper()) ip = net_utils.get_local_ip_for_response() port = net_utils.get_asup_port() ttl = '04' packet = choice + pktid + ip + str(port).zfill(5) + ttl LocalData.set_sent_supe_packet(pktid) old_superfriends_len = len(LocalData.get_super_friends()) server = ServerThread(port, MenuTimedResponseHandler()) server.daemon = True server.start() spinner = SpinnerThread('Searching superpeers (ENTER to continue)', 'Research done! (ENTER to continue)') spinner.start() timer = Timer(20, lambda: (spinner.stop(), server.stop())) timer.start() self.__broadcast(packet) input() print('\033[1A', end='\r') if timer.is_alive(): spinner.stop() spinner.join() timer.cancel() timer.join() server.stop() server.join() else: spinner.join() timer.join() server.join() if len(LocalData.get_super_friends()) == old_superfriends_len: shell.print_yellow('\nNo new superpeer found.\n') elif choice == "ADFF": if not os.path.exists('shared'): shell.print_red('\nCannot find the shared folder.') return dir_file = list() if not os.scandir('shared'): shell.print_yellow('\nNo file in the shared folder.') return for count, dir_entry in enumerate(os.scandir('shared'), 1): dir_file.append((dir_entry.name, hasher.get_md5(dir_entry.path), dir_entry.stat().st_size)) print(f'\n{count}) {dir_entry.name}', end='') shell.print_yellow(f' {hasher.get_md5(dir_entry.path)}', end='') print(f' size: {dir_entry.stat().st_size}') while True: index = input('\nPlease select a file to share(pres q to exit): ') if index == 'q': print('\n') return try: index = int(index) - 1 except ValueError: shell.print_red(f'\nWrong index: number in range 1 - {count} expected.') continue if 0 <= index <= count - 1: chosen_file = dir_file.pop(index) filename = LocalData.get_shared_filename(chosen_file) filemd5 = LocalData.get_shared_filemd5(chosen_file) filedim = LocalData.get_shared_dim(chosen_file) if not LocalData.exist_shared_file(filename, filemd5, filedim): LocalData.add_shared_file(filename, filemd5, filedim) shell.print_green('\nThe file is now shared.') else: shell.print_yellow('\nThe file is already shared.') break else: shell.print_red(f'\nWrong index: number in range 1 - {count} expected.') continue elif choice == "DEFF": if not LocalData.get_shared_files(): shell.print_yellow('\nNo file in sharing.') return for count, file in enumerate(LocalData.get_shared_files(), 1): print(f'\n{count}) {LocalData.get_shared_filename(file)}', end='') shell.print_yellow(f' {LocalData.get_shared_filemd5(file)}', end='') print(f' size: {LocalData.get_shared_dim(file)}') while True: index = input('\nPlease select a file to delete from sharing(pres q to exit): ') if index == 'q': print('\n') return try: index = int(index) - 1 except ValueError: shell.print_red(f'\nWrong index: number in range 1 - {count} expected.') continue if 0 <= index <= count - 1: deleted_file = LocalData.get_shared_file_by_index(index) shell.print_blue(f'\n{LocalData.get_shared_filename(deleted_file)}', end='') shell.print_yellow(f' {LocalData.get_shared_filemd5(deleted_file)}', end='') shell.print_blue(' removed from sharing.') break else: shell.print_red(f'\nWrong index: number in range 1 - {count} expected.') continue elif choice == "QUER": while True: search = input('\nEnter the file name: ') if search != '*': search = '%' + search + '%' if not 0 < len(search) <= 20: shell.print_red('\nFile name must be between 1 and 20 chars long.\n') continue break # Read matching files from DB try: conn = database.get_connection(db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: shell.print_red(f'\nError while getting connection from database: {e}') return try: total_db_file = file_repository.get_files_count_by_querystring(conn, search) if total_db_file == 0: shell.print_yellow('\nNo matching results from your peers.\n') else: shell.print_green('\nFiles from your logged peers:\n') file_rows = file_repository.get_files_by_querystring(conn, search) # print('\nFile from peers: ') for file_row in file_rows: file_md5 = file_row['file_md5'] file_name = file_row['file_name'] owner_rows = peer_repository.get_peers_by_file(conn, file_md5) for owner_row in owner_rows: owner_ip = owner_row['ip'] owner_port = int(owner_row['port']) ip4_peer, ip6_peer = net_utils.get_ip_pair(owner_ip) # stampa di debug # print(f'\n{LocalData.menu_peer_file_index(ip4_peer, ip6_peer, peer.port, file.file_md5, file.file_name)}', end='') # shell.print_yellow(f' {file.file_md5}', end='') # print(f' {file.file_name} from {ip4_peer|ip6_peer} on port {peer.port}') LocalData.add_menu_peer_file(ip4_peer, ip6_peer, owner_port, file_md5, file_name) index = LocalData.menu_peer_file_index(ip4_peer, ip6_peer, owner_port, file_md5, file_name) print(f'{index +1}] ', end='') print(f'{file_name} ', end='') shell.print_yellow(f'md5={file_md5} ', end='') print(f'({ip4_peer}|{ip6_peer} [{owner_port}])') conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() LocalData.clear_menu_peer_files() shell.print_red(f'\nError while retrieving data from database: {e}') # Send a search for a file on the superpeer network shell.print_green('\nFiles from the network:\n') pktid = str(uuid.uuid4().hex[:16].upper()) ip = net_utils.get_local_ip_for_response() port = net_utils.get_aque_port() ttl = '05' packet = choice + pktid + ip + str(port).zfill(5) + ttl + search.ljust(20) LocalData.set_sent_menu_quer_packet(pktid) server = ServerThread(port, MenuTimedResponseHandler()) server.daemon = True server.start() spinner = SpinnerThread('Searching files (ENTER to continue)', 'Research done! (ENTER to continue)') spinner.start() timer = Timer(20, lambda: (spinner.stop(), server.stop())) timer.start() self.__broadcast(packet) input() print('\033[1A', end='\r') if timer.is_alive(): spinner.stop() spinner.join() timer.cancel() timer.join() server.stop() server.join() else: spinner.join() timer.join() server.join() # Retrieving the list of database's files and superpeer network's files peer_files = LocalData.get_menu_peer_files() if len(peer_files) == total_db_file: shell.print_yellow('\nNo matching results from the superpeer network.\n') if len(peer_files) < 1: shell.print_yellow('\nNo file matching the keyword.\n') return while True: index = input('\nPlease select a file to download: ') if index == 'q': print('\n') LocalData.clear_menu_peer_files() return try: index = int(index) - 1 except ValueError: shell.print_red(f'\nWrong index: number in range 1 - {len(peer_files)} expected.') continue if 0 <= index <= len(peer_files): chosen_peer_file = LocalData.get_menu_peer_file_by_index(index) host_ip4 = LocalData.get_menu_file_owner_ip4(chosen_peer_file) host_ip6 = LocalData.get_menu_file_owner_ip6(chosen_peer_file) host_port = LocalData.get_menu_file_owner_port(chosen_peer_file) file_md5 = LocalData.get_menu_file_md5(chosen_peer_file) file_name = LocalData.get_menu_file_name(chosen_peer_file) # preparo packet per retr, faccio partire server in attesa download, invio packet e attendo packet = 'RETR' + file_md5 try: Downloader(host_ip4, host_ip6, host_port, packet, file_name).start() shell.print_green(f'\nDownload of {file_name} completed.\n') LocalData.clear_menu_peer_files() except OSError: shell.print_red(f'\nError while downloading {file_name}\n') break else: shell.print_red(f'\nWrong index: number in range 1 - {len(peer_files)} expected.') continue elif choice == "LISTSUPERPEERS": shell.print_green('\nList of known superpeers:') if not LocalData.get_super_friends(): shell.print_red('You do not know any superpeers.') else: for count, friend in enumerate(LocalData.get_super_friends(), 1): friend_ip4 = LocalData.get_super_friend_ip4(friend) friend_ip6 = LocalData.get_super_friend_ip6(friend) friend_port = LocalData.get_super_friend_port(friend) shell.print_blue(f'{count}] {friend_ip4} {friend_ip6} {str(friend_port)}') elif choice == "LISTPEERS": try: conn = database.get_connection(db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: print(f'Error: {e}') print('The server has encountered an error while trying to serve the request.') return try: peer_list = peer_repository.find_all(conn) if not peer_list: shell.print_red('You do not know any peers.') conn.close() return else: shell.print_green('\nList of known peers:') for count, peer_row in enumerate(peer_list, 1): shell.print_blue(f'{count}]' + peer_row['ip'] + peer_row['port'] + '\n') except database.Error as e: conn.rollback() conn.close() print(f'Error: {e}') print('The server has encountered an error while trying to serve the request.') return elif choice == "LISTFILES": try: conn = database.get_connection(db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: print(f'Error: {e}') print('The server has encountered an error while trying to serve the request.') return try: files = file_repository.find_all(conn) shell.print_green('\nYour shared files:') if not LocalData.get_shared_files(): shell.print_red('You do not have shared files.') for count, shared_file in enumerate(LocalData.get_shared_files(), 1): print(f'{count}] {LocalData.get_shared_filename(shared_file)} ', end='') shell.print_yellow(f'{LocalData.get_shared_filemd5(shared_file)}\n') shell.print_green('\nLogged peers files:') if not files: shell.print_red('You do not have logged peers files.') conn.close() return for count, file_row in enumerate(files, 1): print(f'{count}] {file_row["file_name"]} ', end='') shell.print_yellow(f'{file_row["file_md5"]}') except database.Error as e: conn.rollback() conn.close() print(f'Error: {e}') print('The server has encountered an error while trying to serve the request.') return else: pass
def serve(self, sd: socket.socket) -> None: """ Handle a network packet :param sd: the socket descriptor used for read the packet :return: None """ try: packet = sd.recv(200).decode() except socket.error as e: self.log.write_red(f'Unable to read the packet from the socket: {e}') sd.close() return # log the packet received socket_ip_sender = sd.getpeername()[0] if ipaddress.IPv6Address(socket_ip_sender).ipv4_mapped is None: socket_ip_sender = ipaddress.IPv6Address(socket_ip_sender).compressed else: socket_ip_sender = ipaddress.IPv6Address(socket_ip_sender).ipv4_mapped.compressed socket_port_sender = sd.getpeername()[1] self.log.write_green(f'{socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{packet}') command = packet[:4] if command == "SUPE": sd.close() if len(packet) != 82: self.log.write_red(f'Invalid packet received: {packet}\nUnable to reply.') return pktid = packet[4:20] ip_peer = packet[20:75] ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer) port_peer = int(packet[75:80]) ttl = packet[80:82] # packet management if pktid == LocalData.get_sent_supe_packet(): # if the SUPE i sent has been forwarded to me erroneously return if not LocalData.exist_in_received_packets(pktid): LocalData.add_received_packet(pktid, ip_peer, port_peer) t = Timer(20, function=self.__delete_packet, args=(pktid,)) t.start() else: return # send the NEAR acknowledge response = "ASUP" + pktid + net_utils.get_local_ip_for_response() +\ str(net_utils.get_network_port()).zfill(5) try: net_utils.send_packet_and_close(ip4_peer, ip6_peer, port_peer, response) self.log.write_blue(f'Sending to {ip4_peer}|{ip6_peer} [{port_peer}] -> ', end='') self.log.write(f'{response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending an {response} to {ip4_peer}|{ip6_peer} [{port_peer}]: {e}') # forwarding the packet to other superpeers self.__forward_packet(socket_ip_sender, ip_peer, ttl, packet) elif command == "LOGI": error_response = "ALGI" + '0' * 16 if len(packet) != 64: self.log.write_red(f'Invalid packet received: {packet}') try: sd.send(error_response.encode()) sd.close() self.log.write_blue(f'Sending to {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{error_response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending an ALGI response to {socket_ip_sender}: {e}') return return ip = packet[4:59] port = packet[59:64] try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') try: sd.send(error_response.encode()) sd.close() self.log.write_blue(f'Sending to {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{error_response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {error_response} to {socket_ip_sender}: {e}') return return try: peer = peer_repository.find_by_ip(conn, ip) # if the peer didn't already logged in if peer is None: session_id = str(uuid.uuid4().hex[:16].upper()) peer = peer_repository.find(conn, session_id) # while the generated session_id exists while peer is not None: session_id = str(uuid.uuid4().hex[:16].upper()) peer = peer_repository.find(conn, session_id) peer = Peer(session_id, ip, port) peer.insert(conn) conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') try: sd.send(error_response.encode()) sd.close() self.log.write_blue(f'Sending to {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{error_response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {error_response} to {socket_ip_sender}: {e}') return return response = "ALGI" + peer.session_id try: sd.send(response.encode()) sd.close() self.log.write_blue(f'Sending to {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {response} to {socket_ip_sender}: {e}') return elif command == "ADFF": sd.close() if len(packet) != 152: self.log.write_red(f'Invalid packet received: {packet}\nUnable to add the file in the DB.') return session_id = packet[4:20] md5 = packet[20:52] name = packet[52:152].lower().lstrip().rstrip() try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return try: peer = peer_repository.find(conn, session_id) if peer is None: conn.close() self.log.write_red('Unauthorized request received: SessionID is invalid') return file = file_repository.find(conn, md5) if file is None: file = File(md5, name, 0) file.insert(conn) file_repository.add_owner(conn, md5, session_id) else: file.file_name = name file.update(conn) if not file_repository.peer_has_file(conn, session_id, md5): file_repository.add_owner(conn, md5, session_id) conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return self.log.write_blue(f'Successfully added file: {file.file_name} ({file.file_md5})') elif command == "DEFF": sd.close() if len(packet) != 52: self.log.write_red(f'Invalid packet received: {packet}\nUnable to delete the file from the DB.') return session_id = packet[4:20] md5 = packet[20:52] try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return try: peer = peer_repository.find(conn, session_id) if peer is None: conn.close() self.log.write_red('Unauthorized request received: SessionID is invalid') return if not file_repository.peer_has_file(conn, session_id, md5): conn.close() return peer_repository.file_unlink(conn, session_id, md5) copy = file_repository.get_copies(conn, md5) if copy == 0: file = file_repository.find(conn, md5) file.delete(conn) conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return self.log.write_blue(f'Successfully removed file: {file.file_name} ({file.file_md5})') elif command == "FIND": if len(packet) != 40: self.log.write_red(f'Invalid packet received: {packet}\nUnable to reply.') sd.close() return session_id = packet[4:20] query = packet[20:40].lower().lstrip().rstrip() if query != '*': query = '%' + query + '%' try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') sd.close() return # check in my peers files (DB) try: peer = peer_repository.find(conn, session_id) if peer is None: self.log.write_red('Unauthorized request received: SessionID is invalid') sd.close() return else: file_rows = file_repository.get_files_by_querystring(conn, query) for file_row in file_rows: file_md5 = file_row['file_md5'] file_name = file_row['file_name'] owner_rows = peer_repository.get_peers_by_file(conn, file_md5) for owner_row in owner_rows: owner_ip = owner_row['ip'] owner_port = owner_row['port'] LocalData.add_net_peer_file(owner_ip, owner_port, file_md5, file_name) conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') sd.close() return # check in my shared files for shared_file in LocalData.search_in_shared_files(query.strip('%')): LocalData.add_net_peer_file( net_utils.get_local_ip_for_response(), net_utils.get_network_port(), LocalData.get_shared_filemd5(shared_file), LocalData.get_shared_filename(shared_file) ) # flooding the QUER pktid = str(uuid.uuid4().hex[:16].upper()) ip = net_utils.get_local_ip_for_response() port = net_utils.get_aque_port() ttl = '05' query = packet[20:40] packet = "QUER" + pktid + ip + str(port).zfill(5) + ttl + query LocalData.set_sent_net_quer_packet(pktid) server = ServerThread(port, NetworkTimedResponseHandler(self.log)) server.daemon = True server.start() timer = Timer(20, lambda: server.stop()) timer.start() self.__broadcast_packet(packet) timer.join() try: self.log.write_blue(f'Sending {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write('AFIN') # send the AFIN packet fragment = "AFIN" + str(LocalData.get_net_peer_files_md5_amount()).zfill(3) sd.send(fragment.encode()) self.log.write_blue(f'Sending fragment -> ', end='') self.log.write(f'{fragment}') for md5 in LocalData.get_net_peer_files().keys(): fragment = md5 + LocalData.get_net_peer_file_name_by_md5(md5).ljust(100) + str(LocalData.get_net_peer_file_copy_amount_by_md5(md5)).zfill(3) sd.send(fragment.encode()) self.log.write_blue(f'Sending fragment -> ', end='') self.log.write(f'{fragment}') for file_tuple in LocalData.get_net_peer_files_list_by_md5(md5): fragment = LocalData.get_net_peer_file_owner_ip(file_tuple) + str(LocalData.get_net_peer_file_owner_port(file_tuple)).zfill(5) sd.send(fragment.encode()) self.log.write_blue(f'Sending fragment -> ', end='') self.log.write(f'{fragment}') except socket.error as e: self.log.write_red(f'An error has occurred while sending an AFIN response to {socket_ip_sender}: {e}') sd.close() LocalData.clear_net_peer_files() elif command == "LOGO": if len(packet) != 20: self.log.write_red(f'Invalid packet received: {packet}\nUnable to reply.') sd.close() return session_id = packet[4:20] try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') sd.close() return try: peer = peer_repository.find(conn, session_id) if peer is None: conn.close() self.log.write_red('Unauthorized request received: SessionID is invalid') sd.close() return deleted = file_repository.delete_peer_files(conn, session_id) peer.delete(conn) conn.commit() conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') sd.close() return response = "ALGO" + str(deleted).zfill(3) try: sd.send(response.encode()) sd.close() self.log.write_blue(f'Sending {socket_ip_sender} [{socket_port_sender}] -> ', end='') self.log.write(f'{response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {response} to {socket_ip_sender}: {e}') return elif command == "QUER": sd.close() if len(packet) != 102: self.log.write_red(f'Invalid packet received: {packet}\nUnable to reply.') return self.log.write(f'{packet}') pktid = packet[4:20] ip_peer = packet[20:75] ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer) port_peer = int(packet[75:80]) ttl = packet[80:82] query = packet[82:102].lower().lstrip().rstrip() if query != '*': query = '%' + query + '%' try: conn = database.get_connection(self.db_file) conn.row_factory = database.sqlite3.Row except database.Error as e: self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return # check in my peers files (DB) try: total_file = file_repository.get_files_count_by_querystring(conn, query) if total_file != 0: file_rows = file_repository.get_files_by_querystring(conn, query) for file_row in file_rows: file_md5 = file_row['file_md5'] file_name = file_row['file_name'] owner_rows = peer_repository.get_peers_by_file(conn, file_md5) for owner_row in owner_rows: owner_ip = owner_row['ip'] owner_port = owner_row['port'] response = "AQUE" + pktid + owner_ip + owner_port + file_md5 + file_name.ljust(100) try: net_utils.send_packet_and_close(ip4_peer, ip6_peer, port_peer, response) self.log.write_blue(f'Sending {ip4_peer}|{ip6_peer} [{port_peer}] -> ', end='') self.log.write(f'{response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {response}: {e}') conn.commit() conn.close() else: conn.close() except database.Error as e: conn.rollback() conn.close() self.log.write_red(f'An error has occurred while trying to serve the request: {e}') return # check in my shared files for local_shared_file in LocalData.search_in_shared_files(query.strip('%')): local_ip = net_utils.get_local_ip_for_response() local_port = str(net_utils.get_network_port()).zfill(5) file_md5 = LocalData.get_shared_filemd5(local_shared_file) file_name = LocalData.get_shared_filename(local_shared_file).ljust(100) response = "AQUE" + pktid + local_ip + local_port + file_md5 + file_name try: net_utils.send_packet_and_close(ip4_peer, ip6_peer, port_peer, response) self.log.write_blue(f'Sending {ip4_peer}|{ip6_peer} [{port_peer}] -> ', end='') self.log.write(f'{response}') except socket.error as e: self.log.write_red(f'An error has occurred while sending {response}: {e}') # forwarding the packet to other superpeers self.__forward_packet(socket_ip_sender, ip_peer, ttl, packet) elif command == "RETR": if len(packet) != 36: self.log.write_blue('Sending -> ', end='') self.log.write('Invalid packet. Unable to reply.') sd.send('Invalid packet. Unable to reply.'.encode()) sd.close() return file_md5 = packet[4:36] file_name = LocalData.get_shared_filename_by_filemd5(file_md5) if file_name is None: self.log.write_blue('Sending -> ', end='') self.log.write('Sorry, the requested file is not available anymore by the selected peer.') sd.send('Sorry, the requested file is not available anymore by the selected peer.'.encode()) sd.close() return try: f_obj = open('shared/' + file_name, 'rb') except OSError as e: self.log.write_red(f'Cannot open the file to upload: {e}') self.log.write_blue('Sending -> ', end='') self.log.write('Sorry, the peer encountered a problem while serving your packet.') sd.send('Sorry, the peer encountered a problem while serving your packet.'.encode()) sd.close() return try: Uploader(sd, f_obj, self.log).start() self.log.write_blue(f'Sent {sd.getpeername()[0]} [{sd.getpeername()[1]}] -> ', end='') self.log.write(f'{file_name}') sd.close() except OSError as e: self.log.write_red(f'Error while sending the file: {e}') sd.close() return else: sd.close() self.log.write_red(f'Invalid packet received from {socket_ip_sender} [{socket_port_sender}]: ', end='') self.log.write(f'{packet}') return