Пример #1
0
    def proccess_message(self, data, addr, running_in_thread=False):
        # data = json.loads(msg)
        if data['operation'] != 'DISCOVER':
            print("Data received: " + str(data))

        if data['operation'] == 'DISCOVER':
            if data['join']:
                # addr = str(data['sender'][1]), int(data['sender'][2])
                if addr != (self.node.ip, self.node.port):
                    answer = { 'operation': 'CONTACT', 'sender': list(self.node),
                            'key': data['key'] }

                    self.send_udp_msg(json.dumps(answer).encode(), addr)
                    self.update(tuple(data['sender']))
                    print(f"{data['sender']} joined")

            else:
                if addr != (self.node.ip, self.node.port):
                    ip, port = str(data['ip']), int(data['port'])
                    server_addr = (self.node.ip, self.tcp_server_port)
                    try: self.sendall(server_addr, ip, port)
                    except: pass

        elif data['operation'] == 'CONTACT':
            contact = tuple(data['sender'])
            self.update(contact)
            self.lookup_node(self.node.ID)

        # A peer has to perform a method specified by other peer by RPC
        elif data['operation'] == 'EXECUTE':
            result = None
            if data['method'] == 'FIND_NODE':
                result =  self.node.FIND_NODE(data['id'])
            elif data['method'] == 'FIND_VALUE':
                result = self.node.FIND_VALUE(data['id'])
                answer = {'operation': 'RESPONSE', 'result': result,
                            'key': data['key'], 'sender': [self.node.ID, self.node.ip, self.node.port] }
                self.sendall(answer, addr[1])
                if 'sender' in data: self.update(tuple(data['sender']))
                return

            elif data['method'] == 'PING':
                result = self.node.PING()
            elif data['method'] == 'STORE':
                key, value = data['store_key'], data['store_value']
                publisher, sender = tuple(data['publisher']), tuple(data['sender'])
                result = self.node.STORE(key, value, publisher, sender, to_update=data['to_update'])
            elif data['method'] == 'LOOKUP':
                result = self.lookup_value(data["id"])
            elif data['method'] == 'PUBLISH':
                node = self.node.asTuple()
                self.publish(data, node, node)

            if result is not None:
                answer = {'operation': 'RESPONSE', 'result': result,
                            'key': data['key'], 'sender': [self.node.ID, self.node.ip, self.node.port] }
                answer = utils.dumps_json(answer).encode()
                self.send_udp_msg(answer, addr)


                if 'sender' in data:
                    self.update(tuple(data['sender']))

        # A peer is requested to perform a RPC to other peer
        elif data['operation'] == 'RPC':
            msg = None

            if data['method'] == 'FIND_NODE':
                msg =  utils.build_FIND_NODE_msg(data['id'], self.node)
            elif data['method'] == 'FIND_VALUE':
                msg =  utils.build_FIND_VALUE_msg(data['id'], self.node)
            elif data['method'] == 'PING':
                msg =  utils.build_PING_msg(self.node)
            elif data['method'] == 'STORE':
                msg = utils.build_STORE_msg(data['storeKey'], data['store_value'], self.node, self.node)

            if msg is not None:
                # The address of the remote peer wich it will be used as the target of the RPC
                addr = (data['ip'], data['port'])
                msg = utils.dumps_json(msg).encode()
                self.send_udp_msg(msg, addr)


        # The peer receives the answer of a RPC made before
        elif data['operation'] == 'RESPONSE':
            self.set_response(data['key'], data)
            if not Node.Equals(data['sender'], self.node):
                self.update(data['sender'])
        if running_in_thread:
            exit_thread()
Пример #2
0
    def lookup_value(self, ID):
        to_query = self.node.get_n_closest(ID, self.node.alpha)

        pending = []
        heapq.heapify(pending)

        myinfo = (self.node.ID ^ ID, self.node.asTuple())
        enquired = [myinfo]
        alives = [myinfo]

        if len(to_query) == 0:
            founded, data, file_bytes = self.node.FIND_VALUE(ID)
            if founded: return (True, data, file_bytes)
            else: return (False, myinfo, None)
        else:
            founded, data, file_bytes = self.node.FIND_VALUE(ID)
            if founded: return (True, data, file_bytes)

        closest_node = heapq.nsmallest(1, to_query)[0][0]

        round = 1
        while True:

            for d,n in to_query:
                k_closest, data = [], None
                if not Node.Equals(n, self.node):
                    msg = utils.build_FIND_VALUE_msg(ID, self.node.asTuple())

                    sock = self.sendall(msg, n[1], close=False)
                    # data = self.get_response(msg['key'])
                    data = self.recvall(sock)
                    utils.close_connection(sock)

                    if data != None:
                        data = json.loads(data)
                        if data['result'][0]: return data['result']
                        # if data['result'][0]: return data
                        k_closest = [(t[0], tuple(t[1])) for t in data['result'][1]]
                        self.update(tuple(data['sender']))

                if (d,n) not in enquired:
                    enquired.append((d, n))

                if data != None and (d,n) not in alives:
                    alives.append((d, n))

                for t in k_closest:
                    if not t in enquired and not t in to_query and not t in pending:
                        pending.append(t)

            to_query.clear()

            if pending == []:
                break

            c = heapq.nsmallest(1, pending)[0][0]
            top = self.node.alpha if c <= closest_node else self.node.k
            closest_node = min(closest_node, c)
            for _ in range(top):
                try:
                    to_query.append(heapq.heappop(pending))
                except:
                    break
            round += 1

        return (False, heapq.nsmallest(self.node.k, enquired), None)
Пример #3
0
        def attend(client):
            while True:
                msg = self.recvall(client)

                if not msg:
                    break

                # print(f'RECEIVED MSG {msg}')
                data = {'method': None}
                try:
                    data = json.loads(msg)
                except:
                    pass

                if data['method'] == 'PUBLISH':
                    node = self.node.asTuple()
                    self.publish(data, node, node)
                elif data['method'] == 'LOOKUP':
                    answer = self.lookup_value(data['id'])

                    founded, result, file_bytes = answer[0], answer[1], answer[2]
                    if founded and result['value_type'] == 'file':

                        if not file_bytes: file_bytes = self.recv_file()
                        # try: client.sendall(file_bytes)
                        # except: pass
                        client.sendall(file_bytes)
                    else:
                        if not founded: result = None
                        client.sendall(utils.dumps_json(result).encode() + b'\r\n\r\n')
                    client.close()

                elif data['method'] == 'PING':
                    client.send(b'PING')
                elif data['method'] == 'STORE':
                    key, value = data['store_key'], data['store_value']
                    publisher, sender = tuple(data['publisher']), tuple(data['sender'])

                    real_value = None
                    if data['value_type'] == 'file':
                        real_value = self.recv_file()

                    self.node.STORE(key, value, publisher, sender, data['value_type'], real_value, data['to_update'])

                elif data['method'] == 'FIND_VALUE':
                    founded, result, file_bytes = self.node.FIND_VALUE(data['id'])
                    answer = {'operation': 'RESPONSE', 'result': (founded, result, file_bytes),
                                'key': data['key'], 'sender': [self.node.ID, self.node.ip, self.node.port] }

                    # client.sendall(utils.dumps_json(answer).encode() + b'\r\n\r\n')
                    answer = utils.dumps_json(answer)
                    client.sendall(answer.encode() + b'\r\n\r\n')
                    if founded and result['value_type'] == 'file':
                        # files_bytes = utils.load_file(result['value'])
                        self._send_file(file_bytes, data['sender'][1])

                    if not Node.Equals(data['sender'], self.node):
                        self.update(data['sender'])

                elif data['method'] == 'UPDATE':
                    self._update(data['store_key'], data['store_value'], data['publisher'], data['sender'])

                elif data['method'] == 'FIND_NODE':
                    result = self.node.FIND_NODE(data['id'])
                    answer = {'operation': 'RESPONSE', 'result': result,
                                'key': data['key'], 'sender': [self.node.ID, self.node.ip, self.node.port] }

                    # client.sendall(utils.dumps_json(answer).encode() + b'\r\n\r\n')
                    answer = utils.dumps_json(answer)
                    client.sendall(answer.encode() + b'\r\n\r\n')

                    if not Node.Equals(data['sender'], self.node):
                        self.update(data['sender'])
            exit_thread()
Пример #4
0
    def lookup_node(self, ID):
        ID = int(ID)
        to_query = self.node.get_n_closest(ID, self.node.alpha)

        pending = []
        heapq.heapify(pending)

        myinfo = (self.node.ID ^ ID, self.node.asTuple())
        enquired = [myinfo]
        alives = [myinfo]

        if len(to_query) == 0:
            return [(self.node.ID ^ ID, self.node.asTuple())]
            # return []

        closest_node = heapq.nsmallest(1, to_query)[0][0]

        round = 1
        while True:

            for d,n in to_query:
                k_closest, data = [], None
                if not Node.Equals(n, self.node):

                    # k_closest = n[1].FIND_NODE(ID, self.node.k)
                    msg = utils.build_FIND_NODE_msg(ID, self.node.asTuple())

                    ip, port = n[1], n[2]
                    # self.send_udp_msg(utils.dumps_json(msg).encode(), (ip, port))
                    # # data = self.get_answer(msg['key'])
                    # data = self.get_response(msg['key'])

                    sock = self.sendall(msg, n[1], close=False)
                    # data = self.get_response(msg['key'])
                    data = self.recvall(sock)
                    try:
                        data = json.loads(data)
                    except: data = None
                    utils.close_connection(sock)

                    if data:
                        k_closest = [(t[0], tuple(t[1])) for t in data['result']]
                        self.update(tuple(data['sender']))

                if (d,n) not in enquired:
                    enquired.append((d, n))

                if data != None and (d,n) not in alives:
                    alives.append((d, n))

                for t in k_closest:
                    if not t in enquired and not t in to_query and not t in pending:
                        pending.append(t)

            to_query.clear()

            if pending == []:
                break

            c = heapq.nsmallest(1, pending)[0][0]
           # print(c)
            #print(closest_node)
            top = self.node.alpha if c <= closest_node else self.node.k
            closest_node = min(closest_node, c)
            for _ in range(top):
                try:
                    to_query.append(heapq.heappop(pending))
                except:
                    break
            round += 1

        # return heapq.nsmallest(self.node.k, enquired)
        return heapq.nsmallest(self.node.k, alives)