class Protocol(object): _STATE_IDLE = 0 _STATE_HEADER_MAGIC_0 = 1 _STATE_HEADER_MAGIC_1 = 2 _STATE_HEADER_MAGIC_2 = 3 _STATE_HEADER_MAGIC_3 = 4 _STATE_HEADER = 5 _STATE_PAYLOAD = 6 def __init__(self): self.state = Protocol._STATE_IDLE self.headerBuf = None self.header = None self.msg = None self.bufSrc = None self.offSrc = 0 self.lenSrc = 0 self._reset() def decode(self, buf, off): rxMsg = None # If idle start a new parsing if self.state == Protocol._STATE_IDLE: self.state = Protocol._STATE_HEADER_MAGIC_0 # Setup source buffer self.bufSrc = buf self.offSrc = off self.lenSrc = len(buf) - off while self.lenSrc > 0 and self.state != Protocol._STATE_IDLE: if self.state == Protocol._STATE_HEADER_MAGIC_0: self._reset() self.state = Protocol._STATE_HEADER_MAGIC_0 self._copyOne(self.headerBuf) self._checkMagic(0, POMP_MAGIC_0, Protocol._STATE_HEADER_MAGIC_1) elif self.state == Protocol._STATE_HEADER_MAGIC_1: self._copyOne(self.headerBuf) self._checkMagic(1, POMP_MAGIC_1, Protocol._STATE_HEADER_MAGIC_2) elif self.state == Protocol._STATE_HEADER_MAGIC_2: self._copyOne(self.headerBuf) self._checkMagic(2, POMP_MAGIC_2, Protocol._STATE_HEADER_MAGIC_3) elif self.state == Protocol._STATE_HEADER_MAGIC_3: self._copyOne(self.headerBuf) self._checkMagic(3, POMP_MAGIC_3, Protocol._STATE_HEADER) elif self.state == Protocol._STATE_HEADER: self._copy(self.headerBuf, HEADER_SIZE) if len(self.headerBuf) == HEADER_SIZE: self._decodeHeader() elif self.state == Protocol._STATE_PAYLOAD: self._copy(self.msg.buf, self.header.size) else: assert False # Check end of payload if (self.state == Protocol._STATE_PAYLOAD and len(self.msg.buf) == self.header.size): # Give ownership of message to caller self.msg.setFinished() rxMsg = self.msg self.msg = None self.state = Protocol._STATE_IDLE return (self.offSrc, rxMsg) def _reset(self): self.state = Protocol._STATE_IDLE self.headerBuf = Buffer() self.header = None self.msg = None def _checkMagic(self, idx, val, state): if isinstance(self.headerBuf.getData(), str): magic = ord(self.headerBuf.getData()[idx]) else: magic = self.headerBuf.getData()[idx] if magic != val: _log.warning("Bad header magic %d: 0x%02x(0x%02x)", idx, magic, val) self.state = Protocol._STATE_HEADER_MAGIC_0 else: self.state = state def _copyOne(self, bufDst): bufDst.write(self.bufSrc[self.offSrc:self.offSrc+1]) self.offSrc += 1 self.lenSrc -= 1 def _copy(self, bufDst, sizeDst): cpyLen = min(self.lenSrc, sizeDst - len(bufDst)) bufDst.write(self.bufSrc[self.offSrc:self.offSrc+cpyLen]) self.offSrc += cpyLen self.lenSrc -= cpyLen def _decodeHeader(self): try: # Decode header fields self.headerBuf.rewind() magic = self.headerBuf.readInt() msgid = self.headerBuf.readInt() size = self.headerBuf.readInt() self.header = Header(magic, msgid, size) # Check header and setup payload decoding */ if self.header.size < HEADER_SIZE: _log.warning("Bad header size: %d", self.header.size) self.state = Protocol._STATE_HEADER_MAGIC_0 else: self._allocMsg(self.header.msgid, self.header.size) self.msg.buf.write(self.headerBuf.getData()) self.state = Protocol._STATE_PAYLOAD except struct.error as ex: _log.error(ex) self.state = Protocol._STATE_HEADER_MAGIC_0 def _allocMsg(self, msgid, size): from pomp.message import Message self.msg = Message() self.msg.init(msgid)
def _reset(self): self.state = Protocol._STATE_IDLE self.headerBuf = Buffer() self.header = None self.msg = None
def init(self, msgid): self.msgid = msgid self.finished = False self.buf = Buffer()
class Message(object): def __init__(self): self.msgid = 0 # Id of message self.finished = False # Header is filled self.buf = None # Buffer with data def init(self, msgid): self.msgid = msgid self.finished = False self.buf = Buffer() def finish(self): # Make sure position is at least after header if self.buf.getPos() < protocol.HEADER_SIZE: self.buf.skip(protocol.HEADER_SIZE - self.buf.getPos()) # Write header self.buf.rewind() self.buf.writeInt(protocol.POMP_MAGIC) self.buf.writeInt(self.msgid) self.buf.writeInt(len(self.buf)) # Make message read-only self.finished = True self.buf.setReadOnly(True) def setFinished(self): self.finished = True self.buf.setReadOnly(True) def clear(self): self.msgid = 0 self.finished = False self.buf = None def write(self, msgid, fmt, *args): self.init(msgid) enc = Encoder() enc.init(self) enc.write(fmt, *args) enc.clear() self.finish() def read(self, fmt): dec = Decoder() dec.init(self) res = dec.read(fmt) dec.clear() return res def dump(self): dec = Decoder() dec.init(self) res = dec.dump() dec.clear() return res