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()
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
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
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()