def __init__(self): self.parser = MessageParser() self.queries = []
class KatCP(LineReceiver): """ A base class for protocol implementation of KatCP on top of twisted infrastructure. Specific subclasses provide client and server parts (which are not shared). """ delimiter = '\n' MAX_LENGTH = 64*(2**20) # 64 MB should be fine def __init__(self): self.parser = MessageParser() self.queries = [] def send_request(self, name, *args): if not self.transport.connected: raise DeviceNotConnected() d = Deferred() self.send_message(Message.request(name, *args)) self.queries.append((name, d, [])) return d def dataReceived(self, data): # translate '\r' into '\n' return LineReceiver.dataReceived(self, data.replace('\r', '\n')) def lineReceived(self, line): if not line: return msg = self.parser.parse(line) if msg.mtype == msg.INFORM: self.handle_inform(msg) elif msg.mtype == msg.REPLY: self.handle_reply(msg) elif msg.mtype == msg.REQUEST: self.handle_request(msg) else: assert False # this could never happen since parser should complain # some default informs def inform_version(self, msg): if msg.arguments: self.version = msg.arguments[0] def inform_build_state(self, msg): if msg.arguments: self.build_state = msg.arguments[0] def inform_disconnect(self, args): pass # unnecessary, we have a callback on loseConnection def handle_inform(self, msg): # if we have a request being processed, store all the informs # in a list of stuff to process name = msg.name name = name.replace('-', '_') meth = getattr(self, 'inform_' + name, None) if meth is not None: meth(msg) elif self.queries: name, d, queue = self.queries[0] if name != msg.name: return # instead of raising WrongQueryOrder, we discard informs # that we don't know about queue.append(msg) # unespace? else: raise UnhandledMessage(msg) def handle_request(self, msg): name = msg.name name = name.replace('-', '_') try: rep_msg = getattr(self, 'request_' + name, self._request_unknown)(msg) if not isinstance(rep_msg, Message): raise ShouldReturnMessage('request_' + name + ' should return a' 'message or raise AsyncReply, instead' 'it returned %r' % rep_msg) self.send_message(rep_msg) except FailReply, fr: self.send_message(Message.reply(name, "fail", str(fr))) except AsyncReply: return