예제 #1
0
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)
예제 #2
0
 def _reset(self):
     self.state = Protocol._STATE_IDLE
     self.headerBuf = Buffer()
     self.header = None
     self.msg = None
예제 #3
0
 def init(self, msgid):
     self.msgid = msgid
     self.finished = False
     self.buf = Buffer()
예제 #4
0
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
예제 #5
0
 def init(self, msgid):
     self.msgid = msgid
     self.finished = False
     self.buf = Buffer()
예제 #6
0
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