Beispiel #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
Beispiel #2
0
    def new_reunion_packet(type, source_address, nodes_array):
        """
        :param type: Reunion Hello (REQ) or Reunion Hello Back (RES)
        :param source_address: IP/Port address of the packet sender.
        :param nodes_array: [(ip0, port0), (ip1, port1), ...] It is the path to the 'destination'.

        :type type: str
        :type source_address: tuple
        :type nodes_array: list

        :return New reunion packet.
        :rtype Packet
        """

        body = ""
        body += type
        body += str(len(nodes_array)).zfill(2)
        if type == "REQ":
            for i in range(len(nodes_array)):
                body += Node.parse_ip(nodes_array[i][0])
                body += Node.parse_port(nodes_array[i][1])
        else:
            for i in range(len(nodes_array) - 1, -1, -1):
                body += Node.parse_ip(nodes_array[i][0])
                body += Node.parse_port(nodes_array[i][1])
        return Packet(None, PacketFactory.version, Type.reunion,
                      source_address[0], source_address[1], body)
Beispiel #3
0
    def __init__(self, ip, port):
        """
		The Stream object constructor.

		Code design suggestion:
			1. Make a separate Thread for your TCPServer and start immediately.


		:param ip: 15 characters
		:param port: 5 characters
		"""

        ip = Node.parse_ip(ip)
        port = Node.parse_port(port)
        self.nodes = {}

        self._server_in_buf = []

        def callback(address, queue, data):
            """
			The callback function will run when a new data received from server_buffer.

			:param address: Source address.
			:param queue: Response queue.
			:param data: The data received from the socket.
			:return:
			"""
            queue.put(bytes('ACK', 'utf8'))
            self._server_in_buf.append(data)

        self.tcp_server = TCPServer(ip, int(port), read_callback=callback)
        t = threading.Thread(target=self.tcp_server.run)
        t.start()
Beispiel #4
0
    def __init__(self, ip, port):
        """
        The Stream object constructor.

        Code design suggestion:
            1. Make a separate Thread for your TCPServer and start immediately.


        :param ip: 15 characters
        :param port: 5 characters
        """

        ip = Node.parse_ip(ip)
        port = Node.parse_port(port)

        self._server_in_buf = []

        def cb(ip, queue, data):
            queue.put(bytes('ACK', 'utf8'))
            # self.messages_dic.update({ip: self.messages_dic.get(ip).append(data)})
            self._server_in_buf.append(data)

        print("Binding server: ", ip, ": ", port)
        self._server = TCPServer(ip, int(port), cb)
        tcpserver_thread = threading.Thread(target=self._server.run)
        # self._server.run()
        tcpserver_thread.start()
        self.nodes = []
        self.ip = ip
        self.port = port
Beispiel #5
0
    def get_server_address(self):
        """

        :return: Our TCPServer address
        :rtype: tuple
        """
        return Node.parse_ip(self._server.ip), Node.parse_port(
            self._server.port)
Beispiel #6
0
 def parse_reunion_packet_body(body):
     body = str(body)
     numEntry = int(body[3:5])
     body = body[5:]
     result = []
     for i in range(0, numEntry):
         result.append((Node.parse_ip(body[20 * i:20 * i + 15]),
                        Node.parse_port(body[20 * i + 15:20 * i + 20])))
     return result
Beispiel #7
0
    def __init__(self, server_ip, server_port, is_root, ui, 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
        """
        super().__init__()
        self.ui_buffer = queue.Queue()
        self.stream = Stream(server_ip, server_port, ui)
        self.ip = Node.parse_ip(server_ip)
        self.port = Node.parse_port(str(server_port))

        self.address = (self.ip, int(self.port))
        self.setDaemon(True)
        self.ui = ui
        self.is_root = is_root
        self.root_address = self.address
        if not is_root:
            self.root_address = root_address
        self.children = []
        self.is_reunion_running = False
        self.parent = None
        self.is_connected = False
        # self.reunion_timer = ReunionTimer(self)
        self.graph = NetworkGraph(GraphNode(self.root_address))
        if not self.is_root:
            print('making the shit')
            self.stream.add_node(self.root_address, True)

        self.r_h_b_received = True
        self.since_last = 0
        self.timer = Timer(self)
        self.timer.start()
        self.stop = False
Beispiel #8
0
 def make_header(source_address, type, length):
     port = Node.parse_port(source_address[1])
     ip = Node.parse_ip(source_address[0])
     ip = ip.split('.')
     result = bytes([0])
     result = result + bytes([1])
     result = result + type.to_bytes(2, byteorder='big')
     result = result + length.to_bytes(4, byteorder='big')
     for a in ip:
         result = result + int(a).to_bytes(2, byteorder='big')
     result = result + int(port).to_bytes(4, byteorder='big')
     return result
     pass
Beispiel #9
0
    def __check_registered(self, source_address):
        """
        If the Peer is the root of the network we need to find that is a node registered or not.

        :param source_address: Unknown IP/Port address.
        :type source_address: tuple

        :return:
        """
        if self.registered_peers is not None:
            if str(
                (Node.parse_ip(source_address[0]),
                 Node.parse_port(source_address[1]))) in self.registered_peers:
                return True
            return False
    def send_messages_to_node(self, node: Node):
        """
        Send buffered messages to the 'node'

        Warnings:
            1. Insert an exception handler here; Maybe the node socket you want to send the message has turned off and
            you need to remove this node from stream nodes.

        :param node:
        :type node Node

        :return:
        """
        try:
            node.send_message()
        except:
            self.remove_node(node)
Beispiel #11
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
    def remove_node(self, node: Node):
        """
        Remove the node from our Stream.

        Warnings:
            1. Close the node after deletion.

        :param node: The node we want to remove.
        :type node: Node

        :return:
        """
        try:
            log(f"Something happened to Node({node.get_server_address()}).\n\tI'm Going to kill him. Right NOW!"
                )
            self.nodes.remove(node)
            node.close()
        except:
            return
Beispiel #13
0
    def new_reunion_packet(type, source_address, nodes_array):
        """
        :param type: Reunion Hello (REQ) or Reunion Hello Back (RES)
        :param source_address: IP/Port address of the packet sender.
        :param nodes_array: [(ip0, port0), (ip1, port1), ...] It is the path to the 'destination'.

        :type type: str
        :type source_address: tuple
        :type nodes_array: list

        :return New reunion packet.
        :rtype Packet
        """
        body = bytes(type, 'UTF-8') + bytes(str(len(nodes_array)),
                                            'UTF-8').zfill(2)
        for node in nodes_array:
            body += bytes(Node.parse_ip(node[0]), 'UTF-8') + bytes(
                Node.parse_port(node[1]), 'UTF-8')
        return PacketFactory.make_header(source_address, 5, len(body)) + body
        pass
Beispiel #14
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
        """
        port = Node.parse_port(port)
        ip = Node.parse_ip(ip)
        for nd in self.nodes:
            if nd.get_server_address()[0] == ip and nd.get_server_address(
            )[1] == port:
                return nd
Beispiel #15
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
        """
        try:
            return self.nodes[str((Node.parse_ip(ip), Node.parse_port(port)))]
        except KeyError:
            print('get node by server, could not find node')

        return None
Beispiel #16
0
    def __init__(self, ip, port, ui):
        """
        The Stream object constructor.

        Code design suggestion:
            1. Make a separate Thread for your TCPServer and start immediately.


        :param ip: 15 characters
        :param port: 5 characters

        """
        self.ip = Node.parse_ip(ip)
        self.port = int(Node.parse_port(port))
        self.server = TCPServer(self.ip, self.port, self.callback, 1000, 2048)
        self.server.start()
        self._server_in_buf = []
        self.nodes = []
        self.out_buffer = []
        self.ui = ui
Beispiel #17
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
        """
        ip = Node.parse_ip(ip)
        port = Node.parse_port(port)
        for node in self.nodes_list:
            if node.server_ip == ip and node.server_port == port:
                return node
        return None
Beispiel #18
0
    def add_node(self, server_address, set_register_connection=False):
        """
        Will add new a node to our Stream.

        :param server_address: New node TCPServer address.
        :param set_register_connection: Shows that is this connection a register_connection or not.

        :type server_address: tuple
        :type set_register_connection: bool

        :return:
        """
        try:
            self.nodes.append(Node((Node.parse_ip(server_address[0]), int(Node.parse_port(server_address[1]))), False,
                               set_register_connection))
            return True
        except:
            self.ui.display_message('Could not Establish Connection!')
            return False
        pass
    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
Beispiel #20
0
    def __init__(self, server_ip, server_port, is_root=False, root_address=None, gui=False, interface=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.has_gui = gui

        self.ip = Node.parse_ip(server_ip)
        self.port = server_port
        self.stream = Stream(server_ip, server_port)
        self.packet_factory = PacketFactory()

        self.interface = interface
        self.parse_interface_thread = threading.Thread(target=self.handle_user_interface_buffer, daemon=True)

        self.is_root = is_root
        self.root_address = root_address
        self.reunion_daemon = threading.Thread(target=self.run_reunion_daemon, daemon=True)
        if is_root:
            root_node = GraphNode((server_ip, server_port))
            self.network_graph = NetworkGraph(root_node)

        if not is_root:
            try:
                self.stream.add_node(root_address, True)
            except LostConnection as lc:
                print("Couldn't connect to root")
            self.father_address = None
            self.send_reunion_timer = 4
            self.last_reunion_back = 0
            self.is_alive = False
Beispiel #21
0
    def new_advertise_packet(type, source_server_address, neighbour=None):
        """
        :param type: Type of Advertise packet
        :param source_server_address Server address of the packet sender.
        :param neighbour: The neighbour for advertise response packet; The format is like ('192.168.001.001', '05335').

        :type type: str
        :type source_server_address: tuple
        :type neighbour: tuple

        :return New advertise packet.
        :rtype Packet

        """
        body = ""
        body += type
        if type == "RES":
            body += Node.parse_ip(neighbour[0])
            body += Node.parse_port(neighbour[1])
        return Packet(None, PacketFactory.version, Type.advertise,
                      source_server_address[0], source_server_address[1], body)
Beispiel #22
0
    def __init__(self, ip, port):
        """
        The Stream object constructor.

        Code design suggestion:
            1. Make a separate Thread for your TCPServer and start immediately.


        :param ip: 15 characters
        :param port: 5 characters
        """

        self.ip = Node.parse_ip(ip)
        self.port = Node.parse_port(port)

        self._server_in_buf = []

        self.nodes = []
        self.nodes_parent_index = 1

        def callback(address, queue, data):
            """
            The callback function will run when a new data received from server_buffer.

            :param address: Source address.
            :param queue: Response queue.
            :param data: The data received from the socket.
            :return:
            """
            # print(data)
            queue.put(bytes('ACK', 'utf8'))
            self._server_in_buf.append(data)
            # print(self._server_in_buf)

        tcp_server = TCPServer(self.ip, port, callback)

        # creating thread
        t1 = threading.Thread(target=tcp_server.run)
        # starting thread 2
        t1.start()
Beispiel #23
0
    def add_node(self, server_address, set_register_connection=False):
        """
        Will add new a node to our Stream.

        :param server_address: New node TCPServer address.
        :param set_register_connection: Shows that is this connection a register_connection or not.

        :type server_address: tuple
        :type set_register_connection: bool

        :return:
        """
        self.nodes.append(Node(server_address, set_register_connection))
Beispiel #24
0
    def new_register_packet(type, source_server_address, address=(None, None)):
        """
        :param type: Type of Register packet
        :param source_server_address: Server address of the packet sender.
        :param address: If 'type' is 'request' we need an address; The format is like ('192.168.001.001', '05335').

        :type type: str
        :type source_server_address: tuple
        :type address: tuple

        :return New Register packet.
        :rtype Packet

        """
        body = ""
        body += type
        if type == "REQ":
            body += Node.parse_ip(address[0])
            body += Node.parse_port(address[1])
        else:
            body += "ACK"
        return Packet(None, PacketFactory.version, Type.register,
                      source_server_address[0], source_server_address[1], body)
Beispiel #25
0
    def __init__(self, ip, port):
        """
        The Stream object constructor.

        Code design suggestion:
            1. Make a separate Thread for your TCPServer and start immediately.



        :param ip: 15 characters
        :param port: 5 characters
        """
        def callback(address, queue, data):
            """
            The callback function will run when a new data received from server_buffer.

            :param address: Source address.
            :param queue: Response queue.
            :param data: The data received from the socket.
            :return:
            """
            queue.put(bytes('ACK', 'utf8'))
            self._server_in_buf.append(data)

        ip = Node.parse_ip(ip)
        port = Node.parse_port(port)
        self._server_in_buf = []
        self.parent_node_address = (None, None)
        self.nodes: List[Node] = []
        self.server = TCPServer(ip,
                                port,
                                callback,
                                maximum_connections=256,
                                receive_bytes=2048)
        threading.Thread(target=self.server.run).start()
        # todo: problem!. update:I think it's solved!
        pass
Beispiel #26
0
    def add_message_to_out_buff(self, address, message, is_register_node=False):
        """
        In this function, we will add the message to the output buffer of the node that has the input address.
        Later we should use send_out_buf_messages to send these buffers into their sockets.

        :param is_register_node:
        :param address: Node address that we want to send the message
        :param message: Message we want to send

        Warnings:
            1. Check whether the node address is in our nodes or not.

        :return:
        """

        if is_register_node:
            if self.is_root:
                node = self.root_register_nodes[str(address)]
                node.add_message_to_out_buff(message)
            else:
                self.register_node.add_message_to_out_buff(message)
        else:
            node = self.nodes[str((Node.parse_ip(address[0]), Node.parse_port(address[1])))]
            node.add_message_to_out_buff(message)
Beispiel #27
0
    def add_node(self, server_address, set_register_connection=False):
        """
        Will add new a node to our Stream.

        :param server_address: New node TCPServer address.
        :param set_register_connection: Shows that is this connection a register_connection or not.

        :type server_address: tuple
        :type set_register_connection: bool

        :return:
        """

        new_node = Node(server_address, set_register=set_register_connection)

        if set_register_connection:
            if self.is_root:
                self.root_register_nodes[str(new_node.get_server_address())] = new_node
            else:
                print('register node set')
                self.register_node = new_node
            return

        self.nodes[str((new_node.server_ip, new_node.server_port))] = new_node
Beispiel #28
0
    def new_register_packet(kind, source_server_address, address=(None, None)):
        """
        :param kind: Type of Register packet
        :param source_server_address: Server address of the packet sender.
        :param address: If 'type' is 'request' we need an address; The format is like ('192.168.001.001', '05335').

        :type kind: str
        :type source_server_address: tuple
        :type address: tuple

        :return New Register packet.
        :rtype Packet

        """
        if kind == 'REQ':
            body = bytes('REQ', 'UTF-8') + bytes(
                Node.parse_ip(source_server_address[0]), 'UTF-8') + bytes(
                    str(Node.parse_port(source_server_address[1])), 'UTF-8')
            return PacketFactory.make_header(source_server_address, 1,
                                             len(body)) + body
        else:
            body = bytes('RES ACK', 'UTF-8')
            return PacketFactory.make_header(source_server_address, 1,
                                             len(body)) + body
Beispiel #29
0
    def add_node(self, server_address, set_register_connection=False):
        """
        Will add new node to our Stream.

        :param server_address: New node TCPServer address
        :param set_register_connection: Shows that is this connection a register_connection or not.

        :type server_address: tuple
        :type set_register_connection: bool

        :return:
        """
        print("Trying to connect to this address: ", server_address)
        node = Node(server_address, set_register=set_register_connection)

        self.nodes.append(node)
Beispiel #30
0
    def add_node(self, server_address, set_register_connection=False):
        """
		Will add new a node to our Stream.

		:param server_address: New node TCPServer address.
		:param set_register_connection: Shows that is this connection a register_connection or not.

		:type server_address: tuple
		:type set_register_connection: bool

		:return:
		"""
        try:
            self.nodes[server_address] = Node(
                server_address, set_register=set_register_connection)
            return self.nodes[server_address]
        except:
            return None