async def _rw_handler(self, reader, writer):
        """
        This gets called when a connection is established.

        """
        connection_info = writer.get_extra_info('peername')
        p_host = connection_info[0]
        p_port = connection_info[1]
        bl.info('Connection established from {}:{}'.format(
            p_host, p_port))

        self.new_file_task = self.loop.create_task(self.push_new_file(reader, writer))
        self.data_index_task = self.loop.create_task(self.get_data_and_index(reader, writer))

        try:

            await self.new_file_task
            await self.data_index_task

        except Exception as e:
            bl.error("Exception: {}".format(e))

        finally:
            bl.info('Connection terminated')
            writer.close()
Beispiel #2
0
    async def read_data(self, reader, writer):
        """
        Read data from the connection.

        NOTE: Do not forget to send an ACK or NACK after using this method.
        Otherwise the connection might hang up.

        await self.send_ack(writer)
        await self.send_nack(writer)

        """
        # wait until we have read something that is up to 1k (until the newline
        # comes)
        length_b = await reader.read(1024)

        if reader.at_eof():
            return

        try:
            # try and parse it as an int (expecting the length of the data)
            length = struct.unpack("L", length_b)[0]
        except Exception as e:
            # if something goes wrong send a nack and start anew
            await self.send_nack(writer)
            bl.error("An Exception occured: {}".format(e))
            raise
            return
        else:
            # otherwise send the ack
            await self.send_ack(writer)

        try:
            # try and read exactly the length of the data
            data = await reader.readexactly(length)
            res = data.decode("UTF-8")
            res = json.loads(res)
        except json.decoder.JSONDecodeError:
            # if we can not parse the json send a nack and start from the
            # beginning
            bl.debug("Parsing {} as json failed".format(res))
            await self.send_nack(writer)
            raise
        except Exception as e:
            # if ANYTHING else goes wrong send a nack and start from the
            # beginning
            await self.send_nack(writer)
            bl.error("An Exception occured: {}".format(e))
            raise
        else:
            # otherwise return the received data
            return res
Beispiel #3
0
    async def check_ack(self, reader):
        """
        Check for ack or nack.

        Returns True (ACK) or False (NACK).

        """
        ck = await reader.read(8)
        try:
            ck = ck.decode("UTF-8")
        except Exception as e:
            bl.error("An Exception occured: {}".format(e))
            raise
        else:
            if ck.lower() == "ack":
                return True
        return False
Beispiel #4
0
    async def _rw_handler(self, reader, writer):
        """
        This gets called when a connection is established.

        """
        connection_info = writer.get_extra_info('peername')
        p_host = connection_info[0]
        p_port = connection_info[1]

        bl.info("Connection open from {}/{}".format(p_host, p_port))

        # perform a handshake with the new connection
        task_dict = await self.read_data(reader, writer)
        if not task_dict:
            await self.send_nack(writer)
            return
        await self.send_ack(writer)
        task = task_dict["task"]

        bl.info("Connection from port {} is tasked with {}".format(
            p_port, task))

        try:

            # watch the connection
            self.connection_active_task = self._loop.create_task(
                self._connection_active_coro(reader, writer))

            # depending on the task that is to be performed this creates on of
            # four tasks
            #
            # push information about new files to the client
            if task == "new_file_message":
                self._new_file_connection_active = True

                self.send_new_files_task = self._loop.create_task(
                    self._new_file_information_coro(reader, writer))

                await self.send_new_files_task

                # watch the connection
                conn_active = await self.connection_active_task
                if not conn_active:
                    bl.info("Connection to {}/{} lost".format(p_host, p_port))
                    bl.debug("Cancelling send_new_files_task")
                    self.send_new_files_task.cancel()

                self._new_file_connection_active = False

            # manage requests for the complete index from the client
            if task == "index":
                self._index_connection_active = True
                self.get_index_task = self._loop.create_task(
                    self._index_request_coro(reader, writer))

                await self.get_index_task

                # watch the connection
                conn_active = await self.connection_active_task
                if not conn_active:
                    bl.info("Connection to {}/{} lost".format(p_host, p_port))
                    bl.debug("Cancelling get_index_task")
                    self.get_index_task.cancel()

                self._index_connection_active = False

            # manage requests for file data from the ceph cluster
            if task == "file_download":

                self.file_download_task = self._loop.create_task(
                    self._file_download_coro(reader, writer))
                # optional?
                await self.file_download_task

        except Exception as e:
            bl.error("Exception: {}".format(e))
            raise

        finally:
            writer.close()