Esempio n. 1
0
 def test_data_received(self):
     with patch.object(MockClass, 'write', return_value=None) and\
             patch.object(MockClass, 'handle_message', return_value=Message()):
         remuprotocol = RemuProtocol()
         remuprotocol.transport = MockClass()
         tcp = RemuTCP(None, False, None, 8003)
         tcp.connection = MockClass()
         tcp.parent = MockClass()
         remuprotocol.factory = RemuProtocolFactory(tcp)
         remuprotocol.dataReceived(b'{"name": "test", "last": "case"}')
Esempio n. 2
0
 def connect_to_IP(self, address):
     """
     Attempts to create a new Networking-connection with the provided IP address
     """
     try:
         slave_address_parts = address.split(":")
         ip_address = slave_address_parts[0] if len(slave_address_parts) > 0 else None
         port = slave_address_parts[1] if len(slave_address_parts) > 1 else 8000
         ipaddress.ip_address(ip_address)
         self.full_address = ip_address + ":" + str(port)
         self.connection = RemuTCP(self, True, ip_address, int(port))
         self.connection.run()
         Logger.info("SlaveConnection: Slave added: %s", ip_address)
     except ValueError as e:
         self.connection = None
         Logger.error("SlaveConnection: Invalid IP-address or port. Error: \"%s\", str(e)")
Esempio n. 3
0
    def test_close_connections(self):
        with patch.object(RemuTCP, 'end_connection', return_value=None) as mock_method:
            connection_mock = RemuTCP(self.mock_master, True, "")
            slave_connection_mock = SlaveConnection(self.mock_master)
            slave_connection_mock.set_connection(connection_mock)
            self.mock_master.add_slave_connection(slave_connection_mock)
            self.mock_master.close_TCP_connections()

        mock_method.assert_called_once_with()
Esempio n. 4
0
    def create_servicemode(self, layout, is_master):
        """
        Creates a new service object and sets it in the self.servicemode

        layout: the layout to bind with self.servicemode
        """
        if is_master:
            new_master = Master(layout)
            self.set_servicemode(new_master, True)
            empty_project = Project()

            # Uncomment to test
            # empty_project.create_test_presentation()
            new_master.setup_project(empty_project)
            new_master.load_project_to_gui()
        else:
            new_slave = Slave(layout)
            tcp_port = self.config.getint('tcp port')
            new_slave.set_master_connection(RemuTCP(new_slave, port=tcp_port))
            self.set_servicemode(new_slave, False)
Esempio n. 5
0
 def test_init_master(self):
     tcp = RemuTCP(None, True, "127.0.0.1", 8002)
     self.assertEqual("127.0.0.1", tcp.address)
     self.assertIsNone(tcp.listener)
Esempio n. 6
0
 def test_init_slave(self):
     tcp = RemuTCP(None, False, None, 8001)
     self.assertIsNone(tcp.address)
     tcp.stop_listening()
Esempio n. 7
0
class SlaveConnection:
    """
    A class to handle one master-slave connection
    """

    def __init__(self, master, slave_name=None, connection=None):
        """
        Constructor.

        Connection: a Networking object, if constructed beforehand
        """
        self.master = master
        self.set_connection(connection)
        self.presentation = None
        self.full_address = "localhost:8000"
        self.slave_name = slave_name
        self.connected = self.connection is not None
        self.currently_showing = -1

    def set_connection(self, connection):
        """
        Sets the connection to the slave
        """
        self.connection = connection

    def connect_to_IP(self, address):
        """
        Attempts to create a new Networking-connection with the provided IP address
        """
        try:
            slave_address_parts = address.split(":")
            ip_address = slave_address_parts[0] if len(slave_address_parts) > 0 else None
            port = slave_address_parts[1] if len(slave_address_parts) > 1 else 8000
            ipaddress.ip_address(ip_address)
            self.full_address = ip_address + ":" + str(port)
            self.connection = RemuTCP(self, True, ip_address, int(port))
            self.connection.run()
            Logger.info("SlaveConnection: Slave added: %s", ip_address)
        except ValueError as e:
            self.connection = None
            Logger.error("SlaveConnection: Invalid IP-address or port. Error: \"%s\", str(e)")

    def send_command(self, command, params=None):
        """
        Private function for sending commands
        """
        if self.connection:
            msg = Message()
            Logger.debug("SlaveConnection: %s", str(params))
            msg.set_field(MessageKeys.type_key, "command")
            msg.set_field(MessageKeys.command_key, command)
            msg.set_field(MessageKeys.params_key, params)
            self.connection.send_message(msg)

    def show_next(self):
        """
        Ask slave to show next item in presentation
        """
        self.send_command(Command.SHOW_NEXT.value)

    def terminate_connection(self):
        """
        Ask slave to reset the presentation and closes the connection to it.
        """
        self.send_command(Command.DROP_CONNECTION.value)
        self.connection.end_connection() if self.connection else None
        self.master.notify(Notification.CONNECTION_TERMINATED, self)

    def set_presentation(self, presentation):
        """
        Sets the connection's presentation object
        """
        self.presentation = presentation

    def send_presentation(self, presentation_filenames):
        """
        Sends the given presentation's filenames to the slave that the SlaveConnection instance represents.
        :param presentation_filenames: List of the filenames contained in the presentation
        :return: Nothing
        """
        self.set_presentation(presentation_filenames)
        params = {}
        params[MessageKeys.presentation_content_key] = presentation_filenames

        self.send_command(Command.SEND_PRESENTATION.value, params)

    def end_presentation(self):
        """
        Ends the current presentation
        """
        self.send_command(Command.END_PRESENTATION.value)

    def retrieve_presentation_files(self, port, subpath):
        """
        Retrieves the actual presentation files from the master through an FTP connection
        :param port: FTP connection port
        :param subpath: Subpath to the default media path
        :return:
        """
        params = {MessageKeys.ftp_port_key: port,
                  MessageKeys.ftp_subpath_key: subpath,
                  MessageKeys.presentation_content_key: self.presentation.presentation_filenames}
        self.send_command(Command.RETRIEVE_FILES.value, params)

    def handle_show_next_response(self, response=None):
        """
        Handles command to show next file
        """
        self.presentation.index = response[MessageKeys.index_key]
        self.currently_showing = response[MessageKeys.index_key]
        self.master.notify(Notification.PRESENTATION_STATUS_CHANGE, self.currently_showing)

    def handle_ending_presentation(self, data=None):
        """
        Resets the presentation on master's side, called when slave is told to
        reset its presentation
        """
        self.currently_showing = -1

    def handle_invalid_command_response(self, data=None):
        """
        Invalid command handler, doesn't do anything useful except catch bad mistakes
        """
        Logger.error("SlaveConnection: Invalid command given")

    def handle_retrieve_files_response(self, fields):
        Logger.info("SlaveConnection: Slave %s retrieved files, yay!", fields["sender"])

    def connection_established(self, full_address):
        """
        Forwards the information of connection being established to master and its layout
        """
        self.connected = True
        self.master.notify(Notification.CONNECTION_ESTABLISHED, self.slave_name)

    handle_responses = {Command.SHOW_NEXT.value: handle_show_next_response,
                        Command.END_PRESENTATION.value: handle_ending_presentation,
                        Command.INVALID_COMMAND.value: handle_invalid_command_response,
                        Command.RETRIEVE_FILES.value: handle_retrieve_files_response
                        }

    def handle_message(self, msg):
        """
        Handles incoming messages
        """
        Logger.debug("SlaveConnection: Message received!")
        Logger.debug("SlaveConnection: Message content: \"%s\"", str(msg.fields))
        if MessageKeys.response_key in msg.fields:
            self.handle_responses[msg.get_response()](self, msg.fields)

    def on_connection_lost(self):
        """
        Called from RemuTCP when the connection is lost; used to notify GUI of the status
        """
        self.connected = False
        self.master.notify(Notification.CONNECTION_FAILED, self.slave_name)