class SslHandshakingTransport(BaseSocketTransport): __slots__ = ["connected_dfr"] def __init__(self, reactor, sslsock): BaseSocketTransport.__init__(self, reactor, sslsock) self.connected_dfr = ReactorDeferred(self.reactor) def handshake(self): if not self.connected_dfr.is_set(): self._handshake() return self.connected_dfr def _handshake(self): try: self.sock.do_handshake() except ssl.SSLError as ex: if ex.errno == ssl.SSL_ERROR_WANT_READ: self.reactor.register_read(self) elif ex.errno == ssl.SSL_ERROR_WANT_WRITE: self.reactor.register_write(self) else: self.connected_dfr.throw(ex) else: sock = self.sock self.detach() trns = SslStreamTransport(self.reactor, sock) self.connected_dfr.set(trns) def on_read(self): self.reactor.unregister_read(self) self._handshake() def on_write(self): self.reactor.unregister_write(self) self._handshake()
class SslHandshakingTransport(BaseSocketTransport): __slots__ = ["connected_dfr"] def __init__(self, reactor, sslsock): BaseSocketTransport.__init__(self, reactor, sslsock) self.connected_dfr = ReactorDeferred(self.reactor) def handshake(self): if not self.connected_dfr.is_set(): self._handshake() return self.connected_dfr def _handshake(self): try: self.sock.do_handshake() except ssl.SSLError as ex: if ex.errno == ssl.SSL_ERROR_WANT_READ: self.reactor.register_read(self) elif ex.errno == ssl.SSL_ERROR_WANT_WRITE: self.reactor.register_write(self) else: self.connected_dfr.throw(ex) else: sock = self.sock self.detach() trns = SslStreamTransport(self.reactor, sock) self.connected_dfr.set(trns) def on_read(self): self.reactor.unregister_read(self) self._handshake() def on_write(self): self.reactor.unregister_write(self) self._handshake()
class ConnectingSocketTransport(BaseSocketTransport): __slots__ = ["addr", "connected_dfr", "_connecting"] def __init__(self, reactor, sock, addr): BaseSocketTransport.__init__(self, reactor, sock) self.addr = addr self.connected_dfr = ReactorDeferred(self.reactor) self._connecting = False def connect(self, timeout=None): if self._connecting: raise OverlappingRequestError("already connecting") self._connecting = True if timeout is not None: self.reactor.jobs.schedule(timeout, self._cancel) self.reactor.register_write(self) self._attempt_connect() return self.connected_dfr def on_write(self): self._attempt_connect() def _attempt_connect(self): if self.connected_dfr.is_set(): self.detach() return err = self.sock.connect_ex(self.addr) if err in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): return if err == errno.EINVAL and sys.platform == "win32": return sock = self.sock self.detach() if err in (0, errno.EISCONN): self.connected_dfr.set(SocketStreamTransport(self.reactor, sock)) else: self.connected_dfr.throw(socket.error(err, errno.errorcode[err])) def _cancel(self): if self.connected_dfr.is_set(): return self.close() self.connected_dfr.throw(socket.timeout("connection timed out"))
class ConnectingSocketTransport(BaseSocketTransport): __slots__ = ["addr", "connected_dfr", "_connecting"] def __init__(self, reactor, sock, addr): BaseSocketTransport.__init__(self, reactor, sock) self.addr = addr self.connected_dfr = ReactorDeferred(self.reactor) self._connecting = False def connect(self, timeout = None): if self._connecting: raise OverlappingRequestError("already connecting") self._connecting = True if timeout is not None: self.reactor.jobs.schedule(timeout, self._cancel) self.reactor.register_write(self) self._attempt_connect() return self.connected_dfr def on_write(self): self._attempt_connect() def _attempt_connect(self): if self.connected_dfr.is_set(): self.detach() return err = self.sock.connect_ex(self.addr) if err in (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK): return if err == errno.EINVAL and sys.platform == "win32": return sock = self.sock self.detach() if err in (0, errno.EISCONN): self.connected_dfr.set(SocketStreamTransport(self.reactor, sock)) else: self.connected_dfr.throw(socket.error(err, errno.errorcode[err])) def _cancel(self): if self.connected_dfr.is_set(): return self.close() self.connected_dfr.throw(socket.timeout("connection timed out"))
class IOSubsystem(Subsystem): NAME = "io" def _init(self): # self._console_thd = None # if winconsole.Console.is_attached(): # print "console attached" # self.console = winconsole.Console() # self._console_buffer = "" # self._console_input_dfr = None # self._console_thd = threading.Thread(target = self._console_input_thread) # self._console_thd.daemon = True # self._console_thd_started = False # else: # self.console = None # # check if stdin has FLAG_FILE_FLAG_OVERLAPPED by trying to register # # it with the IOCP # handle = msvcrt.get_osfhandle(sys.stdin.fileno()) # try: # self.reactor._port.register(handle) # except win32file.error: # print "no OVERLAPPED" # self._console_buffer = "" # self._console_input_dfr = None # self._console_thd = threading.Thread(target = self._console_input_thread) # self._console_thd.daemon = True # self._console_thd_started = False # else: # print "OVERLAPPED enabled" # # successfully registered with IOCP -- PipeTransport will work # # just fine # pass self._stdin = None self._stdout = None self._stderr = None #def _unload(self): # if self.console: # self.console.close() # self.console = None @property def stdin(self): if not self._stdin: #if getattr(self, "_console_thd", False): # self._stdin = ConsoleInputTransport(self.reactor) #else: self._stdin = PipeTransport(self.reactor, sys.stdin, "r") return self._stdin @property def stdout(self): if not self._stdout: #if getattr(self, "_console_thd", False): # self._stdout = BlockingStreamTransport(self, sys.stdout) #else: self._stdout = PipeTransport(self.reactor, sys.stdout, "w") return self._stdout @property def stderr(self): if not self._stderr: #if getattr(self, "_console_thd", False): # self._stderr = BlockingStreamTransport(self, sys.stdout) #else: self._stderr = PipeTransport(self.reactor, sys.stderr, "w") return self._stderr def _assure_started(self): if getattr(self, "_console_thd", False) and not self._console_thd_started: self._console_thd.start() self._console_thd_started = True def _request_console_read(self): self._assure_started() if not self._console_input_dfr or self._console_input_dfr.is_set(): self._console_input_dfr = ReactorDeferred(self.reactor) return self._console_input_dfr def _console_input_thread(self): while self.reactor._active: data = os.read(sys.stdin.fileno(), 1000) self._console_buffer += data if self._console_input_dfr and not self._console_input_dfr.is_set( ): self._console_input_dfr.set(self._console_buffer) self._console_buffer = "" self._console_input_dfr = None self.reactor._wakeup() def _wrap_pipe(self, fileobj, mode): return PipeTransport(self.reactor, fileobj, mode) @reactive def open(self, filename, mode): yield self.reactor.started fobj, access = win32iocp.WinFile.open(filename, mode) rreturn(FileTransport(self.reactor, fobj, access)) @reactive def pipe(self): yield self.reactor.started rh, wh = win32iocp.create_overlapped_pipe() rtrns = PipeTransport(self.reactor, win32iocp.WinFile(rh), "r") wtrns = PipeTransport(self.reactor, win32iocp.WinFile(wh), "w") rreturn((rtrns, wtrns))
class IOSubsystem(Subsystem): NAME = "io" def _init(self): # self._console_thd = None # if winconsole.Console.is_attached(): # print "console attached" # self.console = winconsole.Console() # self._console_buffer = "" # self._console_input_dfr = None # self._console_thd = threading.Thread(target = self._console_input_thread) # self._console_thd.daemon = True # self._console_thd_started = False # else: # self.console = None # # check if stdin has FLAG_FILE_FLAG_OVERLAPPED by trying to register # # it with the IOCP # handle = msvcrt.get_osfhandle(sys.stdin.fileno()) # try: # self.reactor._port.register(handle) # except win32file.error: # print "no OVERLAPPED" # self._console_buffer = "" # self._console_input_dfr = None # self._console_thd = threading.Thread(target = self._console_input_thread) # self._console_thd.daemon = True # self._console_thd_started = False # else: # print "OVERLAPPED enabled" # # successfully registered with IOCP -- PipeTransport will work # # just fine # pass self._stdin = None self._stdout = None self._stderr = None #def _unload(self): # if self.console: # self.console.close() # self.console = None @property def stdin(self): if not self._stdin: #if getattr(self, "_console_thd", False): # self._stdin = ConsoleInputTransport(self.reactor) #else: self._stdin = PipeTransport(self.reactor, sys.stdin, "r") return self._stdin @property def stdout(self): if not self._stdout: #if getattr(self, "_console_thd", False): # self._stdout = BlockingStreamTransport(self, sys.stdout) #else: self._stdout = PipeTransport(self.reactor, sys.stdout, "w") return self._stdout @property def stderr(self): if not self._stderr: #if getattr(self, "_console_thd", False): # self._stderr = BlockingStreamTransport(self, sys.stdout) #else: self._stderr = PipeTransport(self.reactor, sys.stderr, "w") return self._stderr def _assure_started(self): if getattr(self, "_console_thd", False) and not self._console_thd_started: self._console_thd.start() self._console_thd_started = True def _request_console_read(self): self._assure_started() if not self._console_input_dfr or self._console_input_dfr.is_set(): self._console_input_dfr = ReactorDeferred(self.reactor) return self._console_input_dfr def _console_input_thread(self): while self.reactor._active: data = os.read(sys.stdin.fileno(), 1000) self._console_buffer += data if self._console_input_dfr and not self._console_input_dfr.is_set(): self._console_input_dfr.set(self._console_buffer) self._console_buffer = "" self._console_input_dfr = None self.reactor._wakeup() def _wrap_pipe(self, fileobj, mode): return PipeTransport(self.reactor, fileobj, mode) @reactive def open(self, filename, mode): yield self.reactor.started fobj, access = win32iocp.WinFile.open(filename, mode) rreturn(FileTransport(self.reactor, fobj, access)) @reactive def pipe(self): yield self.reactor.started rh, wh = win32iocp.create_overlapped_pipe() rtrns = PipeTransport(self.reactor, win32iocp.WinFile(rh), "r") wtrns = PipeTransport(self.reactor, win32iocp.WinFile(wh), "w") rreturn((rtrns, wtrns))