135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""
 | 
						|
SocketIO imported from socket module in Python 3.
 | 
						|
 | 
						|
Copyright (c) 2001-2013 Python Software Foundation; All Rights Reserved.
 | 
						|
"""
 | 
						|
 | 
						|
from socket import *
 | 
						|
import io
 | 
						|
import errno
 | 
						|
 | 
						|
__all__ = ['SocketIO']
 | 
						|
 | 
						|
EINTR = errno.EINTR
 | 
						|
_blocking_errnos = (errno.EAGAIN, errno.EWOULDBLOCK)
 | 
						|
 | 
						|
class SocketIO(io.RawIOBase):
 | 
						|
 | 
						|
    """Raw I/O implementation for stream sockets.
 | 
						|
 | 
						|
    This class supports the makefile() method on sockets.  It provides
 | 
						|
    the raw I/O interface on top of a socket object.
 | 
						|
    """
 | 
						|
 | 
						|
    # One might wonder why not let FileIO do the job instead.  There are two
 | 
						|
    # main reasons why FileIO is not adapted:
 | 
						|
    # - it wouldn't work under Windows (where you can't used read() and
 | 
						|
    #   write() on a socket handle)
 | 
						|
    # - it wouldn't work with socket timeouts (FileIO would ignore the
 | 
						|
    #   timeout and consider the socket non-blocking)
 | 
						|
 | 
						|
    # XXX More docs
 | 
						|
 | 
						|
    def __init__(self, sock, mode):
 | 
						|
        if mode not in ("r", "w", "rw", "rb", "wb", "rwb"):
 | 
						|
            raise ValueError("invalid mode: %r" % mode)
 | 
						|
        io.RawIOBase.__init__(self)
 | 
						|
        self._sock = sock
 | 
						|
        if "b" not in mode:
 | 
						|
            mode += "b"
 | 
						|
        self._mode = mode
 | 
						|
        self._reading = "r" in mode
 | 
						|
        self._writing = "w" in mode
 | 
						|
        self._timeout_occurred = False
 | 
						|
 | 
						|
    def readinto(self, b):
 | 
						|
        """Read up to len(b) bytes into the writable buffer *b* and return
 | 
						|
        the number of bytes read.  If the socket is non-blocking and no bytes
 | 
						|
        are available, None is returned.
 | 
						|
 | 
						|
        If *b* is non-empty, a 0 return value indicates that the connection
 | 
						|
        was shutdown at the other end.
 | 
						|
        """
 | 
						|
        self._checkClosed()
 | 
						|
        self._checkReadable()
 | 
						|
        if self._timeout_occurred:
 | 
						|
            raise IOError("cannot read from timed out object")
 | 
						|
        while True:
 | 
						|
            try:
 | 
						|
                return self._sock.recv_into(b)
 | 
						|
            except timeout:
 | 
						|
                self._timeout_occurred = True
 | 
						|
                raise
 | 
						|
            except error as e:
 | 
						|
                n = e.args[0]
 | 
						|
                if n == EINTR:
 | 
						|
                    continue
 | 
						|
                if n in _blocking_errnos:
 | 
						|
                    return None
 | 
						|
                raise
 | 
						|
 | 
						|
    def write(self, b):
 | 
						|
        """Write the given bytes or bytearray object *b* to the socket
 | 
						|
        and return the number of bytes written.  This can be less than
 | 
						|
        len(b) if not all data could be written.  If the socket is
 | 
						|
        non-blocking and no bytes could be written None is returned.
 | 
						|
        """
 | 
						|
        self._checkClosed()
 | 
						|
        self._checkWritable()
 | 
						|
        try:
 | 
						|
            return self._sock.send(b)
 | 
						|
        except error as e:
 | 
						|
            # XXX what about EINTR?
 | 
						|
            if e.args[0] in _blocking_errnos:
 | 
						|
                return None
 | 
						|
            raise
 | 
						|
 | 
						|
    def readable(self):
 | 
						|
        """True if the SocketIO is open for reading.
 | 
						|
        """
 | 
						|
        if self.closed:
 | 
						|
            raise ValueError("I/O operation on closed socket.")
 | 
						|
        return self._reading
 | 
						|
 | 
						|
    def writable(self):
 | 
						|
        """True if the SocketIO is open for writing.
 | 
						|
        """
 | 
						|
        if self.closed:
 | 
						|
            raise ValueError("I/O operation on closed socket.")
 | 
						|
        return self._writing
 | 
						|
 | 
						|
    def seekable(self):
 | 
						|
        """True if the SocketIO is open for seeking.
 | 
						|
        """
 | 
						|
        if self.closed:
 | 
						|
            raise ValueError("I/O operation on closed socket.")
 | 
						|
        return super().seekable()
 | 
						|
 | 
						|
    def fileno(self):
 | 
						|
        """Return the file descriptor of the underlying socket.
 | 
						|
        """
 | 
						|
        self._checkClosed()
 | 
						|
        return self._sock.fileno()
 | 
						|
 | 
						|
    @property
 | 
						|
    def name(self):
 | 
						|
        if not self.closed:
 | 
						|
            return self.fileno()
 | 
						|
        else:
 | 
						|
            return -1
 | 
						|
 | 
						|
    @property
 | 
						|
    def mode(self):
 | 
						|
        return self._mode
 | 
						|
 | 
						|
    def close(self):
 | 
						|
        """Close the SocketIO object.  This doesn't close the underlying
 | 
						|
        socket, except if all references to it have disappeared.
 | 
						|
        """
 | 
						|
        if self.closed:
 | 
						|
            return
 | 
						|
        io.RawIOBase.close(self)
 | 
						|
        self._sock._decref_socketios()
 | 
						|
        self._sock = None
 | 
						|
 |