qmsk/net/transport/stream.py
author Tero Marttila <terom@fixme.fi>
Sat, 26 Sep 2009 16:39:20 +0300
changeset 50 da394bb715af
parent 28 020c89baaa33
permissions -rw-r--r--
try and keep lib.event2.event objects alive (via self-ref) while pending
"""
    Abstract byte-stream transport interface.
"""

from qmsk.net.transport import transport

class Stream (transport.Transport) :
    """
        A byte stream oriented transport.

        This provides a sequenced, reliable, full-duplex, connection-oriented byte stream.
    """

    def read (self, iov) :
        """
            Read and return up to `iov` bytes from this stream. This may return fewer bytes than requested.

            If the stream does not contain any more data (i.e. EOF), an empty string is returned.
        """

        raise NotImplementedError()

    def readv (self, iovecs) :
        """
            Attempt to read data into a sequence of iov's, returning a sequence of buffers with the read data.

            This may return fewer buffers than specified if there was not sufficient data to fill all buffers.

            By default, this is simply implemented using read(), but an implementation may also provide a more
            efficient version.
        """
        
        ret = []

        for iovec in iovecs :
            buf = self.read(iovec)

            if buf :
                ret.append(buf)

            else :
                # EOF! This should not be returned by readv!
                break
        
        return ret

    def write (self, buf) :
        """
            Attempt to write the given data to this stream, returning the number of bytes written, which may be less
            than the length of the buffer given.
        """

        raise NotImplementedError()

    def writev (self, iovecs) :
        """
            Attempt to write data from the given sequence of buffers to this stream, returning the total number of
            bytes written, which may be less than the total length of the buffers given.

            By default, this is simply implemented using write(), but an implementation may also provide a more
            efficient version.
        """

        ret = 0

        for buf in iovec :
            # send this buffer
            buf_len = self.write(buf)
            
            # count total bytes sent
            ret += buf_len

            if buf_len < len(buf) :
                # buffer was sent incompletely, do not try and send any more
                break
        
        return ret

    def close (eslf) :
        """
            Close this stream, disallowing any more read/write operations.

            This discards any unread data, but written data that has been buffered will still be sent.
        """

        raise NotImplementedError()

    def abort (self) :
        """
            Close this stream immediately, invalidating it for future use.

            This discards any unread data, and may discard written data that has been buffered and not yet sent. This
            should also ignore any close-related errors.

            By default, this is implemented using close(), but an implementation may also provide a more efficient
            version.

            XXX: remove default implementation?
        """
        
        # XXX: ignore close-related errors?
        self.close()