Esempio n. 1
0
    def run(self):

        try:
            self._socket.setblocking(1)  # <-------- ??

            command = str(self._socket.recv(4))

            #
            # FILES
            #

            # Received package looking for a file
            if command == "QUER":

                if UsersManager.is_super_node():
                    pckt_id = str(self._socket.recv(16))
                    sender_ip = str(self._socket.recv(15))
                    sender_port = str(self._socket.recv(5))
                    ttl = int(self._socket.recv(2))
                    query = str(self._socket.recv(20))

                    klog("%s pid: %s %s:%s ttl: %s query: %s" % (command, pckt_id, sender_ip, sender_port, ttl, query))

                    if not PacketsManager.is_packet_id_known(pckt_id):

                        PacketsManager.add_new_packet(pckt_id, sender_ip)

                        if int(ttl) > 0:

                            # look for the requested file
                            for f in FilesManager.find_files_by_query(query):
                                command = "AQUE"
                                sock = connect_socket(sender_ip, sender_port)

                                sock.send(
                                    command + pckt_id + format_ip_address(self.ip) + format_port_number(self.port)
                                )
                                sock.send(decode_md5(f.hash))
                                sock.send(format_filename(f.filename))
                                klog(
                                    "command sent %s pkid:%s %s:%s md5: %s filename: %s"
                                    % (command, pckt_id, self.ip, self.port, f.hash, f.filename)
                                )

                                sock.close()

                            # decrease ttl propagate the message to the peers
                            ttl = format_ttl(ttl - 1)

                            if int(ttl) > 0:
                                for superpeer in PeersManager.find_known_peers(superpeers=True):
                                    # query flooding to the known superpeers peers except for the sender
                                    if not PeersManager.are_same_peer(superpeer, Peer(sender_ip, sender_port)):
                                        sock = connect_socket(superpeer.ip, superpeer.port)
                                        sock.send(command + pckt_id + sender_ip + sender_port + str(ttl) + query)
                                        klog(
                                            "command sent to %s:%s: %s pkid:%s %s:%s ttl: %s query: %s"
                                            % (
                                                superpeer.ip,
                                                superpeer.port,
                                                command,
                                                pckt_id,
                                                sender_ip,
                                                sender_port,
                                                ttl,
                                                query,
                                            )
                                        )
                                        sock.close()

            # Received package in reply to a file research
            elif command == "AQUE":
                klog("AQUE received")
                search_id = str(self._socket.recv(16))
                sender_ip = str(self._socket.recv(15))
                sender_port = str(self._socket.recv(5))
                hash = encode_md5(self._socket.recv(16))
                filename = str(self._socket.recv(100)).strip(" ")
                if PacketsManager.is_local_search(search_id):
                    if PacketsManager.is_generated_packet_still_valid(search_id):
                        klog("Found %s from %s:%s" % (filename, sender_ip, sender_port))
                        self.ui_handler.add_new_result_file(filename, sender_ip, sender_port, hash)
                else:
                    ServiceThread.add_query_result(search_id, sender_ip, sender_port, hash, filename)

            elif command == "FIND":
                if UsersManager.is_super_node():
                    session_id = str(self._socket.recv(16))
                    query = str(self._socket.recv(20))
                    p_id = generate_packet_id(16)
                    ttl = 3

                    # Launch a request to the other super peers with the query
                    for superpeer in PeersManager.find_known_peers(True):
                        sock = connect_socket(superpeer.ip, superpeer.port)
                        local_ip = get_local_ip(sock.getsockname()[0])
                        sock.send(
                            "QUER"
                            + p_id
                            + format_ip_address(local_ip)
                            + format_port_number(self.port)
                            + format_ttl(ttl)
                            + format_query(query)
                        )
                        sock.close()

                    ServiceThread.initialize_for_pckt(p_id)  # enable the receive of packets for this query

                    time.sleep(20)

                    # search_id is the packet id of QUER request, it identifies univocally the query
                    superpeers_result = ServiceThread.get_query_results(p_id)
                    my_directory_result = FilesManager.find_files_by_query(query)
                    ServiceThread.clear_pending_query(p_id)
                    result = {}
                    # costruisco l array di risultati
                    for r in superpeers_result:
                        if result.has_key(r["hash"]):
                            result[r["hash"]].peers.append([{"ip": r["ip"], "port": r["port"]}])
                        else:
                            result[r["hash"]] = {
                                "filemd5": r["hash"],
                                "filename": r["filename"],
                                "peers": [{"ip": r["ip"], "port": r["port"]}],
                            }

                    for f in my_directory_result:
                        if f.is_my_file():
                            if result.has_key(f.hash):
                                result[f.hash]["peers"].append({"ip": self.ip, "port": self.port})
                            else:
                                result[f.hash] = {
                                    "filemd5": f.hash,
                                    "filename": f.filename,
                                    "peers": [{"ip": self.ip, "port": self.port}],
                                }
                        else:
                            u = UsersManager.find_user_by_session_id(f.session_id)
                            if result.has_key(f.hash):
                                result[f.hash]["peers"].append({"ip": u.ip, "port": u.port})
                            else:
                                result[f.hash] = {
                                    "filemd5": f.hash,
                                    "filename": f.filename,
                                    "peers": [{"ip": u.ip, "port": u.port}],
                                }
                        # must send AFIN

                    # self._socket.close()

                    peer = UsersManager.find_user_by_session_id(session_id)
                    # sock = connect_socket(peer.ip, peer.port)
                    sock = self._socket
                    sock.send("AFIN" + format_deletenum(len(result)))
                    for key, r in result.items():
                        sock.send(decode_md5(r["filemd5"]))
                        sock.send(format_filename(r["filename"]))
                        sock.send(format_deletenum(len(r["peers"])))
                        for peer in r["peers"]:
                            sock.send(format_ip_address(peer["ip"]))
                            sock.send(format_port_number(peer["port"]))
                    # threading.Timer(20, self.search_finished, args=(p_id,)).start()  #calls the fun function with p_id as argument
                    klog("Sent AFIN")

            elif command == "AFIN":
                klog("AFIN received")
                ServiceThread.afin_received(self._socket, self.ui_handler)

            #
            # PEERS
            #

            elif command == "LOGI":
                if UsersManager.is_super_node():
                    peer_ip = str(read_from_socket(self._socket, 15))
                    peer_port = str(read_from_socket(self._socket, 5))

                    if UsersManager.find_user_by_ip(peer_ip) is not None:
                        self._socket.send("ALGI" + "0" * 16)
                        klog("Sent ALGI" + "0" * 16 + "to: %s" % (peer_ip))
                    else:
                        session_id = self.login_user(peer_ip, peer_port)
                        klog(
                            "Received a LOGI, from: %s, port: %s. Session id created: %s"
                            % (peer_ip, peer_port, session_id)
                        )
                        self._socket.send("ALGI" + session_id)
                        klog("Sent ALGI to: %s, port: %s" % (peer_ip, peer_port))
                        self.ui_handler.add_new_peer(peer_ip, peer_port)

            elif command == "ALGI":
                # Normally this is done in the RequestEmitter, but we have the same code here to
                # prevent crashes in case of closed and re-opened socket
                session_id = str(read_from_socket(self._socket, 16))
                klog("ALGI received form super peer: %s", session_id)
                UsersManager.set_my_session_id(session_id)
                self.ui_handler.login_done(session_id)

            elif command == "LOGO":
                peer_session_id = str(read_from_socket(self._socket, 16))
                peer = UsersManager.find_user_by_session_id(peer_session_id)
                peer_ip = peer.ip
                peer_port = peer.port
                klog("Received a LOGO, from session_id: %s. Peer: %s:%s" % (peer_session_id, peer_ip, peer_port))

                delete_num = self.logout_user(peer_session_id)
                self._socket.send("ALGO" + format_deletenum(delete_num))
                klog("Sent ALGO to session_id: %s deletenum: %d" % (peer_session_id, delete_num))
                self.ui_handler.remove_peer(peer_ip, peer_port)

            elif command == "ALGO":
                delete_num = read_from_socket(self._socket, 3)
                klog("ALGO received. delete num: %s" % delete_num)

                UsersManager.set_my_session_id("")
                klog("TODO: destroy the listening client???")

            # Received package looking for super-peer
            elif command == "SUPE":
                klog("SUPE received")
                pckt_id = str(read_from_socket(self._socket, 16))
                sender_ip = str(read_from_socket(self._socket, 15))
                sender_port = str(read_from_socket(self._socket, 5))
                ttl = int(read_from_socket(self._socket, 2))

                if not PacketsManager.is_packet_id_known(pckt_id):

                    PacketsManager.add_new_packet(pckt_id, sender_ip)

                    if int(ttl) > 0:

                        if UsersManager.is_super_node():
                            # Respond with an ASUP
                            sock = connect_socket(sender_ip, sender_port)
                            sock.send("ASUP" + pckt_id + self.ip + self.port + str(ttl))
                            klog(
                                "command sent to %s:%s: ASUP pkid:%s %s:%s ttl: %s"
                                % (sender_ip, sender_port, pckt_id, self.ip, self.port, ttl)
                            )
                            sock.close()

                        # decrease ttl and propagate the message to the peers/superpeers
                        ttl = format_ttl(ttl - 1)

                        if int(ttl) > 0:
                            # propagate the SUPE
                            for peer in PeersManager.find_known_peers():
                                if not PeersManager.are_same_peer(peer, Peer(sender_ip, sender_port)):
                                    sock = connect_socket(peer.ip, peer.port)
                                    sock.send("SUPE" + pckt_id + sender_ip + sender_port + str(ttl))
                                    klog(
                                        "command sent to %s:%s: SUPE pkid:%s %s:%s ttl: %s"
                                        % (peer.ip, peer.port, pckt_id, sender_ip, sender_port, ttl)
                                    )
                                    sock.close()

            # Received package in reply to a super-peer search
            elif command == "ASUP":

                pckt_id = str(self._socket.recv(16))
                peer_ip = str(self._socket.recv(15))
                peer_port = str(self._socket.recv(5))

                klog("ASUP received from %s:%s" % (peer_ip, peer_port))

                if PacketsManager.is_generated_packet_still_valid(pckt_id):
                    # Check if the superpeer war already added as a normal peer
                    if PeersManager.is_known_peer(Peer(peer_ip, peer_port)):
                        PeersManager.become_superpeer(peer_ip, peer_port)
                        self.ui_handler.add_new_superpeer(peer_ip, peer_port)
                    else:
                        if peer_ip != self.ip:
                            PeersManager.add_new_peer(Peer(peer_ip, peer_port, True))
                            self.ui_handler.add_new_superpeer(peer_ip, peer_port)

            # Received package asking for a file
            elif command == "RETR":
                klog("RETR received")
                CHUNK_DIM = 128

                md5 = encode_md5(self._socket.recv(16))

                self._socket.send("ARET")  # sending the ack command
                remote_ip = self._socket.getpeername()[0]
                my_session_id = UsersManager.get_my_session_id()

                # Get the file matching the md5
                klog("finding file with md5: %s, session_id %s" % (md5, my_session_id))

                file = FilesManager.find_file_by_hash(md5)

                if file:
                    klog("i have found the file: %s stored in %s" % (file.filename, file.filepath))

                    # Chunks
                    size = file_size(file.filepath)
                    bytes_sent = 0
                    chunks_num = int(size // CHUNK_DIM)
                    leftover = size % CHUNK_DIM
                    if leftover != 0.0:
                        chunks_num += 1

                    self._socket.send(format_chunks_number(chunks_num))  # sending the chunks number

                    # open the file
                    file2send = open(file.filepath, "rb")
                    chunk = file2send.read(CHUNK_DIM)

                    while chunk != "":
                        self._socket.send(format_chunk_length(len(chunk)))  # sending the chunk length
                        bytes_sent += self._socket.send(chunk)  # sending the chunk

                        percent = bytes_sent * 100 / size
                        self.ui_handler.upload_file_changed(file.filename, file.hash, remote_ip, percent)

                        chunk = file2send.read(CHUNK_DIM)
                    file2send.close()

                    klog("upload completed: %s" % file.filename)
                    self.ui_handler.upload_file_changed(file.filename, file.hash, remote_ip, 100)

                else:
                    klog("I do not have this file!")

            elif command == "ADFF":
                peer_session_id = str(read_from_socket(self._socket, 16))
                file_hash = encode_md5(read_from_socket(self._socket, 16))
                file_name = str(read_from_socket(self._socket, 100)).strip(" ")
                klog("Received a ADFF, from: %s. Hash: %s. Filename: %s." % (peer_session_id, file_hash, file_name))
                self.add_file(peer_session_id, file_hash, file_name)

            elif command == "DEFF":
                peer_session_id = str(read_from_socket(self._socket, 16))
                file_hash = encode_md5(read_from_socket(self._socket, 16))
                self.remove_file(peer_session_id, file_hash)
                klog("Received a DELF, from: %s. Hash: %s." % (peer_session_id, file_hash))

            if command == "":
                condition = False

            # Close the socket
            self._socket.close()

        except Exception, ex:
            condition = False
            print ex
Esempio n. 2
0
    def run(self):

        try:
            self._socket.setblocking(1) # <-------- ??

            command = str(self._socket.recv(4))

            # Received package looking for a file
            if command == "QUER":
                pckt_id = str(self._socket.recv(16))
                sender_ip = str(self._socket.recv(15))
                sender_port = str(self._socket.recv(5))
                ttl = int(self._socket.recv(2))
                query = str(self._socket.recv(20))

                klog("%s pid: %s %s:%s ttl: %s query: %s" % (command, pckt_id, sender_ip, sender_port, ttl, query))

                if not PacketsManager.is_packet_id_known(pckt_id):

                    PacketsManager.add_new_packet(pckt_id, sender_ip)

                    if int(ttl) > 1:
                        # decrease ttl propagate the message to the peers
                        ttl = format_ttl(ttl -1)

                        for peer in PeersManager.find_known_peers():
                            #query flooding to the known peers except for the sender
                            if not PeersManager.are_same_peer(peer, Peer(sender_ip, sender_port)):
                                sock = connect_socket(peer.ip, peer.port)
                                sock.send(command + pckt_id + sender_ip + sender_port + str(ttl) + query)
                                klog("command sent to %s:%s: %s pkid:%s %s:%s ttl: %s query: %s" % (peer.ip, peer.port, command, pckt_id, sender_ip, sender_port, ttl, query))
                                sock.close()


                        # look for the requested file
                        for f in FilesManager.find_files_by_query(query):
                            md5 = f.md5
                            filename = f.filename
                            command = "AQUE"
                            sock = connect_socket(sender_ip, sender_port)
                            sent = 0
                            sent += sock.send(command + pckt_id + format_ip_address(self.ip) + format_port_number(self.port))
                            sent += sock.send(decode_md5(md5))
                            sent += sock.send(format_filename(filename))
                            klog("command sent %s pkid:%s %s:%s md5: %s filename: %s" % (command, pckt_id, self.ip, self.port, md5, filename))

                            sock.close()

            # Received package in reply to a file research
            if command == "AQUE":
                klog("AQUE received")
                pckt_id = str(self._socket.recv(16))
                peer_ip = str(self._socket.recv(15))
                peer_port = str(self._socket.recv(5))
                file_md5 = str(self._socket.recv(16))
                file_name = str(self._socket.recv(100)).strip(" ")

                if PacketsManager.is_generated_packet_still_valid(pckt_id):
                    # Add the result to the result list and show it on screen
                    self.ui_handler.add_new_result_file(file_name, peer_ip, peer_port, encode_md5(file_md5))


            # Received package looking for neighbour peers
            if command == "NEAR":
                klog("NEAR received")
                pckt_id = str(self._socket.recv(16))
                sender_ip = str(self._socket.recv(15))
                sender_port = str(self._socket.recv(5))
                ttl = int(self._socket.recv(2))

                if not PacketsManager.is_packet_id_known(pckt_id):

                    PacketsManager.add_new_packet(pckt_id, sender_ip)

                    if ttl > 1:
                        # decrease ttl and propagate the message to the peers
                        ttl = format_ttl(ttl -1)

                        for peer in PeersManager.find_known_peers():

                            #query floading to the known peers except for the sender
                            if not PeersManager.are_same_peer(peer, Peer(sender_ip, sender_port)):
                                sock = connect_socket(peer.ip, peer.port)
                                sock.send(command + pckt_id + sender_ip + sender_port + ttl)
                                klog("command sent to %s:%s: %s pkid:%s %s:%s ttl: %s" % (peer.ip, peer.port, command, pckt_id, sender_ip, sender_port, ttl))
                                sock.close()

                    # show yourself to the peer
                    sock = connect_socket(sender_ip, sender_port)
                    sock.send("ANEA" + pckt_id + self.ip + self.port)
                    sock.close()

            # Received package in reply to a neighbour peer search
            if command == "ANEA":

                pckt_id = str(self._socket.recv(16))
                peer_ip = str(self._socket.recv(15))
                peer_port = str(self._socket.recv(5))

                klog("ANEA received from %s:%s" %(peer_ip, peer_port))

                if PacketsManager.is_generated_packet_still_valid(pckt_id):
                    # Add peer to known peers
                    PeersManager.add_new_peer(peer_ip, peer_port)
                    self.ui_handler.peers_changed()

            # Received package asking for a file
            if command == "RETR":
                klog("RETR received")
                CHUNK_DIM = 128

                md5 = encode_md5(self._socket.recv(16))

                self._socket.send("ARET")   #sending the ack command
                remote_ip = self._socket.getpeername()[0]

                # Get the file matching the md5

                file = FilesManager.find_file_by_md5(md5)
                if file:
                    klog("i have found the file: %s" % file.filename)

                    # Chunks
                    size = file_size(os.path.join(file.filepath, file.filename))
                    bytes_sent = 0
                    chunks_num = int(size // CHUNK_DIM)
                    leftover = size % CHUNK_DIM
                    if leftover != 0.0:
                        chunks_num += 1

                    self._socket.send(format_chunks_number(chunks_num)) #sending the chunks number

                    #open the file
                    file2send= open(os.path.join(file.filepath, file.filename), 'rb')
                    chunk = file2send.read(CHUNK_DIM)

                    while chunk != '':
                        self._socket.send(format_chunk_length(len(chunk)))  #sending the chunk length
                        bytes_sent += self._socket.send(chunk)    #sending the chunk

                        percent = bytes_sent*100/size
                        self.ui_handler.upload_file_changed(file.filename, file.md5, remote_ip, percent)

                        chunk = file2send.read(CHUNK_DIM)
                    file2send.close()

                    klog("upload completed: %s" %file.filename)
                    self.ui_handler.upload_file_changed(file.filename, file.md5, remote_ip, 100)

                else:
                    klog("file by md5 not found")

            if command == "":
                condition = False

            # Close the socket
            self._socket.close()

        except Exception, ex:
            condition = False
            print ex