예제 #1
0
def startup():

    if not database.exist(DB_FILE):
        database.create_database(DB_FILE)
    else:
        database.reset_database(DB_FILE)

    while len(LocalData.get_super_friends()) == 0:
        shell.print_blue(
            '\nThis process will allow you to add a known peer to your list of known peers.\n'
        )
        ip4, ip6, port = net_utils.prompt_friend_request()

        LocalData.add_super_friend(ip4, ip6, port)
        shell.print_green(
            f'\nSuccessfully added the new peer: {ip4}|{ip6} [{port}]\n')

    log = Logger.Logger('superpeer/superpeer.log')

    server = ServerThread(net_utils.get_network_port(),
                          NetworkHandler.NetworkHandler(DB_FILE, log))
    server.daemon = True
    server.start()

    Menu(MenuHandler.MenuHandler()).show()
예제 #2
0
def startup():

	while True:
		shell.print_blue('\nThis process will allow you to add a tracker.\n')
		tracker = net_utils.prompt_host_request('Insert a known host')
		LocalData.set_tracker(tracker)
		# LocalData.set_tracker(('172.16.1.', 'fc00::1:', 3000))

		# tenta login
		ip = net_utils.get_local_ip_for_response()
		port = str(net_utils.get_peer_port()).zfill(5)
		packet = "LOGI" + ip + port

		tracker_ip4 = LocalData.get_tracker_ip4()
		tracker_ip6 = LocalData.get_tracker_ip6()
		tracker_port = LocalData.get_tracker_port()

		try:
			sock = net_utils.send_packet(tracker_ip4, tracker_ip6, tracker_port, packet)
			response = sock.recv(50).decode()

			if len(response) != 20:
				shell.print_red(f'There was an error in the login process: unexpected: {response}.\nPlease retry.')
				continue

			session_id = response[4:20]

			if session_id == '0' * 16:
				shell.print_red(
					f'There was an error in the login process: unexpected session_id: {session_id}.\nPlease retry.')
				continue

			LocalData.session_id = session_id
			break

		except (socket.error, AttributeError):
			shell.print_yellow(f'Unable to contact {tracker_ip4}|{tracker_ip6} [{tracker_port}]')
			if sock is not None:
				sock.close()
			continue

	shell.print_green(f'Successfully logged to the tracker: {tracker_ip4}|{tracker_ip6} [{tracker_port}]\n')

	log = Logger.Logger('peer/peer.log')

	server = ServerThread(net_utils.get_peer_port(), UploadHandler.UploadHandler(log))
	server.daemon = True
	server.start()

	Menu(MenuHandler.MenuHandler(), server).show()
예제 #3
0
def prompt_neighbours_request() -> None:
	""" Guide the user to manually insert peers in the data structure

	:return: None
	"""

	while True:
		ip4 = input('Insert a known peer (IPv4): ')
		if ip4 == 'q':
			break

		try:
			ipaddress.IPv4Address(ip4)
		except ipaddress.AddressValueError:
			shell_colors.print_red(f'{ip4} is not a valid IPv4 address, please retry.')
			continue
		break

	while True:
		ip6 = input('Insert a known peer (IPv6): ')
		try:
			ipaddress.IPv6Address(ip6)
		except ipaddress.AddressValueError:
			shell_colors.print_red(f'{ip6} is not a valid IPv6 address, please retry.')
			continue
		break

	while True:
		port = input('Insert a known peer (port): ')
		try:
			port = int(port)
			if not 1024 < port < 65535:
				shell_colors.print_red(f'{port} must be in range 1025 - 65535')
				continue
		except ValueError:
			shell_colors.print_red(f'{port} is not a valid port number, please retry.')
			continue
		break

	AppData.add_neighbour(ip4, ip6, port)

	shell_colors.print_green(f'\nSuccessfully added the new peer: {ip4}|{ip6} [{port}]\n')
예제 #4
0
    def child(self, sd, clientaddr):
        (client, client_port) = socket.getnameinfo(clientaddr,
                                                   socket.NI_NUMERICHOST)
        self.ss.close()

        request = sd.recv(self.BUFF_SIZE)
        shell.print_green(f'{client} [{client_port}] -> ', end='')
        print(f'{request.decode()}', end='')

        response = handler.serve(request)
        sd.send(response.encode())
        shell.print_red(' -> ', end='')
        print(f'{response}')

        if response[0:4] == "ALGO":
            shell.print_blue(
                f'Client {client} [{client_port}] said goodbye! {int(response[4:])} files deleted.'
            )

        sd.close()
        os._exit(0)
예제 #5
0
    def serve(self, choice: str) -> None:
        """ Handle the peer packet

		:param choice: the choice to handle
		:return: None
		"""

        if choice == "QUER":

            # codice che manda il pkt sulla socket
            pktid = str(uuid.uuid4().hex[:16].upper())
            ip = net_utils.get_local_ip_for_response()
            port = net_utils.get_aque_port()
            ttl = '50'

            while True:
                search = input('\nEnter the file name: ')

                if not 0 <= len(search) <= 20:
                    shell_colors.print_red(
                        '\nFile name must be between 1 and 20 chars long.\n')
                    continue
                break

            packet = choice + pktid + ip + str(port).zfill(
                5) + ttl + search.ljust(20)
            AppData.set_sent_packet(pktid)

            # avvio il server di ricezione delle response, lo faccio prima del broadcast
            # per evitare che i primi client che rispondono non riescano a connettersi
            server = ServerThread(port, SelfHandler())
            server.daemon = True
            server.start()

            spinner = SpinnerThread('Searching files (ENTER to continue)',
                                    'Research done!')
            spinner.start()

            timer = Timer(300, 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()

            files = AppData.get_peer_files()

            if len(files) < 1:
                shell_colors.print_red('\nNo matching results.\n')
                return

            # for count, file in enumerate(files, start=1):
            # 	print(f'{count}]', file)

            while True:
                index = input('\nPlease select a file to download: ')
                try:
                    index = int(index)
                    if 1 <= index <= len(files):
                        break
                    else:
                        shell_colors.print_red(
                            f'Index chosen must be in the correct range: 1 - {len(files)}.\n'
                        )
                except ValueError:
                    shell_colors.print_red(
                        f'Your choice must be a valid one: number in range 1 - {len(files)} expected.\n'
                    )

            host_ip4 = AppData.get_file_owner_ip4(files[index - 1])
            host_ip6 = AppData.get_file_owner_ip6(files[index - 1])
            host_port = AppData.get_file_owner_port(files[index - 1])
            file_md5 = AppData.get_file_md5(files[index - 1])
            file_name = AppData.get_file_name(files[index - 1])

            # 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_colors.print_green(
                    f'\nDownload of {file_name} completed.\n')
                AppData.clear_peer_files()
                AppData.add_shared_file(file_name, file_md5,
                                        os.stat('shared/' + file_name).st_size)
            except OSError:
                shell_colors.print_red(
                    f'\nError while downloading {file_name}\n')

        elif choice == "NEAR":
            # NEAR[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_anea_port()
            ttl = '03'

            packet = choice + pktid + ip + str(port).zfill(5) + ttl
            AppData.set_sent_packet(pktid)

            old_neighbours_len = len(AppData.get_neighbours())

            # avvio il server di ricezione delle response, lo faccio prima del broadcast
            # per evitare che i primi client che rispondono non riescano a connettersi
            server = ServerThread(port, SelfHandler())
            server.daemon = True
            server.start()

            spinner = SpinnerThread('Searching peers (ENTER to continue)',
                                    'Research done!')
            spinner.start()

            timer = Timer(300, 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(AppData.get_neighbours()) == old_neighbours_len:
                shell_colors.print_red('\nNo new peer found.\n')

        elif choice == 'ADDPEER':
            net_utils.prompt_neighbours_request()

        elif choice == 'LISTPEERS':
            shell_colors.print_green('\nList of known peers:')
            for count, neighbour in enumerate(AppData.get_neighbours(),
                                              start=1):
                shell_colors.print_blue(
                    f'{count}] {AppData.get_peer_ip4(neighbour)} {AppData.get_peer_ip6(neighbour)} {str(AppData.get_peer_port(neighbour))}'
                )

        elif choice == 'REMOVEPEER':
            neighbours = AppData.get_neighbours()
            shell_colors.print_green('\nList of known peers:')
            for count, neighbour in enumerate(neighbours, start=1):
                shell_colors.print_blue(
                    f'{count}] {AppData.get_peer_ip4(neighbour)} {AppData.get_peer_ip6(neighbour)} {str(AppData.get_peer_port(neighbour))}'
                )

            while True:
                index = input(
                    '\nPlease select a peer to delete (q to cancel): ')
                if index == 'q':
                    break

                try:
                    index = int(index)
                    if 1 <= index <= len(neighbours):
                        AppData.remove_neighbour(index - 1)
                        break
                    else:
                        shell_colors.print_red(
                            f'Index chosen must be in the correct range: 1 - {len(neighbours)}.\n'
                        )
                except ValueError:
                    shell_colors.print_red(
                        f'Your choice must be a valid one: number in range 1 - {len(neighbours)} expected.\n'
                    )

        else:
            pass
	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
예제 #7
0
def startup():

    while True:
        # verifico se ho superpeer e file in sharing nel json (ossia se il peer è crashato)
        if LocalData.superpeer_is_empty():
            while True:
                shell.print_blue(
                    '\nThis process will allow you to add your known peer.\n')
                superpeer = net_utils.prompt_friend_request()
                LocalData.set_superpeer(superpeer)

                # 1) Lancia una SUPE al nodo conosciuto
                pktid = str(uuid.uuid4().hex[:16].upper())
                ip = net_utils.get_local_ip_for_response()
                port = str(net_utils.get_network_port()).zfill(5)
                ttl = '04'
                packet = 'SUPE' + pktid + ip + port + ttl

                super_ip4 = LocalData.get_superpeer_ip4()
                super_ip6 = LocalData.get_superpeer_ip6()
                super_port = LocalData.get_superpeer_port()

                LocalData.set_sent_packet(pktid)

                server = ServerThread(
                    net_utils.get_network_port(),
                    TimedResponseHandler.TimedResponseHandler())
                server.start()

                spinner = SpinnerThread('Trying to login', '')
                spinner.start()

                try:
                    net_utils.send_packet_and_close(super_ip4, super_ip6,
                                                    super_port, packet)
                except socket.error as e:
                    shell.print_red(
                        f'There was an error in the login process: {e}')
                    continue

                # 2) Attende ASUP per 20 sec
                timer = Timer(20, lambda: (server.stop(), spinner.stop()))
                timer.start()

                timer.join()
                spinner.join()

                # 3) Se non è possibile agganciarsi ad un super, devo far reinserire il peer all'utente
                if len(LocalData.get_superpeer_candidates()) == 0:
                    shell.print_red(
                        'Cannot contact a superpeer from the peer you provide, please retry.'
                    )
                    continue

                # 3) Se il peer aggiunto era veramente un superpeer, allora non lo cambio
                elif LocalData.get_superpeer(
                ) in LocalData.get_superpeer_candidates():
                    break

                # 3) Se invece era un superpeer falso, pesco un super a random dalla lista dei candidati
                else:
                    index = random.randint(
                        0,
                        len(LocalData.get_superpeer_candidates()) - 1)
                    superpeer = LocalData.get_superpeer_candidate_by_index(
                        index)
                    LocalData.set_superpeer(superpeer)
                    break

        # Lancio una LOGI al superpeer scelto
        ip = net_utils.get_local_ip_for_response()
        port = str(net_utils.get_network_port()).zfill(5)
        packet = "LOGI" + ip + port

        super_ip4 = LocalData.get_superpeer_ip4()
        super_ip6 = LocalData.get_superpeer_ip6()
        super_port = LocalData.get_superpeer_port()

        try:
            sock = net_utils.send_packet(super_ip4, super_ip6, super_port,
                                         packet)
            response = sock.recv(100).decode()

            if len(response) != 20:
                shell.print_red(
                    f'There was an error in the login process: unexpected: {response}.\nPlease retry.'
                )
                LocalData.clear_backup_data()
                continue

            session_id = response[4:20]

            if session_id == '0' * 16:
                shell.print_red(
                    f'There was an error in the login process: unexpected session_id: {session_id}.\nPlease retry.'
                )
                LocalData.clear_backup_data()
                continue

            LocalData.session_id = response[4:20]
            break
        except (socket.error, AttributeError):
            shell.print_yellow(
                f'Unable to contact {super_ip4}|{super_ip6} [{super_port}]')
            # pulisco il file json da file in sharing e superpeer vecchio
            LocalData.clear_backup_data()
            if sock is not None:
                sock.close()
            continue

    shell.print_green(
        f'Successfully logged to the superpeer: {super_ip4}|{super_ip6} [{super_port}]\n'
    )

    log = Logger.Logger('peer/peer.log')

    server = ServerThread(net_utils.get_network_port(),
                          NetworkHandler.NetworkHandler(log))
    server.daemon = True
    server.start()

    Menu(MenuHandler.MenuHandler()).show()
예제 #8
0
	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
예제 #9
0
    def serve(self, sd: socket.socket) -> None:
        """ Handle the peer request

		:param sd: the socket descriptor used for read the request
		:return None
		"""
        try:
            command = sd.recv(4).decode()
        except OSError as e:
            shell_colors.print_red(
                f'\nUnable to read the command from the socket: {e}\n')
            sd.close()
            return

        if command == "AQUE":
            try:
                response = sd.recv(300).decode()
            except socket.error as e:
                shell_colors.print_red(
                    f'\nUnable to read the {command} response from the socket: {e}\n'
                )
                sd.close()
                return

            sd.close()

            if len(response) != 208:
                print(
                    f"\nInvalid response: {command} -> {response}. Expected: AQUE<pkt_id><ip_peer><port_peer><fileMD5><filename>\n"
                )
                return

            pktid = response[0:16]
            ip_peer = response[16:71]
            ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer)
            port_peer = int(response[71:76])
            filemd5 = response[76:108]
            filename = response[108:208].lower().lstrip().rstrip()

            if pktid != AppData.get_sent_packet():
                sd.close()
                return

            if not AppData.exist_peer_files(ip4_peer, ip6_peer, port_peer,
                                            filemd5, filename):
                AppData.add_peer_files(ip4_peer, ip6_peer, port_peer, filemd5,
                                       filename)
                index = AppData.peer_file_index(ip4_peer, ip6_peer, port_peer,
                                                filemd5, filename)
                print(f'{index +1}] ', end='')
                shell_colors.print_blue(f'{filename} ', end='')
                shell_colors.print_yellow(f'md5={filemd5} ', end='')
                print(f'({ip4_peer}|{ip6_peer} [{port_peer}])')

        elif command == "ANEA":
            try:
                response = sd.recv(300).decode()
            except socket.error as e:
                shell_colors.print_red(
                    f'\nUnable to read the {command} response from the socket: {e}\n'
                )
                sd.close()
                return

            sd.close()

            if len(response) != 76:
                shell_colors.print_red(
                    f"\nInvalid response: : {command} -> {response}. Expected: ANEA<pkt_id><ip_peer><port_peer>"
                )
                return

            pktid = response[0:16]
            ip_peer = response[16:71]
            ip4_peer, ip6_peer = net_utils.get_ip_pair(ip_peer)
            port_peer = int(response[71:76])

            if pktid != AppData.get_sent_packet():
                return

            if len(AppData.get_neighbours()) >= 5:
                return

            if not AppData.is_neighbour(ip4_peer, ip6_peer, port_peer):
                AppData.add_neighbour(ip4_peer, ip6_peer, port_peer)
                shell_colors.print_green('New neighbour found: ', end='')
                print(f'{ip4_peer}|{ip6_peer} [{port_peer}]')

        else:
            wrong_response = sd.recv(300).decode()
            sd.close()
            shell_colors.print_red(
                f"\nInvalid response: {command} -> {wrong_response}\n")

        return
예제 #10
0
    def serve(choice: str) -> None:
        """ Handle the peer packet

		:param choice: the choice to handle
		:return: None
		"""

        tracker_ip4 = LocalData.get_tracker_ip4()
        tracker_ip6 = LocalData.get_tracker_ip6()
        tracker_port = LocalData.get_tracker_port()
        ssid = LocalData.get_session_id()
        log = Logger.Logger('peer/peer.log')

        if choice == "LOOK":
            # Search a file
            while True:
                search = input('\nInsert file\'s name (q to cancel): ')

                if search == "q":
                    print('\n')
                    return

                if not 0 < len(search) <= 20:
                    shell.print_red(
                        '\nQuery string must be a valid value (1 - 20 chars).')
                    continue

                break

            packet = choice + ssid + search.ljust(20)

            sd = None
            try:
                sd = net_utils.send_packet(tracker_ip4, tracker_ip6,
                                           tracker_port, packet)
            except net_utils.socket.error as e:
                shell.print_red(
                    f'\nError while sending the request to the tracker: {tracker_ip4}|{tracker_ip6} [{tracker_port}].'
                )
                shell.print_red(f'Error: {e}')
                if sd is not None:
                    sd.close()
                return

            # Receiving the response list
            try:
                command = sd.recv(4).decode()
            except net_utils.socket.error as e:
                shell.print_red(
                    f'Unable to read the command from the socket: {e}\n')
                sd.close()
                return

            if command != 'ALOO':
                shell.print_red(
                    f'\nReceived a packet with a wrong command ({command}).')
                return

            try:
                num_files = int(sd.recv(3).decode())
            except net_utils.socket.error as e:
                shell.print_red(
                    f'Unable to read the command from the socket: {e}\n')
                sd.close()
                return

            if num_files == 0:
                shell.print_yellow(f'{search} not found.\n')
                sd.close()
                return

            downloadables = list()

            for i in range(num_files):
                try:
                    file_md5 = sd.recv(32).decode()
                    file_name = sd.recv(100).decode().lstrip().rstrip()
                    len_file = int(sd.recv(10))
                    len_part = int(sd.recv(6))
                except net_utils.socket.error as e:
                    shell.print_red(
                        f'\nError while receiving the response from the tracker: {e}\n'
                    )
                    continue
                except ValueError:
                    shell.print_red(f'\nInvalid packet from tracker: {e}\n')
                    continue

                downloadables.append((file_md5, file_name, len_file, len_part))

            sd.close()

            if not downloadables:
                shell.print_red(
                    f'\nSomething went wrong while retrieving {search}\n')
                return

            shell.print_green(f'\nFiles found:')
            for count, downloadable in enumerate(downloadables, 1):
                print(
                    f'{count}] {LocalData.get_downloadable_file_name(downloadable)} | ',
                    end='')
                shell.print_yellow(
                    f'{LocalData.get_downloadable_file_md5(downloadable)}')

            # Download choice
            while True:
                file_index = input(
                    '\nChoose a file to download (q to cancel): ')

                if file_index == "q":
                    return

                try:
                    file_index = int(file_index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(downloadables)} expected\n'
                    )
                    continue

                if not 0 <= file_index <= len(downloadables) - 1:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(downloadables)} expected\n'
                    )
                    continue
                else:
                    choosed_file_md5 = LocalData.get_downloadable_file_md5(
                        downloadables[file_index])
                    choosed_file_name = LocalData.get_downloadable_file_name(
                        downloadables[file_index])
                    if LocalData.is_shared_file(choosed_file_md5,
                                                choosed_file_name):
                        shell.print_green(
                            f'\nYou already have downloaded {choosed_file_name}.'
                        )
                        continue
                    choosed_file_lenght = LocalData.get_downloadable_file_length(
                        downloadables[file_index])
                    choosed_file_part_lenght = LocalData.get_downloadable_file_part_length(
                        downloadables[file_index])
                    break

            choosed_file_parts = int(
                math.ceil(choosed_file_lenght / choosed_file_part_lenght))
            choosed_file_part_list_length = int(
                math.ceil(choosed_file_parts / 8))

            # Download phase
            LocalData.create_downloading_part_list(
                choosed_file_part_list_length)

            # 1) Initiating the thread responsible for update of the part_list_table in background
            update_event = Event()
            updater_thread = UpdaterThread.UpdaterThread(
                choosed_file_md5, choosed_file_part_list_length, update_event,
                log)
            updater_thread.start()

            # 2) Create the new file
            f_obj = open(f'shared/{choosed_file_name}', 'wb')
            f_obj.close()
            LocalData.set_num_parts_owned(0)
            progress_bar.print_progress_bar(0,
                                            choosed_file_parts,
                                            prefix='Downloading:',
                                            suffix='Complete',
                                            length=50)
            # Adding the file to the shared file list
            LocalData.add_shared_file(choosed_file_md5, choosed_file_name)

            # Until all the parts hasn't been downloaded
            while choosed_file_parts != LocalData.get_num_parts_owned():
                update_event.wait(70)
                update_event.clear()
                # We can use a with statement to ensure threads are cleaned up promptly
                with ThreadPoolExecutor(max_workers=10) as executor:
                    # Get the file parts we don't have yet
                    downloadable_parts = LocalData.get_downloadable_parts()
                    for part_num in downloadable_parts:
                        try:
                            # Start the load operations
                            executor.submit(download_task.run,
                                            choosed_file_md5,
                                            choosed_file_name, part_num,
                                            choosed_file_part_lenght,
                                            choosed_file_parts, log)
                        except OSError as e:
                            log.write_red(
                                f'\nError while downloading {choosed_file_name}: {e}'
                            )
                    executor.shutdown()

            updater_thread.stop()
            shell.print_green('\nDownload completed.')

        elif choice == "ADDR":
            # check if shared directory exist
            if not os.path.exists('shared'):
                shell.print_red('\nCannot find the shared folder.')
                return

            # check for file available in shared directory
            if not os.listdir('shared'):
                shell.print_yellow(
                    'No file available for sharing.\nAdd files to shared dir to get started.\n'
                )
                return

            temp_files = []
            shell.print_blue('\nFiles available for sharing:')
            for count, file in enumerate(os.scandir('shared'), 1):
                # print scandir results
                file_md5 = hasher.get_md5(f'shared/{file.name}')
                print(f'{count}] {file.name} | {file_md5}')
                temp_files.append((file_md5, file.name))

            while True:
                file_index = input('\nChoose a file to share (q to cancel): ')

                if file_index == "q":
                    return

                try:
                    file_index = int(file_index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(temp_files)} expected\n'
                    )
                    continue

                if 0 <= file_index <= len(temp_files) - 1:
                    file_name = LocalData.get_shared_file_name(
                        temp_files[file_index])
                    file_md5 = LocalData.get_shared_file_md5(
                        temp_files[file_index])

                    # check if file is already in sharing
                    if not LocalData.is_shared_file(file_md5, file_name):

                        try:
                            f_obj = open('shared/' + file_name, 'rb')
                        except OSError as e:
                            shell.print_red(
                                f'Cannot open the file to upload: {e}')
                            return

                        try:
                            filesize = str(os.fstat(f_obj.fileno()).st_size)
                        except OSError as e:
                            shell.print_red(f'Something went wrong: {e}')
                            return
                        except ValueError as e:
                            shell.print_red(
                                f'\nUnable to convert filesize in string: {e}\n'
                            )
                            return

                        part_size = str(net_utils.get_part_size())

                        # build packet and sent to tracker
                        packet = choice + ssid + filesize.zfill(
                            10) + part_size.zfill(6) + file_name.ljust(
                                100) + file_md5

                        sd = None
                        try:
                            sd = net_utils.send_packet(tracker_ip4,
                                                       tracker_ip6,
                                                       tracker_port, packet)
                        except net_utils.socket.error as e:
                            shell.print_red(
                                f'\nError while sending the request to the tracker: {tracker_ip4}|{tracker_ip6} [{tracker_port}].'
                            )
                            shell.print_red(f'Error: {e}')
                            if sd is not None:
                                sd.close()
                            return

                        try:
                            response = sd.recv(200).decode()
                        except net_utils.socket.error as e:
                            shell.print_red(
                                f'Unable to read the response from the socket: {e}\n'
                            )
                            sd.close()
                            return
                        sd.close()

                        if len(response) != 12:
                            shell.print_red(
                                f"Invalid response: : {response}. Expected: AADR<num_part>"
                            )
                            return

                        command = response[0:4]

                        if command != 'AADR':
                            shell.print_red(
                                f'\nReceived a packet with a wrong command ({command}).'
                            )
                            return

                        num_part = response[4:12]

                        # add file to shared_files
                        LocalData.add_shared_file(file_md5, file_name)
                        shell.print_blue(
                            f'\nNew shared file added {file_name} | {file_md5}',
                            end='')
                        shell.print_green(f' #parts: {num_part}')
                        break
                    else:
                        # if not in sharing
                        shell.print_yellow(
                            f'\n{file_name} | {file_md5} already in sharing.\n'
                        )
                        break
                else:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(temp_files)} expected\n'
                    )
                    continue

        elif choice == "LOGO":
            packet = choice + ssid

            sd = None
            try:
                sd = net_utils.send_packet(tracker_ip4, tracker_ip6,
                                           tracker_port, packet)
            except net_utils.socket.error as e:
                shell.print_red(
                    f'\nError while sending the request to the tracker: {tracker_ip4}|{tracker_ip6} [{tracker_port}].'
                )
                shell.print_red(f'{e}')
                if sd is not None:
                    sd.close()
                return

            try:
                response = sd.recv(50).decode()
            except net_utils.socket.error as e:
                shell.print_red(
                    f'Unable to read the response from the socket: {e}\n')
                sd.close()
                return

            sd.close()

            if len(response) != 14:
                shell.print_red(
                    f"Invalid response form the socket: {response}.")
                return

            command = response[0:4]

            if command == "ALOG":
                part_own = int(response[4:14])
                shell.print_green('\nSuccessfully logged out')
                shell.print_blue(
                    f'{part_own} parts has been removed from sharing.\n')
                LocalData.clear_tracker()

            elif command == "NLOG":
                part_down = int(response[4:14])
                shell.print_yellow(
                    f'\nUnable to logout:\nYou have shared only {part_down} parts with other peer.\n'
                )

            else:
                shell.print_red(
                    f'\nReceived a packet with a wrong command from the socket: {command} -> {response}'
                )

        elif choice == 'SHAR':
            files = LocalData.get_shared_files()
            if not files:
                shell.print_red('\nYou currently have no files in sharing.')

            print('\nFiles actually in sharing:')
            for count, file in enumerate(files, 1):
                print(f'{count}] {LocalData.get_downloadable_file_name(file)}')

        elif choice == 'TRAC':
            shell.print_green(
                f'\nYour tracker is: {LocalData.get_tracker_ip4()}|{LocalData.get_tracker_ip6()} [{LocalData.get_tracker_port()}]'
            )

        else:
            shell.print_yellow(
                f'\nInvalid input code: "{choice}".\nPlease retry.\n')
            return
예제 #11
0
import os
from utils import net_utils, shell_colors as shell
from peer import peer
from tracker import tracker

shell.print_purple("__________", end="")
shell.print_green("           ___________                                 __")
shell.print_purple("\______   \__ __  ___", end="")
shell.print_green("\__    ___/_________________   ____   _____/  |_")
shell.print_purple(" |    |  _/  |  \/ ___\\", end="")
shell.print_green("|    | /  _ \_  __ \_  __ \_/ __ \ /    \   __\\")
shell.print_purple(" |    |   \  |  / /_/  >", end="")
shell.print_green("    |(  <_> )  | \/|  | \/\  ___/|   |  \  |")
shell.print_purple(" |______  /____/\___  /", end="")
shell.print_green("|____| \____/|__|   |__|    \___  >___|  /__|")
shell.print_purple("        \/     /_____/", end="")
shell.print_green("                                 \/     \/")

if not os.path.exists('shared'):
    os.mkdir('shared')

net_utils.prompt_parameters_request()

choice = ''
while choice != 'q':
    choice = input('\nAre you a tracker? (y/n): ')
    if choice == 'y':
        tracker.startup()
        break
    elif choice == 'n':
        peer.startup()
예제 #12
0
    def serve(choice: str) -> None:
        """ Handle the peer packet

		:param choice: the choice to handle
		:return: None
		"""
        sp_ip4 = LocalData.get_superpeer_ip4()
        sp_ip6 = LocalData.get_superpeer_ip6()
        sp_port = LocalData.get_superpeer_port()
        p_ssid = LocalData.session_id

        if choice == "ADFF":
            # check se shared dir esiste
            if not os.path.exists('shared'):
                shell.print_red('\nCannot find the shared folder.')
                return

            # se non ci sono file nella shared dir avvisa ed esce
            if not os.scandir('shared'):
                shell.print_yellow(
                    'No file available for sharing. Add files to shared dir to get started.\n'
                )
                return

            temp_files = []
            shell.print_blue('\nFiles available for sharing:')
            for count, file in enumerate(os.scandir('shared'), 1):
                # stampa i risultati della scandir
                file_md5 = hasher.get_md5(f'shared/{file.name}')
                print(f'{count}] {file.name} | {file_md5}')
                temp_files.append((file_md5, file.name))

            while True:
                index = input('Choose a file to share (q to cancel): ')

                if index == "q":
                    print('\n')
                    return

                try:
                    index = int(index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(temp_files)} expected\n'
                    )
                    continue

                if 0 <= index <= len(temp_files) - 1:
                    file_name = LocalData.get_shared_file_name(
                        temp_files[index])
                    file_md5 = LocalData.get_shared_file_md5(temp_files[index])

                    # controlla se il file è già in condivisione
                    if not LocalData.is_shared_file(temp_files[index]):

                        # crea il pacchetto e lo invia al super peer
                        packet = choice + p_ssid + file_md5 + file_name.ljust(
                            100)
                        try:
                            net_utils.send_packet_and_close(
                                sp_ip4, sp_ip6, sp_port, packet)
                            shell.print_green(
                                f'Packet sent to supernode: {sp_ip4}|{sp_ip6} [{sp_port}]'
                            )
                        except net_utils.socket.error:
                            shell.print_red(
                                f'\nError while sending packet to supernode: {sp_ip4}|{sp_ip6} [{sp_port}]\n'
                            )

                        # aggiunge il file alla struttura dati ed esce
                        LocalData.add_shared_file(file_md5, file_name)
                        shell.print_blue(
                            f'\nNew shared file added {file_name} | {file_md5}'
                        )
                        break
                    else:
                        # il file è già in condivisione
                        shell.print_yellow(
                            f'\n{file_name} | {file_md5} already in sharing.\n'
                        )
                        break
                else:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(temp_files)} expected\n'
                    )
                    continue

        elif choice == "DEFF":
            # recupera i files in sharing
            files = LocalData.get_shared_files()

            # check se ci sono file in sharing
            if not files:
                shell.print_yellow(
                    'No files currently in sharing. Add files choosing the command from the menu.\n'
                )
                return

            # scelta del file da rimuovere
            shell.print_blue('\nFile currently in sharing:')
            for count, file in enumerate(files, 1):
                print(
                    f'{count}] {LocalData.get_shared_file_name(file)} | {LocalData.get_shared_file_md5(file)}'
                )

            while True:
                index = input(
                    'Choose a file to remove from sharing (q to cancel): ')

                if index == "q":
                    print('\n')
                    return

                try:
                    index = int(index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(files)} expected\n'
                    )
                    continue

                if 0 <= index <= len(files) - 1:
                    # recupera il file dalla DS
                    file = LocalData.get_shared_file(index)

                    # crea ed invia il pacchetto al supernode
                    packet = choice + p_ssid + LocalData.get_shared_file_md5(
                        file)
                    try:
                        net_utils.send_packet_and_close(
                            sp_ip4, sp_ip6, sp_port, packet)
                    except net_utils.socket.error:
                        shell.print_red(
                            f'\nError while sending packet to supernode: {sp_ip4}|{sp_ip6} [{sp_port}]\n'
                        )

                    # rimuove il file dalla DS
                    LocalData.remove_shared_file(file)

                    shell.print_green(
                        f'\n{LocalData.get_shared_file_name(file)} | {LocalData.get_shared_file_md5(file)} removed successfully.'
                    )
                    break
                else:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(files)} expected\n'
                    )
                    continue

        elif choice == "FIND":
            while True:
                search = input('\nInsert file\'s name (q to cancel): ')

                if search == "q":
                    print('\n')
                    return

                if not 0 < len(search) <= 20:
                    shell.print_red(
                        '\nQuery string must be a valid value (1 - 20 chars).')
                    continue

                break

            packet = choice + p_ssid + search.ljust(20)

            try:
                socket = net_utils.send_packet(sp_ip4, sp_ip6, sp_port, packet)

            except (net_utils.socket.error, AttributeError):
                shell.print_red(
                    f'\nError while sending the request to the superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                )
                if socket is not None:
                    socket.close()
                return

            spinner = SpinnerThread('Searching files', 'Research done!')
            spinner.start()

            try:
                socket.settimeout(25)
                command = socket.recv(4).decode()

                spinner.stop()
                spinner.join()
                print('\033[1A', end='\r')

                if command != "AFIN":
                    shell.print_red(
                        f'\nReceived a packet with a wrong command ({command}).\n'
                    )
                    socket.close()
                    return

            except net_utils.socket.error:
                shell.print_red(
                    f'\nError while receiving the response from the superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                )
                return
            except ValueError:
                shell.print_red(
                    f'\nInvalid packet from superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                )
                return

            # ('file_name', 'file_md5', owners[])
            downloadables = list()

            try:
                num_downloadables = int(socket.recv(3))

                # check se ci sono file da scaricare
                if num_downloadables == 0:
                    shell.print_yellow(f'{search} not found.\n')
                    socket.close()
                    return
            except net_utils.socket.error:
                shell.print_red(
                    f'\nError while receiving the response from the superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                )
                return

            for i in range(num_downloadables):
                # ('owner_ip4', 'owner_ip6', 'owner_port')
                owners = list()

                try:
                    file_md5 = socket.recv(32).decode()
                    file_name = socket.recv(100).decode().lstrip().rstrip()
                    num_copies = int(socket.recv(3))
                except net_utils.socket.error:
                    shell.print_red(
                        f'\nError while receiving the response from the superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                    )
                    continue
                except ValueError:
                    shell.print_red(
                        f'\nInvalid packet from superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                    )
                    continue

                for j in range(num_copies):
                    try:
                        (owner_ip4, owner_ip6) = net_utils.get_ip_pair(
                            socket.recv(55).decode())
                        owner_port = int(socket.recv(5))
                        owners.append((owner_ip4, owner_ip6, owner_port))
                    except net_utils.socket.error:
                        shell.print_red(
                            f'\nError while receiving the response from the superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                        )
                        continue
                    except ValueError:
                        shell.print_red(
                            f'\nInvalid packet from superpeer: {sp_ip4}|{sp_ip6} [{sp_port}].\n'
                        )
                        continue

                if owners:
                    # prepara una lista con tutti i file che possono essere scaricati
                    downloadables.append((file_name, file_md5, owners))

            if not downloadables:
                shell.print_red(
                    f'\nSomething went wrong while retrieving {search}\n')
                socket.close()
                return

            shell.print_green(f'\nFiles found:')
            for count, downloadable in enumerate(downloadables, 1):
                print(f'{count}] {downloadable[0]} | {downloadable[1]}')

            while True:
                choosed_file_index = input(
                    'Choose a file to download (q to cancel): ')

                if choosed_file_index == "q":
                    print('\n')
                    socket.close()
                    return

                try:
                    choosed_file_index = int(choosed_file_index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(downloadables)} expected\n'
                    )
                    continue

                if not 0 <= choosed_file_index <= len(downloadables) - 1:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(downloadables)} expected\n'
                    )
                    continue
                else:
                    choosed_file_name = downloadables[choosed_file_index][0]
                    choosed_file_md5 = downloadables[choosed_file_index][1]
                    choosed_file_owners = downloadables[choosed_file_index][2]

                    shell.print_green(
                        f'\nAvailable sources for {choosed_file_name}:')
                    for count, choosed_file_owner in enumerate(
                            choosed_file_owners, 1):
                        print(
                            f'{count}] {choosed_file_owner[0]}|{choosed_file_owner[1]} [{choosed_file_owner[2]}]'
                        )

                    while True:
                        choosed_owner_index = input(
                            f'Choose a source for {choosed_file_name} (q to cancel): '
                        )

                        if choosed_owner_index == "q":
                            print('\n')
                            return

                        try:
                            choosed_owner_index = int(choosed_owner_index) - 1
                        except ValueError:
                            shell.print_red(
                                f'\nWrong index: number in range 1 - {len(choosed_file_owners)} expected\n'
                            )
                            continue

                        if 0 <= choosed_owner_index <= len(
                                choosed_file_owners) - 1:
                            packet = "RETR" + choosed_file_md5
                            try:
                                Downloader(
                                    choosed_file_owners[choosed_owner_index]
                                    [0],
                                    choosed_file_owners[choosed_owner_index]
                                    [1],
                                    choosed_file_owners[choosed_owner_index]
                                    [2], packet, choosed_file_name).start()
                                shell.print_green(
                                    f'\n{choosed_file_name} downloaded successfully.\n'
                                )
                            except OSError:
                                shell.print_red(
                                    f'\nError while downloading {choosed_file_name}.\n'
                                )
                            break
                        else:
                            shell.print_red(
                                f'\nWrong index: number in range 1 - {len(choosed_file_owners)} expected\n'
                            )
                            continue
                    break

        elif choice == "SHOWSUPER":
            print(
                f'\nYour current superpeer is: {sp_ip4}|{sp_ip6} [{sp_port}]\n'
            )

        elif choice == "LOGO":
            packet = choice + p_ssid
            sock = net_utils.send_packet(sp_ip4, sp_ip6, sp_port, packet)

            try:
                command = sock.recv(4).decode()
                if command != "ALGO":
                    shell.print_red(
                        f'\nWrong response code "{command}": "{choice}" expected.\n'
                    )

                num_files = int(sock.recv(3))
                shell.print_blue(
                    f'\n{num_files} files has been removed from sharing.\n')
            except (net_utils.socket.error, AttributeError):
                shell.print_red(
                    f'\nError while receiving the response for "{choice}".\n')

            LocalData.clear_backup_data()

        else:
            pass
예제 #13
0
    def serve(self, choice: str) -> None:
        """ Handle the peer packet

		:param choice: the choice to handle
		:return: None
		"""

        if choice == "LISTFILES":
            try:
                conn = database.get_connection(self.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('\nLogged peers files:')
                if not files:
                    shell.print_red('There are not logged peers files.')

                for count, shared_file in enumerate(files, 1):
                    print(f'{count}] {shared_file["file_name"]} ', end='')
                    shell.print_yellow(f'{shared_file["file_md5"]}\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 == "SHOWPARTS":

            try:
                conn = database.get_connection(self.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

            peer_list = peer_repository.find_all(conn)

            if not peer_list:
                shell.print_red('There are no logged 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')

            while True:
                index = input('\nPlease select a peer(q to cancel): ')

                if index == 'q':
                    print('\n')
                    return

                try:
                    index = int(index) - 1
                except ValueError:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(peer_list)} expected.'
                    )
                    continue

                if 0 <= index <= len(peer_list):

                    chosen_peer = peer_list.pop(index)

                    peer_session_id = chosen_peer['session_id']

                    file_rows = file_repository.get_all_peer_files(
                        conn, peer_session_id)

                    if not file_rows:
                        shell.print_red('This peer has no file\'s parts')
                        conn.close()
                        return

                    for count, file_row in enumerate(file_rows, 1):
                        file_name = file_row['file_name']
                        file_md5 = file_row['file_md5']

                        part_list = bytearray(
                            file_repository.get_part_list_by_file_and_owner(
                                conn, file_md5, peer_session_id))

                        print(f'{count}] ', end='')
                        shell.print_blue(f'{file_name}|{file_md5} -> ', end='')

                        for byte_index in range(len(part_list)):
                            print(
                                f'{bin(part_list[byte_index])[2:].zfill(8)} ',
                                end='')
                        print('')
                    return ()
                else:
                    shell.print_red(
                        f'\nWrong index: number in range 1 - {len(peer_list)} expected.'
                    )
                    continue

        elif choice == "LISTPEERS":
            try:
                conn = database.get_connection(self.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('There are not logged 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

        else:
            pass