def handle_write(self): # # Deal with the case where send() is blocked by recv(), that happens # when we are using SSL and recv() returned WANT_WRITE. In the common # case, this costs just one extra if in the fast path. # if self.send_blocked: logging.debug('stream: handle_write() => handle_read()') POLLER.set_readable(self) if not self.send_octets: POLLER.unset_writable(self) self.send_blocked = False self.handle_read() return status, count = self.sock.sosend(self.send_octets) # # Optimisation: reorder if branches such that the ones more relevant # for better performance come first. Testing in early 2011 showed that # this arrangement allows to gain a little more speed. (And the code # is still readable.) # if status == SUCCESS and count > 0: self.bytes_out += count if count == len(self.send_octets): POLLER.unset_writable(self) self.send_octets = EMPTY_STRING self.send_complete(self) return if count < len(self.send_octets): self.send_octets = six.buff(self.send_octets, count) return raise RuntimeError('stream: invalid count') if status == WANT_WRITE: return if status == WANT_READ: logging.debug('stream: blocking recv()') POLLER.unset_writable(self) POLLER.set_readable(self) self.recv_blocked = True return if status == CONNRST and count == 0: logging.debug('stream: RST') self.conn_rst = True POLLER.close(self) return if status == SUCCESS and count < 0: raise RuntimeError('stream: negative count') raise RuntimeError('stream: invalid status')
def __init__(self, parent, sock, endpoint): Pollable.__init__(self) self.parent = parent self.lsock = sock self.endpoint = endpoint # Want to listen "forever" self.watchdog = -1 POLLER.set_readable(self) self.parent.handle_listen(self)
def handshake(self): ''' Async SSL handshake ''' try: self.opaque.sock.sock.do_handshake() except ssl.SSLError: exception = sys.exc_info()[1] if exception.args[0] == ssl.SSL_ERROR_WANT_READ: POLLER.set_readable(self) elif exception.args[0] == ssl.SSL_ERROR_WANT_WRITE: POLLER.set_writable(self) else: raise else: stream = self.opaque self.opaque = None stream.atconnect.callback(stream)
def recv(self, recv_bytes, recv_complete): ''' Async recv() ''' if self.isclosed: raise RuntimeError('stream: recv() on a closed stream') if self.recv_bytes > 0: raise RuntimeError('stream: already recv()ing') if recv_bytes <= 0: raise RuntimeError('stream: invalid recv_bytes') self.recv_bytes = recv_bytes self.recv_complete = recv_complete if self.recv_blocked: logging.debug('stream: recv() is blocked') return POLLER.set_readable(self)