class SocketTransport(object): """Provides network I/O for a Proton Transport via a socket. """ def __init__(self, socket, name=None): """socket - Python socket. Expected to be configured and connected. name - optional name for this SocketTransport """ self._name = name self._socket = socket self._transport = Transport() self._read_done = False self._write_done = False self._next_tick = 0 def fileno(self): """Allows use of a SocketTransport by the select module. """ return self._socket.fileno() @property def transport(self): return self._transport @property def socket(self): return self._socket @property def name(self): return self._name def tick(self, now): """Invoke the transport's tick method. 'now' is seconds since Epoch. Returns the timestamp for the next tick, or zero if no next tick. """ self._next_tick = self._transport.tick(now) return self._next_tick @property def next_tick(self): """Timestamp for next call to tick() """ return self._next_tick @property def need_read(self): """True when the Transport requires data from the network layer. """ return (not self._read_done) and self._transport.capacity() > 0 @property def need_write(self): """True when the Transport has data to write to the network layer. """ return (not self._write_done) and self._transport.pending() > 0 def read_input(self): """Read from the network layer and processes all data read. Can support both blocking and non-blocking sockets. """ if self._read_done: return None c = self._transport.capacity() if c < 0: try: self._socket.shutdown(socket.SHUT_RD) except: pass self._read_done = True return None if c > 0: try: buf = self._socket.recv(c) if buf: self._transport.push(buf) return len(buf) # else socket closed self._transport.close_tail() self._read_done = True return None except socket.timeout, e: raise # let the caller handle this except socket.error, e: err = e.args[0] if err != errno.EAGAIN and err != errno.EWOULDBLOCK and err != errno.EINTR: # otherwise, unrecoverable: self._transport.close_tail() self._read_done = True raise except: # beats me...