@loop(fin='stop', exit_exceptions=(socket.error, ))
    def read(self):
        if self._disconnected:
            self.logger.info("Agent client {} write loop exited, exiting read loop"
                             .format(self._id))
            return

        line = with_timeout(self.config['agent']['timeout'],
                            self.fp.readline,
                            timeout_value='timeout')

        # push a new job every timeout seconds if requested
        if line == 'timeout':
            raise LoopExit("Agent client timeout")

        line = line.strip()

        # Reading from a defunct connection yeilds an EOF character which gets
        # stripped off
        if not line:
            raise LoopExit("Closed file descriptor encountered")

        try:
            data = json.loads(line)
        except ValueError:
            self.logger.info("Data {} not JSON".format(line))
            self.send_error()
            return

        self.logger.debug("Data {} recieved on client {}".format(data, self._id))

        if 'method' not in data:
            self.logger.info("Unkown action for command {}".format(data))
            self.send_error()

        meth = data['method'].lower()
        if meth == 'hello':
            if self._client_version is not None:
                self.send_error(32)
                return
            self._client_version = data.get('params', [0.1])[0]
            self.logger.info("Agent {} identified as version {}"
                             .format(self._id, self._client_version))
        elif meth == 'worker.authenticate':
            if self._client_version is None:
                self.send_error(33)
                return
            username = data.get('params', [""])[0]
            user_worker = self.convert_username(username)
            # setup lookup table for easier access from other read sources
            self.client_state = self.server.address_worker_lut.get(user_worker)
            if not self.client_state:
                self.send_error(31)
                return

            # here's where we do some top security checking...
            self._authed[username] = user_worker
            self.send_success()
            self.logger.info("Agent {} authenticated worker {}"
                             .format(self._id, username))
        elif meth == "stats.submit":
            if self._client_version is None:
                self.send_error(33)
                return

            if data.get('params', [''])[0] not in self._authed:
                self.send_error(34)
                return

            if 'params' not in data and len(data['params']) != 4:
                self.send_error(36)
                return

            user_worker, typ, data, stamp = data['params']
            # lookup our authed usernames translated creds
            address, worker = self._authed[user_worker]
            if typ in self.config['agent']['accepted_types']:
                self.reporter.agent_send(address, worker, typ, data, stamp)
                self.send_success()
                self.logger.info("Agent {} transmitted payload for worker "
                                 "{}.{} of type {} and length {}"
                                 .format(self._id, address, worker, typ, len(line)))
            else:
                self.send_error(35)
dataset/ETHPy150Open simplecrypto/powerpool/powerpool/agent_server.py/AgentClient.read/operator `or` -> `and`