DatagramService.py 1.92 KB
"""
Associate a physical transport layer with a protocol.

Author: Georg Hopp <ghopp@spamtitan.com>
"""
from collections import deque

from EndPoint import CommunicationEndPoint
from Transport import Transport

class DatagramService(CommunicationEndPoint):
    _EVENTS = {}

    def __init__(self, transport, protocol, read_chunk_size=8192):
        super(DatagramService, self).__init__(
            transport, protocol, read_chunk_size)
        self._read_buffer     = deque([])
        self._write_buffer    = deque([])
        self._transport.open()

    def hasPendingData(self):
        return self._write_buffer

    def __iter__(self):
        return self

    def next(self):
        """
        here a message has to be fit into a single packet, so no multiple
        reads are done.. if a message was not complete after a read the
        data will be dropped silently because it can't be guaranteed
        that we got the rest somehow in the correct order.
        """
        if not self._read_buffer:
            raise StopIteration

        msginfo = self._read_buffer.popleft()
        message = self._protocol.createMessage(msginfo[1])
        if not message:
            raise StopIteration
                
        end = self._protocol.getParser().parse(message, msginfo[0])
        if 0 == end: raise StopIteration

        return message

    def compose(self, message):
        try:
            data = self._protocol.getComposer().compose(message)
            self.appendWriteData((data, message.getRemote()))
        except Exception:
            return False

        return True

    def appendReadData(self, data_remote):
        self._read_buffer.append(data_remote)

    def nextWriteData(self):
        if not self._write_buffer:
            return ('', None)

        return self._write_buffer.popleft()

    def appendWriteData(self, data_remote):
        self._write_buffer.append(data_remote)

# vim: set ft=python et ts=8 sw=4 sts=4: