Exemplo n.º 1
0
    def get_neighbours(self, new_peer_id, new_peer_ip_address, new_peer_port):
        if not self.peer.successor["id"]:
            # I AM YOUR PREDECESSOR -- only one node in network
            data = self._generate_data_second_node()
            self._add_second_node(new_peer_id, new_peer_ip_address,
                                  new_peer_port)

            return data

        if self.peer.predecessor["id"] < new_peer_id < self.peer.peer_id:
            data = self._generate_data_new_predecessor()
            self._add_node_to_predecessor(new_peer_id, new_peer_ip_address,
                                          new_peer_port)

            return data

        if self.peer.peer_id < new_peer_id < self.peer.successor["id"]:
            data = self._generate_data_new_successor()
            self._add_node_to_successor(new_peer_id, new_peer_ip_address,
                                        new_peer_port)

            return data

        if new_peer_id > self.peer.peer_id and new_peer_id > self.peer.successor[
                "id"]:
            if self.peer.successor["id"] < self.peer.peer_id:  # WRAP AROUND
                data = self._generate_data_new_successor()
                self._add_node_to_successor(new_peer_id, new_peer_ip_address,
                                            new_peer_port)

                return data
            else:
                # print("Recursively ask my successor")
                req_packet = P2PRequestPacket(
                    libp2pproto.GET_NEIGHBOURS_OP_WORD,
                    [new_peer_id, new_peer_ip_address, new_peer_port])
                res_pkt = send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                              self.peer.successor["port"],
                                              req_packet)
                return res_pkt.data[0]

        if new_peer_id < self.peer.peer_id and new_peer_id < self.peer.successor[
                "id"]:
            if self.peer.successor["id"] < self.peer.peer_id:  # WRAP AROUND
                data = self._generate_data_new_successor()
                self._add_node_to_successor(new_peer_id, new_peer_ip_address,
                                            new_peer_port)

                return data
            else:
                # print("Recursively ask my successor")
                req_packet = P2PRequestPacket(
                    libp2pproto.GET_NEIGHBOURS_OP_WORD,
                    [new_peer_id, new_peer_ip_address, new_peer_port])
                res_pkt = send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                              self.peer.successor["port"],
                                              req_packet)
                return res_pkt.data[0]
Exemplo n.º 2
0
    def _handle_download_file_request(self, filename):
        overall_bytes = b""

        for chunk_name in generate_chunks_filename(filename):
            ip_addr_port = self.dhash.get(chunk_name)

            if ip_addr_port == None:
                return libp2puds.construct_unknown_res()
            else:
                ip_addr, port = ip_addr_port.split(":")[0], int(
                    ip_addr_port.split(":")[1])
                print("Download source of %s is: %s" %
                      (chunk_name, ip_addr_port))

                if ip_addr == self.ip_addr:
                    real_filename = remove_chunk_suffix(chunk_name)
                    chunk_number = get_chunk_number_from_filename(chunk_name)
                    byte_data = get_file_chunk_byte(real_filename,
                                                    chunk_number)
                    overall_bytes = overall_bytes + byte_data
                else:
                    req_packet = P2PRequestPacket(
                        libp2pproto.DOWNLOAD_FILE_OP_WORD, [chunk_name])
                    res_pkt = send_p2p_tcp_packet(
                        self.peer.successor['ip_addr'],
                        self.peer.successor['port'], req_packet)

                    if len(res_pkt.data) > 0:
                        overall_bytes = overall_bytes + res_pkt.data[0].encode(
                        )

        return UdsResponsePacket(libp2puds.OK_RES_CODE, libp2puds.OK_RES_MSG,
                                 [overall_bytes.decode()])
Exemplo n.º 3
0
    def get(self, filename):
        dbconn = sqlite3.connect(DB_NAME)
        cursor = dbconn.cursor()
        cursor.execute(SELECT_QUERY, (filename, ))
        datum = cursor.fetchone()
        dbconn.close()

        if datum == None:
            if self._check_filename_responsibility(filename):
                # If I am responsible and file is not found == ggwp
                return None
            else:
                # Ask successor
                req_packet = P2PRequestPacket(libp2pproto.GET_FILE_OP_WORD,
                                              [filename])
                res_packet = send_p2p_tcp_packet(
                    self.peer.successor["ip_addr"],
                    self.peer.successor['port'], req_packet)

                if len(res_packet.data) > 0:
                    return res_packet.data[0]
                else:
                    return None

                return None
        else:
            ip_addr_port_str = datum[2].replace(' ', '')
            return json.loads(ip_addr_port_str)[0]
Exemplo n.º 4
0
    def put(self, filename, ip_addr_port):
        if self._check_filename_responsibility(filename):
            dbconn = sqlite3.connect(DB_NAME)
            cursor = dbconn.cursor()
            cursor.execute(SELECT_QUERY, (filename, ))
            db_result = cursor.fetchone()

            if db_result == None:
                insert_query = """
                    INSERT INTO p2pdht (filename, ip_addr_list) VALUES (?, ?)
                """
                cursor.execute(insert_query,
                               (filename, json.dumps([ip_addr_port])))
            else:
                update_query = """
                    UPDATE p2pdht SET ip_addr_list=? WHERE id=?
                """
                ip_addr_list = json.loads(db_result[2])
                ip_addr_list.append(ip_addr_port)
                cursor.execute(update_query,
                               (json.dumps(ip_addr_list), int(db_result[0])))
            dbconn.commit()
            dbconn.close()
            return True
        else:
            # Ask successor
            req_packet = P2PRequestPacket(libp2pproto.PUT_FILE_OP_WORD,
                                          [filename, ip_addr_port])
            res_packet = send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                             self.peer.successor['port'],
                                             req_packet)
            return res_packet.code == libp2pproto.OK_RES_CODE
Exemplo n.º 5
0
    def _handle_p2p_list_request(self, ip_addr):
        successor_data = []
        if self.peer.successor["ip_addr"] != ip_addr:
            req_packet = P2PRequestPacket(libp2pproto.LIST_FILES_OP_WORD,
                                          [ip_addr])
            res_pkt = send_p2p_tcp_packet(self.peer.successor['ip_addr'],
                                          self.peer.successor['port'],
                                          req_packet)
            successor_data = res_pkt.data

        successor_data = successor_data + self.dhash.get_local_keys()
        return P2PResponsePacket(libp2pproto.OK_RES_CODE,
                                 libp2pproto.OK_RES_MSG, successor_data)
Exemplo n.º 6
0
    def _handle_list_files_request(self):
        data = self.dhash.get_local_keys()
        if self.peer.successor['id']:
            req_packet = P2PRequestPacket(libp2pproto.LIST_FILES_OP_WORD,
                                          [self.ip_addr])
            res_pkt = send_p2p_tcp_packet(self.peer.successor['ip_addr'],
                                          self.peer.successor['port'],
                                          req_packet)
            data = res_pkt.data + self.dhash.get_local_keys()

        data = [remove_chunk_suffix(f) for f in data]
        return UdsResponsePacket(libp2puds.OK_RES_CODE, libp2puds.OK_RES_MSG,
                                 data)
Exemplo n.º 7
0
    def _handle_p2p_connection(self, socket):
        data_string = ""
        while True:
            try:
                data_bytes = socket.recv(MAX_PACKET_SIZE)
                data_string = data_string + data_bytes.decode("utf-8")

                # print("-------", data.req_str)
                req_pkt = P2PRequestPacket.parse(data_string)
                res_pkt = self._process_p2p_request(req_pkt)

                socket.sendall(res_pkt.encode_bytes())
                socket.close()
                break
            except ValueError as err:
                if int(str(err)) == libp2pproto.MALFORMED_PACKET_ERROR:
                    malform_res = libp2pproto.construct_malformed_res()
                    socket.sendall(malform_res.encode_bytes())
Exemplo n.º 8
0
    def _process_p2p_request(self, req_pkt):
        op_word, args = req_pkt.op_word, req_pkt.args
        # print(op_word, args)

        if op_word == libp2pproto.GET_NEIGHBOURS_OP_WORD:
            peer_id = int(args[libp2pproto.GET_NEIGHBOURS_PEER_ID_INDEX])
            ip_addr = args[libp2pproto.GET_NEIGHBOURS_PEER_IP_ADDR_INDEX]
            port = int(args[libp2pproto.GET_NEIGHBOURS_PEER_PORT_INDEX])
            return self._handle_p2p_get_neighbors(peer_id, ip_addr, port)

        if op_word == libp2pproto.INFORM_PREDECESSOR_PREDECESSOR_OP_WORD:
            peer_id = int(args[libp2pproto.INFORM_PREDECESSOR_PEER_ID_INDEX])
            ip_addr = args[libp2pproto.INFORM_PREDECESSOR_PEER_IP_ADDR_INDEX]
            port = int(args[libp2pproto.INFORM_PREDECESSOR_PEER_PORT_INDEX])

            inform_packet = P2PRequestPacket(
                libp2pproto.INFORM_PREDECESSOR_OP_WORD, [
                    self.peer.peer_id, self.peer.ip_addr,
                    self.peer.external_port, peer_id, ip_addr, port
                ])
            return send_p2p_tcp_packet(self.peer.predecessor["ip_addr"],
                                       self.peer.predecessor["port"],
                                       inform_packet)

        if op_word == libp2pproto.INFORM_PREDECESSOR_OP_WORD:
            peer_id = int(args[libp2pproto.INFORM_PREDECESSOR_PEER_ID_INDEX])
            ip_addr = args[libp2pproto.INFORM_PREDECESSOR_PEER_IP_ADDR_INDEX]
            port = int(args[libp2pproto.INFORM_PREDECESSOR_PEER_PORT_INDEX])

            next_successor_peer_id = int(
                args[libp2pproto.INFORM_PREDECESSOR_SUCCESSOR_PEER_ID_INDEX])
            next_successor_ip_addr = args[
                libp2pproto.INFORM_PREDECESSOR_SUCCESSOR_PEER_IP_ADDR_INDEX]
            next_successor_port = int(
                args[libp2pproto.INFORM_PREDECESSOR_SUCCESSOR_PEER_PORT_INDEX])

            return self._handle_p2p_inform_predecessor(peer_id, ip_addr, port,
                                                       next_successor_peer_id,
                                                       next_successor_ip_addr,
                                                       next_successor_port)

        if op_word == libp2pproto.INFORM_SUCCESSOR_OP_WORD:
            peer_id = int(args[libp2pproto.INFORM_SUCCESSOR_PEER_ID_INDEX])
            ip_addr = args[libp2pproto.INFORM_SUCCESSOR_PEER_IP_ADDR_INDEX]
            port = int(args[libp2pproto.INFORM_SUCCESSOR_PEER_PORT_INDEX])
            return self._handle_p2p_inform_successor(peer_id, ip_addr, port)

        if op_word == libp2pproto.QUERY_SUCCESSOR_FOR_NEIGHBOURS_OP_WORD:
            return self._handle_p2p_query_successor_for_neighbours()

        if op_word == libp2pproto.PUT_FILE_OP_WORD:
            filename = args[libp2pproto.PUT_FILE_FILENAME_INDEX]
            ip_addr_port = args[libp2pproto.PUT_FILE_IP_ADDR_PORT_INDEX]
            return self._handle_p2p_put_request(filename, ip_addr_port)

        if op_word == libp2pproto.GET_FILE_OP_WORD:
            filename = args[libp2pproto.GET_FILE_FILENAME_INDEX]
            return self._handle_p2p_get_request(filename)

        if op_word == libp2pproto.LIST_FILES_OP_WORD:
            ip_addr = args[libp2pproto.LIST_FILES_IP_ADDR_INDEX]
            return self._handle_p2p_list_request(ip_addr)

        if op_word == libp2pproto.DOWNLOAD_FILE_OP_WORD:
            filename = args[libp2pproto.DOWNLOAD_FILE_FILENAME_INDEX]
            return self._handle_p2p_download_request(filename)

        return libp2pproto.construct_unknown_res()
Exemplo n.º 9
0
    def _stabilisation(self):
        if not self.peer.successor["id"]:
            #Genesis node. No Stabilisation needed
            return
        # print("---------------STABLISATION---------------")
        # self.peer.print_info()
        # print()

        stab_packet = P2PRequestPacket(
            libp2pproto.QUERY_SUCCESSOR_FOR_NEIGHBOURS_OP_WORD, [])
        try:
            res_packet = send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                             self.peer.successor["port"],
                                             stab_packet)

            if res_packet is not None:
                data = res_packet.data[0].split(" ")
                successor_predecessor_peer_id = int(data[0])
                successor_successor_peer_id = int(data[3])

                if successor_predecessor_peer_id != self.peer.peer_id:
                    # Oh, you have a new predecessor, let me add that as my successor
                    self.peer.next_successor["id"] = self.peer.successor["id"]
                    self.peer.next_successor["ip_addr"] = self.peer.successor[
                        "ip_addr"]
                    self.peer.next_successor["port"] = self.peer.successor[
                        "port"]
                    self.peer.successor["id"] = int(data[0])
                    self.peer.successor["ip_addr"] = data[1]
                    self.peer.successor["port"] = int(data[2])
                    # Inform successor of new predecessor
                    inform_packet = P2PRequestPacket(
                        libp2pproto.INFORM_SUCCESSOR_OP_WORD, [
                            self.peer.peer_id, self.peer.ip_addr,
                            self.peer.external_port
                        ])
                    send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                        self.peer.successor["port"],
                                        inform_packet)

                    # Inform predecessor of new next successor
                    inform_packet = P2PRequestPacket(
                        libp2pproto.INFORM_PREDECESSOR_OP_WORD, [
                            self.peer.peer_id, self.peer.ip_addr,
                            self.peer.external_port, self.peer.successor["id"],
                            self.peer.successor["ip_addr"],
                            self.peer.successor["port"]
                        ])
                    send_p2p_tcp_packet(self.peer.predecessor["ip_addr"],
                                        self.peer.predecessor["port"],
                                        inform_packet)

                # Ensure that there's 3 nodes in the network.
                # If there's 2 node, then the successor's successor will be the current node
                elif successor_successor_peer_id != self.peer.peer_id:
                    if successor_successor_peer_id != self.peer.next_successor[
                            "id"]:
                        # You have a new successor, let me add that as my next successor
                        self.peer.next_successor["id"] = int(data[3])
                        self.peer.next_successor["ip_addr"] = data[4]
                        self.peer.next_successor["port"] = int(data[5])

                else:
                    self.peer.next_successor["id"] = None
                    self.peer.next_successor["ip_addr"] = None
                    self.peer.next_successor["port"] = None

        # Handle when node leaves the network
        except socket.error as e:
            if e.errno == 111:
                # print("Destination node has left the network...")
                if self.peer.next_successor["id"]:
                    self.peer.successor["id"] = self.peer.next_successor["id"]
                    self.peer.successor["ip_addr"] = self.peer.next_successor[
                        "ip_addr"]
                    self.peer.successor["port"] = self.peer.next_successor[
                        "port"]

                    self.peer.next_successor["id"] = None
                    self.peer.next_successor["ip_addr"] = None
                    self.peer.next_successor["port"] = None

                    # print("Informing my predecessor to add me as its successor and my successor as its next successor")
                    inform_packet = P2PRequestPacket(
                        libp2pproto.INFORM_PREDECESSOR_OP_WORD, [
                            self.peer.peer_id, self.peer.ip_addr,
                            self.peer.external_port, self.peer.successor["id"],
                            self.peer.successor["ip_addr"],
                            self.peer.successor["port"]
                        ])

                    send_p2p_tcp_packet(self.peer.predecessor["ip_addr"],
                                        self.peer.predecessor["port"],
                                        inform_packet)

                    # print("Informing my successor to add me as its predecessor")
                    inform_packet = P2PRequestPacket(
                        libp2pproto.INFORM_SUCCESSOR_OP_WORD, [
                            self.peer.peer_id, self.peer.ip_addr,
                            self.peer.external_port
                        ])
                    send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                        self.peer.successor["port"],
                                        inform_packet)

                    self._stabilisation()
                else:
                    self.peer.predecessor["id"] = None
                    self.peer.predecessor["ip_addr"] = None
                    self.peer.predecessor["port"] = None

                    self.peer.successor["id"] = None
                    self.peer.successor["ip_addr"] = None
                    self.peer.successor["port"] = None
            else:
                raise e.strerror
Exemplo n.º 10
0
    def enter_p2p_network(self, peers_ip_port_list, dns_ip_addr):
        if len(peers_ip_port_list) == 0:
            # First node has no peers
            pass
        else:
            rand_index = randrange(len(peers_ip_port_list))
            peer_id, peer_ip_addr, peer_port = peers_ip_port_list[rand_index]
            print("Joining P2P Network...")
            print("Chosen peer_ip addr: ", peer_ip_addr, "\tport: ", peer_port)

            req_packet = P2PRequestPacket(libp2pproto.GET_NEIGHBOURS_OP_WORD, [
                self.peer.peer_id, self.peer.ip_addr, self.peer.external_port
            ])
            try:
                res_packet = send_p2p_tcp_packet(peer_ip_addr, peer_port,
                                                 req_packet)
                data = res_packet.data[0].split(" ")
                self.peer.predecessor["id"] = int(data[0])
                self.peer.predecessor["ip_addr"] = data[1]
                self.peer.predecessor["port"] = int(data[2])

                self.peer.successor["id"] = int(data[3])
                self.peer.successor["ip_addr"] = data[4]
                self.peer.successor["port"] = int(data[5])

                # handle case where there are at least 3 nodes in the network
                if int(data[6]) != -1:
                    self.peer.next_successor["id"] = int(data[6])
                    self.peer.next_successor["ip_addr"] = data[7]
                    self.peer.next_successor["port"] = int(data[8])

                    # print("Informing my predecessor's predecessor to add me as its next successor")
                    inform_packet = P2PRequestPacket(
                        libp2pproto.INFORM_PREDECESSOR_PREDECESSOR_OP_WORD, [
                            self.peer.peer_id, self.peer.ip_addr,
                            self.peer.external_port
                        ])
                    send_p2p_tcp_packet(self.peer.predecessor["ip_addr"],
                                        self.peer.predecessor["port"],
                                        inform_packet)

                # print("Informing my predecessor to add me as its successor and my successor as its next successor")
                inform_packet = P2PRequestPacket(
                    libp2pproto.INFORM_PREDECESSOR_OP_WORD, [
                        self.peer.peer_id, self.peer.ip_addr,
                        self.peer.external_port, self.peer.successor["id"],
                        self.peer.successor["ip_addr"],
                        self.peer.successor["port"]
                    ])

                send_p2p_tcp_packet(self.peer.predecessor["ip_addr"],
                                    self.peer.predecessor["port"],
                                    inform_packet)

                # print("Informing my successor to add me as its predecessor")
                inform_packet = P2PRequestPacket(
                    libp2pproto.INFORM_SUCCESSOR_OP_WORD, [
                        self.peer.peer_id, self.peer.ip_addr,
                        self.peer.external_port
                    ])
                send_p2p_tcp_packet(self.peer.successor["ip_addr"],
                                    self.peer.successor["port"], inform_packet)

            # Handle when node has left the network
            except socket.error as e:
                if e.errno == 111:
                    libp2pdns.send_dns_remove_entry(peer_id, dns_ip_addr)
                    del peers_ip_port_list[rand_index]
                    self.enter_p2p_network(peers_ip_port_list, dns_ip_addr)
                else:
                    raise e.strerror

        self.scheduler.add_job(self._stabilisation,
                               'interval',
                               seconds=STABILISATION_INTERVAL)
        self.scheduler.start()
        return