Example #1
0
    def get_node_by_server(self, ip, port):
        """

        Will find the node that has IP/Port address of input.

        Warnings:
            1. Before comparing the address parse it to a standard format with Node.parse_### functions.

        :param ip: input address IP
        :param port: input address Port

        :return: The node that input address.
        :rtype: Node
        """
        input = Node.parse_address((ip, port))
        # print('.........')
        # print(input[0])
        # print(input[1])
        # print('.........')
        # print(len(self.nodes))
        for node in self.nodes:
            add = Node.parse_address(node.get_server_address())
            # print('xxxxxxxxxxxx')
            # print(add[0])
            # print(add[1])
            # print('xxxxxxxxxxxx')
            if (input[0] == add[0]) and (input[1] == add[1]):
                return node

        pass
Example #2
0
    def __handle_advertise_packet(self, packet):
        """
        For advertising peers in the network, It is peer discovery message.

        Request:
            We should act as the root of the network and reply with a neighbour address in a new Advertise Response packet.

        Response:
            When an Advertise Response packet type arrived we should update our parent peer and send a Join packet to the
            new parent.

        Code design suggestion:
            1. Start the Reunion daemon thread when the first Advertise Response packet received.
            2. When an Advertise Response message arrived, make a new Join packet immediately for the advertised address.

        Warnings:
            1. Don't forget to ignore Advertise Request packets when you are a non-root peer.
            2. The addresses which still haven't registered to the network can not request any peer discovery message.
            3. Maybe it's not the first time that the source of the packet sends Advertise Request message. This will happen
               in rare situations like Reunion Failure. Pay attention, don't advertise the address to the packet sender
               sub-tree.
            4. When an Advertise Response packet arrived update our Peer parent for sending Reunion Packets.

        :param packet: Arrived register packet

        :type packet Packet

        :return:
        """
        if (packet.body[0:3] == 'RES') and (not self.is_root):
            self.children.clear()
            self.stream.remove_not_reg_nodes()
            self.parent = Node.parse_address(
                (packet.body[3:18], packet.body[18:23]))
            succ = self.stream.add_node(self.parent)
            if not succ:
                return
            join = PacketFactory.new_join_packet(self.address)
            self.stream.add_message_to_out_buff(self.parent, join)
            self.is_connected = True
            self.r_h_b_received = True
            self.since_last = 0
            # now we are connected
        elif (packet.body[0:3] == 'REQ') and (self.is_root):
            if not self.graph.is_registered(
                    packet.get_source_server_address()):
                return
            address = self.graph.find_live_node(
                packet.get_source_server_address()).get_address()
            if address is None:
                return
            self.graph.add_node(packet.sender_ip, packet.sender_port, address)
            res_pkt = PacketFactory.new_advertise_packet(
                'RES', self.address, address)
            self.stream.add_message_to_out_buff(
                packet.get_source_server_address(), res_pkt)
        pass
Example #3
0
    def find_node(self, ip, port):
        input = Node.parse_address((ip, port))
        for g_node in self.nodes:
            if (g_node.get_address()[0]
                    == input[0]) and (g_node.get_address()[1] == input[1]):
                return g_node
        for g_node in self.registered:
            if (g_node.get_address()[0]
                    == input[0]) and (g_node.get_address()[1] == input[1]):
                return g_node

        pass
Example #4
0
 def get_address(self):
     return Node.parse_address(self.address)
Example #5
0
    def __handle_advertise_packet(self, packet):
        """
        For advertising peers in the network, It is peer discovery message.

        Request:
            We should act as the root of the network and reply with a neighbour address in a new Advertise Response packet.

        Response:
            When an Advertise Response packet type arrived we should update our parent peer and send a Join packet to the
            new parent.

        Code design suggestion:
            1. Start the Reunion daemon thread when the first Advertise Response packet received.
            2. When an Advertise Response message arrived, make a new Join packet immediately for the advertised address.

        Warnings:
            1. Don't forget to ignore Advertise Request packets when you are a non-root peer.
            2. The addresses which still haven't registered to the network can not request any peer discovery message.
            3. Maybe it's not the first time that the source of the packet sends Advertise Request message. This will happen
               in rare situations like Reunion Failure. Pay attention, don't advertise the address to the packet sender
               sub-tree.
            4. When an Advertise Response packet arrived update our Peer parent for sending Reunion Packets.

        :param packet: Arrived advertise packet

        :type packet Packet

        :return:
        """
        body_str = packet.get_body()
        if self.is_root:
            if len(body_str) != 3 or body_str != Packet.BODY_REQ:
                return
            if not self.__check_registered(packet.get_source_server_address()):
                print(
                    'Peer that has sent request advertise has not registered before.'
                )
                return
            neighbour_address = self.__get_neighbour(
                packet.get_source_server_address())
            print('neighbour for', packet.get_source_server_address(), 'is',
                  neighbour_address)
            response_packet = self.packet_factory.new_advertise_packet(
                Packet.BODY_RES, packet.get_source_server_address(),
                Node.parse_address(neighbour_address))
            message = response_packet.get_buf()
            self.stream.add_message_to_out_buff(
                packet.get_source_server_address(),
                message,
                is_register_node=True)
            self.network_graph.add_node(packet.get_source_server_ip(),
                                        packet.get_source_server_port(),
                                        neighbour_address)
            self.network_graph.turn_on_node(packet.get_source_server_address())

            self.last_received_hello_times[
                packet.get_source_server_address()] = time.time()

        else:
            if len(body_str) != 23 or body_str[:3] != Packet.BODY_RES:
                return
            parent_ip = body_str[3:18]
            parent_port = body_str[18:23]
            self.parent_address = (parent_ip, parent_port)
            self.stream.add_node(self.parent_address)
            join_packet = self.packet_factory.new_join_packet(self.address)
            message = join_packet.get_buf()
            self.stream.add_message_to_out_buff(self.parent_address, message)

            self.waiting_for_hello_back = False
            if not self.reunion_daemon.is_alive():
                self.reunion_daemon.start()
Example #6
0
    def __init__(self,
                 server_ip,
                 server_port,
                 is_root=False,
                 root_address=None):
        """
        The Peer object constructor.

        Code design suggestions:
            1. Initialise a Stream object for our Peer.
            2. Initialise a PacketFactory object.
            3. Initialise our UserInterface for interaction with user commandline.
            4. Initialise a Thread for handling reunion daemon.

        Warnings:
            1. For root Peer, we need a NetworkGraph object.
            2. In root Peer, start reunion daemon as soon as possible.
            3. In client Peer, we need to connect to the root of the network, Don't forget to set this connection
               as a register_connection.


        :param server_ip: Server IP address for this Peer that should be pass to Stream.
        :param server_port: Server Port address for this Peer that should be pass to Stream.
        :param is_root: Specify that is this Peer root or not.
        :param root_address: Root IP/Port address if we are a client.

        :type server_ip: str
        :type server_port: int
        :type is_root: bool
        :type root_address: tuple
        """
        self.address = (Node.parse_ip(server_ip),
                        Node.parse_port(str(server_port)))
        self.root_address = None if root_address is None else Node.parse_address(
            root_address)
        self.stream = Stream(server_ip, server_port, root_address)
        self.packet_factory = PacketFactory()
        self.ui = UserInterface()
        self.ui.daemon = True
        self.is_root = is_root
        self.parent_address = None
        self.children = []

        self.network_graph = None
        self.registered_peers = None

        self.waiting_for_hello_back = False
        self.last_sent_hello_time = None
        self.reunion_daemon = threading.Thread(target=self.run_reunion_daemon)
        self.reunion_daemon.daemon = True

        if is_root:
            root_graph_node = GraphNode(self.address)
            root_graph_node.depth = 0
            self.network_graph = NetworkGraph(root_graph_node)
            self.registered_peers = dict()
            self.last_received_hello_times = dict()
            self.reunion_daemon.start()
        elif root_address is not None:
            self.stream.add_node(root_address, set_register_connection=True)

        self.start_user_interface()
        print('Peer initialized.')
Example #7
0
 def address_equal(self, address1, address2):
     address1 = Node.parse_address(address1)
     address2 = Node.parse_address(address2)
     return (address1[0] == address2[0]) and (address1[1] == address2[1])
Example #8
0
 def set_root_address(self, ip, port):
     self.root_address = Node.parse_address((ip, port))
     print(self.root_address)