示例#1
0
    def __delete_packet(self, pktid: str) -> None:
        """ Delete a packet from the net

		:param pktid: id of the packet
		:return: None
		"""
        if LocalData.exist_in_received_packets(pktid):
            LocalData.delete_received_packet(pktid)
示例#2
0
	def show(self) -> None:
		""" Shows the menu that interacts with the user

		:return: None
		"""

		choice = ''
		while choice != 'q':
			print('\n- Main Menù -----------------------')
			print('| <1> Search a file to download   |')
			print('| <2> Share a file                |')
			print('| <3> Files in sharing            |')
			print('| <4> Your tracker                |')
			print('-----------------------------------')
			choice = input('Select an option (q to logout): ')

			if choice in {'1', '2', '3', '4'}:
				if choice == '1':
					command = 'LOOK'
				elif choice == '2':
					command = 'ADDR'
				elif choice == '3':
					command = 'SHAR'
				elif choice == '4':
					command = 'TRAC'

				self.handler.serve(command)

			elif choice == 'q':

				self.handler.serve('LOGO')
				if LocalData.tracker_is_empty():
					break
				else:
					choice = ''
					continue

			elif choice != 'q':
				shell_colors.print_red('Input code is wrong. Choose one action!\n')

		# waiting 60s for any upload running
		spinner = SpinnerThread('Waiting for any upload in progress', '')
		spinner.start()

		timer = Timer(60, lambda: (self.server.stop(), spinner.stop()))
		timer.start()

		timer.join()
		spinner.join()
		LocalData.clear_shared_files()

		shell_colors.print_blue('\nYou leaved the Network\nBye!\n')
示例#3
0
    def __forward_packet(self, ttl: str, packet: str) -> None:
        """ Forward a supe packet in the net to superpeer

		: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:
            packet = packet[:80] + str(new_ttl).zfill(2) + packet[82:]
            superpeer_ip4 = LocalData.get_superpeer_ip4()
            superpeer_ip6 = LocalData.get_superpeer_ip6()
            superpeer_port = LocalData.get_superpeer_port()

            net_utils.send_packet_and_close(superpeer_ip4, superpeer_ip6,
                                            superpeer_port, packet)
示例#4
0
    def run(self):
        tracker_ip4 = LocalData.get_tracker_ip4()
        tracker_ip6 = LocalData.get_tracker_ip6()
        tracker_port = LocalData.get_tracker_port()
        session_id = LocalData.get_session_id()

        while not self.__stop_event.is_set():
            try:
                packet = 'FCHU' + session_id + self.file_md5

                sock = self.__connect(tracker_ip4, tracker_ip6, tracker_port,
                                      packet)
            except socket.error as e:
                self.log.write_red(
                    f'\nImpossible to send data to {tracker_ip4}|{tracker_ip6} [{tracker_port}]: {e}\n'
                )
                break

            ack = sock.recv(4).decode()
            if ack != "AFCH":
                self.log.write_red(
                    f'\nInvalid command received: {ack}. Expected: AFCH\n')
                sock.close()
                break

            num_hitpeer = int(sock.recv(3).decode())

            part_list_table = list()
            for i in range(num_hitpeer):
                (hitpeer_ip4,
                 hitpeer_ip6) = net_utils.get_ip_pair(sock.recv(55).decode())
                hitpeer_port = sock.recv(5).decode()
                part_list = sock.recv(self.part_list_length)

                # Adding only other peers to the part list table regarding the file of interest
                if hitpeer_ip4 != net_utils.get_local_ipv4(
                ) and hitpeer_ip6 != net_utils.get_local_ipv6():
                    part_list_table.append(
                        ((hitpeer_ip4, hitpeer_ip6, hitpeer_port),
                         bytearray(part_list)))

            LocalData.set_part_list_table(part_list_table)

            self.log.write(f'\nPart list table for ', end='')
            self.log.write_yellow(f'{self.file_md5} ', end='')
            self.log.write(f'updated: ', end='')
            self.log.write_green(f'{len(part_list_table)} ', end='')
            self.log.write(f'sources added:')
            for source in part_list_table:
                self.log.write_blue(
                    f'{source[0][0]}|{source[0][1]} [{source[0][2]}]')
            self.log.write('')

            LocalData.update_downloadable_parts()
            self.log.write_blue(f'Downloadable parts:')
            for part_num in LocalData.get_downloadable_parts():
                self.log.write(f'{str(part_num)}, ', end='')
            self.log.write('')

            self.update_event.set()

            time.sleep(60)
示例#5
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
示例#6
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
示例#7
0
	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 == "RETP":

			if len(packet) != 44:
				self.log.write_red(f'Invalid packet received: {packet}')
				return

			file_md5 = packet[4:36]

			try:
				num_part = int(packet[36:44])
			except ValueError:
				shell.print_red(f'Invalid packet received: Part-Num must be an integer -> {num_part}\n')
				return

			file_name = LocalData.get_shared_file_name_from_md5(file_md5)

			if file_name is None:
				error_packet = 'Sorry, the requested file is not available anymore.'
				self.send_packet(sd, socket_ip_sender, socket_port_sender, error_packet)
				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}')
				error_packet = 'Sorry, the peer encountered a problem while uploading the file.'
				self.send_packet(sd, socket_ip_sender, socket_port_sender, error_packet)
				sd.close()
				return

			try:
				Uploader(sd, f_obj, num_part, self.log).start()
				self.log.write_blue(f'Sent {socket_ip_sender} [{socket_port_sender}] -> ', 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
	def run(self) -> None:
		""" Start file download

		:return: None
		"""

		try:
			packet = 'RETP' + self.file_md5 + str(self.part_num).zfill(8)

			sock = self.__connect(self.owner_ip4, self.owner_ip6, self.owner_port, packet)
		except socket.error as e:
			shell_colors.print_red(f'\nImpossible to send data to {self.owner_ip4}|{self.owner_ip6} [{self.owner_port}]: {e}\n')
			return

		ack = sock.recv(4).decode()
		if ack != "AREP":
			shell_colors.print_red(f'Invalid command received: {ack}. Expected: AREP')
			sock.close()
			return

		try:
			total_chunks = int(sock.recv(6).decode())
		except ValueError:
			shell_colors.print_red('Impossible to retrieve the part. Trying later.')
			return

		for i in range(total_chunks):
			chunk_size = sock.recv(5)
			# if not all the 5 expected bytes has been received
			while len(chunk_size) < 5:
				chunk_size += sock.recv(1)
			chunk_size = int(chunk_size)

			data = sock.recv(chunk_size)
			# if not all the expected bytes has been received
			while len(data) < chunk_size:
				data += sock.recv(1)
			self.f_obj.write(data)

		self.f_obj.close()

		try:
			packet = 'RPAD' + LocalData.session_id + self.file_md5 + str(self.part_num).zfill(8)

			sock = self.__connect(LocalData.get_tracker_ip4(), LocalData.get_tracker_ip6(), LocalData.get_tracker_port(), packet)
		except socket.error as e:
			shell_colors.print_red(f'\nImpossible to send data to {self.owner_ip4}|{self.owner_ip6} [{self.owner_port}]: {e}\n')
			return

		ack = sock.recv(4).decode()
		if ack != "APAD":
			shell_colors.print_red(f'\nInvalid command received: {ack}. Expected: APAD\n')
			sock.close()
			return

		try:
			num_parts_owned = int(sock.recv(8).decode())
		except ValueError:
			shell_colors.print_red('Error while retrieving the parts owned from the tracker.')
			return

		binary_utils.update_owned_parts(self.part_num)
		LocalData.set_num_parts_owned(num_parts_owned)
		progress_bar.print_progress_bar(num_parts_owned, self.total_file_parts, prefix='Downloading:', suffix='Complete', length=50)
示例#9
0
    def serve(self, sd: socket.socket) -> None:
        """ Handle the neighbours 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]
        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('Invalid packet. Unable to reply.')
                return

            pktid = packet[4:20]
            ip_peer = packet[20:75]
            port_peer = int(packet[75:80])
            ttl = packet[80:82]

            # packet management
            if pktid == LocalData.get_sent_packet():
                return

            if not LocalData.exist_in_received_packets(pktid):
                LocalData.add_received_packet(pktid)
                t = Timer(20, function=self.__delete_packet, args=(pktid, ))
                t.start()
            else:
                return

            # forwarding the supe packet to superpeer
            self.__forward_packet(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_file_name_from_md5(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:
            self.log.write_red('Invalid packet. Unable to reply.')
            sd.close()

        return